diff --git a/apps/web/.editorconfig b/.editorconfig similarity index 91% rename from apps/web/.editorconfig rename to .editorconfig index b342a11203..4371601fe1 100644 --- a/apps/web/.editorconfig +++ b/.editorconfig @@ -7,6 +7,7 @@ root = true [*] end_of_line = lf insert_final_newline = true +trim_trailing_whitespace = true # Set default charset [*.{js,ts,scss,html}] diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..1a4673e357 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,19 @@ +**/build +**/dist + +**/node_modules + +**/webpack.*.js +**/jest.config.js +**/gulpfile.js + +apps/browser/src/content/autofill.js +apps/browser/src/scripts/duo.js + +apps/desktop/desktop_native +apps/desktop/src/scripts/duo.js + +apps/web/config.js +apps/web/scripts/*.js +apps/web/src/theme.js +apps/web/tailwind.config.js diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000000..9c211247cb --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,55 @@ +{ + "root": true, + "env": { + "browser": true, + "webextensions": true + }, + "plugins": ["@typescript-eslint"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + "prettier" + ], + "rules": { + "@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled + "@typescript-eslint/no-unused-vars": ["warn", { "args": "none" }], + "@typescript-eslint/explicit-member-accessibility": [ + "error", + { + "accessibility": "no-public" + } + ], + "@typescript-eslint/no-this-alias": [ + "error", + { + "allowedNames": ["self"] + } + ], + "no-console": "warn", + "import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package. + "import/order": [ + "error", + { + "alphabetize": { + "order": "asc" + }, + "newlines-between": "always", + "pathGroups": [ + { + "pattern": "jslib-*/**", + "group": "external", + "position": "after" + }, + { + "pattern": "src/**/*", + "group": "parent", + "position": "before" + } + ], + "pathGroupsExcludedImportTypes": ["builtin"] + } + ] + } +} diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..9dd7b5c2e6 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,24 @@ +# Browser: Apply Prettier https://github.com/bitwarden/browser/pull/2238 +8fe821b9a3f9728bcb02d607ca75add468d380c1 +# Browser: Monorepository https://github.com/bitwarden/browser/pull/2531 +7fe51f83daa38df15a105f4a917abd01d94eddd1 + +# Desktop: Apply Prettier https://github.com/bitwarden/desktop/pull/1202 +521feae535d83166e620c3c28dfc3e7b0314a00e +# Browser: Monorepository https://github.com/bitwarden/clients/commit/7712ca6fa505c4b80b168258a7fc6a02c13160fd +28bc4113b9bbae4dba2b5af14d460764fce79acf + +# CLI: Apply Prettier https://github.com/bitwarden/cli/pull/426 +910b4a24e649f21acbf4da5b2d422b121d514bd5 +# CLI: Monorepository https://github.com/bitwarden/clients/commit/980429f4bdcb178d8d92d8202cbdacfaa45c917e +980429f4bdcb178d8d92d8202cbdacfaa45c917e + +# Web: Apply Prettier https://github.com/bitwarden/web/pull/1347 +56477eb39cfd8a73c9920577d24d75fed36e2cf5 +# Web: Monorepository https://github.com/bitwarden/clients/commit/02fe7159034b04d763a61fcf0200869e3209fa33 +02fe7159034b04d763a61fcf0200869e3209fa33 + +# Jslib: Apply Prettier https://github.com/bitwarden/jslib/pull/581 +193434461dbd9c48fe5dcbad95693470aec422ac +# Jslib: Monorepository https://github.com/bitwarden/clients/pull/2824/commits/d7492e3cf320410e74ebd0e0675ab994e64bd01a +d7492e3cf320410e74ebd0e0675ab994e64bd01a diff --git a/apps/web/.gitattributes b/.gitattributes similarity index 100% rename from apps/web/.gitattributes rename to .gitattributes diff --git a/.github/ISSUE_TEMPLATE/browser.yml b/.github/ISSUE_TEMPLATE/browser.yml new file mode 100644 index 0000000000..b28dce144b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/browser.yml @@ -0,0 +1,93 @@ +name: Browser Bug Report +description: File a bug report +labels: [bug, browser] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests. + - type: textarea + id: reproduce + attributes: + label: Steps To Reproduce + description: How can we reproduce the behavior. + value: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. Click on '...' + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Result + description: A clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual Result + description: A clear and concise description of what is happening. + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Screenshots or Videos + description: If applicable, add screenshots and/or a short video to help explain your problem. + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: Add any other context about the problem here. + - type: dropdown + id: os + attributes: + label: Operating System + description: What operating system are you seeing the problem on? + multiple: true + options: + - Windows + - macOS + - Linux + - Android + - iOS + validations: + required: true + - type: input + id: os-version + attributes: + label: Operating System Version + description: What version of the operating system(s) are you seeing the problem on? + - type: dropdown + id: browsers + attributes: + label: Web Browser + description: What browser(s) are you seeing the problem on? + multiple: true + options: + - Chrome + - Safari + - Microsoft Edge + - Firefox + - Opera + - Brave + - Vivaldi + validations: + required: true + - type: input + id: browser-version + attributes: + label: Browser Version + description: What version of the browser(s) are you seeing the problem on? + - type: input + id: version + attributes: + label: Build Version + description: What version of our software are you running? (go to "Settings" → "About" in the extension) + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/cli.yml b/.github/ISSUE_TEMPLATE/cli.yml new file mode 100644 index 0000000000..3a54a40477 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/cli.yml @@ -0,0 +1,82 @@ +name: CLI Bug Report +description: File a bug report +labels: [bug, cli] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests. + - type: textarea + id: reproduce + attributes: + label: Steps To Reproduce + description: How can we reproduce the behavior. + value: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. Click on '...' + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Result + description: A clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual Result + description: A clear and concise description of what is happening. + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Screenshots or Videos + description: If applicable, add screenshots and/or a short video to help explain your problem. + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: Add any other context about the problem here. + - type: dropdown + id: os + attributes: + label: Operating System + description: What operating system are you seeing the problem on? + multiple: true + options: + - Windows + - macOS + - Linux + validations: + required: true + - type: input + id: os-version + attributes: + label: Operating System Version + description: What version of the operating system(s) are you seeing the problem on? + - type: dropdown + id: shell + attributes: + label: Shell + description: What shell(s) are you seeing the problem on? + multiple: true + options: + - Bash + - Zsh + - PowerShell + validations: + required: true + - type: input + id: version + attributes: + label: Build Version + description: What version of our software are you running? (run `bw --version`) + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..7f3bf2560e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,20 @@ +blank_issues_enabled: false +contact_links: + - name: Report failure of prompt to save credentials in browser + url: https://docs.google.com/forms/d/e/1FAIpQLSeG-Dtpn2xnr9N7oF04NyY6ETUM-JF8pagFfAv8mW7bgcMVxA/viewform + about: We are aware of many sites' login forms where the Bitwarden browser extension either on a single platform/browser or multiple will not prompt the user to save a new password or update an existing password. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users! + - name: Report autofill failure in browser + url: https://docs.google.com/forms/d/e/1FAIpQLSfkxh1w6vK8fLYwAbAAEVhvhMAJwfFNDtYtPUVk1y5WTHvJmQ/viewform + about: We are aware of many sites' login forms, payment gateways, identity forms, etc. where the Bitwarden browser extension either on a single platform/browser or multiple will not autofill information. This is something the Bitwarden team is actively working on but need your help as a community and active Bitwarden users! + - name: Feature Requests + url: https://community.bitwarden.com/c/feature-requests/ + about: Request new features using the Community Forums. Please search existing feature requests before making a new one. + - name: Bitwarden Community Forums + url: https://community.bitwarden.com + about: Please visit the community forums for general community discussion, support and the development roadmap. + - name: Customer Support + url: https://bitwarden.com/contact/ + about: Please contact our customer support for account issues and general customer support. + - name: Security Issues + url: https://hackerone.com/bitwarden + about: We use HackerOne to manage security disclosures. diff --git a/.github/ISSUE_TEMPLATE/desktop.yml b/.github/ISSUE_TEMPLATE/desktop.yml new file mode 100644 index 0000000000..94b72a0020 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/desktop.yml @@ -0,0 +1,85 @@ +name: Desktop Bug Report +description: File a bug report +labels: [bug, desktop] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + + Please do not submit feature requests. The [Community Forums](https://community.bitwarden.com) has a section for submitting, voting for, and discussing product feature requests. + - type: textarea + id: reproduce + attributes: + label: Steps To Reproduce + description: How can we reproduce the behavior. + value: | + 1. Go to '...' + 2. Click on '....' + 3. Scroll down to '....' + 4. Click on '...' + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected Result + description: A clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual Result + description: A clear and concise description of what is happening. + validations: + required: true + - type: textarea + id: screenshots + attributes: + label: Screenshots or Videos + description: If applicable, add screenshots and/or a short video to help explain your problem. + - type: textarea + id: additional-context + attributes: + label: Additional Context + description: Add any other context about the problem here. + - type: dropdown + id: os + attributes: + label: Operating System + description: What operating system are you seeing the problem on? + multiple: true + options: + - Windows + - macOS + - Linux + validations: + required: true + - type: input + id: os-version + attributes: + label: Operating System Version + description: What version of the operating system(s) are you seeing the problem on? + - type: dropdown + id: install-method + attributes: + label: Installation method + multiple: true + options: + - Direct Download (from bitwarden.com) + - Mac App Store + - Microsoft Store + - Homebrew + - Chocolatey + - Snap + - Other + validations: + required: true + - type: input + id: version + attributes: + label: Build Version + description: What version of our software are you running? (go to "Help" → "About Bitwarden" in the app) + validations: + required: true diff --git a/apps/web/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/web.yml similarity index 98% rename from apps/web/.github/ISSUE_TEMPLATE/bug.yml rename to .github/ISSUE_TEMPLATE/web.yml index 143797b983..ef995e662c 100644 --- a/apps/web/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/web.yml @@ -1,6 +1,6 @@ -name: Bug Report +name: Web Bug Report description: File a bug report -labels: [bug] +labels: [bug, web] body: - type: markdown attributes: diff --git a/apps/web/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md similarity index 90% rename from apps/web/.github/PULL_REQUEST_TEMPLATE.md rename to .github/PULL_REQUEST_TEMPLATE.md index 5ea1b6313c..ecb361a934 100644 --- a/apps/web/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -24,5 +24,6 @@ ## Before you submit - [ ] I have checked for **linting** errors (`npm run lint`) (required) +- [ ] I have added **unit tests** where it makes sense to do so (encouraged but not required) - [ ] This change requires a **documentation update** (notify the documentation team) - [ ] This change has particular **deployment requirements** (notify the DevOps team) diff --git a/.github/secrets/appstore-app-cert.p12.gpg b/.github/secrets/appstore-app-cert.p12.gpg new file mode 100644 index 0000000000..ef81792f3d Binary files /dev/null and b/.github/secrets/appstore-app-cert.p12.gpg differ diff --git a/.github/secrets/appstore-installer-cert.p12.gpg b/.github/secrets/appstore-installer-cert.p12.gpg new file mode 100644 index 0000000000..09652a3a1b Binary files /dev/null and b/.github/secrets/appstore-installer-cert.p12.gpg differ diff --git a/.github/secrets/bitwarden-desktop-key.p12.gpg b/.github/secrets/bitwarden-desktop-key.p12.gpg new file mode 100644 index 0000000000..84c7f00e2d Binary files /dev/null and b/.github/secrets/bitwarden-desktop-key.p12.gpg differ diff --git a/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg b/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg new file mode 100644 index 0000000000..3b9ee4d1ee Binary files /dev/null and b/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg differ diff --git a/.github/secrets/devid-app-cert.p12.gpg b/.github/secrets/devid-app-cert.p12.gpg new file mode 100644 index 0000000000..8e2e2146e2 Binary files /dev/null and b/.github/secrets/devid-app-cert.p12.gpg differ diff --git a/.github/secrets/devid-installer-cert.p12.gpg b/.github/secrets/devid-installer-cert.p12.gpg new file mode 100644 index 0000000000..f379fc214f Binary files /dev/null and b/.github/secrets/devid-installer-cert.p12.gpg differ diff --git a/.github/secrets/macdev-cert.p12.gpg b/.github/secrets/macdev-cert.p12.gpg new file mode 100644 index 0000000000..4b8e0ef474 Binary files /dev/null and b/.github/secrets/macdev-cert.p12.gpg differ diff --git a/.github/workflows/build-browser.yml b/.github/workflows/build-browser.yml new file mode 100644 index 0000000000..9a8b9bff43 --- /dev/null +++ b/.github/workflows/build-browser.yml @@ -0,0 +1,433 @@ +--- +name: Build Browser + +on: + pull_request: + branches-ignore: + - 'l10n_master' + - 'gh-pages' + paths: + - 'apps/browser/**' + - '.github/workflows/build-browser.yml' + push: + branches: + - 'master' + - 'rc' + - 'hotfix-rc/**' + paths: + - 'apps/browser/**' + - '.github/workflows/build-browser.yml' + workflow_dispatch: + inputs: {} + +defaults: + run: + shell: bash + +jobs: + cloc: + name: CLOC + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 + + - name: Set up cloc + run: | + sudo apt update + sudo apt -y install cloc + + - name: Print lines of code + run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git + + + setup: + name: Setup + runs-on: ubuntu-20.04 + outputs: + repo_url: ${{ steps.gen_vars.outputs.repo_url }} + adj_build_number: ${{ steps.gen_vars.outputs.adj_build_number }} + steps: + - name: Get Package Version + id: gen_vars + run: | + repo_url=https://github.com/$GITHUB_REPOSITORY.git + adj_build_num=${GITHUB_SHA:0:7} + + echo "::set-output name=repo_url::$repo_url" + echo "::set-output name=adj_build_number::$adj_build_num" + + + locales-test: + name: Locales Test + runs-on: ubuntu-20.04 + needs: + - setup + defaults: + run: + working-directory: apps/browser + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 + + - name: Testing locales - extName length + run: | + found_error=false + + echo "Locales Test" + echo "============" + echo "extName string must be 40 characters or less" + echo + for locale in $(ls src/_locales/); do + string_length=$(jq '.extName.message | length' src/_locales/$locale/messages.json) + if [[ $string_length -gt 40 ]]; then + echo "$locale: $string_length" + found_error=true + fi + done + + if $found_error; then + echo + echo "Please fix 'extName' for the locales listed above." + exit 1 + else + echo "Test passed!" + fi + + + build: + name: Build + runs-on: windows-2019 + needs: + - setup + - locales-test + env: + _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} + defaults: + run: + working-directory: apps/browser + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Print environment + run: | + node --version + npm --version + + - name: NPM setup + run: npm ci + working-directory: ./ + + - name: Build & Test + run: | + npm run dist + npm run test + + - name: Gulp + run: gulp ci + + - name: Build sources for reviewers + shell: cmd + run: | + mkdir dist\Source + call git clone %GITHUB_SERVER_URL%/%GITHUB_REPOSITORY% dist\Source + cd dist\Source + call git checkout %GITHUB_SHA% + call git submodule update --init --recursive + cd ../ + del /S/Q "Source\.git\objects\pack\*" + call 7z a browser-source.zip "Source\*" + + - name: Upload Opera artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 + with: + name: dist-opera-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/dist/dist-opera.zip + if-no-files-found: error + + - name: Upload Chrome artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 + with: + name: dist-chrome-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/dist/dist-chrome.zip + if-no-files-found: error + + - name: Upload Firefox artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 + with: + name: dist-firefox-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/dist/dist-firefox.zip + if-no-files-found: error + + - name: Upload Edge artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 + with: + name: dist-edge-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/dist/dist-edge.zip + if-no-files-found: error + + - name: Upload browser source + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 + with: + name: browser-source-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/dist/browser-source.zip + if-no-files-found: error + + - name: Upload coverage artifact + if: false + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 + with: + name: coverage-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/coverage/coverage-${{ env._BUILD_NUMBER }}.zip + if-no-files-found: error + + build-safari: + name: Build Safari + runs-on: macos-11 + needs: + - setup + - locales-test + env: + _BUILD_NUMBER: ${{ needs.setup.outputs.adj_build_number }} + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Print environment + run: | + node --version + npm --version + + - name: Decrypt secrets + env: + DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + run: | + mkdir -p $HOME/secrets + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden-desktop-key.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/macdev-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" + + - name: Set up keychain + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }} + DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }} + APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }} + MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + run: | + security create-keychain -p $KEYCHAIN_PASSWORD build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain + security set-keychain-settings -lut 1200 build.keychain + security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + + - name: NPM setup + run: npm ci + working-directory: ./ + + - name: Build Safari extension + run: npm run dist:safari + working-directory: apps/browser + + - name: Zip Safari build artifact + run: | + cd apps/browser/dist + zip dist-safari.zip ./Safari/**/build/Release/safari.appex -r + pwd + ls -la + + - name: Upload Safari artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 + with: + name: dist-safari-${{ env._BUILD_NUMBER }}.zip + path: apps/browser/dist/dist-safari.zip + if-no-files-found: error + + crowdin-push: + name: Crowdin Push + if: github.ref == 'refs/heads/master' + runs-on: ubuntu-20.04 + needs: + - build + - build-safari + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 + + - name: Login to Azure + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + with: + keyvault: "bitwarden-prod-kv" + secrets: "crowdin-api-token" + + - name: Upload Sources + uses: crowdin/github-action@ecd7eb0ef6f3cfa16293c79e9cbc4bc5b5fd9c49 # v1.4.9 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} + CROWDIN_PROJECT_ID: "268134" + with: + config: apps/browser/crowdin.yml + crowdin_branch_name: master + upload_sources: true + upload_translations: false + + trigger-desktop-build: + name: Trigger desktop build + if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') || contains(github.ref, 'hotfix-rc') }} + runs-on: ubuntu-20.04 + needs: + - build + - build-safari + steps: + + - name: Login to Azure + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + with: + keyvault: "bitwarden-prod-kv" + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Extract branch name + id: extract_branch + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + + - name: Call GitHub API to trigger desktop build workflow + env: + TOKEN: ${{ steps.retrieve-secrets.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + BRANCH_NAME: ${{ steps.extract_branch.outputs.branch }} + run: | + + JSON_STRING=$(printf '{"ref":"%s"}' "$BRANCH_NAME") + + curl \ + -X POST \ + -i -u bitwarden-devops-bot:$TOKEN \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/bitwarden/clients/actions/workflows/build-desktop.yml/dispatches \ + -d $JSON_STRING + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-20.04 + needs: + - cloc + - setup + - locales-test + - build + - build-safari + - crowdin-push + - trigger-desktop-build + steps: + - name: Check if any job failed + if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} + env: + CLOC_STATUS: ${{ needs.cloc.result }} + SETUP_STATUS: ${{ needs.setup.result }} + LOCALES_TEST_STATUS: ${{ needs.locales-test.result }} + BUILD_STATUS: ${{ needs.build.result }} + SAFARI_BUILD_STATUS: ${{ needs.build-safari.result }} + CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }} + TRIGGER_DESKTOP_BUILD_STATUS: ${{ needs.trigger-desktop-build.result }} + run: | + if [ "$CLOC_STATUS" = "failure" ]; then + exit 1 + elif [ "$SETUP_STATUS" = "failure" ]; then + exit 1 + elif [ "$LOCALES_TEST_STATUS" = "failure" ]; then + exit 1 + elif [ "$BUILD_STATUS" = "failure" ]; then + exit 1 + elif [ "$SAFARI_BUILD_STATUS" = "failure" ]; then + exit 1 + elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then + exit 1 + elif [ "$TRIGGER_DESKTOP_BUILD_STATUS" = "failure" ]; then + exit 1 + fi + + - name: Login to Azure - Prod Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + if: failure() + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + if: failure() + with: + keyvault: "bitwarden-prod-kv" + secrets: "devops-alerts-slack-webhook-url" + + - name: Notify Slack on failure + uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 # v1.5.0 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} + with: + status: ${{ job.status }} diff --git a/.github/workflows/build-cli.yml b/.github/workflows/build-cli.yml new file mode 100644 index 0000000000..99c2a45434 --- /dev/null +++ b/.github/workflows/build-cli.yml @@ -0,0 +1,370 @@ +--- +name: Build CLI + +on: + pull_request: + branches-ignore: + - 'l10n_master' + - 'gh-pages' + paths: + - 'apps/cli/**' + - '.github/workflows/build-cli.yml' + push: + branches: + - 'master' + - 'rc' + - 'hotfix-rc/**' + paths: + - 'apps/cli/**' + - '.github/workflows/build-cli.yml' + workflow_dispatch: + inputs: {} + +defaults: + run: + working-directory: apps/cli + +jobs: + cloc: + name: CLOC + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Set up cloc + run: | + sudo apt update + sudo apt -y install cloc + + - name: Print lines of code + run: cloc --include-lang TypeScript,JavaScript --vcs git + + + setup: + name: Setup + runs-on: ubuntu-20.04 + outputs: + package_version: ${{ steps.retrieve-version.outputs.package_version }} + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Get Package Version + id: retrieve-version + run: | + PKG_VERSION=$(jq -r .version package.json) + echo "::set-output name=package_version::$PKG_VERSION" + + + cli: + name: Build CLI + runs-on: windows-2019 + needs: + - setup + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + _WIN_PKG_FETCH_VERSION: 16.15.0 + _WIN_PKG_VERSION: 3.4 + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Setup Windows builder + run: | + choco install checksum --no-progress + choco install reshack --no-progress + choco install nasm --no-progress + + - name: Set up Node + uses: actions/setup-node@17f8bd926464a1afa4c6a11669539e9c1ba77048 # v3.2.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Get pkg-fetch + shell: pwsh + run: | + cd $HOME + $fetchedUrl = "https://github.com/vercel/pkg-fetch/releases/download/v$env:_WIN_PKG_VERSION/node-v$env:_WIN_PKG_FETCH_VERSION-win-x64" + New-Item -ItemType directory -Path .\.pkg-cache + New-Item -ItemType directory -Path .\.pkg-cache\v$env:_WIN_PKG_VERSION + Invoke-RestMethod -Uri $fetchedUrl ` + -OutFile ".\.pkg-cache\v$env:_WIN_PKG_VERSION\fetched-v$env:_WIN_PKG_FETCH_VERSION-win-x64" + + - name: Setup Version Info + shell: pwsh + run: | + $major,$minor,$patch = $env:_PACKAGE_VERSION.split('.') + $versionInfo = @" + 1 VERSIONINFO + FILEVERSION $major,$minor,$patch,0 + PRODUCTVERSION $major,$minor,$patch,0 + FILEOS 0x40004 + FILETYPE 0x1 + { + BLOCK "StringFileInfo" + { + BLOCK "040904b0" + { + VALUE "CompanyName", "Bitwarden Inc." + VALUE "ProductName", "Bitwarden" + VALUE "FileDescription", "Bitwarden CLI" + VALUE "FileVersion", "$env:_PACKAGE_VERSION" + VALUE "ProductVersion", "$env:_PACKAGE_VERSION" + VALUE "OriginalFilename", "bw.exe" + VALUE "InternalName", "bw" + VALUE "LegalCopyright", "Copyright Bitwarden Inc." + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0409 0x04B0 + } + } + "@ + $versionInfo | Out-File ./version-info.rc + # https://github.com/vercel/pkg-fetch/issues/188 + + - name: Resource Hacker + shell: cmd + run: | + set PATH=%PATH%;C:\Program Files (x86)\Resource Hacker + set WIN_PKG=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\fetched-v%_WIN_PKG_FETCH_VERSION%-win-x64 + set WIN_PKG_BUILT=C:\Users\runneradmin\.pkg-cache\v%_WIN_PKG_VERSION%\built-v%_WIN_PKG_FETCH_VERSION%-win-x64 + copy %WIN_PKG% %WIN_PKG_BUILT% + ResourceHacker -open %WIN_PKG_BUILT% -save %WIN_PKG_BUILT% -action delete -mask ICONGROUP,1, + ResourceHacker -open version-info.rc -save version-info.res -action compile + ResourceHacker -open %WIN_PKG_BUILT% -save %WIN_PKG_BUILT% -action addoverwrite -resource version-info.res + + - name: Install + run: npm ci + working-directory: ./ + + - name: Run tests + run: npm run test + + - name: Build & Package + run: npm run dist --quiet + + - name: Package Chocolatey + shell: pwsh + run: | + Copy-Item -Path stores/chocolatey -Destination dist/chocolatey -Recurse + Copy-Item dist/windows/bw.exe -Destination dist/chocolatey/tools + Copy-Item ${{ github.workspace }}/LICENSE.txt -Destination dist/chocolatey/tools + choco pack dist/chocolatey/bitwarden-cli.nuspec --version ${{ env._PACKAGE_VERSION }} --out dist/chocolatey + + - name: Zip + shell: cmd + run: | + 7z a ./dist/bw-windows-%_PACKAGE_VERSION%.zip ./dist/windows/bw.exe + 7z a ./dist/bw-macos-%_PACKAGE_VERSION%.zip ./dist/macos/bw + 7z a ./dist/bw-linux-%_PACKAGE_VERSION%.zip ./dist/linux/bw + + - name: Version Test + run: | + dir ./dist/ + Expand-Archive -Path "./dist/bw-windows-${env:_PACKAGE_VERSION}.zip" -DestinationPath "./test/windows" + $testVersion = Invoke-Expression '& ./test/windows/bw.exe -v' + echo "version: $env:_PACKAGE_VERSION" + echo "testVersion: $testVersion" + if($testVersion -ne $env:_PACKAGE_VERSION) { + Throw "Version test failed." + } + + - name: Create checksums + run: | + checksum -f="./dist/bw-windows-${env:_PACKAGE_VERSION}.zip" ` + -t sha256 | Out-File -Encoding ASCII ./dist/bw-windows-sha256-${env:_PACKAGE_VERSION}.txt + checksum -f="./dist/bw-macos-${env:_PACKAGE_VERSION}.zip" ` + -t sha256 | Out-File -Encoding ASCII ./dist/bw-macos-sha256-${env:_PACKAGE_VERSION}.txt + checksum -f="./dist/bw-linux-${env:_PACKAGE_VERSION}.zip" ` + -t sha256 | Out-File -Encoding ASCII ./dist/bw-linux-sha256-${env:_PACKAGE_VERSION}.txt + + - name: Upload windows zip asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw-windows-${{ env._PACKAGE_VERSION }}.zip + path: apps/cli/dist/bw-windows-${{ env._PACKAGE_VERSION }}.zip + if-no-files-found: error + + - name: Upload windows checksum asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt + path: apps/cli/dist/bw-windows-sha256-${{ env._PACKAGE_VERSION }}.txt + if-no-files-found: error + + - name: Upload macos zip asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw-macos-${{ env._PACKAGE_VERSION }}.zip + path: apps/cli/dist/bw-macos-${{ env._PACKAGE_VERSION }}.zip + if-no-files-found: error + + - name: Upload macos checksum asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw-macos-sha256-${{ env._PACKAGE_VERSION }}.txt + path: apps/cli/dist/bw-macos-sha256-${{ env._PACKAGE_VERSION }}.txt + if-no-files-found: error + + - name: Upload linux zip asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw-linux-${{ env._PACKAGE_VERSION }}.zip + path: apps/cli/dist/bw-linux-${{ env._PACKAGE_VERSION }}.zip + if-no-files-found: error + + - name: Upload linux checksum asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw-linux-sha256-${{ env._PACKAGE_VERSION }}.txt + path: apps/cli/dist/bw-linux-sha256-${{ env._PACKAGE_VERSION }}.txt + if-no-files-found: error + + - name: Upload Chocolatey asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg + path: apps/cli/dist/chocolatey/bitwarden-cli.${{ env._PACKAGE_VERSION }}.nupkg + if-no-files-found: error + + - name: Upload NPM Build Directory asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bitwarden-cli-${{ env._PACKAGE_VERSION }}-npm-build.zip + path: apps/cli/build + if-no-files-found: error + + snap: + name: Build Snap + runs-on: ubuntu-20.04 + needs: [setup, cli] + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Print environment + run: | + whoami + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + echo "BW Package Version: $_PACKAGE_VERSION" + + - name: Get bw linux cli + uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 + with: + name: bw-linux-${{ env._PACKAGE_VERSION }}.zip + path: apps/cli/dist/snap + + - name: Setup Snap Package + run: | + cp -r stores/snap/* -t dist/snap + sed -i s/__version__/${{ env._PACKAGE_VERSION }}/g dist/snap/snapcraft.yaml + cd dist/snap + ls -alth + + - name: Build snap + uses: snapcore/action-build@ea14cdeb353272f75977040488ca191880509a8c # v1.1.0 + with: + path: apps/cli/dist/snap + + - name: Create checksum + run: | + cd dist/snap + ls -alth + sha256sum bw_${{ env._PACKAGE_VERSION }}_amd64.snap \ + | awk '{split($0, a); print a[1]}' > bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt + + - name: Install Snap + run: sudo snap install dist/snap/bw*.snap --dangerous + + - name: Test Snap + shell: pwsh + run: | + $testVersion = Invoke-Expression '& bw -v' + if($testVersion -ne $env:_PACKAGE_VERSION) { + Throw "Version test failed." + } + env: + BITWARDENCLI_APPDATA_DIR: "/home/runner/snap/bw/x1/.config/Bitwarden CLI" + + - name: Cleanup Test & Update Snap for Publish + shell: pwsh + run: sudo snap remove bw + + - name: Upload snap asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw_${{ env._PACKAGE_VERSION }}_amd64.snap + path: apps/cli/dist/snap/bw_${{ env._PACKAGE_VERSION }}_amd64.snap + if-no-files-found: error + + - name: Upload snap checksum asset + uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0 + with: + name: bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt + path: apps/cli/dist/snap/bw-snap-sha256-${{ env._PACKAGE_VERSION }}.txt + if-no-files-found: error + + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-20.04 + needs: + - cloc + - setup + - cli + - snap + steps: + - name: Check if any job failed + working-directory: ${{ github.workspace }} + if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} + env: + CLOC_STATUS: ${{ needs.cloc.result }} + SETUP_STATUS: ${{ needs.setup.result }} + CLI_STATUS: ${{ needs.cli.result }} + SNAP_STATUS: ${{ needs.snap.result }} + run: | + if [ "$CLOC_STATUS" = "failure" ]; then + exit 1 + elif [ "$SETUP_STATUS" = "failure" ]; then + exit 1 + elif [ "$CLI_STATUS" = "failure" ]; then + exit 1 + elif [ "$SNAP_STATUS" = "failure" ]; then + exit 1 + fi + + - name: Login to Azure - Prod Subscription + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1 + if: failure() + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + if: failure() + with: + keyvault: "bitwarden-prod-kv" + secrets: "devops-alerts-slack-webhook-url" + + - name: Notify Slack on failure + uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} + with: + status: ${{ job.status }} diff --git a/.github/workflows/build-desktop.yml b/.github/workflows/build-desktop.yml new file mode 100644 index 0000000000..023778b9ca --- /dev/null +++ b/.github/workflows/build-desktop.yml @@ -0,0 +1,1193 @@ +--- +name: Build Desktop + +on: + pull_request: + branches-ignore: + - 'l10n_master' + - 'gh-pages' + paths: + - 'apps/desktop/**' + - '.github/workflows/build-desktop.yml' + push: + branches: + - 'master' + - 'rc' + - 'hotfix-rc/**' + paths: + - 'apps/desktop/**' + - '.github/workflows/build-desktop.yml' + workflow_dispatch: + inputs: {} + +defaults: + run: + shell: bash + +jobs: + cloc: + name: CLOC + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Set up cloc + run: | + sudo apt-get update + sudo apt-get -y install cloc + + - name: Print lines of code + run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git + + electron-verify: + name: Verify Electron Version + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Verify + run: | + PACKAGE_VERSION=$(jq -r .devDependencies.electron package.json) + ELECTRON_BUILDER_VERSION=$(jq -r .electronVersion ./apps/desktop/electron-builder.json) + + if [[ "$PACKAGE_VERSION" == "$ELECTRON_BUILDER_VERSION" ]]; then + echo "Versions matches" + else + echo "Version missmatch, package.json: $PACKAGE_VERSION, electron-builder.json: $ELECTRON_BUILDER_VERSION" + exit 1 + fi + + setup: + name: Setup + runs-on: ubuntu-20.04 + outputs: + package_version: ${{ steps.retrieve-version.outputs.package_version }} + build_number: ${{ steps.increment-version.outputs.build_number }} + rc_branch_exists: ${{ steps.branch-check.outputs.rc_branch_exists }} + hotfix_branch_exists: ${{ steps.branch-check.outputs.hotfix_branch_exists }} + defaults: + run: + working-directory: apps/desktop + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Get Package Version + id: retrieve-version + run: | + PKG_VERSION=$(jq -r .version src/package.json) + echo "::set-output name=package_version::$PKG_VERSION" + + - name: Increment Version + id: increment-version + run: | + BUILD_NUMBER=$(expr 3000 + $GITHUB_RUN_NUMBER) + echo "Setting build number to $BUILD_NUMBER" + echo "::set-output name=build_number::$BUILD_NUMBER" + + - name: Check if special branches exist + id: branch-check + run: | + if [[ $(git ls-remote --heads origin rc) ]]; then + echo "::set-output name=rc_branch_exists::1" + else + echo "::set-output name=rc_branch_exists::0" + fi + + if [[ $(git ls-remote --heads origin hotfix-rc) ]]; then + echo "::set-output name=hotfix_branch_exists::1" + else + echo "::set-output name=hotfix_branch_exists::0" + fi + + + linux: + name: Linux Build + runs-on: ubuntu-20.04 + needs: setup + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + defaults: + run: + working-directory: apps/desktop + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Set Node options + run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Set up environment + run: | + sudo apt-get update + sudo apt-get -y install pkg-config libxss-dev libsecret-1-dev rpm + + - name: Set up Snap + run: sudo snap install snapcraft --classic + + - name: Print environment + run: | + node --version + npm --version + snap --version + snapcraft --version || echo 'snapcraft unavailable' + + - name: Install Node dependencies + run: npm ci + working-directory: ./ + + - name: Build application + run: npm run dist:lin + + - name: Upload .deb artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-amd64.deb + if-no-files-found: error + + - name: Upload .rpm artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.rpm + if-no-files-found: error + + - name: Upload .freebsd artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.freebsd + if-no-files-found: error + + - name: Upload .snap artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap + path: apps/desktop/dist/bitwarden_${{ env._PACKAGE_VERSION }}_amd64.snap + if-no-files-found: error + + - name: Upload .AppImage artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x86_64.AppImage + if-no-files-found: error + + - name: Upload latest auto-update artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: latest-linux.yml + path: apps/desktop/dist/latest-linux.yml + if-no-files-found: error + + + windows: + name: Windows Build + runs-on: windows-2019 + needs: setup + defaults: + run: + shell: pwsh + working-directory: apps/desktop + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Set Node options + run: echo "NODE_OPTIONS=--max_old_space_size=4096" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Install AST + uses: bitwarden/gh-actions/install-ast@f135c42c8596cb535c5bcb7523c0b2eef89709ac + + - name: Set up environment + run: choco install checksum --no-progress + + - name: Print environment + run: | + node --version + npm --version + choco --version + + - name: Login to Azure + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + with: + keyvault: "bitwarden-prod-kv" + secrets: "code-signing-vault-url, + code-signing-client-id, + code-signing-tenant-id, + code-signing-client-secret, + code-signing-cert-name" + + - name: Install Node dependencies + run: npm ci + working-directory: ./ + + - name: Build & Sign (dev) + env: + ELECTRON_BUILDER_SIGN: 1 + SIGNING_VAULT_URL: ${{ steps.retrieve-secrets.outputs.code-signing-vault-url }} + SIGNING_CLIENT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-client-id }} + SIGNING_TENANT_ID: ${{ steps.retrieve-secrets.outputs.code-signing-tenant-id }} + SIGNING_CLIENT_SECRET: ${{ steps.retrieve-secrets.outputs.code-signing-client-secret }} + SIGNING_CERT_NAME: ${{ steps.retrieve-secrets.outputs.code-signing-cert-name }} + run: | + npm run build + npm run pack:win + + - name: Rename appx files for store + run: | + Copy-Item "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx" ` + -Destination "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx" + Copy-Item "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx" ` + -Destination "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx" + Copy-Item "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx" ` + -Destination "./dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx" + + - name: Package for Chocolatey + run: | + Copy-Item -Path ./stores/chocolatey -Destination ./dist/chocolatey -Recurse + Copy-Item -Path ./dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe ` + -Destination ./dist/chocolatey + + $checksum = checksum -t sha256 ./dist/chocolatey/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe + $chocoInstall = "./dist/chocolatey/tools/chocolateyinstall.ps1" + (Get-Content $chocoInstall).replace('__version__', "$env:_PACKAGE_VERSION").replace('__checksum__', $checksum) | Set-Content $chocoInstall + choco pack ./dist/chocolatey/bitwarden.nuspec --version "$env:_PACKAGE_VERSION" --out ./dist/chocolatey + + - name: Upload portable exe artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe + path: apps/desktop/dist/Bitwarden-Portable-${{ env._PACKAGE_VERSION }}.exe + if-no-files-found: error + + - name: Upload installer exe artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe + path: apps/desktop/dist/nsis-web/Bitwarden-Installer-${{ env._PACKAGE_VERSION }}.exe + if-no-files-found: error + + - name: Upload appx ia32 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.appx + if-no-files-found: error + + - name: Upload store appx ia32 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32-store.appx + if-no-files-found: error + + - name: Upload NSIS ia32 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z + path: apps/desktop/dist/nsis-web/Bitwarden-${{ env._PACKAGE_VERSION }}-ia32.nsis.7z + if-no-files-found: error + + - name: Upload appx x64 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.appx + if-no-files-found: error + + - name: Upload store appx x64 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-x64-store.appx + if-no-files-found: error + + - name: Upload NSIS x64 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z + path: apps/desktop/dist/nsis-web/Bitwarden-${{ env._PACKAGE_VERSION }}-x64.nsis.7z + if-no-files-found: error + + - name: Upload appx ARM64 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.appx + if-no-files-found: error + + - name: Upload store appx ARM64 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64-store.appx + if-no-files-found: error + + - name: Upload NSIS ARM64 artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z + path: apps/desktop/dist/nsis-web/Bitwarden-${{ env._PACKAGE_VERSION }}-arm64.nsis.7z + if-no-files-found: error + + - name: Upload nupkg artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: bitwarden.${{ env._PACKAGE_VERSION }}.nupkg + path: apps/desktop/dist/chocolatey/bitwarden.${{ env._PACKAGE_VERSION }}.nupkg + if-no-files-found: error + + - name: Upload latest auto-update artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: latest.yml + path: apps/desktop/dist/nsis-web/latest.yml + if-no-files-found: error + + + macos-build: + name: MacOS Build + runs-on: macos-11 + needs: setup + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + defaults: + run: + working-directory: apps/desktop + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Set Node options + run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Print environment + run: | + node --version + npm --version + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + - name: Cache Build + id: build-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/desktop/build + key: ${{ runner.os }}-${{ github.run_id }}-build + + - name: Cache Safari + id: safari-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/browser/dist/Safari + key: ${{ runner.os }}-${{ github.run_id }}-safari-extension + + - name: Decrypt secrets + env: + DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + run: | + mkdir -p $HOME/secrets + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden-desktop-key.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/macdev-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" + + - name: Set up keychain + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }} + DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }} + APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }} + MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + run: | + security create-keychain -p $KEYCHAIN_PASSWORD build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain + security set-keychain-settings -lut 1200 build.keychain + security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + + - name: Set up provisioning profiles + run: | + cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ + $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile + + - name: Increment version + shell: pwsh + env: + BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} + run: | + $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" + $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json + + - name: Install Node dependencies + run: npm ci + working-directory: ./ + + - name: Build application (dev) + run: npm run build + + + macos-package-github: + name: MacOS Package GitHub Release Assets + runs-on: macos-11 + needs: + - setup + - macos-build + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + defaults: + run: + working-directory: apps/desktop + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Set Node options + run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Print environment + run: | + node --version + npm --version + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + - name: Get Build Cache + id: build-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/desktop/build + key: ${{ runner.os }}-${{ github.run_id }}-build + + - name: Setup Safari Cache + id: safari-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/browser/dist/Safari + key: ${{ runner.os }}-${{ github.run_id }}-safari-extension + + - name: Decrypt secrets + env: + DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + run: | + mkdir -p $HOME/secrets + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden-desktop-key.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/macdev-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" + + - name: Set up keychain + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }} + DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }} + APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }} + MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + run: | + security create-keychain -p $KEYCHAIN_PASSWORD build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain + security set-keychain-settings -lut 1200 build.keychain + security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + + - name: Set up provisioning profiles + run: | + cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ + $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile + + - name: Increment version + shell: pwsh + env: + BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} + run: | + $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" + $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json + + - name: Install Node dependencies + run: npm ci + working-directory: ./ + + - name: Build + if: steps.build-cache.outputs.cache-hit != 'true' + run: npm run build + + - name: Extract branch name + if: contains(github.ref, 'hotfix-rc') + id: extract_branch + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + + - name: Download artifact from hotfix-rc + if: contains(github.ref, 'hotfix-rc') + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: ${{ steps.extract_branch.outputs.branch }} + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Download artifact from rc + if: github.ref == 'refs/heads/rc' + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: rc + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Download artifact from master + if: ${{ github.ref != 'refs/heads/rc' && !contains(github.ref, 'hotfix-rc') }} + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: master + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Unzip Safari artifact + run: | + SAFARI_DIR=$(find $GITHUB_WORKSPACE/browser-build-artifacts -name 'dist-safari-*.zip') + echo $SAFARI_DIR + unzip $SAFARI_DIR/dist-safari.zip -d $GITHUB_WORKSPACE/browser-build-artifacts + + - name: Load Safari extension for .dmg + run: | + mkdir PlugIns + cp -r $GITHUB_WORKSPACE/browser-build-artifacts/Safari/dmg/build/Release/safari.appex PlugIns/safari.appex + + - name: Build application (dist) + env: + APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + run: npm run pack:mac + + - name: Upload .zip artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal-mac.zip + if-no-files-found: error + + - name: Upload .dmg artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg + if-no-files-found: error + + - name: Upload .dmg blockmap artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap + path: apps/desktop/dist/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.dmg.blockmap + if-no-files-found: error + + - name: Upload latest auto-update artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: latest-mac.yml + path: apps/desktop/dist/latest-mac.yml + if-no-files-found: error + + + macos-package-mas: + name: MacOS Package Prod Release Asset + runs-on: macos-11 + needs: + - setup + - macos-build + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + defaults: + run: + working-directory: apps/desktop + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Set Node options + run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Print environment + run: | + node --version + npm --version + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + - name: Get Build Cache + id: build-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/desktop/build + key: ${{ runner.os }}-${{ github.run_id }}-build + + - name: Setup Safari Cache + id: safari-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/browser/dist/Safari + key: ${{ runner.os }}-${{ github.run_id }}-safari-extension + + - name: Decrypt secrets + env: + DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + run: | + mkdir -p $HOME/secrets + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden-desktop-key.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/macdev-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" + + - name: Set up keychain + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }} + DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }} + APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }} + MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + run: | + security create-keychain -p $KEYCHAIN_PASSWORD build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain + security set-keychain-settings -lut 1200 build.keychain + security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + + - name: Set up provisioning profiles + run: | + cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ + $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile + + - name: Increment version + shell: pwsh + env: + BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} + run: | + $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" + $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json + + - name: Install Node dependencies + run: npm ci + working-directory: ./ + + - name: Build + if: steps.build-cache.outputs.cache-hit != 'true' + run: npm run build + + - name: Extract branch name + if: contains(github.ref, 'hotfix-rc') + id: extract_branch + shell: bash + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + + - name: Download artifact from hotfix-rc + if: contains(github.ref, 'hotfix-rc') + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: ${{ steps.extract_branch.outputs.branch }} + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Download artifact from rc + if: github.ref == 'refs/heads/rc' + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: rc + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Download artifact from master + if: ${{ github.ref != 'refs/heads/rc' && !contains(github.ref, 'hotfix-rc') }} + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: master + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Unzip Safari artifact + run: | + SAFARI_DIR=$(find $GITHUB_WORKSPACE/browser-build-artifacts -name 'dist-safari-*.zip') + echo $SAFARI_DIR + unzip $SAFARI_DIR/dist-safari.zip -d $GITHUB_WORKSPACE/browser-build-artifacts + + - name: Load Safari extension for App Store + run: | + mkdir PlugIns + cp -r $GITHUB_WORKSPACE/browser-build-artifacts/Safari/mas/build/Release/safari.appex PlugIns/safari.appex + + - name: Build application for App Store + run: npm run pack:mac:mas + env: + APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + + - name: Upload .pkg artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg + path: apps/desktop/dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-universal.pkg + if-no-files-found: error + + - name: Deploy to TestFlight + env: + APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + if: | + (github.ref == 'refs/heads/master' + && needs.setup.outputs.rc_branch_exists == 0 + && needs.setup.outputs.hotfix_branch_exists == 0) + || (github.ref == 'refs/heads/rc' && needs.setup.outputs.hotfix_branch_exists == 0) + || github.ref == 'refs/heads/hotfix-rc' + run: npm run upload:mas + + + macos-package-dev: + name: MacOS Package Dev Release Asset + if: false # We need to look into how code signing works for dev + runs-on: macos-11 + needs: + - setup + - macos-build + env: + _PACKAGE_VERSION: ${{ needs.setup.outputs.package_version }} + defaults: + run: + working-directory: apps/desktop + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Set Node options + run: echo "NODE_OPTIONS=--max_old_space_size=4096" >> $GITHUB_ENV + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Print environment + run: | + node --version + npm --version + echo "GitHub ref: $GITHUB_REF" + echo "GitHub event: $GITHUB_EVENT" + + - name: Get Build Cache + id: build-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/desktop/build + key: ${{ runner.os }}-${{ github.run_id }}-build + + - name: Setup Safari Cache + id: safari-cache + uses: actions/cache@937d24475381cd9c75ae6db12cb4e79714b926ed + with: + path: apps/browser/dist/Safari + key: ${{ runner.os }}-${{ github.run_id }}-safari-extension + + - name: Decrypt secrets + env: + DECRYPT_FILE_PASSWORD: ${{ secrets.DECRYPT_FILE_PASSWORD }} + run: | + mkdir -p $HOME/secrets + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden-desktop-key.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden-desktop-key.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/appstore-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/appstore-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-app-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-app-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/devid-installer-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/devid-installer-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/macdev-cert.p12" \ + "$GITHUB_WORKSPACE/.github/secrets/macdev-cert.p12.gpg" + gpg --quiet --batch --yes --decrypt --passphrase="$DECRYPT_FILE_PASSWORD" \ + --output "$HOME/secrets/bitwarden_desktop_appstore.provisionprofile" \ + "$GITHUB_WORKSPACE/.github/secrets/bitwarden_desktop_appstore.provisionprofile.gpg" + + - name: Set up keychain + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + DESKTOP_KEY_PASSWORD: ${{ secrets.DESKTOP_KEY_PASSWORD }} + DEVID_CERT_PASSWORD: ${{ secrets.DEVID_CERT_PASSWORD }} + APPSTORE_CERT_PASSWORD: ${{ secrets.APPSTORE_CERT_PASSWORD }} + MACDEV_CERT_PASSWORD: ${{ secrets.MACDEV_CERT_PASSWORD }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + run: | + security create-keychain -p $KEYCHAIN_PASSWORD build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p $KEYCHAIN_PASSWORD build.keychain + security set-keychain-settings -lut 1200 build.keychain + security import "$HOME/secrets/bitwarden-desktop-key.p12" -k build.keychain -P $DESKTOP_KEY_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-app-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/devid-installer-cert.p12" -k build.keychain -P $DEVID_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-app-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/appstore-installer-cert.p12" -k build.keychain -P $APPSTORE_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security import "$HOME/secrets/macdev-cert.p12" -k build.keychain -P $MACDEV_CERT_PASSWORD \ + -T /usr/bin/codesign -T /usr/bin/security -T /usr/bin/productbuild + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $KEYCHAIN_PASSWORD build.keychain + + - name: Set up provisioning profiles + run: | + cp $HOME/secrets/bitwarden_desktop_appstore.provisionprofile \ + $GITHUB_WORKSPACE/apps/desktop/bitwarden_desktop_appstore.provisionprofile + + - name: Increment version + shell: pwsh + env: + BUILD_NUMBER: ${{ needs.setup.outputs.build_number }} + run: | + $package = Get-Content -Raw -Path electron-builder.json | ConvertFrom-Json + $package | Add-Member -MemberType NoteProperty -Name buildVersion -Value "$env:BUILD_NUMBER" + $package | ConvertTo-Json -Depth 32 | Set-Content -Path electron-builder.json + + - name: Install Node dependencies + run: npm ci + working-directory: ./ + + - name: Build + if: steps.build-cache.outputs.cache-hit != 'true' + run: npm run build + + - name: Download artifact from rc + if: github.ref == 'refs/heads/rc' + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: rc + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Download artifact from master + if: github.ref != 'refs/heads/rc' + uses: dawidd6/action-download-artifact@b2abf1705491048a2d7074f7d90513044fd25d39 # v2.19.0 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: master + path: ${{ github.workspace }}/browser-build-artifacts + + - name: Unzip Safari artifact + run: | + SAFARI_DIR=$(find $GITHUB_WORKSPACE/browser-build-artifacts -name 'dist-safari-*.zip') + echo $SAFARI_DIR + unzip $SAFARI_DIR/dist-safari.zip -d $GITHUB_WORKSPACE/browser-build-artifacts + + - name: Load Safari extension for App Store + run: | + mkdir PlugIns + cp -r $GITHUB_WORKSPACE/browser-build-artifacts/Safari/masdev/build/Release/safari.appex PlugIns/safari.appex + + - name: Build dev application for App Store + run: npm run pack:mac:masdev + env: + APPLE_ID_USERNAME: ${{ secrets.APPLE_ID_USERNAME }} + APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + + - name: Zip masdev asset + working-directory: ./dist/mas-dev-universal + run: zip -r Bitwarden-${{ env.PACKAGE_VERSION }}-masdev-universal.zip Bitwarden.app + + - name: Upload masdev artifact + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 + with: + name: Bitwarden-${{ env._PACKAGE_VERSION }}-masdev-universal.zip + path: apps/desktop/dist/mas-universal/Bitwarden-${{ env._PACKAGE_VERSION }}-masdev-universal.zip + if-no-files-found: error + + + crowdin-push: + name: Crowdin Push + if: github.ref == 'refs/heads/master' + needs: + - linux + - windows + - macos-package-github + - macos-package-mas + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 + + - name: Login to Azure + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + with: + keyvault: "bitwarden-prod-kv" + secrets: "crowdin-api-token" + + - name: Upload Sources + uses: crowdin/github-action@ecd7eb0ef6f3cfa16293c79e9cbc4bc5b5fd9c49 # v1.4.9 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} + CROWDIN_PROJECT_ID: "299360" + with: + config: apps/desktop/crowdin.yml + crowdin_branch_name: master + upload_sources: true + upload_translations: false + + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-20.04 + needs: + - cloc + - electron-verify + - setup + - linux + - windows + - macos-build + - macos-package-github + - macos-package-mas + - crowdin-push + steps: + - name: Check if any job failed + if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} + env: + CLOC_STATUS: ${{ needs.cloc.result }} + ELECTRON_VERIFY_STATUS: ${{ needs.electron-verify.result }} + SETUP_STATUS: ${{ needs.setup.result }} + LINUX_STATUS: ${{ needs.linux.result }} + WINDOWS_STATUS: ${{ needs.windows.result }} + MACOS_BUILD_STATUS: ${{ needs.macos-build.result }} + MACOS_PKG_GITHUB_STATUS: ${{ needs.macos-package-github.result }} + MACOS_PKG_MAS_STATUS: ${{ needs.macos-package-mas.result }} + CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }} + run: | + if [ "$CLOC_STATUS" = "failure" ]; then + exit 1 + if [ "$ELECTRON_VERIFY_STATUS" = "failure" ]; then + exit 1 + elif [ "$SETUP_STATUS" = "failure" ]; then + exit 1 + elif [ "$LINUX_STATUS" = "failure" ]; then + exit 1 + elif [ "$WINDOWS_STATUS" = "failure" ]; then + exit 1 + elif [ "$MACOS_BUILD_STATUS" = "failure" ]; then + exit 1 + elif [ "$MACOS_PKG_GITHUB_STATUS" = "failure" ]; then + exit 1 + elif [ "$MACOS_PKG_MAS_STATUS" = "failure" ]; then + exit 1 + elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then + exit 1 + fi + + - name: Login to Azure - Prod Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf + if: failure() + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + if: failure() + with: + keyvault: "bitwarden-prod-kv" + secrets: "devops-alerts-slack-webhook-url" + + - name: Notify Slack on failure + uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} + with: + status: ${{ job.status }} diff --git a/apps/web/.github/workflows/build.yml b/.github/workflows/build-web.yml similarity index 74% rename from apps/web/.github/workflows/build.yml rename to .github/workflows/build-web.yml index 16f0a3bd70..2602905b05 100644 --- a/apps/web/.github/workflows/build.yml +++ b/.github/workflows/build-web.yml @@ -1,20 +1,24 @@ --- -name: Build +name: Build Web on: - workflow_dispatch: - inputs: - custom_tag_extension: - description: "Custom image tag extension" - required: false - push: + pull_request: branches-ignore: - - "l10n_master" - - "gh-pages" - - "deploy" - paths-ignore: - - '.github/workflows/**' - + - 'l10n_master' + - 'gh-pages' + paths: + - 'apps/web/**' + - '.github/workflows/build-web.yml' + push: + branches: + - 'master' + - 'rc' + - 'hotfix-rc/**' + paths: + - 'apps/web/**' + - '.github/workflows/build-web.yml' + workflow_dispatch: + inputs: {} jobs: cloc: @@ -22,7 +26,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Set up cloc run: | @@ -30,30 +34,10 @@ jobs: sudo apt -y install cloc - name: Print lines of code + working-directory: apps/web run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git - lint: - name: Lint - runs-on: ubuntu-20.04 - steps: - - name: Checkout repo - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 - - - name: Cache npm - id: npm-cache - uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6 - with: - path: "~/.npm" - key: ${{ runner.os }}-npm-lint-${{ hashFiles('**/package-lock.json') }} - - - name: Install dependencies - run: npm ci - - - name: Run linter - run: npm run lint - - setup: name: Setup runs-on: ubuntu-20.04 @@ -61,7 +45,7 @@ jobs: version: ${{ steps.version.outputs.value }} steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Get GitHub sha as version id: version @@ -73,15 +57,14 @@ jobs: runs-on: ubuntu-20.04 needs: - setup - - lint env: _VERSION: ${{ needs.setup.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Set up Node - uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' @@ -101,15 +84,16 @@ jobs: run: npm ci - name: Build OSS selfhost + working-directory: apps/web run: | npm run dist:oss:selfhost zip -r web-$_VERSION-selfhosted-open-source.zip build - name: Upload build artifact - uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: web-${{ env._VERSION }}-selfhosted-open-source.zip - path: ./web-${{ env._VERSION }}-selfhosted-open-source.zip + path: apps/web/web-${{ env._VERSION }}-selfhosted-open-source.zip if-no-files-found: error @@ -118,15 +102,14 @@ jobs: runs-on: ubuntu-20.04 needs: - setup - - lint env: _VERSION: ${{ needs.setup.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Set up Node - uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' @@ -146,15 +129,16 @@ jobs: run: npm ci - name: Build Cloud + working-directory: apps/web run: | npm run dist:bit:cloud zip -r web-$_VERSION-cloud-COMMERCIAL.zip build - name: Upload build artifact - uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: web-${{ env._VERSION }}-cloud-COMMERCIAL.zip - path: ./web-${{ env._VERSION }}-cloud-COMMERCIAL.zip + path: apps/web/web-${{ env._VERSION }}-cloud-COMMERCIAL.zip if-no-files-found: error @@ -163,15 +147,14 @@ jobs: runs-on: ubuntu-20.04 needs: - setup - - lint env: _VERSION: ${{ needs.setup.outputs.version }} steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Set up Node - uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' @@ -199,6 +182,7 @@ jobs: run: npm ci - name: Build + working-directory: apps/web run: | echo -e "# Building Web\n" echo "Building app" @@ -208,13 +192,14 @@ jobs: zip -r web-$_VERSION-selfhosted-COMMERCIAL.zip build - name: Upload build artifact - uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 # v2.2.3 + uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # v3.0.0 with: name: web-${{ env._VERSION }}-selfhosted-COMMERCIAL.zip - path: ./web-${{ env._VERSION }}-selfhosted-COMMERCIAL.zip + path: apps/web/web-${{ env._VERSION }}-selfhosted-COMMERCIAL.zip if-no-files-found: error - name: Build Docker image + working-directory: apps/web run: | echo -e "\nBuilding Docker image" docker --version @@ -264,7 +249,7 @@ jobs: echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV - name: Login to Azure - QA Subscription - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1 with: creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} @@ -292,13 +277,12 @@ jobs: runs-on: ubuntu-20.04 needs: - setup - - lint steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Set up Node - uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + uses: actions/setup-node@56337c425554a6be30cdef71bf441f15be286854 # v3.1.1 with: cache: 'npm' cache-dependency-path: '**/package-lock.json' @@ -315,7 +299,7 @@ jobs: echo "GitHub event: $GITHUB_EVENT" - name: Login to Azure - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1 with: creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} @@ -326,6 +310,7 @@ jobs: run: npm ci - name: Build + working-directory: apps/web run: | echo -e "# Building Web\n" echo "Building app" @@ -377,44 +362,6 @@ jobs: - name: Log out of Docker run: docker logout - - windows: - name: Test code on Windows - runs-on: windows-2019 - steps: - - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f - - - name: Set up NuGet - uses: nuget/setup-nuget@04b0c2b8d1b97922f67eca497d7cf0bf17b8ffe1 - with: - nuget-version: "latest" - - - name: Set up Node - uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 - with: - cache: 'npm' - cache-dependency-path: '**/package-lock.json' - node-version: "16" - - - name: Print environment - run: | - nuget help | grep Version - node --version - npm --version - echo "GitHub ref: $GITHUB_REF" - echo "GitHub event: $GITHUB_EVENT" - env: - GITHUB_REF: ${{ github.ref }} - GITHUB_EVENT: ${{ github.event_name }} - - - name: Install dependencies - run: npm ci - - - name: NPM build - run: npm run build:bit:cloud - - crowdin-push: name: Crowdin Push if: github.ref == 'refs/heads/master' @@ -428,27 +375,27 @@ jobs: _CROWDIN_PROJECT_ID: "308189" steps: - name: Checkout repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 # v2.3.4 - name: Login to Azure - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1 with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - name: Retrieve secrets id: retrieve-secrets - uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f # v1.0.0 with: keyvault: "bitwarden-prod-kv" secrets: "crowdin-api-token" - name: Upload Sources - uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea # v1.3.2 + uses: crowdin/github-action@a3160b9e5a9e00739392c23da5e580c6cabe526d # v1.4.8 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} with: - config: crowdin.yml + config: apps/web/crowdin.yml crowdin_branch_name: master upload_sources: true upload_translations: false @@ -461,31 +408,25 @@ jobs: needs: - cloc - setup - - lint - build-oss-selfhost - build-cloud - build-commercial-selfhost - build-qa - crowdin-push - - windows steps: - name: Check if any job failed if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} env: CLOC_STATUS: ${{ needs.cloc.result }} - LINT_STATUS: ${{ needs.lint.result }} SETUP_STATUS: ${{ needs.setup.result }} BUILD_OSS_SELFHOST_STATUS: ${{ needs.build-oss-selfhost.result }} BUILD_CLOUD_STATUS: ${{ needs.build-cloud.result }} BUILD_COMMERCIAL_SELFHOST_STATUS: ${{ needs.build-commercial-selfhost.result }} BUILD_QA_STATUS: ${{ needs.build-qa.result }} CROWDIN_PUSH_STATUS: ${{ needs.crowdin-push.result }} - WINDOWS_STATUS: ${{ needs.windows.result }} run: | if [ "$CLOC_STATUS" = "failure" ]; then exit 1 - elif [ "$LINT_STATUS" = "failure" ]; then - exit 1 elif [ "$SETUP_STATUS" = "failure" ]; then exit 1 elif [ "$BUILD_OSS_SELFHOST_STATUS" = "failure" ]; then @@ -498,26 +439,24 @@ jobs: exit 1 elif [ "$CROWDIN_PUSH_STATUS" = "failure" ]; then exit 1 - elif [ "$WINDOWS_STATUS" = "failure" ]; then - exit 1 fi - name: Login to Azure - Prod Subscription - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1 if: failure() with: creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - name: Retrieve secrets id: retrieve-secrets - uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f # v1.0.0 if: failure() with: keyvault: "bitwarden-prod-kv" secrets: "devops-alerts-slack-webhook-url" - name: Notify Slack on failure - uses: act10ns/slack@e4e71685b9b239384b0f676a63c32367f59c2522 # v1.2.2 + uses: act10ns/slack@da3191ebe2e67f49b46880b4633f5591a96d1d33 # v1.5.1 if: failure() env: SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} diff --git a/apps/web/.github/workflows/crowdin-pull.yml b/.github/workflows/crowdin-pull.yml similarity index 65% rename from apps/web/.github/workflows/crowdin-pull.yml rename to .github/workflows/crowdin-pull.yml index 0c959fea2f..df1cb46c71 100644 --- a/apps/web/.github/workflows/crowdin-pull.yml +++ b/.github/workflows/crowdin-pull.yml @@ -1,18 +1,24 @@ --- -name: Crowdin Pull +name: Crowdin Sync on: workflow_dispatch: inputs: {} schedule: - - cron: "0 0 * * 5" + - cron: '0 0 * * 5' jobs: - crowdin-pull: - name: Pull + crowdin-sync: + name: Autosync runs-on: ubuntu-20.04 - env: - _CROWDIN_PROJECT_ID: "308189" + strategy: + fail-fast: false + matrix: + include: + - app_name: browser + crowdin_project_id: "268134" + - app_name: desktop + crowdin_project_id: "299360" steps: - name: Checkout repo uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 @@ -30,10 +36,11 @@ jobs: secrets: "crowdin-api-token" - name: Download translations - uses: crowdin/github-action@e39093fd75daae7859c68eded4b43d42ec78d8ea # v1.3.2 + uses: bitwarden/gh-actions/crowdin@05052c5c575ceb09ceea397fe241879e199ed44b env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CROWDIN_API_TOKEN: ${{ steps.retrieve-secrets.outputs.crowdin-api-token }} + CROWDIN_PROJECT_ID: ${{ matrix.crowdin_project_id }} with: config: crowdin.yml crowdin_branch_name: master @@ -43,7 +50,8 @@ jobs: github_user_name: "github-actions" github_user_email: "<>" commit_message: "Autosync the updated translations" - localization_branch_name: crowdin-auto-sync + localization_branch_name: crowdin-auto-sync-${{ matrix.app_name }} create_pull_request: true - pull_request_title: "Autosync Crowdin Translations" + pull_request_title: "Autosync Crowdin Translations for ${{ matrix.app_name }}" pull_request_body: "Autosync the updated translations" + working_directory: apps/${{ matrix.app_name }} diff --git a/apps/web/.github/workflows/enforce-labels.yml b/.github/workflows/enforce-labels.yml similarity index 93% rename from apps/web/.github/workflows/enforce-labels.yml rename to .github/workflows/enforce-labels.yml index 0a63c70e4a..bf8517cc25 100644 --- a/apps/web/.github/workflows/enforce-labels.yml +++ b/.github/workflows/enforce-labels.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Enforce Label - uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb + uses: yogevbd/enforce-label-action@8d1e1709b1011e6d90400a0e6cf7c0b77aa5efeb # v2.1.0 with: BANNED_LABELS: "hold" BANNED_LABELS_DESCRIPTION: "PRs on hold cannot be merged" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000..9c1ff9b064 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,36 @@ +--- +name: Lint + +on: + push: + branches-ignore: + - 'l10n_master' + - 'gh-pages' + paths-ignore: + - '.github/workflows/**' + workflow_dispatch: + inputs: {} + +defaults: + run: + shell: bash + +jobs: + lint: + name: Lint + runs-on: ubuntu-20.04 + steps: + - name: Checkout repo + uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3.0.0 + + - name: Set up Node + uses: actions/setup-node@9ced9a43a244f3ac94f13bfd896db8c8f30da67a # v3.0.0 + with: + cache: 'npm' + cache-dependency-path: '**/package-lock.json' + node-version: '16' + + - name: Run linter + run: | + npm ci + npm run lint diff --git a/.github/workflows/release-browser.yml b/.github/workflows/release-browser.yml new file mode 100644 index 0000000000..e85b9dbf74 --- /dev/null +++ b/.github/workflows/release-browser.yml @@ -0,0 +1,136 @@ +--- +name: Release Browser + +on: + workflow_dispatch: + inputs: + release_type: + description: 'Release Options' + required: true + default: 'Initial Release' + type: choice + options: + - Initial Release + - Redeploy + - Dry Run + +defaults: + run: + shell: bash + +jobs: + setup: + name: Setup + runs-on: ubuntu-20.04 + outputs: + release-version: ${{ steps.version.outputs.version }} + branch-name: ${{ steps.branch.outputs.branch-name }} + steps: + - name: Branch check + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: | + if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then + echo "===================================" + echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches" + echo "===================================" + exit 1 + fi + + - name: Checkout repo + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + + - name: Check Release Version + id: version + uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6 + with: + release-type: ${{ github.event.inputs.release_type }} + project-type: ts + file: apps/browser/src/manifest.json + monorepo: true + monorepo-project: browser + + - name: Get branch name + id: branch + run: | + BRANCH_NAME=$(basename ${{ github.ref }}) + echo "::set-output name=branch-name::$BRANCH_NAME" + + + locales-test: + name: Locales Test + runs-on: ubuntu-20.04 + needs: setup + steps: + - name: Checkout repo + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + + - name: Testing locales - extName length + run: | + found_error=false + + echo "Locales Test" + echo "============" + echo "extName string must be 40 characters or less" + echo + for locale in $(ls src/_locales/); do + string_length=$(jq '.extName.message | length' src/_locales/$locale/messages.json) + if [[ $string_length -gt 40 ]]; then + echo "$locale: $string_length" + found_error=true + fi + done + + if $found_error; then + echo + echo "Please fix 'extName' for the locales listed above." + exit 1 + else + echo "Test passed!" + fi + working-directory: apps/browser + + + release: + name: Create GitHub Release + runs-on: ubuntu-20.04 + needs: + - setup + - locales-test + steps: + - name: Download latest RC build artifacts + uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 + with: + workflow: build-browser.yml + workflow_conclusion: success + branch: ${{ needs.setup.outputs.branch-name }} + artifacts: 'browser-source-*.zip, + dist-chrome-*.zip, + dist-opera-*.zip, + dist-firefox-*.zip, + dist-edge-*.zip' + + - name: Rename build artifacts + env: + PACKAGE_VERSION: ${{ needs.setup.outputs.release-version }} + run: | + mv browser-source.zip browser-source-$PACKAGE_VERSION.zip + mv dist-chrome.zip dist-chrome-$PACKAGE_VERSION.zip + mv dist-opera.zip dist-opera-$PACKAGE_VERSION.zip + mv dist-firefox.zip dist-firefox-$PACKAGE_VERSION.zip + mv dist-edge.zip dist-edge-$PACKAGE_VERSION.zip + + - name: Create release + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 + with: + artifacts: 'browser-source-${{ needs.setup.outputs.release-version }}.zip, + dist-chrome-${{ needs.setup.outputs.release-version }}.zip, + dist-opera-${{ needs.setup.outputs.release-version }}.zip, + dist-firefox-${{ needs.setup.outputs.release-version }}.zip, + dist-edge-${{ needs.setup.outputs.release-version }}.zip' + commit: ${{ github.sha }} + tag: "browser-v${{ needs.setup.outputs.release-version }}" + name: "Browser v${{ needs.setup.outputs.release-version }}" + body: "" + token: ${{ secrets.GITHUB_TOKEN }} + draft: true diff --git a/.github/workflows/release-cli.yml b/.github/workflows/release-cli.yml new file mode 100644 index 0000000000..6ab350c8ce --- /dev/null +++ b/.github/workflows/release-cli.yml @@ -0,0 +1,196 @@ +--- +name: Release CLI + +on: + workflow_dispatch: + inputs: + release_type: + description: 'Release Options' + required: true + default: 'Initial Release' + type: choice + options: + - Initial Release + - Redeploy + - Dry Run + +defaults: + run: + working-directory: apps/cli + +jobs: + setup: + name: Setup + runs-on: ubuntu-20.04 + outputs: + release-version: ${{ steps.version.outputs.version }} + branch-name: ${{ steps.branch.outputs.branch-name }} + steps: + - name: Branch check + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: | + if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then + echo "===================================" + echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches" + echo "===================================" + exit 1 + fi + + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Check Release Version + id: version + uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6 + with: + release-type: ${{ github.event.inputs.release_type }} + project-type: ts + file: apps/cli/package.json + monorepo: true + monorepo-project: cli + + - name: Get branch name + id: branch + run: | + BRANCH_NAME=$(basename ${{ github.ref }}) + echo "::set-output name=branch-name::$BRANCH_NAME" + + - name: Download all artifacts + uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 + with: + workflow: build-cli.yml + path: apps/cli + workflow_conclusion: success + branch: ${{ steps.branch.outputs.branch-name }} + + - name: Create release + uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0 + env: + PKG_VERSION: ${{ steps.version.outputs.version }} + with: + artifacts: "apps/cli/bw-windows-${{ env.PKG_VERSION }}.zip, + apps/cli/bw-windows-sha256-${{ env.PKG_VERSION }}.txt, + apps/cli/bw-macos-${{ env.PKG_VERSION }}.zip, + apps/cli/bw-macos-sha256-${{ env.PKG_VERSION }}.txt, + apps/cli/bw-linux-${{ env.PKG_VERSION }}.zip, + apps/cli/bw-linux-sha256-${{ env.PKG_VERSION }}.txt, + apps/cli/bitwarden-cli.${{ env.PKG_VERSION }}.nupkg, + apps/cli/bw_${{ env.PKG_VERSION }}_amd64.snap, + apps/cli/bw-snap-sha256-${{ env.PKG_VERSION }}.txt" + commit: ${{ github.sha }} + tag: cli-v${{ env.PKG_VERSION }} + name: CLI v${{ env.PKG_VERSION }} + body: "" + token: ${{ secrets.GITHUB_TOKEN }} + draft: true + + + snap: + name: Deploy Snap + runs-on: ubuntu-20.04 + needs: setup + env: + _PKG_VERSION: ${{ needs.setup.outputs.release-version }} + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Login to Azure + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1 + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + with: + keyvault: "bitwarden-prod-kv" + secrets: "snapcraft-store-token" + + - name: Install Snap + uses: samuelmeuli/action-snapcraft@10d7d0a84d9d86098b19f872257df314b0bd8e2d # v1.2.0 + with: + snapcraft_token: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }} + + - name: Download artifacts + uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 + with: + workflow: build-cli.yml + path: apps/cli + workflow_conclusion: success + branch: ${{ needs.setup.outputs.branch-name }} + artifacts: bw_${{ env._PKG_VERSION }}_amd64.snap + + - name: Publish Snap & logout + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: | + snapcraft push bw_${{ env._PKG_VERSION }}_amd64.snap --release stable + snapcraft logout + + + choco: + name: Deploy Choco + runs-on: windows-2019 + needs: setup + env: + _PKG_VERSION: ${{ needs.setup.outputs.release-version }} + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Setup Chocolatey + run: choco apikey --key $env:CHOCO_API_KEY --source https://push.chocolatey.org/ + env: + CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }} + + - name: Make dist dir + shell: pwsh + run: New-Item -ItemType directory -Path ./dist + + - name: Download artifacts + uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 + with: + workflow: build-cli.yml + path: apps/cli + workflow_conclusion: success + branch: ${{ needs.setup.outputs.branch-name }} + artifacts: bitwarden-cli.${{ env._PKG_VERSION }}.nupkg + + - name: Push to Chocolatey + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + shell: pwsh + run: | + cd dist + choco push + + + npm: + name: Publish NPM + runs-on: ubuntu-20.04 + needs: setup + env: + _PKG_VERSION: ${{ needs.setup.outputs.release-version }} + steps: + - name: Checkout repo + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 + + - name: Download artifacts + uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 + with: + workflow: build-cli.yml + path: apps/cli + workflow_conclusion: success + branch: ${{ needs.setup.outputs.branch-name }} + artifacts: bitwarden-cli-${{ env._PKG_VERSION }}-npm-build.zip + + - name: Setup NPM + run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Install Husky + run: npm install -g husky + + - name: Publish NPM + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: npm publish --access public diff --git a/.github/workflows/release-desktop.yml b/.github/workflows/release-desktop.yml new file mode 100644 index 0000000000..54933fe162 --- /dev/null +++ b/.github/workflows/release-desktop.yml @@ -0,0 +1,209 @@ +--- +name: Release Desktop + +on: + workflow_dispatch: + inputs: + release_type: + description: 'Release Options' + required: true + default: 'Initial Release' + type: choice + options: + - Initial Release + - Redeploy + - Dry Run +defaults: + run: + shell: bash + +jobs: + setup: + name: Setup + runs-on: ubuntu-20.04 + outputs: + release-version: ${{ steps.version.outputs.version }} + branch-name: ${{ steps.branch.outputs.branch-name }} + steps: + - name: Branch check + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: | + if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then + echo "===================================" + echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches" + echo "===================================" + exit 1 + fi + + - name: Checkout repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + + - name: Check Release Version + id: version + uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6 + with: + release-type: ${{ github.event.inputs.release_type }} + project-type: ts + file: apps/desktop/src/package.json + monorepo: true + monorepo-project: desktop + + - name: Get branch name + id: branch + run: | + BRANCH_NAME=$(basename ${{ github.ref }}) + echo "::set-output name=branch-name::$BRANCH_NAME" + + - name: Login to Azure + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@b5c723b9ac7870c022b8c35befe620b7009b336f + with: + keyvault: "bitwarden-prod-kv" + secrets: "aws-electron-access-id, aws-electron-access-key, aws-electron-bucket-name" + + - name: Download all artifacts + uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783 + with: + workflow: build-desktop.yml + workflow_conclusion: success + branch: ${{ steps.branch.outputs.branch-name }} + path: apps/desktop/artifacts + + - name: Rename .pkg to .pkg.archive + env: + PKG_VERSION: ${{ steps.version.outputs.version }} + working-directory: apps/desktop/artifacts + run: mv Bitwarden-${{ env.PKG_VERSION }}-universal.pkg Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive + + - name: Publish artifacts to S3 + env: + AWS_ACCESS_KEY_ID: ${{ steps.retrieve-secrets.outputs.aws-electron-access-id }} + AWS_SECRET_ACCESS_KEY: ${{ steps.retrieve-secrets.outputs.aws-electron-access-key }} + AWS_DEFAULT_REGION: 'us-west-2' + AWS_S3_BUCKET_NAME: ${{ steps.retrieve-secrets.outputs.aws-electron-bucket-name }} + working-directory: apps/desktop/artifacts + run: | + aws s3 cp ./ $AWS_S3_BUCKET_NAME/desktop/ \ + --acl "public-read" \ + --recursive \ + --quiet + + - name: Create release + uses: ncipollo/release-action@95215a3cb6e6a1908b3c44e00b4fdb15548b1e09 # v2.8.5 + env: + PKG_VERSION: ${{ steps.version.outputs.version }} + with: + artifacts: "apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-amd64.deb, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x86_64.rpm, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.freebsd, + apps/desktop/artifacts/bitwarden_${{ env.PKG_VERSION }}_amd64.snap, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x86_64.AppImage, + apps/desktop/artifacts/Bitwarden-Portable-${{ env.PKG_VERSION }}.exe, + apps/desktop/artifacts/Bitwarden-Installer-${{ env.PKG_VERSION }}.exe, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32-store.appx, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32.appx, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-ia32.nsis.7z, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64-store.appx, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.appx, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-x64.nsis.7z, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64-store.appx, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64.appx, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-arm64.nsis.7z, + apps/desktop/artifacts/bitwarden.${{ env.PKG_VERSION }}.nupkg, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal-mac.zip, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.dmg, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.dmg.blockmap, + apps/desktop/artifacts/Bitwarden-${{ env.PKG_VERSION }}-universal.pkg.archive" + commit: ${{ github.sha }} + tag: desktop-v${{ env.PKG_VERSION }} + name: Desktop v${{ env.PKG_VERSION }} + body: "" + token: ${{ secrets.GITHUB_TOKEN }} + draft: true + + snap: + name: Deploy Snap + runs-on: ubuntu-20.04 + needs: setup + env: + _PKG_VERSION: ${{ needs.setup.outputs.release-version }} + steps: + - name: Checkout Repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + + - name: Login to Azure + uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 + with: + keyvault: "bitwarden-prod-kv" + secrets: "snapcraft-store-token" + + - name: Install Snap + uses: samuelmeuli/action-snapcraft@10d7d0a84d9d86098b19f872257df314b0bd8e2d # v1.2.0 + with: + snapcraft_token: ${{ steps.retrieve-secrets.outputs.snapcraft-store-token }} + + - name: Setup + run: mkdir dist + working-directory: apps/desktop + + - name: Download Snap artifact + uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783 + with: + workflow: build-desktop.yml + workflow_conclusion: success + branch: ${{ needs.setup.outputs.branch-name }} + artifacts: bitwarden_${{ env._PKG_VERSION }}_amd64.snap + path: apps/desktop/dist + + - name: Deploy to Snap Store + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + run: | + snapcraft upload bitwarden_${{ env._PKG_VERSION }}_amd64.snap --release stable + snapcraft logout + working-directory: apps/desktop/dist + + choco: + name: Deploy Choco + runs-on: windows-2019 + needs: setup + env: + _PKG_VERSION: ${{ needs.setup.outputs.release-version }} + steps: + - name: Checkout Repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + + - name: Setup Chocolatey + run: choco apikey --key $env:CHOCO_API_KEY --source https://push.chocolatey.org/ + env: + CHOCO_API_KEY: ${{ secrets.CHOCO_API_KEY }} + + - name: Make dist dir + shell: pwsh + run: New-Item -ItemType directory -Path ./dist + working-directory: apps/desktop + + - name: Download choco artifact + uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783 + with: + workflow: build-desktop.yml + workflow_conclusion: success + branch: ${{ needs.setup.outputs.branch-name }} + artifacts: bitwarden.${{ env._PKG_VERSION }}.nupkg + path: apps/desktop/dist + + - name: Push to Chocolatey + if: ${{ github.event.inputs.release_type != 'Dry Run' }} + shell: pwsh + run: choco push + working-directory: apps/desktop/dist diff --git a/apps/web/.github/workflows/release.yml b/.github/workflows/release-web.yml similarity index 77% rename from apps/web/.github/workflows/release.yml rename to .github/workflows/release-web.yml index af81eb7398..4b508bfee6 100644 --- a/apps/web/.github/workflows/release.yml +++ b/.github/workflows/release-web.yml @@ -1,5 +1,5 @@ --- -name: Release +name: Release Web on: workflow_dispatch: @@ -20,29 +20,31 @@ jobs: runs-on: ubuntu-20.04 outputs: release_version: ${{ steps.version.outputs.version }} - tag_version: ${{ steps.version.outputs.version }} + tag_version: ${{ steps.version.outputs.tag }} branch_name: ${{ steps.branch.outputs.branch_name }} steps: - name: Branch check if: ${{ github.event.inputs.release_type != 'Dry Run' }} run: | - if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ "$GITHUB_REF" != "refs/heads/hotfix-rc" ]]; then + if [[ "$GITHUB_REF" != "refs/heads/rc" ]] && [[ $GITHUB_REF != refs/heads/hotfix-rc/* ]]; then echo "===================================" - echo "[!] Can only release from the 'rc' or 'hotfix-rc' branches" + echo "[!] Can only release from the 'rc' or 'hotfix-rc/*' branches" echo "===================================" exit 1 fi - name: Checkout repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # 2.4.0 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Check Release Version id: version - uses: bitwarden/gh-actions/release-version-check@ea9fab01d76940267b4147cc1c4542431246b9f6 + uses: bitwarden/gh-actions/release-version-check@8f055ef543c7433c967a1b9b04a0f230923233bb with: release-type: ${{ github.event.inputs.release_type }} project-type: ts - file: package.json + file: apps/web/package.json + monorepo: true + monorepo-project: web - name: Get branch name id: branch @@ -69,7 +71,7 @@ jobs: echo "Github Release Option: $_RELEASE_OPTION" - name: Checkout repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 ########## DockerHub ########## - name: Setup DCT @@ -87,16 +89,12 @@ jobs: docker pull bitwarden/web:$_BRANCH_NAME fi - - name: Tag version and latest + - name: Docker Tag version and latest image run: | - if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then - docker tag bitwarden/web:latest bitwarden/web:dryrun - else - docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:$_RELEASE_VERSION - docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:latest - fi + docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:$_RELEASE_VERSION + docker tag bitwarden/web:$_BRANCH_NAME bitwarden/web:latest - - name: Push version and latest image + - name: Docker Push version and latest image if: ${{ github.event.inputs.release_type != 'Dry Run' }} env: DOCKER_CONTENT_TRUST: 1 @@ -112,7 +110,7 @@ jobs: ########## ACR ########## - name: Login to Azure - QA Subscription - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + uses: Azure/login@ec3c14589bd3e9312b3cc8c41e6860e258df9010 # v1.1 with: creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} @@ -123,15 +121,11 @@ jobs: env: REGISTRY: bitwardenqa.azurecr.io run: | - if [[ "${{ github.event.inputs.release_type }}" == "Dry Run" ]]; then - docker tag bitwarden/web:latest $REGISTRY/web:dryrun - else - docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:$_RELEASE_VERSION - docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:latest + docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:$_RELEASE_VERSION + docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web:latest - docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:$_RELEASE_VERSION - docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:latest - fi + docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:$_RELEASE_VERSION + docker tag bitwarden/web:$_BRANCH_NAME $REGISTRY/web-sh:latest - name: Push version and latest image if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -159,7 +153,7 @@ jobs: _TAG_VERSION: ${{ needs.setup.outputs.tag_version }} steps: - name: Checkout Repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 # v2.4.0 with: ref: gh-pages @@ -169,7 +163,7 @@ jobs: git push -u origin gh-pages-deploy-$_TAG_VERSION - name: Checkout Repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 # v2.4.0 - name: Setup git config run: | @@ -181,22 +175,24 @@ jobs: - name: Download latest cloud asset uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 with: - workflow: build.yml + workflow: build-web.yml + path: apps/web workflow_conclusion: success branch: ${{ needs.setup.outputs.branch_name }} artifacts: web-*-cloud-COMMERCIAL.zip # This should result in a build directory in the current working directory - name: Unzip build asset + working-directory: apps/web run: unzip web-*-cloud-COMMERCIAL.zip - name: Deploy GitHub Pages - uses: crazy-max/ghaction-github-pages@a117e4aa1fb4854d021546d2abdfac95be568a3a # v2.6.0 + uses: crazy-max/ghaction-github-pages@eb08c35b9fab86751edfff4e55cd5cde35ff0e52 # v3.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: target_branch: gh-pages-deploy-${{ needs.setup.outputs.tag_version }} - build_dir: build + build_dir: apps/web/build keep_history: true commit_message: "Staging deploy ${{ needs.setup.outputs.release_version }}" dry_run: ${{ github.event.inputs.release_type == 'Dry Run' }} @@ -224,22 +220,24 @@ jobs: _TAG_VERSION: ${{ needs.setup.outputs.tag_version }} steps: - name: Checkout Repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Download latest cloud asset uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 with: - workflow: build.yml + workflow: build-web.yml + path: apps/web workflow_conclusion: success branch: ${{ needs.setup.outputs.branch_name }} artifacts: web-*-cloud-COMMERCIAL.zip # This should result in a build directory in the current working directory - name: Unzip build asset + working-directory: apps/web run: unzip web-*-cloud-COMMERCIAL.zip - name: Checkout Repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2.4.0 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 with: ref: deploy path: deployment @@ -254,7 +252,7 @@ jobs: - name: Deploy CloudFlare Pages run: | rm -rf ./* - cp -R ../build/* . + cp -R apps/web/build/* . working-directory: deployment - name: Create cf-pages-deploy branch @@ -263,7 +261,7 @@ jobs: git add . git commit -m "Staging deploy ${{ needs.setup.outputs.release_version }}" git push -u origin cf-pages-deploy-$_TAG_VERSION - working-directory: deployment + working-directory: deployment - name: Create CloudFlare Pages Deploy PR if: ${{ github.event.inputs.release_type != 'Dry Run' }} @@ -287,29 +285,31 @@ jobs: - cfpages-deploy steps: - name: Download latest build artifacts - uses: bitwarden/gh-actions/download-artifacts@23433be15ed6fd046ce12b6889c5184a8d9c8783 + uses: bitwarden/gh-actions/download-artifacts@c1fa8e09871a860862d6bbe36184b06d2c7e35a8 with: - workflow: build.yml + workflow: build-web.yml + path: apps/web/artifacts workflow_conclusion: success branch: ${{ needs.setup.outputs.branch_name }} artifacts: "web-*-selfhosted-COMMERCIAL.zip, web-*-selfhosted-open-source.zip" - name: Rename assets + working-directory: apps/web/artifacts run: | mv web-*-selfhosted-COMMERCIAL.zip web-${{ needs.setup.outputs.release_version }}-selfhosted-COMMERCIAL.zip mv web-*-selfhosted-open-source.zip web-${{ needs.setup.outputs.release_version }}-selfhosted-open-source.zip - name: Create release if: ${{ github.event.inputs.release_type != 'Dry Run' }} - uses: ncipollo/release-action@40bb172bd05f266cf9ba4ff965cb61e9ee5f6d01 + uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0 with: - name: "Version ${{ needs.setup.outputs.release_version }}" + name: "Version v${{ needs.setup.outputs.release_version }}" commit: ${{ github.sha }} tag: "${{ needs.setup.outputs.tag_version }}" body: "" - artifacts: "web-${{ needs.setup.outputs.release_version }}-selfhosted-COMMERCIAL.zip, - web-${{ needs.setup.outputs.release_version }}-selfhosted-open-source.zip" + artifacts: "apps/web/artifacts/web-${{ needs.setup.outputs.release_version }}-selfhosted-COMMERCIAL.zip, + apps/web/artifacts/web-${{ needs.setup.outputs.release_version }}-selfhosted-open-source.zip" token: ${{ secrets.GITHUB_TOKEN }} draft: true @@ -325,7 +325,7 @@ jobs: - release steps: - name: Checkout repo - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # 2.4.0 + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2 - name: Remove gh-pages-deploy branch run: git push origin --delete gh-pages-deploy-$_TAG_VERSION diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml new file mode 100644 index 0000000000..3d293c8466 --- /dev/null +++ b/.github/workflows/version-bump.yml @@ -0,0 +1,140 @@ +--- +name: Version Bump + +on: + workflow_dispatch: + inputs: + client: + description: "Client Project" + required: true + type: choice + options: + - Browser + - CLI + - Desktop + - Web + version_number: + description: "New Version" + required: true + +defaults: + run: + shell: bash + +jobs: + bump_version: + name: "Bump ${{ github.event.inputs.client }} Version" + runs-on: ubuntu-20.04 + steps: + - name: Checkout Branch + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + + - name: Create Version Branch + id: branch + env: + CLIENT_NAME: ${{ github.event.inputs.client }} + run: | + CLIENT=$(python -c "print('$CLIENT_NAME'.lower())") + echo "::set-output name=client::$CLIENT" + + git switch -c ${CLIENT}_version_bump_${{ github.event.inputs.version_number }} + git push -u origin ${CLIENT}_version_bump_${{ github.event.inputs.version_number }} + + - name: Checkout Version Branch + uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 + with: + ref: ${{ steps.branch.outputs.client }}_version_bump_${{ github.event.inputs.version_number }} + + ######################## + # VERSION BUMP SECTION # + ######################## + + ### Browser + - name: Bump Browser Version - Manifest + if: ${{ github.event.inputs.client == 'Browser' }} + uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + with: + version: ${{ github.event.inputs.version_number }} + file_path: "apps/browser/src/manifest.json" + + - name: Run Prettier after Browser Version Bump + if: ${{ github.event.inputs.client == 'Browser' }} + run: | + npm install -g prettier + prettier --write apps/browser/src/manifest.json + + ### CLI + - name: Bump CLI Version - Package + if: ${{ github.event.inputs.client == 'CLI' }} + uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + with: + version: ${{ github.event.inputs.version_number }} + file_path: "apps/cli/package.json" + + - name: Bump CLI Version - Package-lock + if: ${{ github.event.inputs.client == 'CLI' }} + uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + with: + version: ${{ github.event.inputs.version_number }} + file_path: "apps/cli/package-lock.json" + + ### Desktop + - name: Bump Desktop Version - Package + if: ${{ github.event.inputs.client == 'Desktop' }} + uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + with: + version: ${{ github.event.inputs.version_number }} + file_path: "apps/desktop/src/package.json" + + ### Web + - name: Bump Web Version - package.json + if: ${{ github.event.inputs.client == 'Web' }} + uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + with: + version: ${{ github.event.inputs.version_number }} + file_path: "apps/web/package.json" + + - name: Bump Web Version - package-lock.json + if: ${{ github.event.inputs.client == 'Web' }} + uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 + with: + version: ${{ github.event.inputs.version_number }} + file_path: "apps/web/package-lock.json" + + ######################## + + - name: Commit files + env: + CLIENT: ${{ steps.branch.outputs.client }} + run: | + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git commit -m "Bumped ${CLIENT} version to ${{ github.event.inputs.version_number }}" -a + + - name: Push changes + env: + CLIENT: ${{ steps.branch.outputs.client }} + run: git push -u origin ${CLIENT}_version_bump_${{ github.event.inputs.version_number }} + + - name: Create Bump Version PR + env: + PR_BRANCH: "${{ steps.branch.outputs.client }}_version_bump_${{ github.event.inputs.version_number }}" + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + BASE_BRANCH: master + TITLE: "Bump ${{ github.event.inputs.client }} version to ${{ github.event.inputs.version_number }}" + run: | + gh pr create --title "$TITLE" \ + --base "$BASE" \ + --head "$PR_BRANCH" \ + --label "version update" \ + --label "automated pr" \ + --body " + ## Type of change + - [ ] Bug fix + - [ ] New feature development + - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) + - [ ] Build/deploy pipeline (DevOps) + - [X] Other + + ## Objective + Automated ${{ github.event.inputs.client }} version bump to ${{ github.event.inputs.version_number }}" diff --git a/apps/web/.github/workflows/workflow-linter.yml b/.github/workflows/workflow-linter.yml similarity index 100% rename from apps/web/.github/workflows/workflow-linter.yml rename to .github/workflows/workflow-linter.yml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..71fec37f66 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +**/coverage/ +.github/workflows/act \ No newline at end of file diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 0000000000..31354ec138 --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/apps/web/.husky/pre-commit b/.husky/pre-commit similarity index 100% rename from apps/web/.husky/pre-commit rename to .husky/pre-commit diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000000..f0b10f153f --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v16.13.1 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..8f0e568829 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,27 @@ +# Build directories +**/build +**/dist +**/coverage + +# External libraries / auto synced locales +apps/browser/src/_locales +apps/browser/src/scripts/duo.js +apps/browser/src/content/autofill.js +apps/browser/src/safari + +apps/desktop/src/locales +apps/desktop/dist-safari +apps/desktop/desktop_native +apps/desktop/src/scripts/duo.js + +apps/cli/src/locales +apps/cli/.github + +apps/web/.github +apps/web/src/404/bootstrap.min.css +apps/web/src/locales + +libs/.github + +# Github Workflows +.github/workflows diff --git a/apps/web/.prettierrc.json b/.prettierrc.json similarity index 100% rename from apps/web/.prettierrc.json rename to .prettierrc.json diff --git a/apps/web/CONTRIBUTING.md b/CONTRIBUTING.md similarity index 76% rename from apps/web/CONTRIBUTING.md rename to CONTRIBUTING.md index bdb83691aa..b1938d2383 100644 --- a/apps/web/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,11 +11,11 @@ Here is how you can get involved: - **Report a bug or submit a bugfix:** Use Github issues and pull requests - **Write documentation:** Submit a pull request to the [Bitwarden help repository](https://github.com/bitwarden/help) - **Help other users:** Go to the [Ask the Bitwarden Community category](https://community.bitwarden.com/c/support/) on the Community Forums -- **Translate:** See the localization (l10n) section below +- **Translate:** See the localization (i10n) section below ## Contributor Agreement -Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/web) if you intend on contributing to any Github repository. Pull requests cannot be accepted and merged unless the author has signed the Contributor Agreement. +Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/clients) if you intend on contributing to any Github repository. Pull requests cannot be accepted and merged unless the author has signed the Contributor Agreement. ## Pull Request Guidelines @@ -25,11 +25,13 @@ Please sign the [Contributor Agreement](https://cla-assistant.io/bitwarden/web) # Localization (l10n) -[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-web/localized.svg)](https://crowdin.com/project/bitwarden-web) - We use a translation tool called [Crowdin](https://crowdin.com) to help manage our localization efforts across many different languages. -If you are interested in helping translate the Bitwarden web vault into another language (or make a translation correction), please register an account at Crowdin and join our project here: https://crowdin.com/project/bitwarden-web +If you are interested in helping translate the Bitwarden applications into another language (or make a translation correction), please register an account at Crowdin and join our projects here: + +- https://crowdin.com/project/bitwarden-web +- https://crowdin.com/project/bitwarden-desktop +- https://crowdin.com/project/bitwarden-browser If the language that you are interested in translating is not already listed, create a new account on Crowdin, join the project, and contact the project owner (https://crowdin.com/profile/dwbit). diff --git a/apps/web/LICENSE.txt b/LICENSE.txt similarity index 100% rename from apps/web/LICENSE.txt rename to LICENSE.txt diff --git a/apps/web/LICENSE_BITWARDEN.txt b/LICENSE_BITWARDEN.txt similarity index 100% rename from apps/web/LICENSE_BITWARDEN.txt rename to LICENSE_BITWARDEN.txt diff --git a/apps/web/LICENSE_GPL.txt b/LICENSE_GPL.txt similarity index 100% rename from apps/web/LICENSE_GPL.txt rename to LICENSE_GPL.txt diff --git a/README.md b/README.md new file mode 100644 index 0000000000..0d238e0bdd --- /dev/null +++ b/README.md @@ -0,0 +1,134 @@ +

+ Bitwarden +

+

+ + Github Workflow browser build on master + + + Github Workflow desktop build on master + + + gitter chat + +

+ +--- + +# Bitwarden Client Applications + +This repository houses all Bitwarden client applications except the [Mobile application](https://github.com/bitwarden/mobile). + +Please check the readmes for each application under `apps` for instructions on how to build the different applications. + +## Related projects: + +- [bitwarden/server](https://github.com/bitwarden/server): The core infrastructure backend (API, database, Docker, etc). +- [bitwarden/mobile](https://github.com/bitwarden/mobile): The mobile app vault (iOS and Android). +- [bitwarden/directory-connector](https://github.com/bitwarden/directory-connector): A tool for syncing a directory (AD, LDAP, Azure, G Suite, Okta) to an organization. + +# We're Hiring! + +Interested in contributing in a big way? Consider joining our team! We're hiring for many positions. Please take a look at our [Careers page](https://bitwarden.com/careers/) to see what opportunities are currently open as well as what it's like to work at Bitwarden. + +# Contribute + +Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [`CONTRIBUTING.md`](CONTRIBUTING.md) file. + +Security audits and feedback are welcome. Please open an issue or email us privately if the report is sensitive in nature. You can read our security policy in the [`SECURITY.md`](SECURITY.md) file. + +## Git blame + +We recommend that you configure git to ignore specific revision using: + +```bash +git config blame.ignoreRevsFile .git-blame-ignore-revs +``` + +## Migrate PRs from old repositories + +We recently migrated from individual client repositories. And some PRs were unfortunately left behind in the old repositories. Luckily it's fairly straightforward to sync them up again. Please follow all the instructions below in order to avoid most merge conflicts. + +### Desktop + +``` +# Merge master +git merge master + +# Merge branch mono-repo-prep +git merge 28bc4113b9bbae4dba2b5af14d460764fce79acf + +# Verify files are placed in apps/desktop + +# Add remote +git remote add clients git@github.com:bitwarden/clients.git + +# Merge against clients master +git fetch clients +git merge clients/master + +# Push to clients or your own fork +``` + +### CLI + +``` +# Merge master +git merge master + +# Merge branch mono-repo-prep +git merge 980429f4bdcb178d8d92d8202cbdacfaa45c917e + +# Verify files are placed in apps/cli + +# Add remote +git remote add clients git@github.com:bitwarden/clients.git + +# Merge against clients master +git fetch clients +git merge clients/master + +# Push to clients or your own fork +``` + +### Web + +``` +# Merge master +git merge master + +# Merge branch mono-repo-prep +git merge 02fe7159034b04d763a61fcf0200869e3209fa33 + +# Verify files are placed in apps/web + +# Add remote +git remote add clients git@github.com:bitwarden/clients.git + +# Merge against clients master +git fetch clients +git merge clients/master + +# Push to clients or your own fork +``` + +### Jslib + +``` +# Merge master +git merge master + +# Merge branch mono-repo +git merge d7492e3cf320410e74ebd0e0675ab994e64bd01a + +# Verify files are placed in libs + +# Add remote +git remote add clients git@github.com:bitwarden/clients.git + +# Merge against clients master +git fetch clients +git merge clients/master + +# Push to clients or your own fork +``` diff --git a/apps/web/SECURITY.md b/SECURITY.md similarity index 100% rename from apps/web/SECURITY.md rename to SECURITY.md diff --git a/apps/browser/.gitignore b/apps/browser/.gitignore new file mode 100644 index 0000000000..9909d8417b --- /dev/null +++ b/apps/browser/.gitignore @@ -0,0 +1,20 @@ +.vs +.vscode +.idea +.DS_Store +node_modules +npm-debug.log +vwd.webinfo +css/ +dist/ +dist-safari/ +webfonts/ +*.crx +*.pem +*.zip +build/ +build.safariextension/ +xcuserdata/ +*.hmap +!src/safari/safari/app/popup/index.html +src/safari/safari/app/ diff --git a/apps/browser/README.md b/apps/browser/README.md new file mode 100644 index 0000000000..90a46e8dfb --- /dev/null +++ b/apps/browser/README.md @@ -0,0 +1,52 @@ +[![Github Workflow build browser on master](https://github.com/bitwarden/clients/actions/workflows/build-browser.yml/badge.svg?branch=master)](https://github.com/bitwarden/clients/actions/workflows/build-browser.yml?query=branch:master) +[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-browser/localized.svg)](https://crowdin.com/project/bitwarden-browser) +[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby) + +# Bitwarden Browser Extension + + + + + + + + + + +The Bitwarden browser extension is written using the Web Extension API and Angular. + +![My Vault](https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/browser-chrome.png) + +# Build/Run + +**Requirements** + +- [Node.js](https://nodejs.org) v16.13.1 or greater +- NPM v8 +- [Gulp](https://gulpjs.com/) (`npm install --global gulp-cli`) +- Chrome (preferred), Opera, or Firefox browser + +**Run the app** + +``` +npm install +npm run build:watch +``` + +You can now load the extension into your browser through the browser's extension tools page: + +- Chrome/Opera: + 1. Type `chrome://extensions` in your address bar to bring up the extensions page. + 2. Enable developer mode (toggle switch) + 3. Click the "Load unpacked extension" button, navigate to the `build` folder of your local extension instance, and click "Ok". +- Firefox + 1. Type `about:debugging` in your address bar to bring up the add-ons page. + 2. Click the `Load Temporary Add-on` button, navigate to the `build/manifest.json` file, and "Open". + +**Desktop communication** + +Native Messaging (communication between the desktop application and browser extension) works by having the browser start a lightweight proxy baked into our desktop application. + +Out of the box, the desktop application can only communicate with the production browser extension. When you enable browser integration in the desktop application, the application generates manifests which contain the production IDs of the browser extensions. To enable communication between the desktop application and development versions of browser extensions, add the development IDs to the `allowed_extensions` section of the corresponding manifests. + +Manifests are located in the `browser` subdirectory of the Bitwarden configuration directory. For instance, on Windows the manifests are located at `C:\Users\\AppData\Roaming\Bitwarden\browsers` and on macOS these are in `Application Support` for various browsers ([for example](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#manifest_location)). Note that disabling the desktop integration will delete the manifests, and the files will need to be updated again. diff --git a/apps/browser/crowdin.yml b/apps/browser/crowdin.yml new file mode 100644 index 0000000000..6d51304a18 --- /dev/null +++ b/apps/browser/crowdin.yml @@ -0,0 +1,28 @@ +project_id_env: CROWDIN_PROJECT_ID +api_token_env: CROWDIN_API_TOKEN +preserve_hierarchy: true +files: + - source: /src/_locales/en/messages.json + dest: /src/_locales/en/%original_file_name% + translation: /src/_locales/%two_letters_code%/%original_file_name% + update_option: update_as_unapproved + languages_mapping: + two_letters_code: + pt-PT: pt_PT + pt-BR: pt_BR + zh-CN: zh_CN + zh-TW: zh_TW + en-GB: en_GB + en-IN: en_IN + - source: /store/locales/en/copy.resx + dest: /store/locales/en/%original_file_name% + translation: /store/locales/%two_letters_code%/%original_file_name% + update_option: update_as_unapproved + languages_mapping: + two_letters_code: + pt-PT: pt_PT + pt-BR: pt_BR + zh-CN: zh_CN + zh-TW: zh_TW + en-GB: en_GB + en-IN: en_IN diff --git a/apps/browser/gulpfile.js b/apps/browser/gulpfile.js new file mode 100644 index 0000000000..87fb086ca6 --- /dev/null +++ b/apps/browser/gulpfile.js @@ -0,0 +1,245 @@ +const child = require("child_process"); +const fs = require("fs"); + +const del = require("del"); +const gulp = require("gulp"); +const filter = require("gulp-filter"); +const gulpif = require("gulp-if"); +const jeditor = require("gulp-json-editor"); +const replace = require("gulp-replace"); +const zip = require("gulp-zip"); + +const manifest = require("./src/manifest.json"); + +const paths = { + build: "./build/", + dist: "./dist/", + coverage: "./coverage/", + node_modules: "./node_modules/", + popupDir: "./src/popup/", + cssDir: "./src/popup/css/", + safari: "./src/safari/", +}; + +const filters = { + fonts: [ + "!build/popup/fonts/*", + "build/popup/fonts/Open_Sans*.woff", + "build/popup/fonts/bwi-font.woff2", + "build/popup/fonts/bwi-font.woff", + "build/popup/fonts/bwi-font.ttf", + ], + safari: ["!build/safari/**/*"], +}; + +function buildString() { + var build = ""; + if (process.env.BUILD_NUMBER && process.env.BUILD_NUMBER !== "") { + build = `-${process.env.BUILD_NUMBER}`; + } + return build; +} + +function distFileName(browserName, ext) { + return `dist-${browserName}${buildString()}.${ext}`; +} + +function dist(browserName, manifest) { + return gulp + .src(paths.build + "**/*") + .pipe(filter(["**"].concat(filters.fonts).concat(filters.safari))) + .pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_" + browserName))) + .pipe(gulpif("manifest.json", jeditor(manifest))) + .pipe(zip(distFileName(browserName, "zip"))) + .pipe(gulp.dest(paths.dist)); +} + +function distFirefox() { + return dist("firefox", (manifest) => { + delete manifest.content_security_policy; + removeShortcuts(manifest); + return manifest; + }); +} + +function distOpera() { + return dist("opera", (manifest) => { + delete manifest.applications; + delete manifest.content_security_policy; + removeShortcuts(manifest); + return manifest; + }); +} + +function distChrome() { + return dist("chrome", (manifest) => { + delete manifest.applications; + delete manifest.content_security_policy; + delete manifest.sidebar_action; + delete manifest.commands._execute_sidebar_action; + return manifest; + }); +} + +function distEdge() { + return dist("edge", (manifest) => { + delete manifest.applications; + delete manifest.content_security_policy; + delete manifest.sidebar_action; + delete manifest.commands._execute_sidebar_action; + return manifest; + }); +} + +function removeShortcuts(manifest) { + if (manifest.content_scripts && manifest.content_scripts.length > 1) { + const shortcutsScript = manifest.content_scripts[1]; + if (shortcutsScript.js.indexOf("content/shortcuts.js") > -1) { + manifest.content_scripts.splice(1, 1); + } + } +} + +function distSafariMas(cb) { + return distSafariApp(cb, "mas"); +} + +function distSafariMasDev(cb) { + return distSafariApp(cb, "masdev"); +} + +function distSafariDmg(cb) { + return distSafariApp(cb, "dmg"); +} + +function distSafariApp(cb, subBuildPath) { + const buildPath = paths.dist + "Safari/" + subBuildPath + "/"; + const builtAppexPath = buildPath + "build/Release/safari.appex"; + const builtAppexFrameworkPath = buildPath + "build/Release/safari.appex/Contents/Frameworks/"; + const entitlementsPath = paths.safari + "safari/safari.entitlements"; + var args = [ + "--verbose", + "--force", + "-o", + "runtime", + "--sign", + "Developer ID Application: 8bit Solutions LLC", + "--entitlements", + entitlementsPath, + ]; + if (subBuildPath !== "dmg") { + args = [ + "--verbose", + "--force", + "--sign", + subBuildPath === "mas" + ? "3rd Party Mac Developer Application: 8bit Solutions LLC" + : "6B287DD81FF922D86FD836128B0F62F358B38726", + "--entitlements", + entitlementsPath, + ]; + } + + return del([buildPath + "**/*"]) + .then(() => safariCopyAssets(paths.safari + "**/*", buildPath)) + .then(() => safariCopyBuild(paths.build + "**/*", buildPath + "safari/app")) + .then(() => { + const proc = child.spawn("xcodebuild", [ + "-project", + buildPath + "desktop.xcodeproj", + "-alltargets", + "-configuration", + "Release", + ]); + stdOutProc(proc); + return new Promise((resolve) => proc.on("close", resolve)); + }) + .then(() => { + const libs = fs + .readdirSync(builtAppexFrameworkPath) + .filter((p) => p.endsWith(".dylib")) + .map((p) => builtAppexFrameworkPath + p); + const libPromises = []; + libs.forEach((i) => { + const proc = child.spawn("codesign", args.concat([i])); + stdOutProc(proc); + libPromises.push(new Promise((resolve) => proc.on("close", resolve))); + }); + return Promise.all(libPromises); + }) + .then(() => { + const proc = child.spawn("codesign", args.concat([builtAppexPath])); + stdOutProc(proc); + return new Promise((resolve) => proc.on("close", resolve)); + }) + .then( + () => { + return cb; + }, + () => { + return cb; + } + ); +} + +function safariCopyAssets(source, dest) { + return new Promise((resolve, reject) => { + gulp + .src(source) + .on("error", reject) + .pipe(gulpif("safari/Info.plist", replace("0.0.1", manifest.version))) + .pipe( + gulpif("safari/Info.plist", replace("0.0.2", process.env.BUILD_NUMBER || manifest.version)) + ) + .pipe(gulpif("desktop.xcodeproj/project.pbxproj", replace("../../../build", "../safari/app"))) + .pipe(gulp.dest(dest)) + .on("end", resolve); + }); +} + +function safariCopyBuild(source, dest) { + return new Promise((resolve, reject) => { + gulp + .src(source) + .on("error", reject) + .pipe(filter(["**"].concat(filters.fonts))) + .pipe(gulpif("popup/index.html", replace("__BROWSER__", "browser_safari"))) + .pipe( + gulpif( + "manifest.json", + jeditor((manifest) => { + delete manifest.optional_permissions; + manifest.permissions.push("nativeMessaging"); + return manifest; + }) + ) + ) + .pipe(gulp.dest(dest)) + .on("end", resolve); + }); +} + +function stdOutProc(proc) { + proc.stdout.on("data", (data) => console.log(data.toString())); + proc.stderr.on("data", (data) => console.error(data.toString())); +} + +function ciCoverage(cb) { + return gulp + .src(paths.coverage + "**/*") + .pipe(filter(["**", "!coverage/coverage*.zip"])) + .pipe(zip(`coverage${buildString()}.zip`)) + .pipe(gulp.dest(paths.coverage)); +} + +exports["dist:firefox"] = distFirefox; +exports["dist:chrome"] = distChrome; +exports["dist:opera"] = distOpera; +exports["dist:edge"] = distEdge; +exports["dist:safari"] = gulp.parallel(distSafariMas, distSafariMasDev, distSafariDmg); +exports["dist:safari:mas"] = distSafariMas; +exports["dist:safari:masdev"] = distSafariMasDev; +exports["dist:safari:dmg"] = distSafariDmg; +exports.dist = gulp.parallel(distFirefox, distChrome, distOpera, distEdge); +exports["ci:coverage"] = ciCoverage; +exports.ci = ciCoverage; diff --git a/apps/browser/jest.config.js b/apps/browser/jest.config.js new file mode 100644 index 0000000000..025db301eb --- /dev/null +++ b/apps/browser/jest.config.js @@ -0,0 +1,13 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + preset: "jest-preset-angular", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), +}; diff --git a/apps/browser/package.json b/apps/browser/package.json new file mode 100644 index 0000000000..9019d30bad --- /dev/null +++ b/apps/browser/package.json @@ -0,0 +1,20 @@ +{ + "name": "@bitwarden/browser", + "version": "0.0.0", + "scripts": { + "build": "webpack", + "build:watch": "webpack --watch", + "build:prod": "cross-env NODE_ENV=production webpack", + "build:prod:watch": "cross-env NODE_ENV=production webpack --watch", + "dist": "npm run build:prod && gulp dist", + "dist:firefox": "npm run build:prod && gulp dist:firefox", + "dist:opera": "npm run build:prod && gulp dist:opera", + "dist:safari": "npm run build:prod && gulp dist:safari", + "dist:safari:mas": "npm run build:prod && gulp dist:safari:mas", + "dist:safari:masdev": "npm run build:prod && gulp dist:safari:masdev", + "dist:safari:dmg": "npm run build:prod && gulp dist:safari:dmg", + "test": "jest", + "test:watch": "jest --watch", + "test:watch:all": "jest --watchAll" + } +} diff --git a/apps/browser/src/_locales/az/messages.json b/apps/browser/src/_locales/az/messages.json new file mode 100644 index 0000000000..745c3e5e95 --- /dev/null +++ b/apps/browser/src/_locales/az/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Ödənişsiz Parol Meneceri", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bütün cihazlarınız üçün təhlükəsiz və ödənişsiz bir parol meneceri.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Təhlükəsiz anbarınıza müraciət etmək üçün giriş edin və ya yeni bir hesab yaradın." + }, + "createAccount": { + "message": "Hesab yarat" + }, + "login": { + "message": "Giriş et" + }, + "enterpriseSingleSignOn": { + "message": "Müəssisə üçün tək daxil olma" + }, + "cancel": { + "message": "İmtina" + }, + "close": { + "message": "Bağla" + }, + "submit": { + "message": "Göndər" + }, + "emailAddress": { + "message": "E-poçt ünvanı" + }, + "masterPass": { + "message": "Ana parol" + }, + "masterPassDesc": { + "message": "Ana parol, anbarınıza müraciət etmək üçün istifadə edəcəyiniz paroldur. Ana parolu yadda saxlamaq çox vacibdir. Unutsanız, parolu bərpa etməyin heç bir yolu yoxdur." + }, + "masterPassHintDesc": { + "message": "Ana parol məsləhəti, unutduğunuz parolunuzu xatırlamağınıza kömək edir." + }, + "reTypeMasterPass": { + "message": "Ana parolu yenidən yaz" + }, + "masterPassHint": { + "message": "Ana parol məsləhəti (ixtiyari)" + }, + "tab": { + "message": "Vərəq" + }, + "myVault": { + "message": "Anbarım" + }, + "tools": { + "message": "Alətlər" + }, + "settings": { + "message": "Tənzimləmələr" + }, + "currentTab": { + "message": "Hazırkı vərəq" + }, + "copyPassword": { + "message": "Parolu kopyala" + }, + "copyNote": { + "message": "Qeydi kopyala" + }, + "copyUri": { + "message": "URI-ni kopyala" + }, + "copyUsername": { + "message": "İstifadəçi adını kopyala" + }, + "copyNumber": { + "message": "Nömrəni kopyala" + }, + "copySecurityCode": { + "message": "Təhlükəsizlik kodunu kopyala" + }, + "autoFill": { + "message": "Avto-doldurma" + }, + "generatePasswordCopied": { + "message": "Parol yarat (kopyalandı)" + }, + "copyElementIdentifier": { + "message": "Özəl sahə adını kopyala" + }, + "noMatchingLogins": { + "message": "Uyğun gələn hesab yoxdur." + }, + "unlockVaultMenu": { + "message": "Anbarın kilidini açın" + }, + "loginToVaultMenu": { + "message": "Anbarınıza giriş edin" + }, + "autoFillInfo": { + "message": "Hazırkı səyyah vərəqi üçün avto-doldurulacaq giriş məlumatları yoxdur." + }, + "addLogin": { + "message": "Hesab əlavə et" + }, + "addItem": { + "message": "Element əlavə et" + }, + "passwordHint": { + "message": "Parol məsləhəti" + }, + "enterEmailToGetHint": { + "message": "Ana parol məsləhətini alacağınız hesabınızın e-poçt ünvanını daxil edin." + }, + "getMasterPasswordHint": { + "message": "Ana parol üçün məsləhət alın" + }, + "continue": { + "message": "Davam" + }, + "sendVerificationCode": { + "message": "E-poçtunuza bir təsdiqləmə kodu göndərin" + }, + "sendCode": { + "message": "Kod göndər" + }, + "codeSent": { + "message": "Kod göndərildi" + }, + "verificationCode": { + "message": "Təsdiqləmə kodu" + }, + "confirmIdentity": { + "message": "Davam etmək üçün kimliyinizi təsdiqləyin." + }, + "account": { + "message": "Hesab" + }, + "changeMasterPassword": { + "message": "Ana parolu dəyişdir" + }, + "fingerprintPhrase": { + "message": "Barmaq izi ifadəsi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Hesabınızın barmaq izi ifadəsi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "İki mərhələli giriş" + }, + "logOut": { + "message": "Çıxış" + }, + "about": { + "message": "Haqqında" + }, + "version": { + "message": "Versiya" + }, + "save": { + "message": "Saxla" + }, + "move": { + "message": "Daşı" + }, + "addFolder": { + "message": "Qovluq əlavə et" + }, + "name": { + "message": "Ad" + }, + "editFolder": { + "message": "Qovluğa düzəliş et" + }, + "deleteFolder": { + "message": "Qovluğu sil" + }, + "folders": { + "message": "Qovluqlar" + }, + "noFolders": { + "message": "Siyahılanacaq heç bir qovluq yoxdur." + }, + "helpFeedback": { + "message": "Kömək və əks əlaqə" + }, + "sync": { + "message": "Eyniləşdirmə" + }, + "syncVaultNow": { + "message": "Anbarı indi eyniləşdir" + }, + "lastSync": { + "message": "Son eyniləşdirmə:" + }, + "passGen": { + "message": "Parol yaradıcı" + }, + "generator": { + "message": "Yaradıcı", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Hesablarınız üçün avtomatik olaraq güclü, unikal parollar yaradın." + }, + "bitWebVault": { + "message": "Bitwarden veb anbarı" + }, + "importItems": { + "message": "Elementləri idxal et" + }, + "select": { + "message": "Seçin" + }, + "generatePassword": { + "message": "Parol yarat" + }, + "regeneratePassword": { + "message": "Parolu yenidən yarat" + }, + "options": { + "message": "Seçimlər" + }, + "length": { + "message": "Uzunluq" + }, + "uppercase": { + "message": "Böyük hərf (A-Z)" + }, + "lowercase": { + "message": "Kiçik hərf (a-z)" + }, + "numbers": { + "message": "Rəqəmlər (0-9)" + }, + "specialCharacters": { + "message": "Xüsusi simvollar (!@#$%^&*)" + }, + "numWords": { + "message": "Söz sayı" + }, + "wordSeparator": { + "message": "Söz ayırıcı" + }, + "capitalize": { + "message": "İlk hərfi böyük yaz", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Rəqəm əlavə et" + }, + "minNumbers": { + "message": "Minimum rəqəm" + }, + "minSpecial": { + "message": "Minimum simvol" + }, + "avoidAmbChar": { + "message": "Anlaşılmaz simvollardan çəkinin" + }, + "searchVault": { + "message": "Anbarda axtar" + }, + "edit": { + "message": "Düzəliş et" + }, + "view": { + "message": "Bax" + }, + "noItemsInList": { + "message": "Siyahılanacaq heç bir element yoxdur." + }, + "itemInformation": { + "message": "Element məlumatları" + }, + "username": { + "message": "İstifadəçi adı" + }, + "password": { + "message": "Parol" + }, + "passphrase": { + "message": "Uzun ifadə" + }, + "favorite": { + "message": "Sevimli" + }, + "notes": { + "message": "Qeydlər" + }, + "note": { + "message": "Qeyd" + }, + "editItem": { + "message": "Elementə düzəliş et" + }, + "folder": { + "message": "Qovluq" + }, + "deleteItem": { + "message": "Elementi sil" + }, + "viewItem": { + "message": "Elementə bax" + }, + "launch": { + "message": "Başlat" + }, + "website": { + "message": "Veb sayt" + }, + "toggleVisibility": { + "message": "Görünməni aç/bağla" + }, + "manage": { + "message": "İdarə et" + }, + "other": { + "message": "Digər" + }, + "rateExtension": { + "message": "Genişləndirməni qiymətləndir" + }, + "rateExtensionDesc": { + "message": "Gözəl bir rəy ilə bizə dəstək ola bilərsiniz!" + }, + "browserNotSupportClipboard": { + "message": "Veb səyyahınız lövhəyə kopyalamağı dəstəkləmir. Əvəzində əllə kopyalayın." + }, + "verifyIdentity": { + "message": "Kimliyi təsdiqləyin" + }, + "yourVaultIsLocked": { + "message": "Anbarınız kilidlənib. Davam etmək üçün ana parolunuzu təsdiqləyin." + }, + "unlock": { + "message": "Kilidi aç" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ üzərində $EMAIL$ kimi giriş edildi.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Etibarsız ana parol" + }, + "vaultTimeout": { + "message": "Anbara müraciət bitəcək" + }, + "lockNow": { + "message": "İndi kilidlə" + }, + "immediately": { + "message": "Dərhal" + }, + "tenSeconds": { + "message": "10 saniyə" + }, + "twentySeconds": { + "message": "20 saniyə" + }, + "thirtySeconds": { + "message": "30 saniyə" + }, + "oneMinute": { + "message": "1 dəqiqə" + }, + "twoMinutes": { + "message": "2 dəqiqə" + }, + "fiveMinutes": { + "message": "5 dəqiqə" + }, + "fifteenMinutes": { + "message": "15 dəqiqə" + }, + "thirtyMinutes": { + "message": "30 dəqiqə" + }, + "oneHour": { + "message": "1 saat" + }, + "fourHours": { + "message": "4 saat" + }, + "onLocked": { + "message": "Sistem kilidlənəndə" + }, + "onRestart": { + "message": "Səyyah yenidən başladılanda" + }, + "never": { + "message": "Heç vaxt" + }, + "security": { + "message": "Təhlükəsizlik" + }, + "errorOccurred": { + "message": "Bir xəta baş verdi" + }, + "emailRequired": { + "message": "E-poçt ünvanı lazımdır." + }, + "invalidEmail": { + "message": "Etibarsız e-poçt ünvanı." + }, + "masterPassRequired": { + "message": "Ana parol lazımdır." + }, + "masterPassLength": { + "message": "Ana parol ən azı 8 simvol uzunluğunda olmalıdır." + }, + "masterPassDoesntMatch": { + "message": "Ana parol təsdiqləməsi uyğun gəlmir." + }, + "newAccountCreated": { + "message": "Yeni hesabınız yaradıldı! İndi giriş edə bilərsiniz." + }, + "masterPassSent": { + "message": "Ana parol məsləhətini ehtiva edən bir e-poçt göndərdik." + }, + "verificationCodeRequired": { + "message": "Təsdiq kodu lazımdır." + }, + "invalidVerificationCode": { + "message": "Etibarsız təsdiqləmə kodu" + }, + "valueCopied": { + "message": "$VALUE$ kopyalandı", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Bu səhifədə seçilən element avto-doldurulmur. Əvəzində məlumatları kopyalayıb yapışdırın." + }, + "loggedOut": { + "message": "Çıxış edildi" + }, + "loginExpired": { + "message": "Seansın müddəti bitdi." + }, + "logOutConfirmation": { + "message": "Çıxış etmək istədiyinizə əminsiniz?" + }, + "yes": { + "message": "Bəli" + }, + "no": { + "message": "Xeyr" + }, + "unexpectedError": { + "message": "Gözlənilməz bir səhv baş verdi" + }, + "nameRequired": { + "message": "Ad lazımdır." + }, + "addedFolder": { + "message": "Qovluq əlavə edildi" + }, + "changeMasterPass": { + "message": "Ana parolu dəyişdir" + }, + "changeMasterPasswordConfirmation": { + "message": "Ana parolunuzu bitwarden.com veb anbarında dəyişdirə bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?" + }, + "twoStepLoginConfirmation": { + "message": "İki mərhələli giriş, təhlükəsizlik açarı, kimlik təsdiqləyici tətbiq, SMS, telefon zəngi və ya e-poçt kimi digər cihazlarla girişinizi təsdiqləməyinizi tələb edərək hesabınızı daha da təhlükəsiz edir. İki mərhələli giriş, bitwarden.com veb anbarında fəallaşdırıla bilər. Veb saytı indi ziyarət etmək istəyirsiniz?" + }, + "editedFolder": { + "message": "Qovluğa düzəliş edildi" + }, + "deleteFolderConfirmation": { + "message": "Bu qovluğu silmək istədiyinizə əminsiniz?" + }, + "deletedFolder": { + "message": "Qovluq silindi" + }, + "gettingStartedTutorial": { + "message": "Başlanğıc təlimatı" + }, + "gettingStartedTutorialVideo": { + "message": "Səyyah genişləndirməsindən necə daha yaxşı faydalanmağı öyrənmək üçün başlanğıc təlimatına baxa bilərsiniz." + }, + "syncingComplete": { + "message": "Eyniləşdirmə tamamlandı" + }, + "syncingFailed": { + "message": "Uğursuz eyniləşdirmə" + }, + "passwordCopied": { + "message": "Parol kopyalandı" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Yeni URI" + }, + "addedItem": { + "message": "Element əlavə edildi" + }, + "editedItem": { + "message": "Elementə düzəliş edildi" + }, + "deleteItemConfirmation": { + "message": "Həqiqətən tullantı qutusuna göndərmək istəyirsiniz?" + }, + "deletedItem": { + "message": "Element tullantı qutusuna göndərildi" + }, + "overwritePassword": { + "message": "Parolun üzərinə yaz" + }, + "overwritePasswordConfirmation": { + "message": "Hazırkı parolun üzərinə yazmaq istədiyinizə əminsiniz?" + }, + "overwriteUsername": { + "message": "İstifadəçi adının üzərinə yaz" + }, + "overwriteUsernameConfirmation": { + "message": "Hazırkı istifadəçi adının üzərinə yazmaq istədiyinizə əminsiniz?" + }, + "searchFolder": { + "message": "Qovluq axtar" + }, + "searchCollection": { + "message": "Kolleksiya axtar" + }, + "searchType": { + "message": "Axtarış növü" + }, + "noneFolder": { + "message": "Qovluq yoxdur", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "\"Hesab əlavə et\" bildirişini sıradan çıxart" + }, + "addLoginNotificationDesc": { + "message": "\"Hesab əlavə et bildirişi\", ilk dəfə giriş edəndə yeni giriş məlumatlarını anbarda saxlamaq istəyib-istəmədiyinizi avtomatik olaraq soruşur." + }, + "dontShowCardsCurrentTab": { + "message": "Vərəq səhifəsində kartları göstərmə" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Anbarınızdakı kart elementləri, avto-doldurma müraciətini asanlaşdırmaq üçün \"Hazırkı vərəq\" səhifəsində siyahılanır." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Vərəq səhifəsində kimlikləri göstərmə" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Anbarınızdakı kimlik elementləri, avto-doldurma müraciətini asanlaşdırmaq üçün \"Hazırkı vərəq\" səhifəsində siyahılanır." + }, + "clearClipboard": { + "message": "Lövhəni təmizlə", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Kopyalanmış dəyərləri lövhədən avtomatik təmizlə.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Bitwarden sizin üçün bu parolu xatırlasın?" + }, + "notificationAddSave": { + "message": "Bəli, indi saxla" + }, + "disableChangedPasswordNotification": { + "message": "\"Parol dəyişdirildi\" bildirişini sıradan çıxart" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Parol dəyişdirildi bildirişi\", bir veb saytında parolu dəyişdirdiyinizi aşkarlayanda, anbarınızda qeyd etdiyiniz parolu yeniləməyinizi avtomatik olaraq soruşur." + }, + "notificationChangeDesc": { + "message": "Bu parolu \"Bitwarden\"də yeniləmək istəyirsiniz?" + }, + "notificationChangeSave": { + "message": "Bəli, indi yenilə" + }, + "disableContextMenuItem": { + "message": "Kontekst menyu seçimlərini sıradan çıxart" + }, + "disableContextMenuItemDesc": { + "message": "Kontekst menyu seçimləri, hazırkı vərəqinizdə veb sayt üçün parol yaratma və giriş etmə əməliyyatlarına cəld müraciəti təmin edir." + }, + "defaultUriMatchDetection": { + "message": "İlkin URI uyğunluq aşkarlaması", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Avto-doldurma kimi əməliyyatları icra edərkən giriş etmə prosesi üçün URI uyğunluq aşkarlamasının ilkin yolunu seçin." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Tətbiqin rəng temasını dəyişdirin." + }, + "dark": { + "message": "Tünd", + "description": "Dark color" + }, + "light": { + "message": "Açıq", + "description": "Light color" + }, + "solarizedDark": { + "message": "Günəşli tünd", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Anbarı ixrac et" + }, + "fileFormat": { + "message": "Fayl formatı" + }, + "warning": { + "message": "XƏBƏRDARLIQ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Anbarın ixracını təsdiqləyin" + }, + "exportWarningDesc": { + "message": "Bu ixrac faylındakı anbar verilənləriniz şifrələnməmiş formatdadır. İxrac edilən faylı saxlamamalı və etibarsız yollarla (e-poçt kimi) göndərməməlisiniz. Bu faylı işiniz bitdikdən sonra dərhal silin." + }, + "encExportKeyWarningDesc": { + "message": "Bu ixrac faylı, hesabınızın şifrələmə açarını istifadə edərək verilənlərinizi şifrələyir. Hesabınızın şifrələmə açarını döndərsəniz, bu ixrac faylının şifrəsini aça bilməyəcəyiniz üçün yenidən ixrac etməli olacaqsınız." + }, + "encExportAccountWarningDesc": { + "message": "Hesab şifrələmə açarları, hər Bitwarden istifadəçi hesabı üçün unikaldır, buna görə də şifrələnmiş bir ixracı, fərqli bir hesaba idxal edə bilməzsiniz." + }, + "exportMasterPassword": { + "message": "Anbar verilənlərinizi ixrac etmək üçün ana parolunuzu daxil edin." + }, + "shared": { + "message": "Paylaşılan" + }, + "learnOrg": { + "message": "Təşkilatlar barədə daha ətraflı" + }, + "learnOrgConfirmation": { + "message": "Bitwarden, bir təşkilat hesabı istifadə edərək anbar elementlərinizi başqaları ilə paylaşmağınıza icazə verər. Daha ətraflı məlumat üçün bitwarden.com saytını ziyarət etmək istəyirsiniz?" + }, + "moveToOrganization": { + "message": "Təşkilata daşı" + }, + "share": { + "message": "Paylaş" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ $ORGNAME$ şirkətinə daşındı", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Bu elementi daşımaq istədiyiniz təşkilatı seçin. Bir təşkilata daşımaq, elementin sahibliyini də həmin təşkilata daşıyacaq. Daşıdıqdan sonra bu elementə birbaşa sahibliyiniz olmayacaq." + }, + "learnMore": { + "message": "Daha ətraflı" + }, + "authenticatorKeyTotp": { + "message": "Kimlik təsdiqləyici açarı (TOTP)" + }, + "verificationCodeTotp": { + "message": "Təsdiqləmə kodu (TOTP)" + }, + "copyVerificationCode": { + "message": "Təsdiqləmə kodunu kopyala" + }, + "attachments": { + "message": "Qoşmalar" + }, + "deleteAttachment": { + "message": "Qoşmanı sil" + }, + "deleteAttachmentConfirmation": { + "message": "Bu qoşmanı silmək istədiyinizə əminsiniz?" + }, + "deletedAttachment": { + "message": "Qoşma silindi" + }, + "newAttachment": { + "message": "Yeni qoşma əlavə et" + }, + "noAttachments": { + "message": "Qoşma yoxdur." + }, + "attachmentSaved": { + "message": "Qoşma saxlanıldı." + }, + "file": { + "message": "Fayl" + }, + "selectFile": { + "message": "Fayl seçin." + }, + "maxFileSize": { + "message": "Maksimal fayl həcmi 500 MB-dır" + }, + "featureUnavailable": { + "message": "Özəllik əlçatmazdır" + }, + "updateKey": { + "message": "Şifrələmə açarınızı yeniləyənə qədər bu özəlliyi istifadə edə bilməzsiniz." + }, + "premiumMembership": { + "message": "Premium üzvlük" + }, + "premiumManage": { + "message": "Üzvlüyü idarə edin" + }, + "premiumManageAlert": { + "message": "Üzvlüyünüzü bitwarden.com veb anbarında idarə edə bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?" + }, + "premiumRefresh": { + "message": "Üzvlüyü təzələ" + }, + "premiumNotCurrentMember": { + "message": "Hazırda premium bir üzvlüyünüz yoxdur" + }, + "premiumSignUpAndGet": { + "message": "Premium üzvlük üçün qeydiyyatdan keçin və bunları əldə edin:" + }, + "ppremiumSignUpStorage": { + "message": "Fayl qoşmaları üçün 1 GB şifrələnmiş saxlama sahəsi" + }, + "ppremiumSignUpTwoStep": { + "message": "YubiKey, FIDO U2F və Duo kimi iki mərhələli giriş seçimləri" + }, + "ppremiumSignUpReports": { + "message": "Anbarınızın təhlükəsiyini təmin etmək üçün parol gigiyenası, hesab sağlamlığı və verilənlərin pozulması hesabatları." + }, + "ppremiumSignUpTotp": { + "message": "Anbarınızdakı hesablar üçün TOTP təsdiqləmə kodu (2FA) yaradıcısı." + }, + "ppremiumSignUpSupport": { + "message": "Prioritet müştəri dəstəyi." + }, + "ppremiumSignUpFuture": { + "message": "Bütün gələcək premium özəlliklər. Daha çoxu tezliklə!" + }, + "premiumPurchase": { + "message": "Premium satın al" + }, + "premiumPurchaseAlert": { + "message": "Premium üzvlüyü bitwarden.com veb anbarında satın ala bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?" + }, + "premiumCurrentMember": { + "message": "Premium üzvsünüz!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden-i dəstəklədiyiniz üçün təşəkkürlər!" + }, + "premiumPrice": { + "message": "Hamısı sadəcə ildə $PRICE$!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Təzələmə tamamlandı" + }, + "disableAutoTotpCopy": { + "message": "Avtomatik TOTP kopyalamasını sıradan çıxart" + }, + "disableAutoTotpCopyDesc": { + "message": "Hesabınıza əlavə edilən kimlik təsdiqləyici açarı varsa, giriş məlumatları avto-doldurulanda TOTP təsdiqləmə kodu da avtomatik olaraq lövhəyə kopyalanacaq." + }, + "disableAutoBiometricsPrompt": { + "message": "Açılışda biometrik üçün soruşma" + }, + "premiumRequired": { + "message": "Premium üzvlük lazımdır" + }, + "premiumRequiredDesc": { + "message": "Bu özəlliyi istifadə etmək üçün premium üzvlük lazımdır." + }, + "enterVerificationCodeApp": { + "message": "Kimlik təsdiqləyici tətbiqindən 6 rəqəmli təsdiqləmə kodunu daxil edin." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ ünvanına göndərilən e-poçtdakı 6 rəqəmli təsdiqləmə kodunu daxil edin.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Təsdiqləmə poçtu $EMAIL$ ünvanına göndərildi.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Məni xatırla" + }, + "sendVerificationCodeEmailAgain": { + "message": "Təsdiqləmə kodu olan e-poçtu yenidən göndər" + }, + "useAnotherTwoStepMethod": { + "message": "Başqa bir iki mərhələli giriş metodu istifadə edin" + }, + "insertYubiKey": { + "message": "\"YubiKey\"i kompüterinizin USB portuna taxın, daha sonra düyməsinə toxunun." + }, + "insertU2f": { + "message": "Təhlükəsizlik açarını kompüterinizin USB portun taxın. Düyməsi varsa toxunun." + }, + "webAuthnNewTab": { + "message": "WebAuthn 2FA təsdiqləməsini başladın. Yeni bir vərəq açmaq üçün aşağıdakı düyməyə klikləyin və yeni vərəqdəki təlimatları izləyin." + }, + "webAuthnNewTabOpen": { + "message": "Yeni vərəq aç" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn təsdiqləmə" + }, + "loginUnavailable": { + "message": "Giriş edilə bilmir" + }, + "noTwoStepProviders": { + "message": "Bu hesabın iki mərhələli giriş özəlliyi fəaldır, ancaq, konfiqurasiya edilmiş iki mərhələli təchizatçıların heç biri bu səyyah tərəfindən dəstəklənmir." + }, + "noTwoStepProviders2": { + "message": "Zəhmət olmasa (Chrome kimi) dəstəklənən bir veb səyyah istifadə edin və/və ya veb səyyahlara (kimlik təsdiqləyici tətbiq kimi) daha yaxşı dəstəklənən təchizatçılar əlavə edin." + }, + "twoStepOptions": { + "message": "İki mərhələli giriş seçimləri" + }, + "recoveryCodeDesc": { + "message": "İki mərhələli təsdiqləmə təchizatçılarına müraciəti itirmisiniz? Bərpa kodunuzu istifadə edərək hesabınızdakı bütün iki mərhələli təchizatçıları sıradan çıxara bilərsiniz." + }, + "recoveryCodeTitle": { + "message": "Bərpa kodu" + }, + "authenticatorAppTitle": { + "message": "Kimlik təsdiqləyici tətbiqi" + }, + "authenticatorAppDesc": { + "message": "Vaxt əsaslı təsdiqləmə kodları yaratmaq üçün (Authy və ya Google Authenticator kimi) kimlik təsdiqləyici tətbiq istifadə edin.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP təhlükəsizlik açarı" + }, + "yubiKeyDesc": { + "message": "Hesabınıza müraciət etmək üçün bir YubiKey istifadə edin. YubiKey 4, 4 Nano, 4C və NEO cihazları ilə işləyir." + }, + "duoDesc": { + "message": "Duo Security ilə təsdiqləmək üçün Duo Mobile tətbiqi, SMS, telefon zəngi və ya U2F təhlükəsizlik açarını istifadə edin.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Təşkilatınızını Duo Security ilə təsdiqləmək üçün Duo Mobile tətbiqi, SMS, telefon zəngi və ya U2F təhlükəsizlik açarını istifadə edin.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Hesabınıza müraciət etmək üçün hər hansısa bir WebAuthn fəallaşdırılan təhlükəsizlik açarı istifadə edin." + }, + "emailTitle": { + "message": "E-poçt" + }, + "emailDesc": { + "message": "Təsdiqləmə kodları e-poçt ünvanınıza göndəriləcək." + }, + "selfHostedEnvironment": { + "message": "Öz-özünə sahiblik edən mühit" + }, + "selfHostedEnvironmentFooter": { + "message": "Öz-özünə sahiblik edən Bitwarden quraşdırmasının baza URL-sini müəyyənləşdirin." + }, + "customEnvironment": { + "message": "Özəl mühit" + }, + "customEnvironmentFooter": { + "message": "Qabaqcıl istifadəçilər üçündür. Hər xidmətin baza URL-sini müstəqil olaraq müəyyənləşdirə bilərsiniz." + }, + "baseUrl": { + "message": "Server URL-si" + }, + "apiUrl": { + "message": "API server URL-si" + }, + "webVaultUrl": { + "message": "Veb anbar server URL-si" + }, + "identityUrl": { + "message": "Kimlik server URL-si" + }, + "notificationsUrl": { + "message": "Bildiriş server URL-si" + }, + "iconsUrl": { + "message": "Nişan server URL-si" + }, + "environmentSaved": { + "message": "Mühit URL-ləri saxlanıldı." + }, + "enableAutoFillOnPageLoad": { + "message": "Səhifə yüklənəndə avto-doldurmanı fəallaşdır" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Giriş formu aşkarlananda, səhifə yüklənən zaman formu avto-doldurma icra edilsin." + }, + "experimentalFeature": { + "message": "Bu, hazırda təcrübi bir özəllikdir. İstifadə zamanı riski sizə aiddir." + }, + "defaultAutoFillOnPageLoad": { + "message": "Giriş məlumatları üçün ilkin avto-doldurma tənzimləməsi" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "\"Səhifə yüklənəndə avto-doldur\"u fəal etdikdən sonra, fərdi giriş elementləri üçün özəlliyi fəallaşdıra və ya sıradan çıxarda bilərsiniz. Bu ayrı-ayrı konfiqurasiya edilməmiş giriş elementləri üçün ilkin tənzimləmədir." + }, + "itemAutoFillOnPageLoad": { + "message": "Səhifə yüklənəndə avto-doldur (Seçimlərdə fəallaşdırılıbsa)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "İlkin tənzimləməni istifadə et" + }, + "autoFillOnPageLoadYes": { + "message": "Səhifə yüklənəndə avto-doldur" + }, + "autoFillOnPageLoadNo": { + "message": "Səhifə yüklənəndə avto-doldurma" + }, + "commandOpenPopup": { + "message": "Anbar açılan pəncərədə aç" + }, + "commandOpenSidebar": { + "message": "Anbar yan sətirdə aç" + }, + "commandAutofillDesc": { + "message": "Hazırkı veb sayt üçün son istifadə edilən giriş məlumatlarını avto-doldur" + }, + "commandGeneratePasswordDesc": { + "message": "Təsadüfi yeni bir parol yarat və lövhəyə kopyala" + }, + "commandLockVaultDesc": { + "message": "Anbarı kilidlə" + }, + "privateModeWarning": { + "message": "Gizli rejim dəstəyi təcrübidir və bəzi özəlliklər limitlidir." + }, + "customFields": { + "message": "Özəl sahələr" + }, + "copyValue": { + "message": "Dəyəri kopyala" + }, + "value": { + "message": "Dəyər" + }, + "newCustomField": { + "message": "Yeni özəl sahə" + }, + "dragToSort": { + "message": "Sıralamaq üçün sürüşdürün" + }, + "cfTypeText": { + "message": "Mətn" + }, + "cfTypeHidden": { + "message": "Gizli" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Əlaqə yaradıldı", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Əlaqəli dəyər", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Təsdiqləmə kodunu alacağınız e-poçtu yoxlamaq üçün bu pəncərə xaricində bir yerə klikləsəniz bu pəncərə bağlanacaq. Bu pəncərənin bağlanmaması üçün yeni bir pəncərədə açmaq istəyirsiniz?" + }, + "popupU2fCloseMessage": { + "message": "Bu səyyah bu açılan pəncərədə U2F tələblərini emal edə bilmir. U2F istifadə edərək giriş etmək üçün bu açılan pəncərəni yeni bir pəncərədə açmaq istəyirsiniz?" + }, + "disableFavicon": { + "message": "Veb sayt nişanlarını sıradan çıxart" + }, + "disableFaviconDesc": { + "message": "Veb sayt nişanları, anbarınızda hər bir giriş elementinin yanında tanımağınıza kömək edən bir təsvir təqdim edir." + }, + "disableBadgeCounter": { + "message": "Nişan sayğacını sıradan çıxart" + }, + "disableBadgeCounterDesc": { + "message": "Nişan sayğacı, anbarınızdakı hazırkı səhifə üçün neçə dəfə giriş etdiyinizi göstərir." + }, + "cardholderName": { + "message": "Kart sahibinin adı" + }, + "number": { + "message": "Nömrə" + }, + "brand": { + "message": "Brend" + }, + "expirationMonth": { + "message": "Son istifadə ayı" + }, + "expirationYear": { + "message": "Son istifadə ili" + }, + "expiration": { + "message": "Bitmə vaxtı" + }, + "january": { + "message": "Yanvar" + }, + "february": { + "message": "Fevral" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "Aprel" + }, + "may": { + "message": "May" + }, + "june": { + "message": "İyun" + }, + "july": { + "message": "İyul" + }, + "august": { + "message": "Avqust" + }, + "september": { + "message": "Sentyabr" + }, + "october": { + "message": "Oktyabr" + }, + "november": { + "message": "Noyabr" + }, + "december": { + "message": "Dekabr" + }, + "securityCode": { + "message": "Təhlükəsizlik kodu" + }, + "ex": { + "message": "məs." + }, + "title": { + "message": "Başlıq" + }, + "mr": { + "message": "Cənab" + }, + "mrs": { + "message": "Xanım" + }, + "ms": { + "message": "Hörmətli" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Ad" + }, + "middleName": { + "message": "Orta ad" + }, + "lastName": { + "message": "Soyad" + }, + "fullName": { + "message": "Tam ad" + }, + "identityName": { + "message": "Kimlik adı" + }, + "company": { + "message": "Şirkət" + }, + "ssn": { + "message": "Sosial təhlükəsizlik nömrəsi" + }, + "passportNumber": { + "message": "Pasport nömrəsi" + }, + "licenseNumber": { + "message": "Lisenziya nömrəsi" + }, + "email": { + "message": "E-poçt" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Ünvan" + }, + "address1": { + "message": "Ünvan 1" + }, + "address2": { + "message": "Ünvan 2" + }, + "address3": { + "message": "Ünvan 3" + }, + "cityTown": { + "message": "Şəhər/Rayon" + }, + "stateProvince": { + "message": "Ölkə/Əyalət" + }, + "zipPostalCode": { + "message": "Zip/ Poçt kodu" + }, + "country": { + "message": "Ölkə" + }, + "type": { + "message": "Növ" + }, + "typeLogin": { + "message": "Giriş" + }, + "typeLogins": { + "message": "Girişlər" + }, + "typeSecureNote": { + "message": "Təhlükəsizlik qeydi" + }, + "typeCard": { + "message": "Kart" + }, + "typeIdentity": { + "message": "Kimlik" + }, + "passwordHistory": { + "message": "Parol tarixçəsi" + }, + "back": { + "message": "Geri" + }, + "collections": { + "message": "Kolleksiyalar" + }, + "favorites": { + "message": "Sevimlilər" + }, + "popOutNewWindow": { + "message": "Yeni bir pəncərədə aç" + }, + "refresh": { + "message": "Təzələ" + }, + "cards": { + "message": "Kartlar" + }, + "identities": { + "message": "Kimliklər" + }, + "logins": { + "message": "Girişlər" + }, + "secureNotes": { + "message": "Təhlükəsizlik qeydləri" + }, + "clear": { + "message": "Təmizlə", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Parolunuzun oğurlanıb oğurlanmadığını yoxlayın." + }, + "passwordExposed": { + "message": "Bu parol, məlumat pozuntularında $VALUE$ dəfə üzə çıxıb. Dəyişdirməyi məsləhət görürük.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Bu parol, məlumat pozuntularında qeydə alınmayıb. Rahatlıqla istifadə edə bilərsiniz." + }, + "baseDomain": { + "message": "Baza domeni", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domen adı", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tam" + }, + "startsWith": { + "message": "Başlayır" + }, + "regEx": { + "message": "Müntəzəm ifadə", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Uyğunluq aşkarlaması", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "İlkin uyğunluq aşkarlaması", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Seçimləri aç/bağla" + }, + "toggleCurrentUris": { + "message": "Hazırkı URI-ləri aç/bağla", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Hazırkı URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Təşkilat", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Növlər" + }, + "allItems": { + "message": "Bütün elementlər" + }, + "noPasswordsInList": { + "message": "Siyahılanacaq heç bir parol yoxdur." + }, + "remove": { + "message": "Çıxart" + }, + "default": { + "message": "İlkin" + }, + "dateUpdated": { + "message": "Yeniləndi", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parol yeniləndi", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "\"Heç vaxt\" seçimini istifadə etmək istədiyinizə əminsiniz? Kilid seçimini \"Heç vaxt\" olaraq tənzimləsəniz, anbarınızın şifrələmə açarı cihazınızda saxlanılacaq. Bu seçimi istifadə etsəniz, cihazınızı daha yaxşı mühafizə etməlisiniz." + }, + "noOrganizationsList": { + "message": "Heç bir təşkilata aid deyilsiniz. Təşkilatlar, elementlərinizi digər istifadəçilərlə təhlükəsiz şəkildə paylaşmağınızı təmin edir." + }, + "noCollectionsInList": { + "message": "Siyahılanacaq heç bir kolleksiya yoxdur." + }, + "ownership": { + "message": "Sahiblik" + }, + "whoOwnsThisItem": { + "message": "Bu elementin sahibi kimdir?" + }, + "strong": { + "message": "Güclü", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Yaxşı", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Zəif", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Zəif ana parol" + }, + "weakMasterPasswordDesc": { + "message": "Seçdiyiniz ana parol zəifdir. Bitwarden hesabınızı daha yaxşı qorumaq üçün güclü bir ana parol (və ya uzun ifadə) istifadə etməlisiniz. Bu ana parol istifadə etmək istədiyinizə əminsiniz?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "PIN ilə kilidi açın" + }, + "setYourPinCode": { + "message": "Bitwarden-in kilidini açmaq üçün PIN kod tənzimləyin. Hər tətbiqdən tam çıxış edəndə PIN tənzimləmələriniz sıfırlanacaq." + }, + "pinRequired": { + "message": "PIN kod lazımdır." + }, + "invalidPin": { + "message": "Etibarsız PIN kod." + }, + "unlockWithBiometrics": { + "message": "Biometriklərlə kilidi açın" + }, + "awaitDesktop": { + "message": "Masaüstündən təsdiq gözlənilir" + }, + "awaitDesktopDesc": { + "message": "Səyyah üçün biometrikləri fəallaşdırmaq üçün zəhmət olmasa Bitwarden masaüstü tətbiqində biometrik istifadəsini təsdiqləyin." + }, + "lockWithMasterPassOnRestart": { + "message": "Səyyah yenidən başladılanda ana parol ilə kilidlə" + }, + "selectOneCollection": { + "message": "Ən azı bir kolleksiya seçməlisiniz." + }, + "cloneItem": { + "message": "Elementi klonla" + }, + "clone": { + "message": "Klonla" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasətləri yaradıcı seçimlərinizə təsir edir." + }, + "vaultTimeoutAction": { + "message": "Anbara müraciət vaxtının bitmə əməliyyatı" + }, + "lock": { + "message": "Kilidlə", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Tullantı qutusu", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Tullantı qutusunda axtar" + }, + "permanentlyDeleteItem": { + "message": "Elementi birdəfəlik sil" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Bu elementi birdəfəlik silmək istədiyinizə əminsiniz?" + }, + "permanentlyDeletedItem": { + "message": "Element birdəfəlik silindi" + }, + "restoreItem": { + "message": "Elementi bərpa et" + }, + "restoreItemConfirmation": { + "message": "Elementi bərpa etmək istədiyinizə əminsiniz?" + }, + "restoredItem": { + "message": "Element bərpa edildi" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Çıxış edəndə, anbarınıza bütün müraciətiniz dayanacaq və vaxt bitməsindən sonra onlayn kimlik təsdiqləməsi tələb olunacaq. Bu tənzimləməni istifadə etmək istədiyinizə əminsiniz?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Vaxt bitmə əməliyyat təsdiqi" + }, + "autoFillAndSave": { + "message": "Avto-doldur və saxla" + }, + "autoFillSuccessAndSavedUri": { + "message": "Element avto-dolduruldu və URI saxlanıldı" + }, + "autoFillSuccess": { + "message": "Element avto-dolduruldu" + }, + "setMasterPassword": { + "message": "Ana parolu tənzimlə" + }, + "masterPasswordPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasəti, aşağıdakı tələbləri qarşılamaq üçün ana parolunuzu tələb edir:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum mürəkkəblik xalı: $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum uzunluq: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Bir və ya daha çox böyük hərf ehtiva etməlidir" + }, + "policyInEffectLowercase": { + "message": "Bir və ya daha çox kiçik hərf ehtiva etməlidir" + }, + "policyInEffectNumbers": { + "message": "Bir və ya daha çox rəqəm ehtiva etməlidir" + }, + "policyInEffectSpecial": { + "message": "Bu özəl simvollardan biri və ya daha çoxunu ehtiva etməlidir: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Yeni ana parolunuz siyasət tələblərini qarşılamır." + }, + "acceptPolicies": { + "message": "Bu qutunu işarələyərək aşağıdakılarla razılaşırsınız:" + }, + "acceptPoliciesError": { + "message": "Xidmət Şərtləri və Gizlilik Siyasəti qəbul edilməyib." + }, + "termsOfService": { + "message": "Xidmət Şərtləri" + }, + "privacyPolicy": { + "message": "Gizlilik Siyasəti" + }, + "hintEqualsPassword": { + "message": "Parol məsləhəti, parolunuzla eyni ola bilməz." + }, + "ok": { + "message": "Oldu" + }, + "desktopSyncVerificationTitle": { + "message": "Masaüstü eyniləşdirmə təsdiqləməsi" + }, + "desktopIntegrationVerificationText": { + "message": "Zəhmət olmasa masaüstü tətbiqin bu barmaq izini gördüyünü təsdiqləyin:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Səyyah inteqrasiyası fəal deyil" + }, + "desktopIntegrationDisabledDesc": { + "message": "Səyyah inteqrasiyası Bitwarden masaüstü tətbiqində fəal deyil. Zəhmət olmasa masaüstü tətbiqinin tənzimləmələrində fəallaşdırın." + }, + "startDesktopTitle": { + "message": "Bitwarden masaüstü tətbiqini başlat" + }, + "startDesktopDesc": { + "message": "Bu funksiyanın istifadə edilə bilməsi üçün Bitwarden masaüstü tətbiqi başladılmalıdır." + }, + "errorEnableBiometricTitle": { + "message": "Biometriklər fəallaşdırıla bilmədi" + }, + "errorEnableBiometricDesc": { + "message": "Əməliyyat, masaüstü tətbiqi tərəfindən ləğv edildi" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Masaüstü tətbiqi, təhlükəsiz rabitə kanalını qüvvədən saldı. Bu əməliyyatı yenidən icra edin" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Masaüstü rabitə əlaqəsi kəsildi" + }, + "nativeMessagingWrongUserDesc": { + "message": "Masaüstü tətbiqdə fərqli bir hesabla giriş edilib. Hər iki tətbiqin eyni hesabla giriş etdiyinə əmin olun." + }, + "nativeMessagingWrongUserTitle": { + "message": "Hesablar uyğunlaşmır" + }, + "biometricsNotEnabledTitle": { + "message": "Biometriklə fəal deyil" + }, + "biometricsNotEnabledDesc": { + "message": "Səyyah biometrikləri, əvvəlcə tənzimləmələrdə masaüstü biometriklərinin fəallaşdırılmasını tələb edir." + }, + "biometricsNotSupportedTitle": { + "message": "Biometriklər dəstəklənmir" + }, + "biometricsNotSupportedDesc": { + "message": "Səyyah biometrikləri bu cihazda dəstəklənmir" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "İcazə verilmədi" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bitwarden masaüstü tətbiqi ilə əlaqə qurma icazəsi olmadan, səyyah genişləndirməsində biometrikləri təmin edə bilmərik. Zəhmət olmasa yenidən sınayın." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "İcazə tələb xətası" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Bu əməliyyatı yan sətirdən edə bilməzsiniz. Zəhmət olmasa açılan pəncərədə yenidən cəhd edin." + }, + "personalOwnershipSubmitError": { + "message": "Müəssisə Siyasətinə görə, elementləri şəxsi anbarınızda saxlamağınız məhdudlaşdırılıb. Sahiblik seçimini təşkilat olaraq dəyişdirin və mövcud kolleksiyalar arasından seçim edin." + }, + "personalOwnershipPolicyInEffect": { + "message": "Bir təşkilat siyasəti, sahiblik seçimlərinizə təsir edir." + }, + "excludedDomains": { + "message": "İstisna edilən domenlər" + }, + "excludedDomainsDesc": { + "message": "Bitwarden bu domenlər üçün giriş təfsilatlarını saxlamağı soruşmayacaq. Dəyişikliklərin təsirli olması üçün səhifəni təzələməlisiniz." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ etibarlı bir domen deyil", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "\"Send\"ləri axtar", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "\"Send\" əlavə et", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Mətn" + }, + "sendTypeFile": { + "message": "Fayl" + }, + "allSends": { + "message": "Bütün \"Send\"lər", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maksimal müraciət sayına çatıldı", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Müddəti bitib" + }, + "pendingDeletion": { + "message": "Silinməsi gözlənilir" + }, + "passwordProtected": { + "message": "Parolla qorunan" + }, + "copySendLink": { + "message": "\"Send\" bağlantısını kopyala", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Parolu çıxart" + }, + "delete": { + "message": "Sil" + }, + "removedPassword": { + "message": "Parol çıxarıldı" + }, + "deletedSend": { + "message": "Send silindi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "\"Send\" bağlantısı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Sıradan çıxarıldı" + }, + "removePasswordConfirmation": { + "message": "Parolu çıxartmaq istədiyinizə əminsiniz?" + }, + "deleteSend": { + "message": "\"Send\"i sil", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Bu \"Send\"i silmək istədiyinizə əminsiniz?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "\"Send\"ə düzəliş et", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "\"Send\"in növü nədir?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Bu \"Send\"i açıqlayan bir ad.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Göndərmək istədiyiniz fayl." + }, + "deletionDate": { + "message": "Silinmə tarixi" + }, + "deletionDateDesc": { + "message": "\"Send\" göstərilən tarix və saatda birdəfəlik silinəcək.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Bitmə tarixi" + }, + "expirationDateDesc": { + "message": "Əgər tənzimlənsə, göstərilən tarix və vaxtda \"Send\"ə müraciət başa çatacaq.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 gün" + }, + "days": { + "message": "$DAYS$ gün", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Özəl" + }, + "maximumAccessCount": { + "message": "Maksimal müraciət sayı" + }, + "maximumAccessCountDesc": { + "message": "Əgər tənzimlənsə, istifadəçilər maksimal müraciət sayına çatdıqdan sonra bu \"Send\"ə müraciət edə bilməyəcək.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "İstəyinizə görə istifadəçilərdən bu \"Send\"ə müraciət edərkən parol tələb edə bilərsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Bu \"Send\" ilə bağlı gizli qeydlər.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Heç kimin müraciət edə bilməməsi üçün bu \"Send\"i sıradan çıxart.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Saxladıqdan sonra \"Send\"in bağlantısını lövhəyə kopyala.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Göndərmək istədiyiniz mətn" + }, + "sendHideText": { + "message": "Bu \"Send\"in mətnini ilkin olaraq gizlət", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Hazırkı müraciət sayı" + }, + "createSend": { + "message": "Yeni \"Send\" yarat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Yeni parol" + }, + "sendDisabled": { + "message": "Send sıradan çıxarıldı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Müəssisə siyasətinə görə, yalnız mövcud \"Send\"i silə bilərsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send yaradıldı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "\"Send\"ə düzəliş edildi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Fayl seçmək üçün (mümkünsə) genişləndirməni yan sətirdə açın və ya bu bannerə klikləyərək yeni bir pəncərədə açın." + }, + "sendFirefoxFileWarning": { + "message": "Firefox istifadə edərək fayl seçmək üçün genişləndirməni yan sətirdə açın və ya bu bannerə klikləyərək yeni bir pəncərədə açın." + }, + "sendSafariFileWarning": { + "message": "Safari istifadə edərək fayl seçmək üçün bu bannerə klikləyərək yeni bir pəncərədə açın." + }, + "sendFileCalloutHeader": { + "message": "Başlamazdan əvvəl" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Təqvim stilində tarix seçici istifadə etmək üçün", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "bura klikləyin", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "yeni bir pəncərə açın.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Göstərilən son istifadə tarixi etibarsızdır." + }, + "deletionDateIsInvalid": { + "message": "Göstərilən silinmə tarixi etibarsızdır." + }, + "expirationDateAndTimeRequired": { + "message": "Son istifadə tarixi və vaxtı lazımdır." + }, + "deletionDateAndTimeRequired": { + "message": "Silinmə tarixi və vaxtı lazımdır." + }, + "dateParsingError": { + "message": "Silinmə və son istifadə tarixlərini saxlayarkən xəta baş verdi." + }, + "hideEmail": { + "message": "E-poçt ünvanımı alıcılardan gizlət." + }, + "sendOptionsPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasətləri \"Send\" seçimlərinizə təsir edir." + }, + "passwordPrompt": { + "message": "Ana parolu təkrar soruş" + }, + "passwordConfirmation": { + "message": "Ana parol təsdiqi" + }, + "passwordConfirmationDesc": { + "message": "Bu əməliyyat qorumalıdır, davam etmək üçün zəhmət olmasa kimliyinizi təsdiqləmək üçün ana parolunuzu təkrar daxil edin." + }, + "emailVerificationRequired": { + "message": "E-poçt təsdiqləməsi tələb olunur" + }, + "emailVerificationRequiredDesc": { + "message": "Bu özəlliyi istifadə etmək üçün e-poçtunuzu təsdiqləməlisiniz. E-poçtunuzu veb anbarında təsdiqləyə bilərsiniz." + }, + "updatedMasterPassword": { + "message": "Yenilənmiş ana parol" + }, + "updateMasterPassword": { + "message": "Ana parolu yenilə" + }, + "updateMasterPasswordWarning": { + "message": "Ana parolunuz təzəlikcə təşkilatınızdakı bir administrator tərəfindən dəyişdirildi. Anbara müraciət üçün indi yeniləməlisiniz. Davam etsəniz, hazırkı seansdan çıxış etmiş və təkrar giriş etməli olacaqsınız. Digər cihazlardakı aktiv seanslar bir saata qədər aktiv qalmağa davam edə bilər." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Avtomatik qeydiyyat" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Bu təşkilat, sizi \"parol sıfırlama\"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək." + }, + "selectFolder": { + "message": "Qovluq seçin..." + }, + "ssoCompleteRegistration": { + "message": "SSO ilə giriş prosesini tamamlamaq üçün zəhmət olmasa anbarınıza müraciət etmək və onu qorumaq üçün bir ana parol tənzimləyin." + }, + "hours": { + "message": "Saat" + }, + "minutes": { + "message": "Dəqiqə" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Təşkilatınızın siyasətləri, anbarınızın vaxt bitişinə təsir edir. Anbar vaxt bitişi üçün icazə verilən maksimum vaxt $HOURS$ saat $MINUTES$ dəqiqədir", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Anbar vaxt bitişi, təşkilatınız tərəfindən tənzimlənən məhdudiyyətləri aşır." + }, + "vaultExportDisabled": { + "message": "Anbar ixracı sıradan çıxarıldı" + }, + "personalVaultExportPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasəti, fərdi anbarınızı ixrac etməyinizin qarşısını alır." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Etibarlı form elementi müəyyənləşdirilə bilmir. Bunun əvəzinə HTML-i nəzərdən keçirməyi sınayın." + }, + "copyCustomFieldNameNotUnique": { + "message": "Unikal identifikator tapılmadı." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$, öz-özünə sahiblik edən açar serveri ilə SSO istifadə edir. Bu təşkilatın üzvlərinin giriş etməsi üçün artıq ana parol tələb edilməyəcək.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Təşkilatı tərk et" + }, + "removeMasterPassword": { + "message": "Ana parolu sil" + }, + "removedMasterPassword": { + "message": "Ana parol silindi." + }, + "leaveOrganizationConfirmation": { + "message": "Bu təşkilatı tərk etmək istədiyinizə əminsiniz?" + }, + "leftOrganization": { + "message": "Təşkilatı tərk etdiniz." + }, + "toggleCharacterCount": { + "message": "Simvol sayını dəyişdir" + }, + "sessionTimeout": { + "message": "Seansınızın vaxtı bitdi. Zəhmət olmasa geri qayıdıb yenidən giriş etməyə cəhd edin." + }, + "exportingPersonalVaultTitle": { + "message": "Şəxsi anbarın ixracı" + }, + "exportingPersonalVaultDescription": { + "message": "Yalnız $EMAIL$ ilə əlaqəli şəxsi anbar elementləri ixrac ediləcək. Təşkilat anbar elementləri daxil edilmir.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Xəta" + }, + "regenerateUsername": { + "message": "İstifadəçi adını yenidən yarat" + }, + "generateUsername": { + "message": "İstifadəçi adı yarat" + }, + "usernameType": { + "message": "İstifadəçi adı növü" + }, + "plusAddressedEmail": { + "message": "Plyus ünvanlı e-poçt", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "E-poçt təchizatçınızın alt ünvan özəlliklərini istifadə et." + }, + "catchallEmail": { + "message": "Catch-all E-poçt" + }, + "catchallEmailDesc": { + "message": "Domeninizin konfiqurasiya edilmiş hamısını yaxalama gələn qutusunu istifadə edin." + }, + "random": { + "message": "Təsadüfi" + }, + "randomWord": { + "message": "Təsadüfi söz" + }, + "websiteName": { + "message": "Veb sayt adı" + }, + "whatWouldYouLikeToGenerate": { + "message": "Nə yaratmaq istəyirsiniz?" + }, + "passwordType": { + "message": "Parol növü" + }, + "service": { + "message": "Xidmət" + } +} diff --git a/apps/browser/src/_locales/be/messages.json b/apps/browser/src/_locales/be/messages.json new file mode 100644 index 0000000000..783a137ddd --- /dev/null +++ b/apps/browser/src/_locales/be/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden – бясплатны менеджар пароляў", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Бяспечны і бясплатны менеджар пароляў для ўсіх вашых прылад.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Увайдзіце або стварыце новы ўліковы запіс для доступу да бяспечнага сховішча." + }, + "createAccount": { + "message": "Стварыць уліковы запіс" + }, + "login": { + "message": "Увайсці" + }, + "enterpriseSingleSignOn": { + "message": "Адзіны ўваход у карпаратыўную сістэму (SSO)." + }, + "cancel": { + "message": "Скасаваць" + }, + "close": { + "message": "Закрыць" + }, + "submit": { + "message": "Адправіць" + }, + "emailAddress": { + "message": "Адрас эл. пошты" + }, + "masterPass": { + "message": "Асноўны пароль" + }, + "masterPassDesc": { + "message": "Асноўны пароль — ключ да вашага бяспечнага сховішча. Ён вельмі важны, таму не забывайце яго. Аднавіць асноўны пароль немагчыма." + }, + "masterPassHintDesc": { + "message": "Падказка да асноўнага пароля можа дапамагчы вам яго ўспомніць." + }, + "reTypeMasterPass": { + "message": "Увядзіце асноўны пароль паўторна" + }, + "masterPassHint": { + "message": "Падказка да асноўнага пароля (неабавязкова)" + }, + "tab": { + "message": "Укладка" + }, + "myVault": { + "message": "Маё сховішча" + }, + "tools": { + "message": "Інструменты" + }, + "settings": { + "message": "Налады" + }, + "currentTab": { + "message": "Бягучая ўкладка" + }, + "copyPassword": { + "message": "Капіяваць пароль" + }, + "copyNote": { + "message": "Капіяваць нататку" + }, + "copyUri": { + "message": "Капіяваць URI" + }, + "copyUsername": { + "message": "Капіяваць імя карыстальніка" + }, + "copyNumber": { + "message": "Капіяваць нумар" + }, + "copySecurityCode": { + "message": "Капіяваць код бяспекі" + }, + "autoFill": { + "message": "Аўтазапаўненне" + }, + "generatePasswordCopied": { + "message": "Стварыць пароль (з капіяваннем)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "Няма падыходных уліковых даных." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "Няма ўліковых даных, даступных для аўтазапаўнення ў бягучую ўкладку браўзера." + }, + "addLogin": { + "message": "Дадаць ўліковыя даныя" + }, + "addItem": { + "message": "Дадаць элемент" + }, + "passwordHint": { + "message": "Падказка да пароля" + }, + "enterEmailToGetHint": { + "message": "Увядзіце адрас электроннай пошты ўліковага запісу для атрымання падказкі для асноўнага пароля." + }, + "getMasterPasswordHint": { + "message": "Атрымаць падказку для асноўнага пароля" + }, + "continue": { + "message": "Працягнуць" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Код праверкі" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Уліковы запіс" + }, + "changeMasterPassword": { + "message": "Змяніць асноўны пароль" + }, + "fingerprintPhrase": { + "message": "Фраза адбітка пальца", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Фраза адбітка пальца вашага ўліковага запісу", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Двухэтапны ўваход" + }, + "logOut": { + "message": "Выйсці" + }, + "about": { + "message": "Пра Bitwarden" + }, + "version": { + "message": "Версія" + }, + "save": { + "message": "Захаваць" + }, + "move": { + "message": "Перамясціць" + }, + "addFolder": { + "message": "Дадаць папку" + }, + "name": { + "message": "Назва" + }, + "editFolder": { + "message": "Рэдагаваць папку" + }, + "deleteFolder": { + "message": "Выдаліць папку" + }, + "folders": { + "message": "Папкі" + }, + "noFolders": { + "message": "Няма элементаў для паказу." + }, + "helpFeedback": { + "message": "Даведка і зваротная сувязь" + }, + "sync": { + "message": "Сінхранізаваць" + }, + "syncVaultNow": { + "message": "Сінхранізаваць сховішча зараз" + }, + "lastSync": { + "message": "Апошняя сінхранізацыя:" + }, + "passGen": { + "message": "Генератар пароляў" + }, + "generator": { + "message": "Згенерыраваць", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Аўтаматычна ствараць моцныя, унікальныя паролі для вашых уліковых даных." + }, + "bitWebVault": { + "message": "Вэб-сховішча Bitwarden" + }, + "importItems": { + "message": "Імпарт элементаў" + }, + "select": { + "message": "Выбраць" + }, + "generatePassword": { + "message": "Стварыць пароль" + }, + "regeneratePassword": { + "message": "Стварыць новы пароль" + }, + "options": { + "message": "Параметры" + }, + "length": { + "message": "Даўжыня" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Колькасць слоў" + }, + "wordSeparator": { + "message": "Раздзяляльнік слоў" + }, + "capitalize": { + "message": "З вялікай літары", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Уключыць лічбу" + }, + "minNumbers": { + "message": "Мін. колькасць лічбаў" + }, + "minSpecial": { + "message": "Мін. колькасць сімвалаў" + }, + "avoidAmbChar": { + "message": "Пазбягаць неадназначных сімвалаў" + }, + "searchVault": { + "message": "Пошук у сховішчы" + }, + "edit": { + "message": "Рэдагаваць" + }, + "view": { + "message": "Выгляд" + }, + "noItemsInList": { + "message": "Няма элементаў для паказу." + }, + "itemInformation": { + "message": "Звесткі аб элеменце" + }, + "username": { + "message": "Імя карыстальніка" + }, + "password": { + "message": "Пароль" + }, + "passphrase": { + "message": "Парольная фраза" + }, + "favorite": { + "message": "Абраны" + }, + "notes": { + "message": "Нататкі" + }, + "note": { + "message": "Нататкі" + }, + "editItem": { + "message": "Рэдагаванне элемента" + }, + "folder": { + "message": "Папка" + }, + "deleteItem": { + "message": "Выдаліць элемент" + }, + "viewItem": { + "message": "Прагляд элемента" + }, + "launch": { + "message": "Запусціць" + }, + "website": { + "message": "Вэб-сайт" + }, + "toggleVisibility": { + "message": "Пераключыць бачнасць" + }, + "manage": { + "message": "Кіраваць" + }, + "other": { + "message": "Iншае" + }, + "rateExtension": { + "message": "Ацаніць пашырэнне" + }, + "rateExtensionDesc": { + "message": "Падумайце аб тым, каб дапамагчы нам, напісаўшы добрым водгукам!" + }, + "browserNotSupportClipboard": { + "message": "Ваш вэб-браўзер не падтрымлівае капіяванне даных у буфер абмену. Скапіюйце іх уручную." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Ваша сховішча заблакіравана. Каб працягнуць, увядзіце асноўны пароль." + }, + "unlock": { + "message": "Разблакіраваць" + }, + "loggedInAsOn": { + "message": "Выкананы ўваход на $HOSTNAME$ як $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Памылковы асноўны пароль" + }, + "vaultTimeout": { + "message": "Тайм-аўт сховішча" + }, + "lockNow": { + "message": "Заблакіраваць зараз" + }, + "immediately": { + "message": "Адразу" + }, + "tenSeconds": { + "message": "10 секунд" + }, + "twentySeconds": { + "message": "20 секунд" + }, + "thirtySeconds": { + "message": "30 секунд" + }, + "oneMinute": { + "message": "1 хвіліна" + }, + "twoMinutes": { + "message": "2 хвіліны" + }, + "fiveMinutes": { + "message": "5 хвілін" + }, + "fifteenMinutes": { + "message": "15 хвілін" + }, + "thirtyMinutes": { + "message": "30 хвілін" + }, + "oneHour": { + "message": "1 гадзіна" + }, + "fourHours": { + "message": "4 гадзіны" + }, + "onLocked": { + "message": "Разам з камп'ютарам" + }, + "onRestart": { + "message": "Пры перазапуску браўзера" + }, + "never": { + "message": "Ніколі" + }, + "security": { + "message": "Бяспека" + }, + "errorOccurred": { + "message": "Адбылася памылка" + }, + "emailRequired": { + "message": "Патрабуецца адрас электроннай пошты." + }, + "invalidEmail": { + "message": "Памылковы адрас электроннай пошты." + }, + "masterPassRequired": { + "message": "Патрабуецца асноўны пароль." + }, + "masterPassLength": { + "message": "Асноўны пароль павінен быць даўжынёй не менш за 8 сімвалаў." + }, + "masterPassDoesntMatch": { + "message": "Асноўныя паролі не супадаюць." + }, + "newAccountCreated": { + "message": "Ваш уліковы запіс створаны! Вы можаце ўвайсці." + }, + "masterPassSent": { + "message": "Мы адправілі вам на электронную пошту падказку для асноўнага пароля." + }, + "verificationCodeRequired": { + "message": "Патрабуецца код праверкі." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ скапіяваны(-а)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Не ўдаецца аўтаматычна запоўніць выбраны элемент на гэтай старонцы. Скапіюйце і ўстаўце інфармацыю ўручную." + }, + "loggedOut": { + "message": "Вы выйшлі са сховішча" + }, + "loginExpired": { + "message": "Скончыўся тэрмін дзеяння вашага сеансу." + }, + "logOutConfirmation": { + "message": "Вы ўпэўнены, што хочаце выйсці?" + }, + "yes": { + "message": "Так" + }, + "no": { + "message": "Не" + }, + "unexpectedError": { + "message": "Адбылася нечаканая памылка." + }, + "nameRequired": { + "message": "Патрэбна назва." + }, + "addedFolder": { + "message": "Папка дададзена" + }, + "changeMasterPass": { + "message": "Змяніць асноўны пароль" + }, + "changeMasterPasswordConfirmation": { + "message": "Вы можаце змяніць свой асноўны пароль на bitwarden.com. Перайсці на сайт зараз?" + }, + "twoStepLoginConfirmation": { + "message": "Двухэтапны ўваход робіць ваш уліковы запіс больш бяспечным, патрабуючы пацвярджэння ўваходу на іншай прыладзе, напрыклад, ключом бяспекі, праграмай для праверкі бяспекі, SMS, тэлефонным выклікам або электроннай поштай. Двухэтапны ўваход уключаецца на bitwarden.com. Перайсці на сайт зараз?" + }, + "editedFolder": { + "message": "Папка адрэдагавана" + }, + "deleteFolderConfirmation": { + "message": "Вы ўпэўнены, што хочаце выдаліць гэту папку?" + }, + "deletedFolder": { + "message": "Папка выдалена" + }, + "gettingStartedTutorial": { + "message": "Дапаможнік па пачатку працы" + }, + "gettingStartedTutorialVideo": { + "message": "Праглядзіце невялікі навучальны матэрыял, каб даведацца. як атрымаць максімальную аддачу ад пашырэння браўзера." + }, + "syncingComplete": { + "message": "Сінхранізацыя завершана" + }, + "syncingFailed": { + "message": "Памылка сінхранізацыі" + }, + "passwordCopied": { + "message": "Пароль скапіяваны" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Новы URI" + }, + "addedItem": { + "message": "Элемент дададзены" + }, + "editedItem": { + "message": "Элемент адрэдагаваны" + }, + "deleteItemConfirmation": { + "message": "Вы ўпэўнены, што хочаце выдаліць гэты элемент?" + }, + "deletedItem": { + "message": "Выдалены элемент" + }, + "overwritePassword": { + "message": "Перазапісаць пароль" + }, + "overwritePasswordConfirmation": { + "message": "Вы ўпэўнены, што хочаце перазапісаць бягучы пароль?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Пошук у папцы" + }, + "searchCollection": { + "message": "Пошук у калекцыі" + }, + "searchType": { + "message": "Пошук па тыпу" + }, + "noneFolder": { + "message": "Без папкі", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Адключыць апавяшчэнне аб даданні ўліковых даных" + }, + "addLoginNotificationDesc": { + "message": "Апавяшчэнне аб даданні ўліковых даных аўтаматычна прапануе вам захаваць новыя ўліковыя даныя ў сховішчы." + }, + "dontShowCardsCurrentTab": { + "message": "Не паказваць карткі на панэлі ўкладак" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Карткі з вашага сховішча пералічаны на 'Бягучай укладцы' для спрашчэння доступу да аўтазапаўнення." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Не показывать Пасведчанні на панэлі картак" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Элементы асабістых даных з вашага сховішча пералічаны на 'Бягучай укладцы' для спрашчэння доступу да аўтазапаўнення." + }, + "clearClipboard": { + "message": "Ачыстка буфера абмену", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Аўтаматычна ачышчаць скапіяваныя значэнні з вашага буфера абмену.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Ці павінен Bitwarden запомніць гэты пароль?" + }, + "notificationAddSave": { + "message": "Так, захаваць зараз" + }, + "disableChangedPasswordNotification": { + "message": "Адключыць апавяшчэнне аб змяненні пароля" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Апавяшчэнне аб змяненні пароля аўтаматычна прапануе вам абнавіць пароль уваходу ў сховішча, калі выявіць, што вы змянілі яго на вэб-сайце." + }, + "notificationChangeDesc": { + "message": "Вы хочаце абнавіць гэты пароль у Bitwarden?" + }, + "notificationChangeSave": { + "message": "Так, абнавіць зараз" + }, + "disableContextMenuItem": { + "message": "Адключыць параметры кантэкстнага меню" + }, + "disableContextMenuItemDesc": { + "message": "Параметры кантэкстнага меню забяспечваюць хуткі доступ да генератара пароляў і ўліковых даных для сайта на бягучай укладцы." + }, + "defaultUriMatchDetection": { + "message": "Выяўленне супадзення URI па змаўчанні", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Выберыце спосаб па змаўчанні, які выкарыстоўваецца пры вызначэнні адпаведнасці URI для ўліковых даных пры выкананні такіх дзеянняў, як аўтаматычнае запаўненне." + }, + "theme": { + "message": "Тэма" + }, + "themeDesc": { + "message": "Змена колеравай тэмы праграмы." + }, + "dark": { + "message": "Цёмная", + "description": "Dark color" + }, + "light": { + "message": "Светлая", + "description": "Light color" + }, + "solarizedDark": { + "message": "Цёмная Solarized", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Экспарт сховішча" + }, + "fileFormat": { + "message": "Фармат файла" + }, + "warning": { + "message": "УВАГА", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Пацвердзіць экспарт сховішча" + }, + "exportWarningDesc": { + "message": "Экспартуемы файл утрымлівае даныя вашага сховішча ў незашыфраваным фармаце. Яго не варта захоўваць ці адпраўляць па небяспечным каналам (напрыклад, па электроннай пошце). Выдаліце яго адразу пасля выкарыстання." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Увядзіце ваш асноўны пароль для экспарту даных са сховішча." + }, + "shared": { + "message": "Абагуленыя" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Абагуліць" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Даведацца больш" + }, + "authenticatorKeyTotp": { + "message": "Ключ праверкі сапраўднасці (TOTP)" + }, + "verificationCodeTotp": { + "message": "Код праверкі (TOTP)" + }, + "copyVerificationCode": { + "message": "Капіяваць код праверкі" + }, + "attachments": { + "message": "Далучэнні" + }, + "deleteAttachment": { + "message": "Выдаліць далучэнне" + }, + "deleteAttachmentConfirmation": { + "message": "Вы ўпэўнены, што хочаце выдаліць гэта далучэнне?" + }, + "deletedAttachment": { + "message": "Далучэнне выдалена" + }, + "newAttachment": { + "message": "Дадаць новае далучэнне" + }, + "noAttachments": { + "message": "Няма далучэнняў." + }, + "attachmentSaved": { + "message": "Далучэнне захавана." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Выберыце файл." + }, + "maxFileSize": { + "message": "Максімальны памер файла 500 МБ." + }, + "featureUnavailable": { + "message": "Функцыя недаступна" + }, + "updateKey": { + "message": "Вы не можаце выкарыстоўваць гэту функцыю, пакуль не абнавіце свой ключ шыфравання." + }, + "premiumMembership": { + "message": "Прэміяльны статус" + }, + "premiumManage": { + "message": "Кіраванне статусам" + }, + "premiumManageAlert": { + "message": "Вы можаце кіраваць сваім статусам на bitwarden.com. Перайсці на сайт зараз?" + }, + "premiumRefresh": { + "message": "Абнавіць статус" + }, + "premiumNotCurrentMember": { + "message": "На дадзены момант у вас не прэміяльны статус." + }, + "premiumSignUpAndGet": { + "message": "Падпішыцеся на прэміяльны статус і атрымайце:" + }, + "ppremiumSignUpStorage": { + "message": "1 ГБ зашыфраванага сховішча для далучаных файлаў." + }, + "ppremiumSignUpTwoStep": { + "message": "Дадатковыя варыянты двухэтапнага ўваходу, такія як YubiKey, FIDO U2F і Duo." + }, + "ppremiumSignUpReports": { + "message": "Гігіена пароляў, здароўе ўліковага запісу і справаздачы аб уцечках даных для забеспячэння бяспекі вашага сховішча." + }, + "ppremiumSignUpTotp": { + "message": "TOTP-генератар кодаў (2ФА) для ўліковых даных вашага сховішча." + }, + "ppremiumSignUpSupport": { + "message": "Прыярытэтная падтрымка." + }, + "ppremiumSignUpFuture": { + "message": "Усе будучыя функцыі прэміяльнага статусу. Іх будзе больш!" + }, + "premiumPurchase": { + "message": "Купіць прэміяльны статус" + }, + "premiumPurchaseAlert": { + "message": "Вы можаце купіць прэміяльны статус на bitwarden.com. Перайсці на сайт зараз?" + }, + "premiumCurrentMember": { + "message": "У вас прэміяльны статус!" + }, + "premiumCurrentMemberThanks": { + "message": "Дзякуем вам за падтрымку Bitwarden." + }, + "premiumPrice": { + "message": "Усяго толькі за $PRICE$ на год!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Абнаўленне завершана" + }, + "disableAutoTotpCopy": { + "message": "Адключыць аўтаматычнае капіяванне TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Калі да вашых уліковых даных прымацаваны ключ праверкі сапраўднасці, то код пацвярджэння TOTP будзе скапіяваны пры аўтазапаўненні ўліковых даных." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Патрабуецца прэміяльны статус" + }, + "premiumRequiredDesc": { + "message": "Для выкарыстання гэтай функцыі патрабуецца прэміяльны статус." + }, + "enterVerificationCodeApp": { + "message": "Увядзіце 6 лічбаў кода праверкі з вашай праграмы праверкі сапраўднасці." + }, + "enterVerificationCodeEmail": { + "message": "Увядзіце 6 лічбаў кода праверкі, які быў адпраўлены на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Адпраўлены ліст для пацвярджэння $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запомніць мяне" + }, + "sendVerificationCodeEmailAgain": { + "message": "Адправіць код пацвярджэння зноў" + }, + "useAnotherTwoStepMethod": { + "message": "Выкарыстоўваць іншы метад двухэтапнага ўваходу" + }, + "insertYubiKey": { + "message": "Устаўце ваш YubiKey ў порт USB вашага камп'ютара, затым націсніце на кнопку." + }, + "insertU2f": { + "message": "Устаўце ваш ключ бяспекі ў порт USB вашага камп'ютара. Калі на ім ёсць кнопка, націсніце на яе." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Уваход недаступны" + }, + "noTwoStepProviders": { + "message": "У гэтага ўліковага запісу ўключаны двухэтапны ўваход, аднак ні адзін з наладжаных варыянтаў не падтрымліваецца гэтым вэб-браўзерам." + }, + "noTwoStepProviders2": { + "message": "Выкарыстоўвайце актуальны вэб-браўзер (напрыклад, Chrome) і/або дадайце дадатковыя варыянты праверкі сапраўднасці, якія падтрымліваюцца ў вэб-браўзерах (напрыклад, праграма для праверкі сапраўднасці)." + }, + "twoStepOptions": { + "message": "Параметры двухэтапнага ўваходу" + }, + "recoveryCodeDesc": { + "message": "Згубілі доступ да ўсіх варыянтаў двухэтапнага ўваходу? Скарыстайцеся кодам аднаўлення, каб адключыць двухэтапны ўваход для вашага ўліковага запісу." + }, + "recoveryCodeTitle": { + "message": "Код аднаўлення" + }, + "authenticatorAppTitle": { + "message": "Праграма праверкі сапраўднасці" + }, + "authenticatorAppDesc": { + "message": "Выкарыстоўвайце праграму для праверкі сапраўднасці (напрыклад, Authy або Google Authenticator) для стварэння кодаў праверкі на аснове часу.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Ключ бяспекі YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Выкарыстоўвайце YubiKey для доступу да вашага ўліковага запісу. Працуе з прыладамі YubiKey серый 4, 5 і NEO." + }, + "duoDesc": { + "message": "Пацвярдзіце з дапамогай Duo Security, выкарыстоўваючы праграму Duo Mobile, SMS, тэлефонны выклік або ключ бяспекі.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Пацвярдзіце з дапамогай Duo Security для вашай арганізацыі, выкарыстоўваючы праграму Duo Mobile, SMS, тэлефонны выклік або ключ бяспекі.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Электронная пошта" + }, + "emailDesc": { + "message": "Коды пацвярджэння будуць адпраўлены вам па электроннай пошце." + }, + "selfHostedEnvironment": { + "message": "Асяроддзе ўласнага хостынгу" + }, + "selfHostedEnvironmentFooter": { + "message": "Увядзіце асноўны URL-адрас на вашым серверы." + }, + "customEnvironment": { + "message": "Налады асяроддзя" + }, + "customEnvironmentFooter": { + "message": "Для вопытных карыстальнікаў. Можна ўвесці URL-адрасы асобна для кжонай службы." + }, + "baseUrl": { + "message": "URL-адрас сервера" + }, + "apiUrl": { + "message": "API URL-адраса сервера" + }, + "webVaultUrl": { + "message": "URL-адрас сервера вэб-сховішча" + }, + "identityUrl": { + "message": "URL-адрас сервера ідэнтыфікацыі" + }, + "notificationsUrl": { + "message": "URL-адрас сервера апавяшчэнняў" + }, + "iconsUrl": { + "message": "URL-адрас сервера значкоў" + }, + "environmentSaved": { + "message": "URL-адрас сервера асяроддзя захаваны." + }, + "enableAutoFillOnPageLoad": { + "message": "Уключыць аўтазапаўненне пры загрузцы старонкі" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Пры выяўленні формы ўваходу выконваецца аўтазапаўненне падчас загрузкі вэб-старонкі." + }, + "experimentalFeature": { + "message": "Гэта эксперыментальная функцыя. Выкарыстоўвайце на свой страх і рызыку." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Адкрыць сховішча ва ўсплывальным акне" + }, + "commandOpenSidebar": { + "message": "Адкрыць сховішча ў бакавой панэлі" + }, + "commandAutofillDesc": { + "message": "Аўтазапаўненне апошніх скарыстаных уліковых даных для бягучага вэб-сайта." + }, + "commandGeneratePasswordDesc": { + "message": "Стварыць і капіяваць новы выпадковы парольу буфер абмену." + }, + "commandLockVaultDesc": { + "message": "Заблакіраваць сховішча" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Карыстальніцкія палі" + }, + "copyValue": { + "message": "Капіяваць значэнне" + }, + "value": { + "message": "Значэнне" + }, + "newCustomField": { + "message": "Новае карыстальніцкае поле" + }, + "dragToSort": { + "message": "Перацягніце для сартавання" + }, + "cfTypeText": { + "message": "Тэкст" + }, + "cfTypeHidden": { + "message": "Схавана" + }, + "cfTypeBoolean": { + "message": "Лагічнае" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Націск за межамі гэтага акна для прагляду кода праверкі з электроннай пошты прывядзе да яго закрыцця. Адкрыць bitwarden у новым акне?" + }, + "popupU2fCloseMessage": { + "message": "Гэты браўзар не можа апрацоўваць запыты U2F у гэтым усплывальным акне. Вы хочаце адкрыць гэта ўсплывальнае акно ў новым акне, каб мець магчымасць увайсці ў сістэму, выкарыстоўваючы U2F?" + }, + "disableFavicon": { + "message": "Адключыць значкі вэб-сайтаў" + }, + "disableFaviconDesc": { + "message": "Значкі вэб-сайтаў паказваюцца з кожным элементам у вашым сховішчы." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Імя ўладальніка карткі" + }, + "number": { + "message": "Нумар" + }, + "brand": { + "message": "Тып карткі" + }, + "expirationMonth": { + "message": "Месяц заканчэння" + }, + "expirationYear": { + "message": "Год заканчэння" + }, + "expiration": { + "message": "Тэрмін дзеяння" + }, + "january": { + "message": "Студзень" + }, + "february": { + "message": "Люты" + }, + "march": { + "message": "Сакавік" + }, + "april": { + "message": "Красавік" + }, + "may": { + "message": "Май" + }, + "june": { + "message": "Чэрвень" + }, + "july": { + "message": "Ліпень" + }, + "august": { + "message": "Жнівень" + }, + "september": { + "message": "Верасень" + }, + "october": { + "message": "Кастрычнік" + }, + "november": { + "message": "Лістапад" + }, + "december": { + "message": "Снежань" + }, + "securityCode": { + "message": "Код бяспекі" + }, + "ex": { + "message": "напр." + }, + "title": { + "message": "Зварот" + }, + "mr": { + "message": "С-р" + }, + "mrs": { + "message": "С-ня" + }, + "ms": { + "message": "Пані" + }, + "dr": { + "message": "Док." + }, + "firstName": { + "message": "Імя" + }, + "middleName": { + "message": "Імя па бацьку" + }, + "lastName": { + "message": "Прозвішча" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Імя" + }, + "company": { + "message": "Кампанія" + }, + "ssn": { + "message": "Нумар сацыяльнага страхавання" + }, + "passportNumber": { + "message": "Нумар пашпарта" + }, + "licenseNumber": { + "message": "Нумар ліцэнзіі" + }, + "email": { + "message": "Электронная пошта" + }, + "phone": { + "message": "Тэлефон" + }, + "address": { + "message": "Адрас" + }, + "address1": { + "message": "Радок адрасу 1" + }, + "address2": { + "message": "Радок адрасу 2" + }, + "address3": { + "message": "Радок адрасу 3" + }, + "cityTown": { + "message": "Горад / Пасёлак" + }, + "stateProvince": { + "message": "Рэгіён / Вобласць" + }, + "zipPostalCode": { + "message": "Паштовы індэкс" + }, + "country": { + "message": "Краіна" + }, + "type": { + "message": "Тып" + }, + "typeLogin": { + "message": "Уліковыя даныя" + }, + "typeLogins": { + "message": "Уліковыя даныя" + }, + "typeSecureNote": { + "message": "Бяспечныя нататкі" + }, + "typeCard": { + "message": "Картка" + }, + "typeIdentity": { + "message": "Пасведчанне" + }, + "passwordHistory": { + "message": "Гісторыя пароляў" + }, + "back": { + "message": "Назад" + }, + "collections": { + "message": "Калекцыі" + }, + "favorites": { + "message": "Абраныя" + }, + "popOutNewWindow": { + "message": "Перайсці ў новае акно" + }, + "refresh": { + "message": "Абнавiць" + }, + "cards": { + "message": "Карткі" + }, + "identities": { + "message": "Пасведчанні" + }, + "logins": { + "message": "Уліковыя даныя" + }, + "secureNotes": { + "message": "Бяспечныя нататкі" + }, + "clear": { + "message": "Ачысціць", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Праверце, ці не скампраметаваны пароль." + }, + "passwordExposed": { + "message": "Гэты пароль быў скампраметаваны $VALUE$ раз(-ы/-оў). Вы павінны змяніць яго.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Гэты пароль не быў знойдзены ў вядомых базах уцечак. Можна працягваць яго выкарыстоўваць." + }, + "baseDomain": { + "message": "Асноўны дамен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Хост", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Дакладна" + }, + "startsWith": { + "message": "Пачынаецца з" + }, + "regEx": { + "message": "Рэгулярны выраз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Выяўленне супадзенняў", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Метад выяўлення па змаўчанні", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Пераключыць параметры" + }, + "toggleCurrentUris": { + "message": "Уключыць бягучыя URI укладак", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Бягучы URI укладкі", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Арганізацыя", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Тыпы" + }, + "allItems": { + "message": "Усе элементы" + }, + "noPasswordsInList": { + "message": "Няма пароляў для паказу." + }, + "remove": { + "message": "Выдаліць" + }, + "default": { + "message": "Па змаўчанні" + }, + "dateUpdated": { + "message": "Абноўлена", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Пароль абноўлены", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Вы ўпэўнены, што хочаце адключыць блакіроўку сховішча? У гэтым выпадку ключ шыфравання вашага сховішча будзе захаваны на вашай прыладзе. Адключаючы блакіроўку, вы павінны пераканацца, што ваша прылада надзейна абаронена." + }, + "noOrganizationsList": { + "message": "Вы не з'яўляецеся членам якой-небудзь арганізацыі. Арганізацыі дазваляюць бяспечна абменьвацца элементамі з іншымі карыстальнікамі." + }, + "noCollectionsInList": { + "message": "Няма калекцый для паказу." + }, + "ownership": { + "message": "Уладальнік" + }, + "whoOwnsThisItem": { + "message": "Каму належыць гэты элемент?" + }, + "strong": { + "message": "Моцны", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Добры", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабы", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слабы асноўны пароль" + }, + "weakMasterPasswordDesc": { + "message": "Асноўны пароль, выбраны вамі, з'яўляецца слабым. Для належнай абароны ўліковага запісу Bitwarden, вы павінны выкарыстоўваць моцны асноўны пароль (або парольную фразу). Вы ўпэўнены, што хочаце выкарыстоўваць гэты асноўны пароль?" + }, + "pin": { + "message": "PIN-код", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Разблакіраваць PIN-кодам" + }, + "setYourPinCode": { + "message": "Задайце PIN-код для разблакіроўкі Bitwarden. Налады PIN-кода будуць скінуты, калі вы калі-небудзь цалкам выйдзеце з праграмы." + }, + "pinRequired": { + "message": "Патрабуецца PIN-код." + }, + "invalidPin": { + "message": "Памылковы PIN-код." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Блакіраваць асноўным паролем пры перазапуску браўзера" + }, + "selectOneCollection": { + "message": "Вы павінны выбраць прынамсі адну калекцыю." + }, + "cloneItem": { + "message": "Кланіраваць элемент" + }, + "clone": { + "message": "Кланіраваць" + }, + "passwordGeneratorPolicyInEffect": { + "message": "На налады генератара ўплываюць адна або некалькі палітык арганізацый." + }, + "vaultTimeoutAction": { + "message": "Дзеянне пры тайм-аўце" + }, + "lock": { + "message": "Заблакіраваць", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Сметніца", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Пошук у сметніцы" + }, + "permanentlyDeleteItem": { + "message": "Выдаліць назаўсёды" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Вы ўпэўнены, што хочаце назаўсёды выдаліць гэты элемент?" + }, + "permanentlyDeletedItem": { + "message": "Выдаленны назаўсёды элемент" + }, + "restoreItem": { + "message": "Аднавіць элемент" + }, + "restoreItemConfirmation": { + "message": "Вы сапраўды жадаеце аднавіць гэты элемент?" + }, + "restoredItem": { + "message": "Элемент адноўлены" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Выхад з сістэмы выдаліць доступ да сховішча і спатрабуе праверку сапраўднасці анлайн па заканчэнні перыяду чакання. Вы сапраўды жадаеце ўключыць гэтую наладу?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Пацвярджэнне дзеяння для тайм-аута" + }, + "autoFillAndSave": { + "message": "Запоўніць і захаваць" + }, + "autoFillSuccessAndSavedUri": { + "message": "Аўтазапоўнены элемент і захаваны URI" + }, + "autoFillSuccess": { + "message": "Аўтазапоўнены элемент" + }, + "setMasterPassword": { + "message": "Задаць асноўны пароль" + }, + "masterPasswordPolicyInEffect": { + "message": "Згодна з адной або некалькімі палітыкамі арганізацыі неабходна, каб ваш асноўны пароль адказваў наступным патрабаванням:" + }, + "policyInEffectMinComplexity": { + "message": "Мінімальны ўзровень складанасці $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Мінімальная даўжыня $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Уключыць адну ці больш прапісных літар" + }, + "policyInEffectLowercase": { + "message": "Уключыць адну ці больш малых літар" + }, + "policyInEffectNumbers": { + "message": "Уключыць адну ці больш лічбаў" + }, + "policyInEffectSpecial": { + "message": "Уключаць хаця б адзін з наступных спецыяльных сімвалаў $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваш новы асноўны пароль не адпавядае патрабаванням палітыкі арганізацыі." + }, + "acceptPolicies": { + "message": "Ставіўшы гэты сцяжок вы пагаджаецеся з наступным:" + }, + "acceptPoliciesError": { + "message": "Умовы выкарыстання і Палітыка прыватнасці не былі пацверджаны." + }, + "termsOfService": { + "message": "Умовы выкарыстання" + }, + "privacyPolicy": { + "message": "Палітыка прыватнасці" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "ОК" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/bg/messages.json b/apps/browser/src/_locales/bg/messages.json new file mode 100644 index 0000000000..bb2d195ee6 --- /dev/null +++ b/apps/browser/src/_locales/bg/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Битуорден (Bitwarden)" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Безопасно и безплатно управление за всичките ви устройства.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Впишете се или създайте нов абонамент, за да достъпите защитен трезор." + }, + "createAccount": { + "message": "Създаване на абонамент" + }, + "login": { + "message": "Вписване" + }, + "enterpriseSingleSignOn": { + "message": "Еднократна идентификация (SSO)" + }, + "cancel": { + "message": "Отказ" + }, + "close": { + "message": "Затваряне" + }, + "submit": { + "message": "Подаване" + }, + "emailAddress": { + "message": "Е-поща" + }, + "masterPass": { + "message": "Главна парола" + }, + "masterPassDesc": { + "message": "Главната парола се използва за достъп до трезора ви. Запомнете я добре, защото възстановяването ѝ е абсолютно невъзможно." + }, + "masterPassHintDesc": { + "message": "Ако сте забравили главната парола, то подсказването може да ви помогне да си я припомните." + }, + "reTypeMasterPass": { + "message": "Въведете пак главната парола" + }, + "masterPassHint": { + "message": "Подсказване за главната парола (по избор)" + }, + "tab": { + "message": "Раздел" + }, + "myVault": { + "message": "Моят трезор" + }, + "tools": { + "message": "Средства" + }, + "settings": { + "message": "Настройки" + }, + "currentTab": { + "message": "Текущ раздел" + }, + "copyPassword": { + "message": "Копиране на паролата" + }, + "copyNote": { + "message": "Копиране на бележката" + }, + "copyUri": { + "message": "Копиране на адреса" + }, + "copyUsername": { + "message": "Копиране на потребителското име" + }, + "copyNumber": { + "message": "Копиране на номера" + }, + "copySecurityCode": { + "message": "Копиране на кода да сигурност" + }, + "autoFill": { + "message": "Автоматично дописване" + }, + "generatePasswordCopied": { + "message": "Генериране на парола (копирана)" + }, + "copyElementIdentifier": { + "message": "Копиране на името на допълнителното поле" + }, + "noMatchingLogins": { + "message": "Няма съвпадащи записи." + }, + "unlockVaultMenu": { + "message": "Отключете трезора си" + }, + "loginToVaultMenu": { + "message": "Влезте в трезора си" + }, + "autoFillInfo": { + "message": "В текущия раздел няма записи, които да бъдат попълнени." + }, + "addLogin": { + "message": "Добавяне на запис" + }, + "addItem": { + "message": "Добавяне на елемент" + }, + "passwordHint": { + "message": "Подсказка за паролата" + }, + "enterEmailToGetHint": { + "message": "Въведете адреса на имейла си, за да получите подсказка за главната си парола." + }, + "getMasterPasswordHint": { + "message": "Подсказка за главната парола" + }, + "continue": { + "message": "Продължаване" + }, + "sendVerificationCode": { + "message": "Изпращане на код за потвърждаване до Вашата ел. поща" + }, + "sendCode": { + "message": "Изпращане на кода" + }, + "codeSent": { + "message": "Кодът е изпратен" + }, + "verificationCode": { + "message": "Код за потвърждаване" + }, + "confirmIdentity": { + "message": "Потвърдете самоличността си, за да продължите." + }, + "account": { + "message": "Регистрация" + }, + "changeMasterPassword": { + "message": "Промяна на главната парола" + }, + "fingerprintPhrase": { + "message": "Уникална фраза", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Уникална фраза, идентифицираща абонамента ви", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Двустепенно удостоверяване" + }, + "logOut": { + "message": "Отписване" + }, + "about": { + "message": "Относно" + }, + "version": { + "message": "Версия" + }, + "save": { + "message": "Запазване" + }, + "move": { + "message": "Преместване" + }, + "addFolder": { + "message": "Добавяне на папка" + }, + "name": { + "message": "Име" + }, + "editFolder": { + "message": "Редактиране на папка" + }, + "deleteFolder": { + "message": "Изтриване на папка" + }, + "folders": { + "message": "Папки" + }, + "noFolders": { + "message": "Няма папки за показване." + }, + "helpFeedback": { + "message": "Помощ и обратна връзка" + }, + "sync": { + "message": "Синхронизиране" + }, + "syncVaultNow": { + "message": "Синхронизиране сега" + }, + "lastSync": { + "message": "Последно синхронизиране:" + }, + "passGen": { + "message": "Генератор на пароли" + }, + "generator": { + "message": "Генератор", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Автоматично създаване на силни и неповторими пароли." + }, + "bitWebVault": { + "message": "Уебтрезорът на Bitwarden" + }, + "importItems": { + "message": "Внасяне на елементи" + }, + "select": { + "message": "Избор" + }, + "generatePassword": { + "message": "Генериране на парола" + }, + "regeneratePassword": { + "message": "Регенериране на паролата" + }, + "options": { + "message": "Опции" + }, + "length": { + "message": "Дължина" + }, + "uppercase": { + "message": "Главни букви (A-Z)" + }, + "lowercase": { + "message": "Малки букви (a-z)" + }, + "numbers": { + "message": "Числа (0-9)" + }, + "specialCharacters": { + "message": "Специални знаци (!@#$%^&*)" + }, + "numWords": { + "message": "Брой думи" + }, + "wordSeparator": { + "message": "Разделител за думи" + }, + "capitalize": { + "message": "Главни букви", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "И цифри" + }, + "minNumbers": { + "message": "Минимален брой цифри" + }, + "minSpecial": { + "message": "Минимален брой специални знаци" + }, + "avoidAmbChar": { + "message": "Без нееднозначни знаци" + }, + "searchVault": { + "message": "Търсене в трезора" + }, + "edit": { + "message": "Редактиране" + }, + "view": { + "message": "Преглед" + }, + "noItemsInList": { + "message": "Няма елементи за показване." + }, + "itemInformation": { + "message": "Сведения за елемента" + }, + "username": { + "message": "Потребителско име" + }, + "password": { + "message": "Парола" + }, + "passphrase": { + "message": "Парола за преминаване" + }, + "favorite": { + "message": "Любими" + }, + "notes": { + "message": "Бележки" + }, + "note": { + "message": "Бележка" + }, + "editItem": { + "message": "Редактиране на елемента" + }, + "folder": { + "message": "Папка" + }, + "deleteItem": { + "message": "Изтриване на елемента" + }, + "viewItem": { + "message": "Преглед на елемента" + }, + "launch": { + "message": "Пускане" + }, + "website": { + "message": "Сайт" + }, + "toggleVisibility": { + "message": "Превключване на видимостта" + }, + "manage": { + "message": "Управление" + }, + "other": { + "message": "Други" + }, + "rateExtension": { + "message": "Оценяване на разширението" + }, + "rateExtensionDesc": { + "message": "Молим да ни помогнете, като оставите положителен отзив!" + }, + "browserNotSupportClipboard": { + "message": "Браузърът не поддържа копиране в буфера, затова копирайте на ръка." + }, + "verifyIdentity": { + "message": "Потвърждаване на самоличността" + }, + "yourVaultIsLocked": { + "message": "Трезорът е заключен — въведете главната си парола, за да продължите." + }, + "unlock": { + "message": "Отключване" + }, + "loggedInAsOn": { + "message": "Влезли сте като $EMAIL$ в $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Грешна главна парола" + }, + "vaultTimeout": { + "message": "Време за достъп" + }, + "lockNow": { + "message": "Заключване сега" + }, + "immediately": { + "message": "Незабавно" + }, + "tenSeconds": { + "message": "10 секунди" + }, + "twentySeconds": { + "message": "20 секунди" + }, + "thirtySeconds": { + "message": "30 секунди" + }, + "oneMinute": { + "message": "1 минута" + }, + "twoMinutes": { + "message": "2 минути" + }, + "fiveMinutes": { + "message": "5 минути" + }, + "fifteenMinutes": { + "message": "15 минути" + }, + "thirtyMinutes": { + "message": "30 минути" + }, + "oneHour": { + "message": "1 час" + }, + "fourHours": { + "message": "4 часа" + }, + "onLocked": { + "message": "При заключване на системата" + }, + "onRestart": { + "message": "При повторно пускане на четеца" + }, + "never": { + "message": "Никога" + }, + "security": { + "message": "Сигурност" + }, + "errorOccurred": { + "message": "Възникна грешка" + }, + "emailRequired": { + "message": "Електронната поща е задължителна." + }, + "invalidEmail": { + "message": "Недействителна електронна поща." + }, + "masterPassRequired": { + "message": "Главната парола е задължителна." + }, + "masterPassLength": { + "message": "Главната парола трябва да съдържа поне 8 знака." + }, + "masterPassDoesntMatch": { + "message": "Главната парола и потвърждението ѝ не съвпадат." + }, + "newAccountCreated": { + "message": "Абонаментът ви бе създаден. Вече можете да се впишете." + }, + "masterPassSent": { + "message": "Изпратихме ви писмо с подсказка за главната ви парола." + }, + "verificationCodeRequired": { + "message": "Кодът за потвърждение е задължителен." + }, + "invalidVerificationCode": { + "message": "Грешен код за потвърждаване" + }, + "valueCopied": { + "message": "$VALUE$ — копирано", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Неуспешно автоматично попълване. Вместо това копирайте и поставете данните." + }, + "loggedOut": { + "message": "Бяхте отписани" + }, + "loginExpired": { + "message": "Сесията ви изтече." + }, + "logOutConfirmation": { + "message": "Сигурни ли сте, че искате да се отпишете?" + }, + "yes": { + "message": "Да" + }, + "no": { + "message": "Не" + }, + "unexpectedError": { + "message": "Възникна неочаквана грешка." + }, + "nameRequired": { + "message": "Изисква се име." + }, + "addedFolder": { + "message": "Добавена папка" + }, + "changeMasterPass": { + "message": "Промяна на главната парола" + }, + "changeMasterPasswordConfirmation": { + "message": "Главната парола на трезор може да се промени чрез сайта bitwarden.com. Искате ли да го посетите?" + }, + "twoStepLoginConfirmation": { + "message": "Двустепенното вписване защитава регистрацията ви, като ви кара да потвърдите влизането си чрез устройство-ключ, приложение за удостоверение, мобилно съобщение, телефонно обаждане или електронна поща. Двустепенното вписване може да се включи чрез сайта bitwarden.com. Искате ли да го посетите?" + }, + "editedFolder": { + "message": "Редактирана папка" + }, + "deleteFolderConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете тази папка?" + }, + "deletedFolder": { + "message": "Изтрита папка" + }, + "gettingStartedTutorial": { + "message": "Въведение" + }, + "gettingStartedTutorialVideo": { + "message": "Изгледайте въведението, за да извлечете максимална полза от разширението Bitwarden." + }, + "syncingComplete": { + "message": "Синхронизацията завърши" + }, + "syncingFailed": { + "message": "Неуспешно синхронизиране" + }, + "passwordCopied": { + "message": "Копирана парола" + }, + "uri": { + "message": "Адрес" + }, + "uriPosition": { + "message": "Адрес $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Нов адрес" + }, + "addedItem": { + "message": "Елементът е добавен" + }, + "editedItem": { + "message": "Елементът е редактиран" + }, + "deleteItemConfirmation": { + "message": "Наистина ли искате да изтриете елемента?" + }, + "deletedItem": { + "message": "Елементът е изтрит" + }, + "overwritePassword": { + "message": "Презаписване на паролата" + }, + "overwritePasswordConfirmation": { + "message": "Наистина ли искате да презапишете текущата парола?" + }, + "overwriteUsername": { + "message": "Замяна на потребителското име" + }, + "overwriteUsernameConfirmation": { + "message": "Наостина ли искате да замените текущото потребителско име?" + }, + "searchFolder": { + "message": "Търсене в папката" + }, + "searchCollection": { + "message": "Търсене в колекцията" + }, + "searchType": { + "message": "Търсене по вид" + }, + "noneFolder": { + "message": "Няма папка", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Без известия за запазване на регистрации" + }, + "addLoginNotificationDesc": { + "message": "Известията за запазване на регистрации автоматично ви подканят да запазите новите регистрации в трезора при първото ви вписване в тях." + }, + "dontShowCardsCurrentTab": { + "message": "Без карти в основния прозорец" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Скриване на записите за платежните карти, които обичайно се извеждат в основния прозорец за лесно въвеждане." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Без самоличности в основния прозорец" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Скриване на записите за самоличност, които обичайно се извеждат в основния прозорец за лесно въвеждане." + }, + "clearClipboard": { + "message": "Изчистване на буфера", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Автоматично изчистване на буфера след поставяне на стойността.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Искате ли тази парола да бъде запазена?" + }, + "notificationAddSave": { + "message": "Да, нека се запише сега" + }, + "disableChangedPasswordNotification": { + "message": "Без известия за обновяване на регистрации" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Известията за обновяване на регистрации автоматично ви подканят да запазите променените регистрации в трезора при засичането на промяната." + }, + "notificationChangeDesc": { + "message": "Да се обнови ли паролата в Bitwarden?" + }, + "notificationChangeSave": { + "message": "Да, нека се обнови сега" + }, + "disableContextMenuItem": { + "message": "Без добавки към контекстното меню" + }, + "disableContextMenuItemDesc": { + "message": "Добавките към контекстното меню позволяват бърз достъп до данните за сайтовете в текущия раздел, както и създаването на нова парола." + }, + "defaultUriMatchDetection": { + "message": "Стандартно засичане на адреси", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Какъв да е начинът, по който да се засича съответствие на адреса за автоматичното попълване на данните." + }, + "theme": { + "message": "Облик" + }, + "themeDesc": { + "message": "Промяна на цветовия облик на програмата." + }, + "dark": { + "message": "Тъмен", + "description": "Dark color" + }, + "light": { + "message": "Светъл", + "description": "Light color" + }, + "solarizedDark": { + "message": "Преекспонирано тъмен", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Изнасяне на трезора" + }, + "fileFormat": { + "message": "Формат на файла" + }, + "warning": { + "message": "ВНИМАНИЕ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Потвърждаване на изнасянето на трезора" + }, + "exportWarningDesc": { + "message": "Данните от трезора ви ще се изнесат в незащитен формат. Не го пращайте по незащитени канали като е-поща. Изтрийте файла незабавно след като свършите работата си с него." + }, + "encExportKeyWarningDesc": { + "message": "При изнасяне данните се шифрират с ключа ви. Ако го смените, ще трябва наново да ги изнесете, защото няма да може да дешифрирате настоящия файл." + }, + "encExportAccountWarningDesc": { + "message": "Ключовете за шифриране са уникални за всеки потребител, затова не може да внесете шифрирани данни от един потребител в регистрацията на друг." + }, + "exportMasterPassword": { + "message": "Въведете главната парола, за да изнесете данните." + }, + "shared": { + "message": "Споделено" + }, + "learnOrg": { + "message": "Разберете повече за организациите" + }, + "learnOrgConfirmation": { + "message": "Битуорден позволява да споделяте части от трезора си чрез използването на организация. Искате ли да научите повече от сайта bitwarden.com?" + }, + "moveToOrganization": { + "message": "Преместване в организация" + }, + "share": { + "message": "Споделяне" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ се премести в $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Изберете организацията, в която искате да преместите записа. Преместването прехвърля собствеността му към новата организация. След това няма вече директно да го притежавате." + }, + "learnMore": { + "message": "Научете повече" + }, + "authenticatorKeyTotp": { + "message": "Удостоверителен ключ (TOTP)" + }, + "verificationCodeTotp": { + "message": "Код за потвърждаване (TOTP)" + }, + "copyVerificationCode": { + "message": "Копиране на кода за потвърждаване" + }, + "attachments": { + "message": "Прикачвания" + }, + "deleteAttachment": { + "message": "Изтриване на прикачения файл" + }, + "deleteAttachmentConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете прикачения файл?" + }, + "deletedAttachment": { + "message": "Прикаченият файл е изтрит" + }, + "newAttachment": { + "message": "Прикачване на файл" + }, + "noAttachments": { + "message": "Няма прикачени файлове." + }, + "attachmentSaved": { + "message": "Прикаченият файл е запазен." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Изберете файл." + }, + "maxFileSize": { + "message": "Големината на файла е най-много 500 MB." + }, + "featureUnavailable": { + "message": "Функцията е недостъпна" + }, + "updateKey": { + "message": "Трябва да обновите шифриращия си ключ, за да използвате тази възможност." + }, + "premiumMembership": { + "message": "Платен абонамент" + }, + "premiumManage": { + "message": "Управление на абонамента" + }, + "premiumManageAlert": { + "message": "Можете да управлявате абонамента си през сайта bitwarden.com. Искате ли да го посетите сега?" + }, + "premiumRefresh": { + "message": "Опресняване на абонамента" + }, + "premiumNotCurrentMember": { + "message": "В момента ползвате безплатен абонамент." + }, + "premiumSignUpAndGet": { + "message": "Платеният абонамент дава следните предимства:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB пространство за файлове, които се шифрират." + }, + "ppremiumSignUpTwoStep": { + "message": "Двустепенно удостоверяване чрез YubiKey, FIDO U2F и Duo." + }, + "ppremiumSignUpReports": { + "message": "Проверки в списъците с публикувани пароли, проверка на регистрациите и доклади за пробивите в сигурността, което спомага трезорът ви да е допълнително защитен." + }, + "ppremiumSignUpTotp": { + "message": "Генериране на временни, еднократни кодове за двустепенно удостоверяване за регистрациите в трезора." + }, + "ppremiumSignUpSupport": { + "message": "Приоритетна поддръжка." + }, + "ppremiumSignUpFuture": { + "message": "Всички бъдещи функции на платения абонамент! Предстои въвеждането на още!" + }, + "premiumPurchase": { + "message": "Покупка на платен абонамент" + }, + "premiumPurchaseAlert": { + "message": "Може да платите абонамента си през сайта bitwarden.com. Искате ли да го посетите сега?" + }, + "premiumCurrentMember": { + "message": "Честито, ползвате платен абонамент!" + }, + "premiumCurrentMemberThanks": { + "message": "Благодарим ви за подкрепата на Bitwarden." + }, + "premiumPrice": { + "message": "И това само за $PRICE$ на година!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Абонаментът е опреснен" + }, + "disableAutoTotpCopy": { + "message": "Без автоматично копиране на временни, еднократни пароли" + }, + "disableAutoTotpCopyDesc": { + "message": "Ако регистрацията използва и удостоверителен ключ, временният, еднократен код се копира в буфера при всяко автоматично попълване на формуляра." + }, + "disableAutoBiometricsPrompt": { + "message": "Да не се изискват биометрични данни при стартиране" + }, + "premiumRequired": { + "message": "Изисква се платен абонамент" + }, + "premiumRequiredDesc": { + "message": "За да се възползвате от тази възможност, трябва да ползвате платен абонамент." + }, + "enterVerificationCodeApp": { + "message": "Въведете шестцифрения код за потвърждение от приложението за удостоверяване." + }, + "enterVerificationCodeEmail": { + "message": "Въведете шестцифрения код за потвърждение, който е бил изпратен на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Писмото за потвърждение е изпратено на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запомняне" + }, + "sendVerificationCodeEmailAgain": { + "message": "Повторно изпращане на писмото за потвърждение" + }, + "useAnotherTwoStepMethod": { + "message": "Използвайте друг начин на двустепенно удостоверяване" + }, + "insertYubiKey": { + "message": "Поставете устройството на YubiKey в USB порт на компютъра и натиснете бутона на устройството." + }, + "insertU2f": { + "message": "Поставете устройството за удостоверяване в USB порт на компютъра. Ако на устройството има бутон, натиснете го." + }, + "webAuthnNewTab": { + "message": "Продължаване на двустепенното удостоверяване чрез WebAuthn в новия раздел." + }, + "webAuthnNewTabOpen": { + "message": "Отваряне на нов раздел" + }, + "webAuthnAuthenticate": { + "message": "Идентификация WebAuthn" + }, + "loginUnavailable": { + "message": "Записът липсва" + }, + "noTwoStepProviders": { + "message": "Регистрацията е защитена с двустепенно удостоверяване, но никой от настроените доставчици на удостоверяване не се поддържа от този браузър." + }, + "noTwoStepProviders2": { + "message": "Пробвайте с поддържан уеб браузър (като Chrome или Firefox) и други доставчици на удостоверяване, които се поддържат от браузърите (като специални програми за удостоверяване)." + }, + "twoStepOptions": { + "message": "Настройки на двустепенното удостоверяване" + }, + "recoveryCodeDesc": { + "message": "Ако сте загубили достъп до двустепенното удостоверяване, може да използвате код за възстановяване, за да изключите двустепенното удостоверяване в абонамента си." + }, + "recoveryCodeTitle": { + "message": "Код за възстановяване" + }, + "authenticatorAppTitle": { + "message": "Приложение за удостоверяване" + }, + "authenticatorAppDesc": { + "message": "Използвайте приложение за удостоверяване (като Authy или Google Authenticator) за генерирането на временни кодове за потвърждение.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Устройство YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Използвайте устройство на YubiKey, за да влезете в абонамента си. Поддържат се моделите YubiKey 4, 4 Nano, 4C и NEO." + }, + "duoDesc": { + "message": "Удостоверяване чрез Duo Security, с ползване на приложението Duo Mobile, SMS, телефонен разговор или устройство U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Удостоверяване чрез Duo Security за организацията ви, с ползване на приложението Duo Mobile, SMS, телефонен разговор или устройство U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Използвайте всяко устройство, поддържащо WebAuthn, за да влезете в абонамента си." + }, + "emailTitle": { + "message": "Електронна поща" + }, + "emailDesc": { + "message": "Кодовете за потвърждение ще ви бъдат пратени по е-поща." + }, + "selfHostedEnvironment": { + "message": "Собствена среда" + }, + "selfHostedEnvironmentFooter": { + "message": "Укажете базовия адрес за собствената ви инсталирана среда на Bitwarden." + }, + "customEnvironment": { + "message": "Специална среда" + }, + "customEnvironmentFooter": { + "message": "За специални случаи. Може да укажете основните адреси на всяка ползвана услуга поотделно." + }, + "baseUrl": { + "message": "Адрес на сървъра" + }, + "apiUrl": { + "message": "Адрес на ППИ-сървъра" + }, + "webVaultUrl": { + "message": "Адрес на сървъра с трезора в уеб" + }, + "identityUrl": { + "message": "Адрес на сървъра със самоличности" + }, + "notificationsUrl": { + "message": "Адрес на сървъра за уведомления" + }, + "iconsUrl": { + "message": "Адрес на сървъра с иконки" + }, + "environmentSaved": { + "message": "Средата с адресите е запазена." + }, + "enableAutoFillOnPageLoad": { + "message": "Включване на автоматичното попълване" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "При засичане на формуляр за вписване при зареждането на уеб страницата автоматично да се попълват данните на съответстващата регистрация." + }, + "experimentalFeature": { + "message": "Това все още е в експериментална фаза, ползвате го на собствена глава." + }, + "defaultAutoFillOnPageLoad": { + "message": "Стандартна настройка за автоматичното попълване" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Ако включите автоматичното попълване при зареждане на страница, след това можете да включвате или изключвате тази функционалност за всеки отделен запис. Това ще бъде стандартният начин на работа за записите, за които не е настроено допълнително." + }, + "itemAutoFillOnPageLoad": { + "message": "Автоматично попълване при зареждане на страницата (ако е включено в настройките)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Използване на стандартната настройка" + }, + "autoFillOnPageLoadYes": { + "message": "Автоматично попълване при зареждане на страницата" + }, + "autoFillOnPageLoadNo": { + "message": "Без автоматично попълване при зареждане на страницата" + }, + "commandOpenPopup": { + "message": "Отваряне на трезора в изскачащ прозорец" + }, + "commandOpenSidebar": { + "message": "Отваряне на трезора в страничната лента" + }, + "commandAutofillDesc": { + "message": "Автоматично попълване на последно използвания запис в текущия сайт." + }, + "commandGeneratePasswordDesc": { + "message": "Създаване и копиране на нова случайна парола в буфера." + }, + "commandLockVaultDesc": { + "message": "Заключване на трезора" + }, + "privateModeWarning": { + "message": "Поддръжката на частния режим е експериментална и някои функционалности са ограничени." + }, + "customFields": { + "message": "Допълнителни полета" + }, + "copyValue": { + "message": "Копиране на стойността" + }, + "value": { + "message": "Стойност" + }, + "newCustomField": { + "message": "Ново допълнително поле" + }, + "dragToSort": { + "message": "Подредба чрез влачене" + }, + "cfTypeText": { + "message": "Текст" + }, + "cfTypeHidden": { + "message": "Скрито" + }, + "cfTypeBoolean": { + "message": "Булево" + }, + "cfTypeLinked": { + "message": "Свързано", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Свързана стойност", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Ако натиснете бутон на мишката извън изскочилия прозорец за кода за потвърждение, същият този прозорец ще се затвори. Искате ли проверката да се извърши в нормален прозорец, който не се затваря толкова лесно?" + }, + "popupU2fCloseMessage": { + "message": "Този браузър не поддържа заявки чрез U2F в такъв изскачащ прозорец. Искате ли да се отвори нов прозорец, за да може да се впишете чрез U2F?" + }, + "disableFavicon": { + "message": "Без иконки на сайтовете" + }, + "disableFaviconDesc": { + "message": "Иконките на сайтовете са разпознаваемо изображение за всеки запис в трезора." + }, + "disableBadgeCounter": { + "message": "Изключване на значката с брояч" + }, + "disableBadgeCounterDesc": { + "message": "Значката с брояч показва колко варианта за вписване имате в трезора си за текущата страница." + }, + "cardholderName": { + "message": "Име на притежателя на картата" + }, + "number": { + "message": "Номер" + }, + "brand": { + "message": "Вид" + }, + "expirationMonth": { + "message": "Месец на изтичане" + }, + "expirationYear": { + "message": "Година на изтичане" + }, + "expiration": { + "message": "Изтичане" + }, + "january": { + "message": "януари" + }, + "february": { + "message": "февруари" + }, + "march": { + "message": "март" + }, + "april": { + "message": "април" + }, + "may": { + "message": "май" + }, + "june": { + "message": "юни" + }, + "july": { + "message": "юли" + }, + "august": { + "message": "август" + }, + "september": { + "message": "септември" + }, + "october": { + "message": "октомври" + }, + "november": { + "message": "ноември" + }, + "december": { + "message": "декември" + }, + "securityCode": { + "message": "Код за сигурност" + }, + "ex": { + "message": "напр." + }, + "title": { + "message": "Заглавие" + }, + "mr": { + "message": "Г-н" + }, + "mrs": { + "message": "Г-жа" + }, + "ms": { + "message": "Г-ца" + }, + "dr": { + "message": "Д-р" + }, + "firstName": { + "message": "Собствено име" + }, + "middleName": { + "message": "Презиме" + }, + "lastName": { + "message": "Фамилно име" + }, + "fullName": { + "message": "Пълно име" + }, + "identityName": { + "message": "Име на самоличността" + }, + "company": { + "message": "Фирма" + }, + "ssn": { + "message": "№ на осигуровката" + }, + "passportNumber": { + "message": "№ на паспорта" + }, + "licenseNumber": { + "message": "№ на лиценза" + }, + "email": { + "message": "Електронна поща" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адрес" + }, + "address1": { + "message": "Адрес 1" + }, + "address2": { + "message": "Адрес 2" + }, + "address3": { + "message": "Адрес 3" + }, + "cityTown": { + "message": "Населено място" + }, + "stateProvince": { + "message": "Област / щат / провинция" + }, + "zipPostalCode": { + "message": "Пощенски код" + }, + "country": { + "message": "Държава" + }, + "type": { + "message": "Вид" + }, + "typeLogin": { + "message": "Запис" + }, + "typeLogins": { + "message": "Записи" + }, + "typeSecureNote": { + "message": "Защитена бележка" + }, + "typeCard": { + "message": "Карта" + }, + "typeIdentity": { + "message": "Самоличност" + }, + "passwordHistory": { + "message": "Хронология на паролата" + }, + "back": { + "message": "Назад" + }, + "collections": { + "message": "Колекции" + }, + "favorites": { + "message": "Любими" + }, + "popOutNewWindow": { + "message": "Отваряне в нов прозорец" + }, + "refresh": { + "message": "Опресняване" + }, + "cards": { + "message": "Карти" + }, + "identities": { + "message": "Самоличности" + }, + "logins": { + "message": "Записи" + }, + "secureNotes": { + "message": "Защитени бележки" + }, + "clear": { + "message": "Изчистване", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Проверка дали паролата е разкрита." + }, + "passwordExposed": { + "message": "Паролата е била разкрита поне $VALUE$ път/и в пробиви. Непременно я сменете.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Паролата не е била разкрита в известните пробиви. Засега ползването ѝ изглежда безопасно." + }, + "baseDomain": { + "message": "Основен домейн", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Име на домейн", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Сървър", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Точно" + }, + "startsWith": { + "message": "Започва с" + }, + "regEx": { + "message": "Регулярен израз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Откриване на съвпадения", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Стандартно откриване на съвпадения", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Настройки на превключване" + }, + "toggleCurrentUris": { + "message": "Превключване на текущите адреси", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Текущ адрес", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Организация", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Видове" + }, + "allItems": { + "message": "Всички елементи" + }, + "noPasswordsInList": { + "message": "Няма пароли за показване." + }, + "remove": { + "message": "Премахване" + }, + "default": { + "message": "Стандартно" + }, + "dateUpdated": { + "message": "Обновено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Обновена парола", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Уверени ли сте, че искате да зададете стойност „Никога“? Това води до съхранение на шифриращия ключ за трезора във устройството ви. Ако използвате тази възможност, е много важно да имате надлежна защита на устройството си." + }, + "noOrganizationsList": { + "message": "Не сте член на никоя организация. Организациите позволяват да споделяте записи с други потребители по защитен начин." + }, + "noCollectionsInList": { + "message": "Няма колекции за показване." + }, + "ownership": { + "message": "Собственост" + }, + "whoOwnsThisItem": { + "message": "Кой притежава този запис?" + }, + "strong": { + "message": "Силна", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Добра", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слаба", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слаба главна парола" + }, + "weakMasterPasswordDesc": { + "message": "Зададената главна парола е твърде слаба. Главната парола трябва да е силна. Добре е да ползвате цяла фраза за парола, за да защитите данните в трезора в Bitwarden. Уверени ли сте, че искате да ползвате слаба парола?" + }, + "pin": { + "message": "ПИН", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Отключване с ПИН" + }, + "setYourPinCode": { + "message": "Задайте ПИН за отключване на Bitwarden. Настройките за ПИН се изчистват при всяко пълно излизане от програмата." + }, + "pinRequired": { + "message": "Необходим е ПИН." + }, + "invalidPin": { + "message": "Неправилен ПИН." + }, + "unlockWithBiometrics": { + "message": "Отключване с биометрични данни" + }, + "awaitDesktop": { + "message": "Чака се потвърждение от самостоятелното приложение" + }, + "awaitDesktopDesc": { + "message": "За да включите потвърждаване с биометрични данни в браузъра, потвърдете ползването им в самостоятелното приложение." + }, + "lockWithMasterPassOnRestart": { + "message": "Заключване с главната парола при повторно пускане на браузъра" + }, + "selectOneCollection": { + "message": "Изберете поне една колекция." + }, + "cloneItem": { + "message": "Дублирате на елемент" + }, + "clone": { + "message": "Клониране" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Поне една политика на организация влияе на настройките на генерирането на паролите." + }, + "vaultTimeoutAction": { + "message": "Действие при изтичане на времето" + }, + "lock": { + "message": "Заключване", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Кошче", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Търсене в кошчето" + }, + "permanentlyDeleteItem": { + "message": "Окончателно изтриване на запис" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете записа окончателно?" + }, + "permanentlyDeletedItem": { + "message": "Записът е изтрит окончателно" + }, + "restoreItem": { + "message": "Възстановяване на запис" + }, + "restoreItemConfirmation": { + "message": "Сигурни ли сте, че искате да възстановите записа?" + }, + "restoredItem": { + "message": "Записът е възстановен" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Излизането от трезора изцяло спира достъпа до него след изтичане на времето. Ще ви се наложи отново да се идентифицирате, за да го достъпите. Сигурни ли сте, че искате това действие?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Потвърждаване на действието" + }, + "autoFillAndSave": { + "message": "Дописване и обновяване" + }, + "autoFillSuccessAndSavedUri": { + "message": "Автоматично дописан запис и адрес" + }, + "autoFillSuccess": { + "message": "Автоматично дописан запис" + }, + "setMasterPassword": { + "message": "Задаване на главна парола" + }, + "masterPasswordPolicyInEffect": { + "message": "Поне една политика на организация има следните изисквания към главната ви парола:" + }, + "policyInEffectMinComplexity": { + "message": "Минимална сложност от $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Минимална дължина: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Поне една главна буква" + }, + "policyInEffectLowercase": { + "message": "Поне една малка буква" + }, + "policyInEffectNumbers": { + "message": "Поне една цифра" + }, + "policyInEffectSpecial": { + "message": "Поне един от следните специални знаци: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Паролата ви не отговаря на политиките." + }, + "acceptPolicies": { + "message": "Чрез тази отметка вие се съгласявате със следното:" + }, + "acceptPoliciesError": { + "message": "Условията за използване и политиката за поверителност не бяха приети." + }, + "termsOfService": { + "message": "Общи условия" + }, + "privacyPolicy": { + "message": "Политика за поверителност" + }, + "hintEqualsPassword": { + "message": "Подсказването за паролата не може да съвпада с нея." + }, + "ok": { + "message": "Добре" + }, + "desktopSyncVerificationTitle": { + "message": "Потвърждаване на синхронизацията на самостоятелното приложение" + }, + "desktopIntegrationVerificationText": { + "message": "Уверете се, че самостоятелното приложение показва следния идентификатор:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Интеграцията с браузър е изключена" + }, + "desktopIntegrationDisabledDesc": { + "message": "Интеграцията с браузъри не е включена в самостоятелното приложение на Битуорден. Включете я в неговите настройки." + }, + "startDesktopTitle": { + "message": "Стартиране на самостоятелното приложение на Битуорден" + }, + "startDesktopDesc": { + "message": "Трябва да стартирате самостоятелното приложение на Битуорден, преди да ползвате тази функционалност." + }, + "errorEnableBiometricTitle": { + "message": "Потвърждаването с биометрични данни не може да се включи" + }, + "errorEnableBiometricDesc": { + "message": "Действието е отменено от самостоятелното приложение" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Самостоятелното приложение прекъсна надеждния канал за връзка. Пробвайте отново" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Връзката със самостоятелното приложение е нарушена" + }, + "nativeMessagingWrongUserDesc": { + "message": "В момента самостоятелното приложение е с регистрация на различен потребител. За да работят заедно, двете приложения трябва да ползват една и съща регистрация." + }, + "nativeMessagingWrongUserTitle": { + "message": "Регистрациите са различни" + }, + "biometricsNotEnabledTitle": { + "message": "Потвърждаването с биометрични данни не е включено" + }, + "biometricsNotEnabledDesc": { + "message": "Потвърждаването с биометрични данни в браузъра изисква включването включването им в настройките за самостоятелното приложение." + }, + "biometricsNotSupportedTitle": { + "message": "Потвърждаването с биометрични данни не се поддържа" + }, + "biometricsNotSupportedDesc": { + "message": "Устройството не поддържа потвърждаване с биометрични данни." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Правото не е дадено" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Разширението за браузъра не може да осигури потвърждаване с биометрични данни, когато липсва право за връзка със самостоятелното приложение. Пробвайте отново." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Необходимо е разрешение" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Това действие не може да бъде извършено в страничната лента, опитайте отново в изскачащ прозорец." + }, + "personalOwnershipSubmitError": { + "message": "Заради някоя политика за голяма организация не може да запазвате елементи в собствения си трезор. Променете собствеността да е на организация и изберете от наличните колекции." + }, + "personalOwnershipPolicyInEffect": { + "message": "Политика от някоя организация влияе на вариантите за собственост." + }, + "excludedDomains": { + "message": "Изключени домейни" + }, + "excludedDomainsDesc": { + "message": "Битуорден няма да пита дали да запазва данните за вход в тези сайтове. За да влезе правилото в сила, презаредете страницата." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ не е валиден домейн", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Търсене в изпратените", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Добавяне на изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Текст" + }, + "sendTypeFile": { + "message": "Файл" + }, + "allSends": { + "message": "Всички изпращания", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Достигнат е максималният брой достъпвания", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Изтекъл" + }, + "pendingDeletion": { + "message": "Предстои изтриване" + }, + "passwordProtected": { + "message": "Защита с парола" + }, + "copySendLink": { + "message": "Копиране на връзката към изпратеното", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Премахване на парола" + }, + "delete": { + "message": "Изтриване" + }, + "removedPassword": { + "message": "Паролата е премахната" + }, + "deletedSend": { + "message": "Изтрито изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Изпращане на връзката", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Изключено" + }, + "removePasswordConfirmation": { + "message": "Сигурни ли сте, че искате да премахнете паролата?" + }, + "deleteSend": { + "message": "Изтриване на изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете това изпращане?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Редактиране на изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Вид на изпратеното", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Описателно име за това изпращане.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Файл за изпращане." + }, + "deletionDate": { + "message": "Дата на изтриване" + }, + "deletionDateDesc": { + "message": "Изпращането ще бъде окончателно изтрито на зададената дата и време.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Срок на валидност" + }, + "expirationDateDesc": { + "message": "При задаване — това изпращане ще се изключи на зададената дата и време.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 ден" + }, + "days": { + "message": "$DAYS$ ден/дни", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "По избор" + }, + "maximumAccessCount": { + "message": "Максимален брой достъпвания." + }, + "maximumAccessCountDesc": { + "message": "При задаване — това изпращане ще се изключи след определен брой достъпвания.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Изискване на парола за достъп до това изпращане.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Скрити бележки за това изпращане.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Пълно спиране на това изпращане — никой няма да има достъп.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Копиране на връзката към това изпращане при запазването му.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст за изпращане." + }, + "sendHideText": { + "message": "Стандартно текстът на това изпращане да се крие.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Текущ брой на достъпванията" + }, + "createSend": { + "message": "Създаване на изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Нова парола" + }, + "sendDisabled": { + "message": "Изпращането е изключено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Поради политика на организация, може само да изтривате съществуващи изпращания.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Създадено изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Редактирано изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "За да изберете файл, отворете разширението в страничната лента (ако е възможно) или в нов прозорец, като натиснете това съобщение." + }, + "sendFirefoxFileWarning": { + "message": "За да изберете файл във Firefox, отворете разширението в страничната лента или в нов прозорец, като натиснете това съобщение." + }, + "sendSafariFileWarning": { + "message": "За да изберете файл в Safari, отворете разширението в нов прозорец, като натиснете това съобщение." + }, + "sendFileCalloutHeader": { + "message": "Преди да почнете" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "За избор на дата от каландар", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "натиснете тук", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "за изскачащ прозорец.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Неправилна дата на валидност." + }, + "deletionDateIsInvalid": { + "message": "Неправилна дата на изтриване." + }, + "expirationDateAndTimeRequired": { + "message": "Необходими са дата и време на валидност." + }, + "deletionDateAndTimeRequired": { + "message": "Необходима е дата на изтриване." + }, + "dateParsingError": { + "message": "Грешка при запазване на датата на валидност и изтриване." + }, + "hideEmail": { + "message": "Скриване на е-пощата ми от получателите." + }, + "sendOptionsPolicyInEffect": { + "message": "Поне една политика на организация влияе на настройките за изпращане." + }, + "passwordPrompt": { + "message": "Повторно запитване за главната парола" + }, + "passwordConfirmation": { + "message": "Потвърждение на главната парола" + }, + "passwordConfirmationDesc": { + "message": "Това действие е защитено. За да продължите, въведете отново главната си парола, за да потвърдите самоличността си." + }, + "emailVerificationRequired": { + "message": "Изисква се потвърждение на е-пощата" + }, + "emailVerificationRequiredDesc": { + "message": "Трябва да потвърдите е-пощата си, за да използвате тази функционалност. Можете да го направите в уеб-трезора." + }, + "updatedMasterPassword": { + "message": "Главната парола е променена" + }, + "updateMasterPassword": { + "message": "Промяна на главната парола" + }, + "updateMasterPasswordWarning": { + "message": "Вашата главна парола наскоро е била сменена от администратор в организацията Ви. За да получите достъп до трезора, трябва първо да я промените. Това означава, че ще бъдете отписан(а) от текущата си сесия и ще трябва да се впишете отново. Активните сесии на други устройства може да продължат да бъдат активни още един час." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Автоматично включване" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Тази организация включва автоматично новите си потребители в смяната на пароли. Това означава, че администраторите на организацията ще могат да променят главната Ви парола." + }, + "selectFolder": { + "message": "Избиране на папка..." + }, + "ssoCompleteRegistration": { + "message": "За да завършите настройките за еднократна идентификация, трябва да зададете главна парола за трезора." + }, + "hours": { + "message": "Часа" + }, + "minutes": { + "message": "Минути" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Настройките на организацията Ви влияят върху времето за достъп до трезора Ви. Максималното разрешено време за достъп е $HOURS$ час(а) и $MINUTES$ минути", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Времето за достъп до трезора Ви превишава ограничението, определено от организацията Ви." + }, + "vaultExportDisabled": { + "message": "Изнасянето на трезора е изключено" + }, + "personalVaultExportPolicyInEffect": { + "message": "Една или повече от настройките на организацията Ви не позволяват да изнасяте личния си трезор." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Не може да бъде открит подходящ елемент от формуляр. Опитайте да инспектирате кода на HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Няма намерен уникален идентификатор." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ използва еднократно удостоверяване със собствен сървър за ключове. Членовете на тази организация вече нямат нужда от главна парола за вписване.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Напускане на организацията" + }, + "removeMasterPassword": { + "message": "Премахване на главната парола" + }, + "removedMasterPassword": { + "message": "Главната парола е премахната." + }, + "leaveOrganizationConfirmation": { + "message": "Наистина ли искате да напуснете тази организация?" + }, + "leftOrganization": { + "message": "Напуснахте организацията." + }, + "toggleCharacterCount": { + "message": "Превключване на броя знаци" + }, + "sessionTimeout": { + "message": "Сесията Ви изтече. Моля, върнете се назад и се опитайте да влезете отново." + }, + "exportingPersonalVaultTitle": { + "message": "Изнасяне на личния трезор" + }, + "exportingPersonalVaultDescription": { + "message": "Ще бъдат изнесени само записите от личния трезор свързан с $EMAIL$. Записите в трезора на организацията няма да бъдат включени.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Грешка" + }, + "regenerateUsername": { + "message": "Повторно генериране на потр. име" + }, + "generateUsername": { + "message": "Генериране на потр. име" + }, + "usernameType": { + "message": "Тип потребителско име" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Използвайте възможностите за под-адресиране на е-поща на своя доставчик." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Произволно" + }, + "randomWord": { + "message": "Произволна дума" + }, + "websiteName": { + "message": "Име на уеб сайт" + }, + "whatWouldYouLikeToGenerate": { + "message": "Какво бихте искали да генерирате?" + }, + "passwordType": { + "message": "Тип парола" + }, + "service": { + "message": "Услуга" + } +} diff --git a/apps/browser/src/_locales/bn/messages.json b/apps/browser/src/_locales/bn/messages.json new file mode 100644 index 0000000000..249d1b68b4 --- /dev/null +++ b/apps/browser/src/_locales/bn/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "আপনার সমস্ত ডিভাইসের জন্য একটি সুরক্ষিত এবং বিনামূল্যের পাসওয়ার্ড ব্যবস্থাপক।", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "আপনার সুরক্ষিত ভল্টে প্রবেশ করতে লগ ইন করুন অথবা একটি নতুন অ্যাকাউন্ট তৈরি করুন।" + }, + "createAccount": { + "message": "অ্যাকাউন্ট তৈরি করুন" + }, + "login": { + "message": "প্রবেশ করুন" + }, + "enterpriseSingleSignOn": { + "message": "এন্টারপ্রাইজ একক সাইন-অন" + }, + "cancel": { + "message": "বাতিল" + }, + "close": { + "message": "বন্ধ করুন" + }, + "submit": { + "message": "জমা দিন" + }, + "emailAddress": { + "message": "ইমেইল ঠিকানা" + }, + "masterPass": { + "message": "মূল পাসওয়ার্ড" + }, + "masterPassDesc": { + "message": "মূল পাসওয়ার্ড হল সেই পাসওয়ার্ডটি যা আপনি নিজের ভল্ট ব্যাবহার করতে ব্যবহার করেন। এটি খুব গুরুত্বপূর্ণ যে আপনি নিজের মূল পাসওয়ার্ডটি ভুলে যাবেন না। আপনি যদি ভুলে গিয়ে থাকেন তবে পাসওয়ার্ডটি পুনরুদ্ধার করার কোনও উপায় নেই।" + }, + "masterPassHintDesc": { + "message": "যদি আপনি আপনার পাসওয়ার্ড ভুলে যান তাহলে একটি মূল পাসওয়ার্ডের ইঙ্গিতটি আপনাকে মনে করাতে সাহায্য করতে পারে।" + }, + "reTypeMasterPass": { + "message": "পুনরায় মূল পাসওয়ার্ডটি লিখুন" + }, + "masterPassHint": { + "message": "মূল পাসওয়ার্ড ইঙ্গিত (ঐচ্ছিক)" + }, + "tab": { + "message": "ট্যাব" + }, + "myVault": { + "message": "আমার ভল্ট" + }, + "tools": { + "message": "সরঞ্জামসমূহ" + }, + "settings": { + "message": "সেটিংস" + }, + "currentTab": { + "message": "বর্তমান ট্যাব" + }, + "copyPassword": { + "message": "পাসওয়ার্ড অনুলিপিত করুন" + }, + "copyNote": { + "message": "নোট অনুলিপিত করুন" + }, + "copyUri": { + "message": "URI অনুলিপিত করুন" + }, + "copyUsername": { + "message": "ব্যবহারকারীর নাম অনুলিপিত করুন" + }, + "copyNumber": { + "message": "নম্বর অনুলিপিত করুন" + }, + "copySecurityCode": { + "message": "সুরক্ষা কোড অনুলিপিত করুন" + }, + "autoFill": { + "message": "স্বতঃপূরণ" + }, + "generatePasswordCopied": { + "message": "পাসওয়ার্ড তৈরি করুন (অনুলিপিকৃত)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "কোনও মিলত লগইন নেই।" + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "বর্তমান ব্রাউজার ট্যাবের জন্য স্বয়ংক্রিয় পূরণের কোনও লগইন উপলব্ধ নেই।" + }, + "addLogin": { + "message": "একটি লগইন জুড়ুন " + }, + "addItem": { + "message": "বস্তু জুড়ুন" + }, + "passwordHint": { + "message": "পাসওয়ার্ড ইঙ্গিত" + }, + "enterEmailToGetHint": { + "message": "আপনার মূল পাসওয়ার্ডের ইঙ্গিতটি পেতে আপনার অ্যাকাউন্টের ইমেল ঠিকানা প্রবেশ করুন।" + }, + "getMasterPasswordHint": { + "message": "মূল পাসওয়ার্ডের ইঙ্গিত পান" + }, + "continue": { + "message": "অবিরত" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "যাচাইকরণ কোড" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "অ্যাকাউন্ট" + }, + "changeMasterPassword": { + "message": "মূল পাসওয়ার্ড পরিবর্তন" + }, + "fingerprintPhrase": { + "message": "ফিঙ্গারপ্রিন্ট ফ্রেজ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "আপনার অ্যাকাউন্টের ফিঙ্গারপ্রিন্ট ফ্রেজ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "দ্বি-পদক্ষেপের লগইন" + }, + "logOut": { + "message": "লগ আউট" + }, + "about": { + "message": "সম্বন্ধে" + }, + "version": { + "message": "সংস্করণ" + }, + "save": { + "message": "সংরক্ষণ" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "ফোল্ডার জুড়ুন" + }, + "name": { + "message": "নাম" + }, + "editFolder": { + "message": "ফোল্ডার সম্পাদনা" + }, + "deleteFolder": { + "message": "ফোল্ডার মুছুন" + }, + "folders": { + "message": "ফোল্ডারসমূহ" + }, + "noFolders": { + "message": "তালিকার জন্য কোনও ফোল্ডার নেই।" + }, + "helpFeedback": { + "message": "সহায়তা এবং প্রতিক্রিয়া" + }, + "sync": { + "message": "সিঙ্ক" + }, + "syncVaultNow": { + "message": "এখনই ভল্ট সিঙ্ক করুন" + }, + "lastSync": { + "message": "শেষ সিঙ্ক:" + }, + "passGen": { + "message": "পাসওয়ার্ড উৎপাদক" + }, + "generator": { + "message": "উৎপাদক", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "আপনার লগইনগুলির জন্য স্বয়ংক্রিয়ভাবে শক্তিশালী, অদ্বিতীয় পাসওয়ার্ড তৈরি করুন।" + }, + "bitWebVault": { + "message": "Bitwarden ওয়েব ভল্ট" + }, + "importItems": { + "message": "বস্তু আমদানি" + }, + "select": { + "message": "নির্বাচন করুন" + }, + "generatePassword": { + "message": "পাসওয়ার্ড তৈরি করুন" + }, + "regeneratePassword": { + "message": "পাসওয়ার্ড পুনঃতৈরি করুন" + }, + "options": { + "message": "বিকল্পসমূহ" + }, + "length": { + "message": "দৈর্ঘ্য" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "শব্দের সংখ্যা" + }, + "wordSeparator": { + "message": "শব্দ বিভাজক" + }, + "capitalize": { + "message": "বড় হাতের করুন", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "নম্বর অন্তর্ভুক্ত করুন" + }, + "minNumbers": { + "message": "সর্বনিম্ন সংখ্যা" + }, + "minSpecial": { + "message": "ন্যূনতম বিশেষ" + }, + "avoidAmbChar": { + "message": "অস্পষ্ট বর্ণগুলি এড়িয়ে চলুন" + }, + "searchVault": { + "message": "ভল্ট খুঁজুন" + }, + "edit": { + "message": "সম্পাদনা" + }, + "view": { + "message": "দেখুন" + }, + "noItemsInList": { + "message": "তালিকার জন্য কোনও বস্তু নেই।" + }, + "itemInformation": { + "message": "বস্তু তথ্য" + }, + "username": { + "message": "ব্যবহারকারীর নাম" + }, + "password": { + "message": "পাসওয়ার্ড" + }, + "passphrase": { + "message": "পাসফ্রেজ" + }, + "favorite": { + "message": "প্রিয়" + }, + "notes": { + "message": "নোট" + }, + "note": { + "message": "নোট" + }, + "editItem": { + "message": "বস্তু সম্পাদনা" + }, + "folder": { + "message": "ফোল্ডার" + }, + "deleteItem": { + "message": "বস্তু মুছুন" + }, + "viewItem": { + "message": "বস্তু দেখুন" + }, + "launch": { + "message": "শুরু" + }, + "website": { + "message": "ওয়েবসাইট" + }, + "toggleVisibility": { + "message": "দৃশ্যমানতা টগল করুন" + }, + "manage": { + "message": "পরিচালনা" + }, + "other": { + "message": "অন্যান্য" + }, + "rateExtension": { + "message": "এক্সটেনশনটি মূল্যায়ন করুন" + }, + "rateExtensionDesc": { + "message": "দয়া করে একটি ভাল পর্যালোচনার মাধ্যমে সাহায্য করতে আমাদের বিবেচনা করুন!" + }, + "browserNotSupportClipboard": { + "message": "আপনার ওয়েব ব্রাউজার সহজে ক্লিপবোর্ড অনুলিপি সমর্থন করে না। পরিবর্তে এটি নিজেই অনুলিপি করুন।" + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার মূল পাসওয়ার্ডটি যাচাই করান।" + }, + "unlock": { + "message": "আনলক" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ এ $EMAIL$ হিসাবে লগ ইনকৃত", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "অবৈধ মূল পাসওয়ার্ড" + }, + "vaultTimeout": { + "message": "ভল্টের সময়সীমা" + }, + "lockNow": { + "message": "এখনই লক করুন" + }, + "immediately": { + "message": "সঙ্গে সঙ্গে" + }, + "tenSeconds": { + "message": "১০ সেকেন্ড" + }, + "twentySeconds": { + "message": "২০ সেকেন্ড" + }, + "thirtySeconds": { + "message": "৩০ সেকেন্ড" + }, + "oneMinute": { + "message": "১ মিনিট" + }, + "twoMinutes": { + "message": "২ মিনিট" + }, + "fiveMinutes": { + "message": "৫ মিনিট" + }, + "fifteenMinutes": { + "message": "১৫ মিনিট" + }, + "thirtyMinutes": { + "message": "৩০ মিনিট" + }, + "oneHour": { + "message": "১ ঘণ্টা" + }, + "fourHours": { + "message": "৪ ঘন্টা" + }, + "onLocked": { + "message": "সিস্টেম লকে" + }, + "onRestart": { + "message": "ব্রাউজার পুনঃসূচনাই" + }, + "never": { + "message": "কখনই না" + }, + "security": { + "message": "নিরাপত্তা" + }, + "errorOccurred": { + "message": "একটি ত্রুটি উৎপন্ন হয়েছে" + }, + "emailRequired": { + "message": "ইমেইল ঠিকানা প্রয়োজন।" + }, + "invalidEmail": { + "message": "অকার্যকর ইমেইল ঠিকানা।" + }, + "masterPassRequired": { + "message": "মূল পাসওয়ার্ড প্রয়োজন।" + }, + "masterPassLength": { + "message": "মূল পাসওয়ার্ড কমপক্ষে ৮ অক্ষর দীর্ঘ হওয়া উচিত।" + }, + "masterPassDoesntMatch": { + "message": "মূল পাসওয়ার্ড নিশ্চিতকরণ মেলেনি।" + }, + "newAccountCreated": { + "message": "আপনার নতুন অ্যাকাউন্ট তৈরি করা হয়েছে! আপনি এখন প্রবেশ করতে পারেন।" + }, + "masterPassSent": { + "message": "আমরা আপনাকে আপনার মূল পাসওয়ার্ডের ইঙ্গিত সহ একটি ইমেল প্রেরণ করেছি।" + }, + "verificationCodeRequired": { + "message": "যাচাইকরণ কোড প্রয়োজন।" + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ অনুলিপিত", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "এই পৃষ্ঠায় নির্বাচিত বস্তুটি স্বতঃপূর্ণে অক্ষম। পরিবর্তে তথ্যটি অনুলিপিত করুন এবং আটকান।" + }, + "loggedOut": { + "message": "প্রস্থানকৃত" + }, + "loginExpired": { + "message": "আপনার লগইন মাত্রকালটির মেয়াদ শেষ হয়ে গেছে।" + }, + "logOutConfirmation": { + "message": "আপনি লগ আউট করতে চান?" + }, + "yes": { + "message": "হ্যাঁ" + }, + "no": { + "message": "না" + }, + "unexpectedError": { + "message": "একটি অপ্রত্যাশিত ত্রুটি ঘটেছে।" + }, + "nameRequired": { + "message": "নাম প্রয়োজন।" + }, + "addedFolder": { + "message": "ফোল্ডার জোড়া হয়েছে" + }, + "changeMasterPass": { + "message": "মূল পাসওয়ার্ড পরিবর্তন" + }, + "changeMasterPasswordConfirmation": { + "message": "আপনি bitwarden.com ওয়েব ভল্ট থেকে মূল পাসওয়ার্ডটি পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "twoStepLoginConfirmation": { + "message": "দ্বি-পদক্ষেপ লগইন অন্য ডিভাইসে আপনার লগইনটি যাচাই করার জন্য সিকিউরিটি কী, প্রমাণীকরণকারী অ্যাপ্লিকেশন, এসএমএস, ফোন কল বা ই-মেইল ব্যাবহারের মাধ্যমে আপনার অ্যাকাউন্টকে আরও সুরক্ষিত করে। bitwarden.com ওয়েব ভল্টে দ্বি-পদক্ষেপের লগইন সক্ষম করা যাবে। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "editedFolder": { + "message": "ফোল্ডার সম্পাদিত" + }, + "deleteFolderConfirmation": { + "message": "আপনি কি নিশ্চিত যে এই ফোল্ডারটি মুছতে চান?" + }, + "deletedFolder": { + "message": "ফোল্ডার মোছা হয়েছে" + }, + "gettingStartedTutorial": { + "message": "শুরু করার গৃহশিক্ষা" + }, + "gettingStartedTutorialVideo": { + "message": "ব্রাউজার এক্সটেনশান থেকে কীভাবে সর্বাধিক লাভবান হতে পারবেন তা জানতে আমাদের শুরু করার গৃহশিক্ষাটি দেখুন" + }, + "syncingComplete": { + "message": "সিঙ্কিং সম্পন্ন" + }, + "syncingFailed": { + "message": "সিঙ্কিঙ্গে ব্যর্থ" + }, + "passwordCopied": { + "message": "পাসওয়ার্ড অনুলিপিত" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "নতুন URI" + }, + "addedItem": { + "message": "বস্তু যোগ করা হয়েছে" + }, + "editedItem": { + "message": "সম্পাদিত বস্তু" + }, + "deleteItemConfirmation": { + "message": "আপনি কি সত্যিই আবর্জনাতে পাঠাতে চান?" + }, + "deletedItem": { + "message": "বস্তুতটি আবর্জনাতে পাঠানো হয়েছে" + }, + "overwritePassword": { + "message": "ওভাররাইট পাসওয়ার্ড" + }, + "overwritePasswordConfirmation": { + "message": "আপনি কি নিশ্চিত যে আপনি বর্তমান পাসওয়ার্ডটি ওভাররাইট করতে চান?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "ফোল্ডার অনুসন্ধান" + }, + "searchCollection": { + "message": "সংগ্রহ অনুসন্ধান" + }, + "searchType": { + "message": "অনুসন্ধানের ধরন" + }, + "noneFolder": { + "message": "কোন ফোল্ডার নেই", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "লগইন যোগ করুন বিজ্ঞপ্তি অক্ষম করুন" + }, + "addLoginNotificationDesc": { + "message": "\"লগইন যোগ করুন বিজ্ঞপ্তি\" স্বয়ংক্রিয়ভাবে আপনই যখনই প্রথমবারের জন্য লগ ইন করেন তখন আপনার ভল্টে নতুন লগইনগুলি সংরক্ষণ করতে অনুরোধ জানায়।" + }, + "dontShowCardsCurrentTab": { + "message": "ট্যাব পৃষ্ঠায় কার্ডগুলি দেখাবেন না" + }, + "dontShowCardsCurrentTabDesc": { + "message": "আপনার ভল্ট থেকে কার্ড বস্তুগুলি সহজেই স্বতঃপূরণের জন্য 'বর্তমান ট্যাব' পৃষ্ঠাতে তালিকাভুক্ত করা হয়েছে।" + }, + "dontShowIdentitiesCurrentTab": { + "message": "ট্যাব পৃষ্ঠায় পরিচয় দেখাবেন না" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "আপনার ভল্ট থেকে পরিচিতি বস্তুগুলি সহজেই স্বতঃপূরণের জন্য 'বর্তমান ট্যাব' পৃষ্ঠাতে তালিকাভুক্ত করা হয়েছে।" + }, + "clearClipboard": { + "message": "ক্লিপবোর্ড পরিষ্কার", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "আপনার ক্লিপবোর্ড থেকে অনুলিপিত মানগুলি স্বয়ংক্রিয়ভাবে সাফ করে।", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Bitwarden আপনার জন্য এই পাসওয়ার্ডটি মনে রাখবে?" + }, + "notificationAddSave": { + "message": "হ্যাঁ, এখনই সংরক্ষণ করুন" + }, + "disableChangedPasswordNotification": { + "message": "পাসওয়ার্ড পরিবর্তন বিজ্ঞপ্তি অক্ষম করুন" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"পাসওয়ার্ড পরিবর্তন বিজ্ঞপ্তি\" স্বয়ংক্রিয়ভাবে আপনাকে আপনার ভল্টে একটি লগইনের পাসওয়ার্ড হালনাগাদ করার অনুরোধ জানায় যখনই কোনও ওয়েবসাইটে আপনি এটি পরিবর্তন করেছেন তা সনাক্ত করে।" + }, + "notificationChangeDesc": { + "message": "আপনি কি এই পাসওয়ার্ডটি Bitwarden এ হালনাগাদ করতে চান?" + }, + "notificationChangeSave": { + "message": "হ্যাঁ, এখনই হালনাগাদ করুন" + }, + "disableContextMenuItem": { + "message": "প্রসঙ্গ মেনু বিকল্পগুলি অক্ষম করুন" + }, + "disableContextMenuItemDesc": { + "message": "প্রসঙ্গ মেনু বিকল্পগুলি আপনার বর্তমান ট্যাবের ওয়েবসাইটটির জন্য পাসওয়ার্ড তৈরি এবং লগিনগুলি দ্রুত সরবরাহ করে।" + }, + "defaultUriMatchDetection": { + "message": "পূর্ব-নির্ধারিত URI মিল সনাক্তকরণ", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "স্বতঃপূরণের মতো ক্রিয়া সম্পাদন করার সময় লগইনগুলির জন্য URI মিল সনাক্তকরণ যে পূর্ব-নির্ধারিত পদ্ধতিতে পরিচালনা করা হবে তা চয়ন করুন।" + }, + "theme": { + "message": "থিম" + }, + "themeDesc": { + "message": "অ্যাপ্লিকেশনটির রং থিম পরিবর্তন।" + }, + "dark": { + "message": "অন্ধকার", + "description": "Dark color" + }, + "light": { + "message": "উজ্জ্বল", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "ভল্ট রফতানি" + }, + "fileFormat": { + "message": "ফাইলের ধরণ" + }, + "warning": { + "message": "সতর্কতা", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "ভল্ট রফতানির নিশ্চয়তা দিন" + }, + "exportWarningDesc": { + "message": "এই রফতানীতে একটি বিনা-এনক্রিপ্টেড করা বিন্যাসে আপনার ভল্ট তথ্য রয়েছে। আপনার রফতানিকৃত হওয়া ফাইল নিরাপত্তাহীন চ্যানেলগুলির মাধ্যমে (যেমন ইমেল) সংরক্ষণ বা প্রেরণ করা উচিত নয়। আপনি এটি ব্যবহার করে কাজ শেষ করার পর সাথে সাথে মুছে ফেলুন।" + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "আপনার ভল্ট তথ্য রফতানি করতে আপনার মূল পাসওয়ার্ডটি দিন।" + }, + "shared": { + "message": "ভাগকৃত" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "ভাগ করুন" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "আরও জানুন" + }, + "authenticatorKeyTotp": { + "message": "প্রমাণীকরণকারী কী (TOTP)" + }, + "verificationCodeTotp": { + "message": "যাচাইকরণ কোড (TOTP)" + }, + "copyVerificationCode": { + "message": "যাচাইকরণ কোড অনুলিপিত করুন" + }, + "attachments": { + "message": "সংযুক্তি" + }, + "deleteAttachment": { + "message": "সংযুক্তি মুছুন" + }, + "deleteAttachmentConfirmation": { + "message": "আপনি কি এই সংযুক্তিটি মোছার বিষয়ে নিশ্চিত?" + }, + "deletedAttachment": { + "message": "সংযুক্তি মোছা হয়েছে" + }, + "newAttachment": { + "message": "নতুন সংযুক্তি যুক্ত করুন" + }, + "noAttachments": { + "message": "সংযুক্তি নেই।" + }, + "attachmentSaved": { + "message": "সংযুক্তিটি সংরক্ষণ করা হয়েছে।" + }, + "file": { + "message": "ফাইল" + }, + "selectFile": { + "message": "একটি ফাইল নির্বাচন করুন।" + }, + "maxFileSize": { + "message": "সর্বোচ্চ ফাইলের আকার ১০০ এমবি।" + }, + "featureUnavailable": { + "message": "বৈশিষ্ট্য অনুপলব্ধ" + }, + "updateKey": { + "message": "আপনি আপনার এনক্রিপশন কী হালনাগাদ না করা পর্যন্ত এই বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না।" + }, + "premiumMembership": { + "message": "প্রিমিয়াম সদস্য" + }, + "premiumManage": { + "message": "সদস্যতা পরিচালনা" + }, + "premiumManageAlert": { + "message": "আপনি bitwarden.com ওয়েব ভল্টে আপনার সদস্যপদ পরিচালনা করতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "premiumRefresh": { + "message": "সদস্যতা সতেজ করুন" + }, + "premiumNotCurrentMember": { + "message": "আপনি বর্তমানে প্রিমিয়াম সদস্য নন।" + }, + "premiumSignUpAndGet": { + "message": "প্রিমিয়াম সদস্যতার জন্য সাইন আপ করুন এবং পান:" + }, + "ppremiumSignUpStorage": { + "message": "ফাইল সংযুক্তির জন্য ১ জিবি এনক্রিপ্টেড স্থান।" + }, + "ppremiumSignUpTwoStep": { + "message": "YubiKey, FIDO U2F, ও Duo এর মতো অতিরিক্ত দ্বি-পদক্ষেপ লগইন বিকল্পগুলি।" + }, + "ppremiumSignUpReports": { + "message": "আপনার ভল্টটি সুরক্ষিত রাখতে পাসওয়ার্ড স্বাস্থ্যকরন, অ্যাকাউন্ট স্বাস্থ্য এবং ডেটা লঙ্ঘনের প্রতিবেদন।" + }, + "ppremiumSignUpTotp": { + "message": "আপনার ভল্টে লগইনগুলির জন্য TOTP যাচাইকরণ কোড (2FA) উৎপাদক।" + }, + "ppremiumSignUpSupport": { + "message": "অগ্রাধিকার গ্রাহক সমর্থন।" + }, + "ppremiumSignUpFuture": { + "message": "ভবিষ্যতের সমস্ত প্রিমিয়াম বৈশিষ্ট্য। আরও শীঘ্রই আসছে!" + }, + "premiumPurchase": { + "message": "প্রিমিয়াম কিনুন" + }, + "premiumPurchaseAlert": { + "message": "আপনি bitwarden.com ওয়েব ভল্টে প্রিমিয়াম সদস্যতা কিনতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "premiumCurrentMember": { + "message": "আপনি প্রিমিয়াম সদস্য!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden কে সমর্থন করার জন্য আপনাকে ধন্যবাদ।" + }, + "premiumPrice": { + "message": "সমস্ত মাত্র $PRICE$ / বছরের জন্য!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "পুনঃসতেজ সম্পূর্ণ" + }, + "disableAutoTotpCopy": { + "message": "স্বয়ংক্রিয় TOTP অনুলিপি অক্ষম করুন" + }, + "disableAutoTotpCopyDesc": { + "message": "যদি আপনার লগইনের সাথে একটি প্রমাণীকরণ কী থাকে, আপনি যখনই লগইনটি স্বতঃপূরণ করেন তবে TOTP যাচাইকরণ কোডটি স্বয়ংক্রিয়ভাবে আপনার ক্লিপবোর্ডে অনুলিপিত করা হয়।" + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "প্রিমিয়াম আবশ্যক" + }, + "premiumRequiredDesc": { + "message": "এই বৈশিষ্ট্যটি ব্যবহার করতে একটি প্রিমিয়াম সদস্যতার প্রয়োজন।" + }, + "enterVerificationCodeApp": { + "message": "আপনার প্রমাণীকরণকারী অ্যাপ থেকে ৬ সংখ্যার যাচাইকরণ কোডটি প্রবেশ করুন।" + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ এ ইমেইল করা ৬ সংখ্যার যাচাই কোডটি প্রবেশ করুন।", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "$EMAIL$ এ যাচাইকরণ ইমেইল প্রেরণ করা হয়েছে।", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "আমাকে মনে রাখবেন" + }, + "sendVerificationCodeEmailAgain": { + "message": "আবার যাচাইকরণ কোড ইমেইলে প্রেরণ করুন" + }, + "useAnotherTwoStepMethod": { + "message": "অন্য দ্বি-পদক্ষেপ প্রবেশ পদ্ধতি ব্যবহার করুন" + }, + "insertYubiKey": { + "message": "আপনার কম্পিউটারের ইউএসবি পোর্টে আপনার YubiKey ঢোকান, তারপরে তার বোতামটি স্পর্শ করুন।" + }, + "insertU2f": { + "message": "আপনার কম্পিউটারের ইউএসবি পোর্টে আপনার সুরক্ষা কী ঢোকান। এটিতে যদি একটি বোতাম থাকে তবে তা স্পর্শ করুন।" + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "লগইন অনুপলব্ধ" + }, + "noTwoStepProviders": { + "message": "এই অ্যাকাউন্টে দ্বি-পদক্ষেপ লগইন সক্ষম রয়েছে, তবে কনফিগারকৃত দ্বি-পদক্ষেপ সরবরাহকারীদের কোনওটিই এই ওয়েব ব্রাউজার দ্বারা সমর্থিত নয়।" + }, + "noTwoStepProviders2": { + "message": "দয়া করে একটি সমর্থিত ওয়েব ব্রাউজার ব্যবহার করুন (যেমন ক্রোম) এবং/অথবা অতিরিক্ত সরবরাহকারী যুক্ত করুন যা ওয়েব ব্রাউজারগুলিতে আরও ভাল সমর্থিত (যেমন একটি প্রমাণীকরণকারী অ্যাপ)।" + }, + "twoStepOptions": { + "message": "দ্বি-পদক্ষেপ লগইন বিকল্প" + }, + "recoveryCodeDesc": { + "message": "আপনার সমস্ত দ্বি-গুণক সরবরাহকারীদের অ্যাক্সেস হারিয়েছেন? আপনার অ্যাকাউন্ট থেকে সমস্ত দ্বি-গুণক সরবরাহকারীদের অক্ষম করতে আপনার পুনরুদ্ধার কোডটি ব্যবহার করুন।" + }, + "recoveryCodeTitle": { + "message": "পুনরুদ্ধার কোড" + }, + "authenticatorAppTitle": { + "message": "প্রমাণীকরণকারী অ্যাপ" + }, + "authenticatorAppDesc": { + "message": "সময় ভিত্তিক যাচাইকরণ কোড উৎপন্ন করতে একটি প্রমাণীকরণকারী অ্যাপ্লিকেশন (যেমন Authy বা Google Authenticator) ব্যবহার করুন।", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP সুরক্ষা কী" + }, + "yubiKeyDesc": { + "message": "আপনার অ্যাকাউন্ট ব্যাবহার করতে একটি YubiKey ব্যবহার করুন। YubiKey 4, 4 Nano, 4C, এবং NEO ডিভাইসগুলির সাথে কাজ করে।" + }, + "duoDesc": { + "message": "Duo Mobile app, এসএমএস, ফোন কল, বা U2F সুরক্ষা কী ব্যবহার করে Duo Security এর মাধ্যমে যাচাই করুন।", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo Mobile app, এসএমএস, ফোন কল, বা U2F সুরক্ষা কী ব্যবহার করে আপনার সংস্থার জন্য Duo Security এর মাধ্যমে যাচাই করুন।", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "ই-মেইল" + }, + "emailDesc": { + "message": "যাচাই কোডগুলি আপনাকে ই-মেইল করা হবে।" + }, + "selfHostedEnvironment": { + "message": "স্ব-হোস্টকৃত পরিবেশ" + }, + "selfHostedEnvironmentFooter": { + "message": "আপনার অন-প্রাঙ্গনে হোস্টকৃত Bitwarden ইনস্টলেশনটির বেস URL উল্লেখ করুন।" + }, + "customEnvironment": { + "message": "পছন্দসই পরিবেশ" + }, + "customEnvironmentFooter": { + "message": "উন্নত ব্যবহারকারীদের জন্য। আপনি স্বতন্ত্রভাবে প্রতিটি পরিষেবার মূল URL নির্দিষ্ট করতে পারেন।" + }, + "baseUrl": { + "message": "সার্ভার URL" + }, + "apiUrl": { + "message": "এপিআই সার্ভার URL" + }, + "webVaultUrl": { + "message": "ওয়েব ভল্ট সার্ভার URL" + }, + "identityUrl": { + "message": "পরিচয় সার্ভার URL" + }, + "notificationsUrl": { + "message": "বিজ্ঞপ্তি সার্ভার URL" + }, + "iconsUrl": { + "message": "আইকন সার্ভার URL" + }, + "environmentSaved": { + "message": "পরিবেশের URL গুলি সংরক্ষণ করা হয়েছে।" + }, + "enableAutoFillOnPageLoad": { + "message": "পৃষ্ঠা লোডে স্বতঃপূরণ সক্ষম করুন" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "যদি কোনও লগইন ফর্ম সনাক্ত হয়, ওয়েব পৃষ্ঠাটি লোড হওয়ার পরে স্বয়ংক্রিয়ভাবে স্বতঃপূরণ করুন।" + }, + "experimentalFeature": { + "message": "এটি বর্তমানে একটি পরীক্ষামূলক বৈশিষ্ট্য। আপনার নিজ ঝুঁকিতে ব্যবহার করুন।" + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "ভল্ট পপআপ খুলুন" + }, + "commandOpenSidebar": { + "message": "সাইডবারে ভল্ট খুলুন" + }, + "commandAutofillDesc": { + "message": "বর্তমান ওয়েবসাইটটির জন্য সর্বশেষ ব্যবহৃত লগইনটি স্বতঃপূরণ করুন" + }, + "commandGeneratePasswordDesc": { + "message": "ক্লিপবোর্ডে একটি নতুন এলোমেলো পাসওয়ার্ড তৈরি এবং অনুলিপিত করুন" + }, + "commandLockVaultDesc": { + "message": "ভল্ট লক করুন" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "পছন্দসই ক্ষেত্র" + }, + "copyValue": { + "message": "মান অনুলিপিত করুন" + }, + "value": { + "message": "মান" + }, + "newCustomField": { + "message": "নতুন পছন্দসই ক্ষেত্র" + }, + "dragToSort": { + "message": "বাছাই করতে টানুন" + }, + "cfTypeText": { + "message": "পাঠ্য" + }, + "cfTypeHidden": { + "message": "লুকায়িত" + }, + "cfTypeBoolean": { + "message": "বুলিয়ান" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "আপনার যাচাইকরণ কোডটির জন্য আপনার ইমেলটি পরীক্ষা করতে পপআপ উইন্ডোটির বাইরে ক্লিক করলে এই পপআপটি বন্ধ হয়ে যাবে। আপনি কি এই পপআপটি একটি নতুন উইন্ডোতে খুলতে চান যাতে এটি বন্ধ না হয়?" + }, + "popupU2fCloseMessage": { + "message": "ব্রাউজারটি এই পপআপ উইন্ডোতে U2F অনুরোধগুলি প্রক্রিয়া করতে পারে না। আপনি কি এই পপআপটি একটি নতুন উইন্ডোতে খুলতে চান যাতে আপনি U2F ব্যবহার করে লগ ইন করতে পারেন?" + }, + "disableFavicon": { + "message": "ওয়েবসাইট আইকন অক্ষম করুন" + }, + "disableFaviconDesc": { + "message": "ওয়েবসাইট আইকনগুলি আপনার ভল্টের প্রতিটি লগইন বস্তুর পাশে একটি পরিচয়যোগ্য চিত্র সরবরাহ করে।" + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "কার্ডধারীর নাম" + }, + "number": { + "message": "নম্বর" + }, + "brand": { + "message": "ব্র্যান্ড" + }, + "expirationMonth": { + "message": "মেয়াদোত্তীর্ণ মাস" + }, + "expirationYear": { + "message": "মেয়াদোত্তীর্ণ বছর" + }, + "expiration": { + "message": "মেয়াদোত্তীর্ণতা" + }, + "january": { + "message": "জানুয়ারী" + }, + "february": { + "message": "ফেব্রুয়ারী" + }, + "march": { + "message": "মার্চ" + }, + "april": { + "message": "এপ্রিল" + }, + "may": { + "message": "মে" + }, + "june": { + "message": "জুন" + }, + "july": { + "message": "জুলাই" + }, + "august": { + "message": "আগস্ট" + }, + "september": { + "message": "সেপ্টেম্বর" + }, + "october": { + "message": "অক্টোবর" + }, + "november": { + "message": "নভেম্বর" + }, + "december": { + "message": "ডিসেম্বর" + }, + "securityCode": { + "message": "নিরাপত্তা কোড" + }, + "ex": { + "message": "উদাহরণ" + }, + "title": { + "message": "শিরোনাম" + }, + "mr": { + "message": "জনাব" + }, + "mrs": { + "message": "জনাবা" + }, + "ms": { + "message": "জনাবা" + }, + "dr": { + "message": "ডাঃ" + }, + "firstName": { + "message": "নামের প্রথমাংশ" + }, + "middleName": { + "message": "নামের মধ্যাংশ" + }, + "lastName": { + "message": "নামের শেষাংশ" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "পরিচয়ের নাম" + }, + "company": { + "message": "প্রতিষ্ঠান" + }, + "ssn": { + "message": "সামাজিক সুরক্ষা নম্বর" + }, + "passportNumber": { + "message": "পাসপোর্ট নম্বর" + }, + "licenseNumber": { + "message": "লাইসেন্স নম্বর" + }, + "email": { + "message": "ই-মেইল" + }, + "phone": { + "message": "ফোন" + }, + "address": { + "message": "ঠিকানা" + }, + "address1": { + "message": "ঠিকানা ১" + }, + "address2": { + "message": "ঠিকানা ২" + }, + "address3": { + "message": "ঠিকানা ৩" + }, + "cityTown": { + "message": "শহর" + }, + "stateProvince": { + "message": "রাজ্য / প্রদেশ" + }, + "zipPostalCode": { + "message": "জিপ / ডাক কোড" + }, + "country": { + "message": "দেশ" + }, + "type": { + "message": "ধরন" + }, + "typeLogin": { + "message": "লগইন" + }, + "typeLogins": { + "message": "লগিনগুলি" + }, + "typeSecureNote": { + "message": "সুরক্ষিত নোট" + }, + "typeCard": { + "message": "কার্ড" + }, + "typeIdentity": { + "message": "পরিচয়" + }, + "passwordHistory": { + "message": "পাসওয়ার্ড ইতিহাস" + }, + "back": { + "message": "পেছন" + }, + "collections": { + "message": "সংগ্রহ" + }, + "favorites": { + "message": "প্রিয়গুলো" + }, + "popOutNewWindow": { + "message": "একটি নতুন উইন্ডোতে পপ আউট" + }, + "refresh": { + "message": "পুনঃসতেজ" + }, + "cards": { + "message": "কার্ডগুলো" + }, + "identities": { + "message": "পরিচয়" + }, + "logins": { + "message": "লগিনগুলি" + }, + "secureNotes": { + "message": "সুরক্ষিত নোট" + }, + "clear": { + "message": "পরিষ্কার", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "পাসওয়ার্ড উন্মুক্ত হয়েছে কিনা তা পরীক্ষা করুন।" + }, + "passwordExposed": { + "message": "ডেটা লঙ্ঘনে এই পাসওয়ার্ডটি $VALUE$ সময় (গুলি) উন্মুক্ত করা হয়েছে। আপনার এটি পরিবর্তন করা উচিত।", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "এই পাসওয়ার্ডটি কোনও পরিচিত তথ্য লঙ্ঘনে পাওয়া যায় নি। এটি ব্যবহার করা নিরাপদ হওয়া উচিত।" + }, + "baseDomain": { + "message": "ভিত্তি ডোমেইন", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "নিয়ন্ত্রণকর্তা", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "হুবহু" + }, + "startsWith": { + "message": "শুরু করুন" + }, + "regEx": { + "message": "নিয়মিত অভিব্যাক্তি", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "মিল সনাক্তকরণ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "পূর্ব-নির্ধারিত মিল সনাক্তকরণ", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "বিকল্পগুলি টগল করুন" + }, + "toggleCurrentUris": { + "message": "বর্তমান URIs টগল করুন", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "বর্তমান URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "সংগঠন", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "প্রকার" + }, + "allItems": { + "message": "সকল বস্তু" + }, + "noPasswordsInList": { + "message": "তালিকার জন্য কোনও পাসওয়ার্ড নেই।" + }, + "remove": { + "message": "সরান" + }, + "default": { + "message": "পূর্ব-নির্ধারিত" + }, + "dateUpdated": { + "message": "হালনাগাদকৃত", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "পাসওয়ার্ড হালনাগাদকৃত", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "আপনি কি নিশ্চিত যে \"কখনই না\" বিকল্পটি ব্যবহার করবেন? আপনার লক বিকল্পগুলি \"কখনই না\" এ সেট করার ফলে আপনার ডিভাইসে ভল্টের এনক্রিপশন কী সঞ্চয় করা হবে। আপনি যদি এই বিকল্পটি ব্যবহার করেন তবে আপনার ডিভাইসটি সঠিকভাবে সুরক্ষিত রাখা নিশ্চিত করা উচিত।" + }, + "noOrganizationsList": { + "message": "আপনি কোনও সংস্থার অন্তর্ভুক্ত নন। সংগঠনগুলি আপনাকে নিরাপদে অন্য ব্যবহারকারীর সাথে বস্তুসমূহ ভাগ করে নেওয়ার অনুমতি দেয়।" + }, + "noCollectionsInList": { + "message": "তালিকার জন্য কোনও সংগ্রহ নেই।" + }, + "ownership": { + "message": "মালিকানা" + }, + "whoOwnsThisItem": { + "message": "এই বস্তুটির মালিক কে?" + }, + "strong": { + "message": "শক্তিশালী", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "ভাল", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "দুর্বল", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "দুর্বল মূল পাসওয়ার্ড" + }, + "weakMasterPasswordDesc": { + "message": "আপনার চয়নকৃত মূল পাসওয়ার্ডটি দুর্বল। আপনার Bitwarden অ্যাকাউন্টটি সঠিকভাবে সুরক্ষিত করার জন্য আপনার একটি শক্তিশালী মূল পাসওয়ার্ড (বা একটি পাসফ্রেজ) ব্যবহার করা উচিত। আপনি কি নিশ্চিত যে এই মূল পাসওয়ার্ডটি ব্যবহার করতে চান?" + }, + "pin": { + "message": "পিন", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "পিন দিয়ে আনলক" + }, + "setYourPinCode": { + "message": "Bitwarden আনলক করার জন্য আপনার পিন কোডটি সেট করুন। আপনি যদি অ্যাপ্লিকেশনটি থেকে পুরোপুরি লগ আউট করেন তবে আপনার পিন সেটিংস রিসেট করা হবে।" + }, + "pinRequired": { + "message": "পিন কোড প্রয়োজন।" + }, + "invalidPin": { + "message": "অবৈধ পিন কোড।" + }, + "unlockWithBiometrics": { + "message": "বায়োমেট্রিক্স দিয়ে আনলক করুন" + }, + "awaitDesktop": { + "message": "ডেস্কটপ থেকে নিশ্চিতকরণের অপেক্ষায়" + }, + "awaitDesktopDesc": { + "message": "ব্রাউজারের জন্য বায়োমেট্রিক্স সক্ষম করতে দয়া করে Bitwarden ডেস্কটপ অ্যাপ্লিকেশনটিতে বায়োমেট্রিক্স ব্যবহার সক্ষম করুন।" + }, + "lockWithMasterPassOnRestart": { + "message": "ব্রাউজার পুনরারম্ভতে মূল পাসওয়ার্ড দিয়ে লক করুন" + }, + "selectOneCollection": { + "message": "কমপক্ষে একটি সংগ্রহ নির্বাচন করুন।" + }, + "cloneItem": { + "message": "বস্তুটি নকল করুন" + }, + "clone": { + "message": "নকল" + }, + "passwordGeneratorPolicyInEffect": { + "message": "এক বা একাধিক সংস্থার নীতিগুলি আপনার উৎপাদকের সেটিংসকে প্রভাবিত করছে।" + }, + "vaultTimeoutAction": { + "message": "ভল্টের সময়সীমা কর্ম" + }, + "lock": { + "message": "লক", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "আবর্জনা", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "আবর্জনাতে খুঁজুন" + }, + "permanentlyDeleteItem": { + "message": "স্থায়ীভাবে বস্তু মুছুন" + }, + "permanentlyDeleteItemConfirmation": { + "message": "আপনি কি নিশ্চিত এই বস্তুটি স্থায়ীভাবে মুছতে চান?" + }, + "permanentlyDeletedItem": { + "message": "বস্তুটি স্থায়ীভাবে মুছে ফেলা হয়েছে" + }, + "restoreItem": { + "message": "বস্তু পুনরুদ্ধার" + }, + "restoreItemConfirmation": { + "message": "আপনি কি নিশ্চিত যে আপনি এই বস্তুটি পুনরুদ্ধার করতে চান?" + }, + "restoredItem": { + "message": "বস্তু পুনরুদ্ধারকৃত" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "লগ আউট করা আপনার ভল্টের সমস্ত অ্যাক্সেস সরিয়ে ফেলবে এবং সময়সীমার পরে অনলাইন প্রমাণীকরণের প্রয়োজন। আপনি কি নিশ্চিত যে এই সেটিংটি ব্যবহার করবেন?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "সময়সীমা কর্ম নিশ্চিতকরণ" + }, + "autoFillAndSave": { + "message": "স্বতঃপূরণ ও সংরক্ষণ" + }, + "autoFillSuccessAndSavedUri": { + "message": "স্বতঃপূরণকৃত বস্তু ও সংরক্ষিত URI" + }, + "autoFillSuccess": { + "message": "স্বতঃপূরণকৃত বস্তু" + }, + "setMasterPassword": { + "message": "মূল পাসওয়ার্ড ধার্য করুন" + }, + "masterPasswordPolicyInEffect": { + "message": "এক বা একাধিক সংস্থার নীতিগুলির কারণে নিম্নলিখিত প্রয়োজনসমূহ মূল পাসওয়ার্ডের পূরণ করা প্রয়োজন:" + }, + "policyInEffectMinComplexity": { + "message": "$SCORE$ এর সর্বনিম্ন জটিলতার স্কোর", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "$LENGTH$ এর সর্বনিম্ন দৈর্ঘ্য", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "এক বা একাধিক বড় হাতের অক্ষর রয়েছে" + }, + "policyInEffectLowercase": { + "message": "এক বা একাধিক ছোট হাতের অক্ষর রয়েছে" + }, + "policyInEffectNumbers": { + "message": "এক বা একাধিক সংখ্যা রয়েছে" + }, + "policyInEffectSpecial": { + "message": "নিম্নলিখিত বিশেষ অক্ষরগুলির একটি বা একাধিক রয়েছে $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "আপনার নতুন মূল পাসওয়ার্ড নীতির প্রয়োজনীয়তা পূরণ করে না।" + }, + "acceptPolicies": { + "message": "এই বাক্সটি টিক করে আপনি নিম্নলিখিতগুলিতে সম্মত হন:" + }, + "acceptPoliciesError": { + "message": "পরিষেবার শর্তাদি এবং গোপনীয়তা নীতি স্বীকার করা হয়নি।" + }, + "termsOfService": { + "message": "সেবা পাবার শর্ত" + }, + "privacyPolicy": { + "message": "গোপনীয়তা নীতি" + }, + "hintEqualsPassword": { + "message": "আপনার পাসওয়ার্ডের ইঙ্গিতটি আপনার পাসওয়ার্ড হতে পারবে না।" + }, + "ok": { + "message": "ঠিক আছে" + }, + "desktopSyncVerificationTitle": { + "message": "ডেস্কটপ সিঙ্ক যাচাইকরণ" + }, + "desktopIntegrationVerificationText": { + "message": "ডেস্কটপ অ্যাপ্লিকেশন এই আঙুলের ছাপ প্রদর্শন করে কিনা তা যাচাই করুন:" + }, + "desktopIntegrationDisabledTitle": { + "message": "ব্রাউজার একীকরণ সক্ষম নেই" + }, + "desktopIntegrationDisabledDesc": { + "message": "Bitwarden ডেস্কটপ অ্যাপ্লিকেশনটিতে ব্রাউজার ইন্টিগ্রেশন সক্ষম নেই। ডেস্কটপ অ্যাপ্লিকেশন মধ্যে সেটিংস এ দয়া করে এটি সক্ষম করুন।" + }, + "startDesktopTitle": { + "message": "Bitwarden ডেস্কটপ অ্যাপ্লিকেশন শুরু করুন" + }, + "startDesktopDesc": { + "message": "এই ক্রিয়াকলাপ ব্যবহার করার পূর্বে Bitwarden ডেস্কটপ অ্যাপ্লিকেশনটি শুরু করা দরকার।" + }, + "errorEnableBiometricTitle": { + "message": "বায়োমেট্রিক্স সক্ষম করতে অক্ষম" + }, + "errorEnableBiometricDesc": { + "message": "ডেস্কটপ অ্যাপ্লিকেশন দ্বারা কর্মটি বাতিলকৃত" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "ডেস্কটপ অ্যাপ্লিকেশনটি সুরক্ষিত যোগাযোগ চ্যানেলকে অবৈধ করেছে। দয়া করে এই ক্রিয়াটি আবার চেষ্টা করুন" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "ডেস্কটপ যোগাযোগ ব্যাহত" + }, + "nativeMessagingWrongUserDesc": { + "message": "ডেস্কটপ অ্যাপ্লিকেশনটি একটি ভিন্ন অ্যাকাউন্টে লগইনকৃত। উভয় অ্যাপ্লিকেশন একই অ্যাকাউন্টে লগ ইন করা রয়েছে কিনা তা নিশ্চিত করুন।" + }, + "nativeMessagingWrongUserTitle": { + "message": "অ্যাকাউন্ট মেলেনি" + }, + "biometricsNotEnabledTitle": { + "message": "বায়োমেট্রিকস সক্ষম নেই" + }, + "biometricsNotEnabledDesc": { + "message": "ব্রাউজার বায়োমেট্রিক্সের জন্য প্রথমে সেটিংসে ডেস্কটপ বায়োমেট্রিক সক্ষম করা প্রয়োজন।" + }, + "biometricsNotSupportedTitle": { + "message": "বায়োমেট্রিক্স অসমর্থিত" + }, + "biometricsNotSupportedDesc": { + "message": "ব্রাউজার বায়োমেট্রিক্স এই ডিভাইসে সমর্থিত নয়।" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "অনুমতি দেওয়া হয়নি" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bitwarden ডেস্কটপ অ্যাপ্লিকেশনটির সাথে যোগাযোগের অনুমতি ছাড়াই আমরা ব্রাউজার এক্সটেনশনে বায়োমেট্রিক সরবরাহ করতে পারি না। অনুগ্রহপূর্বক আবার চেষ্টা করুন।" + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "একটি এন্টারপ্রাইজ নীতির কারণে, আপনি আপনার ব্যক্তিগত ভল্টে বস্তুসমূহ সংরক্ষণ করা থেকে সীমাবদ্ধ। একটি প্রতিষ্ঠানের মালিকানা বিকল্পটি পরিবর্তন করুন এবং উপলভ্য সংগ্রহগুলি থেকে চয়ন করুন।" + }, + "personalOwnershipPolicyInEffect": { + "message": "একটি প্রতিষ্ঠানের নীতি আপনার মালিকানা বিকল্পগুলিকে প্রভাবিত করছে।" + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "ফাইল" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "অবসায়িত" + }, + "pendingDeletion": { + "message": "মুছে ফেলার জন্য অপেক্ষমান" + }, + "passwordProtected": { + "message": "পাসওয়ার্ড সুরক্ষিত" + }, + "copySendLink": { + "message": "Send লিঙ্ক কপি করুন", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "পাসওয়ার্ড অপসারণ করুন" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "পাসওয়ার্ড অপসারিত হয়েছে" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "আপনি কি নিশ্চিত যে আপনি এই পাসওয়ার্ডটি অপসারণ করতে চান?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "ইমেইল সত্যায়ন প্রয়োজন" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "প্রধান পাসওয়ার্ড আপডেট করা হয়েছে" + }, + "updateMasterPassword": { + "message": "প্রধান পাসওয়ার্ড আপডেট করুন" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "প্রধান পাসওয়ার্ডটি অপসারণ করুন" + }, + "removedMasterPassword": { + "message": "প্রধান পাসওয়ার্ড অপসারিত হয়েছে।" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/bs/messages.json b/apps/browser/src/_locales/bs/messages.json new file mode 100644 index 0000000000..c0fc9f75c3 --- /dev/null +++ b/apps/browser/src/_locales/bs/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "login": { + "message": "Log In" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "Cancel" + }, + "close": { + "message": "Close" + }, + "submit": { + "message": "Submit" + }, + "emailAddress": { + "message": "Email Address" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "My Vault" + }, + "tools": { + "message": "Tools" + }, + "settings": { + "message": "Settings" + }, + "currentTab": { + "message": "Current Tab" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number" + }, + "copySecurityCode": { + "message": "Copy Security Code" + }, + "autoFill": { + "message": "Auto-fill" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "Add a Login" + }, + "addItem": { + "message": "Add Item" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "Continue" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "logOut": { + "message": "Log Out" + }, + "about": { + "message": "About" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Save" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Add Folder" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Edit Folder" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "folders": { + "message": "Folders" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "Help & Feedback" + }, + "sync": { + "message": "Sync" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "Select" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Length" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "View" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favorite" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit Item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Delete Item" + }, + "viewItem": { + "message": "View Item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "Manage" + }, + "other": { + "message": "Other" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Browser Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "errorOccurred": { + "message": "An error has occurred" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "Name is required." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Save" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Update" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/ca/messages.json b/apps/browser/src/_locales/ca/messages.json new file mode 100644 index 0000000000..31b9a37f00 --- /dev/null +++ b/apps/browser/src/_locales/ca/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Administrador de contrasenyes segur i gratuït per a tots els vostres dispositius.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Inicieu sessió o creeu un compte nou per accedir a la caixa forta." + }, + "createAccount": { + "message": "Crea un compte" + }, + "login": { + "message": "Inicia sessió" + }, + "enterpriseSingleSignOn": { + "message": "Inici de sessió únic d'empresa" + }, + "cancel": { + "message": "Cancel·la" + }, + "close": { + "message": "Tanca" + }, + "submit": { + "message": "Envia" + }, + "emailAddress": { + "message": "Adreça electrònica" + }, + "masterPass": { + "message": "Contrasenya mestra" + }, + "masterPassDesc": { + "message": "La contrasenya mestra és la que utilitzeu per accedir a la vostra caixa forta. És molt important que no la oblideu. No hi ha manera de recuperar-la en cas de perdre-la." + }, + "masterPassHintDesc": { + "message": "Una pista de contrasenya mestra us pot ajudar a recordar-la si l'oblideu." + }, + "reTypeMasterPass": { + "message": "Torneu a escriure la contrasenya mestra" + }, + "masterPassHint": { + "message": "Suggeriment de la contrasenya mestra (opcional)" + }, + "tab": { + "message": "Pestanya" + }, + "myVault": { + "message": "La meua caixa forta" + }, + "tools": { + "message": "Eines" + }, + "settings": { + "message": "Configuració" + }, + "currentTab": { + "message": "Pestanya actual" + }, + "copyPassword": { + "message": "Copia contrasenya" + }, + "copyNote": { + "message": "Copia nota" + }, + "copyUri": { + "message": "Copia URI" + }, + "copyUsername": { + "message": "Copia el nom d'usuari" + }, + "copyNumber": { + "message": "Copia el número" + }, + "copySecurityCode": { + "message": "Copia el codi de seguretat" + }, + "autoFill": { + "message": "Emplenament automàtic" + }, + "generatePasswordCopied": { + "message": "Genera contrasenya (copiada)" + }, + "copyElementIdentifier": { + "message": "Copia nom del camp personalitzat" + }, + "noMatchingLogins": { + "message": "No hi ha inicis de sessió coincidents." + }, + "unlockVaultMenu": { + "message": "1. Desbloquegeu la caixa forta." + }, + "loginToVaultMenu": { + "message": "Inicia sessió a la caixa forta" + }, + "autoFillInfo": { + "message": "No hi ha cap inici de sessió disponible per omplir automàticament la pestanya del navegador actual." + }, + "addLogin": { + "message": "Afegeix un inici de sessió" + }, + "addItem": { + "message": "Afegeix element" + }, + "passwordHint": { + "message": "Pista de la contrasenya" + }, + "enterEmailToGetHint": { + "message": "Introduïu l'adreça electrònica del vostre compte per rebre la contrasenya mestra." + }, + "getMasterPasswordHint": { + "message": "Obteniu la pista de la contrasenya mestra" + }, + "continue": { + "message": "Continua" + }, + "sendVerificationCode": { + "message": "Envia un codi de verificació al correu electrònic" + }, + "sendCode": { + "message": "Envia codi" + }, + "codeSent": { + "message": "Codi enviat" + }, + "verificationCode": { + "message": "Codi de verificació" + }, + "confirmIdentity": { + "message": "Confirmeu la vostra identitat per continuar." + }, + "account": { + "message": "Compte" + }, + "changeMasterPassword": { + "message": "Canvia la contrasenya mestra" + }, + "fingerprintPhrase": { + "message": "Frase d'empremta digital", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frase d'empremta digital del vostre compte", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Inici de sessió en dues passes" + }, + "logOut": { + "message": "Tanca la sessió" + }, + "about": { + "message": "Quant a" + }, + "version": { + "message": "Versió" + }, + "save": { + "message": "Guarda" + }, + "move": { + "message": "Desplaça" + }, + "addFolder": { + "message": "Afegeix carpeta" + }, + "name": { + "message": "Nom" + }, + "editFolder": { + "message": "Edita la carpeta" + }, + "deleteFolder": { + "message": "Suprimeix carpeta" + }, + "folders": { + "message": "Carpetes" + }, + "noFolders": { + "message": "No hi ha cap carpeta a llistar." + }, + "helpFeedback": { + "message": "Ajuda i comentaris" + }, + "sync": { + "message": "Sincronització" + }, + "syncVaultNow": { + "message": "Sincronitza la caixa forta ara" + }, + "lastSync": { + "message": "Última sincronització:" + }, + "passGen": { + "message": "Generador de contrasenyes" + }, + "generator": { + "message": "Generador", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Genera automàticament contrasenyes fortes i úniques per als vostres inicis de sessió." + }, + "bitWebVault": { + "message": "Caixa forta web de Bitwarden" + }, + "importItems": { + "message": "Importa elements" + }, + "select": { + "message": "Selecciona" + }, + "generatePassword": { + "message": "Genera contrasenya" + }, + "regeneratePassword": { + "message": "Regenera contrasenya" + }, + "options": { + "message": "Opcions" + }, + "length": { + "message": "Longitud" + }, + "uppercase": { + "message": "Majúscula (A-Z)" + }, + "lowercase": { + "message": "Minúscula (a-z)" + }, + "numbers": { + "message": "Números (0-9)" + }, + "specialCharacters": { + "message": "Caràcters especials (!@#$%^&*)" + }, + "numWords": { + "message": "Nombre de paraules" + }, + "wordSeparator": { + "message": "Separador de paraules" + }, + "capitalize": { + "message": "Majúscules inicials", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inclou número" + }, + "minNumbers": { + "message": "Mínim de caràcters númerics" + }, + "minSpecial": { + "message": "Mínim de caràcters especials" + }, + "avoidAmbChar": { + "message": "Eviteu caràcters ambigus" + }, + "searchVault": { + "message": "Cerca en la caixa forta" + }, + "edit": { + "message": "Edita" + }, + "view": { + "message": "Visualitza" + }, + "noItemsInList": { + "message": "No hi ha cap element a llistar." + }, + "itemInformation": { + "message": "Informació de l'element" + }, + "username": { + "message": "Nom d'usuari" + }, + "password": { + "message": "Contrasenya" + }, + "passphrase": { + "message": "Frase de pas" + }, + "favorite": { + "message": "Preferit" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Nota" + }, + "editItem": { + "message": "Edita l'element" + }, + "folder": { + "message": "Carpeta" + }, + "deleteItem": { + "message": "Suprimeix element" + }, + "viewItem": { + "message": "Mostra element" + }, + "launch": { + "message": "Inicia" + }, + "website": { + "message": "Lloc web" + }, + "toggleVisibility": { + "message": "Commuta la visibilitat" + }, + "manage": { + "message": "Administra" + }, + "other": { + "message": "Altres" + }, + "rateExtension": { + "message": "Valora aquesta extensió" + }, + "rateExtensionDesc": { + "message": "Considereu ajudar-nos amb una bona valoració!" + }, + "browserNotSupportClipboard": { + "message": "El vostre navegador web no admet la còpia fàcil del porta-retalls. Copieu-ho manualment." + }, + "verifyIdentity": { + "message": "Verifica identitat" + }, + "yourVaultIsLocked": { + "message": "La caixa forta està bloquejada. Comproveu la contrasenya mestra per continuar." + }, + "unlock": { + "message": "Desbloqueja" + }, + "loggedInAsOn": { + "message": "Heu iniciat sessió com a $EMAIL$ en $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Contrasenya mestra no vàlida" + }, + "vaultTimeout": { + "message": "Temps d'espera de la caixa forta" + }, + "lockNow": { + "message": "Bloqueja ara" + }, + "immediately": { + "message": "Immediatament" + }, + "tenSeconds": { + "message": "10 segons" + }, + "twentySeconds": { + "message": "20 segons" + }, + "thirtySeconds": { + "message": "30 segons" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minuts" + }, + "fiveMinutes": { + "message": "5 Minuts" + }, + "fifteenMinutes": { + "message": "15 minuts" + }, + "thirtyMinutes": { + "message": "30 minuts" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 hores" + }, + "onLocked": { + "message": "En bloquejar el sistema" + }, + "onRestart": { + "message": "En reiniciar el navegador" + }, + "never": { + "message": "Mai" + }, + "security": { + "message": "Seguretat" + }, + "errorOccurred": { + "message": "S'ha produït un error" + }, + "emailRequired": { + "message": "L'adreça de correu electrònic és obligatoria." + }, + "invalidEmail": { + "message": "L'adreça de correu electrònic no és vàlida." + }, + "masterPassRequired": { + "message": "La contrasenya mestra és obligatòria." + }, + "masterPassLength": { + "message": "La contrasenya mestra ha de contenir almenys 8 caràcters." + }, + "masterPassDoesntMatch": { + "message": "La confirmació de la contrasenya mestra no coincideix." + }, + "newAccountCreated": { + "message": "El vostre compte s'ha creat correctament. Ara ja podeu iniciar sessió." + }, + "masterPassSent": { + "message": "Hem enviat un correu electrònic amb la vostra contrasenya mestra." + }, + "verificationCodeRequired": { + "message": "El codi de verificació és obligatori." + }, + "invalidVerificationCode": { + "message": "Codi de verificació no vàlid" + }, + "valueCopied": { + "message": "S'ha copiat $VALUE$", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "No es pot omplir automàticament l'element seleccionat en aquesta pàgina. Com a alternativa, copieu i enganxeu la informació." + }, + "loggedOut": { + "message": "Sessió tancada" + }, + "loginExpired": { + "message": "La vostra sessió ha caducat." + }, + "logOutConfirmation": { + "message": "Segur que voleu tancar la sessió?" + }, + "yes": { + "message": "Sí" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "S'ha produït un error inesperat." + }, + "nameRequired": { + "message": "El nom és obligatori." + }, + "addedFolder": { + "message": "Carpeta afegida" + }, + "changeMasterPass": { + "message": "Canvia la contrasenya mestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Podeu canviar la contrasenya mestra a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "twoStepLoginConfirmation": { + "message": "L'inici de sessió en dues passes fa que el vostre compte siga més segur, ja que obliga a verificar el vostre inici de sessió amb un altre dispositiu, com ara una clau de seguretat, una aplicació autenticadora, un SMS, una trucada telefònica o un correu electrònic. Es pot habilitar l'inici de sessió en dues passes a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "editedFolder": { + "message": "Carpeta editada" + }, + "deleteFolderConfirmation": { + "message": "Esteu segur que voleu suprimir aquesta carpeta?" + }, + "deletedFolder": { + "message": "Carpeta suprimida" + }, + "gettingStartedTutorial": { + "message": "Tutorial d'introducció" + }, + "gettingStartedTutorialVideo": { + "message": "Mireu el nostre tutorial sobre com aprendre a aprofitar al màxim l'extensió del navegador." + }, + "syncingComplete": { + "message": "S'ha completat la sincronització" + }, + "syncingFailed": { + "message": "Ha fallat la sincronització" + }, + "passwordCopied": { + "message": "S'ha copiat la contrasenya" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nova URI" + }, + "addedItem": { + "message": "Element afegit" + }, + "editedItem": { + "message": "Element editat" + }, + "deleteItemConfirmation": { + "message": "Esteu segur que voleu suprimir aquest element?" + }, + "deletedItem": { + "message": "Element suprimit" + }, + "overwritePassword": { + "message": "Sobreescriu la contrasenya" + }, + "overwritePasswordConfirmation": { + "message": "Esteu segur que voleu sobreescriure la contrasenya actual?" + }, + "overwriteUsername": { + "message": "Sobrescriu el nom d'usuari" + }, + "overwriteUsernameConfirmation": { + "message": "Segur que voleu sobreescriure el nom d'usuari actual?" + }, + "searchFolder": { + "message": "Cerca la carpeta" + }, + "searchCollection": { + "message": "Cerca la col·lecció" + }, + "searchType": { + "message": "Cerca el tipus" + }, + "noneFolder": { + "message": "Cap carpeta", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Deshabilita la notificació per afegir inicis de sessió" + }, + "addLoginNotificationDesc": { + "message": "La \"Notificació per afegir inicis de sessió\" demana automàticament que guardeu els nous inicis de sessió a la vostra caixa forta quan inicieu la sessió per primera vegada." + }, + "dontShowCardsCurrentTab": { + "message": "No mostres les targetes a la pàgina de la pestanya" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Els elements de targeta de la vostra caixa forta es detallen a la pàgina \"Fitxa actual\" per obtenir un fàcil accés amb l'emplenat automàtic." + }, + "dontShowIdentitiesCurrentTab": { + "message": "No mostres les identitats a la pàgina de la pestanya" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Els elements d'identitat de la vostra caixa forta es detallen a la pàgina \"Fitxa actual\" per obtenir un fàcil accés amb l'emplenat automàtic." + }, + "clearClipboard": { + "message": "Neteja el porta-retalls", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Esborra automàticament els valors copiats del porta-retalls.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Bitwarden ha de recordar aquesta contrasenya per a vosaltres?" + }, + "notificationAddSave": { + "message": "Guarda" + }, + "disableChangedPasswordNotification": { + "message": "Deshabilita la notificació de contrasenya modificada" + }, + "disableChangedPasswordNotificationDesc": { + "message": "La \"Notificació de contrasenya modificada\" us demanarà automàticament que actualitzeu la contrasenya d'inici de sessió a la vostra caixa forta cada vegada que detecte que s'ha canviat en un lloc web." + }, + "notificationChangeDesc": { + "message": "Voleu actualitzar aquesta contrasenya a Bitwarden?" + }, + "notificationChangeSave": { + "message": "Actualitza" + }, + "disableContextMenuItem": { + "message": "Inhabilita opcions del menú contextual" + }, + "disableContextMenuItemDesc": { + "message": "Les opcions del menú contextual proporcionen accés ràpid a la generació de contrasenyes i inici de sessió al lloc web en la vostra pestanya actual." + }, + "defaultUriMatchDetection": { + "message": "Detecció de coincidències URI per defecte", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Trieu la manera predeterminada en que es gestiona la detecció de coincidència d'URI per als inicis de sessió en realitzar accions com l'emplenament automàtic." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Canvia el color del tema de l'aplicació." + }, + "dark": { + "message": "Fosc", + "description": "Dark color" + }, + "light": { + "message": "Clar", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solaritzat fosc", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Exporta caixa forta" + }, + "fileFormat": { + "message": "Format de fitxer" + }, + "warning": { + "message": "ADVERTIMENT", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirma l'exportació de la Caixa forta" + }, + "exportWarningDesc": { + "message": "Aquesta exportació conté les dades de la vostra caixa forta en un format no xifrat. No hauríeu d'emmagatzemar o enviar el fitxer exportat a través de canals no segurs (com ara el correu electrònic). Elimineu-lo immediatament després d'haver acabat d'usar-lo." + }, + "encExportKeyWarningDesc": { + "message": "Aquesta exportació xifra les vostres dades mitjançant la clau de xifratge del vostre compte. Si alguna vegada gireu eixa clau, hauríeu d'exportar de nou, ja que no podreu desxifrar aquest fitxer d'exportació." + }, + "encExportAccountWarningDesc": { + "message": "Les claus de xifratge són exclusives de cada compte d'usuari Bitwarden, de manera que no podeu importar una exportació xifrada a un compte diferent." + }, + "exportMasterPassword": { + "message": "Introduïu la contrasenya mestra per exportar les dades de la caixa forta." + }, + "shared": { + "message": "Compartit" + }, + "learnOrg": { + "message": "Més informació sobre les organitzacions" + }, + "learnOrgConfirmation": { + "message": "Bitwarden us permet compartir els elements de la vostra caixa forta amb altres usuaris mitjançant una organització. Voleu visitar el lloc web de bitwarden.com per obtenir més informació?" + }, + "moveToOrganization": { + "message": "Desplaça a l'organització" + }, + "share": { + "message": "Comparteix" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ desplaçat a $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Trieu una organització a la qual vulgueu desplaçar aquest element. El trasllat a una organització transfereix la propietat de l'element a aquesta organització. Ja no sereu el propietari directe d'aquest element una vegada s'haja mogut." + }, + "learnMore": { + "message": "Més informació" + }, + "authenticatorKeyTotp": { + "message": "Clau d'autenticació (TOTP)" + }, + "verificationCodeTotp": { + "message": "Codi de verificació (TOTP)" + }, + "copyVerificationCode": { + "message": "Copia el codi de verificació" + }, + "attachments": { + "message": "Adjunts" + }, + "deleteAttachment": { + "message": "Suprimeix l'adjunt" + }, + "deleteAttachmentConfirmation": { + "message": "Esteu segur que voleu suprimir aquest adjunt?" + }, + "deletedAttachment": { + "message": "Adjunt suprimit" + }, + "newAttachment": { + "message": "Afegeix un adjunt nou" + }, + "noAttachments": { + "message": "No hi ha cap adjunt." + }, + "attachmentSaved": { + "message": "S'ha guardat el fitxer adjunt." + }, + "file": { + "message": "Fitxer" + }, + "selectFile": { + "message": "Seleccioneu un fitxer." + }, + "maxFileSize": { + "message": "La mida màxima del fitxer és de 500 MB." + }, + "featureUnavailable": { + "message": "Característica no disponible" + }, + "updateKey": { + "message": "No podeu utilitzar aquesta característica fins que actualitzeu la vostra clau de xifratge." + }, + "premiumMembership": { + "message": "Subscripció Premium" + }, + "premiumManage": { + "message": "Administra la subscripció" + }, + "premiumManageAlert": { + "message": "Podeu administrar la vostra subscripció a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "premiumRefresh": { + "message": "Actualitza la subscripció" + }, + "premiumNotCurrentMember": { + "message": "No sou actualment un membre premium." + }, + "premiumSignUpAndGet": { + "message": "Inscriviu-vos per una subscripció premium i obteniu:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB d'emmagatzematge xifrat per als fitxers adjunts." + }, + "ppremiumSignUpTwoStep": { + "message": "Opcions addicionals d'inici de sessió en dues passes com ara YubiKey, FIDO U2F i Duo." + }, + "ppremiumSignUpReports": { + "message": "Requisits d'higiene de la contrasenya, salut del compte i informe d'infraccions de dades per mantenir la seguretat de la vostra caixa forta." + }, + "ppremiumSignUpTotp": { + "message": "Generador de codi de verificació TOTP (2FA) per a inici de sessió a la vostra caixa forta." + }, + "ppremiumSignUpSupport": { + "message": "Prioritat d'atenció al client." + }, + "ppremiumSignUpFuture": { + "message": "Totes les funcions premium futures. Aviat, més!" + }, + "premiumPurchase": { + "message": "Compra Premium" + }, + "premiumPurchaseAlert": { + "message": "Podeu comprar la vostra subscripció a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "premiumCurrentMember": { + "message": "Sou un membre premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Gràcies per donar suport a Bitwarden." + }, + "premiumPrice": { + "message": "Tot per només $PRICE$ / any!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Actualització completa" + }, + "disableAutoTotpCopy": { + "message": "Deshabilita la còpia TOTP automàtica" + }, + "disableAutoTotpCopyDesc": { + "message": "Si el vostre inici de sessió té una clau d'autenticació associada, el codi de verificació TOTP es copiarà al vostre porta-retalls quan s'òmpliga automàticament l'inici de sessió." + }, + "disableAutoBiometricsPrompt": { + "message": "No sol·liciteu biomètrica en iniciar." + }, + "premiumRequired": { + "message": "Premium requerit" + }, + "premiumRequiredDesc": { + "message": "Cal una subscripció premium per utilitzar aquesta característica." + }, + "enterVerificationCodeApp": { + "message": "Introduïu el codi de verificació de 6 dígits de l'aplicació autenticadora." + }, + "enterVerificationCodeEmail": { + "message": "Introduïu el codi de verificació de 6 dígits que s'ha enviat per correu electrònic a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Correu electrònic de verificació enviat a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Recorda'm" + }, + "sendVerificationCodeEmailAgain": { + "message": "Envia el codi de verificació altra vegada" + }, + "useAnotherTwoStepMethod": { + "message": "Utilitzeu un altre mètode d'inici de sessió en dues passes" + }, + "insertYubiKey": { + "message": "Introduïu la vostra YubiKey al port USB de l'ordinador i, a continuació, premeu el seu botó." + }, + "insertU2f": { + "message": "Introduïu la vostra clau de seguretat al port USB de l'ordinador. Si té un botó, premeu-lo." + }, + "webAuthnNewTab": { + "message": "\nPer iniciar la verificació de WebAuthn 2FA. Feu clic al botó següent per obrir una pestanya nova i seguiu les instruccions d'aquesta." + }, + "webAuthnNewTabOpen": { + "message": "Obri una pestanya nova" + }, + "webAuthnAuthenticate": { + "message": "Autenticar WebAuthn" + }, + "loginUnavailable": { + "message": "Inici de sessió no disponible" + }, + "noTwoStepProviders": { + "message": "Aquest compte té habilitat l'inici de sessió en dues passes, però aquest navegador web no admet cap dels dos proveïdors configurats." + }, + "noTwoStepProviders2": { + "message": "Utilitzeu un navegador web compatible (com ara Chrome) o afegiu proveïdors addicionals que siguen compatibles amb tots els navegadors web (com una aplicació d'autenticació)." + }, + "twoStepOptions": { + "message": "Opcions d'inici de sessió en dues passes" + }, + "recoveryCodeDesc": { + "message": "Heu perdut l'accés a tots els vostres proveïdors de dos factors? Utilitzeu el vostre codi de recuperació per desactivar tots els proveïdors de dos factors del vostre compte." + }, + "recoveryCodeTitle": { + "message": "Codi de recuperació" + }, + "authenticatorAppTitle": { + "message": "Aplicació autenticadora" + }, + "authenticatorAppDesc": { + "message": "Utilitzeu una aplicació autenticadora (com Authy o Google Authenticator) per generar codis de verificació basats en el temps.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Clau de seguretat OTP de YubiKey" + }, + "yubiKeyDesc": { + "message": "Utilitzeu una YubiKey per accedir al vostre compte. Funciona amb els dispositius YubiKey 4, 4 Nano, 4C i NEO." + }, + "duoDesc": { + "message": "Verifiqueu amb Duo Security mitjançant l'aplicació Duo Mobile, SMS, trucada telefònica o clau de seguretat U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifiqueu amb Duo Security per a la vostra organització mitjançant l'aplicació Duo Mobile, SMS, trucada telefònica o clau de seguretat U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Utilitzeu qualsevol clau de seguretat habilitada per WebAuthn per accedir al vostre compte." + }, + "emailTitle": { + "message": "Correu electrònic" + }, + "emailDesc": { + "message": "Els codis de verificació els rebreu per correu electrònic." + }, + "selfHostedEnvironment": { + "message": "Entorn d'allotjament propi" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifiqueu l'URL base de la vostra instal·lació de Bitwarden allotjada en un entorn propi." + }, + "customEnvironment": { + "message": "Entorn personalitzat" + }, + "customEnvironmentFooter": { + "message": "Per a usuaris avançats. Podeu especificar l'URL base de cada servei independentment." + }, + "baseUrl": { + "message": "URL del servidor" + }, + "apiUrl": { + "message": "URL del servidor API" + }, + "webVaultUrl": { + "message": "URL del servidor de la caixa forta web" + }, + "identityUrl": { + "message": "URL del servidor d'identitat" + }, + "notificationsUrl": { + "message": "URL del servidor de notificacions" + }, + "iconsUrl": { + "message": "URL del servidor d'icones" + }, + "environmentSaved": { + "message": "S'han guardat les URL de l'entorn." + }, + "enableAutoFillOnPageLoad": { + "message": "Habilita l'emplenament automàtic en carregar la pàgina" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Si es detecta un formulari d'inici de sessió, es realitza automàticament un emplenament automàtic quan es carrega la pàgina web." + }, + "experimentalFeature": { + "message": "Actualment és una característica experimental. Utilitzeu sota el vostre propi risc." + }, + "defaultAutoFillOnPageLoad": { + "message": "Configuració per defecte d'emplenament automàtic per als elements d'inici de sessió" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Després d'habilitar l'emplenament automàtic a la càrrega de la pàgina, podeu habilitar o inhabilitar la característica per a elements d'inici de sessió individuals. Aquesta és la configuració per defecte per als elements d'inici de sessió que no estan configurats per separat." + }, + "itemAutoFillOnPageLoad": { + "message": "Emplenament automàtic a la càrrega de la pàgina (si està habilitat a Opcions)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Utilitza la configuració per defecte" + }, + "autoFillOnPageLoadYes": { + "message": "Emplenament automàtic a la càrrega de la pàgina" + }, + "autoFillOnPageLoadNo": { + "message": "No s'emplena automàticament a la càrrega de la pàgina" + }, + "commandOpenPopup": { + "message": "Obri l'emergent de la caixa forta" + }, + "commandOpenSidebar": { + "message": "Obri la caixa forta a la barra lateral" + }, + "commandAutofillDesc": { + "message": "Ompliu automàticament amb l'últim accés utilitzat per al lloc web actual." + }, + "commandGeneratePasswordDesc": { + "message": "Genera i copia una nova contrasenya aleatòria al porta-retalls." + }, + "commandLockVaultDesc": { + "message": "Tanca la caixa forta" + }, + "privateModeWarning": { + "message": "El suport del mode privat és experimental i algunes funcions són limitades." + }, + "customFields": { + "message": "Camps personalitzats" + }, + "copyValue": { + "message": "Copia el valor" + }, + "value": { + "message": "Valor" + }, + "newCustomField": { + "message": "Camp nou personalitzat" + }, + "dragToSort": { + "message": "Arrossega per ordenar" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Amagat" + }, + "cfTypeBoolean": { + "message": "Booleà" + }, + "cfTypeLinked": { + "message": "Enllaçat", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Valor enllaçat", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Si feu clic a l'exterior de la finestra emergent per comprovar el vostre correu electrònic amb el codi de verificació, es tancarà aquesta finestra. Voleu obrir aquesta finestra emergent en una finestra nova perquè no es tanque?" + }, + "popupU2fCloseMessage": { + "message": "Aquest navegador no pot processar sol·licituds U2F en aquesta finestra emergent. Voleu obrir l'emergent en una finestra nova per poder iniciar la sessió mitjançant U2F?" + }, + "disableFavicon": { + "message": "Deshabilitar icones del lloc web" + }, + "disableFaviconDesc": { + "message": "Les icones del lloc web proporcionen una imatge que es pot reconèixer al costat de cada element d'inici de sessió a la vostra caixa forta." + }, + "disableBadgeCounter": { + "message": "Deshabilita el comptador d'insígnies" + }, + "disableBadgeCounterDesc": { + "message": "El comptador d’insígnies indica quants inicis de sessió teniu de la pàgina actual en la vostra caixa forta." + }, + "cardholderName": { + "message": "Nom del titular de la targeta" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Marca" + }, + "expirationMonth": { + "message": "Mes de venciment" + }, + "expirationYear": { + "message": "Any de venciment" + }, + "expiration": { + "message": "Caducitat" + }, + "january": { + "message": "Gener" + }, + "february": { + "message": "Febrer" + }, + "march": { + "message": "Març" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Maig" + }, + "june": { + "message": "Juny" + }, + "july": { + "message": "Juliol" + }, + "august": { + "message": "Agost" + }, + "september": { + "message": "Setembre" + }, + "october": { + "message": "Octubre" + }, + "november": { + "message": "Novembre" + }, + "december": { + "message": "Desembre" + }, + "securityCode": { + "message": "Codi de seguretat" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Títol" + }, + "mr": { + "message": "Sr." + }, + "mrs": { + "message": "Sra." + }, + "ms": { + "message": "Srta." + }, + "dr": { + "message": "Dr." + }, + "firstName": { + "message": "Nom" + }, + "middleName": { + "message": "Segon nom" + }, + "lastName": { + "message": "Cognoms" + }, + "fullName": { + "message": "Nom complet" + }, + "identityName": { + "message": "Nom d'identitat" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Número de la Seguretat Social" + }, + "passportNumber": { + "message": "Número de passaport" + }, + "licenseNumber": { + "message": "Número de llicència" + }, + "email": { + "message": "Correu electrònic" + }, + "phone": { + "message": "Telèfon" + }, + "address": { + "message": "Adreça" + }, + "address1": { + "message": "Adreça 1" + }, + "address2": { + "message": "Adreça 2" + }, + "address3": { + "message": "Adreça 3" + }, + "cityTown": { + "message": "Localitat" + }, + "stateProvince": { + "message": "Estat/província" + }, + "zipPostalCode": { + "message": "Codi postal" + }, + "country": { + "message": "País" + }, + "type": { + "message": "Tipus" + }, + "typeLogin": { + "message": "Inici de sessió" + }, + "typeLogins": { + "message": "Inicis de sessió" + }, + "typeSecureNote": { + "message": "Nota segura" + }, + "typeCard": { + "message": "Targeta" + }, + "typeIdentity": { + "message": "Identitat" + }, + "passwordHistory": { + "message": "Historial de les contrasenyes" + }, + "back": { + "message": "Arrere" + }, + "collections": { + "message": "Col·leccions" + }, + "favorites": { + "message": "Preferits" + }, + "popOutNewWindow": { + "message": "Obri en una finestra nova" + }, + "refresh": { + "message": "Actualitza" + }, + "cards": { + "message": "Targetes" + }, + "identities": { + "message": "Identitats" + }, + "logins": { + "message": "Inicis de sessió" + }, + "secureNotes": { + "message": "Notes segures" + }, + "clear": { + "message": "Esborra", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Comprova si la contrasenya ha estat exposada." + }, + "passwordExposed": { + "message": "Aquesta contrasenya ha estat exposada $VALUE$ vegades en errors de seguretat de dades. Heu de canviar-la.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Aquesta contrasenya no s'ha trobat en cap filtració de dades coneguda. Hauries de poder utilitzar-la de manera segura." + }, + "baseDomain": { + "message": "Domini base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nom del domini", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Amfitrió", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exacte" + }, + "startsWith": { + "message": "Comença amb" + }, + "regEx": { + "message": "Expressió regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Detecció de coincidències", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detecció de coincidències per defecte", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Commuta opcions" + }, + "toggleCurrentUris": { + "message": "Commuta URI actuals", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI actual", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organització", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tipus" + }, + "allItems": { + "message": "Tots els elements" + }, + "noPasswordsInList": { + "message": "No hi ha cap contrasenya a llistar." + }, + "remove": { + "message": "Suprimeix" + }, + "default": { + "message": "Per defecte" + }, + "dateUpdated": { + "message": "Actualitzat", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Contrasenya actualitzada", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Esteu segur que voleu utilitzar l'opció \"Mai\"? En configurar les opcions de bloqueig a \"Mai\" s'emmagatzema la clau de xifratge de la vostra caixa forta al vostre dispositiu. Si utilitzeu aquesta opció, heu d'assegurar-vos que conserveu el dispositiu degudament protegit." + }, + "noOrganizationsList": { + "message": "No pertanyeu a cap organització. Les organitzacions permeten compartir elements amb seguretat amb altres usuaris." + }, + "noCollectionsInList": { + "message": "No hi ha cap col·lecció a llistar." + }, + "ownership": { + "message": "Propietat" + }, + "whoOwnsThisItem": { + "message": "Qui és propietari d'aquest element?" + }, + "strong": { + "message": "Forta", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bona", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Poc segura", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Contrasenya mestra poc segura" + }, + "weakMasterPasswordDesc": { + "message": "La contrasenya mestra que heu triat és poc segura. Heu d'utilitzar una contrasenya mestra segura (o una frase de pas) per protegir correctament el vostre compte de Bitwarden. Esteu segur que voleu utilitzar aquesta contrasenya mestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloqueja amb codi PIN" + }, + "setYourPinCode": { + "message": "Configureu el vostre codi PIN per desbloquejar Bitwarden. La configuració del PIN es restablirà si tanqueu la sessió definitivament." + }, + "pinRequired": { + "message": "Es necessita el codi PIN." + }, + "invalidPin": { + "message": "El codi PIN no és vàlid." + }, + "unlockWithBiometrics": { + "message": "Desbloqueja amb biomètrica" + }, + "awaitDesktop": { + "message": "S’espera confirmació des de l’escriptori" + }, + "awaitDesktopDesc": { + "message": "Confirmeu que utilitzeu la biomètrica a l'aplicació Bitwarden Desktop per habilitar la biomètrica per al navegador." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloqueja amb la contrasenya mestra en reiniciar el navegador" + }, + "selectOneCollection": { + "message": "Heu d'escollir com a mínim una col·lecció." + }, + "cloneItem": { + "message": "Clona l'element" + }, + "clone": { + "message": "Clona" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una o més polítiques d’organització afecten la configuració del generador." + }, + "vaultTimeoutAction": { + "message": "Acció del temps d'espera de la caixa forta" + }, + "lock": { + "message": "Bloqueja", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Paperera", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Cerca a la paperera" + }, + "permanentlyDeleteItem": { + "message": "Element suprimit definitivament" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Esteu segur que voleu suprimir aquest element definitivament?" + }, + "permanentlyDeletedItem": { + "message": "Element suprimit definitivament" + }, + "restoreItem": { + "message": "Restaura l'element" + }, + "restoreItemConfirmation": { + "message": "Esteu segur que voleu restaurar aquest element?" + }, + "restoredItem": { + "message": "Element restaurat" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "En tancar la sessió s'eliminarà tot l'accés a la vostra caixa forta i es requerirà una autenticació en línia després del període de temps d'espera. Esteu segur que voleu utilitzar aquesta configuració?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmació de l’acció de temps d'espera de la caixa forta" + }, + "autoFillAndSave": { + "message": "Ompli automàticament i guarda" + }, + "autoFillSuccessAndSavedUri": { + "message": "Element emplenat automàticament i URI guardat" + }, + "autoFillSuccess": { + "message": "Element emplenat automàticament " + }, + "setMasterPassword": { + "message": "Estableix la contrasenya mestra" + }, + "masterPasswordPolicyInEffect": { + "message": "Una o més polítiques d’organització requereixen que la vostra contrasenya principal complisca els requisits següents:" + }, + "policyInEffectMinComplexity": { + "message": "Puntuació mínima de complexitat de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Longitud mínima de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Conté un o més caràcters en majúscula" + }, + "policyInEffectLowercase": { + "message": "Conté un o més caràcters en minúscula" + }, + "policyInEffectNumbers": { + "message": "Conté un o més números" + }, + "policyInEffectSpecial": { + "message": "Conté un o més dels següents caràcters especials $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "La nova contrasenya principal no compleix els requisits de la política." + }, + "acceptPolicies": { + "message": "Si activeu aquesta casella, indiqueu que esteu d’acord amb el següent:" + }, + "acceptPoliciesError": { + "message": "No s’han reconegut les condicions del servei i la declaració de privadesa." + }, + "termsOfService": { + "message": "Condicions del servei" + }, + "privacyPolicy": { + "message": "Declaració de privadesa" + }, + "hintEqualsPassword": { + "message": "El vostre suggeriment de contrasenya no pot ser el mateix que la vostra contrasenya." + }, + "ok": { + "message": "D’acord" + }, + "desktopSyncVerificationTitle": { + "message": "Verificació de sincronització d'escriptori" + }, + "desktopIntegrationVerificationText": { + "message": "Verifiqueu que l'aplicació d'escriptori mostre aquesta empremta digital:" + }, + "desktopIntegrationDisabledTitle": { + "message": "La integració en el navegador no està habilitada" + }, + "desktopIntegrationDisabledDesc": { + "message": "La integració del navegador no està habilitada a l'aplicació Bitwarden Desktop. Activeu-la a la configuració de l'aplicació d'escriptori." + }, + "startDesktopTitle": { + "message": "Inicia l'aplicació Bitwarden Desktop" + }, + "startDesktopDesc": { + "message": "Per poder utilitzar aquesta funció, cal iniciar l'aplicació Bitwarden Desktop." + }, + "errorEnableBiometricTitle": { + "message": "No es pot habilitar la biomètrica" + }, + "errorEnableBiometricDesc": { + "message": "L'aplicació d'escriptori ha cancel·lat l'acció" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "L'aplicació d'escriptori ha invalidat el canal de comunicació segur. Torneu a provar aquesta operació" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "S'ha interromput la comunicació d'escriptori" + }, + "nativeMessagingWrongUserDesc": { + "message": "L'aplicació d'escriptori està iniciada en un compte diferent. Assegureu-vos que totes dues aplicacions estiguen connectades al mateix compte." + }, + "nativeMessagingWrongUserTitle": { + "message": "El compte no coincideix" + }, + "biometricsNotEnabledTitle": { + "message": "La biomètrica no està habilitada" + }, + "biometricsNotEnabledDesc": { + "message": "La biometria del navegador primer necessita habilitar la biomètrica d’escriptori a la configuració." + }, + "biometricsNotSupportedTitle": { + "message": "La biomètrica no és compatible" + }, + "biometricsNotSupportedDesc": { + "message": "La biometria del navegador no és compatible amb aquest dispositiu." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "No s'ha proporcionat el permís" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Sense permís per comunicar-nos amb l’aplicació d’escriptori Bitwarden, no podem proporcionar dades biomètriques a l’extensió del navegador. Torneu-ho a provar." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Error de sol·licitud de permís" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Aquesta acció no es pot fer a la barra lateral, torneu-ho a provar a la finestra emergent o l'emergent." + }, + "personalOwnershipSubmitError": { + "message": "A causa d'una política empresarial, no podeu guardar elements a la vostra caixa forta personal. Canvieu l'opció Propietat en organització i trieu entre les col·leccions disponibles." + }, + "personalOwnershipPolicyInEffect": { + "message": "Una política d’organització afecta les vostres opcions de propietat." + }, + "excludedDomains": { + "message": "Dominis exclosos" + }, + "excludedDomainsDesc": { + "message": "Bitwarden no demanarà que es guarden les dades d’inici de sessió d’aquests dominis. Heu d'actualitzar la pàgina perquè els canvis tinguen efecte." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ no és un domini vàlid", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Cerca Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Afig Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "Fitxer" + }, + "allSends": { + "message": "Tots els Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "S'ha assolit el recompte màxim d'accesos", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Caducat" + }, + "pendingDeletion": { + "message": "Pendent de supressió" + }, + "passwordProtected": { + "message": "Protegit amb contrasenya" + }, + "copySendLink": { + "message": "Copia l'enllaç Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Suprimeix la contrasenya" + }, + "delete": { + "message": "Suprimeix" + }, + "removedPassword": { + "message": "Contrasenya suprimida" + }, + "deletedSend": { + "message": "Send suprimit", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Enllaç Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Deshabilitat" + }, + "removePasswordConfirmation": { + "message": "Esteu segur que voleu suprimir la contrasenya?" + }, + "deleteSend": { + "message": "Suprimeix el Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Esteu segur que voleu suprimir aquest Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edita Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Quin tipus de Send és aquest?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Un nom apropiat per descriure aquest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "El fitxer que voleu enviar." + }, + "deletionDate": { + "message": "Data de supressió" + }, + "deletionDateDesc": { + "message": "L'enviament se suprimirà permanentment a la data i hora especificades.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data de caducitat" + }, + "expirationDateDesc": { + "message": "Si s'estableix, l'accés a aquest enviament caducarà en la data i hora especificades.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dia" + }, + "days": { + "message": "$DAYS$ dies", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Personalitzat" + }, + "maximumAccessCount": { + "message": "Recompte màxim d'accessos" + }, + "maximumAccessCountDesc": { + "message": "Si s’estableix, els usuaris ja no podran accedir a aquest Send una vegada s’assolisca el nombre màxim d’accessos.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcionalment, necessiteu una contrasenya perquè els usuaris accedisquen a aquest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notes privades sobre aquest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Desactiveu aquest Send perquè ningú no hi puga accedir.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copieu l'enllaç d'aquest Send al porta-retalls després de guardar-lo.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "El text que voleu enviar." + }, + "sendHideText": { + "message": "Amaga el text d'aquest Send per defecte.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Recompte d’accessos actual" + }, + "createSend": { + "message": "Crea un nou Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Contrasenya nova" + }, + "sendDisabled": { + "message": "Send desactivat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "A causa d'una política empresarial, només podeu suprimir un Send existent.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send creat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send editat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Per triar un fitxer, obriu l'extensió a la barra lateral (si és possible) o eixiu a una finestra nova fent clic a aquest bàner." + }, + "sendFirefoxFileWarning": { + "message": "Per triar un fitxer mitjançant Firefox, obriu l'extensió a la barra lateral o bé apareixerà a una finestra nova fent clic a aquest bàner." + }, + "sendSafariFileWarning": { + "message": "Per triar un fitxer mitjançant Safari, eixiu a una finestra nova fent clic en aquest bàner." + }, + "sendFileCalloutHeader": { + "message": "Abans de començar" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Per utilitzar un selector de dates d'estil calendari", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "feu clic ací", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "per eixir de la finestra.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "La data de caducitat proporcionada no és vàlida." + }, + "deletionDateIsInvalid": { + "message": "La data de supressió proporcionada no és vàlida." + }, + "expirationDateAndTimeRequired": { + "message": "Requereix una data i hora de caducitat." + }, + "deletionDateAndTimeRequired": { + "message": "Requereix una data i hora de supressió." + }, + "dateParsingError": { + "message": "S'ha produït un error en guardar les dates de supressió i caducitat." + }, + "hideEmail": { + "message": "Amagueu la meua adreça de correu electrònic als destinataris." + }, + "sendOptionsPolicyInEffect": { + "message": "Una o més polítiques d'organització afecten les vostres opcions del Send." + }, + "passwordPrompt": { + "message": "Sol·licitud de la contrasenya mestra" + }, + "passwordConfirmation": { + "message": "Confirmació de la contrasenya mestra" + }, + "passwordConfirmationDesc": { + "message": "Aquesta acció està protegida. Per continuar, torneu a introduir la contrasenya principal per verificar la vostra identitat." + }, + "emailVerificationRequired": { + "message": "Es requereix verificació del correu electrònic" + }, + "emailVerificationRequiredDesc": { + "message": "Heu de verificar el correu electrònic per utilitzar aquesta característica. Podeu verificar el vostre correu electrònic a la caixa forta web." + }, + "updatedMasterPassword": { + "message": "Contrasenya mestra actualitzada" + }, + "updateMasterPassword": { + "message": "Actualitza contrasenya mestra" + }, + "updateMasterPasswordWarning": { + "message": "Un administrador de l'organització ha canviat recentment la contrasenya principal. Per accedir a la caixa forta, heu d'actualitzar-la ara. Si continueu, es tancarà la sessió actual i heu de tornar a iniciar-la. És possible que les sessions obertes en altres dispositius continuen actives fins a una hora." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscripció automàtica" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Aquesta organització té una política empresarial que us inscriurà automàticament al restabliment de la contrasenya. La inscripció permetrà als administradors de l’organització canviar la vostra contrasenya mestra." + }, + "selectFolder": { + "message": "Seleccioneu la carpeta..." + }, + "ssoCompleteRegistration": { + "message": "Per completar la sessió amb SSO, configureu una contrasenya mestra per accedir i protegir la vostra caixa forta." + }, + "hours": { + "message": "Hores" + }, + "minutes": { + "message": "Minuts" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Les polítiques de l'organització afecten el temps d'espera de la caixa forta. El temps d'espera màxim permès d'aquesta és de $HOURS$ hores i $MINUTES$ minuts", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "El temps d'espera de la caixa forta supera les restriccions establertes per la vostra organització." + }, + "vaultExportDisabled": { + "message": "L'exportació de la caixa forta està desactivada" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una o més polítiques d'organització us impedeixen exportar la vostra caixa forta." + }, + "copyCustomFieldNameInvalidElement": { + "message": "No es pot identificar un element de formulari vàlid. Proveu d'inspeccionar l'HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "No s'ha trobat cap identificador únic." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ està utilitzant SSO amb un servidor autoallotjat de claus. Ja no es requereix una contrasenya mestra d'inici de sessió per als membres d'aquesta organització.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Abandona organització" + }, + "removeMasterPassword": { + "message": "Suprimiu la contrasenya mestra" + }, + "removedMasterPassword": { + "message": "S'ha suprimit la contrasenya mestra" + }, + "leaveOrganizationConfirmation": { + "message": "Segur que voleu abandonar aquesta organització?" + }, + "leftOrganization": { + "message": "Heu deixat l'organització." + }, + "toggleCharacterCount": { + "message": "Commuta el recompte de caràcters" + }, + "sessionTimeout": { + "message": "La sessió ha expirat. Torneu arrere i proveu d'iniciar sessió de nou." + }, + "exportingPersonalVaultTitle": { + "message": "S'està exportant la caixa forta personal" + }, + "exportingPersonalVaultDescription": { + "message": "Només s'exportaran els elements personals de la caixa forta associats a $EMAIL$. Els elements de la caixa forta de l'organització no s'inclouran.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenera el nom d'usuari" + }, + "generateUsername": { + "message": "Genera un nom d'usuari" + }, + "usernameType": { + "message": "Tipus de nom d'usuari" + }, + "plusAddressedEmail": { + "message": "Adreça amb sufix", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Aleatori" + }, + "randomWord": { + "message": "Paraula aleatòria" + }, + "websiteName": { + "message": "Nom del lloc web" + }, + "whatWouldYouLikeToGenerate": { + "message": "Què voleu generar?" + }, + "passwordType": { + "message": "Tipus de contrasenya" + }, + "service": { + "message": "Servei" + } +} diff --git a/apps/browser/src/_locales/cs/messages.json b/apps/browser/src/_locales/cs/messages.json new file mode 100644 index 0000000000..e1de780a93 --- /dev/null +++ b/apps/browser/src/_locales/cs/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden – Bezplatný správce hesel", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bezpečný a bezplatný správce hesel pro všechna vaše zařízení.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Pro přístup do vašeho bezpečného trezoru se přihlašte nebo si vytvořte nový účet." + }, + "createAccount": { + "message": "Vytvořit účet" + }, + "login": { + "message": "Přihlásit se" + }, + "enterpriseSingleSignOn": { + "message": "Jednotné podnikové přihlášení" + }, + "cancel": { + "message": "Zrušit" + }, + "close": { + "message": "Zavřít" + }, + "submit": { + "message": "Potvrdit" + }, + "emailAddress": { + "message": "E-mailová adresa" + }, + "masterPass": { + "message": "Hlavní heslo" + }, + "masterPassDesc": { + "message": "Hlavní heslo je heslo, které používáte k přístupu do vašeho trezoru. Je velmi důležité, abyste jej nezapomněli. Neexistuje totiž žádný způsob, jak heslo obnovit v případě, že jste na něj zapomněli." + }, + "masterPassHintDesc": { + "message": "Nápověda k hlavnímu heslu vám pomůže zapamatovat si heslo, pokud ho zapomenete." + }, + "reTypeMasterPass": { + "message": "Znovu zadejte hlavní heslo" + }, + "masterPassHint": { + "message": "Nápověda k hlavnímu heslu (volitelné)" + }, + "tab": { + "message": "Karta" + }, + "myVault": { + "message": "Můj trezor" + }, + "tools": { + "message": "Nástroje" + }, + "settings": { + "message": "Nastavení" + }, + "currentTab": { + "message": "Aktuální karta" + }, + "copyPassword": { + "message": "Kopírovat heslo" + }, + "copyNote": { + "message": "Kopírovat poznámku" + }, + "copyUri": { + "message": "Kopírovat URI" + }, + "copyUsername": { + "message": "Kopírovat uživatelské jméno" + }, + "copyNumber": { + "message": "Kopírovat číslo" + }, + "copySecurityCode": { + "message": "Kopírovat bezpečnostní kód" + }, + "autoFill": { + "message": "Automatické vyplnění" + }, + "generatePasswordCopied": { + "message": "Vygenerovat heslo a zkopírovat do schránky" + }, + "copyElementIdentifier": { + "message": "Kopírovat název vlastního pole" + }, + "noMatchingLogins": { + "message": "Žádné odpovídající přihlašovací údaje." + }, + "unlockVaultMenu": { + "message": "Odemknout váš trezor" + }, + "loginToVaultMenu": { + "message": "Přihlaste se do svého trezoru" + }, + "autoFillInfo": { + "message": "Pro aktuální stránku neexistují žádné přihlašovací údaje." + }, + "addLogin": { + "message": "Přidat přihlašovací údaje" + }, + "addItem": { + "message": "Přidat položku" + }, + "passwordHint": { + "message": "Nápověda k heslu" + }, + "enterEmailToGetHint": { + "message": "Zadejte e-mailovou adresu pro zaslání nápovědy k hlavnímu heslu." + }, + "getMasterPasswordHint": { + "message": "Zaslat nápovědu k hlavnímu heslu" + }, + "continue": { + "message": "Pokračovat" + }, + "sendVerificationCode": { + "message": "Poslat ověřovací kód na váš e-mail" + }, + "sendCode": { + "message": "Poslat kód" + }, + "codeSent": { + "message": "Kód odeslán" + }, + "verificationCode": { + "message": "Ověřovací kód" + }, + "confirmIdentity": { + "message": "Pro pokračování potvrďte svou identitu." + }, + "account": { + "message": "Účet" + }, + "changeMasterPassword": { + "message": "Změnit hlavní heslo" + }, + "fingerprintPhrase": { + "message": "Fráze otisku prstu", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fráze otisku prstu vašeho účtu", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Dvoufázové přihlášení" + }, + "logOut": { + "message": "Odhlásit se" + }, + "about": { + "message": "O rozšíření" + }, + "version": { + "message": "Verze" + }, + "save": { + "message": "Uložit" + }, + "move": { + "message": "Přesunout" + }, + "addFolder": { + "message": "Přidat složku" + }, + "name": { + "message": "Název" + }, + "editFolder": { + "message": "Upravit složku" + }, + "deleteFolder": { + "message": "Smazat složku" + }, + "folders": { + "message": "Složky" + }, + "noFolders": { + "message": "Nejsou k dispozici žádné složky." + }, + "helpFeedback": { + "message": "Nápověda a zpětná vazba" + }, + "sync": { + "message": "Synchronizace" + }, + "syncVaultNow": { + "message": "Synchronizovat nyní" + }, + "lastSync": { + "message": "Poslední synchronizace:" + }, + "passGen": { + "message": "Generátor hesla" + }, + "generator": { + "message": "Generátor", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Vygenerujte si silné a unikátní heslo pro přihlašovací údaje." + }, + "bitWebVault": { + "message": "Webová aplikace" + }, + "importItems": { + "message": "Importovat položky" + }, + "select": { + "message": "Vybrat" + }, + "generatePassword": { + "message": "Vygenerovat heslo" + }, + "regeneratePassword": { + "message": "Vygenerovat další heslo" + }, + "options": { + "message": "Možnosti" + }, + "length": { + "message": "Délka" + }, + "uppercase": { + "message": "Velká písmena (A-Z)" + }, + "lowercase": { + "message": "Malá písmena (a-z)" + }, + "numbers": { + "message": "Čísla (0-9)" + }, + "specialCharacters": { + "message": "Speciální znaky (!@#$%^&*)" + }, + "numWords": { + "message": "Počet slov" + }, + "wordSeparator": { + "message": "Oddělovač slov" + }, + "capitalize": { + "message": "Velká písmena na začátku slova", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Zahrnout číslo" + }, + "minNumbers": { + "message": "Minimální počet čísel" + }, + "minSpecial": { + "message": "Minimální počet speciálních znaků" + }, + "avoidAmbChar": { + "message": "Nepoužít zaměnitelné znaky" + }, + "searchVault": { + "message": "Vyhledat v trezoru" + }, + "edit": { + "message": "Upravit" + }, + "view": { + "message": "Zobrazit" + }, + "noItemsInList": { + "message": "Žádné položky k zobrazení." + }, + "itemInformation": { + "message": "Informace o položce" + }, + "username": { + "message": "Uživatelské jméno" + }, + "password": { + "message": "Heslo" + }, + "passphrase": { + "message": "Heslová fráze" + }, + "favorite": { + "message": "Oblíbené" + }, + "notes": { + "message": "Poznámky" + }, + "note": { + "message": "Poznámka" + }, + "editItem": { + "message": "Upravit položku" + }, + "folder": { + "message": "Složka" + }, + "deleteItem": { + "message": "Smazat položku" + }, + "viewItem": { + "message": "Zobrazit položku" + }, + "launch": { + "message": "Spustit" + }, + "website": { + "message": "Webová stránka" + }, + "toggleVisibility": { + "message": "Přepnout viditelnost" + }, + "manage": { + "message": "Správa" + }, + "other": { + "message": "Ostatní" + }, + "rateExtension": { + "message": "Ohodnotit rozšíření" + }, + "rateExtensionDesc": { + "message": "Pomozte nám napsáním dobré recenze!" + }, + "browserNotSupportClipboard": { + "message": "Váš webový prohlížeč nepodporuje automatické kopírování do schránky. Musíte ho zkopírovat ručně." + }, + "verifyIdentity": { + "message": "Ověřit identitu" + }, + "yourVaultIsLocked": { + "message": "Váš trezor je uzamčen. Pro pokračování musíte zadat hlavní heslo." + }, + "unlock": { + "message": "Odemknout" + }, + "loggedInAsOn": { + "message": "Přihlášen jako $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Chybné hlavní heslo" + }, + "vaultTimeout": { + "message": "Časový limit trezoru" + }, + "lockNow": { + "message": "Zamknout nyní" + }, + "immediately": { + "message": "Okamžitě" + }, + "tenSeconds": { + "message": "10 sekund" + }, + "twentySeconds": { + "message": "20 sekund" + }, + "thirtySeconds": { + "message": "30 sekund" + }, + "oneMinute": { + "message": "Po 1 minutě" + }, + "twoMinutes": { + "message": "2 minuty" + }, + "fiveMinutes": { + "message": "Po 5 minutách" + }, + "fifteenMinutes": { + "message": "Po 15 minutách" + }, + "thirtyMinutes": { + "message": "Po 30 minutách" + }, + "oneHour": { + "message": "Po 1 hodině" + }, + "fourHours": { + "message": "Po 4 hodinách" + }, + "onLocked": { + "message": "Při uzamknutí systému" + }, + "onRestart": { + "message": "Při restartu prohlížeče" + }, + "never": { + "message": "Nikdy" + }, + "security": { + "message": "Zabezpečení" + }, + "errorOccurred": { + "message": "Došlo k chybě" + }, + "emailRequired": { + "message": "E-mailová adresa je povinná." + }, + "invalidEmail": { + "message": "Neplatná e-mailová adresa." + }, + "masterPassRequired": { + "message": "Hlavní heslo je povinné." + }, + "masterPassLength": { + "message": "Hlavní heslo musí obsahovat alespoň 8 znaků." + }, + "masterPassDoesntMatch": { + "message": "Potvrzení hlavního hesla se neshoduje." + }, + "newAccountCreated": { + "message": "Váš účet byl vytvořen! Můžete se přihlásit." + }, + "masterPassSent": { + "message": "Poslali jsme vám e-mail s nápovědou k hlavnímu heslu." + }, + "verificationCodeRequired": { + "message": "Ověřovací kód je povinný." + }, + "invalidVerificationCode": { + "message": "Neplatný ověřovací kód" + }, + "valueCopied": { + "message": "Zkopírováno: $VALUE$", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Vybrané přihlašovací údaje nelze na této stránce automaticky vyplnit. Zkopírujte a vložte své přihlašovací údaje ručně." + }, + "loggedOut": { + "message": "Odhlášení" + }, + "loginExpired": { + "message": "Platnost přihlášení vypršela." + }, + "logOutConfirmation": { + "message": "Opravdu se chcete odhlásit?" + }, + "yes": { + "message": "Ano" + }, + "no": { + "message": "Ne" + }, + "unexpectedError": { + "message": "Došlo k neznámé chybě." + }, + "nameRequired": { + "message": "Název je povinný." + }, + "addedFolder": { + "message": "Složka byla přidána" + }, + "changeMasterPass": { + "message": "Změnit hlavní heslo" + }, + "changeMasterPasswordConfirmation": { + "message": "Hlavní heslo si můžete změnit na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "twoStepLoginConfirmation": { + "message": "Dvoufázové přihlášení činí váš účet mnohem bezpečnějším díky nutnosti po každém úspěšném přihlášení zadat ověřovací kód získaný z aplikace, SMS, e-mailu nebo telefonního hovoru. Dvoufázové přihlášení lze aktivovat na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "editedFolder": { + "message": "Složka byla upravena" + }, + "deleteFolderConfirmation": { + "message": "Opravdu chcete tuto složku smazat?" + }, + "deletedFolder": { + "message": "Složka byla smazána" + }, + "gettingStartedTutorial": { + "message": "Průvodce pro začátečníky" + }, + "gettingStartedTutorialVideo": { + "message": "Podívejte se na našeho průvodce pro začátečníky a zjistěte, jak používat naše rozšíření prohlížeče." + }, + "syncingComplete": { + "message": "Synchronizace je dokončena" + }, + "syncingFailed": { + "message": "Synchronizace selhala" + }, + "passwordCopied": { + "message": "Heslo bylo zkopírováno" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nová URI" + }, + "addedItem": { + "message": "Položka byla přidána" + }, + "editedItem": { + "message": "Položka byla upravena" + }, + "deleteItemConfirmation": { + "message": "Opravdu chcete položku přesunout do koše?" + }, + "deletedItem": { + "message": "Položka byla přesunuta do koše" + }, + "overwritePassword": { + "message": "Přepsat heslo" + }, + "overwritePasswordConfirmation": { + "message": "Opravdu chcete přepsat aktuální heslo?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Vyhledat ve složce" + }, + "searchCollection": { + "message": "Vyledat v kolekci" + }, + "searchType": { + "message": "Typ hledání" + }, + "noneFolder": { + "message": "Žádná složka", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Vypnout oznámení Přidat přihlašovací údaje" + }, + "addLoginNotificationDesc": { + "message": "Oznámení „Přidat přihlašovací údaje“ automaticky vyzve k uložení přihlašovacích údajů do trezoru, pokud se s nimi přihlašujete poprvé." + }, + "dontShowCardsCurrentTab": { + "message": "Nezobrazovat karty na stránce Karta" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Položky karet jsou zobrazovány na stránce „Karta“ pro usnadnění automatického vyplňování." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Nezobrazovat identity na stránce Karta" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Položky identit jsou zobrazovány na stránce „Karta“ pro usnadnění automatického vyplňování." + }, + "clearClipboard": { + "message": "Vyčistit schránku", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automaticky vymazat zkopírované hodnoty z vaší schránky.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Má si pro vás Bitwarden toto heslo pamatovat?" + }, + "notificationAddSave": { + "message": "Ano, uložit nyní" + }, + "disableChangedPasswordNotification": { + "message": "Vypnout oznámení o změněném heslu" + }, + "disableChangedPasswordNotificationDesc": { + "message": "„Oznámení o změněném heslu“ vás automaticky požádá o potvrzení uložení aktualizovaného hesla v případě, že aplikace rozpozná vámi provedenou změnu hesla na webu." + }, + "notificationChangeDesc": { + "message": "Chcete aktualizovat toto heslo v Bitwarden?" + }, + "notificationChangeSave": { + "message": "Ano, aktualizovat" + }, + "disableContextMenuItem": { + "message": "Vypnout kontextové menu" + }, + "disableContextMenuItemDesc": { + "message": "Kontextové menu poskytuje rychlý přístup k automatickému vyplnění, zkopírování nebo vygenerování přihlašovacích údajů pro aktuální stránku." + }, + "defaultUriMatchDetection": { + "message": "Výchozí zjišťování shody URI", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Vyberte výchozí způsob, jakým se detekuje shoda URI přihlašovacích údajů. Používá se například pro automatické vyplňování." + }, + "theme": { + "message": "Motiv" + }, + "themeDesc": { + "message": "Změna barevného motivu aplikace." + }, + "dark": { + "message": "Tmavý", + "description": "Dark color" + }, + "light": { + "message": "Světlý", + "description": "Light color" + }, + "solarizedDark": { + "message": "Tmavý –⁠ Solarized", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Exportovat trezor" + }, + "fileFormat": { + "message": "Formát souboru" + }, + "warning": { + "message": "VAROVÁNÍ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potvrdit export trezoru" + }, + "exportWarningDesc": { + "message": "Tento export obsahuje data vašeho trezoru v nezašifrovaném formátu. Soubor exportu byste neměli ukládat ani odesílat přes nezabezpečené kanály (např. e-mailem). Odstraňte jej okamžitě po jeho použití." + }, + "encExportKeyWarningDesc": { + "message": "Tento export zašifruje vaše data pomocí šifrovacího klíče vašeho účtu. Pokud někdy změníte šifrovací klíč vašeho účtu, měli by jste vyexportovat data znovu, protože tento exportovaný soubor nebudete moci dešifrovat." + }, + "encExportAccountWarningDesc": { + "message": "Šifrovací klíče účtu jsou pro každý uživatelský účet Bitwarden jedinečné, takže nelze importovat šifrovaný export do jiného účtu." + }, + "exportMasterPassword": { + "message": "Zadejte své hlavní heslo pro export dat." + }, + "shared": { + "message": "Sdílené" + }, + "learnOrg": { + "message": "Zjistěte více o organizacích" + }, + "learnOrgConfirmation": { + "message": "Bitwarden umožňuje sdílet vaše položky v trezoru s ostatními prostřednictvím organizace. Chcete přejít na bitwarden.com a dozvědět se více?" + }, + "moveToOrganization": { + "message": "Přesunout do organizace" + }, + "share": { + "message": "Sdílet" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ přesunut do $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vyberte organizaci, do které chcete tuto položku přesunout. Přesun do organizace převede vlastnictví položky této organizaci. Po přesunutí této položky již nebudete přímým vlastníkem této položky." + }, + "learnMore": { + "message": "Dozvědět se více" + }, + "authenticatorKeyTotp": { + "message": "Autentizační klíč (TOTP)" + }, + "verificationCodeTotp": { + "message": "Ověřovací kód (TOTP)" + }, + "copyVerificationCode": { + "message": "Zkopírovat ověřovací kód" + }, + "attachments": { + "message": "Přílohy" + }, + "deleteAttachment": { + "message": "Smazat přílohu" + }, + "deleteAttachmentConfirmation": { + "message": "Opravdu chcete tuto přílohu smazat?" + }, + "deletedAttachment": { + "message": "Příloha byla smazána" + }, + "newAttachment": { + "message": "Přidat přílohu" + }, + "noAttachments": { + "message": "Žádné přílohy." + }, + "attachmentSaved": { + "message": "Příloha byla uložena" + }, + "file": { + "message": "Soubor" + }, + "selectFile": { + "message": "Vybrat soubor." + }, + "maxFileSize": { + "message": "Maximální velikost souboru je 500 MB." + }, + "featureUnavailable": { + "message": "Funkce není dostupná" + }, + "updateKey": { + "message": "Tuto funkci nemůžete použít dokud neaktualizujete svůj šifrovací klíč." + }, + "premiumMembership": { + "message": "Prémiové členství" + }, + "premiumManage": { + "message": "Spravovat členství" + }, + "premiumManageAlert": { + "message": "Své členství můžete spravovat na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "premiumRefresh": { + "message": "Obnovit členství" + }, + "premiumNotCurrentMember": { + "message": "Momentálně nejste prémiovým členem." + }, + "premiumSignUpAndGet": { + "message": "Přihlaste se k prémiovému členství a získejte:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB šifrovaného úložiště pro přílohy." + }, + "ppremiumSignUpTwoStep": { + "message": "Další možnosti dvoufázového přihlášení, jako je například YubiKey, FIDO U2F a Duo." + }, + "ppremiumSignUpReports": { + "message": "Reporty o hygieně vašich hesel, zdraví účtu a narušeních bezpečnosti." + }, + "ppremiumSignUpTotp": { + "message": "Generátor TOTP kódu dvoufázového přihlašování (2FA) pro přihlašovací údaje ve vašem trezoru." + }, + "ppremiumSignUpSupport": { + "message": "Prioritní zákaznickou podporu." + }, + "ppremiumSignUpFuture": { + "message": "Všechny budoucí prémiové funkce. Více již brzy!" + }, + "premiumPurchase": { + "message": "Zakoupit prémiové členství" + }, + "premiumPurchaseAlert": { + "message": "Prémiové členství můžete zakoupit na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "premiumCurrentMember": { + "message": "Jste prémiovým členem!" + }, + "premiumCurrentMemberThanks": { + "message": "Děkujeme za podporu Bitwarden." + }, + "premiumPrice": { + "message": "Vše jen za %price% ročně!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Obnova je dokončena" + }, + "disableAutoTotpCopy": { + "message": "Vypnout automatické kopírování kódu TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Pokud mají vaše přihlašovací údaje přidán autentizační klíč pro TOTP, vygenerovaný ověřovací kód (TOTP) se automaticky zkopíruje do schránky při každém automatickém vyplnění přihlašovacích údajů." + }, + "disableAutoBiometricsPrompt": { + "message": "Neptat se na biometriku při spuštění." + }, + "premiumRequired": { + "message": "Vyžaduje prémiové členství" + }, + "premiumRequiredDesc": { + "message": "Pro použití této funkce je potřebné prémiové členství." + }, + "enterVerificationCodeApp": { + "message": "Zadejte 6místný kód z ověřovací aplikace." + }, + "enterVerificationCodeEmail": { + "message": "Zadejte 6místný kód z e-mailu, který byl zaslán na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Ověřovací e-mail byl zaslán na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Pamatuj si mě" + }, + "sendVerificationCodeEmailAgain": { + "message": "Znovu zaslat ověřovací kód na e-mail" + }, + "useAnotherTwoStepMethod": { + "message": "Použít jinou metodu dvoufázového přihlášení" + }, + "insertYubiKey": { + "message": "Vložte YubiKey do USB portu vašeho počítače a stiskněte jeho tlačítko." + }, + "insertU2f": { + "message": "Vložte svůj bezpečnostní klíč do USB portu vašeho počítače a pokud má tlačítko, tak jej stiskněte." + }, + "webAuthnNewTab": { + "message": "Pokračujte v ověřování WebAuthn 2FA na nové kartě." + }, + "webAuthnNewTabOpen": { + "message": "Otevřít novou kartu" + }, + "webAuthnAuthenticate": { + "message": "Ověřit WebAuthn" + }, + "loginUnavailable": { + "message": "Přihlášení není dostupné" + }, + "noTwoStepProviders": { + "message": "Tento účet má zapnuté dvoufázové ověřování, ale žádný z nastavených poskytovalů dvoufázového přihlášení není v tomto prohlížeči podporován." + }, + "noTwoStepProviders2": { + "message": "Použijte prosím podporovaný webový prohlížeč (například Chrome) a přidejte další poskytovatele, kteří lépe podporují více různých webových prohlížečích (jako například ověřovací aplikace)." + }, + "twoStepOptions": { + "message": "Možnosti dvoufázového přihlášení" + }, + "recoveryCodeDesc": { + "message": "Ztratili jste přístup ke všem nastaveným poskytovatelům dvoufázového přihlášení? Použijte obnovovací kód pro vypnutí dvoufázového přihlášení." + }, + "recoveryCodeTitle": { + "message": "Kód pro obnovení" + }, + "authenticatorAppTitle": { + "message": "Ověřovací aplikace" + }, + "authenticatorAppDesc": { + "message": "Použijte ověřovací aplikaci (jako je Authy nebo Google Authenticator) pro generování časově omezených kódů.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP bezpečnostní klíč" + }, + "yubiKeyDesc": { + "message": "Použít YubiKey pro přístup k vašemu trezoru. Podporuje YubiKey 4, 4 Nano, 4C a NEO zařízení." + }, + "duoDesc": { + "message": "Ověřit pomocí Duo Security prostřednictvím aplikace Duo Mobile, SMS, telefonního hovoru nebo U2F bezpečnostního kódu.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Ověřit pomocí Duo Security pro vaši organizaci prostřednictvím aplikace Duo Mobile, SMS, telefonního hovoru nebo U2F bezpečnostního kódu.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Použijte jakýkoliv WebAuthn bezpečnostní klíč pro přístup k vašemu účtu." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Ověřovací kódy vám budou zaslány e-mailem." + }, + "selfHostedEnvironment": { + "message": "Vlastnoručně hostované prostředí" + }, + "selfHostedEnvironmentFooter": { + "message": "Zadejte základní URL adresu vlastnoručně hostované aplikace Bitwarden." + }, + "customEnvironment": { + "message": "Vlastní prostředí" + }, + "customEnvironmentFooter": { + "message": "Pro pokročilé uživatele. Můžete zadat základní URL adresu každé služby zvlášť." + }, + "baseUrl": { + "message": "URL serveru" + }, + "apiUrl": { + "message": "URL serveru API" + }, + "webVaultUrl": { + "message": "URL serveru webového trezoru" + }, + "identityUrl": { + "message": "URL serveru identity" + }, + "notificationsUrl": { + "message": "URL serveru pro oznámení" + }, + "iconsUrl": { + "message": "URL serveru ikonek" + }, + "environmentSaved": { + "message": "URL adresy vlastního prostředí byly uloženy" + }, + "enableAutoFillOnPageLoad": { + "message": "Automaticky vyplnit údaje při načtení stránky" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Pokud je zjištěn přihlašovací formulář, automaticky se při načítání webové stránky vyplní přihlašovací údaje." + }, + "experimentalFeature": { + "message": "Toto je momentálně experimentální funkce. Použijte na vlastní riziko." + }, + "defaultAutoFillOnPageLoad": { + "message": "Výchozí nastavení automatického vyplňování pro položky přihlášení" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Po povolení automatického vyplňování při načtení stránky můžete tuto funkci povolit nebo zakázat pro jednotlivé položky přihlášení. Toto je výchozí nastavení pro položky přihlášení, které nejsou samostatně konfigurovány." + }, + "itemAutoFillOnPageLoad": { + "message": "Automatické vyplnění při načtení stránky (pokud je povoleno v nastavení)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Použít výchozí nastavení" + }, + "autoFillOnPageLoadYes": { + "message": "Automatické vyplnění při načtení stránky" + }, + "autoFillOnPageLoadNo": { + "message": "Nevyplňovat automaticky při načtení stránky" + }, + "commandOpenPopup": { + "message": "Otevřít vyskakovací okno trezoru" + }, + "commandOpenSidebar": { + "message": "Otevřít trezor v postranním panelu" + }, + "commandAutofillDesc": { + "message": "Automaticky vyplnit poslední použité přihlašovací údaje pro tuto stránku." + }, + "commandGeneratePasswordDesc": { + "message": "Vygenerovat a zkopírovat nové náhodné heslo do schránky." + }, + "commandLockVaultDesc": { + "message": "Zamknout trezor" + }, + "privateModeWarning": { + "message": "Podpora soukromého režimu je experimentální a některé funkce jsou omezené." + }, + "customFields": { + "message": "Vlastní pole" + }, + "copyValue": { + "message": "Zkopírovat hodnotu" + }, + "value": { + "message": "Hodnota" + }, + "newCustomField": { + "message": "Nové vlastní pole" + }, + "dragToSort": { + "message": "Přetáhnutím seřadíte" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Skryté" + }, + "cfTypeBoolean": { + "message": "Ano/Ne" + }, + "cfTypeLinked": { + "message": "Propojené", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Propojená hodnota", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Klepnutím mimo vyskakovací okno při zjišťování ověřovacího kódu zaslaného na e-mail bude vyskakovací okno zavřeno. Chcete otevřít toto vyskakovací okno v novém okně, aby se nezavřelo?" + }, + "popupU2fCloseMessage": { + "message": "Tento prohlížeč nemůže zpracovat U2F požadavky ve vyskakovacím okně. Chcete otevřít toto vyskakovací okno v novém okně, abyste se mohli přihlásit pomocí U2F?" + }, + "disableFavicon": { + "message": "Vypnout ikonky webových stránek" + }, + "disableFaviconDesc": { + "message": "Ikonky webových stránek zobrazí snadno rozeznatelný obrázek vedle každé položky ve vašem trezoru." + }, + "disableBadgeCounter": { + "message": "Nezobrazovat počet přihlašovacích údajů" + }, + "disableBadgeCounterDesc": { + "message": "Počítadlo zobrazuje, kolik přihlašovacích údajů máte pro aktuální stránku ve svém trezoru." + }, + "cardholderName": { + "message": "Jméno držitele karty" + }, + "number": { + "message": "Číslo" + }, + "brand": { + "message": "Značka" + }, + "expirationMonth": { + "message": "Měsíc expirace" + }, + "expirationYear": { + "message": "Rok expirace" + }, + "expiration": { + "message": "Expirace" + }, + "january": { + "message": "Leden" + }, + "february": { + "message": "Únor" + }, + "march": { + "message": "Březen" + }, + "april": { + "message": "Duben" + }, + "may": { + "message": "Květen" + }, + "june": { + "message": "Červen" + }, + "july": { + "message": "Červenec" + }, + "august": { + "message": "Srpen" + }, + "september": { + "message": "Září" + }, + "october": { + "message": "Říjen" + }, + "november": { + "message": "Listopad" + }, + "december": { + "message": "Prosinec" + }, + "securityCode": { + "message": "Bezpečnostní kód" + }, + "ex": { + "message": "např." + }, + "title": { + "message": "Oslovení" + }, + "mr": { + "message": "Pan" + }, + "mrs": { + "message": "Paní" + }, + "ms": { + "message": "Slečna" + }, + "dr": { + "message": "MUDr" + }, + "firstName": { + "message": "Jméno" + }, + "middleName": { + "message": "Druhé jméno" + }, + "lastName": { + "message": "Příjmení" + }, + "fullName": { + "message": "Celé jméno" + }, + "identityName": { + "message": "Název identity" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Číslo sociálního pojištění" + }, + "passportNumber": { + "message": "Číslo cestovního pasu" + }, + "licenseNumber": { + "message": "Číslo dokladu totožnosti" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresa" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Město" + }, + "stateProvince": { + "message": "Kraj / Provincie" + }, + "zipPostalCode": { + "message": "PSČ" + }, + "country": { + "message": "Stát" + }, + "type": { + "message": "Typ" + }, + "typeLogin": { + "message": "Přihlašovací údaje" + }, + "typeLogins": { + "message": "Přihlašovací údaje" + }, + "typeSecureNote": { + "message": "Poznámka" + }, + "typeCard": { + "message": "Karta" + }, + "typeIdentity": { + "message": "Identita" + }, + "passwordHistory": { + "message": "Historie hesel" + }, + "back": { + "message": "Zpět" + }, + "collections": { + "message": "Kolekce" + }, + "favorites": { + "message": "Oblíbené" + }, + "popOutNewWindow": { + "message": "Otevřít v novém okně" + }, + "refresh": { + "message": "Obnovit" + }, + "cards": { + "message": "Karty" + }, + "identities": { + "message": "Identity" + }, + "logins": { + "message": "Přihlašovací údaje" + }, + "secureNotes": { + "message": "Poznámky" + }, + "clear": { + "message": "Vymazat", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Zkontrolujte, zda nedošlo k úniku hesla." + }, + "passwordExposed": { + "message": "K úniku tohoto hesla došlo celkem $VALUE$x. Měli byste jej změnit.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": " V žádném ze známých případů nedošlo k úniku tohoto hesla. Mělo by být bezpečné používat jej i nadále." + }, + "baseDomain": { + "message": "Základní doména", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Přesně" + }, + "startsWith": { + "message": "Začíná na" + }, + "regEx": { + "message": "Regulární výraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Zjišťování shody", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Výchozí", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Přepnout možnosti" + }, + "toggleCurrentUris": { + "message": "Přepnout zobrazení aktuálních URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Aktuální URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organizace", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Typy" + }, + "allItems": { + "message": "Všechny položky" + }, + "noPasswordsInList": { + "message": "Nejsou k dispozici žádná hesla." + }, + "remove": { + "message": "Smazat" + }, + "default": { + "message": "Výchozí" + }, + "dateUpdated": { + "message": "Změněno", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Heslo bylo změněno", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Opravdu chcete použít možnost „Nikdy“? Nastavením možností uzamčení na „Nikdy“ bude šifrovací klíč k trezoru uložen přímo ve vašem zařízení. Pokud tuto možnost použijete, měli byste vaše zařízení řádně zabezpečit a chránit." + }, + "noOrganizationsList": { + "message": "Nepatříte do žádné organizace. Organizace umožňují bezpečné sdílení položek s ostatními uživateli." + }, + "noCollectionsInList": { + "message": "Žádné kolekce k zobrazení." + }, + "ownership": { + "message": "Vlastnictví" + }, + "whoOwnsThisItem": { + "message": "Kdo vlastní tuto položku?" + }, + "strong": { + "message": "Silné", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobré", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slabé", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slabé hlavní heslo" + }, + "weakMasterPasswordDesc": { + "message": "Zvolené hlavní heslo je slabé. Pro správnou ochranu účtu Bitwarden byste měli použít silné hlavní heslo (nebo heslovou frázi). Opravdu chcete toto heslo použít?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Odemknout pomocí PIN" + }, + "setYourPinCode": { + "message": "Nastavte svůj PIN kód pro odemknutí trezoru. Pokud se zcela odhlásíte z aplikace bude váš současný PIN bude resetován." + }, + "pinRequired": { + "message": "PIN kód je vyžadován." + }, + "invalidPin": { + "message": "Neplatný PIN kód." + }, + "unlockWithBiometrics": { + "message": "Odemknout pomocí biometrie" + }, + "awaitDesktop": { + "message": "Čeká se na potvrzení z aplikace v počítači" + }, + "awaitDesktopDesc": { + "message": "Prosím potvrďte použití biometrie v desktopové Bitwarden aplikaci, pro povolení biometrie v prohlížeči." + }, + "lockWithMasterPassOnRestart": { + "message": "Zamknout trezor při restartu prohlížeče pomocí hlavního hesla" + }, + "selectOneCollection": { + "message": "Musíte vybrat alespoň jednu kolekci." + }, + "cloneItem": { + "message": "Duplikovat položku" + }, + "clone": { + "message": "Duplikovat" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Jedna nebo více zásad organizace ovlivňují nastavení generátoru." + }, + "vaultTimeoutAction": { + "message": "Akce při vypršení časového limitu" + }, + "lock": { + "message": "Zamknout", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Koš", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Hledat v koši" + }, + "permanentlyDeleteItem": { + "message": "Trvale smazat položku" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Opravdu chcete tuto položku trvale smazat?" + }, + "permanentlyDeletedItem": { + "message": "Položka byla trvale smazána" + }, + "restoreItem": { + "message": "Obnovit položku" + }, + "restoreItemConfirmation": { + "message": "Opravdu chcete tuto položku obnovit?" + }, + "restoredItem": { + "message": "Položka byla obnovena" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Po vypršení časového limitu dojde k odhlášení. Přístup k trezoru bude odebrán a pro opětovné přihlášení bude vyžadováno online ověření. Opravdu chcete použít toto nastavení?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potvrzení akce při vypršení časového limitu" + }, + "autoFillAndSave": { + "message": "Automaticky vyplnit a uložit" + }, + "autoFillSuccessAndSavedUri": { + "message": "Položka byla automaticky vyplněna a uloženo URI" + }, + "autoFillSuccess": { + "message": "Položka byla automaticky vyplněna" + }, + "setMasterPassword": { + "message": "Nastavit hlavní heslo" + }, + "masterPasswordPolicyInEffect": { + "message": "Jedna nebo více zásad organizace vyžaduje, aby hlavní heslo splňovalo následující požadavky:" + }, + "policyInEffectMinComplexity": { + "message": "Minimální skóre složitosti $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimální délka $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Obsahuje jedno nebo více velkých písmen" + }, + "policyInEffectLowercase": { + "message": "Obsahuje jedno nebo více malých písmen" + }, + "policyInEffectNumbers": { + "message": "Obsahuje jednu nebo více číslic" + }, + "policyInEffectSpecial": { + "message": "Obsahuje jeden nebo více následujících speciálních znaků: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Vaše nové hlavní heslo nesplňuje požadavky zásad organizace." + }, + "acceptPolicies": { + "message": "Zaškrtnutím tohoto políčka souhlasím s následujícím:" + }, + "acceptPoliciesError": { + "message": "Podmínky použití a zásady ochrany osobních údajů nebyly odsouhlaseny." + }, + "termsOfService": { + "message": "Podmínky použití" + }, + "privacyPolicy": { + "message": "Zásady ochrany osobních údajů" + }, + "hintEqualsPassword": { + "message": "Nápověda k vašemu heslu nemůže být stejná jako vaše heslo." + }, + "ok": { + "message": "OK" + }, + "desktopSyncVerificationTitle": { + "message": "Ověření synchronizace s desktopovou aplikací" + }, + "desktopIntegrationVerificationText": { + "message": "Ověřte, zda desktopová aplikace zobrazuje tento otisk: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Integrace prohlížeče není povolena" + }, + "desktopIntegrationDisabledDesc": { + "message": "Integrace prohlížeče není povolena v aplikaci Bitwarden. Povolte ji prosím v nastavení v aplikaci pro počítač." + }, + "startDesktopTitle": { + "message": "Spustit aplikaci Bitwarden" + }, + "startDesktopDesc": { + "message": "Počítačová aplikace Bitwarden musí být spuštěna před použitím této funkce." + }, + "errorEnableBiometricTitle": { + "message": "Nelze povolit biometrii" + }, + "errorEnableBiometricDesc": { + "message": "Akce byla zrušena aplikací pro počítač" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Aplikace pro počítač zrušila platnost zabezpečeného komunikačního kanálu. Zkuste to prosím znovu" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Komunikace s počítačovou aplikací přerušena" + }, + "nativeMessagingWrongUserDesc": { + "message": "Počítačová aplikace je přihlášena k jinému účtu. Ujistěte se, že jsou obě aplikace přihlášeny ke stejnému účtu." + }, + "nativeMessagingWrongUserTitle": { + "message": "Neshoda účtu" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrie není povolena" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrické prvky v prohlížeči vyžadují, aby v nastavení počítačové aplikace byla povolena biometrie." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrie není podporována" + }, + "biometricsNotSupportedDesc": { + "message": "Biometrie v prohlížeči není na tomto zařízení podporována." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Oprávnění nebylo uděleno" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bez oprávnění ke komunikaci s počítačovou aplikací Bitwarden nelze v rozšíření prohlížeče používat biometrické údaje. Zkuste to prosím znovu." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Žádost o oprávnění selhala" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Tuto akci nelze provést v postranním panelu, prosím zkuste akci znovu v novém okně." + }, + "personalOwnershipSubmitError": { + "message": "Z důvodu zásad organizace nemůžete ukládat položky do svého osobního trezoru. Změňte vlastnictví položky na organizaci a poté si vyberte z dostupných kolekcí." + }, + "personalOwnershipPolicyInEffect": { + "message": "Zásady organizace ovlivňují možnosti vlastnictví." + }, + "excludedDomains": { + "message": "Vyloučené domény" + }, + "excludedDomainsDesc": { + "message": "Bitwarden nebude žádat o uložení přihlašovacích údajů pro tyto domény. Aby se změny projevily, musíte stránku obnovit." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ není platná doména", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Hledat Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Přidat Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "Soubor" + }, + "allSends": { + "message": "Všechny Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Dosažen maximální počet přístupů", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Vypršela platnost" + }, + "pendingDeletion": { + "message": "Čeká na smazání" + }, + "passwordProtected": { + "message": "Chráněno heslem" + }, + "copySendLink": { + "message": "Zkopírovat odkaz Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Odstranit heslo" + }, + "delete": { + "message": "Smazat" + }, + "removedPassword": { + "message": "Odstraněné heslo" + }, + "deletedSend": { + "message": "Smazaný Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Odkaz tohoto Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Zakázáno" + }, + "removePasswordConfirmation": { + "message": "Jste si jisti, že chcete odstranit heslo?" + }, + "deleteSend": { + "message": "Smazat Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Jste si jisti, že chcete odstranit tento Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Upravit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Jakého typu je tento Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Přátelský název pro popis tohoto Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Soubor, který chcete odeslat." + }, + "deletionDate": { + "message": "Datum odstranění" + }, + "deletionDateDesc": { + "message": "Tento Send bude trvale smazán v určený datum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Datum vypršení platnosti" + }, + "expirationDateDesc": { + "message": "Je-li nastaveno, přístup k tomuto Send vyprší v daný datum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 den" + }, + "days": { + "message": "$DAYS$ dní", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Vlastní" + }, + "maximumAccessCount": { + "message": "Maximální počet přístupů" + }, + "maximumAccessCountDesc": { + "message": "Je-li nastaveno, uživatelé již nebudou mít přístup k tomuto Send, jakmile bude dosaženo maximálního počtu přístupů.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Volitelně vyžadovat heslo pro přístup k tomuto Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Soukromé poznámky o tomto Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Vypnout tento Send, díky čemuž k němu nebude moci nikdo přistoupit.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Zkopírovat odkaz pro sdílení tohoto Send po uložení.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Text, který chcete odeslat." + }, + "sendHideText": { + "message": "Skrýt ve výchozím stavu text tohoto Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Počet aktuálních přístupů" + }, + "createSend": { + "message": "Vytvořit nový Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nové heslo" + }, + "sendDisabled": { + "message": "Send deaktivován", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Kvůli firemním pravidlům můžete odstranit pouze existující Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send vytvořen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send upraven", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Chcete-li vybrat soubor, otevřete rozšíření v postranním panelu (pokud je to možné) nebo jej otevřete v novém okně kliknutím na tento banner." + }, + "sendFirefoxFileWarning": { + "message": "Chcete-li vybrat soubor pomocí prohlížeče Firefox, otevřete rozšíření v postranním panelu (pokud je to možné) nebo jej otevřete v novém okně kliknutím na tento banner." + }, + "sendSafariFileWarning": { + "message": "Chcete-li vybrat soubor pomocí prohlížeče Safari, otevřete nové okno kliknutím na tento banner." + }, + "sendFileCalloutHeader": { + "message": "Než začnete" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Chcete-li použít k výběru data styl kalendáře", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klikněte zde", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "pro zobrazení okna.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Uvedené datum vypršení platnosti není platné." + }, + "deletionDateIsInvalid": { + "message": "Uvedené datum odstranění není platné." + }, + "expirationDateAndTimeRequired": { + "message": "Je vyžadován datum a čas vypršení platnosti." + }, + "deletionDateAndTimeRequired": { + "message": "Je vyžadován datum a čas odstranění." + }, + "dateParsingError": { + "message": "Došlo k chybě při ukládání data odstranění a vypršení platnosti." + }, + "hideEmail": { + "message": "Skrýt mou e-mailovou adresu před příjemci." + }, + "sendOptionsPolicyInEffect": { + "message": "Jedna nebo více zásad organizace ovlivňuje nastavení Send." + }, + "passwordPrompt": { + "message": "Zeptat se znovu na hlavní heslo" + }, + "passwordConfirmation": { + "message": "Potvrzení hlavního hesla" + }, + "passwordConfirmationDesc": { + "message": "Tato akce je chráněna. Chcete-li pokračovat, zadejte znovu vaše hlavní heslo, abychom ověřili vaší totožnost." + }, + "emailVerificationRequired": { + "message": "Je vyžadováno ověření emailu" + }, + "emailVerificationRequiredDesc": { + "message": "Abyste mohli tuto funkci používat, musíte ověřit svůj e-mail. Svůj e-mail můžete ověřit ve webovém trezoru." + }, + "updatedMasterPassword": { + "message": "Hlavní heslo aktualizováno" + }, + "updateMasterPassword": { + "message": "Změnit hlavní heslo" + }, + "updateMasterPasswordWarning": { + "message": "Administrátor v organizaci nedávno změnil vaše hlavní heslo. Pro přístup k trezoru jej nyní musíte změnit. Pokračování vás odhlásí z vaší aktuální relace a bude nutné se znovu přihlásit. Aktivní relace na jiných zařízeních mohou zůstat aktivní až po dobu jedné hodiny." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatická registrace" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Tato organizace má podnikové zásady, které vás automaticky zaregistrují k obnovení hesla. Registrace umožní správcům organizace změnit vaše hlavní heslo." + }, + "selectFolder": { + "message": "Vyberte složku" + }, + "ssoCompleteRegistration": { + "message": "Chcete-li dokončit přihlášení pomocí SSO, nastavte prosím hlavní přístupové heslo k vašemu trezoru." + }, + "hours": { + "message": "Hodin" + }, + "minutes": { + "message": "Minuty" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Pravidla vaší organizace ovlivňují časový limit trezoru. Maximální povolený časový limit trezoru je $HOURS$ hodin a $MINUTES$ minut", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Časový limit vašeho trezoru překračuje omezení stanovená vaší organizací." + }, + "vaultExportDisabled": { + "message": "Export trezoru zakázán" + }, + "personalVaultExportPolicyInEffect": { + "message": "Jedna nebo více zásad organizace vám brání v exportu vašeho osobního trezoru." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Nelze identifikovat platný prvek formuláře. Zkuste místo toho zkontrolovat HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nenalezen žádný jedinečný identifikátor." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ používá SSO s vlastním klíčovým serverem. Hlavní heslo pro členy této organizace již není vyžadováno.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Opustit organizaci" + }, + "removeMasterPassword": { + "message": "Odstranit hlavní heslo" + }, + "removedMasterPassword": { + "message": "Hlavní heslo bylo odstraněno." + }, + "leaveOrganizationConfirmation": { + "message": "Opravdu chcete tuto organizaci opustit?" + }, + "leftOrganization": { + "message": "Opustili jste organizaci." + }, + "toggleCharacterCount": { + "message": "Zobrazit počet znaků" + }, + "sessionTimeout": { + "message": "Vypršel časový limit relace. Vraťte se prosím zpět a zkuste se znovu přihlásit." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/da/messages.json b/apps/browser/src/_locales/da/messages.json new file mode 100644 index 0000000000..162b07f5a5 --- /dev/null +++ b/apps/browser/src/_locales/da/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Gratis adgangskodemanager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "En sikker og gratis adgangskodemanager til alle dine enheder.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log ind eller opret en ny konto for at få adgang til din sikre boks." + }, + "createAccount": { + "message": "Opret konto" + }, + "login": { + "message": "Log ind" + }, + "enterpriseSingleSignOn": { + "message": "Virksomheds Single Sign On" + }, + "cancel": { + "message": "Annullér" + }, + "close": { + "message": "Luk" + }, + "submit": { + "message": "Bekræft" + }, + "emailAddress": { + "message": "E-mailadresse" + }, + "masterPass": { + "message": "Hovedadgangskode" + }, + "masterPassDesc": { + "message": "Hovedadgangskoden er den adgangskode, du bruger til at få adgang til din boks. Det er meget vigtigt, at du ikke glemmer din hovedadgangskode. Der er ingen måde hvorpå koden kan genoprettes, i tilfælde af at du glemmer den." + }, + "masterPassHintDesc": { + "message": "Et tip til hovedadgangskoden kan hjælpe dig med at huske din adgangskode, hvis du glemmer den." + }, + "reTypeMasterPass": { + "message": "Bekræft hovedadgangskode" + }, + "masterPassHint": { + "message": "Hovedadgangskodetip (valgfrit)" + }, + "tab": { + "message": "Fane" + }, + "myVault": { + "message": "Min boks" + }, + "tools": { + "message": "Værktøjer" + }, + "settings": { + "message": "Indstillinger" + }, + "currentTab": { + "message": "Aktuel fane" + }, + "copyPassword": { + "message": "Kopiér adgangskode" + }, + "copyNote": { + "message": "Kopiér notat" + }, + "copyUri": { + "message": "Kopiér URI" + }, + "copyUsername": { + "message": "Kopiér brugernavn" + }, + "copyNumber": { + "message": "Kopiér nummer" + }, + "copySecurityCode": { + "message": "Kopiér sikkerhedskode" + }, + "autoFill": { + "message": "Auto-udfyld" + }, + "generatePasswordCopied": { + "message": "Generér adgangskode (kopieret)" + }, + "copyElementIdentifier": { + "message": "Kopiér brugerdefineret feltnavn" + }, + "noMatchingLogins": { + "message": "Ingen matchende logins." + }, + "unlockVaultMenu": { + "message": "Lås din boks op" + }, + "loginToVaultMenu": { + "message": "Log ind på din boks" + }, + "autoFillInfo": { + "message": "Der findes ingen login til at auto-udfylde i den nuværende browserfane." + }, + "addLogin": { + "message": "Tilføj et login" + }, + "addItem": { + "message": "Tilføj element" + }, + "passwordHint": { + "message": "Adgangskodetip" + }, + "enterEmailToGetHint": { + "message": "Indtast din kontos e-mailadresse for at modtage dit hovedadgangskodetip." + }, + "getMasterPasswordHint": { + "message": "Få hovedadgangskodetip" + }, + "continue": { + "message": "Forsæt" + }, + "sendVerificationCode": { + "message": "Send en bekræftelseskode til din e-mail" + }, + "sendCode": { + "message": "Send kode" + }, + "codeSent": { + "message": "Kode sendt" + }, + "verificationCode": { + "message": "Bekræftelseskode" + }, + "confirmIdentity": { + "message": "Bekræft din identitet for at fortsætte." + }, + "account": { + "message": "Konto" + }, + "changeMasterPassword": { + "message": "Skift hovedadgangskode" + }, + "fingerprintPhrase": { + "message": "Fingeraftrykssætning", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Din kontos fingeraftrykssætning", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "To-trins login" + }, + "logOut": { + "message": "Log ud" + }, + "about": { + "message": "Om" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Gem" + }, + "move": { + "message": "Flyt" + }, + "addFolder": { + "message": "Tilføj mappe" + }, + "name": { + "message": "Navn" + }, + "editFolder": { + "message": "Redigér mappe" + }, + "deleteFolder": { + "message": "Slet mappe" + }, + "folders": { + "message": "Mapper" + }, + "noFolders": { + "message": "Der er ingen mapper at vise." + }, + "helpFeedback": { + "message": "Hjælp & feedback" + }, + "sync": { + "message": "Synkronisér" + }, + "syncVaultNow": { + "message": "Synkronisér boks nu" + }, + "lastSync": { + "message": "Seneste synkronisering:" + }, + "passGen": { + "message": "Adgangskodegenerator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Opret automatisk stærke, unikke adgangskoder til dine logins." + }, + "bitWebVault": { + "message": "Bitwarden web-boks" + }, + "importItems": { + "message": "Importér elementer" + }, + "select": { + "message": "Vælg" + }, + "generatePassword": { + "message": "Generér adgangskode" + }, + "regeneratePassword": { + "message": "Regenerér adgangskode" + }, + "options": { + "message": "Indstillinger" + }, + "length": { + "message": "Længde" + }, + "uppercase": { + "message": "Store bogstaver (A-Z)" + }, + "lowercase": { + "message": "Små bogstaver (a-z)" + }, + "numbers": { + "message": "Tal (0-9)" + }, + "specialCharacters": { + "message": "Specielle tegn (!@#$%^&*)" + }, + "numWords": { + "message": "Antal ord" + }, + "wordSeparator": { + "message": "Ordseparator" + }, + "capitalize": { + "message": "Stort begyndelsesbogstav", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inkludér ciffer" + }, + "minNumbers": { + "message": "Mindste antal cifre" + }, + "minSpecial": { + "message": "Mindste antal specialtegn" + }, + "avoidAmbChar": { + "message": "Undgå tvetydige tegn" + }, + "searchVault": { + "message": "Søg i boks" + }, + "edit": { + "message": "Redigér" + }, + "view": { + "message": "Vis" + }, + "noItemsInList": { + "message": "Der er ingen elementer at vise." + }, + "itemInformation": { + "message": "Elementinformation" + }, + "username": { + "message": "Brugernavn" + }, + "password": { + "message": "Adgangskode" + }, + "passphrase": { + "message": "Adgangssætning" + }, + "favorite": { + "message": "Favorit" + }, + "notes": { + "message": "Notater" + }, + "note": { + "message": "Notat" + }, + "editItem": { + "message": "Redigér element" + }, + "folder": { + "message": "Mappe" + }, + "deleteItem": { + "message": "Slet element" + }, + "viewItem": { + "message": "Vis element" + }, + "launch": { + "message": "Start" + }, + "website": { + "message": "Hjemmeside" + }, + "toggleVisibility": { + "message": "Slå synlighed til/fra" + }, + "manage": { + "message": "Håndtér" + }, + "other": { + "message": "Andre" + }, + "rateExtension": { + "message": "Bedøm udvidelsen" + }, + "rateExtensionDesc": { + "message": "Overvej om du vil hjælpe os med en god anmeldelse!" + }, + "browserNotSupportClipboard": { + "message": "Din webbrowser understøtter ikke udklipsholder kopiering. Kopiér det manuelt i stedet." + }, + "verifyIdentity": { + "message": "Bekræft identitet" + }, + "yourVaultIsLocked": { + "message": "Din boks er låst. Bekræft din identitet for at fortsætte." + }, + "unlock": { + "message": "Lås op" + }, + "loggedInAsOn": { + "message": "Logget ind som $EMAIL$ på $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ugyldig hovedadgangskode" + }, + "vaultTimeout": { + "message": "Boks timeout" + }, + "lockNow": { + "message": "Lås nu" + }, + "immediately": { + "message": "Straks" + }, + "tenSeconds": { + "message": "10 sekunder" + }, + "twentySeconds": { + "message": "20 sekunder" + }, + "thirtySeconds": { + "message": "30 sekunder" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minutter" + }, + "fiveMinutes": { + "message": "5 minutter" + }, + "fifteenMinutes": { + "message": "15 minutter" + }, + "thirtyMinutes": { + "message": "30 minutter" + }, + "oneHour": { + "message": "1 time" + }, + "fourHours": { + "message": "4 timer" + }, + "onLocked": { + "message": "Når systemet låses" + }, + "onRestart": { + "message": "Ved genstart af browseren" + }, + "never": { + "message": "Aldrig" + }, + "security": { + "message": "Sikkerhed" + }, + "errorOccurred": { + "message": "Der er opstået en fejl" + }, + "emailRequired": { + "message": "E-mailadresse er påkrævet." + }, + "invalidEmail": { + "message": "Ugyldig e-mailadresse." + }, + "masterPassRequired": { + "message": "Hovedadgangskode er påkrævet." + }, + "masterPassLength": { + "message": "Hovedadgangskoden skal være på mindst 8 tegn." + }, + "masterPassDoesntMatch": { + "message": "De to adgangskoder matcher ikke." + }, + "newAccountCreated": { + "message": "Din nye konto er oprettet! Du kan nu logge ind." + }, + "masterPassSent": { + "message": "Vi har sendt dig en e-mail med dit hovedadgangskodetip." + }, + "verificationCodeRequired": { + "message": "Bekræftelseskode er påkrævet." + }, + "invalidVerificationCode": { + "message": "Ugyldig bekræftelseskode" + }, + "valueCopied": { + "message": "$VALUE$ kopieret", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Ikke i stand til at auto-udfylde det valgte element på denne side. Kopiér og indsæt dataene i stedet for." + }, + "loggedOut": { + "message": "Logget ud" + }, + "loginExpired": { + "message": "Din login-session er udløbet." + }, + "logOutConfirmation": { + "message": "Er du sikker på, du vil logge ud?" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nej" + }, + "unexpectedError": { + "message": "Der opstod en uventet fejl." + }, + "nameRequired": { + "message": "Navn er påkrævet." + }, + "addedFolder": { + "message": "Tilføjede mappe" + }, + "changeMasterPass": { + "message": "Skift hovedadgangskode" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kan ændre din hovedadgangskode i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "twoStepLoginConfirmation": { + "message": "To-trins login gør din konto mere sikker ved at kræve, at du verificerer dit login med en anden enhed, med en sikkerhedsnøgle, autentificerings app, SMS, telefonopkald eller e-mail. To-trins login kan aktiveres i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "editedFolder": { + "message": "Redigerede mappe" + }, + "deleteFolderConfirmation": { + "message": "Er du sikker på du vil slette denne mappe?" + }, + "deletedFolder": { + "message": "Slettede mappe" + }, + "gettingStartedTutorial": { + "message": "Sådan kommer du i gang" + }, + "gettingStartedTutorialVideo": { + "message": "Se vores introduktion for at lære hvordan du får mest ud af browser-udvidelsen." + }, + "syncingComplete": { + "message": "Synkronisering fuldført" + }, + "syncingFailed": { + "message": "Synkronisering mislykkedes" + }, + "passwordCopied": { + "message": "Adgangskode kopieret" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Ny URI" + }, + "addedItem": { + "message": "Tilføjede element" + }, + "editedItem": { + "message": "Redigerede element" + }, + "deleteItemConfirmation": { + "message": "Er du sikker på, at du sende til papirkurven?" + }, + "deletedItem": { + "message": "Element sendt til papirkurven" + }, + "overwritePassword": { + "message": "Overskriv adgangskode" + }, + "overwritePasswordConfirmation": { + "message": "Er du sikker på, at du vil overskrive den aktuelle adgangskode?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Søg mappe" + }, + "searchCollection": { + "message": "Søg samling" + }, + "searchType": { + "message": "Søgetype" + }, + "noneFolder": { + "message": "Ingen mappe", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Deaktivér Tilføj login notifikation" + }, + "addLoginNotificationDesc": { + "message": "\"Tilføj login notifikation\" spørger dig automatisk om du vil gemme nye logins til din boks, når du logger ind med dem for første gang." + }, + "dontShowCardsCurrentTab": { + "message": "Vis ikke kort på fanebladet" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Kort fra din boks er vist på siden 'Aktuel fane' for nem adgang til automatisk udfyldning." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Vis ikke identiteter på fanebladet" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identiteter fra din boks er vist på siden 'Aktuel fane' for nem adgang til automatisk udfyldning." + }, + "clearClipboard": { + "message": "Ryd udklipsholder", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Fjern automatisk kopierede data fra din udklipsholder.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Skal Bitwarden huske denne adgangskode for dig?" + }, + "notificationAddSave": { + "message": "Gem" + }, + "disableChangedPasswordNotification": { + "message": "Deaktivér besked om ændret adgangskode" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Besked om ændret adgangskode\" beder dig automatisk om at opdatere en adgangskode i din boks, når det opdager, at du har ændret den på en hjemmeside." + }, + "notificationChangeDesc": { + "message": "Vil du opdatere denne adgangskode i Bitwarden?" + }, + "notificationChangeSave": { + "message": "Opdatér" + }, + "disableContextMenuItem": { + "message": "Deaktivér Kontekst-menu valgmuligheder" + }, + "disableContextMenuItemDesc": { + "message": "Kontekst-menu valgmuligheder giver hurtig adgang til adgangskode generering og login til hjemmesiden i din aktuelle fane." + }, + "defaultUriMatchDetection": { + "message": "Standard URI matchmetode", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Vælg den standard måde, som URI matchmetode håndteres til logins, når du udfører handlinger som f.eks. Auto-udfyld." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Skift applikationens farvetema." + }, + "dark": { + "message": "Mørk", + "description": "Dark color" + }, + "light": { + "message": "Lys", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solariseret mørk", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Eksportér boks" + }, + "fileFormat": { + "message": "Filformat" + }, + "warning": { + "message": "ADVARSEL", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Bekræft eksport af boks" + }, + "exportWarningDesc": { + "message": "Denne eksport indeholder dine boksdata i ukrypteret form. Du bør ikke gemme eller sende den eksporterede fil over usikre kanaler (f.eks. e-mail). Slet den straks efter at du er færdig med at bruge den." + }, + "encExportKeyWarningDesc": { + "message": "Denne eksport krypterer dine data vha. din kontos krypteringsnøgle. Roterer du på et tidspunkt denne kontokrypteringsnøgle, skal du eksportere igen, da du ikke vil kunne dekryptere denne eksportfil." + }, + "encExportAccountWarningDesc": { + "message": "Kontokrypteringsnøgler er unikke for hver Bitwarden-brugerkonto, så du kan ikke importere en krypteret eksport til en anden konto." + }, + "exportMasterPassword": { + "message": "Indtast din hovedadgangskode for at eksportere dine data fra boksen." + }, + "shared": { + "message": "Delt" + }, + "learnOrg": { + "message": "Få mere at vide om organisationer" + }, + "learnOrgConfirmation": { + "message": "Bitwarden giver dig mulighed for at dele elementer i din boks med andre ved hjælp af en organisation. Vil du besøge bitwarden.com-webstedet for at få mere at vide?" + }, + "moveToOrganization": { + "message": "Flyt til organisation" + }, + "share": { + "message": "Del" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ flyttet til $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vælg den organisation, som du vil flytte dette emne til. Flytning overfører ejerskab af emnet til organisationen, og du vil efter flytningen ikke længere være den direkte ejer af emnet." + }, + "learnMore": { + "message": "Lær mere" + }, + "authenticatorKeyTotp": { + "message": "Autentificeringsnøgle (TOTP)" + }, + "verificationCodeTotp": { + "message": "Bekræftelseskode (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopiér bekræftelseskoden" + }, + "attachments": { + "message": "Vedhæftninger" + }, + "deleteAttachment": { + "message": "Slet vedhæftning" + }, + "deleteAttachmentConfirmation": { + "message": "Er du sikker på du vil slette denne vedhæftning?" + }, + "deletedAttachment": { + "message": "Slettet vedhæftning" + }, + "newAttachment": { + "message": "Tilføj ny vedhæftning" + }, + "noAttachments": { + "message": "Ingen vedhæftninger." + }, + "attachmentSaved": { + "message": "Vedhæftningen er blevet gemt." + }, + "file": { + "message": "Fil" + }, + "selectFile": { + "message": "Vælg en fil." + }, + "maxFileSize": { + "message": "Maksimum filstørrelse er 500 MB." + }, + "featureUnavailable": { + "message": "Funktion ikke tilgængelig" + }, + "updateKey": { + "message": "Du kan ikke bruge denne funktion, før du opdaterer din krypteringsnøgle." + }, + "premiumMembership": { + "message": "Premium-medlemskab" + }, + "premiumManage": { + "message": "Håndtér medlemsskab" + }, + "premiumManageAlert": { + "message": "Du kan håndtere dit medlemskab i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "premiumRefresh": { + "message": "Opdatér medlemskab" + }, + "premiumNotCurrentMember": { + "message": "Du er i øjeblikket ikke premium-medlem." + }, + "premiumSignUpAndGet": { + "message": "Tilmeld dig et premium-medlemskab og få:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB krypteret lager til vedhæftede filer." + }, + "ppremiumSignUpTwoStep": { + "message": "Yderligere to-trins login muligheder såsom YubiKey, FIDO U2F og Duo." + }, + "ppremiumSignUpReports": { + "message": "Adgangskodehygiejne, kontosundhed og rapporter om datalæk til at holde din boks sikker." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verifikationskode (2FA) generator til logins i din boks." + }, + "ppremiumSignUpSupport": { + "message": "Prioriteret kundeservice." + }, + "ppremiumSignUpFuture": { + "message": "Alle fremtidige premium-funktioner. Mere kommer snart!" + }, + "premiumPurchase": { + "message": "Køb premium" + }, + "premiumPurchaseAlert": { + "message": "Du kan købe premium-medlemskab i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "premiumCurrentMember": { + "message": "Du er premium-medlem!" + }, + "premiumCurrentMemberThanks": { + "message": "Tak fordi du støtter Bitwarden." + }, + "premiumPrice": { + "message": "Alt dette for kun $PRICE$ /år!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Opdatering færdig" + }, + "disableAutoTotpCopy": { + "message": "Deaktivér Automatisk TOTP kopi" + }, + "disableAutoTotpCopyDesc": { + "message": "Hvis dit login har en autentificeringsnøgle tilknyttet, kopieres TOTP verifikationskoden automatisk til din udklipsholder når du auto-udfylder login." + }, + "disableAutoBiometricsPrompt": { + "message": "Bed ikke om biometri ved start" + }, + "premiumRequired": { + "message": "Premium påkrævet" + }, + "premiumRequiredDesc": { + "message": "Premium-medlemskab kræves for at anvende denne funktion." + }, + "enterVerificationCodeApp": { + "message": "Indtast den 6-cifrede verifikationskode fra din autentificerings-app." + }, + "enterVerificationCodeEmail": { + "message": "Indtast den 6-cifrede verifikationskode, der blev sendt til $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Bekræftelsesmail sendt til $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Husk mig" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verifikationskode-email igen" + }, + "useAnotherTwoStepMethod": { + "message": "Brug en anden to-trins login metode" + }, + "insertYubiKey": { + "message": "Indsæt din YubiKey i din computers USB-port, og tryk derefter på dens knap." + }, + "insertU2f": { + "message": "Indsæt din sikkerhedsnøgle i din computers USB-port. Hvis den har en knap, tryk på den." + }, + "webAuthnNewTab": { + "message": "For at starte WebAuthn 2FA-verifikationen. Klik på knappen nedenfor for at åbne en ny fane og følg instruktionerne i den nye fane." + }, + "webAuthnNewTabOpen": { + "message": "Åbn ny fane" + }, + "webAuthnAuthenticate": { + "message": "Godkend WebAuthn" + }, + "loginUnavailable": { + "message": "Login ikke tilgængelig" + }, + "noTwoStepProviders": { + "message": "Denne konto har to-trins login aktiveret, men ingen af de konfigurerede to-trins udbydere understøttes af denne webbrowser." + }, + "noTwoStepProviders2": { + "message": "Du skal bruge en understøttet webbrowser (såsom Chrome) og/eller tilføje ekstra udbydere, der understøttes bedre på tværs af webbrowsere (f.eks. en autentificering app)." + }, + "twoStepOptions": { + "message": "To-trins login muligheder" + }, + "recoveryCodeDesc": { + "message": "Mistet adgang til alle dine to-faktor-udbydere? Brug din genoprettelseskode til at deaktivere alle to-faktor udbydere på din konto." + }, + "recoveryCodeTitle": { + "message": "Gendannelseskode" + }, + "authenticatorAppTitle": { + "message": "Autentificerings-app" + }, + "authenticatorAppDesc": { + "message": "Brug en autentificerings app (f.eks. Authy eller Google Autentificering) til at generere tidsbaserede bekræftelseskoder.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP sikkerhedsnøgle" + }, + "yubiKeyDesc": { + "message": "Brug en YubiKey til at få adgang til din konto. Virker med YubiKey 4, 4 Nano, 4C og NEO enheder." + }, + "duoDesc": { + "message": "Bekræft med Duo sikkerhed ved hjælp af Duo Mobile app, SMS, telefonopkald eller U2F sikkerhedsnøgle.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Bekræft med Duo sikkerhed for din organisation ved hjælp af Duo Mobile app, SMS, telefonopkald eller U2F sikkerhedsnøgle.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Brug en hvilken som helst WebAuthn-aktiveret sikkerhedsnøgle til at få adgang til din konto." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Bekræftelseskoder vil blive e-mailet til dig." + }, + "selfHostedEnvironment": { + "message": "Selv-hosted miljø" + }, + "selfHostedEnvironmentFooter": { + "message": "Angiv grund-URL'en i din lokal-hostede Bitwarden-installation." + }, + "customEnvironment": { + "message": "Brugerdefineret miljø" + }, + "customEnvironmentFooter": { + "message": "Til avancerede brugere. Du kan angive grund-URL'en for hver service uafhængigt." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API server URL" + }, + "webVaultUrl": { + "message": "Web-boks server URL" + }, + "identityUrl": { + "message": "Identitets-server URL" + }, + "notificationsUrl": { + "message": "Meddelelsesserver URL" + }, + "iconsUrl": { + "message": "Ikonserver URL" + }, + "environmentSaved": { + "message": "Miljøets URLs er blevet gemt." + }, + "enableAutoFillOnPageLoad": { + "message": "Aktivér Auto-udfyld ved sideindlæsning" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Hvis en login-formular er opdaget, så udfør automatisk en auto-udfyld når hjemmesiden indlæses." + }, + "experimentalFeature": { + "message": "Dette er i øjeblikket en eksperimentel funktion. Brug på egen risiko." + }, + "defaultAutoFillOnPageLoad": { + "message": "Standardindstilling for autofyld for loginelementer" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Når du har aktiveret auto-udfyldning ved sideindlæsning, kan du aktivere eller deaktivere funktionen for individuelle loginelementer. Dette er standardindstillingen for loginelementer, der ikke er konfigureret separat." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-udfyld ved sideindlæsning (hvis aktiveret i Indstillinger)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Anvend standardindstilling" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-udfyld ved sideindlæsning" + }, + "autoFillOnPageLoadNo": { + "message": "Auto-udfyld ikke ved sideindlæsning" + }, + "commandOpenPopup": { + "message": "Åbn boks popup" + }, + "commandOpenSidebar": { + "message": "Åbn boks i sidebjælken" + }, + "commandAutofillDesc": { + "message": "Auto-udfyld det sidste anvendte login for den aktuelle hjemmeside" + }, + "commandGeneratePasswordDesc": { + "message": "Generér en ny tilfældig adgangskode og kopiér den til udklipsholderen" + }, + "commandLockVaultDesc": { + "message": "Lås boksen" + }, + "privateModeWarning": { + "message": "Understøttelse af privat tilstand er eksperimentel, og nogle funktioner er begrænsede." + }, + "customFields": { + "message": "Brugerdefinerede felter" + }, + "copyValue": { + "message": "Kopiér værdi" + }, + "value": { + "message": "Værdi" + }, + "newCustomField": { + "message": "Nyt brugerdefineret felt" + }, + "dragToSort": { + "message": "Træk for at sortere" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Skjult" + }, + "cfTypeBoolean": { + "message": "Boolsk" + }, + "cfTypeLinked": { + "message": "Forbundet", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Forbundet værdi", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Ved at klikke uden for pop-up-vinduet for at tjekke din e-mail for din bekræftelseskode vil få denne popup til at lukke. Vil du åbne denne popup i et nyt vindue, så det ikke lukker?" + }, + "popupU2fCloseMessage": { + "message": "Denne browser kan ikke behandle U2F-anmodninger i dette popup-vindue. Vil du åbne denne popup i et nyt vindue, så du kan logge ind ved hjælp af U2F?" + }, + "disableFavicon": { + "message": "Slå webikoner fra" + }, + "disableFaviconDesc": { + "message": "Webikoner vises som et genkendeligt billede ved siden af hvert loginelement i din boks." + }, + "disableBadgeCounter": { + "message": "Deaktivér Badge-tæller" + }, + "disableBadgeCounterDesc": { + "message": "Badge-tæller angiver, hvor mange logins du har for den aktuelle side i din boks." + }, + "cardholderName": { + "message": "Kortindehaverens navn" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Type" + }, + "expirationMonth": { + "message": "Udløbsmåned" + }, + "expirationYear": { + "message": "Udløbsår" + }, + "expiration": { + "message": "Udløb" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Marts" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Sikkerhedskode" + }, + "ex": { + "message": "eks." + }, + "title": { + "message": "Titel" + }, + "mr": { + "message": "Hr" + }, + "mrs": { + "message": "Fru" + }, + "ms": { + "message": "Frk" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Fornavn" + }, + "middleName": { + "message": "Mellemnavn" + }, + "lastName": { + "message": "Efternavn" + }, + "fullName": { + "message": "Fulde navn" + }, + "identityName": { + "message": "Identitetsnavn" + }, + "company": { + "message": "Virksomhed" + }, + "ssn": { + "message": "CPR-nummer" + }, + "passportNumber": { + "message": "Pasnummer" + }, + "licenseNumber": { + "message": "Kørekortnummer" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresse" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "By" + }, + "stateProvince": { + "message": "Region" + }, + "zipPostalCode": { + "message": "Postnummer" + }, + "country": { + "message": "Land" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Sikret notat" + }, + "typeCard": { + "message": "Kort" + }, + "typeIdentity": { + "message": "Identitet" + }, + "passwordHistory": { + "message": "Adgangskodehistorik" + }, + "back": { + "message": "Tilbage" + }, + "collections": { + "message": "Samlinger" + }, + "favorites": { + "message": "Favoritter" + }, + "popOutNewWindow": { + "message": "Åbn i et nyt vindue" + }, + "refresh": { + "message": "Opdater" + }, + "cards": { + "message": "Kort" + }, + "identities": { + "message": "Identiteter" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Sikre notater" + }, + "clear": { + "message": "Ryd", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Undersøg om adgangskoden er blevet afsløret." + }, + "passwordExposed": { + "message": "Denne adgangskode er blevet afsløret $VALUE$ gang(e) i datalæk. Du burde skifte den.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Denne adgangskode er ikke fundet i nogen kendte datalæk. Den burde være sikker at bruge." + }, + "baseDomain": { + "message": "Grund-domæne", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Vært", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Nøjagtig" + }, + "startsWith": { + "message": "Begynder med" + }, + "regEx": { + "message": "Regulært udtryk", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Matchmetode", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standard matchmetode", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Skift indstillinger" + }, + "toggleCurrentUris": { + "message": "Skift aktuelle URI'er", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Aktuel URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Typer" + }, + "allItems": { + "message": "Alle elementer" + }, + "noPasswordsInList": { + "message": "Der er ingen kodeord at vise." + }, + "remove": { + "message": "Fjern" + }, + "default": { + "message": "Standard" + }, + "dateUpdated": { + "message": "Opdateret", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Adgangskode opdateret", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Er du sikker på, at du vil bruge indstillingen \"Aldrig\"? Hvis du sætter dine låseindstillinger til \"Aldrig\" gemmes din boks krypteringsnøgle på din enhed. Hvis du bruger denne indstilling, skal du sikre dig, at du holder din enhed ordentligt beskyttet." + }, + "noOrganizationsList": { + "message": "Du tilhører ikke nogen organisationer. Organisationer giver dig mulighed for at dele elementer med andre brugere på en sikker måde." + }, + "noCollectionsInList": { + "message": "Der er ingen samlinger at vise." + }, + "ownership": { + "message": "Ejerskab" + }, + "whoOwnsThisItem": { + "message": "Hvem ejer dette element?" + }, + "strong": { + "message": "Stærk", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "God", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Svag", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Svag hovedadgangskode" + }, + "weakMasterPasswordDesc": { + "message": "Hovedadgangskoden du har valgt er svag. Du skal bruge en stærk hovedadgangskode (eller en adgangssætning) for at beskytte din Bitwarden-konto korrekt. Er du sikker på, at du vil bruge denne hovedadgangskode?" + }, + "pin": { + "message": "Pinkode", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Lås op med pinkode" + }, + "setYourPinCode": { + "message": "Indstil din pinkode til at låse Bitwarden op. Dine pin-indstillinger nulstilles, hvis du nogensinde logger helt ud af programmet." + }, + "pinRequired": { + "message": "Pinkode er påkrævet." + }, + "invalidPin": { + "message": "Ugyldig pinkode." + }, + "unlockWithBiometrics": { + "message": "Lås op med biometri" + }, + "awaitDesktop": { + "message": "Afventer bekræftelse fra skrivebordet" + }, + "awaitDesktopDesc": { + "message": "Bekræft venligst brug af biometri i Bitwarden skrivebordsapplikationen for at aktivere biometri for browseren." + }, + "lockWithMasterPassOnRestart": { + "message": "Lås med hovedadgangskode ved genstart af browseren" + }, + "selectOneCollection": { + "message": "Du skal vælge minimum én samling." + }, + "cloneItem": { + "message": "Klon element" + }, + "clone": { + "message": "Klon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Én eller flere organisationspolitikker påvirker dine generatorindstillinger." + }, + "vaultTimeoutAction": { + "message": "Boks timeout-handling" + }, + "lock": { + "message": "Lås", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papirkurv", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Søg i papirkurven" + }, + "permanentlyDeleteItem": { + "message": "Slet element permanent" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Er du sikker på, at du vil slette dette element permanent?" + }, + "permanentlyDeletedItem": { + "message": "Element slettet permanent" + }, + "restoreItem": { + "message": "Gendan element" + }, + "restoreItemConfirmation": { + "message": "Er du sikker på, at du vil gendanne dette element?" + }, + "restoredItem": { + "message": "Element gendannet" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Ved at logge ud fjernes al adgang til din boks og kræver online-godkendelse efter timeout-perioden. Er du sikker på, at du vil bruge denne indstilling?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bekræft timeout-handling" + }, + "autoFillAndSave": { + "message": "Autoudfyld og gem" + }, + "autoFillSuccessAndSavedUri": { + "message": "Autoudfyldte element og URI gemt" + }, + "autoFillSuccess": { + "message": "Autoudfyldte element" + }, + "setMasterPassword": { + "message": "Indstil hovedadgangskode" + }, + "masterPasswordPolicyInEffect": { + "message": "Én eller flere organisationspolitikker kræver, at din hovedadgangskode opfylder flg. krav:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum kompleksitetsscore på $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimumslængde på $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Indeholder ét eller flere store bogstaver" + }, + "policyInEffectLowercase": { + "message": "Indeholder ét eller flere små bogstaver" + }, + "policyInEffectNumbers": { + "message": "Indeholder ét eller flere cifre" + }, + "policyInEffectSpecial": { + "message": "Indeholder ét eller flere af følgende specialtegn $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Din nye hovedadgangskode opfylder ikke politikkravene." + }, + "acceptPolicies": { + "message": "Ved at markere dette felt accepterer du følgende:" + }, + "acceptPoliciesError": { + "message": "Servicevilkår og fortrolighedspolitik er ikke blevet bekræftet." + }, + "termsOfService": { + "message": "Servicevilkår" + }, + "privacyPolicy": { + "message": "Fortrolighedspolitik" + }, + "hintEqualsPassword": { + "message": "Dit adgangskodetip kan ikke være det samme som din adgangskode." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Verifikation af skrivebordssynkronisering" + }, + "desktopIntegrationVerificationText": { + "message": "Bekræft venligst at skrivebordsprogrammet viser dette fingeraftryk: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browserintegration er ikke aktiveret" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browserintegration er ikke aktiveret i Bitwarden skrivebordsapplikationen. Aktivér det i indstillingerne i skrivebordsprogrammet." + }, + "startDesktopTitle": { + "message": "Start Bitwarden skrivebordsapplikationen" + }, + "startDesktopDesc": { + "message": "Bitwarden skrivebordsapplikationen skal startes, før oplåsning med biometri kan bruges." + }, + "errorEnableBiometricTitle": { + "message": "Kan ikke aktivere biometri" + }, + "errorEnableBiometricDesc": { + "message": "Handlingen blev annulleret af skrivebordsprogrammet" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Skrivebordsapplikation ugyldiggjorde den sikre kommunikationskanal. Prøv denne handling igen" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Skrivebordskommunikation afbrudt" + }, + "nativeMessagingWrongUserDesc": { + "message": "Skrivebordsapplikationen er logget ind på en anden konto. Sørg for, at begge applikationer er logget ind på den samme konto." + }, + "nativeMessagingWrongUserTitle": { + "message": "Konto mismatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometri ikke aktiveret" + }, + "biometricsNotEnabledDesc": { + "message": "Browserbiometri kræver, at desktop-biometri er aktiveret i indstillingerne først." + }, + "biometricsNotSupportedTitle": { + "message": "Biometri ikke understøttet" + }, + "biometricsNotSupportedDesc": { + "message": "Browserbiometri understøttes ikke på denne enhed." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Tilladelse ikke givet" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Uden tilladelse til at kommunikere med Bitwarden skrivebordsapplikationen kan vi ikke levere biometri i browserudvidelsen. Prøv igen." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Fejl ved anmodning om tilladelse" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Denne handling kan ikke udføres i sidebjælken, prøv handlingen igen i popup tilstand eller i et nyt vindue." + }, + "personalOwnershipSubmitError": { + "message": "På grund af en virksomhedspolitik er du begrænset til at gemme elementer i din personlige boks. Skift ejerskabsindstillingen til en organisation, og vælg blandt de tilgængelige samlinger." + }, + "personalOwnershipPolicyInEffect": { + "message": "En organisationspolitik påvirker dine ejerskabsmuligheder." + }, + "excludedDomains": { + "message": "Ekskluderede domæner" + }, + "excludedDomainsDesc": { + "message": "Bitwarden vil ikke bede om at gemme login-detaljer for disse domæner. Du skal opdatere siden for at ændringerne kan træde i kraft." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ er ikke et gyldigt domæne", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Søg i Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Tilføj Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Tekst" + }, + "sendTypeFile": { + "message": "Fil" + }, + "allSends": { + "message": "Alle Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maksimalt adgangsantal nået", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Udløbet" + }, + "pendingDeletion": { + "message": "Afventer sletning" + }, + "passwordProtected": { + "message": "Kodeordsbeskyttet" + }, + "copySendLink": { + "message": "Kopiér Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Fjern adgangskode" + }, + "delete": { + "message": "Slet" + }, + "removedPassword": { + "message": "Adgangskode fjernet" + }, + "deletedSend": { + "message": "Send slettet", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Deaktiveret" + }, + "removePasswordConfirmation": { + "message": "Er du sikker på, at du vil fjerne adgangskoden?" + }, + "deleteSend": { + "message": "Slet Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Er du sikker på, at du vil slette denne Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Redigér Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Hvilken type Send er denne?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Et venligt navn til at beskrive denne Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Den fil, du vil sende." + }, + "deletionDate": { + "message": "Sletningsdato" + }, + "deletionDateDesc": { + "message": "Send'en slettes permanent på den angivne dato og tid.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Udløbsdato" + }, + "expirationDateDesc": { + "message": "Hvis angivet, vil adgangen til denne Send udløbe på den angivne dato og tidspunkt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dag" + }, + "days": { + "message": "$DAYS$ dage", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Tilpasset" + }, + "maximumAccessCount": { + "message": "Maksimalt antal tilgange" + }, + "maximumAccessCountDesc": { + "message": "Hvis opsat, vil brugere ikke længere kunne tilgå denne Send, når det maksimale adgangsantal er nået.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Valgfrit brugeradgangskodekrav for at tilgå denne Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notater om denne Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Deaktivér denne Send, så ingen kan tilgå den.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kopiér denne Sends link til udklipsholderen når du gemmer.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Den tekst, du vil sende." + }, + "sendHideText": { + "message": "Skjul denne Sends tekst som standard.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Aktuelt antal tilgange" + }, + "createSend": { + "message": "Opret ny Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Ny adgangskode" + }, + "sendDisabled": { + "message": "Send deaktiveret", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Du kan grundet en virksomhedspolitik kun slette en eksisterende Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send oprettet", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send opdateret", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "For at vælge en fil, åben udvidelsen i sidepanelet (om muligt) eller pop ud til et nyt vindue ved at klikke på dette banner." + }, + "sendFirefoxFileWarning": { + "message": "For at vælge en fil i Firefox skal du flytte udvidelsen til sidepanelet eller åbne i et nyt vindue ved at klikke på dette banner." + }, + "sendSafariFileWarning": { + "message": "For at vælge en fil i Safari skal du åbne i et nyt vindue ved at klikke på dette banner." + }, + "sendFileCalloutHeader": { + "message": "Før du starter" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "For at bruge en datovælger i kalenderstil skal du", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klikke her", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "for at åbne dit vindue.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Den angivne udløbsdato er ikke gyldig." + }, + "deletionDateIsInvalid": { + "message": "Den angivne sletningsdato er ikke gyldig." + }, + "expirationDateAndTimeRequired": { + "message": "Der kræves en udløbsdato og -tid." + }, + "deletionDateAndTimeRequired": { + "message": "En sletningsdato og -tid er påkrævet." + }, + "dateParsingError": { + "message": "Der opstod en fejl under forsøget på at gemme dine sletnings- og udløbsdatoer." + }, + "hideEmail": { + "message": "Skjul min e-mailadresse for modtagere." + }, + "sendOptionsPolicyInEffect": { + "message": "Én eller flere organisationspolitikker påvirker dine Send-valgmuligheder." + }, + "passwordPrompt": { + "message": "Genanmodning om hovedadgangskode" + }, + "passwordConfirmation": { + "message": "Bekræftelse af hovedadgangskode" + }, + "passwordConfirmationDesc": { + "message": "Denne handling er beskyttet. For at fortsætte, indtast venligst din hovedadgangskode igen for at bekræfte din identitet." + }, + "emailVerificationRequired": { + "message": "E-mailbekræftelse kræves" + }, + "emailVerificationRequiredDesc": { + "message": "Du skal bekræfte din e-mail for at bruge denne funktion. Du kan bekræfte din e-mail i web-boksen." + }, + "updatedMasterPassword": { + "message": "Hovedadgangskode opdateret" + }, + "updateMasterPassword": { + "message": "Opdatér hovedadgangskode" + }, + "updateMasterPasswordWarning": { + "message": "Dit hovedadgangskode blev for nylig ændret af en administrator i din organisation. For at få adgang til boksen skal du opdatere din hovedadgangskode nu. Hvis du fortsætter, logges du ud af din nuværende session, hvilket kræver, at du logger ind igen. Aktive sessioner på andre enheder kan fortsætte med at være aktive i op til én time." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Auto-indrullering" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Denne organisation har en virksomhedspolitik, der automatisk tilmelder dig til nulstilling af adgangskode. Tilmelding giver organisationsadministratorer mulighed for at skifte din hovedadgangskode." + }, + "selectFolder": { + "message": "Vælg mappe..." + }, + "ssoCompleteRegistration": { + "message": "For at fuldføre indlogning med SSO skal du opsætte en hovedadgangskode for at få adgang til samt beskytte din boks." + }, + "hours": { + "message": "Timer" + }, + "minutes": { + "message": "Minutter" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Din organisations politikker påvirker din boks-timeout. Maksimalt tilladt boks-timeout er $HOURS$ time(r) og $MINUTES$ minut(ter)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Din boks-timeout overskrider de begrænsninger, der er fastsat af din organisation." + }, + "vaultExportDisabled": { + "message": "Bokseksport deaktiveret" + }, + "personalVaultExportPolicyInEffect": { + "message": "En eller flere organisationspolitikker forhindrer dig i at eksportere din personlige boks." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Kan ikke identificere et gyldigt formularelement. Prøv i stedet at inspicere HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Ingen entydig identifikator fundet." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ bruger SSO med en selv-hostet nøgleserver. En hovedadgangskode er ikke længere påkrævet for at logge ind for medlemmer af denne organisation.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Forlad organisation" + }, + "removeMasterPassword": { + "message": "Fjern hovedadgangskode" + }, + "removedMasterPassword": { + "message": "Hovedadgangskode fjernet." + }, + "leaveOrganizationConfirmation": { + "message": "Er du sikker på, at du vil forlade denne organisation?" + }, + "leftOrganization": { + "message": "Du har forladt organisationen." + }, + "toggleCharacterCount": { + "message": "Slå tegnantal til/fra" + }, + "sessionTimeout": { + "message": "Din session er udløbet. Gå tilbage og prøv at logge ind igen." + }, + "exportingPersonalVaultTitle": { + "message": "Eksporterer personlig boks" + }, + "exportingPersonalVaultDescription": { + "message": "Kun de personlige bokselementer tilknyttet $EMAIL$ eksporteres. Organisationsbokseelementer medtages ikke.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Fejl" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/de/messages.json b/apps/browser/src/_locales/de/messages.json new file mode 100644 index 0000000000..37413975f8 --- /dev/null +++ b/apps/browser/src/_locales/de/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Kostenloser Passwortmanager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden ist ein sicherer und kostenloser Passwortmanager für all Ihre Geräte.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Du musst dich anmelden oder einen neuen Account erstellen, um auf den Tresor zugreifen zu können." + }, + "createAccount": { + "message": "Konto erstellen" + }, + "login": { + "message": "Anmelden" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "Abbrechen" + }, + "close": { + "message": "Schließen" + }, + "submit": { + "message": "Absenden" + }, + "emailAddress": { + "message": "E-Mail Adresse" + }, + "masterPass": { + "message": "Master-Passwort" + }, + "masterPassDesc": { + "message": "Das Master-Passwort wird verwendet, um den Tresor zu öffnen. Es ist sehr wichtig, dass du das Passwort nicht vergisst, da es keine Möglichkeit gibt es zurückzusetzen." + }, + "masterPassHintDesc": { + "message": "Ein Master-Passwort-Hinweis kann dir helfen, dich an das Passwort zu erinnern, solltest du es vergessen." + }, + "reTypeMasterPass": { + "message": "Master-Passwort wiederholen" + }, + "masterPassHint": { + "message": "Master-Passwort-Hinweis (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "Mein Tresor" + }, + "tools": { + "message": "Werkzeuge" + }, + "settings": { + "message": "Einstellungen" + }, + "currentTab": { + "message": "Aktueller Tab" + }, + "copyPassword": { + "message": "Passwort kopieren" + }, + "copyNote": { + "message": "Notiz kopieren" + }, + "copyUri": { + "message": "URI kopieren" + }, + "copyUsername": { + "message": "Nutzernamen Kopieren" + }, + "copyNumber": { + "message": "Nummer kopieren" + }, + "copySecurityCode": { + "message": "Sicherheitscode kopieren" + }, + "autoFill": { + "message": "Auto-Ausfüllen" + }, + "generatePasswordCopied": { + "message": "Passwort generieren (kopiert)" + }, + "copyElementIdentifier": { + "message": "Benutzerdefinierten Feldnamen kopieren" + }, + "noMatchingLogins": { + "message": "Keine passenden Zugangsdaten." + }, + "unlockVaultMenu": { + "message": "Entsperre deinen Tresor" + }, + "loginToVaultMenu": { + "message": "In deinem Tresor anmelden" + }, + "autoFillInfo": { + "message": "Für den aktuellen Browser-Tab gibt es keine passenden Zugangsdaten, welche automatisch ausgefüllt werden können." + }, + "addLogin": { + "message": "Zugangsdaten hinzufügen" + }, + "addItem": { + "message": "Neuer Eintrag" + }, + "passwordHint": { + "message": "Passwort-Hinweis" + }, + "enterEmailToGetHint": { + "message": "Gib die E-Mail-Adresse deines Kontos ein, um den Hinweis für dein Master-Passwort zu erhalten." + }, + "getMasterPasswordHint": { + "message": "Hinweis zum Masterpasswort erhalten" + }, + "continue": { + "message": "Weiter" + }, + "sendVerificationCode": { + "message": "Einen Bestätigungscode an deine E-Mail senden" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code gesendet" + }, + "verificationCode": { + "message": "Verifizierungscode" + }, + "confirmIdentity": { + "message": "Bestätige deine Identität, um fortzufahren." + }, + "account": { + "message": "Konto" + }, + "changeMasterPassword": { + "message": "Master-Passwort ändern" + }, + "fingerprintPhrase": { + "message": "Prüfschlüssel", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Prüfschlüssel für deinen Account", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Zwei-Faktor Authentifizierung" + }, + "logOut": { + "message": "Abmelden" + }, + "about": { + "message": "Über uns" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Speichern" + }, + "move": { + "message": "Verschieben" + }, + "addFolder": { + "message": "Ordner hinzufügen" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Ordner bearbeiten" + }, + "deleteFolder": { + "message": "Ordner löschen" + }, + "folders": { + "message": "Ordner" + }, + "noFolders": { + "message": "Es gibt keine Ordner zum Anzeigen." + }, + "helpFeedback": { + "message": "Hilfe & Feedback" + }, + "sync": { + "message": "Synchronisierung" + }, + "syncVaultNow": { + "message": "Tresor jetzt synchronisieren" + }, + "lastSync": { + "message": "Letzte Synchronisation:" + }, + "passGen": { + "message": "Passwort-Generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Generiert automatisch ein starkes und einzigartiges Passwort." + }, + "bitWebVault": { + "message": "Bitwarden Web-Tresor" + }, + "importItems": { + "message": "Einträge importieren" + }, + "select": { + "message": "Auswählen" + }, + "generatePassword": { + "message": "Passwort generieren" + }, + "regeneratePassword": { + "message": "Password neu generieren" + }, + "options": { + "message": "Optionen" + }, + "length": { + "message": "Länge" + }, + "uppercase": { + "message": "Großbuchstaben (A-Z)" + }, + "lowercase": { + "message": "Kleinbuchstaben (a-z)" + }, + "numbers": { + "message": "Zahlen (0-9)" + }, + "specialCharacters": { + "message": "Sonderzeichen (!@#$%^&*)" + }, + "numWords": { + "message": "Anzahl der Wörter" + }, + "wordSeparator": { + "message": "Trennzeichen" + }, + "capitalize": { + "message": "Großschreiben", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Ziffer hinzufügen" + }, + "minNumbers": { + "message": "Mindestanzahl Zahlen" + }, + "minSpecial": { + "message": "Mindestanzahl Sonderzeichen" + }, + "avoidAmbChar": { + "message": "Mehrdeutige Zeichen vermeiden" + }, + "searchVault": { + "message": "Tresor durchsuchen" + }, + "edit": { + "message": "Bearbeiten" + }, + "view": { + "message": "Anzeigen" + }, + "noItemsInList": { + "message": "Keine Einträge zum Anzeigen vorhanden." + }, + "itemInformation": { + "message": "Eintrags-Information" + }, + "username": { + "message": "Nutzername" + }, + "password": { + "message": "Passwort" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favoriten" + }, + "notes": { + "message": "Notizen" + }, + "note": { + "message": "Notiz" + }, + "editItem": { + "message": "Eintrag bearbeiten" + }, + "folder": { + "message": "Ordner" + }, + "deleteItem": { + "message": "Eintrag löschen" + }, + "viewItem": { + "message": "Eintrag anzeigen" + }, + "launch": { + "message": "Öffnen" + }, + "website": { + "message": "Webseite" + }, + "toggleVisibility": { + "message": "Sichtbarkeit umschalten" + }, + "manage": { + "message": "Verwalten" + }, + "other": { + "message": "Sonstige" + }, + "rateExtension": { + "message": "Bewerte die Erweiterung" + }, + "rateExtensionDesc": { + "message": "Wir würden uns freuen, wenn du uns mit einer positiven Bewertung helfen könntest!" + }, + "browserNotSupportClipboard": { + "message": "Den Browser unterstützt das einfache Kopieren nicht. Bitte kopiere es manuell." + }, + "verifyIdentity": { + "message": "Identität verifizieren" + }, + "yourVaultIsLocked": { + "message": "Dein Tresor ist gesperrt. Überprüfe dein Master-Passwort um fortzufahren." + }, + "unlock": { + "message": "Entsperren" + }, + "loggedInAsOn": { + "message": "Eingeloggt als $EMAIL$ auf $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ungültiges Master-Passwort" + }, + "vaultTimeout": { + "message": "Tresor-Timeout" + }, + "lockNow": { + "message": "Jetzt sperren" + }, + "immediately": { + "message": "Sofort" + }, + "tenSeconds": { + "message": "10 Sekunden" + }, + "twentySeconds": { + "message": "20 Sekunden" + }, + "thirtySeconds": { + "message": "30 Sekunden" + }, + "oneMinute": { + "message": "1 Minute" + }, + "twoMinutes": { + "message": "2 Minuten" + }, + "fiveMinutes": { + "message": "5 Minuten" + }, + "fifteenMinutes": { + "message": "15 Minuten" + }, + "thirtyMinutes": { + "message": "30 Minuten" + }, + "oneHour": { + "message": "1 Stunde" + }, + "fourHours": { + "message": "4 Stunde" + }, + "onLocked": { + "message": "Wenn System gesperrt" + }, + "onRestart": { + "message": "Bei Browser-Neustart" + }, + "never": { + "message": "Nie" + }, + "security": { + "message": "Sicherheit" + }, + "errorOccurred": { + "message": "Ein Fehler ist aufgetaucht" + }, + "emailRequired": { + "message": "Die E-Mail Adresse wird benötigt." + }, + "invalidEmail": { + "message": "Ungültige E-Mail Adresse." + }, + "masterPassRequired": { + "message": "Das Master-Passwort wird benötigt." + }, + "masterPassLength": { + "message": "Das Master-Passwort muss mindestens 8 Zeichen lang sein." + }, + "masterPassDoesntMatch": { + "message": "Die Master-Passwort-Wiederholung stimmt nicht überein." + }, + "newAccountCreated": { + "message": "Dein neues Konto wurde erstellt! Du kannst dich jetzt anmelden." + }, + "masterPassSent": { + "message": "Wir haben dir eine E-Mail mit dem Master-Passwort-Hinweis geschickt." + }, + "verificationCodeRequired": { + "message": "Verifizierungscode wird benötigt." + }, + "invalidVerificationCode": { + "message": "Ungültiger Verifizierungscode" + }, + "valueCopied": { + "message": "$VALUE$ kopiert", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Die Felder dieser Seite konnten nicht automatisch ausgefüllt werden. Bitte Nutzernamen und/oder Passwort manuell kopieren." + }, + "loggedOut": { + "message": "Ausgeloggt" + }, + "loginExpired": { + "message": "Ihre Login-Sitzung ist abgelaufen." + }, + "logOutConfirmation": { + "message": "Bist du sicher, dass du dich abmelden willst?" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nein" + }, + "unexpectedError": { + "message": "Ein unerwarteter Fehler ist aufgetreten." + }, + "nameRequired": { + "message": "Der Name wird benötigt." + }, + "addedFolder": { + "message": "Ordner hinzugefügt" + }, + "changeMasterPass": { + "message": "Master-Passwort ändern" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kannst dein Master-Passwort im Bitwarden.com Web-Tresor ändern. Möchtest du die Seite jetzt öffnen?" + }, + "twoStepLoginConfirmation": { + "message": "Mit der Zwei-Faktor Authentifizierung wird dein Account zusätzlich abgesichert, da jede Anmeldung durch einen Sicherheitscode, eine Authentifizierungs-App, SMS, einen Anruf oder eine E-Mail verifiziert werden muss. Die Zwei-Faktor Authentifizierung kann im Bitwarden.com Web-Tresor aktiviert werden. Möchtest du die Seite jetzt öffnen?" + }, + "editedFolder": { + "message": "Ordner bearbeitet" + }, + "deleteFolderConfirmation": { + "message": "Soll dieser Ordner wirklich gelöscht werden?" + }, + "deletedFolder": { + "message": "Ordner gelöscht" + }, + "gettingStartedTutorial": { + "message": "Erste Schritte Anleitung" + }, + "gettingStartedTutorialVideo": { + "message": "Sieh dir unser Tutorial an, um hilfreiche Tipps zum Umgang mit der Browser-Erweiterung zu erfahren." + }, + "syncingComplete": { + "message": "Synchronisierung abgeschlossen" + }, + "syncingFailed": { + "message": "Synchronisierung fehlgeschlagen" + }, + "passwordCopied": { + "message": "Passwort kopiert" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Neue URL" + }, + "addedItem": { + "message": "Neuer Eintrag" + }, + "editedItem": { + "message": "Eintrag bearbeitet" + }, + "deleteItemConfirmation": { + "message": "Soll dieser Eintrag wirklich in den Papierkorb verschoben werden?" + }, + "deletedItem": { + "message": "Eintrag in Papierkorb verschoben" + }, + "overwritePassword": { + "message": "Passwort ersetzen" + }, + "overwritePasswordConfirmation": { + "message": "Sind Sie sicher, dass Sie das aktuelle Passwort ersetzen möchten?" + }, + "overwriteUsername": { + "message": "Benutzername überschreiben" + }, + "overwriteUsernameConfirmation": { + "message": "Bist du sicher, dass du den aktuellen Benutzernamen überschreiben möchtest?" + }, + "searchFolder": { + "message": "Ordner durchsuchen" + }, + "searchCollection": { + "message": "Sammlung durchsuchen" + }, + "searchType": { + "message": "Suchmodus" + }, + "noneFolder": { + "message": "Kein Ordner", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "\"Login hinzufügen\" Benachrichtigung deaktivieren" + }, + "addLoginNotificationDesc": { + "message": "Die \"Login hinzufügen\" Benachrichtigung fragt dich automatisch ob du neue Zugangsdaten im Tresor speichern möchtest wenn du dich zum ersten mal mit ihnen anmeldest." + }, + "dontShowCardsCurrentTab": { + "message": "Zeige keine Karten auf der Tab Seite" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Karten Daten aus deinem Tresors werden unter 'Tab' aufgeführt um automatisches ausfüllen zu vereinfachen." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Zeige keine Identitäten auf der Tab Seite" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identitäts Daten aus deinem Tresors werden unter 'Tab' aufgeführt um automatisches ausfüllen zu vereinfachen." + }, + "clearClipboard": { + "message": "Zwischenablage leeren", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Kopierten Inhalt automatisch aus der Zwischenablage löschen.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Soll Bitwarden sich dieses Passwort merken?" + }, + "notificationAddSave": { + "message": "Ja, jetzt speichern" + }, + "disableChangedPasswordNotification": { + "message": "Passwort geändert Benachrichtigung deaktivieren" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Die \"Passwort geändert Benachrichtigung\" fragt automatisch nach, ein Passwort in deinem Tressor zu aktualisieren, sobald erkannt wurde das du es auf einer Webseite geändert hast." + }, + "notificationChangeDesc": { + "message": "Möchtest du dieses Passwort in Bitwarden aktualisieren?" + }, + "notificationChangeSave": { + "message": "Ja, jetzt aktualisieren" + }, + "disableContextMenuItem": { + "message": "Kontextmenü-Optionen deaktivieren" + }, + "disableContextMenuItemDesc": { + "message": "Kontextmenü-Optionen bieten schnellen Zugriff auf die Passwortgenerierung und Zugangsdaten für die Webseite in Ihrem aktuellen Tab." + }, + "defaultUriMatchDetection": { + "message": "Standard-URI-Match-Erkennung", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Wähle die Standardmethode, mit der die URI-Match-Erkennung für Anmeldungen bei Aktionen wie dem automatischen Ausfüllen behandelt wird." + }, + "theme": { + "message": "Design" + }, + "themeDesc": { + "message": "Ändere das Farbschema der Anwendung." + }, + "dark": { + "message": "Dunkel", + "description": "Dark color" + }, + "light": { + "message": "Hell", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Tresor exportieren" + }, + "fileFormat": { + "message": "Dateiformat" + }, + "warning": { + "message": "ACHTUNG", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Tresor-Export bestätigen" + }, + "exportWarningDesc": { + "message": "Dieser Export enthält deine unverschlüsselten Daten im Csv-Format. Du solltest sie nicht speichern oder über unsichere Kanäle (z. B. E-Mail) senden. Lösche sie sofort nach ihrer Verwendung." + }, + "encExportKeyWarningDesc": { + "message": "Dieser Export verschlüsselt deine Daten mit dem Verschlüsselungscode deines Kontos. Falls du deinen Verschlüsselungscode erneuerst, solltest du den Export erneut durchführen, da du die zuvor erstellte Datei ansonsten nicht mehr entschlüsseln kannst." + }, + "encExportAccountWarningDesc": { + "message": "Die Verschlüsselungscodes eines Kontos sind für jedes Bitwarden Benutzerkonto einzigartig, deshalb kannst du keinen verschlüsselten Export in ein anderes Konto importieren." + }, + "exportMasterPassword": { + "message": "Gib das Masterpasswort ein, um deine Tresordaten zu exportieren." + }, + "shared": { + "message": "Geteilt" + }, + "learnOrg": { + "message": "Erfahre mehr über Organisationen" + }, + "learnOrgConfirmation": { + "message": "Bitwarden erlaubt es dir, deine Tresor-Einträge mit anderen zu teilen, wenn du eine Organisation verwendest. Möchtest du bitwarden.com besuchen, um mehr zu erfahren?" + }, + "moveToOrganization": { + "message": "In Organisation verschieben" + }, + "share": { + "message": "Teilen" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ verschoben nach $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Wähle eine Organisation aus, in die du diesen Eintrag verschieben möchtest. Das Verschieben in eine Organisation überträgt das Eigentum an diese Organisation. Du bist nicht mehr der direkte Besitzer dieses Eintrags, sobald er verschoben wurde." + }, + "learnMore": { + "message": "Erfahre mehr" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Schlüssel (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verifizierungscode (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopiere Verifizierungscode" + }, + "attachments": { + "message": "Anhänge" + }, + "deleteAttachment": { + "message": "Anhang löschen" + }, + "deleteAttachmentConfirmation": { + "message": "Möchtest du diesen Anhang wirklich löschen?" + }, + "deletedAttachment": { + "message": "Gelöschter Anhang" + }, + "newAttachment": { + "message": "Anhang hinzufügen" + }, + "noAttachments": { + "message": "Keine Anhänge." + }, + "attachmentSaved": { + "message": "Der Anhang wurde gespeichert." + }, + "file": { + "message": "Datei" + }, + "selectFile": { + "message": "Wähle eine Datei." + }, + "maxFileSize": { + "message": "Die maximale Dateigröße beträgt 500 MB." + }, + "featureUnavailable": { + "message": "Funktion nicht verfügbar" + }, + "updateKey": { + "message": "Du kannst diese Funktion nicht nutzen, solange du deinen Verschlüsselungsschlüssel nicht aktualisiert hast." + }, + "premiumMembership": { + "message": "Premium-Mitgliedschaft" + }, + "premiumManage": { + "message": "Mitgliedschaft verwalten" + }, + "premiumManageAlert": { + "message": "Du kannst deine Mitgliedschaft im Bitwarden.com Webtresor verwalten. Möchtest du die Seite jetzt aufrufen?" + }, + "premiumRefresh": { + "message": "Mitgliedschaft erneuern" + }, + "premiumNotCurrentMember": { + "message": "Du hast derzeit keine Premium-Mitgliedschaft." + }, + "premiumSignUpAndGet": { + "message": "Werde Premium-Mitglied und erhalte dafür:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB verschlüsselter Speicherplatz für Dateianhänge." + }, + "ppremiumSignUpTwoStep": { + "message": "Zusätzliche Zweifaktor-Anmeldung über YubiKey, FIDO U2F, und Duo." + }, + "ppremiumSignUpReports": { + "message": "Berichte über Kennworthygiene, Kontostatus und Datenschutzverletzungen, um deinen Tresor sicher zu halten." + }, + "ppremiumSignUpTotp": { + "message": "TOTP Prüfcode (2FA) Generator für Anmeldungen in Ihrem Tresor." + }, + "ppremiumSignUpSupport": { + "message": "Vorrangiger Kunden-Support." + }, + "ppremiumSignUpFuture": { + "message": "Alle zukünftigen Premium-Features. Mehr in Kürze!" + }, + "premiumPurchase": { + "message": "Premium-Mitgliedschaft kaufen" + }, + "premiumPurchaseAlert": { + "message": "Du kannst deine Premium-Mitgliedschaft im Bitwarden.com Web-Tresor kaufen. Möchtest du die Webseite jetzt besuchen?" + }, + "premiumCurrentMember": { + "message": "Du bist jetzt Premium-Mitglied!" + }, + "premiumCurrentMemberThanks": { + "message": "Vielen Dank, dass du Bitwarden unterstützt." + }, + "premiumPrice": { + "message": "Das alles für %price% pro Jahr!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Aktualisierung abgeschlossen" + }, + "disableAutoTotpCopy": { + "message": "Automatisches TOTP Kopieren deaktivieren" + }, + "disableAutoTotpCopyDesc": { + "message": "Ist ein Authentifizierungsschlüssel mit deinen Zugangsdaten verknüpft, wird der TOTP Bestätigungscode automatisch in die Zwischenablage kopiert, wenn du die Zugangsdaten einfügen lässt." + }, + "disableAutoBiometricsPrompt": { + "message": "Beim Start nicht nach biometrischen Daten fragen" + }, + "premiumRequired": { + "message": "Premium-Mitgliedschaft wird benötigt" + }, + "premiumRequiredDesc": { + "message": "Eine Premium-Mitgliedschaft ist für diese Funktion notwendig." + }, + "enterVerificationCodeApp": { + "message": "Gib den 6-stelligen Verifizierungscode aus deiner Authenticator App ein." + }, + "enterVerificationCodeEmail": { + "message": "Gib den 6-stelligen Bestätigungscode ein, der an $EMAIL$ gesendet wurde.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verifizierungsmail wurde an $EMAIL$ gesendet.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Angemeldet bleiben" + }, + "sendVerificationCodeEmailAgain": { + "message": "E-Mail mit Bestätigungscode erneut versenden" + }, + "useAnotherTwoStepMethod": { + "message": "Verwende eine andere zweistufige Login-Methode" + }, + "insertYubiKey": { + "message": "Stecke deinen YubiKey in den USB-Port Ihres Computers, dann berühre den Button." + }, + "insertU2f": { + "message": "Stecke deinen Sicherheitsschlüssel in den USB-Port deines Computers. Falls ein Knopf vorhanden ist, berühre diesen." + }, + "webAuthnNewTab": { + "message": "Um die WebAuthn 2FA Verifizierung zu starten, klicke auf die Schaltfläche unten, um einen neuen Tab zu öffnen und folge den Anweisungen, die im neuen Tab angezeigt werden." + }, + "webAuthnNewTabOpen": { + "message": "Neuen Tab öffnen" + }, + "webAuthnAuthenticate": { + "message": "Authentifiziere WebAuthn" + }, + "loginUnavailable": { + "message": "Login nicht verfügbar" + }, + "noTwoStepProviders": { + "message": "Dieses Konto hat eine aktive Zwei-Faktor Authentifizierung, allerdings wird keiner der konfigurierten Zwei-Faktor Anbieter von diesem Browser unterstützt." + }, + "noTwoStepProviders2": { + "message": "Bitte benutze einen unterstützten Browser (z.B. Chrome) und / oder füge zusätzliche Anbieter hinzu, die von mehr Browsern unterstützt werden (wie eine Authentifizierungs-App)." + }, + "twoStepOptions": { + "message": "Optionen für Zwei-Faktor Authentifizierung" + }, + "recoveryCodeDesc": { + "message": "Zugang zu allen Zwei-Faktor Anbietern verloren? Benutze deinen Wiederherstellungscode, um alle Zwei-Faktor Anbieter in deinem Konto zu deaktivieren." + }, + "recoveryCodeTitle": { + "message": "Wiederherstellungscode" + }, + "authenticatorAppTitle": { + "message": "Authentifizierungs-App" + }, + "authenticatorAppDesc": { + "message": "Verwende eine Authentifizierungs-App (wie zum Beispiel Authy oder Google Authenticator), um zeitbasierte Verifizierungscodes zu generieren.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Sicherheitsschlüssel" + }, + "yubiKeyDesc": { + "message": "Verwende einen YubiKey um auf dein Konto zuzugreifen. Funtioniert mit YubiKey 4, Nano 4, 4C und NEO Geräten." + }, + "duoDesc": { + "message": "Verifiziere mit Duo Security, indem du die Duo Mobile App, SMS, Anrufe oder U2F Sicherheitsschlüssel benutzt.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Nutze Duo Security um dich mit der Duo Mobile App, SMS, per Anruf oder U2F Security Key bei deiner Organisation zu verifizieren.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Benutze einen WebAuthn-kompatiblen Sicherheitsschlüssel, um auf dein Konto zuzugreifen." + }, + "emailTitle": { + "message": "E-Mail" + }, + "emailDesc": { + "message": "Bestätigungscodes werden Ihnen per E-Mail zugesandt." + }, + "selfHostedEnvironment": { + "message": "Selbstgehostete Umgebung" + }, + "selfHostedEnvironmentFooter": { + "message": "Bitte gib die Basis-URL deiner selbst gehosteten Bitwarden-Installation an." + }, + "customEnvironment": { + "message": "Benutzerdefinierte Umgebung" + }, + "customEnvironmentFooter": { + "message": "Für fortgeschrittene Benutzer. Du kannst die Basis-URL der jeweiligen Dienste unabhängig voneinander festlegen." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web-Tresor Server URL" + }, + "identityUrl": { + "message": "URL des Identitätsservers" + }, + "notificationsUrl": { + "message": "URL des Benachrichtigungsserver" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "Die URLs der Umgebung wurden gespeichert." + }, + "enableAutoFillOnPageLoad": { + "message": "Auto-Ausfüllen beim Seitenladen aktivieren" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Wenn eine Zugangsmaske erkannt wird, füge automatisch die Zugangsdaten ein während die Webseite lädt." + }, + "experimentalFeature": { + "message": "Dies ist derzeit ein experimentelles Feature. Verwendung auf eigene Gefahr." + }, + "defaultAutoFillOnPageLoad": { + "message": "Standard Auto-Ausfüllen Einstellung für Login-Einträge" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Nachdem du das automatische Ausfüllen beim Laden der Seite aktiviert hast, kannst du die Funktion für einzelne Login-Einträge aktivieren oder deaktivieren. Dies ist die Standardeinstellung für Login-Einträge, die nicht separat konfiguriert wurden." + }, + "itemAutoFillOnPageLoad": { + "message": "Automatisches Ausfüllen beim Laden der Seite (wenn in Optionen aktiviert)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Nutze Standardeinstellung" + }, + "autoFillOnPageLoadYes": { + "message": "Automatisches Ausfüllen beim Laden der Seite" + }, + "autoFillOnPageLoadNo": { + "message": "Kein automatisches Ausfüllen beim Laden der Seite" + }, + "commandOpenPopup": { + "message": "Tresor-Popup öffnen" + }, + "commandOpenSidebar": { + "message": "Tresor in der Seitenleiste öffnen" + }, + "commandAutofillDesc": { + "message": "Die zuletzt verwendeten Zugangsdaten für die aktuelle Website automatisch ausfüllen lassen" + }, + "commandGeneratePasswordDesc": { + "message": "Ein neues zufälliges Passwort generieren und in die Zwischenablage kopieren" + }, + "commandLockVaultDesc": { + "message": "Den Tresor sperren" + }, + "privateModeWarning": { + "message": "Die Unterstützung des privaten Modus ist experimentell und einige Funktionen sind eingeschränkt." + }, + "customFields": { + "message": "Benutzerdefinierte Felder" + }, + "copyValue": { + "message": "Wert kopieren" + }, + "value": { + "message": "Inhalt" + }, + "newCustomField": { + "message": "Neues benutzerdefiniertes Feld" + }, + "dragToSort": { + "message": "Zum Sortieren ziehen" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Versteckt" + }, + "cfTypeBoolean": { + "message": "Ja/Nein" + }, + "cfTypeLinked": { + "message": "Verknüpft", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Verknüpfter Inhalt", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Dieses Pop-up Fenster wird geschlossen, wenn du außerhalb des Fensters klickst um in deinen E-Mails nach dem Verifizierungscode zu suchen. Möchtest du, dass dieses Pop-up in einem separaten Fenster geöffnet wird, damit es nicht geschlossen wird?" + }, + "popupU2fCloseMessage": { + "message": "Dieser Browser kann U2F-Anfragen in diesem Popup-Fenster nicht verarbeiten. Möchtest du dieses Popup in einem neuen Fenster öffnen, damit du dich mit U2F anmelden kannst?" + }, + "disableFavicon": { + "message": "Icons der Website deaktivieren" + }, + "disableFaviconDesc": { + "message": "Website-Symbole zeigen ein erkennbares Bild neben jedem Login in deinem Tresor." + }, + "disableBadgeCounter": { + "message": "Badge-Zähler deaktivieren" + }, + "disableBadgeCounterDesc": { + "message": "Der Badge-Zähler zeigt an, wie viele Zugangsdaten du für die aktuelle Seite in deinem Tresor hast." + }, + "cardholderName": { + "message": "Name des Karteninhabers" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Marke" + }, + "expirationMonth": { + "message": "Ablaufmonat" + }, + "expirationYear": { + "message": "Ablaufjahr" + }, + "expiration": { + "message": "Gültig bis" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "März" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Dezember" + }, + "securityCode": { + "message": "Sicherheitscode" + }, + "ex": { + "message": "Bsp." + }, + "title": { + "message": "Titel" + }, + "mr": { + "message": "Herr" + }, + "mrs": { + "message": "Frau" + }, + "ms": { + "message": "Frau" + }, + "dr": { + "message": "Dr." + }, + "firstName": { + "message": "Vorname" + }, + "middleName": { + "message": "Zweiter Vorname" + }, + "lastName": { + "message": "Nachname" + }, + "fullName": { + "message": "Vollständiger Name" + }, + "identityName": { + "message": "Identitätsname" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Sozialversicherungsnummer" + }, + "passportNumber": { + "message": "Reisepassnummer" + }, + "licenseNumber": { + "message": "Führerscheinnummer" + }, + "email": { + "message": "E-Mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresse" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "Stadt oder Ort" + }, + "stateProvince": { + "message": "Bundesland" + }, + "zipPostalCode": { + "message": "Postleitzahl" + }, + "country": { + "message": "Land" + }, + "type": { + "message": "Typ" + }, + "typeLogin": { + "message": "Zugangsdaten" + }, + "typeLogins": { + "message": "Zugangsdaten" + }, + "typeSecureNote": { + "message": "Sichere Notiz" + }, + "typeCard": { + "message": "Karte" + }, + "typeIdentity": { + "message": "Identität" + }, + "passwordHistory": { + "message": "Kennwort-Historie" + }, + "back": { + "message": "Zurück" + }, + "collections": { + "message": "Sammlungen" + }, + "favorites": { + "message": "Favoriten" + }, + "popOutNewWindow": { + "message": "In einem neuen Fenster öffnen" + }, + "refresh": { + "message": "Aktualisieren" + }, + "cards": { + "message": "Karten" + }, + "identities": { + "message": "Identitäten" + }, + "logins": { + "message": "Zugangsdaten" + }, + "secureNotes": { + "message": "Sichere Notiz" + }, + "clear": { + "message": "Löschen", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Überprüfe ob dein Kennwort kompromittiert ist." + }, + "passwordExposed": { + "message": "Dieses Passwort wurde $VALUE$ mal in öffentlichen Passwortdatenbanken gefunden. Du solltest es ändern.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Dieses Kennwort wurde in keinen bekannten Datensätzen gefunden. Es sollte sicher sein." + }, + "baseDomain": { + "message": "Basis-Domäne", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain-Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Server", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exakt" + }, + "startsWith": { + "message": "Beginnt mit" + }, + "regEx": { + "message": "Regulärer Ausdruck", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match-Erkennung", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standard-Match-Erkennung", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Umschaltoptionen" + }, + "toggleCurrentUris": { + "message": "Aktuelle URIs ändern", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Aktuelle URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Typen" + }, + "allItems": { + "message": "Alle Einträge" + }, + "noPasswordsInList": { + "message": "Keine Einträge zum Anzeigen vorhanden." + }, + "remove": { + "message": "Entfernen" + }, + "default": { + "message": "Standard" + }, + "dateUpdated": { + "message": "Aktualisiert", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Passwort aktualisiert", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Bist du sicher, dass dein Tresor nicht automatisch gesperrt werden soll? Dadurch wird der Verschlüsselungsschlüssel auf dem Gerät gespeichert. Wenn du diese Option verwendest, solltest du darauf achten, dass dein Gerät ausreichend geschützt ist." + }, + "noOrganizationsList": { + "message": "Du bist kein Mitglied einer Organisation. Organisationen erlauben es dir Passwörter sicher mit anderen Nutzern zu teilen." + }, + "noCollectionsInList": { + "message": "Keine Sammlungen vorhanden." + }, + "ownership": { + "message": "Besitzer" + }, + "whoOwnsThisItem": { + "message": "Wem gehört dieser Eintrag?" + }, + "strong": { + "message": "Stark", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Gut", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Schwach", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Schwaches Master-Passwort" + }, + "weakMasterPasswordDesc": { + "message": "Das Haupt-Passwort, das du gewählt hast ist schwach. Du solltest ein starkes Haupt-Passwort auswählen, um dein Bitwarden-Konto richtig zu schützen. Bist du sicher, dass du dieses Haupt-Passwort verwenden sollen?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Mit PIN-Code entsperren" + }, + "setYourPinCode": { + "message": "Gebe deinen PIN-Code für das Entsperren von Bitwarden ein. Deine PIN-Einstellungen werden zurückgesetzt, wenn du dich vollständig von der Anwendung abmeldest." + }, + "pinRequired": { + "message": "PIN-Code ist erforderlich." + }, + "invalidPin": { + "message": "Ungültiger PIN-Code." + }, + "unlockWithBiometrics": { + "message": "Mit Biometrie entsperren" + }, + "awaitDesktop": { + "message": "Warte auf Bestätigung vom Desktop" + }, + "awaitDesktopDesc": { + "message": "Bitte bestätige die Verwendung von Biometrie in der Bitwarden Desktop-Anwendung, um Biometrie für den Browser zu aktivieren." + }, + "lockWithMasterPassOnRestart": { + "message": "Bei Neustart des Browsers mit Master-Passwort sperren" + }, + "selectOneCollection": { + "message": "Sie müssen mindestens eine Sammlung auswählen." + }, + "cloneItem": { + "message": "Eintrag duplizieren" + }, + "clone": { + "message": "Duplizieren" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Eine oder mehrere Organisationsrichtlinien beeinflussen deine Generator-Einstellungen." + }, + "vaultTimeoutAction": { + "message": "Aktion bei Tresor-Timeout" + }, + "lock": { + "message": "Sperren", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papierkorb", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Papierkorb durchsuchen" + }, + "permanentlyDeleteItem": { + "message": "Eintrag dauerhaft löschen" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Soll dieser Eintrag wirklich dauerhaft gelöscht werden?" + }, + "permanentlyDeletedItem": { + "message": "Eintrag dauerhaft gelöscht" + }, + "restoreItem": { + "message": "Eintrag wiederherstellen" + }, + "restoreItemConfirmation": { + "message": "Soll dieser Eintrag wirklich wiederhergestellt werden?" + }, + "restoredItem": { + "message": "Eintrag wiederhergestellt" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Nach dem Ausloggen verlierest du jeglichen Zugriff auf deinen Tresor und es ist nach Ablauf der Timeout-Zeit eine Online-Authentifizierung erforderlich. Bist du sicher, dass du diese Einstellung nutzen möchten?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bestätigung der Timeout-Aktion" + }, + "autoFillAndSave": { + "message": "Automatisch ausfüllen und speichern" + }, + "autoFillSuccessAndSavedUri": { + "message": "Automatisch ausgefüllter Eintrag und gespeicherte URI" + }, + "autoFillSuccess": { + "message": "Automatisch ausgefüllter Eintrag" + }, + "setMasterPassword": { + "message": "Masterpasswort festlegen" + }, + "masterPasswordPolicyInEffect": { + "message": "Eine oder mehrere Organisationsrichtlinien erfordern, dass dein Masterpasswort die folgenden Anforderungen erfüllt:" + }, + "policyInEffectMinComplexity": { + "message": "Kleinster Komplexitätsgrad von $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Mindestlänge von $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Enthält einen oder mehrere Großbuchstaben" + }, + "policyInEffectLowercase": { + "message": "Enthält einen oder mehrere Kleinbuchstaben" + }, + "policyInEffectNumbers": { + "message": "Enthält eine oder mehrere Zahlen" + }, + "policyInEffectSpecial": { + "message": "Enthält eines oder mehrere der folgenden Sonderzeichen $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ihr neues Master-Passwort entspricht nicht den Anforderungen der Richtlinie." + }, + "acceptPolicies": { + "message": "Durch Anwählen dieses Kästchens erklären Sie sich mit folgendem einverstanden:" + }, + "acceptPoliciesError": { + "message": "Die Nutzungsbedingungen und Datenschutzerklärung wurden nicht akzeptiert." + }, + "termsOfService": { + "message": "Nutzungsbedingungen" + }, + "privacyPolicy": { + "message": "Datenschutzbestimmungen" + }, + "hintEqualsPassword": { + "message": "Dein Passwort-Hinweis darf nicht identisch mit deinem Passwort sein." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop-Sync-Überprüfung" + }, + "desktopIntegrationVerificationText": { + "message": "Bitte bestätigen Sie, dass die Desktop-Anwendung diesen Prüfschlüssel anzeigt: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser-Einbindung ist nicht aktiviert" + }, + "desktopIntegrationDisabledDesc": { + "message": "Die Browser-Einbindung ist in der Bitwarden Desktop-Anwendung nicht aktiviert. Bitte aktiviere diese in den Einstellungen innerhalb der Desktop-Anwendung." + }, + "startDesktopTitle": { + "message": "Bitwarden Desktop-Anwendung starten" + }, + "startDesktopDesc": { + "message": "Die Bitwarden Desktop-Anwendung muss gestartet werden, bevor diese Funktion verwendet werden kann." + }, + "errorEnableBiometricTitle": { + "message": "Biometrie kann nicht aktiviert werden" + }, + "errorEnableBiometricDesc": { + "message": "Die Aktion wurde von der Desktop-Anwendung abgebrochen" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Die Desktop-Anwendung hat den sicheren Kommunikationskanal für ungültig erklärt. Bitte starte den Vorgang erneut" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop-Kommunikation unterbrochen" + }, + "nativeMessagingWrongUserDesc": { + "message": "Die Desktop-Anwendung ist in ein anderes Konto eingeloggt. Bitte stelle sicher, dass beide Anwendungen mit demselben Konto angemeldet sind." + }, + "nativeMessagingWrongUserTitle": { + "message": "Konten stimmen nicht überein" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrie ist nicht aktiviert" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrie im Browser setzt voraus, dass Biometrie zuerst in den Einstellungen der Desktop-Anwendung aktiviert ist." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrie wird nicht unterstützt" + }, + "biometricsNotSupportedDesc": { + "message": "Biometrie im Browser wird auf diesem Gerät nicht unterstützt." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Berechtigung nicht erteilt" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Ohne die Berechtigung zur Kommunikation mit der Bitwarden Desktop-Anwendung können wir keine Biometrie in der Browser-Erweiterung anbieten. Bitte versuche es erneut." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Fehler bei der Berechtigungsanfrage" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Diese Aktion kann in der Sidebar nicht durchgeführt werden, bitte versuche die Aktion im Popup oder Popout erneut auszuführen." + }, + "personalOwnershipSubmitError": { + "message": "Aufgrund einer Unternehmensrichtlinie darfst du keine Einträge in deinem persönlichen Tresor speichern. Ändere die Eigentümer-Option in eine Organisation und wähle aus den verfügbaren Sammlungen." + }, + "personalOwnershipPolicyInEffect": { + "message": "Eine Organisationsrichtlinie beeinflusst deine Eigentümer-Optionen." + }, + "excludedDomains": { + "message": "Ausgeschlossene Domänen" + }, + "excludedDomainsDesc": { + "message": "Bitwarden wird keine Login-Daten für diese Domäne speichern. Du musst die Seite aktualisieren, damit die Änderungen wirksam werden." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ ist keine gültige Domäne", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Sends suchen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Send hinzufügen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "Datei" + }, + "allSends": { + "message": "Alle Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maximale Zugriffsanzahl erreicht", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Abgelaufen" + }, + "pendingDeletion": { + "message": "Ausstehende Löschung" + }, + "passwordProtected": { + "message": "Passwortgeschützt" + }, + "copySendLink": { + "message": "Send-Link kopieren", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Passwort entfernen" + }, + "delete": { + "message": "Löschen" + }, + "removedPassword": { + "message": "Passwort entfernt" + }, + "deletedSend": { + "message": "Send gelöscht", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send-Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Deaktiviert" + }, + "removePasswordConfirmation": { + "message": "Bist du sicher, dass du dieses Passwort entfernen möchtest?" + }, + "deleteSend": { + "message": "Send löschen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Bist du sicher, dass du dieses Send löschen möchtest?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send bearbeiten", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Welche Art von Send ist das?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Ein eigener Name, um dieses Send zu beschreiben.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Die Datei, die du senden möchtest." + }, + "deletionDate": { + "message": "Löschdatum" + }, + "deletionDateDesc": { + "message": "Das Send wird am angegebenen Datum zur angegebenen Uhrzeit dauerhaft gelöscht.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Ablaufdatum" + }, + "expirationDateDesc": { + "message": "Falls aktiviert, verfällt der Zugriff auf dieses Send am angegebenen Datum zur angegebenen Uhrzeit.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 Tag" + }, + "days": { + "message": "$DAYS$ Tage", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Benutzerdefiniert" + }, + "maximumAccessCount": { + "message": "Maximale Zugriffsanzahl" + }, + "maximumAccessCountDesc": { + "message": "Falls aktiviert, können Benutzer nicht mehr auf dieses Send zugreifen, sobald die maximale Zugriffsanzahl erreicht ist.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optional ein Passwort verlangen, damit Benutzer auf dieses Send zugreifen können.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private Notizen zu diesem Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Dieses Send deaktivieren, damit niemand darauf zugreifen kann.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kopiere den Send-Link beim Speichern in die Zwischenablage.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Der Text, den du senden möchtest." + }, + "sendHideText": { + "message": "Send-Text standardmäßig ausblenden.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Aktuelle Zugriffsanzahl" + }, + "createSend": { + "message": "Neues Send erstellen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Neues Passwort" + }, + "sendDisabled": { + "message": "Send deaktiviert", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Aufgrund einer Unternehmensrichtlinie kannst du nur ein bestehendes Send löschen.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send erstellt", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Bearbeitetes Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Um eine Datei auszuwählen, öffne die Erweiterung in der Sidebar (falls möglich) oder öffne sie in einem neuem Fenster, indem du auf dieses Banner klickst." + }, + "sendFirefoxFileWarning": { + "message": "Um eine Datei mit Firefox auszuwählen, öffne die Erweiterung in der Sidebar oder öffne ein neues Fenster, indem du auf dieses Banner klickst." + }, + "sendSafariFileWarning": { + "message": "Um eine Datei mit Safari auszuwählen, öffne ein neues Fenster, indem du auf dieses Banner klickst." + }, + "sendFileCalloutHeader": { + "message": "Bevor du beginnst" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Um einen Kalender-Datumsauswahl zu verwenden", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "hier klicken", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "zum Öffnen in einem neuen Fenster.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Das angegebene Verfallsdatum ist nicht gültig." + }, + "deletionDateIsInvalid": { + "message": "Das angegebene Löschdatum ist nicht gültig." + }, + "expirationDateAndTimeRequired": { + "message": "Ein Verfallsdatum und eine Zeit sind erforderlich." + }, + "deletionDateAndTimeRequired": { + "message": "Ein Löschdatum und eine Zeit sind erforderlich." + }, + "dateParsingError": { + "message": "Es gab einen Fehler beim Speichern deiner Lösch- und Verfallsdaten." + }, + "hideEmail": { + "message": "Meine E-Mail-Adresse vor den Empfängern ausblenden." + }, + "sendOptionsPolicyInEffect": { + "message": "Eine oder mehrere Organisationsrichtlinien beeinflussen deine Send Einstellungen." + }, + "passwordPrompt": { + "message": "Master-Passwort erneut abfragen" + }, + "passwordConfirmation": { + "message": "Master-Passwort bestätigen" + }, + "passwordConfirmationDesc": { + "message": "Diese Aktion ist geschützt. Um fortzufahren, gib bitte dein Master-Passwort erneut ein, um deine Identität zu bestätigen." + }, + "emailVerificationRequired": { + "message": "E-Mail-Verifizierung erforderlich" + }, + "emailVerificationRequiredDesc": { + "message": "Du musst deine E-Mail Adresse verifizieren, um diese Funktion nutzen zu können. Du kannst deine E-Mail im Web-Tresor verifizieren." + }, + "updatedMasterPassword": { + "message": "Master-Passwort aktualisiert" + }, + "updateMasterPassword": { + "message": "Master-Passwort aktualisieren" + }, + "updateMasterPasswordWarning": { + "message": "Dein Master-Passwort wurde kürzlich von einem Administrator Ihrer Organisation geändert. Um auf den Tresor zuzugreifen, musst du es jetzt aktualisieren. Wenn du fortfährst, wirst du aus der aktuellen Sitzung abgemeldet, eine erneute Anmeldung wird erforderlich. Aktive Sitzungen auf anderen Geräten können bis zu einer Stunde weiterhin aktiv bleiben." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatische Registrierung" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Diese Organisation hat eine Unternehmensrichtlinie, die dich automatisch zum Zurücksetzen deines Passworts registriert. Die Registrierung wird es Administratoren der Organisation erlauben, dein Master-Passwort zu ändern." + }, + "selectFolder": { + "message": "Ordner auswählen..." + }, + "ssoCompleteRegistration": { + "message": "Um die Anmeldung über SSO abzuschließen, lege bitte ein Master-Passwort fest, um auf deinen Tresor zuzugreifen und ihn zu schützen." + }, + "hours": { + "message": "Stunden" + }, + "minutes": { + "message": "Minuten" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Deine Unternehmensrichtlinien beeinflussen dein Tresor-Timeout. Das maximal zulässige Tresor-Timeout ist $HOURS$ Stunde(n) und $MINUTES$ Minute(n)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Dein Tresor-Timeout überschreitet die von deinem Unternehmen festgelegten Beschränkungen." + }, + "vaultExportDisabled": { + "message": "Tresor-Export deaktiviert" + }, + "personalVaultExportPolicyInEffect": { + "message": "Eine oder mehrere Unternehmensrichtlinien hindern dich daran, deinen persönlichen Tresor zu exportieren." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Es konnte kein gültiges Formularelement identifiziert werden. Versuche stattdessen das HTML zu untersuchen." + }, + "copyCustomFieldNameNotUnique": { + "message": "Keine eindeutige Kennung gefunden." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ verwendet SSO mit einem selbst gehosteten Schlüsselserver. Ein Master-Passwort ist nicht mehr erforderlich, damit sich Mitglieder dieser Organisation anmelden können.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Organisation verlassen" + }, + "removeMasterPassword": { + "message": "Master-Passwort entfernen" + }, + "removedMasterPassword": { + "message": "Master-Passwort entfernt." + }, + "leaveOrganizationConfirmation": { + "message": "Bist du sicher, dass du diese Organisation verlassen möchtest?" + }, + "leftOrganization": { + "message": "Du hast die Organisation verlassen." + }, + "toggleCharacterCount": { + "message": "Zeichenzählung ein-/ausschalten" + }, + "sessionTimeout": { + "message": "Deine Sitzung ist abgelaufen. Bitte gehe zurück und versuche dich erneut einzuloggen." + }, + "exportingPersonalVaultTitle": { + "message": "Persönlichen Tresor exportieren" + }, + "exportingPersonalVaultDescription": { + "message": "Nur die persönlichen Tresoreinträge, die mit $EMAIL$ verbunden sind, werden exportiert. Tresoreinträge der Organisation werden nicht berücksichtigt.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Fehler" + }, + "regenerateUsername": { + "message": "Benutzername neu generieren" + }, + "generateUsername": { + "message": "Benutzernamen generieren" + }, + "usernameType": { + "message": "Benutzernamentyp" + }, + "plusAddressedEmail": { + "message": "Mit Plus adressierte E-Mail", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Verwende die Unteradressierungsmöglichkeiten deines E-Mail-Providers." + }, + "catchallEmail": { + "message": "Catch-All E-Mail-Adresse" + }, + "catchallEmailDesc": { + "message": "Verwende den konfigurierten Catch-All-Posteingang deiner Domain." + }, + "random": { + "message": "Zufällig" + }, + "randomWord": { + "message": "Zufälliges Wort" + }, + "websiteName": { + "message": "Webseiten-Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "Was möchtest du generieren?" + }, + "passwordType": { + "message": "Passworttyp" + }, + "service": { + "message": "Dienst" + } +} diff --git a/apps/browser/src/_locales/el/messages.json b/apps/browser/src/_locales/el/messages.json new file mode 100644 index 0000000000..6f025e3c67 --- /dev/null +++ b/apps/browser/src/_locales/el/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Δωρεάν Διαχειριστής Κωδικών", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Ένας ασφαλής και δωρεάν διαχειριστής κωδικών, για όλες σας τις συσκευές.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Συνδεθείτε ή δημιουργήστε ένα νέο λογαριασμό για να αποκτήσετε πρόσβαση στο ασφαλές vault σας." + }, + "createAccount": { + "message": "Δημιουργία Λογαριασμού" + }, + "login": { + "message": "Σύνδεση" + }, + "enterpriseSingleSignOn": { + "message": "Ενιαία είσοδος για επιχειρήσεις" + }, + "cancel": { + "message": "Ακύρωση" + }, + "close": { + "message": "Κλείσιμο" + }, + "submit": { + "message": "Υποβολή" + }, + "emailAddress": { + "message": "Διεύθυνση Email" + }, + "masterPass": { + "message": "Κύριος κωδικός" + }, + "masterPassDesc": { + "message": "Ο κύριος κωδικός είναι ο κωδικός που χρησιμοποιείτε για την πρόσβαση στο vault σας. Είναι πολύ σημαντικό να μην ξεχάσετε τον κύριο κωδικό. Δεν υπάρχει τρόπος να ανακτήσετε τον κωδικό σε περίπτωση που τον ξεχάσετε." + }, + "masterPassHintDesc": { + "message": "Η υπόδειξη του κύριου κωδικού μπορεί να σας βοηθήσει να θυμηθείτε τον κωδικό σας, σε περίπτωση που τον ξεχάσετε." + }, + "reTypeMasterPass": { + "message": "Εισάγετε Ξανά τον Κύριο Κωδικό σας" + }, + "masterPassHint": { + "message": "Υπόδειξη Κύριου Κωδικού (προαιρετικό)" + }, + "tab": { + "message": "Καρτέλα" + }, + "myVault": { + "message": "Το Vault μου" + }, + "tools": { + "message": "Εργαλεία" + }, + "settings": { + "message": "Ρυθμίσεις" + }, + "currentTab": { + "message": "Τρέχουσα Καρτέλα" + }, + "copyPassword": { + "message": "Αντιγραφή Κωδικού" + }, + "copyNote": { + "message": "Αντιγραφή Σημείωσης" + }, + "copyUri": { + "message": "Αντιγραφή URI" + }, + "copyUsername": { + "message": "Αντιγραφή Ονόματος Χρήστη" + }, + "copyNumber": { + "message": "Αντιγραφή Αριθμού" + }, + "copySecurityCode": { + "message": "Αντιγραφή Κωδικού Ασφαλείας" + }, + "autoFill": { + "message": "Αυτόματη συμπλήρωση" + }, + "generatePasswordCopied": { + "message": "Δημιουργία Κωδικού (αντιγράφηκε)" + }, + "copyElementIdentifier": { + "message": "Αντιγραφή ονόματος προσαρμοσμένου πεδίου" + }, + "noMatchingLogins": { + "message": "Δεν υπάρχουν αντιστοιχίσεις σύνδεσης." + }, + "unlockVaultMenu": { + "message": "Ξεκλειδώστε το vault σας" + }, + "loginToVaultMenu": { + "message": "Συνδεθείτε στο vault σας" + }, + "autoFillInfo": { + "message": "Δεν υπάρχουν διαθέσιμες συνδέσεις για την αυτόματη συμπλήρωση, στην τρέχουσα καρτέλα του προγράμματος περιήγησης." + }, + "addLogin": { + "message": "Προσθήκη Στοιχείων Σύνδεσης" + }, + "addItem": { + "message": "Προσθήκη Αντικειμένου" + }, + "passwordHint": { + "message": "Υπόδειξη Κωδικού" + }, + "enterEmailToGetHint": { + "message": "Εισαγάγετε τη διεύθυνση email του λογαριασμού σας, για να λάβετε την υπόδειξη του κύριου κωδικού." + }, + "getMasterPasswordHint": { + "message": "Λήψη υπόδειξης κύριου κωδικού" + }, + "continue": { + "message": "Συνέχεια" + }, + "sendVerificationCode": { + "message": "Στείλτε έναν κωδικό επαλήθευσης στο email σας" + }, + "sendCode": { + "message": "Αποστολή Κωδικού" + }, + "codeSent": { + "message": "Ο Κωδικός Στάλθηκε" + }, + "verificationCode": { + "message": "Κωδικός Επαλήθευσης" + }, + "confirmIdentity": { + "message": "Επιβεβαιώστε την ταυτότητα σας για να συνεχίσετε." + }, + "account": { + "message": "Λογαριασμός" + }, + "changeMasterPassword": { + "message": "Αλλαγή Κύριου Κωδικού" + }, + "fingerprintPhrase": { + "message": "Φράση Δακτυλικών Αποτυπωμάτων", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Η Φράση δακτυλικών αποτυπωμάτων του λογαριασμού σας", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Σύνδεση σε δύο βήματα" + }, + "logOut": { + "message": "Αποσύνδεση" + }, + "about": { + "message": "Σχετικά" + }, + "version": { + "message": "Έκδοση" + }, + "save": { + "message": "Αποθήκευση" + }, + "move": { + "message": "Μετακίνηση" + }, + "addFolder": { + "message": "Προσθήκη Φακέλου" + }, + "name": { + "message": "Όνομα" + }, + "editFolder": { + "message": "Επεξεργασία Φακέλου" + }, + "deleteFolder": { + "message": "Διαγραφή Φακέλου" + }, + "folders": { + "message": "Φάκελοι" + }, + "noFolders": { + "message": "Δεν υπάρχουν φάκελοι προς εμφάνιση." + }, + "helpFeedback": { + "message": "Βοήθεια & Σχόλια" + }, + "sync": { + "message": "Συγχρονισμός" + }, + "syncVaultNow": { + "message": "Συγχρονισμός λίστας" + }, + "lastSync": { + "message": "Τελευταίος συγχρονισμός:" + }, + "passGen": { + "message": "Γεννήτρια Κωδικού" + }, + "generator": { + "message": "Γεννήτρια", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Δημιουργήστε αυτόματα ισχυρούς και μοναδικούς κωδικούς πρόσβασης για τις συνδέσεις σας." + }, + "bitWebVault": { + "message": "Bitwarden Web Vault" + }, + "importItems": { + "message": "Εισαγωγή στοιχείων" + }, + "select": { + "message": "Επιλογή" + }, + "generatePassword": { + "message": "Δημιουργία Κωδικού" + }, + "regeneratePassword": { + "message": "Επαναδημιουργία Κωδικού" + }, + "options": { + "message": "Επιλογές" + }, + "length": { + "message": "Μήκος" + }, + "uppercase": { + "message": "Κεφαλαία (A-Z)" + }, + "lowercase": { + "message": "Πεζά (α-ω)" + }, + "numbers": { + "message": "Αριθμοί (0-9)" + }, + "specialCharacters": { + "message": "Ειδικοί Χαρακτήρες (!@#$%^&*)" + }, + "numWords": { + "message": "Αριθμός Λέξεων" + }, + "wordSeparator": { + "message": "Διαχωριστής Λέξεων" + }, + "capitalize": { + "message": "Κεφαλαία", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Συμπερίληψη Αριθμών" + }, + "minNumbers": { + "message": "Ελάχιστα Αριθμητικά Ψηφία" + }, + "minSpecial": { + "message": "Ελάχιστο Ειδικών Χαρακτήρων" + }, + "avoidAmbChar": { + "message": "Αποφυγή Αμφιλεγόμενων Χαρακτήρων" + }, + "searchVault": { + "message": "Αναζήτηση στο vault" + }, + "edit": { + "message": "Επεξεργασία" + }, + "view": { + "message": "Προβολή" + }, + "noItemsInList": { + "message": "Δεν υπάρχουν στοιχεία στη λίστα." + }, + "itemInformation": { + "message": "Πληροφορίες Αντικειμένου" + }, + "username": { + "message": "Όνομα Χρήστη" + }, + "password": { + "message": "Κωδικός" + }, + "passphrase": { + "message": "Συνθηματικό" + }, + "favorite": { + "message": "Αγαπημένο" + }, + "notes": { + "message": "Σημειώσεις" + }, + "note": { + "message": "Σημείωση" + }, + "editItem": { + "message": "Επεξεργασία Αντικειμένου" + }, + "folder": { + "message": "Φάκελος" + }, + "deleteItem": { + "message": "Διαγραφή Στοιχείου" + }, + "viewItem": { + "message": "Προβολή Αντικειμένου" + }, + "launch": { + "message": "Εκκίνηση" + }, + "website": { + "message": "Ιστοσελίδα" + }, + "toggleVisibility": { + "message": "Εναλλαγή Ορατότητας" + }, + "manage": { + "message": "Διαχείριση" + }, + "other": { + "message": "Άλλες" + }, + "rateExtension": { + "message": "Βαθμολογήστε την επέκταση" + }, + "rateExtensionDesc": { + "message": "Παρακαλούμε σκεφτείτε να μας βοηθήσετε με μια καλή κριτική!" + }, + "browserNotSupportClipboard": { + "message": "Το πρόγραμμα περιήγησης ιστού δεν υποστηρίζει εύκολη αντιγραφή πρόχειρου. Αντιγράψτε το με το χέρι αντ'αυτού." + }, + "verifyIdentity": { + "message": "Επιβεβαίωση ταυτότητας" + }, + "yourVaultIsLocked": { + "message": "Το vault σας είναι κλειδωμένο. Επαληθεύστε τον κύριο κωδικό πρόσβασης για να συνεχίσετε." + }, + "unlock": { + "message": "Ξεκλείδωμα" + }, + "loggedInAsOn": { + "message": "Συνδεθήκατε ως $EMAIL$ στο $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Μη έγκυρος κύριος κωδικός πρόσβασης" + }, + "vaultTimeout": { + "message": "Χρόνος Λήξης Vault" + }, + "lockNow": { + "message": "Κλείδωμα Τώρα" + }, + "immediately": { + "message": "Άμεσα" + }, + "tenSeconds": { + "message": "10 δευτερόλεπτα" + }, + "twentySeconds": { + "message": "20 δευτερόλεπτα" + }, + "thirtySeconds": { + "message": "30 δευτερόλεπτα" + }, + "oneMinute": { + "message": "1 λεπτό" + }, + "twoMinutes": { + "message": "2 λεπτά" + }, + "fiveMinutes": { + "message": "5 λεπτά" + }, + "fifteenMinutes": { + "message": "15 λεπτά" + }, + "thirtyMinutes": { + "message": "30 λεπτά" + }, + "oneHour": { + "message": "1 ώρα" + }, + "fourHours": { + "message": "4 ώρες" + }, + "onLocked": { + "message": "Κατά το Κλείδωμα Συστήματος" + }, + "onRestart": { + "message": "Κατά την Επανεκκίνηση του Browser" + }, + "never": { + "message": "Ποτέ" + }, + "security": { + "message": "Ασφάλεια" + }, + "errorOccurred": { + "message": "Παρουσιάστηκε σφάλμα" + }, + "emailRequired": { + "message": "Απαιτείται διεύθυνση e-mail." + }, + "invalidEmail": { + "message": "Μη έγκυρη διεύθυνση e-mail." + }, + "masterPassRequired": { + "message": "Απαιτείται κύριος κωδικός πρόσβασης." + }, + "masterPassLength": { + "message": "Ο κύριος κωδικός πρέπει να έχει μήκος τουλάχιστον 8 χαρακτήρες." + }, + "masterPassDoesntMatch": { + "message": "Η επιβεβαίωση κύριου κωδικού δεν ταιριάζει." + }, + "newAccountCreated": { + "message": "Ο λογαριασμός σας έχει δημιουργηθεί! Τώρα μπορείτε να συνδεθείτε." + }, + "masterPassSent": { + "message": "Σας στείλαμε ένα email με την υπόδειξη του κύριου κωδικού." + }, + "verificationCodeRequired": { + "message": "Απαιτείται ο κωδικός επαλήθευσης." + }, + "invalidVerificationCode": { + "message": "Μη έγκυρος κωδικός επαλήθευσης" + }, + "valueCopied": { + "message": "$VALUE$ αντιγράφηκε", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Δεν είναι δυνατή η αυτόματη συμπλήρωση του επιλεγμένου στοιχείου σε αυτήν τη σελίδα. Αντιγράψτε και επικολλήστε τις πληροφορίες." + }, + "loggedOut": { + "message": "Αποσυνδεθήκατε" + }, + "loginExpired": { + "message": "Η περίοδος σύνδεσης σας έχει λήξει." + }, + "logOutConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να αποσυνδεθείτε;" + }, + "yes": { + "message": "Ναι" + }, + "no": { + "message": "Όχι" + }, + "unexpectedError": { + "message": "Παρουσιάστηκε ένα μη αναμενόμενο σφάλμα." + }, + "nameRequired": { + "message": "Απαιτείται όνομα." + }, + "addedFolder": { + "message": "Προστέθηκε φάκελος" + }, + "changeMasterPass": { + "message": "Αλλαγή Κύριου Κωδικού" + }, + "changeMasterPasswordConfirmation": { + "message": "Μπορείτε να αλλάξετε τον κύριο κωδικό στο bitwarden.com. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "twoStepLoginConfirmation": { + "message": "Η σύνδεση σε δύο βήματα καθιστά πιο ασφαλή τον λογαριασμό σας, απαιτώντας να επαληθεύσετε τα στοιχεία σας με μια άλλη συσκευή, όπως κλειδί ασφαλείας, εφαρμογή επαλήθευσης, μήνυμα SMS, τηλεφωνική κλήση ή email. Μπορείτε να ενεργοποιήσετε τη σύνδεση σε δύο βήματα στο bitwarden.com. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "editedFolder": { + "message": "Επεξεργασμένος φάκελος" + }, + "deleteFolderConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτόν το φάκελο;" + }, + "deletedFolder": { + "message": "Διεγραμμένος φάκελος" + }, + "gettingStartedTutorial": { + "message": "Οδηγός Εκμάθησης" + }, + "gettingStartedTutorialVideo": { + "message": "Παρακολουθήστε τον οδηγό εκμάθησης μας, για να μάθετε πώς μπορείτε να αξιοποιήσετε στο έπακρο την επέκταση του προγράμματος περιήγησης." + }, + "syncingComplete": { + "message": "Ο συγχρονισμός ολοκληρώθηκε" + }, + "syncingFailed": { + "message": "Ο συγχρονισμός απέτυχε" + }, + "passwordCopied": { + "message": "Ο κωδικός αντιγράφηκε" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Νέο URI" + }, + "addedItem": { + "message": "Προστέθηκε στοιχείο" + }, + "editedItem": { + "message": "Επεξεργασμένο στοιχείο" + }, + "deleteItemConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το στοιχείο;" + }, + "deletedItem": { + "message": "Διαγραμμένο στοιχείο" + }, + "overwritePassword": { + "message": "Αντικατάσταση Κωδικού Πρόσβασης" + }, + "overwritePasswordConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να αντικαταστήσετε τον τρέχον κωδικό πρόσβασης;" + }, + "overwriteUsername": { + "message": "Αντικατάσταση Username" + }, + "overwriteUsernameConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να αντικαταστήσετε το τρέχον username;" + }, + "searchFolder": { + "message": "Αναζήτηση σε φάκελο" + }, + "searchCollection": { + "message": "Αναζήτηση στη συλλογή" + }, + "searchType": { + "message": "Τύπος αναζήτησης" + }, + "noneFolder": { + "message": "Χωρίς Φάκελο", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Απενεργοποιήστε την Προσθήκη Ειδοποίησης Σύνδεσης" + }, + "addLoginNotificationDesc": { + "message": "Η \"Προσθήκη Ειδοποίησης Σύνδεσης\" σας προτρέπει αυτόματα να αποθηκεύσετε νέες συνδέσεις στο vault σας κάθε φορά που θα συνδεθείτε για πρώτη φορά." + }, + "dontShowCardsCurrentTab": { + "message": "Να μην Εμφανίζονται Κάρτες στη Σελίδα Καρτέλας" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Τα στοιχεία καρτών από το vault σας παρατίθενται στη σελίδα \"Τρέχουσα καρτέλα\" για εύκολη πρόσβαση με αυτόματη συμπλήρωση." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Να μην εμφανίζονται ταυτότητες στην καρτέλα" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Στοιχεία ταυτότητας από το vault σας, παρατίθενται στη σελίδα \"Τρέχουσα καρτέλα\" για εύκολη πρόσβαση με αυτόματη συμπλήρωση." + }, + "clearClipboard": { + "message": "Εκκαθάριση Πρόχειρου", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Αυτόματη εκκαθάριση αντιγραμμένων τιμών προχείρου.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Πρέπει το Bitwarden να θυμάται αυτόν τον κωδικό πρόσβασης για εσάς;" + }, + "notificationAddSave": { + "message": "Ναι, Αποθήκευση Τώρα" + }, + "disableChangedPasswordNotification": { + "message": "Απενεργοποίηση ειδοποίησης αλλαγής κωδικού πρόσβασης" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Η \"Ειδοποίηση Αλλαγής Κωδικού\" σας ζητά αυτόματα να ενημερώσετε τον κωδικό πρόσβασης του εισερχόμενου στο vault σας κάθε φορά που εντοπίζει ότι το έχετε αλλάξει σε έναν ιστότοπο." + }, + "notificationChangeDesc": { + "message": "Θέλετε να ενημερώσετε αυτό τον κωδικό στο Bitwarden ;" + }, + "notificationChangeSave": { + "message": "Ναι, Ενημέρωση Τώρα" + }, + "disableContextMenuItem": { + "message": "Απενεργοποιήστε τις Επιλογές του Μενού Περιβάλλοντος" + }, + "disableContextMenuItemDesc": { + "message": "Οι επιλογές του μενού περιβάλλοντος παρέχουν γρήγορη πρόσβαση στην δημιουργία και σύνδεση κωδικών πρόσβασης για τον ιστότοπο στην τρέχουσα καρτέλα." + }, + "defaultUriMatchDetection": { + "message": "Προεπιλεγμένη ανίχνευση αντιστοιχίας URI", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Επιλέξτε τον προκαθορισμένο τρόπο με τον οποίο αντιμετωπίζεται η ανίχνευση αντιστοίχισης URI για τις συνδέσεις κατά την εκτέλεση ενεργειών όπως η αυτόματη συμπλήρωση." + }, + "theme": { + "message": "Θέμα" + }, + "themeDesc": { + "message": "Αλλαγή χρώματος θέματος εφαρμογής." + }, + "dark": { + "message": "Σκοτεινό", + "description": "Dark color" + }, + "light": { + "message": "Φωτεινό", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Σκούρο", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Εξαγωγή Vault" + }, + "fileFormat": { + "message": "Μορφή Αρχείου" + }, + "warning": { + "message": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Επιβεβαίωση εξαγωγής Vault" + }, + "exportWarningDesc": { + "message": "Αυτή η εξαγωγή περιέχει τα δεδομένα σε μη κρυπτογραφημένη μορφή. Δεν πρέπει να αποθηκεύετε ή να στείλετε το εξαγόμενο αρχείο μέσω μη ασφαλών τρόπων (όπως μέσω email). Διαγράψτε το αμέσως μόλις τελειώσετε με τη χρήση του." + }, + "encExportKeyWarningDesc": { + "message": "Αυτή η εξαγωγή κρυπτογραφεί τα δεδομένα σας χρησιμοποιώντας το κλειδί κρυπτογράφησης του λογαριασμού σας. Εάν ποτέ περιστρέψετε το κλειδί κρυπτογράφησης του λογαριασμού σας, θα πρέπει να κάνετε εξαγωγή ξανά, καθώς δεν θα μπορείτε να αποκρυπτογραφήσετε αυτό το αρχείο εξαγωγής." + }, + "encExportAccountWarningDesc": { + "message": "Τα κλειδιά κρυπτογράφησης λογαριασμού είναι μοναδικά για κάθε λογαριασμό χρήστη Bitwarden, οπότε δεν μπορείτε να εισάγετε μια κρυπτογραφημένη εξαγωγή σε διαφορετικό λογαριασμό." + }, + "exportMasterPassword": { + "message": "Πληκτρολογήστε τον κύριο κωδικό για εξαγωγή δεδομένων vault." + }, + "shared": { + "message": "Κοινοποιήθηκε" + }, + "learnOrg": { + "message": "Μάθετε για τους Οργανισμούς" + }, + "learnOrgConfirmation": { + "message": "Το Bitwarden επιτρέπει να μοιράζεστε τα στοιχεία του vault σας με άλλους χρησιμοποιώντας ένα λογαριασμό οργανισμού. Θέλετε να επισκεφθείτε την ιστοσελίδα bitwarden.com για να μάθετε περισσότερα;" + }, + "moveToOrganization": { + "message": "Μετακίνηση στον Οργανισμό" + }, + "share": { + "message": "Κοινοποίηση" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ μετακινήθηκε στο $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Επιλέξτε έναν οργανισμό στον οποίο θέλετε να μετακινήσετε αυτό το στοιχείο. Η μετακίνηση σε έναν οργανισμό μεταβιβάζει την ιδιοκτησία του στοιχείου σε αυτό τον οργανισμό. Δεν θα είστε πλέον ο άμεσος ιδιοκτήτης αυτού του στοιχείου μόλις το μετακινήσετε." + }, + "learnMore": { + "message": "Μάθετε περισσότερα" + }, + "authenticatorKeyTotp": { + "message": "Κλειδί επαλήθευσης (TOTP)" + }, + "verificationCodeTotp": { + "message": "Κωδικός Επαλήθευσης (TOTP)" + }, + "copyVerificationCode": { + "message": "Αντιγραφή Κωδικού Επαλήθευσης" + }, + "attachments": { + "message": "Συνημμένα" + }, + "deleteAttachment": { + "message": "Διαγραφή συννημένου" + }, + "deleteAttachmentConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το συννημένο;" + }, + "deletedAttachment": { + "message": "Το συνημμένο διαγράφηκε" + }, + "newAttachment": { + "message": "Προσθήκη Νέου Συνημμένου" + }, + "noAttachments": { + "message": "Χωρίς συνημμένα." + }, + "attachmentSaved": { + "message": "Το συννημένο έχει αποθηκευτεί." + }, + "file": { + "message": "Αρχείο" + }, + "selectFile": { + "message": "Επιλέξτε ένα αρχείο." + }, + "maxFileSize": { + "message": "Το μέγιστο μέγεθος αρχείου είναι 500 MB." + }, + "featureUnavailable": { + "message": "Μη Διαθέσιμο Χαρακτηριστικό" + }, + "updateKey": { + "message": "Δεν μπορείτε να χρησιμοποιήσετε αυτήν τη λειτουργία μέχρι να ενημερώσετε το κλειδί κρυπτογράφησης." + }, + "premiumMembership": { + "message": "Συνδρομή Premium" + }, + "premiumManage": { + "message": "Διαχείριση Συνδρομής" + }, + "premiumManageAlert": { + "message": "Μπορείτε να διαχειριστείτε την ιδιότητά σας ως μέλος στο bitwarden.com web vault. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "premiumRefresh": { + "message": "Ανανέωση Συνδρομής" + }, + "premiumNotCurrentMember": { + "message": "Δεν είστε premium μέλος." + }, + "premiumSignUpAndGet": { + "message": "Εγγραφείτε για μια premium συνδρομή και λάβετε:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB κρυπτογραφημένο αποθηκευτικό χώρο για συνημμένα αρχεία." + }, + "ppremiumSignUpTwoStep": { + "message": "Πρόσθετες επιλογές σύνδεσης δύο βημάτων, όπως το YubiKey, το FIDO U2F και το Duo." + }, + "ppremiumSignUpReports": { + "message": "Ασφάλεια κωδικών, υγεία λογαριασμού και αναφορές παραβίασης δεδομένων για να διατηρήσετε ασφαλές το vault σας." + }, + "ppremiumSignUpTotp": { + "message": "Δημιουργία TOTP κωδικού επαλήθευσης (2FA), για συνδέσεις στο vault σας." + }, + "ppremiumSignUpSupport": { + "message": "Προτεραιότητα υποστήριξης πελατών." + }, + "ppremiumSignUpFuture": { + "message": "Όλα τα μελλοντικά χαρακτηριστικά premium. Έρχονται περισσότερα σύντομα!" + }, + "premiumPurchase": { + "message": "Αγορά Premium έκδοσης" + }, + "premiumPurchaseAlert": { + "message": "Μπορείτε να αγοράσετε συνδρομή premium στο bitwarden.com web vault. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "premiumCurrentMember": { + "message": "Είστε ένα premium μέλος!" + }, + "premiumCurrentMemberThanks": { + "message": "Ευχαριστούμε που υποστηρίζετε το Bitwarden." + }, + "premiumPrice": { + "message": "Όλα για μόνο $PRICE$ /έτος!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Επιτυχής ανανέωση" + }, + "disableAutoTotpCopy": { + "message": "Απενεργοποίηση Aυτόματης Aντιγραφής TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Εάν η σύνδεση έχει συνημμένο κάποιο κλειδί επαλήθευσης, ο κωδικός επαλήθευσης TOTP αντιγράφεται αυτόματα στο πρόχειρο κάθε φορά που συμπληρώνετε αυτόματα τα στοιχεία σύνδεσης." + }, + "disableAutoBiometricsPrompt": { + "message": "Μην ζητάτε βιομετρικά στοιχεία κατά την εκκίνηση" + }, + "premiumRequired": { + "message": "Απαιτείται Έκδοση Premium" + }, + "premiumRequiredDesc": { + "message": "Για να χρησιμοποιήσετε αυτή τη λειτουργία, απαιτείται η έκδοση premium." + }, + "enterVerificationCodeApp": { + "message": "Εισάγετε τον 6ψήφιο κωδικό από την εφαρμογή επαλήθευσης." + }, + "enterVerificationCodeEmail": { + "message": "Εισάγετε τον 6ψήφιο κωδικό επαλήθευσης τον οποίο λάβατε στο $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Εστάλη email επαλήθευσης στο $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Να με θυμάσαι" + }, + "sendVerificationCodeEmailAgain": { + "message": "Αποστολή email κωδικού επαλήθευσης ξανά" + }, + "useAnotherTwoStepMethod": { + "message": "Χρήση άλλης μεθόδου σύνδεσης δύο παραγόντων" + }, + "insertYubiKey": { + "message": "Τοποθετήστε το YubiKey στη θύρα USB του υπολογιστή σας και έπειτα κάντε κλικ στο κουμπί του." + }, + "insertU2f": { + "message": "Εισάγετε το κλειδί ασφαλείας στη θύρα USB του υπολογιστή σας. Αν έχει κουμπί, πατήστε το." + }, + "webAuthnNewTab": { + "message": "Συνεχίστε την επαλήθευση WebAuthn 2FA στη νέα καρτέλα." + }, + "webAuthnNewTabOpen": { + "message": "Άνοιγμα νέας καρτέλας" + }, + "webAuthnAuthenticate": { + "message": "Ταυτοποίηση WebAuthn" + }, + "loginUnavailable": { + "message": "Σύνδεση μη Διαθέσιμη" + }, + "noTwoStepProviders": { + "message": "Αυτός ο λογαριασμός έχει ενεργοποιημένη τη σύνδεση σε δύο βήματα, ωστόσο, κανένας από τους διαμορφωμένους παροχείς δύο βημάτων δεν υποστηρίζεται από αυτό το πρόγραμμα περιήγησης." + }, + "noTwoStepProviders2": { + "message": "Παρακαλούμε χρησιμοποιήστε ένα υποστηριζόμενο πρόγραμμα περιήγησης (όπως το Chrome) και/ή προσθέστε επιπλέον ή/και προσθέστε άλλους παρόχους που υποστηρίζονται καλύτερα σε προγράμματα περιήγησης (όπως μια εφαρμογή επαλήθευσης)." + }, + "twoStepOptions": { + "message": "Επιλογές σύνδεσης δύο παραγόντων" + }, + "recoveryCodeDesc": { + "message": "Έχετε χάσει την πρόσβαση σε όλους τους παρόχους δύο παραγόντων; Χρησιμοποιήστε τον κωδικό ανάκτησης για να απενεργοποιήσετε όλους τους παρόχους δύο παραγόντων από το λογαριασμό σας." + }, + "recoveryCodeTitle": { + "message": "Κωδικός Ανάκτησης" + }, + "authenticatorAppTitle": { + "message": "Εφαρμογή Επαλήθευσης Ταυτότητας" + }, + "authenticatorAppDesc": { + "message": "Χρησιμοποιήστε μια εφαρμογή επαλήθευσης (όπως το Authy ή Google Authenticator) για να δημιουργήσει κωδικούς επαλήθευσης με χρόνικο περιορισμό.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Κλειδί ασφαλείας YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Χρησιμοποιήστε ένα YubiKey για να αποκτήσετε πρόσβαση στο λογαριασμό σας. Λειτουργεί με συσκευές σειράς YubiKey 4, 4 Nano, 4C και συσκευές NEO." + }, + "duoDesc": { + "message": "Επαληθεύστε με το Duo Security χρησιμοποιώντας την εφαρμογή Duo Mobile, μηνύματα SMS, τηλεφωνική κλήση ή κλειδί ασφαλείας U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Επαληθεύστε με το Duo Security για τον οργανισμό σας χρησιμοποιώντας την εφαρμογή Duo Mobile, μηνύματα SMS, τηλεφωνική κλήση ή κλειδί ασφαλείας U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Χρησιμοποιήστε οποιοδήποτε κλειδί ασφαλείας WebAuthn για να αποκτήσετε πρόσβαση στο λογαριασμό σας." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Οι κωδικοί επαλήθευσης θα σας αποσταλούν μέσω ηλεκτρονικού ταχυδρομείου." + }, + "selfHostedEnvironment": { + "message": "Αυτο-φιλοξενούμενο περιβάλλον" + }, + "selfHostedEnvironmentFooter": { + "message": "Καθορίστε τη βασική διεύθυνση URL, της εγκατάστασης του Bitwarden που φιλοξενείται στο χώρο σας." + }, + "customEnvironment": { + "message": "Προσαρμοσμένο περιβάλλον" + }, + "customEnvironmentFooter": { + "message": "Για προχωρημένους χρήστες. Μπορείτε να ορίσετε ανεξάρτητα τη βασική διεύθυνση URL κάθε υπηρεσίας." + }, + "baseUrl": { + "message": "URL Διακομιστή" + }, + "apiUrl": { + "message": "URL Διακομιστή API" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "URL Ταυτότητας Διακομιστή" + }, + "notificationsUrl": { + "message": "Ειδοποιήσεις Διεύθυνσης URL Διακομιστή" + }, + "iconsUrl": { + "message": "Εικονίδια διακομιστή URL" + }, + "environmentSaved": { + "message": "Οι διευθύνσεις URL περιβάλλοντος έχουν αποθηκευτεί." + }, + "enableAutoFillOnPageLoad": { + "message": "Ενεργοποίηση αυτόματης συμπλήρωσης κατά την φόρτωση της σελίδας" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Εάν εντοπιστεί μια φόρμα σύνδεσης, πραγματοποιείται αυτόματα μια αυτόματη συμπλήρωση όταν φορτώνεται η ιστοσελίδα." + }, + "experimentalFeature": { + "message": "Αυτή είναι μια πειραματική λειτουργία. Χρησιμοποιήστε το με δική σας ευθύνη." + }, + "defaultAutoFillOnPageLoad": { + "message": "Προεπιλεγμένη ρύθμιση αυτόματης συμπλήρωσης για στοιχεία σύνδεσης" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Αφού ενεργοποιήσετε την αυτόματη συμπλήρωση κατά τη Φόρτωση Σελίδας, μπορείτε να ενεργοποιήσετε ή να απενεργοποιήσετε τη λειτουργία για μεμονωμένα στοιχεία σύνδεσης. Αυτή είναι η προεπιλεγμένη ρύθμιση για στοιχεία σύνδεσης που δεν έχουν ρυθμιστεί ξεχωριστά." + }, + "itemAutoFillOnPageLoad": { + "message": "Αυτόματη συμπλήρωση της Φόρτισης Σελίδας (αν είναι ενεργοποιημένη στις Επιλογές)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Χρήση προεπιλεγμένης ρύθμισης" + }, + "autoFillOnPageLoadYes": { + "message": "Αυτόματη συμπλήρωση κατά την φόρτωση της σελίδας" + }, + "autoFillOnPageLoadNo": { + "message": "Μη αυτόματη συμπλήρωση κατά τη φόρτωση της σελίδας" + }, + "commandOpenPopup": { + "message": "Άνοιγμα αναδυόμενου vault" + }, + "commandOpenSidebar": { + "message": "Άνοιγμα αναδυόμενου vault στην πλευρική μπάρα" + }, + "commandAutofillDesc": { + "message": "Αυτόματη συμπλήρωση της τελευταίας χρησιμοποιούμενης σύνδεσης για αυτόν τον ιστότοπο" + }, + "commandGeneratePasswordDesc": { + "message": "Δημιουργήστε και αντιγράψτε έναν νέο τυχαίο κωδικό πρόσβασης στο πρόχειρο" + }, + "commandLockVaultDesc": { + "message": "Κλειδώστε το vault" + }, + "privateModeWarning": { + "message": "Η υποστήριξη ιδιωτικής λειτουργίας είναι πειραματική και ορισμένες δυνατότητες είναι περιορισμένες." + }, + "customFields": { + "message": "Προσαρμοσμένα Πεδία" + }, + "copyValue": { + "message": "Αντιγραφή Τιμής" + }, + "value": { + "message": "Τιμή" + }, + "newCustomField": { + "message": "Νέο Προσαρμοσμένο Πεδίο" + }, + "dragToSort": { + "message": "Σύρετε για ταξινόμηση" + }, + "cfTypeText": { + "message": "Κείμενο" + }, + "cfTypeHidden": { + "message": "Κρυφό" + }, + "cfTypeBoolean": { + "message": "Δυαδικό" + }, + "cfTypeLinked": { + "message": "Συνδεδεμένο", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Συνδεδεμένη τιμή", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Εάν κάνετε κλικ έξω από το αναδυόμενο παράθυρο για να ελέγξετε το email για κωδικό επαλήθευσης, το αναδυόμενο παράθυρο θα κλείσει. Θέλετε να ανοίξετε αυτό το αναδυόμενο σε νέο παράθυρο ώστε να μην κλείνει;" + }, + "popupU2fCloseMessage": { + "message": "Αυτό το πρόγραμμα περιήγησης δεν μπορεί να επεξεργαστεί αιτήματα του U2F σε αυτό το αναδυόμενο παράθυρο. Θέλετε να ανοίξετε το αναδυόμενο σε νέο παράθυρο, ώστε να μπορείτε να συνδεθείτε χρησιμοποιώντας U2F;" + }, + "disableFavicon": { + "message": "Απενεργοποίηση Εικονιδίων Ιστοσελίδας" + }, + "disableFaviconDesc": { + "message": "Τα εικονίδια ιστοσελίδων παρέχουν μια αναγνωρίσιμη εικόνα δίπλα σε κάθε στοιχείο σύνδεσης της λίστας σας." + }, + "disableBadgeCounter": { + "message": "Απενεργοποίηση Μετρητή Σημάτων" + }, + "disableBadgeCounterDesc": { + "message": "Ο μετρητής εμβλημάτων δείχνει πόσες συνδέσεις έχετε για την τρέχουσα σελίδα στο vault σας." + }, + "cardholderName": { + "message": "Όνομα κατόχου της κάρτας" + }, + "number": { + "message": "Αριθμός" + }, + "brand": { + "message": "Επωνυμία" + }, + "expirationMonth": { + "message": "Μήνας Λήξης" + }, + "expirationYear": { + "message": "Έτος λήξης" + }, + "expiration": { + "message": "Λήξη" + }, + "january": { + "message": "Ιανουάριος" + }, + "february": { + "message": "Φεβρουάριος" + }, + "march": { + "message": "Μάρτιος" + }, + "april": { + "message": "Απρίλιος" + }, + "may": { + "message": "Μάιος" + }, + "june": { + "message": "Ιούνιος" + }, + "july": { + "message": "Ιούλιος" + }, + "august": { + "message": "Αύγουστος" + }, + "september": { + "message": "Σεπτέμβριος" + }, + "october": { + "message": "Οκτώβριος" + }, + "november": { + "message": "Νοέμβριος" + }, + "december": { + "message": "Δεκέμβριος" + }, + "securityCode": { + "message": "Κωδικός Ασφαλείας" + }, + "ex": { + "message": "πχ." + }, + "title": { + "message": "Τίτλος" + }, + "mr": { + "message": "Κος" + }, + "mrs": { + "message": "Κα" + }, + "ms": { + "message": "Κα" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Όνομα" + }, + "middleName": { + "message": "Μεσαίο όνομα" + }, + "lastName": { + "message": "Επίθετο" + }, + "fullName": { + "message": "Ονοματεπώνυμο" + }, + "identityName": { + "message": "Όνομα Ταυτότητας" + }, + "company": { + "message": "Εταιρεία" + }, + "ssn": { + "message": "ΑΜΚΑ" + }, + "passportNumber": { + "message": "Αριθμός Διαβατηρίου" + }, + "licenseNumber": { + "message": "Αριθμός Άδειας" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Τηλέφωνο" + }, + "address": { + "message": "Διεύθυνση" + }, + "address1": { + "message": "Διεύθυνση 1" + }, + "address2": { + "message": "Διεύθυνση 2" + }, + "address3": { + "message": "Διεύθυνση 3" + }, + "cityTown": { + "message": "Πόλη / Κωμόπολη" + }, + "stateProvince": { + "message": "Περιοχή / Νομός" + }, + "zipPostalCode": { + "message": "Ταχυδρομικός Κώδικας" + }, + "country": { + "message": "Χώρα" + }, + "type": { + "message": "Τύπος" + }, + "typeLogin": { + "message": "Σύνδεση" + }, + "typeLogins": { + "message": "Συνδέσεις" + }, + "typeSecureNote": { + "message": "Ασφαλής Σημείωση" + }, + "typeCard": { + "message": "Κάρτα" + }, + "typeIdentity": { + "message": "Ταυτότητα" + }, + "passwordHistory": { + "message": "Ιστορικό Κωδικού" + }, + "back": { + "message": "Πίσω" + }, + "collections": { + "message": "Συλλογές" + }, + "favorites": { + "message": "Αγαπημένα" + }, + "popOutNewWindow": { + "message": "Αναδύεται σε ένα νέο παράθυρο" + }, + "refresh": { + "message": "Ανανέωση" + }, + "cards": { + "message": "Κάρτες" + }, + "identities": { + "message": "Ταυτότητες" + }, + "logins": { + "message": "Συνδέσεις" + }, + "secureNotes": { + "message": "Ασφαλείς Σημειώσεις" + }, + "clear": { + "message": "Εκκαθάριση", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Ελέγξτε εάν ο κωδικός έχει εκτεθεί." + }, + "passwordExposed": { + "message": "Αυτός ο κωδικός έχει εκτεθεί $VALUE$ φορά (ές) σε διαρροές δεδομένων. Πρέπει να τον αλλάξετε.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Αυτός ο κωδικός δεν βρέθηκε σε κάποια γνωστή διαρροή δεδομένων. Θα πρέπει να είναι ασφαλής για χρήση." + }, + "baseDomain": { + "message": "Βασικός τομέας", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Όνομα τομέα", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Διακομιστής", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Ακριβής" + }, + "startsWith": { + "message": "Έναρξη με" + }, + "regEx": { + "message": "Κανονική έκφραση", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Εντοπισμός Αντιστοίχισης", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Προεπιλεγμένος εντοπισμός αντιστοίχισης", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Επιλογές Εναλλαγής" + }, + "toggleCurrentUris": { + "message": "Εναλλαγή τρεχόντων URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Τρεχόν URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Οργανισμός", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Τύποι" + }, + "allItems": { + "message": "Όλα τα στοιχεία" + }, + "noPasswordsInList": { + "message": "Δεν υπάρχουν κωδικοί στη λίστα." + }, + "remove": { + "message": "Αφαίρεση" + }, + "default": { + "message": "Προεπιλογή" + }, + "dateUpdated": { + "message": "Ενημερώθηκε", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Ο Κωδικός Ενημερώθηκε", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Είστε βέβαιοι ότι θέλετε να χρησιμοποιήσετε την επιλογή \"Ποτέ\"; Ο ορισμός των επιλογών κλειδώματος σε \"Ποτέ\" αποθηκεύει το κλειδί κρυπτογράφησης του vault στη συσκευή σας. Εάν χρησιμοποιήσετε αυτήν την επιλογή, θα πρέπει να διασφαλίσετε ότι θα διατηρείτε τη συσκευή σας σωστά προστατευμένη." + }, + "noOrganizationsList": { + "message": "Δεν συμμετέχετε σε κάποιον οργανισμό. Οι οργανισμοί επιτρέπουν την ασφαλή κοινοποίηση στοιχείων με άλλους χρήστες." + }, + "noCollectionsInList": { + "message": "Δεν υπάρχουν στοιχεία για εμφάνιση." + }, + "ownership": { + "message": "Ιδιοκτησία" + }, + "whoOwnsThisItem": { + "message": "Ποιος κατέχει αυτό το στοιχείο;" + }, + "strong": { + "message": "Ισχυρός", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Καλός", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Αδύναμος", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Αδύναμος Κύριος Κωδικός" + }, + "weakMasterPasswordDesc": { + "message": "Ο κύριος κωδικός που έχετε επιλέξει είναι αδύναμος. Θα πρέπει να χρησιμοποιήσετε έναν ισχυρό κύριο κωδικό (ή μια φράση) για την κατάλληλη προστασία του λογαριασμού Bitwarden. Είστε βέβαιοι ότι θέλετε να χρησιμοποιήσετε αυτόν τον κύριο κωδικό;" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Ξεκλείδωμα με PIN" + }, + "setYourPinCode": { + "message": "Ορίστε τον κωδικό PIN για να ξεκλειδώσετε το Bitwarden. Οι ρυθμίσεις PIN θα επαναρυθμιστούν αν αποσυνδεθείτε πλήρως από την εφαρμογή." + }, + "pinRequired": { + "message": "Απαιτείται κωδικός PIN." + }, + "invalidPin": { + "message": "Μη έγκυρος κωδικός PIN." + }, + "unlockWithBiometrics": { + "message": "Ξεκλείδωμα με βιομετρικά στοιχεία" + }, + "awaitDesktop": { + "message": "Αναμονή επιβεβαίωσης από την επιφάνεια εργασίας" + }, + "awaitDesktopDesc": { + "message": "Παρακαλώ επιβεβαιώστε τη χρήση βιομετρικών στοιχείων στην εφαρμογή Bitwarden Desktop για να ενεργοποιήσετε τα βιομετρικά στοιχεία για το πρόγραμμα περιήγησης." + }, + "lockWithMasterPassOnRestart": { + "message": "Κλείδωμα με κύριο κωδικό πρόσβασης στην επανεκκίνηση του προγράμματος περιήγησης" + }, + "selectOneCollection": { + "message": "Πρέπει να επιλέξετε τουλάχιστον μία συλλογή." + }, + "cloneItem": { + "message": "Κλώνος Αντικειμένου" + }, + "clone": { + "message": "Κλώνος" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Μία ή περισσότερες πολιτικές του οργανισμού επηρεάζουν τις ρυθμίσεις της γεννήτριας." + }, + "vaultTimeoutAction": { + "message": "Ενέργεια Χρόνου Λήξης Vault" + }, + "lock": { + "message": "Κλείδωμα", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Κάδος Απορριμάτων", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Αναζήτηση Κάδου" + }, + "permanentlyDeleteItem": { + "message": "Μόνιμη Διαγραφή Αντικειμένου" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε μόνιμα αυτό το στοιχείο;" + }, + "permanentlyDeletedItem": { + "message": "Μόνιμα Διεγραμμένο Στοιχείο" + }, + "restoreItem": { + "message": "Ανάκτηση Στοιχείου" + }, + "restoreItemConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να ανακτήσετε αυτό το στοιχείο;" + }, + "restoredItem": { + "message": "Στοιχείο που έχει Ανακτηθεί" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Η αποσύνδεση θα καταργήσει όλη την πρόσβαση στο vault σας και απαιτεί online έλεγχο ταυτότητας μετά το χρονικό όριο λήξης. Είστε βέβαιοι ότι θέλετε να χρησιμοποιήσετε αυτήν τη ρύθμιση;" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Επιβεβαίωση Ενέργειας Χρονικού Ορίου" + }, + "autoFillAndSave": { + "message": "Αυτόματη συμπλήρωση και αποθήκευση" + }, + "autoFillSuccessAndSavedUri": { + "message": "Αυτόματη συμπλήρωση στοιχείου και αποθηκευμένο URI" + }, + "autoFillSuccess": { + "message": "Αυτόματη συμπλήρωση αντικειμένου" + }, + "setMasterPassword": { + "message": "Ορισμός Κύριου Κωδικού" + }, + "masterPasswordPolicyInEffect": { + "message": "Σε μία ή περισσότερες πολιτικές του οργανισμού απαιτείται ο κύριος κωδικός να πληρεί τις ακόλουθες απαιτήσεις:" + }, + "policyInEffectMinComplexity": { + "message": "Ελάχιστος βαθμός πολυπλοκότητας: $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Ελάχιστο μήκος: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Να περιέχει έναν ή περισσότερους κεφαλαίους χαρακτήρες" + }, + "policyInEffectLowercase": { + "message": "Να περιέχει έναν ή περισσότερους πεζούς χαρακτήρες" + }, + "policyInEffectNumbers": { + "message": "Να περιέχει έναν ή περισσότερους αριθμούς" + }, + "policyInEffectSpecial": { + "message": "Να περιέχει έναν ή περισσότερους από τους ακόλουθους ειδικούς χαρακτήρες $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ο νέος κύριος κωδικός δεν πληροί τις απαιτήσεις πολιτικής." + }, + "acceptPolicies": { + "message": "Επιλέγοντας αυτό το πλαίσιο, συμφωνείτε με τα εξής:" + }, + "acceptPoliciesError": { + "message": "Οι Όροι Παροχής Υπηρεσιών και η Πολιτική Απορρήτου δεν έχουν αναγνωριστεί." + }, + "termsOfService": { + "message": "Όροι Χρήσης" + }, + "privacyPolicy": { + "message": "Πολιτική Απορρήτου" + }, + "hintEqualsPassword": { + "message": "Η υπόδειξη κωδικού πρόσβασης, δεν μπορεί να είναι η ίδια με τον κωδικό πρόσβασης σας." + }, + "ok": { + "message": "Οκ" + }, + "desktopSyncVerificationTitle": { + "message": "Επιβεβαίωση συγχρονισμού επιφάνειας εργασίας" + }, + "desktopIntegrationVerificationText": { + "message": "Παρακαλώ επιβεβαιώστε ότι η εφαρμογή επιφάνειας εργασίας εμφανίζει αυτό το αποτύπωμα: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Η ενσωμάτωση του περιηγητή δεν είναι ενεργοποιημένη" + }, + "desktopIntegrationDisabledDesc": { + "message": "Η ενσωμάτωση του προγράμματος περιήγησης δεν είναι ενεργοποιημένη στην εφαρμογή Bitwarden Desktop. Παρακαλώ ενεργοποιήστε την στις ρυθμίσεις της εφαρμογής desktop." + }, + "startDesktopTitle": { + "message": "Ξεκινήστε την εφαρμογή Bitwarden Επιφάνεια εργασίας" + }, + "startDesktopDesc": { + "message": "Η εφαρμογή Bitwarden Desktop πρέπει να ξεκινήσει για να μπορεί να χρησιμοποιηθεί αυτή η λειτουργία." + }, + "errorEnableBiometricTitle": { + "message": "Αδυναμία ενεργοποίησης βιομετρικών στοιχείων" + }, + "errorEnableBiometricDesc": { + "message": "Η ενέργεια ακυρώθηκε από την εφαρμογή επιφάνειας εργασίας" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Η εφαρμογή επιφάνειας εργασίας ακυρώνει το ασφαλές κανάλι επικοινωνίας. Παρακαλώ δοκιμάστε ξανά αυτή τη λειτουργία" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Η επικοινωνία επιφάνειας εργασίας διακόπηκε" + }, + "nativeMessagingWrongUserDesc": { + "message": "Η εφαρμογή επιφάνειας εργασίας είναι συνδεδεμένη σε διαφορετικό λογαριασμό. Παρακαλώ βεβαιωθείτε ότι και οι δύο εφαρμογές είναι συνδεδεμένες στον ίδιο λογαριασμό." + }, + "nativeMessagingWrongUserTitle": { + "message": "Απόρριψη λογαριασμού" + }, + "biometricsNotEnabledTitle": { + "message": "Η βιομετρική δεν είναι ενεργοποιημένη" + }, + "biometricsNotEnabledDesc": { + "message": "Τα βιομετρικά στοιχεία του προγράμματος περιήγησης απαιτούν την ενεργοποίηση της βιομετρικής επιφάνειας εργασίας στις ρυθμίσεις πρώτα." + }, + "biometricsNotSupportedTitle": { + "message": "Δεν υποστηρίζεται η βιομετρική" + }, + "biometricsNotSupportedDesc": { + "message": "Τα βιομετρικά στοιχεία του προγράμματος περιήγησης δεν υποστηρίζονται σε αυτήν τη συσκευή." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Δεν Έχει Χορηγηθεί Άδεια" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Χωρίς άδεια επικοινωνίας με την εφαρμογή Bitwarden Desktop δεν μπορούμε να παρέχουμε βιομετρικά στοιχεία στην επέκταση του προγράμματος περιήγησης. Παρακαλώ δοκιμάστε ξανά." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Σφάλμα αιτήματος άδειας" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Αυτή η ενέργεια δεν μπορεί να γίνει στην πλαϊνή μπάρα, δοκιμάστε ξανά την ενέργεια στο αναδυόμενο παράθυρο ή αναδυόμενο παράθυρο." + }, + "personalOwnershipSubmitError": { + "message": "Λόγω μιας Πολιτικής Επιχειρήσεων, δεν επιτρέπεται η αποθήκευση στοιχείων στο προσωπικό σας vault. Αλλάξτε την επιλογή Ιδιοκτησίας σε έναν οργανισμό και επιλέξτε από τις διαθέσιμες Συλλογές." + }, + "personalOwnershipPolicyInEffect": { + "message": "Μια πολιτική του οργανισμού, επηρεάζει τις επιλογές ιδιοκτησίας σας." + }, + "excludedDomains": { + "message": "Εξαιρούμενοι Τομείς" + }, + "excludedDomainsDesc": { + "message": "Το Bitwarden δεν θα ζητήσει να αποθηκεύσετε τα στοιχεία σύνδεσης για αυτούς τους τομείς. Πρέπει να ανανεώσετε τη σελίδα για να τεθούν σε ισχύ οι αλλαγές." + }, + "excludedDomainsInvalidDomain": { + "message": "Το $DOMAIN$ δεν είναι έγκυρος τομέας", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Αναζήτηση Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Προσθήκη Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Κείμενο" + }, + "sendTypeFile": { + "message": "Αρχείο" + }, + "allSends": { + "message": "Όλα τα Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Φτάσατε στον μέγιστο αριθμό πρόσβασης", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Έληξε" + }, + "pendingDeletion": { + "message": "Εκκρεμεί διαγραφή" + }, + "passwordProtected": { + "message": "Προστατευμένο με κωδικό" + }, + "copySendLink": { + "message": "Αντιγραφή συνδέσμου Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Αφαίρεση Κωδικού" + }, + "delete": { + "message": "Διαγραφή" + }, + "removedPassword": { + "message": "Καταργήθηκε ο Κωδικός Πρόσβασης" + }, + "deletedSend": { + "message": "Το Send Διαγράφηκε", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Σύνδεσμος Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Απενεργοποιημένο" + }, + "removePasswordConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να καταργήσετε τον κωδικό πρόσβασης;" + }, + "deleteSend": { + "message": "Διαγραφή Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το Send;", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Επεξεργασία Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Τι είδους Send είναι αυτό;", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Ένα φιλικό όνομα για την περιγραφή αυτού του Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Το αρχείο που θέλετε να στείλετε." + }, + "deletionDate": { + "message": "Ημερομηνία Διαγραφής" + }, + "deletionDateDesc": { + "message": "Το Send θα διαγραφεί οριστικά την καθορισμένη ημερομηνία και ώρα.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Ημερομηνία Λήξης" + }, + "expirationDateDesc": { + "message": "Εάν οριστεί, η πρόσβαση σε αυτό το Send θα λήξει την καθορισμένη ημερομηνία και ώρα.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 ημέρα" + }, + "days": { + "message": "$DAYS$ ημέρες", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Προσαρμοσμένο" + }, + "maximumAccessCount": { + "message": "Μέγιστος Αριθμός Πρόσβασης" + }, + "maximumAccessCountDesc": { + "message": "Εάν οριστεί, οι χρήστες δεν θα μπορούν πλέον να έχουν πρόσβαση σε αυτό το send μόλις επιτευχθεί ο μέγιστος αριθμός πρόσβασης.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Προαιρετικά απαιτείται κωδικός πρόσβασης για τους χρήστες για να έχουν πρόσβαση σε αυτό το Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Ιδιωτικές σημειώσεις σχετικά με αυτό το Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Απενεργοποιήστε αυτό το Send έτσι ώστε κανείς να μην μπορεί να έχει πρόσβαση σε αυτό.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Αντιγραφή του συνδέσμου για αυτό το Send στο πρόχειρο κατά την αποθήκευση.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Το κείμενο που θέλετε να στείλετε." + }, + "sendHideText": { + "message": "Απόκρυψη του κειμένου αυτού του Send από προεπιλογή.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Τρέχων Αριθμός Πρόσβασης" + }, + "createSend": { + "message": "Δημιουργία Νέου Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Νέος Κωδικός Πρόσβασης" + }, + "sendDisabled": { + "message": "Το Send Απενεργοποιήθηκε", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Λόγω μιας επιχειρηματικής πολιτικής, είστε σε θέση να διαγράψετε μόνο ένα υπάρχον Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Το Send Δημιουργήθηκε", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Το Send Επεξεργάστηκε", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Για να επιλέξετε ένα αρχείο, ανοίξτε την επέκταση στην πλαϊνή μπάρα (αν είναι δυνατόν) ή βγείτε σε ένα νέο παράθυρο κάνοντας κλικ σε αυτή τη διαφήμιση." + }, + "sendFirefoxFileWarning": { + "message": "Για να επιλέξετε ένα αρχείο χρησιμοποιώντας τον Firefox, ανοίξτε την επέκταση στην πλαϊνή μπάρα ή βγείτε σε ένα νέο παράθυρο κάνοντας κλικ σε αυτή τη διαφήμιση." + }, + "sendSafariFileWarning": { + "message": "Για να επιλέξετε ένα αρχείο χρησιμοποιώντας το Safari, βγαίνετε σε ένα νέο παράθυρο κάνοντας κλικ σε αυτή τη διαφήμιση." + }, + "sendFileCalloutHeader": { + "message": "Πριν ξεκινήσετε" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Για να χρησιμοποιήσετε έναν επιλογέα ημερομηνίας στυλ ημερολογίου", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "κάντε κλικ εδώ", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "για να βγεις από το παράθυρο.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Η ημερομηνία λήξης που δόθηκε δεν είναι έγκυρη." + }, + "deletionDateIsInvalid": { + "message": "Η ημερομηνία διαγραφής που δόθηκε δεν είναι έγκυρη." + }, + "expirationDateAndTimeRequired": { + "message": "Απαιτείται ημερομηνία και ώρα λήξης." + }, + "deletionDateAndTimeRequired": { + "message": "Απαιτείται ημερομηνία και ώρα διαγραφής." + }, + "dateParsingError": { + "message": "Παρουσιάστηκε σφάλμα κατά την αποθήκευση των ημερομηνιών διαγραφής και λήξης." + }, + "hideEmail": { + "message": "Απόκρυψη της διεύθυνσης email μου από τους παραλήπτες." + }, + "sendOptionsPolicyInEffect": { + "message": "Μία ή περισσότερες οργανωτικές πολιτικές επηρεάζουν τις επιλογές send σας." + }, + "passwordPrompt": { + "message": "Προτροπή νέου κωδικού πρόσβασης" + }, + "passwordConfirmation": { + "message": "Επιβεβαίωση κύριου κωδικού πρόσβασης" + }, + "passwordConfirmationDesc": { + "message": "Αυτή η ενέργεια προστατεύεται. Για να συνεχίσετε, πληκτρολογήστε ξανά τον κύριο κωδικό πρόσβασης για να επαληθεύσετε την ταυτότητά σας." + }, + "emailVerificationRequired": { + "message": "Απαιτείται Επαλήθευση Email" + }, + "emailVerificationRequiredDesc": { + "message": "Πρέπει να επαληθεύσετε το email σας για να χρησιμοποιήσετε αυτή τη δυνατότητα. Μπορείτε να επαληθεύσετε το email σας στο web vault." + }, + "updatedMasterPassword": { + "message": "Ενημερώθηκε ο κύριος κωδικός πρόσβασης" + }, + "updateMasterPassword": { + "message": "Ενημερώστε τον κύριο κωδικό πρόσβασης" + }, + "updateMasterPasswordWarning": { + "message": "Ο Κύριος Κωδικός Πρόσβασής σας άλλαξε πρόσφατα από διαχειριστή στον οργανισμό σας. Για να αποκτήσετε πρόσβαση στο vault, πρέπει να τον ενημερώσετε τώρα. Η διαδικασία θα σας αποσυνδέσει από την τρέχουσα συνεδρία σας, απαιτώντας από εσάς να συνδεθείτε ξανά. Οι ενεργές συνεδρίες σε άλλες συσκευές ενδέχεται να συνεχίσουν να είναι ενεργές για μία ώρα." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Αυτόματη Εγγραφή" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Αυτός ο οργανισμός έχει μια επιχειρηματική πολιτική που θα σας εγγράψει αυτόματα στην επαναφορά κωδικού. Η εγγραφή θα επιτρέψει στους διαχειριστές του οργανισμού να αλλάξουν τον κύριο κωδικό πρόσβασης σας." + }, + "selectFolder": { + "message": "Επιλέξτε φάκελο..." + }, + "ssoCompleteRegistration": { + "message": "Για να ολοκληρώσετε τη σύνδεση με SSO, ορίστε έναν κύριο κωδικό πρόσβασης για πρόσβαση και προστασία του vault σας." + }, + "hours": { + "message": "Ώρες" + }, + "minutes": { + "message": "Λεπτά" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο vault σας. Το μέγιστο επιτρεπόμενο Χρονικό όριο Vault είναι $HOURS$ ώρα(ες) και $MINUTES$ λεπτό(ά)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Το χρονικό όριο του vault σας υπερβαίνει τους περιορισμούς που έχει ορίσει ο οργανισμός σας." + }, + "vaultExportDisabled": { + "message": "Εξαγωγή vault Απενεργοποιημένη" + }, + "personalVaultExportPolicyInEffect": { + "message": "Μία ή περισσότερες οργανωτικές πολιτικές σας αποτρέπει από την εξαγωγή του προσωπικού vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Δεν είναι δυνατή η αναγνώριση ενός έγκυρου στοιχείου φόρμας. Δοκιμάστε να επιθεωρήσετε τον κώδικα HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Δε βρέθηκε μοναδικό αναγνωριστικό." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ χρησιμοποιεί SSO με έναν αυτοεξυπηρετητή κλειδιών. Ένας κύριος κωδικός πρόσβασης δεν απαιτείται πλέον για να συνδεθείτε για τα μέλη αυτού του οργανισμού.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Αποχώρηση από τον οργανισμό" + }, + "removeMasterPassword": { + "message": "Αφαίρεση Κύριου Κωδικού Πρόσβασης" + }, + "removedMasterPassword": { + "message": "Ο κύριος κωδικός αφαιρέθηκε." + }, + "leaveOrganizationConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να φύγετε από αυτόν τον οργανισμό;" + }, + "leftOrganization": { + "message": "Έχετε φύγει από τον οργανισμό." + }, + "toggleCharacterCount": { + "message": "Εναλλαγή αριθμού χαρακτήρων" + }, + "sessionTimeout": { + "message": "Έχει λήξει το χρονικό όριο. Παρακαλώ επιστρέψτε και προσπαθήστε να συνδεθείτε ξανά." + }, + "exportingPersonalVaultTitle": { + "message": "Εξαγωγή Προσωπικού Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Θα εξαχθούν μόνο τα προσωπικά αντικείμενα Vault που σχετίζονται με το $EMAIL$ . Τα αντικείμενα Vault οργανισμού δεν θα συμπεριληφθούν.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Σφάλμα" + }, + "regenerateUsername": { + "message": "Επαναδημιουργία Ονόματος Χρήστη" + }, + "generateUsername": { + "message": "Δημιουργία Όνομα Χρήστη" + }, + "usernameType": { + "message": "Τύπος Ονόματος Χρήστη" + }, + "plusAddressedEmail": { + "message": "Συν Διεύθυνση Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Χρησιμοποιήστε τις δυνατότητες δευτερεύουσας διεύθυνσης του παρόχου email σας." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Χρησιμοποιήστε τα διαμορφωμένα εισερχόμενα catch-all του domain σας." + }, + "random": { + "message": "Τυχαίο" + }, + "randomWord": { + "message": "Τυχαία Λέξη" + }, + "websiteName": { + "message": "Όνομα Ιστοσελίδας" + }, + "whatWouldYouLikeToGenerate": { + "message": "Τι θα θέλατε να δημιουργήσετε?" + }, + "passwordType": { + "message": "Τύπος Κωδικού" + }, + "service": { + "message": "Υπηρεσία" + } +} diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json new file mode 100644 index 0000000000..f65da3812c --- /dev/null +++ b/apps/browser/src/_locales/en/messages.json @@ -0,0 +1,1968 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "login": { + "message": "Log In" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "Cancel" + }, + "close": { + "message": "Close" + }, + "submit": { + "message": "Submit" + }, + "emailAddress": { + "message": "Email Address" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "vault": { + "message": "Vault" + }, + "myVault": { + "message": "My Vault" + }, + "allVaults": { + "message": "All Vaults" + }, + "tools": { + "message": "Tools" + }, + "settings": { + "message": "Settings" + }, + "currentTab": { + "message": "Current Tab" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number" + }, + "copySecurityCode": { + "message": "Copy Security Code" + }, + "autoFill": { + "message": "Auto-fill" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "Add a Login" + }, + "addItem": { + "message": "Add Item" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "Continue" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "logOut": { + "message": "Log Out" + }, + "about": { + "message": "About" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Save" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Add Folder" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Edit Folder" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "folders": { + "message": "Folders" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "Help & Feedback" + }, + "sync": { + "message": "Sync" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "Select" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Length" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "View" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favorite" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit Item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Delete Item" + }, + "viewItem": { + "message": "View Item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "Manage" + }, + "other": { + "message": "Other" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Browser Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "errorOccurred": { + "message": "An error has occurred" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "Name is required." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Save" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Update" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + }, + "forwardedEmail": { + "message": "Forwarded Email Alias" + }, + "forwardedEmailDesc": { + "message": "Generate an email alias with an external forwarding service." + }, + "hostname": { + "message": "Hostname", + "description": "Part of a URL." + }, + "apiAccessToken": { + "message": "API Access Token" + }, + "apiKey": { + "message": "API Key" + }, + "ssoKeyConnectorError": { + "message": "Key Connector error: make sure Key Connector is available and working correctly." + } +} diff --git a/apps/browser/src/_locales/en_GB/messages.json b/apps/browser/src/_locales/en_GB/messages.json new file mode 100644 index 0000000000..b573e401c6 --- /dev/null +++ b/apps/browser/src/_locales/en_GB/messages.json @@ -0,0 +1,1817 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create account" + }, + "login": { + "message": "Log in" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise single sign-on" + }, + "cancel": { + "message": "Cancel" + }, + "close": { + "message": "Close" + }, + "submit": { + "message": "Submit" + }, + "emailAddress": { + "message": "Email address" + }, + "masterPass": { + "message": "Master password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type master password" + }, + "masterPassHint": { + "message": "Master password hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "My vault" + }, + "tools": { + "message": "Tools" + }, + "settings": { + "message": "Settings" + }, + "currentTab": { + "message": "Current tab" + }, + "copyPassword": { + "message": "Copy password" + }, + "copyNote": { + "message": "Copy note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "Copy username" + }, + "copyNumber": { + "message": "Copy number" + }, + "copySecurityCode": { + "message": "Copy security code" + }, + "autoFill": { + "message": "Auto-fill" + }, + "generatePasswordCopied": { + "message": "Generate password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "vaultLocked": { + "message": "Vault is locked." + }, + "vaultLoggedOut": { + "message": "Vault is logged out." + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "Add a login" + }, + "addItem": { + "message": "Add item" + }, + "passwordHint": { + "message": "Password hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "Continue" + }, + "verificationCode": { + "message": "Verification code" + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Change master password" + }, + "fingerprintPhrase": { + "message": "Fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step login" + }, + "logOut": { + "message": "Log out" + }, + "about": { + "message": "About" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Save" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Add folder" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Edit folder" + }, + "deleteFolder": { + "message": "Delete folder" + }, + "folders": { + "message": "Folders" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "Help & feedback" + }, + "sync": { + "message": "Sync" + }, + "syncVaultNow": { + "message": "Sync vault now" + }, + "lastSync": { + "message": "Last sync:" + }, + "passGen": { + "message": "Password generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden web vault" + }, + "importItems": { + "message": "Import items" + }, + "select": { + "message": "Select" + }, + "generatePassword": { + "message": "Generate password" + }, + "regeneratePassword": { + "message": "Regenerate password" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of words" + }, + "wordSeparator": { + "message": "Word separator" + }, + "capitalize": { + "message": "Capitalise", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include number" + }, + "minNumbers": { + "message": "Minimum numbers" + }, + "minSpecial": { + "message": "Minimum special" + }, + "avoidAmbChar": { + "message": "Avoid ambiguous characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "View" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item information" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favourite" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Delete item" + }, + "viewItem": { + "message": "View item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Toggle visibility" + }, + "manage": { + "message": "Manage" + }, + "other": { + "message": "Other" + }, + "rateExtension": { + "message": "Rate the extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyMasterPassword": { + "message": "Verify master password" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your master password to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault timeout" + }, + "lockNow": { + "message": "Lock now" + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onLocked": { + "message": "On system lock" + }, + "onRestart": { + "message": "On browser restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "errorOccurred": { + "message": "An error has occurred" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "Name is required." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change master password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting started tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the bin?" + }, + "deletedItem": { + "message": "Sent item to bin" + }, + "overwritePassword": { + "message": "Overwrite password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable add login notification" + }, + "addLoginNotificationDesc": { + "message": "The \"add login notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't show cards on tab page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'current tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't show identities on tab page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'current tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Yes, save now" + }, + "notificationNeverSave": { + "message": "Never for this website" + }, + "disableChangedPasswordNotification": { + "message": "Disable changed password notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"changed password notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Yes, update now" + }, + "disableContextMenuItem": { + "message": "Disable context menu options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI match detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's colour theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export vault" + }, + "fileFormat": { + "message": "File format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over insecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organisations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organisation. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organisation" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organisation that you wish to move this item to. Moving to an organisation transfers ownership of the item to that organisation. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy verification code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add new attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium membership" + }, + "premiumManage": { + "message": "Manage membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable automatic TOTP copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled. However, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step login options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery code" + }, + "authenticatorAppTitle": { + "message": "Authenticator app" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP security key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organisation using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API server URL" + }, + "webVaultUrl": { + "message": "Web vault server URL" + }, + "identityUrl": { + "message": "Identity server URL" + }, + "notificationsUrl": { + "message": "Notifications server URL" + }, + "iconsUrl": { + "message": "Icons server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website." + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard." + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeMessage": { + "message": "Unfortunately this window is not available in private mode for this browser." + }, + "customFields": { + "message": "Custom fields" + }, + "copyValue": { + "message": "Copy value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New custom field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this pop-up window. Do you want to open this pop-up in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable website icons" + }, + "disableFaviconDesc": { + "message": "Website icons provide a recognisable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration month" + }, + "expirationYear": { + "message": "Expiration year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security code" + }, + "ex": { + "message": "e.g." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First name" + }, + "middleName": { + "message": "Middle name" + }, + "lastName": { + "message": "Last name" + }, + "identityName": { + "message": "Identity name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "National Insurance number" + }, + "passportNumber": { + "message": "Passport number" + }, + "licenseNumber": { + "message": "Licence number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / town" + }, + "stateProvince": { + "message": "County" + }, + "zipPostalCode": { + "message": "Postcode" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password history" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favourites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle options" + }, + "toggleCurrentUris": { + "message": "Toggle current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organisations. Organisations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak master password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "verifyPin": { + "message": "Verify PIN" + }, + "yourVaultIsLockedPinCode": { + "message": "Your vault is locked. Verify your PIN code to continue." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organisation policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault timeout action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Bin", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search bin" + }, + "permanentlyDeleteItem": { + "message": "Permanently delete item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently deleted item" + }, + "restoreItem": { + "message": "Restore item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout action confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled item and saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled item" + }, + "setMasterPassword": { + "message": "Set master password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organisation policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of service and privacy policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of service" + }, + "privacyPolicy": { + "message": "Privacy policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "OK" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before this function can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was cancelled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account mismatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organisation and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organisation policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organisation policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + } +} diff --git a/apps/browser/src/_locales/en_IN/messages.json b/apps/browser/src/_locales/en_IN/messages.json new file mode 100644 index 0000000000..c0ec0fcf4c --- /dev/null +++ b/apps/browser/src/_locales/en_IN/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create account" + }, + "login": { + "message": "Log in" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise single sign-on" + }, + "cancel": { + "message": "Cancel" + }, + "close": { + "message": "Close" + }, + "submit": { + "message": "Submit" + }, + "emailAddress": { + "message": "Email address" + }, + "masterPass": { + "message": "Master password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type master password" + }, + "masterPassHint": { + "message": "Master password hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "My vault" + }, + "tools": { + "message": "Tools" + }, + "settings": { + "message": "Settings" + }, + "currentTab": { + "message": "Current tab" + }, + "copyPassword": { + "message": "Copy password" + }, + "copyNote": { + "message": "Copy note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "Copy username" + }, + "copyNumber": { + "message": "Copy number" + }, + "copySecurityCode": { + "message": "Copy security code" + }, + "autoFill": { + "message": "Auto-fill" + }, + "generatePasswordCopied": { + "message": "Generate password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "Add a login" + }, + "addItem": { + "message": "Add item" + }, + "passwordHint": { + "message": "Password hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "Continue" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Change master password" + }, + "fingerprintPhrase": { + "message": "Fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step login" + }, + "logOut": { + "message": "Log out" + }, + "about": { + "message": "About" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Save" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Add folder" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Edit folder" + }, + "deleteFolder": { + "message": "Delete folder" + }, + "folders": { + "message": "Folders" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "Help & feedback" + }, + "sync": { + "message": "Sync" + }, + "syncVaultNow": { + "message": "Sync vault now" + }, + "lastSync": { + "message": "Last sync:" + }, + "passGen": { + "message": "Password generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden web vault" + }, + "importItems": { + "message": "Import items" + }, + "select": { + "message": "Select" + }, + "generatePassword": { + "message": "Generate password" + }, + "regeneratePassword": { + "message": "Regenerate password" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Length" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of words" + }, + "wordSeparator": { + "message": "Word separator" + }, + "capitalize": { + "message": "Capitalise", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include number" + }, + "minNumbers": { + "message": "Minimum numbers" + }, + "minSpecial": { + "message": "Minimum special" + }, + "avoidAmbChar": { + "message": "Avoid ambiguous characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "View" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item information" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favourite" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Delete item" + }, + "viewItem": { + "message": "View item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Toggle visibility" + }, + "manage": { + "message": "Manage" + }, + "other": { + "message": "Other" + }, + "rateExtension": { + "message": "Rate the extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your master password to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault timeout" + }, + "lockNow": { + "message": "Lock now" + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onLocked": { + "message": "On system lock" + }, + "onRestart": { + "message": "On browser restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "errorOccurred": { + "message": "An error has occurred" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "Name is required." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change master password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting started tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the bin?" + }, + "deletedItem": { + "message": "Sent item to bin" + }, + "overwritePassword": { + "message": "Overwrite password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable add login notification" + }, + "addLoginNotificationDesc": { + "message": "The \"add login notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't show cards on tab page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'current tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't show identities on tab page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'current tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Save" + }, + "disableChangedPasswordNotification": { + "message": "Disable changed password notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"changed password notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Update" + }, + "disableContextMenuItem": { + "message": "Disable context menu options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI match detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's colour theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export vault" + }, + "fileFormat": { + "message": "File format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over insecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organisations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organisation. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organisation" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organisation that you wish to move this item to. Moving to an organisation transfers ownership of the item to that organisation. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy verification code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add new attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium membership" + }, + "premiumManage": { + "message": "Manage membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable automatic TOTP copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled. However, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step login options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery code" + }, + "authenticatorAppTitle": { + "message": "Authenticator app" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP security key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organisation using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API server URL" + }, + "webVaultUrl": { + "message": "Web vault server URL" + }, + "identityUrl": { + "message": "Identity server URL" + }, + "notificationsUrl": { + "message": "Notifications server URL" + }, + "iconsUrl": { + "message": "Icons server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website." + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard." + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom fields" + }, + "copyValue": { + "message": "Copy value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New custom field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this pop-up window. Do you want to open this pop-up in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable website icons" + }, + "disableFaviconDesc": { + "message": "Website icons provide a recognisable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration month" + }, + "expirationYear": { + "message": "Expiration year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security code" + }, + "ex": { + "message": "e.g." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First name" + }, + "middleName": { + "message": "Middle name" + }, + "lastName": { + "message": "Last name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "National Insurance number" + }, + "passportNumber": { + "message": "Passport number" + }, + "licenseNumber": { + "message": "Licence number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / town" + }, + "stateProvince": { + "message": "County" + }, + "zipPostalCode": { + "message": "Postcode" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password history" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favourites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle options" + }, + "toggleCurrentUris": { + "message": "Toggle current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organisations. Organisations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak master password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organisation policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault timeout action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Bin", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search bin" + }, + "permanentlyDeleteItem": { + "message": "Permanently delete item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently deleted item" + }, + "restoreItem": { + "message": "Restore item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout action confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled item and saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled item" + }, + "setMasterPassword": { + "message": "Set master password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organisation policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of service and privacy policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of service" + }, + "privacyPolicy": { + "message": "Privacy policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "OK" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before this function can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was cancelled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account mismatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organisation and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organisation policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organisation policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organisation. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrolment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organisation has an enterprise policy that will automatically enrol you in password reset. Enrolment will allow organisation administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organisation policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organisation." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organisation policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organisation.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organisation" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organisation?" + }, + "leftOrganization": { + "message": "You have left the organisation." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organisation vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/es/messages.json b/apps/browser/src/_locales/es/messages.json new file mode 100644 index 0000000000..c4d3c87054 --- /dev/null +++ b/apps/browser/src/_locales/es/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden es un gestor de contraseñas seguro y gratuito para todos tus dispositivos.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Identifícate o crea una nueva cuenta para acceder a tu caja fuerte." + }, + "createAccount": { + "message": "Crear cuenta" + }, + "login": { + "message": "Identificarse" + }, + "enterpriseSingleSignOn": { + "message": "Inicio de sesión único empresarial" + }, + "cancel": { + "message": "Cancelar" + }, + "close": { + "message": "Cerrar" + }, + "submit": { + "message": "Enviar" + }, + "emailAddress": { + "message": "Correo electrónico" + }, + "masterPass": { + "message": "Contraseña maestra" + }, + "masterPassDesc": { + "message": "La contraseña maestra es la clave que utilizas para acceder a tu caja fuerte. Es muy importante que no olvides tu contraseña maestra. No hay forma de recuperarla si la olvidas." + }, + "masterPassHintDesc": { + "message": "Una pista de tu contraseña maestra puede ayudarte a recordarla en caso de que la olvides." + }, + "reTypeMasterPass": { + "message": "Vuelve a escribir tu contraseña maestra" + }, + "masterPassHint": { + "message": "Pista de contraseña maestra (opcional)" + }, + "tab": { + "message": "Pestaña" + }, + "myVault": { + "message": "Mi caja fuerte" + }, + "tools": { + "message": "Herramientas" + }, + "settings": { + "message": "Ajustes" + }, + "currentTab": { + "message": "Pestaña actual" + }, + "copyPassword": { + "message": "Copiar contraseña" + }, + "copyNote": { + "message": "Copiar nota" + }, + "copyUri": { + "message": "Copiar URI" + }, + "copyUsername": { + "message": "Copiar usuario" + }, + "copyNumber": { + "message": "Copiar número" + }, + "copySecurityCode": { + "message": "Copiar código de seguridad" + }, + "autoFill": { + "message": "Autorellenar" + }, + "generatePasswordCopied": { + "message": "Generar contraseña (copiada)" + }, + "copyElementIdentifier": { + "message": "Copiar Nombre del campo personalizado" + }, + "noMatchingLogins": { + "message": "Sin entradas coincidentes." + }, + "unlockVaultMenu": { + "message": "Desbloquea tu bóveda" + }, + "loginToVaultMenu": { + "message": "Inicia sesión en tu bóveda" + }, + "autoFillInfo": { + "message": "No hay entradas disponibles para autorellenar en la pestaña actual del navegador." + }, + "addLogin": { + "message": "Añadir entrada" + }, + "addItem": { + "message": "Añadir elemento" + }, + "passwordHint": { + "message": "Pista de contraseña" + }, + "enterEmailToGetHint": { + "message": "Introduce el correo electrónico de tu cuenta para recibir la pista de tu contraseña maestra." + }, + "getMasterPasswordHint": { + "message": "Obtener pista de la contraseña maestra" + }, + "continue": { + "message": "Continuar" + }, + "sendVerificationCode": { + "message": "Envía un código de verificación a tu correo electrónico" + }, + "sendCode": { + "message": "Enviar código" + }, + "codeSent": { + "message": "Código enviado" + }, + "verificationCode": { + "message": "Código de verificación" + }, + "confirmIdentity": { + "message": "Confirme su identidad para continuar." + }, + "account": { + "message": "Cuenta" + }, + "changeMasterPassword": { + "message": "Cambiar contraseña maestra" + }, + "fingerprintPhrase": { + "message": "Frase de huella digital", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frase de la huella digital de su cuenta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Autenticación en dos pasos" + }, + "logOut": { + "message": "Cerrar sesión" + }, + "about": { + "message": "Acerca de" + }, + "version": { + "message": "Versión" + }, + "save": { + "message": "Guardar" + }, + "move": { + "message": "Mover" + }, + "addFolder": { + "message": "Añadir carpeta" + }, + "name": { + "message": "Nombre" + }, + "editFolder": { + "message": "Editar carpeta" + }, + "deleteFolder": { + "message": "Eliminar carpeta" + }, + "folders": { + "message": "Carpetas" + }, + "noFolders": { + "message": "No hay carpetas que listar." + }, + "helpFeedback": { + "message": "Ayuda y comentarios" + }, + "sync": { + "message": "Sincronizar" + }, + "syncVaultNow": { + "message": "Sincronizar caja fuerte ahora" + }, + "lastSync": { + "message": "Última sincronización:" + }, + "passGen": { + "message": "Generador de contraseñas" + }, + "generator": { + "message": "Generador", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Genera automáticamente contraseñas fuertes y únicas para tus accesos." + }, + "bitWebVault": { + "message": "Caja fuerte web de Bitwarden" + }, + "importItems": { + "message": "Importar elementos" + }, + "select": { + "message": "Seleccionar" + }, + "generatePassword": { + "message": "Generar contraseña" + }, + "regeneratePassword": { + "message": "Regenerar contraseña" + }, + "options": { + "message": "Opciones" + }, + "length": { + "message": "Longitud" + }, + "uppercase": { + "message": "Mayúsculas (A-Z)" + }, + "lowercase": { + "message": "Minúsculas (a-z)" + }, + "numbers": { + "message": "Números (0-9)" + }, + "specialCharacters": { + "message": "Carácteres especiales (!@#$%^&*)" + }, + "numWords": { + "message": "Número de palabras" + }, + "wordSeparator": { + "message": "Separador de palabras" + }, + "capitalize": { + "message": "Mayúsculas iniciales", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Incluir número" + }, + "minNumbers": { + "message": "Mínimo de números" + }, + "minSpecial": { + "message": "Mínimo de caracteres especiales" + }, + "avoidAmbChar": { + "message": "Evitar caracteres ambiguos" + }, + "searchVault": { + "message": "Buscar en caja fuerte" + }, + "edit": { + "message": "Editar" + }, + "view": { + "message": "Ver" + }, + "noItemsInList": { + "message": "No hay elementos que listar." + }, + "itemInformation": { + "message": "Información del elemento" + }, + "username": { + "message": "Usuario" + }, + "password": { + "message": "Contraseña" + }, + "passphrase": { + "message": "Frase de contraseña" + }, + "favorite": { + "message": "Favorito" + }, + "notes": { + "message": "Notas" + }, + "note": { + "message": "Nota" + }, + "editItem": { + "message": "Editar elemento" + }, + "folder": { + "message": "Carpeta" + }, + "deleteItem": { + "message": "Eliminar elemento" + }, + "viewItem": { + "message": "Ver elemento" + }, + "launch": { + "message": "Iniciar" + }, + "website": { + "message": "Web" + }, + "toggleVisibility": { + "message": "Alternar visibilidad" + }, + "manage": { + "message": "Gestionar" + }, + "other": { + "message": "Otros" + }, + "rateExtension": { + "message": "Valora la extensión" + }, + "rateExtensionDesc": { + "message": "¡Por favor, considera ayudarnos con una buena reseña!" + }, + "browserNotSupportClipboard": { + "message": "Tu navegador web no soporta copiar al portapapeles facilmente. Cópialo manualmente." + }, + "verifyIdentity": { + "message": "Verificar identidad" + }, + "yourVaultIsLocked": { + "message": "Su caja fuerte está bloqueada. Verifique su contraseña maestra para continuar." + }, + "unlock": { + "message": "Desbloquear" + }, + "loggedInAsOn": { + "message": "Conectado como $EMAIL$ en $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Contraseña maestra no válida" + }, + "vaultTimeout": { + "message": "Tiempo de espera de la caja fuerte" + }, + "lockNow": { + "message": "Bloquear" + }, + "immediately": { + "message": "Inmediatamente" + }, + "tenSeconds": { + "message": "10 segundos" + }, + "twentySeconds": { + "message": "20 segundos" + }, + "thirtySeconds": { + "message": "30 segundos" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minutos" + }, + "fiveMinutes": { + "message": "5 minutos" + }, + "fifteenMinutes": { + "message": "15 minutos" + }, + "thirtyMinutes": { + "message": "30 minutos" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 horas" + }, + "onLocked": { + "message": "Al bloquear el sistema" + }, + "onRestart": { + "message": "Al reiniciar el navegador" + }, + "never": { + "message": "Nunca" + }, + "security": { + "message": "Seguridad" + }, + "errorOccurred": { + "message": "Ha ocurrido un error" + }, + "emailRequired": { + "message": "Correo electrónico requerido." + }, + "invalidEmail": { + "message": "Correo electrónico no válido." + }, + "masterPassRequired": { + "message": "Contraseña maestra requerida." + }, + "masterPassLength": { + "message": "La contraseña maestra debe tener al menos 8 caracteres." + }, + "masterPassDoesntMatch": { + "message": "La confirmación de contraseña maestra no coincide." + }, + "newAccountCreated": { + "message": "¡Tu nueva cuenta ha sido creada! Ahora puedes acceder." + }, + "masterPassSent": { + "message": "Te hemos enviado un correo electrónico con la pista de tu contraseña maestra." + }, + "verificationCodeRequired": { + "message": "Código de verificación requerido." + }, + "invalidVerificationCode": { + "message": "Código de verificación no válido" + }, + "valueCopied": { + "message": "Valor de $VALUE$ copiado", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "No se ha podido autorellenar la entrada seleccionada en esta página. Copia/pega tu usuario y/o contraseña." + }, + "loggedOut": { + "message": "Sesión terminada" + }, + "loginExpired": { + "message": "Tu sesión ha expirado." + }, + "logOutConfirmation": { + "message": "¿Estás seguro de querer cerrar la sesión?" + }, + "yes": { + "message": "Sí" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "Ha ocurrido un error inesperado." + }, + "nameRequired": { + "message": "Nombre requerido." + }, + "addedFolder": { + "message": "Carpeta añadida" + }, + "changeMasterPass": { + "message": "Cambiar contraseña maestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Puedes cambiar tu contraseña maestra en la caja fuerte web de bitwarden.com. ¿Quieres visitar ahora el sitio web?" + }, + "twoStepLoginConfirmation": { + "message": "La autenticación en dos pasos hace que tu cuenta sea mucho más segura, requiriendo que introduzcas un código de seguridad de una aplicación de autenticación cada vez que accedes. La autenticación en dos pasos puede ser habilitada en la caja fuerte web de bitwarden.com. ¿Quieres visitar ahora el sitio web?" + }, + "editedFolder": { + "message": "Carpeta editada" + }, + "deleteFolderConfirmation": { + "message": "¿Estás seguro de querer eliminar esta carpeta?" + }, + "deletedFolder": { + "message": "Carpeta eliminada" + }, + "gettingStartedTutorial": { + "message": "Tutorial de primeros pasos" + }, + "gettingStartedTutorialVideo": { + "message": "Revisa nuestro tutorial de primeros pasos para aprender a sacar lo máximo de la extensión del navegador." + }, + "syncingComplete": { + "message": "Sincronización completada" + }, + "syncingFailed": { + "message": "Sincronización fallida" + }, + "passwordCopied": { + "message": "Contraseña copiada" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nueva URI" + }, + "addedItem": { + "message": "Elemento añadido" + }, + "editedItem": { + "message": "Elemento editado" + }, + "deleteItemConfirmation": { + "message": "¿Seguro que quieres enviarlo a la papelera?" + }, + "deletedItem": { + "message": "Elemento enviado a la papelera" + }, + "overwritePassword": { + "message": "Sobreescribir contraseña" + }, + "overwritePasswordConfirmation": { + "message": "¿Estás seguro de que quieres sobreescribir la contraseña actual?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Buscar carpeta" + }, + "searchCollection": { + "message": "Buscar colección" + }, + "searchType": { + "message": "Buscar tipo" + }, + "noneFolder": { + "message": "Sin carpeta", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Deshabilitar notificación para añadir entradas" + }, + "addLoginNotificationDesc": { + "message": "La opción \"Notificación para añadir entradas\" pregunta automáticamente si quieres guardar nuevas entradas en tu caja fuerte cuando te identificas en un sitio web por primera vez." + }, + "dontShowCardsCurrentTab": { + "message": "No mostrar tarjetas en la pestaña" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Elementos de la tarjeta de su caja fuerte están listados en la página 'Ficha Actual' para el acceso fácil del autorellenado." + }, + "dontShowIdentitiesCurrentTab": { + "message": "No mostrar las identidades en la página de ficha" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Elementos de identidad de su caja fuerte están listados en la página 'Ficha Actual' para el acceso fácil del autorellenado." + }, + "clearClipboard": { + "message": "Vaciar portapapeles", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Borrar automáticamente los valores copiados de su portapapeles.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "¿Debería Bitwarden recordar esta contraseña por ti?" + }, + "notificationAddSave": { + "message": "Sí, guardar ahora" + }, + "disableChangedPasswordNotification": { + "message": "Deshabilitar la notificación de cambio de contraseña" + }, + "disableChangedPasswordNotificationDesc": { + "message": "La notificación \"Contraseña cambiada\" automáticamente te pedirá que actualices la contraseña de inicio de sesión en tu caja fuerte cuando detecte que se ha cambiado en la web." + }, + "notificationChangeDesc": { + "message": "¿Desea actualizar esta contraseña en Bitwarden?" + }, + "notificationChangeSave": { + "message": "Actualizado" + }, + "disableContextMenuItem": { + "message": "Deshabilitar opciones del menú contextual" + }, + "disableContextMenuItemDesc": { + "message": "Las opciones del menú contextual permiten un acceso rápido al generador de contraseñas y a las entradas para el sitio abierto en tu pestaña actual." + }, + "defaultUriMatchDetection": { + "message": "Detección por defecto de coincidencia de URI", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Elija el método de detección por defecto de coincidencia de URI que se utilizará para acciones de inicio de sesión como autorrellenado." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Cambiar el tema de la aplicación." + }, + "dark": { + "message": "Oscuro", + "description": "Dark color" + }, + "light": { + "message": "Claro", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Exportar caja fuerte" + }, + "fileFormat": { + "message": "Formato de archivo" + }, + "warning": { + "message": "ADVERTENCIA", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirma la exportación de la caja fuerte" + }, + "exportWarningDesc": { + "message": "Esta exportación contiene los datos de tu caja fuerte en un formato no cifrado. No deberías almacenar o enviar el archivo exportado por canales no seguros (como el correo electrónico). Elimínalo inmediatamente cuando termines de utilizarlo." + }, + "encExportKeyWarningDesc": { + "message": "Esta exportación encripta tus datos utilizando la clave de encriptación de tu cuenta. Si alguna vez cambias la clave de encriptación de tu cuenta, deberás exportar de nuevo, ya que no podrás descifrar este archivo exportado." + }, + "encExportAccountWarningDesc": { + "message": "Las claves de encriptación de las cuentas son únicas para cada cuenta de usuario de Bitwarden, por lo que no se puede importar un archivo exportado y encriptado a una cuenta diferente." + }, + "exportMasterPassword": { + "message": "Introduce tu contraseña maestra para exportar la información de tu caja fuerte." + }, + "shared": { + "message": "Compartido" + }, + "learnOrg": { + "message": "Aprende sobre Organizaciones" + }, + "learnOrgConfirmation": { + "message": "Bitwarden te permite compartir objetos de tu caja fuerte con otros usando una organización. ¿Quieres visitar el sitio web de bitwarden.com para saber más?" + }, + "moveToOrganization": { + "message": "Mover a la Organización" + }, + "share": { + "message": "Compartir" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ se desplazó a $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Elige una organización a la que deseas mover este objeto. Moviendo a una organización transfiere la propiedad del objeto a esa organización. Ya no serás el dueño directo de este objeto una vez que haya sido movido." + }, + "learnMore": { + "message": "Más información" + }, + "authenticatorKeyTotp": { + "message": "Clave de autenticación (TOTP)" + }, + "verificationCodeTotp": { + "message": "Código de verificación (TOTP)" + }, + "copyVerificationCode": { + "message": "Copiar código de verificación" + }, + "attachments": { + "message": "Adjuntos" + }, + "deleteAttachment": { + "message": "Eliminar adjunto" + }, + "deleteAttachmentConfirmation": { + "message": "¿Estás seguro de querer eliminar este adjunto?" + }, + "deletedAttachment": { + "message": "Adjunto eliminado" + }, + "newAttachment": { + "message": "Añadir nuevo adjunto" + }, + "noAttachments": { + "message": "Sin adjuntos." + }, + "attachmentSaved": { + "message": "El adjunto se ha guardado." + }, + "file": { + "message": "Archivo" + }, + "selectFile": { + "message": "Selecciona un archivo." + }, + "maxFileSize": { + "message": "El tamaño máximo de archivo es de 500MB." + }, + "featureUnavailable": { + "message": "Característica no disponible" + }, + "updateKey": { + "message": "No puedes usar esta característica hasta que actualices tu clave de cifrado." + }, + "premiumMembership": { + "message": "Membresía Premium" + }, + "premiumManage": { + "message": "Gestionar membresía" + }, + "premiumManageAlert": { + "message": "Puedes gestionar tu membresía en la caja fuerte web de bitwarden.com. ¿Quieres visitar el sitio web ahora?" + }, + "premiumRefresh": { + "message": "Actualizar membresía" + }, + "premiumNotCurrentMember": { + "message": "Actualmente no eres un miembro premium." + }, + "premiumSignUpAndGet": { + "message": "Registrate como miembro Premium y obtén:" + }, + "ppremiumSignUpStorage": { + "message": "1GB de espacio cifrado en disco para adjuntos." + }, + "ppremiumSignUpTwoStep": { + "message": "Métodos de autenticación en dos pasos adicionales como YubiKey, FIDO U2F y Duo." + }, + "ppremiumSignUpReports": { + "message": "Higiene de contraseña, salud de la cuenta e informes de violaciones de datos para mantener su caja fuerte segura." + }, + "ppremiumSignUpTotp": { + "message": "Generación de códigos TOTP (2FA) para registros de tu caja fuerte." + }, + "ppremiumSignUpSupport": { + "message": "Soporte prioritario." + }, + "ppremiumSignUpFuture": { + "message": "Acceso a nuevas características premium en el futuro. ¡Hay más en camino!" + }, + "premiumPurchase": { + "message": "Comprar Premium" + }, + "premiumPurchaseAlert": { + "message": "Puedes comprar la membresía Premium en la caja fuerte web de bitwarden.com. ¿Quieres visitar el sitio web ahora?" + }, + "premiumCurrentMember": { + "message": "¡Eres un miembro Premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Gracias por apoyar el desarrollo de Bitwarden." + }, + "premiumPrice": { + "message": "¡Todo por solo %price% /año!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Actualización completada" + }, + "disableAutoTotpCopy": { + "message": "Deshabilitar copiado automático de códigos TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Si tu entrada tiene una clave de autenticación adjunta, el código de verificación TOTP es copiado automáticamente al portapapeles cuando autorellenas una entrada." + }, + "disableAutoBiometricsPrompt": { + "message": "No solicitar biométricos al iniciar" + }, + "premiumRequired": { + "message": "Premium requerido" + }, + "premiumRequiredDesc": { + "message": "Una membresía Premium es requerida para utilizar esta característica." + }, + "enterVerificationCodeApp": { + "message": "Introduce el código de verificación de 6 dígitos de tu aplicación autenticadora." + }, + "enterVerificationCodeEmail": { + "message": "Introduce el código de verificación de 6 dígitos que te ha sido enviado por correo electrónico", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Correo electrónico de verificación enviado a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Recordarme" + }, + "sendVerificationCodeEmailAgain": { + "message": "Reenviar código de verificación por correo electrónico" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizar otro método de autenticación en dos pasos" + }, + "insertYubiKey": { + "message": "Inserta tu YubiKey en el puerto USB de tu equipo y posteriormente pulsa su botón." + }, + "insertU2f": { + "message": "Inserta tu llave de seguridad en el puerto USB de tu equipo. Si tiene un botón, púlsalo." + }, + "webAuthnNewTab": { + "message": "Para iniciar la verificación de WebAuthn 2FA. Haga clic en el botón de abajo para abrir una nueva pestaña y siga las instrucciones proporcionadas en la nueva pestaña." + }, + "webAuthnNewTabOpen": { + "message": "Abrir nueva pestaña" + }, + "webAuthnAuthenticate": { + "message": "Autenticar WebAuthn" + }, + "loginUnavailable": { + "message": "Entrada no disponible" + }, + "noTwoStepProviders": { + "message": "Esta cuenta tiene autenticación en dos pasos habilitado, pero ninguno de lo métodos configurados es soportado por este navegador web." + }, + "noTwoStepProviders2": { + "message": "Por favor, utiliza un navegador soportado (como Chrome) y/o añade métodos de autenticación adicionales que tengan mejor soporte en diferentes navegadores web (como una aplicación de autenticación)." + }, + "twoStepOptions": { + "message": "Opciones de la autenticación en dos pasos" + }, + "recoveryCodeDesc": { + "message": "¿Has perdido el acceso a todos tus métodos de autenticación en dos pasos? Utiliza tu código de recuperación para deshabilitar todos los métodos de autenticación en dos pasos de tu cuenta." + }, + "recoveryCodeTitle": { + "message": "Código de recuperación" + }, + "authenticatorAppTitle": { + "message": "Aplicación de autenticación" + }, + "authenticatorAppDesc": { + "message": "Utiliza una aplicación de autenticación (como Authy o Google Authenticator) para generar código de verificación basados en tiempo.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Llave de seguridad YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Usa un Yubikey para acceder a tu cuenta. Funciona con YubiKey 4, 4 Nano, 4C y dispositivos NEO." + }, + "duoDesc": { + "message": "Verificar con Duo Security usando la aplicación Duo Mobile, SMS, llamada telefónica o llave de seguridad U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verificar con Duo Security para tu organización usando la aplicación Duo Mobile, SMS, llamada telefónica o llave de seguridad U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Utilice cualquier clave de seguridad WebAuthn habilitada para acceder a su cuenta." + }, + "emailTitle": { + "message": "Correo electrónico" + }, + "emailDesc": { + "message": "Los códigos de verificación te serán enviados por correo electrónico." + }, + "selfHostedEnvironment": { + "message": "Entorno de alojamiento propio" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifica la URL base de tu instalación de Bitwarden de alojamiento propio." + }, + "customEnvironment": { + "message": "Entorno personalizado" + }, + "customEnvironmentFooter": { + "message": "Para usuarios avanzados. Puedes especificar la URL base de cada servicio de forma independiente." + }, + "baseUrl": { + "message": "URL del servidor" + }, + "apiUrl": { + "message": "URL del servidor de la API" + }, + "webVaultUrl": { + "message": "URL del servidor de la caja fuerte web" + }, + "identityUrl": { + "message": "URL del servidor de identidad" + }, + "notificationsUrl": { + "message": "URL del servidor de notificaciones" + }, + "iconsUrl": { + "message": "URL del servidor de iconos" + }, + "environmentSaved": { + "message": "Las URLs del entorno han sido guardadas." + }, + "enableAutoFillOnPageLoad": { + "message": "Habilitar autorrellenar al cargar la página" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Si se detecta un formulario, realizar automáticamente un autorellenado cuando la web cargue." + }, + "experimentalFeature": { + "message": "Esta es una característica experimental. Úsala bajo tu propio riesgo." + }, + "defaultAutoFillOnPageLoad": { + "message": "Configuración de autorrelleno por defecto para elementos de inicio de sesión" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Después de activar el autorelleno en Carga de página, puede activar o desactivar la función para entradas individuales. Esta es la configuración predeterminada para elementos de inicio de sesión que no están configurados por separado." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-relleno en carga de página (si está habilitado en opciones)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Usar configuración predeterminada" + }, + "autoFillOnPageLoadYes": { + "message": "Autocompletar al cargar la página" + }, + "autoFillOnPageLoadNo": { + "message": "No rellenar automáticamente al cargar la página" + }, + "commandOpenPopup": { + "message": "Abrir ventana emergente de la caja fuerte" + }, + "commandOpenSidebar": { + "message": "Abrir caja fuerte en la barra lateral" + }, + "commandAutofillDesc": { + "message": "Autorrellenar la última entrada utilizada para la página actual." + }, + "commandGeneratePasswordDesc": { + "message": "Generar y copiar una nueva contraseña aleatoria al portapapeles." + }, + "commandLockVaultDesc": { + "message": "Bloquear la caja fuerte" + }, + "privateModeWarning": { + "message": "El soporte en modo privado es experimental y algunas características son limitadas." + }, + "customFields": { + "message": "Campos personalizados" + }, + "copyValue": { + "message": "Copiar valor" + }, + "value": { + "message": "Valor" + }, + "newCustomField": { + "message": "Nuevo campo personalizado" + }, + "dragToSort": { + "message": "Arrastrar para ordenar" + }, + "cfTypeText": { + "message": "Texto" + }, + "cfTypeHidden": { + "message": "Oculto" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "cfTypeLinked": { + "message": "Vinculado", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Valor vinculado", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Pulsar fuera de la ventana emergente para comprobar tu correo de verificación, hará que esta se cierre. ¿Quieres abrir esta ventana emergente en una nueva ventana para evitar su cierre?" + }, + "popupU2fCloseMessage": { + "message": "Este navegador no puede procesar las peticiones U2F en esta ventana emergente. ¿Desea abrir esta ventana emergente en una nueva ventana para que pueda iniciar sesión usando U2F?" + }, + "disableFavicon": { + "message": "Deshabilitar iconos del sitio web" + }, + "disableFaviconDesc": { + "message": "Los iconos del sitio web añaden una imagen reconocible al lado de cada entrada de tu caja fuerte." + }, + "disableBadgeCounter": { + "message": "Desactivar contador de insignias" + }, + "disableBadgeCounterDesc": { + "message": "El contador de insinuaciones indica cuántos registros tienes para la página actual en tu bóveda." + }, + "cardholderName": { + "message": "Nombre en la tarjeta" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Marca" + }, + "expirationMonth": { + "message": "Mes de expiración" + }, + "expirationYear": { + "message": "Año de expiración" + }, + "expiration": { + "message": "Expiración" + }, + "january": { + "message": "Enero" + }, + "february": { + "message": "Febrero" + }, + "march": { + "message": "Marzo" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Mayo" + }, + "june": { + "message": "Junio" + }, + "july": { + "message": "Julio" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Septiembre" + }, + "october": { + "message": "Octubre" + }, + "november": { + "message": "Noviembre" + }, + "december": { + "message": "Diciembre" + }, + "securityCode": { + "message": "Código de seguridad" + }, + "ex": { + "message": "ej." + }, + "title": { + "message": "Título" + }, + "mr": { + "message": "Sr" + }, + "mrs": { + "message": "Sra" + }, + "ms": { + "message": "Srta" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Nombre" + }, + "middleName": { + "message": "2º nombre" + }, + "lastName": { + "message": "Apellido" + }, + "fullName": { + "message": "Nombre completo" + }, + "identityName": { + "message": "Nombre de la identidad" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Nº de la seguridad social" + }, + "passportNumber": { + "message": "Nº de pasaporte" + }, + "licenseNumber": { + "message": "Nº de licencia" + }, + "email": { + "message": "Correo electrónico" + }, + "phone": { + "message": "Teléfono" + }, + "address": { + "message": "Dirección" + }, + "address1": { + "message": "Dirección 1" + }, + "address2": { + "message": "Dirección 2" + }, + "address3": { + "message": "Dirección 3" + }, + "cityTown": { + "message": "Ciudad / Pueblo" + }, + "stateProvince": { + "message": "Estado / Provincia" + }, + "zipPostalCode": { + "message": "Código postal" + }, + "country": { + "message": "País" + }, + "type": { + "message": "Tipo" + }, + "typeLogin": { + "message": "Entrada" + }, + "typeLogins": { + "message": "Entradas" + }, + "typeSecureNote": { + "message": "Nota segura" + }, + "typeCard": { + "message": "Tarjeta" + }, + "typeIdentity": { + "message": "Identidad" + }, + "passwordHistory": { + "message": "Historial de contraseñas" + }, + "back": { + "message": "Atrás" + }, + "collections": { + "message": "Colecciones" + }, + "favorites": { + "message": "Favoritos" + }, + "popOutNewWindow": { + "message": "Abrir en una nueva ventana" + }, + "refresh": { + "message": "Actualizar" + }, + "cards": { + "message": "Tarjetas" + }, + "identities": { + "message": "Identidades" + }, + "logins": { + "message": "Entradas" + }, + "secureNotes": { + "message": "Notas seguras" + }, + "clear": { + "message": "Limpiar", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Comprobar si la contraseña está comprometida." + }, + "passwordExposed": { + "message": "Esta contraseña fue encontrada $VALUE$ vez/veces en filtraciones de datos. Deberías cambiarla.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Esta contraseña no fue encontrada en ninguna filtración de datos conocida. Deberías poder utilizarla de forma segura." + }, + "baseDomain": { + "message": "Dominio base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Servidor", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exacta" + }, + "startsWith": { + "message": "Empieza con" + }, + "regEx": { + "message": "Expresión regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Tipo de detección", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detección por defecto", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Alternar opciones" + }, + "toggleCurrentUris": { + "message": "Alternar URIs actuales", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI actual", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organización", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tipos" + }, + "allItems": { + "message": "Todos los elementos" + }, + "noPasswordsInList": { + "message": "No hay contraseñas que listar." + }, + "remove": { + "message": "Eliminar" + }, + "default": { + "message": "Por defecto" + }, + "dateUpdated": { + "message": "Actualizado", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Contraseña actualizada", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "¿Está seguro de que quieres usar la opción \"Nunca\"? Al ajustar las opciones de bloqueo a \"Nunca\", la clave de cifrado de su caja fuerte se guardará en tu dispositivo. Si usas esta opción, asegúrate de mantener tu dispositivo debidamente protegido." + }, + "noOrganizationsList": { + "message": "No perteneces a ninguna organización. Las organizaciones te permiten compartir elementos con otros usuarios de forma segura." + }, + "noCollectionsInList": { + "message": "No hay colecciones que listar." + }, + "ownership": { + "message": "Propiedad" + }, + "whoOwnsThisItem": { + "message": "¿Quién posee este elemento?" + }, + "strong": { + "message": "Fuerte", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Buena", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Débil", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Contraseña maestra débil" + }, + "weakMasterPasswordDesc": { + "message": "La contraseña maestra que ha elegido es débil. Debe usar una contraseña maestra fuerte (o una frase de contraseña) para proteger adecuadamente su cuenta de Bitwarden. ¿Está seguro de que desea utilizar esta contraseña maestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloquear con PIN" + }, + "setYourPinCode": { + "message": "Establece tu código PIN para desbloquear Bitwarden. Tus ajustes de PIN se reiniciarán si alguna vez cierras tu sesión completamente de la aplicación." + }, + "pinRequired": { + "message": "Código PIN requerido." + }, + "invalidPin": { + "message": "Código PIN inválido." + }, + "unlockWithBiometrics": { + "message": "Desbloquear con biométricos" + }, + "awaitDesktop": { + "message": "Esperando la confirmación por parte del escritorio" + }, + "awaitDesktopDesc": { + "message": "Por favor confirma el uso de biométricos en la aplicación de escritorio de Bitwarden para habilitar el uso de biométricos en el navegador." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloquear con contraseña maestra al reiniciar el navegador" + }, + "selectOneCollection": { + "message": "Debes seleccionar al menos una colección." + }, + "cloneItem": { + "message": "Clonar objeto" + }, + "clone": { + "message": "Clonar" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una o más políticas de la organización están afectando la configuración del generador" + }, + "vaultTimeoutAction": { + "message": "Acción de tiempo de espera de la caja fuerte" + }, + "lock": { + "message": "Bloquear", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papelera", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Buscar en la Papelera" + }, + "permanentlyDeleteItem": { + "message": "Eliminar elemento de forma permanente" + }, + "permanentlyDeleteItemConfirmation": { + "message": "¿Estás seguro de eliminar de forma permanente este elemento?" + }, + "permanentlyDeletedItem": { + "message": "Elemento eliminado de forma permanente" + }, + "restoreItem": { + "message": "Restaurar elemento" + }, + "restoreItemConfirmation": { + "message": "¿Estás seguro de que quieres restaurar este elemento?" + }, + "restoredItem": { + "message": "Elemento restaurado" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Cerrar sesión eliminará todo el acceso a tu caja fuerte y requerirá autenticación en línea después del tiempo de espera. ¿Estás seguro de que quieres usar esta configuración?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmación de la acción del tiempo de espera" + }, + "autoFillAndSave": { + "message": "Autorellenar y guardar" + }, + "autoFillSuccessAndSavedUri": { + "message": "Objeto autorellenado y URI guardada" + }, + "autoFillSuccess": { + "message": "Objeto autorellenado" + }, + "setMasterPassword": { + "message": "Establecer contraseña maestra" + }, + "masterPasswordPolicyInEffect": { + "message": "Una o más políticas de la organización requieren que su contraseña maestra cumpla con los siguientes requisitos:" + }, + "policyInEffectMinComplexity": { + "message": "Puntuación mínima de complejidad de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Longitud mínima de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contiene uno o más caracteres en mayúsculas" + }, + "policyInEffectLowercase": { + "message": "Contiene uno o más caracteres en minúsculas" + }, + "policyInEffectNumbers": { + "message": "Contiene uno o más números" + }, + "policyInEffectSpecial": { + "message": "Contiene uno o más de los siguientes caracteres especiales $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Su nueva contraseña maestra no cumple con los requisitos de la política." + }, + "acceptPolicies": { + "message": "Al seleccionar esta casilla, acepta lo siguiente:" + }, + "acceptPoliciesError": { + "message": "Todavía no has aceptado los términos del servicio y la política de privacidad." + }, + "termsOfService": { + "message": "Términos y condiciones del servicio" + }, + "privacyPolicy": { + "message": "Política de privacidad" + }, + "hintEqualsPassword": { + "message": "Tu contraseña no puede ser idéntica a la pista de contraseña." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Verificación de sincronización del escritorio" + }, + "desktopIntegrationVerificationText": { + "message": "Favor de verificar que la aplicación de escritorio muestre ésta huella:" + }, + "desktopIntegrationDisabledTitle": { + "message": "La integración con el navegador se encuentra deshabilitada" + }, + "desktopIntegrationDisabledDesc": { + "message": "La integración con el navegador se encuentra deshabilitada en la aplicación de escritorio de Bitwarden. Favor de habilitarla en los ajustes dentro de la aplicación de escritorio." + }, + "startDesktopTitle": { + "message": "Inicia la aplicación de escritorio de Bitwarden" + }, + "startDesktopDesc": { + "message": "La aplicación de escritorio de Bitwarden necesita iniciarse para poder utilizar ésta función." + }, + "errorEnableBiometricTitle": { + "message": "No fue posible habilitar biométricos" + }, + "errorEnableBiometricDesc": { + "message": "La acción fue cancelada por la aplicación de escritorio" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "La aplicación de escritorio invalidó el canal seguro de comunicación. Favor de intentar la operación nuevamente" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Se ha interrumpido la comunicación con el escritorio" + }, + "nativeMessagingWrongUserDesc": { + "message": "La aplicación de escritorio está conectada a una cuenta distinta. Favor de asegurar que ambas aplicaciones estén conectadas a la misma cuenta. " + }, + "nativeMessagingWrongUserTitle": { + "message": "Las cuentas son distintas" + }, + "biometricsNotEnabledTitle": { + "message": "Biometría deshabilitada" + }, + "biometricsNotEnabledDesc": { + "message": "La biometría del navegador requiere activar primero la biometría de escritorio en los ajustes." + }, + "biometricsNotSupportedTitle": { + "message": "No se admite la biometría" + }, + "biometricsNotSupportedDesc": { + "message": "La biometría del navegador no es compatible con este dispositivo." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permiso no proporcionado" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Sin el permiso para comunicarse con la aplicación de escritorio de Bitwarden, no podemos proporcionar datos biométricos en la extensión del navegador. Por favor, inténtalo de nuevo." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Error de solicitud de permiso" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Esta acción no se puede realizar en la barra lateral, por favor, vuelve a intentar la acción en la ventana emergente o popout." + }, + "personalOwnershipSubmitError": { + "message": "Debido a una política de organización, tiene restringido el guardar elementos a su bóveda personal. Cambie la configuración de propietario a organización y elija entre las colecciones disponibles." + }, + "personalOwnershipPolicyInEffect": { + "message": "Una política de organización está afectando a sus opciones de propiedad." + }, + "excludedDomains": { + "message": "Dominios excluidos" + }, + "excludedDomainsDesc": { + "message": "Bitwarden no pedirá que se guarden los datos de acceso para estos dominios. Debe actualizar la página para que los cambios surtan efecto." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ no es un dominio válido", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Buscar Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Añadir Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Texto" + }, + "sendTypeFile": { + "message": "Archivo" + }, + "allSends": { + "message": "Todos los Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Número máximo de accesos alcanzado", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Caducado" + }, + "pendingDeletion": { + "message": "Borrado pendiente" + }, + "passwordProtected": { + "message": "Protegido por contraseña" + }, + "copySendLink": { + "message": "Copiar enlace Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Eliminar contraseña" + }, + "delete": { + "message": "Eliminar" + }, + "removedPassword": { + "message": "Contraseña eliminada" + }, + "deletedSend": { + "message": "Send eliminado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Enlace Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Desactivado" + }, + "removePasswordConfirmation": { + "message": "¿Está seguro que desea eliminar la contraseña?" + }, + "deleteSend": { + "message": "Eliminar Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "¿Está seguro de que desea eliminar este Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Editar Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "¿Qué tipo de Send es este?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Un nombre amigable para describir este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "El archivo que desea enviar." + }, + "deletionDate": { + "message": "Fecha de eliminación" + }, + "deletionDateDesc": { + "message": "El Send se eliminará permanentemente en la fecha y hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Fecha de caducidad" + }, + "expirationDateDesc": { + "message": "Si se establece, el acceso a este Send caducará en la fecha y hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 día" + }, + "days": { + "message": "$DAYS$ días", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Personalizado" + }, + "maximumAccessCount": { + "message": "Número máximo de accesos" + }, + "maximumAccessCountDesc": { + "message": "Si se establece, los usuarios ya no podrán acceder a este Send una vez que se alcance el número máximo de accesos.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcionalmente se requiere una contraseña para que los usuarios accedan a este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notas privadas sobre este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Desactiva este Send para que nadie pueda acceder a él.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copiar el enlace del Send en el portapapeles al guardar.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "El texto que quieres enviar." + }, + "sendHideText": { + "message": "Ocultar el texto de este Envío por defecto.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Número de acceso actual" + }, + "createSend": { + "message": "Crear Envío nuevo", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nueva contraseña" + }, + "sendDisabled": { + "message": "Envío desactivado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Debido a una política empresarial, sólo puede eliminar el existente Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Envío creado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Envío editado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Para elegir un archivo, abra la extensión en la barra lateral (si es posible) o salga a una nueva ventana haciendo clic en este anouncio." + }, + "sendFirefoxFileWarning": { + "message": "Para elegir un archivo usando Firefox, abra la extensión en la barra lateral o salga a una nueva ventana haciendo clic en este anouncio." + }, + "sendSafariFileWarning": { + "message": "Para elegir un archivo usando Safari, salga a una nueva ventana haciendo clic en este anouncio." + }, + "sendFileCalloutHeader": { + "message": "Antes de empezar" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Para usar un selector de fechas de estilo calendario", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "haz click aquí", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "para abrir la ventana.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "La fecha de caducidad proporcionada no es válida." + }, + "deletionDateIsInvalid": { + "message": "La fecha de eliminación proporcionada no es válida." + }, + "expirationDateAndTimeRequired": { + "message": "Se requiere una fecha y hora de caducidad." + }, + "deletionDateAndTimeRequired": { + "message": "Se requiere una fecha y hora de eliminación." + }, + "dateParsingError": { + "message": "Hubo un error al guardar las fechas de eliminación y caducidad." + }, + "hideEmail": { + "message": "Ocultar mi dirección de correo electrónico a los destinatarios." + }, + "sendOptionsPolicyInEffect": { + "message": "Una o más políticas de organización están afectando sus opciones del Send." + }, + "passwordPrompt": { + "message": "Volver a preguntar contraseña maestra" + }, + "passwordConfirmation": { + "message": "Confirmación de contraseña maestra" + }, + "passwordConfirmationDesc": { + "message": "Esta acción está protegida. Para continuar, vuelva a introducir su contraseña maestra para verificar su identidad." + }, + "emailVerificationRequired": { + "message": "Verificación de correo electrónico requerida" + }, + "emailVerificationRequiredDesc": { + "message": "Debes verificar tu correo electrónico para usar esta función. Puedes verificar tu correo electrónico en la bóveda web." + }, + "updatedMasterPassword": { + "message": "Contraseña maestra actualizada" + }, + "updateMasterPassword": { + "message": "Actualizar contraseña maestra" + }, + "updateMasterPasswordWarning": { + "message": "Su contraseña maestra ha sido cambiada recientemente por un administrador de su organización. Para acceder a la caja fuerte, debe actualizarla ahora. Proceder le desconectará de su sesión actual, requiriendo que vuelva a iniciar sesión. Las sesiones activas en otros dispositivos pueden seguir estando activas durante una hora." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscripción automática" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Esta organización tiene una política empresarial que lo inscribirá automáticamente en el restablecimiento de contraseña. La inscripción permitirá a los administradores de la organización cambiar su contraseña maestra." + }, + "selectFolder": { + "message": "Seleccione carpeta..." + }, + "ssoCompleteRegistration": { + "message": "Para completar el inicio de sesión con SSO, por favor establezca una contraseña maestra para acceder y proteger su caja fuerte." + }, + "hours": { + "message": "Horas" + }, + "minutes": { + "message": "Minutos" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Las políticas de tu organización están afectando el tiempo de espera de tu caja fuerte. El máximo permitido de espera es de $HOURS$ hora(s) y de $MINUTES$ minuto(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "El tiempo de espera de tu caja fuerte excede las restricciones establecidas por tu organización." + }, + "vaultExportDisabled": { + "message": "Exportación de caja fuerte desactivada" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una o más políticas de organización le impiden exportar su caja fuerte personal." + }, + "copyCustomFieldNameInvalidElement": { + "message": "No se puede identificar un elemento de formulario válido. Intenta inspeccionar el HTML en su lugar." + }, + "copyCustomFieldNameNotUnique": { + "message": "Identificador único no encontrado." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ está usando SSO con un servidor de claves autoalojado. Los miembros de esta organización ya no necesitarán una contraseña maestra para iniciar sesión.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Abandonar organización" + }, + "removeMasterPassword": { + "message": "Eliminar contraseña maestra" + }, + "removedMasterPassword": { + "message": "Contraseña maestra eliminada." + }, + "leaveOrganizationConfirmation": { + "message": "¿Confirma que quiere abandonar esta organización?" + }, + "leftOrganization": { + "message": "Ha abandonado la organización." + }, + "toggleCharacterCount": { + "message": "Alternar conteo de caracteres" + }, + "sessionTimeout": { + "message": "Su sesión ha expirado. Por favor, vuelva e intente iniciar sesión de nuevo." + }, + "exportingPersonalVaultTitle": { + "message": "Exportando bóveda personal" + }, + "exportingPersonalVaultDescription": { + "message": "Solo se exportarán los elementos de la bóveda personal asociados con $EMAIL$. Los elementos de la bóveda de la organización no se incluirán.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/et/messages.json b/apps/browser/src/_locales/et/messages.json new file mode 100644 index 0000000000..e7069e0b51 --- /dev/null +++ b/apps/browser/src/_locales/et/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Tasuta paroolihaldur", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Turvaline ja tasuta paroolihaldur kõikidele sinu seadmetele.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Logi oma olemasolevasse kontosse sisse või loo uus konto." + }, + "createAccount": { + "message": "Loo konto" + }, + "login": { + "message": "Logi sisse" + }, + "enterpriseSingleSignOn": { + "message": "Ettevõtte Single Sign-On" + }, + "cancel": { + "message": "Tühista" + }, + "close": { + "message": "Sulge" + }, + "submit": { + "message": "Kinnita" + }, + "emailAddress": { + "message": "E-posti aadress" + }, + "masterPass": { + "message": "Ülemparool" + }, + "masterPassDesc": { + "message": "Ülemparool on parool, millega pääsed oma kontole ligi. On äärmiselt tähtis, et ülemparool ei ununeks. Selle parooli taastamine ei ole mingil moel võimalik." + }, + "masterPassHintDesc": { + "message": "Vihje võib abiks olla olukorras, kui oled ülemparooli unustanud." + }, + "reTypeMasterPass": { + "message": "Sisesta ülemparool uuesti" + }, + "masterPassHint": { + "message": "Ülemparooli vihje (ei ole kohustuslik)" + }, + "tab": { + "message": "Kaart" + }, + "myVault": { + "message": "Minu hoidla" + }, + "tools": { + "message": "Tööriistad" + }, + "settings": { + "message": "Seaded" + }, + "currentTab": { + "message": "Praegune vahekaart" + }, + "copyPassword": { + "message": "Kopeeri parool" + }, + "copyNote": { + "message": "Kopeeri märkus" + }, + "copyUri": { + "message": "Kopeeri URI" + }, + "copyUsername": { + "message": "Kopeeri kasutajanimi" + }, + "copyNumber": { + "message": "Kopeeri number" + }, + "copySecurityCode": { + "message": "Kopeeri turvakood" + }, + "autoFill": { + "message": "Automaatne täitmine" + }, + "generatePasswordCopied": { + "message": "Genereeri parool (kopeeritakse)" + }, + "copyElementIdentifier": { + "message": "Kopeeri kohandatud välja nimi" + }, + "noMatchingLogins": { + "message": "Sobivaid kontoandmeid ei leitud." + }, + "unlockVaultMenu": { + "message": "Lukusta hoidla lahti" + }, + "loginToVaultMenu": { + "message": "Logi hoidlasse sisse" + }, + "autoFillInfo": { + "message": "Selle vahekaardi automaatseks täitmiseks puuduvad kirjed." + }, + "addLogin": { + "message": "Lisa konto andmed" + }, + "addItem": { + "message": "Lisa kirje" + }, + "passwordHint": { + "message": "Parooli vihje" + }, + "enterEmailToGetHint": { + "message": "Ülemparooli vihje saamiseks sisesta oma konto e-posti aadress." + }, + "getMasterPasswordHint": { + "message": "Tuleta ülemparool vihjega meelde" + }, + "continue": { + "message": "Jätka" + }, + "sendVerificationCode": { + "message": "Saada kinnituskood oma e-postile" + }, + "sendCode": { + "message": "Saada kood" + }, + "codeSent": { + "message": "Kood on saadetud" + }, + "verificationCode": { + "message": "Kinnituskood" + }, + "confirmIdentity": { + "message": "Jätkamiseks kinnita oma identiteet." + }, + "account": { + "message": "Konto" + }, + "changeMasterPassword": { + "message": "Muuda ülemparooli" + }, + "fingerprintPhrase": { + "message": "Sõrmejälje fraas", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Konto sõrmejälje fraas", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Kaheastmeline kinnitamine" + }, + "logOut": { + "message": "Logi välja" + }, + "about": { + "message": "Rakenduse info" + }, + "version": { + "message": "Versioon" + }, + "save": { + "message": "Salvesta" + }, + "move": { + "message": "Teisalda" + }, + "addFolder": { + "message": "Kausta lisamine" + }, + "name": { + "message": "Nimi" + }, + "editFolder": { + "message": "Muuda kausta" + }, + "deleteFolder": { + "message": "Kustuta Kaust" + }, + "folders": { + "message": "Kaustad" + }, + "noFolders": { + "message": "Puuduvad kaustad, mida kuvada." + }, + "helpFeedback": { + "message": "Abi ja tagasiside" + }, + "sync": { + "message": "Sünkroniseeri" + }, + "syncVaultNow": { + "message": "Sünkroniseeri hoidla" + }, + "lastSync": { + "message": "Viimane sünkronisatsioon:" + }, + "passGen": { + "message": "Parooli genereerimine" + }, + "generator": { + "message": "Genereerija", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Loo oma kontodele tugevaid ja unikaalseid paroole." + }, + "bitWebVault": { + "message": "Bitwardeni Veebihoidla" + }, + "importItems": { + "message": "Impordi andmed" + }, + "select": { + "message": "Vali" + }, + "generatePassword": { + "message": "Loo parool" + }, + "regeneratePassword": { + "message": "Genereeri parool uuesti" + }, + "options": { + "message": "Valikud" + }, + "length": { + "message": "Pikkus" + }, + "uppercase": { + "message": "Suurtäht (A-Z) " + }, + "lowercase": { + "message": "Väiketäht (a-z) " + }, + "numbers": { + "message": "Numbrid (0-9)" + }, + "specialCharacters": { + "message": "Erimärgid (!@#$%^&*)" + }, + "numWords": { + "message": "Sõnade arv" + }, + "wordSeparator": { + "message": "Sõna eraldaja" + }, + "capitalize": { + "message": "Suurtäht", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Lisa number" + }, + "minNumbers": { + "message": "Vähim arv numbreid" + }, + "minSpecial": { + "message": "Vähim arv spetsiaalmärke" + }, + "avoidAmbChar": { + "message": "Väldi ebamääraseid kirjamärke" + }, + "searchVault": { + "message": "Otsi hoidlast" + }, + "edit": { + "message": "Muuda" + }, + "view": { + "message": "Vaata" + }, + "noItemsInList": { + "message": "Puuduvad kirjed, mida kuvada." + }, + "itemInformation": { + "message": "Kirje andmed" + }, + "username": { + "message": "Kasutajanimi" + }, + "password": { + "message": "Parool" + }, + "passphrase": { + "message": "Paroolifraas" + }, + "favorite": { + "message": "Lemmik" + }, + "notes": { + "message": "Märkmed" + }, + "note": { + "message": "Märkus" + }, + "editItem": { + "message": "Kirje muutmine" + }, + "folder": { + "message": "Kaust" + }, + "deleteItem": { + "message": "Kustuta kirje" + }, + "viewItem": { + "message": "Kirje vaatamine" + }, + "launch": { + "message": "Käivita" + }, + "website": { + "message": "Veebileht" + }, + "toggleVisibility": { + "message": "Näita" + }, + "manage": { + "message": "Halda" + }, + "other": { + "message": "Muu" + }, + "rateExtension": { + "message": "Hinda seda laiendust" + }, + "rateExtensionDesc": { + "message": "Soovi korral võid meid positiivse hinnanguga toetada!" + }, + "browserNotSupportClipboard": { + "message": "Kasutatav brauser ei toeta lihtsat lõikelaua kopeerimist. Kopeeri see käsitsi." + }, + "verifyIdentity": { + "message": "Identiteedi kinnitamine" + }, + "yourVaultIsLocked": { + "message": "Hoidla on lukus. Jätkamiseks sisesta ülemparool." + }, + "unlock": { + "message": "Lukusta lahti" + }, + "loggedInAsOn": { + "message": "Sisse logitud kontosse $EMAIL$ aadressil $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Vale ülemparool" + }, + "vaultTimeout": { + "message": "Hoidla ajalõpp" + }, + "lockNow": { + "message": "Lukusta paroolihoidla" + }, + "immediately": { + "message": "Koheselt" + }, + "tenSeconds": { + "message": "10 sekundi pärast" + }, + "twentySeconds": { + "message": "20 sekundi pärast" + }, + "thirtySeconds": { + "message": "30 sekundi pärast" + }, + "oneMinute": { + "message": "1 minuti pärast" + }, + "twoMinutes": { + "message": "2 minuti pärast" + }, + "fiveMinutes": { + "message": "5 minuti pärast" + }, + "fifteenMinutes": { + "message": "15 minuti pärast" + }, + "thirtyMinutes": { + "message": "30 minuti pärast" + }, + "oneHour": { + "message": "1 tunni pärast" + }, + "fourHours": { + "message": "4 tunni pärast" + }, + "onLocked": { + "message": "Arvutist väljalogimisel" + }, + "onRestart": { + "message": "Brauseri taaskäivitamisel" + }, + "never": { + "message": "Mitte kunagi" + }, + "security": { + "message": "Turvalisus" + }, + "errorOccurred": { + "message": "Ilmnes viga" + }, + "emailRequired": { + "message": "E-posti aadress on nõutud." + }, + "invalidEmail": { + "message": "Vigane e-posti aadress." + }, + "masterPassRequired": { + "message": "Vajalik on ülemparooli sisestamine." + }, + "masterPassLength": { + "message": "Ülemparool peab olema vähemalt 8 tähemärgi pikkune." + }, + "masterPassDoesntMatch": { + "message": "Ülemparoolid ei ühti." + }, + "newAccountCreated": { + "message": "Konto on loodud! Võid nüüd sisse logida." + }, + "masterPassSent": { + "message": "Ülemparooli vihje saadeti sinu e-postile." + }, + "verificationCodeRequired": { + "message": "Nõutav on kinnituskood." + }, + "invalidVerificationCode": { + "message": "Vale kinnituskood" + }, + "valueCopied": { + "message": "$VALUE$ on kopeeritud", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Automaatne täitmine ebaõnnestus. Palun kopeeri informatsioon käsitsi." + }, + "loggedOut": { + "message": "Välja logitud" + }, + "loginExpired": { + "message": "Sessioon on aegunud." + }, + "logOutConfirmation": { + "message": "Oled kindel, et soovid välja logida?" + }, + "yes": { + "message": "Jah" + }, + "no": { + "message": "Ei" + }, + "unexpectedError": { + "message": "Tekkis ootamatu viga." + }, + "nameRequired": { + "message": "Nimi on kohustuslik." + }, + "addedFolder": { + "message": "Kaust on lisatud" + }, + "changeMasterPass": { + "message": "Muuda ülemparooli" + }, + "changeMasterPasswordConfirmation": { + "message": "Saad oma ülemparooli muuta bitwarden.com veebihoidlas. Soovid seda kohe teha?" + }, + "twoStepLoginConfirmation": { + "message": "Kaheastmeline kinnitamine aitab konto turvalisust tõsta. Lisaks paroolile pead kontole ligipääsemiseks kinnitama sisselogimise päringu SMS-ga, telefonikõnega, autentimise rakendusega või e-postiga. Kaheastmelist kinnitust saab sisse lülitada bitwarden.com veebihoidlas. Soovid seda kohe avada?" + }, + "editedFolder": { + "message": "Kaust on muudetud" + }, + "deleteFolderConfirmation": { + "message": "Oled kindel, et soovid seda kausta kustutada?" + }, + "deletedFolder": { + "message": "Kaust on kustutatud" + }, + "gettingStartedTutorial": { + "message": "Alustamise juhend" + }, + "gettingStartedTutorialVideo": { + "message": "Vaata meie alustamise juhendit, et brauseri lisa kohta rohkem teavet saada." + }, + "syncingComplete": { + "message": "Sünkroniseerimine on lõpetatud" + }, + "syncingFailed": { + "message": "Sünkroniseerimine nurjus" + }, + "passwordCopied": { + "message": "Parool on kopeeritud" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Uus URI" + }, + "addedItem": { + "message": "Kirje on lisatud" + }, + "editedItem": { + "message": "Kirje on muudetud" + }, + "deleteItemConfirmation": { + "message": "Soovid tõesti selle kirje kustutada?" + }, + "deletedItem": { + "message": "Kirje on kustutatud" + }, + "overwritePassword": { + "message": "Kirjuta parool üle" + }, + "overwritePasswordConfirmation": { + "message": "Oled kindel, et soovid olemasolevat parooli üle kirjutada?" + }, + "overwriteUsername": { + "message": "Kasutajanime ülekirjutamine" + }, + "overwriteUsernameConfirmation": { + "message": "Oled kindel, et soovid praegust kasutajanime üle kirjutada? " + }, + "searchFolder": { + "message": "Otsi kausta" + }, + "searchCollection": { + "message": "Otsi kogumikku" + }, + "searchType": { + "message": "Otsingu tüüp" + }, + "noneFolder": { + "message": "Kaust puudub", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Keela \"Lisa konto andmed\" teavitus" + }, + "addLoginNotificationDesc": { + "message": "\"Lisa konto andmed\" teavitus ilmub pärast esimest sisselogimist ning võimaldab kontoandmeid automaatselt Bitwardenisse lisada." + }, + "dontShowCardsCurrentTab": { + "message": "Ära kuva \"Kaart\" vaates krediitkaardi andmeid" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Krediit- ja teiste kaartide andmed kuvatakse vaikeseadena \"Kaart\" vaates, et neid oleks lihtsam sisestada." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Ära kuva \"Kaart\" vaates identiteete" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identiteediandmeid kuvatakse vaikeseadena \"Kaart\" vaates, et neid oleks lihtsam sisestada." + }, + "clearClipboard": { + "message": "Lõikelaua sisu kustutamine", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Kustutab automaatselt lõikelauale kopeeritud sisu.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Kas bitwarden peaks seda parooli meeles pidama?" + }, + "notificationAddSave": { + "message": "Jah, salvesta see" + }, + "disableChangedPasswordNotification": { + "message": "Keela Muudetud parooli teavitus" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Kui mistahes veebilehel on toimunud parooli vahetamine, annab \"Muudetud parooli teavitus\" märku, et värskendaksid seda ka Bitwardeni paroolihoidlas." + }, + "notificationChangeDesc": { + "message": "Soovid seda parooli ka Bitwardenis uuendada?" + }, + "notificationChangeSave": { + "message": "Jah, uuenda" + }, + "disableContextMenuItem": { + "message": "Keela parema kliki menüü valikud" + }, + "disableContextMenuItemDesc": { + "message": "Parema kliki menüü abil saad kiiresti parooli genereerida ja konkreetse veebilehe kasutajakonto andmeid sisestada." + }, + "defaultUriMatchDetection": { + "message": "Vaike URI sobivuse tuvastamine", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Vali vaikeviis, kuidas kirje ja URI sobivus tuvastatakse. Seda kasutatakse näiteks siis, kui lehele üritatakse automaatselt andmeid sisestada." + }, + "theme": { + "message": "Teema" + }, + "themeDesc": { + "message": "Muuda rakenduse värvikujundust." + }, + "dark": { + "message": "Tume", + "description": "Dark color" + }, + "light": { + "message": "Hele", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized tume", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Ekspordi hoidla" + }, + "fileFormat": { + "message": "Failivorming" + }, + "warning": { + "message": "HOIATUS", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Hoidla eksportimise kinnitamine" + }, + "exportWarningDesc": { + "message": "Eksporditav fail sisaldab hoidla sisu, mis on krüpteeringuta. Seda faili ei tohiks kaua käidelda ning mitte mingil juhul ebaturvaliselt saata (näiteks e-postiga). Kustuta see koheselt pärast kasutamist." + }, + "encExportKeyWarningDesc": { + "message": "Eksporditavate andmete krüpteerimiseks kasutatakse kontol olevat krüpteerimisvõtit. Kui sa peaksid seda krüpteerimise võtit roteerima, ei saa sa järgnevalt eksporditavaid andmeid enam dekrüpteerida." + }, + "encExportAccountWarningDesc": { + "message": "Iga Bitwardeni kasutaja krüpteerimisvõti on unikaalne. Eksporditud andmeid ei saa importida teise Bitwardeni kasutajakontosse." + }, + "exportMasterPassword": { + "message": "Hoidlas olevate andmete eksportimiseks on vajalik ülemparooli sisestamine." + }, + "shared": { + "message": "Jagatud" + }, + "learnOrg": { + "message": "Info organisatsioonide kohta" + }, + "learnOrgConfirmation": { + "message": "Bitwarden võimaldab sul hoidla sisu teiste kasutajatega jagada, kasutades selleks organisatsiooni kontot. Soovid külastada lehekülge bitwarden.com ja selle kohta rohkem lugeda?" + }, + "moveToOrganization": { + "message": "Teisalda organisatsiooni" + }, + "share": { + "message": "Jaga" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ teisaldati $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vali organisatsioon, kuhu soovid seda kirjet teisaldada. Teisaldamisega saab kirje omanikuks organisatsioon. Pärast kirje teisaldamist ei ole sa enam selle otsene omanik." + }, + "learnMore": { + "message": "Loe edasi" + }, + "authenticatorKeyTotp": { + "message": "Autentimise võti (TOTP)" + }, + "verificationCodeTotp": { + "message": "Kinnituskood (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopeeri kinnituskood" + }, + "attachments": { + "message": "Manused" + }, + "deleteAttachment": { + "message": "Kustuta manus" + }, + "deleteAttachmentConfirmation": { + "message": "Oled kindel, et soovid manuse kustutada?" + }, + "deletedAttachment": { + "message": "Manus on kustutatud" + }, + "newAttachment": { + "message": "Lisa uus manus" + }, + "noAttachments": { + "message": "Manused puuduvad." + }, + "attachmentSaved": { + "message": "Manus on salvestatud." + }, + "file": { + "message": "Fail" + }, + "selectFile": { + "message": "Vali fail." + }, + "maxFileSize": { + "message": "Maksimaalne faili suurus on 500 MB." + }, + "featureUnavailable": { + "message": "Funktsioon pole saadaval" + }, + "updateKey": { + "message": "Seda funktsiooni ei saa enne krüpteerimise võtme uuendamist kasutada." + }, + "premiumMembership": { + "message": "Premium versioon" + }, + "premiumManage": { + "message": "Halda Premium versiooni" + }, + "premiumManageAlert": { + "message": "Saad Premium versiooni hallata bitwarden.com veebihoidlas. Soovid seda kohe teha?" + }, + "premiumRefresh": { + "message": "Uuenda tellimust" + }, + "premiumNotCurrentMember": { + "message": "Sa ei ole hetkel premium versiooni kasutaja." + }, + "premiumSignUpAndGet": { + "message": "Premium versiooni lisab järgmised eelised:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB ulatuses krüpteeritud salvestusruum." + }, + "ppremiumSignUpTwoStep": { + "message": "Lisavõimalused kaheastmeliseks kinnitamiseks, näiteks YubiKey, FIDO U2F ja Duo." + }, + "ppremiumSignUpReports": { + "message": "Parooli hügieen, konto seisukord ja andmelekete raportid aitavad hoidlat turvalisena hoida." + }, + "ppremiumSignUpTotp": { + "message": "TOTP kinnituskoodide (2FA) genereerija hoidlas olevatele kasutajakontodele." + }, + "ppremiumSignUpSupport": { + "message": "Kiirema kasutajatoe." + }, + "ppremiumSignUpFuture": { + "message": "Tulevased premium funktsioonid - tasuta!" + }, + "premiumPurchase": { + "message": "Osta Premium" + }, + "premiumPurchaseAlert": { + "message": "Bitwardeni premium versiooni saab osta bitwarden.com veebihoidlas. Avan veebihoidla?" + }, + "premiumCurrentMember": { + "message": "Oled premium kasutaja!" + }, + "premiumCurrentMemberThanks": { + "message": "Täname, et toetad Bitwardenit." + }, + "premiumPrice": { + "message": "Kõik see ainult %price% aastas!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Uuendamine lõpetatud" + }, + "disableAutoTotpCopy": { + "message": "Keela automaatne TOTP kopeerimine" + }, + "disableAutoTotpCopyDesc": { + "message": "Kui sinu sisselogimise andmetele on juurde lisatud autentimise võti, kopeeritakse TOTP kood automaatse täitmise kasutamisel lõikelauale." + }, + "disableAutoBiometricsPrompt": { + "message": "Ära küsi käivitudes biomeetrilist kinnitamist" + }, + "premiumRequired": { + "message": "Vajalik on Premium versioon" + }, + "premiumRequiredDesc": { + "message": "Selle funktsiooni kasutamiseks on vajalik tasulist kontot omada." + }, + "enterVerificationCodeApp": { + "message": "Sisesta autentimise rakendusest 6 kohaline number." + }, + "enterVerificationCodeEmail": { + "message": "Sisesta 6 kohaline number, mis saadeti e-posti aadressile", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Kinnituskood saadeti e-posti aadressile $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Jäta mind meelde" + }, + "sendVerificationCodeEmailAgain": { + "message": "Saada kinnituskood uuesti e-postile" + }, + "useAnotherTwoStepMethod": { + "message": "Kasuta teist kaheastmelist sisselogimise meetodit" + }, + "insertYubiKey": { + "message": "Sisesta oma YubiKey arvuti USB porti ja kliki sellele nupule." + }, + "insertU2f": { + "message": "Sisesta oma turvaline võti arvuti USB porti. Kui sellel on nupp, siis vajuta seda." + }, + "webAuthnNewTab": { + "message": "Jätka WebAuthn 2FA kinnitamisega uuel vahelehel." + }, + "webAuthnNewTabOpen": { + "message": "Ava uus vahekaart" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn kinnitamine" + }, + "loginUnavailable": { + "message": "Sisselogimine ei ole saadaval" + }, + "noTwoStepProviders": { + "message": "Sellel kontol on aktiveeritud kaheastmeline kinnitus. Siiski ei toeta konkreetne brauser ühtegi aktiveeritud kaheastmelise kinnitamise teenust." + }, + "noTwoStepProviders2": { + "message": "Palun kasuta ühilduvat brauserit (näiteks Chrome) ja/või lisa uus kaheastmelise teenuse pakkuja, mis töötab rohkemates brauserites (näiteks mõni autentimise rakendus)." + }, + "twoStepOptions": { + "message": "Kaheastmelise sisselogimise valikud" + }, + "recoveryCodeDesc": { + "message": "Puudub ligipääs kaheastmelise kinnitamise teenusele? Kasuta Taastamise koodi, et kaheastmeline kinnitamine oma kontol välja lülitada." + }, + "recoveryCodeTitle": { + "message": "Taastamise kood" + }, + "authenticatorAppTitle": { + "message": "Autentimise rakendus" + }, + "authenticatorAppDesc": { + "message": "Kausta autentimise rakendust (näiteks Authy või Google Authenticator), et luua ajal baseeruvaid kinnituskoode.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Turvaline võti" + }, + "yubiKeyDesc": { + "message": "Kasuta kontole ligipääsemiseks YubiKey-d. See töötab YubiKey 4, 4 Nano, 4C ja NEO seadmetega." + }, + "duoDesc": { + "message": "Kinnita Duo Security abil, kasutades selleks Duo Mobile rakendust, SMS-i, telefonikõnet või U2F turvavõtit.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Kinnita organisatsiooni jaoks Duo Security abil, kasutades selleks Duo Mobile rakendust, SMS-i, telefonikõnet või U2F turvavõtit.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Kasuta mistahes WebAuthn toetavat turvalist võtit, et oma kontole ligi pääseda." + }, + "emailTitle": { + "message": "E-post" + }, + "emailDesc": { + "message": "Kinnituskoodid saadetakse e-postiga." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Kohandatud keskkond" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Serveri URL" + }, + "apiUrl": { + "message": "API serveri URL" + }, + "webVaultUrl": { + "message": "Veebihoidla serveri URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Teavitus serveri URL" + }, + "iconsUrl": { + "message": "Ikoonide serveri URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Luba kontoandmete täitmine" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Sisselogimise vormi tuvastamisel sisestatakse sinna kontoandmed automaatselt." + }, + "experimentalFeature": { + "message": "See funktsioon on katsetusjärgus. Kasuta omal vastutusel." + }, + "defaultAutoFillOnPageLoad": { + "message": "Vaikevalik kontoandmete täitmiseks" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "\"Luba kontoandmete täitmine\" sisselülitamisel saad selle siiski individuaalselt iga kirje seadetes välja lülitada. See seadistus rakendub kõikidele kirjetele, mida pole eraldi konfigureeritud." + }, + "itemAutoFillOnPageLoad": { + "message": "Luba kontoandmete täitmine (kui see on aktiveeritud)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Kasuta vaikeseadistust" + }, + "autoFillOnPageLoadYes": { + "message": "Täida kontoandmed lehe laadimisel" + }, + "autoFillOnPageLoadNo": { + "message": "Ära täida kontoandmeid lehe laadimisel" + }, + "commandOpenPopup": { + "message": "Ava hoidla uues aknas" + }, + "commandOpenSidebar": { + "message": "Ava hoidla küljeribal" + }, + "commandAutofillDesc": { + "message": "Sisesta lehele viimati kasutatud kontoandmed." + }, + "commandGeneratePasswordDesc": { + "message": "Loo ja kopeeri uus juhuslikult koostatud parool lõikelauale." + }, + "commandLockVaultDesc": { + "message": "Lukusta hoidla" + }, + "privateModeWarning": { + "message": "Privaatrežiimi toetus on katsejärgus, mistõttu mõned funktsioonid on piiratud." + }, + "customFields": { + "message": "Kohandatud väljad" + }, + "copyValue": { + "message": "Kopeeri kirje" + }, + "value": { + "message": "Väärtus" + }, + "newCustomField": { + "message": "Uus kohandatud väli" + }, + "dragToSort": { + "message": "Lohista sorteerimiseks" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Peidetud" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Ühenduses", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Ühendatud väärtus", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "See aken sulgub, kui klikid oma e-posti aknale, et sealt kinnituskoodi vaadata. Soovid selle hüpikakna uues aknas avada, et seda ei juhtuks?" + }, + "popupU2fCloseMessage": { + "message": "Kasutatav brauser ei suuda selles aknas U2F päringuid töödelda. Kas avan uue akna, et saaksid U2F abil sisse logida?" + }, + "disableFavicon": { + "message": "Keela veebilehel ikoonid" + }, + "disableFaviconDesc": { + "message": "Ikoonid aitavad hoidlas olevaid veebilehti paremini ära tunda." + }, + "disableBadgeCounter": { + "message": "Keela kirjete loendur" + }, + "disableBadgeCounterDesc": { + "message": "Kirjete loendur kuvab Bitwardeni ikoonil konkreetse leheküljega seotud kirjete arvu." + }, + "cardholderName": { + "message": "Kaardiomaniku nimi" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Väljastaja" + }, + "expirationMonth": { + "message": "Aegumise kuu" + }, + "expirationYear": { + "message": "Aegumise aasta" + }, + "expiration": { + "message": "Aegumine" + }, + "january": { + "message": "Jaanuar" + }, + "february": { + "message": "Veebruar" + }, + "march": { + "message": "Märts" + }, + "april": { + "message": "Aprill" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juuni" + }, + "july": { + "message": "Juuli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktoober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Detsember" + }, + "securityCode": { + "message": "Turvakood" + }, + "ex": { + "message": "nt." + }, + "title": { + "message": "Pealkiri" + }, + "mr": { + "message": "Hr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Pr" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Eesnimi" + }, + "middleName": { + "message": "Teine eesnimi" + }, + "lastName": { + "message": "Perekonnanimi" + }, + "fullName": { + "message": "Täisnimi" + }, + "identityName": { + "message": "Identiteedi nimi" + }, + "company": { + "message": "Ettevõte" + }, + "ssn": { + "message": "Isikukood" + }, + "passportNumber": { + "message": "Passi number" + }, + "licenseNumber": { + "message": "Litsentsi number" + }, + "email": { + "message": "E-post" + }, + "phone": { + "message": "Telefoninumber" + }, + "address": { + "message": "Aadress" + }, + "address1": { + "message": "Aadress 1" + }, + "address2": { + "message": "Aadress 2" + }, + "address3": { + "message": "Aadress 3" + }, + "cityTown": { + "message": "Linn / asula" + }, + "stateProvince": { + "message": "Maakond / vald" + }, + "zipPostalCode": { + "message": "Postiindeks" + }, + "country": { + "message": "Riik" + }, + "type": { + "message": "Tüüp" + }, + "typeLogin": { + "message": "Kasutajakonto andmed" + }, + "typeLogins": { + "message": "Kontod" + }, + "typeSecureNote": { + "message": "Turvaline märkus" + }, + "typeCard": { + "message": "Pangakaart" + }, + "typeIdentity": { + "message": "Identiteet" + }, + "passwordHistory": { + "message": "Paroolide ajalugu" + }, + "back": { + "message": "Tagasi" + }, + "collections": { + "message": "Kogumikud" + }, + "favorites": { + "message": "Lemmikud" + }, + "popOutNewWindow": { + "message": "Ava uues aknas" + }, + "refresh": { + "message": "Uuenda" + }, + "cards": { + "message": "Pangakaardid" + }, + "identities": { + "message": "Identiteedid" + }, + "logins": { + "message": "Kontod" + }, + "secureNotes": { + "message": "Turvalised märkmed" + }, + "clear": { + "message": "Tühjenda", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Vaata, kas parool on lekkinud." + }, + "passwordExposed": { + "message": "See parool on erinevates andmeleketes kokku $VALUE$ korda lekkinud. Peaksid selle ära muutma.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Seda parooli ei õnnestu andmeleketest leida. Parooli edasi kasutamine peaks olema turvaline." + }, + "baseDomain": { + "message": "Baasdomeen", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domeeni nimi", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Täpne" + }, + "startsWith": { + "message": "Algab" + }, + "regEx": { + "message": "RegEx", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Sobivuse tuvastamine", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Vaike sobivuse tuvastamine", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Valik sisse" + }, + "toggleCurrentUris": { + "message": "Kuva praegused URI'd", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Praegune URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisatsioon", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tüübid" + }, + "allItems": { + "message": "Kõik kirjed" + }, + "noPasswordsInList": { + "message": "Puuduvad paroolid, mida kuvada." + }, + "remove": { + "message": "Eemalda" + }, + "default": { + "message": "Vaikimisi" + }, + "dateUpdated": { + "message": "Uuendatud", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parool on uuendatud", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Oled kindel, et soovid kasutada valikut \"Mitte kunagi\"? Sellega talletatakse sinu hoidla krüpteerimise võtit seadme mälus. Peaksid olema väga hoolas ja kindel, et seade on ohutu ja selles ei ole pahavara." + }, + "noOrganizationsList": { + "message": "Sa ei kuulu ühessegi organisatsiooni. Organisatsioonid võimaldavad sul kirjeid turvaliselt teiste kasutajatega jagada." + }, + "noCollectionsInList": { + "message": "Puuduvad kollektsioonid, mida kuvada." + }, + "ownership": { + "message": "Omanik" + }, + "whoOwnsThisItem": { + "message": "Kes on selle kirje omanik?" + }, + "strong": { + "message": "Tugev", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Hea", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Nõrk", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Nõrk ülemparool" + }, + "weakMasterPasswordDesc": { + "message": "Valitud ülemparool on nõrk. Oma Bitwardeni konto paremaks kaitsmiseks peaksid kasutama tugevat parooli. Oled kindel, et soovid seda parooli ülemparoolina kasutada?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Ava PIN-iga" + }, + "setYourPinCode": { + "message": "Määra Bitwardeni lahtilukustamiseks PIN kood. Rakendusest täielikult välja logides nullitakse ka PIN koodi seaded." + }, + "pinRequired": { + "message": "Nõutakse PIN koodi." + }, + "invalidPin": { + "message": "Vale PIN kood." + }, + "unlockWithBiometrics": { + "message": "Ava biomeetriaga" + }, + "awaitDesktop": { + "message": "Kinnituse ootamine töölaua rakenduselt" + }, + "awaitDesktopDesc": { + "message": "Kinnitamiseks kasuta biomeetrilist lahtilukustamist Bitwardeni töölaua rakenduses." + }, + "lockWithMasterPassOnRestart": { + "message": "Nõua ülemparooli, kui brauser taaskäivitatakse" + }, + "selectOneCollection": { + "message": "Pead valima vähemalt ühe kogumiku." + }, + "cloneItem": { + "message": "Klooni kirje" + }, + "clone": { + "message": "Kloon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Organisatsiooni seaded mõjutavad parooli genereerija sätteid." + }, + "vaultTimeoutAction": { + "message": "Hoidla ajalõpu tegevus" + }, + "lock": { + "message": "Lukusta", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Prügikast", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Otsi prügikastist" + }, + "permanentlyDeleteItem": { + "message": "Kustuta kirje jäädavalt" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Oled kindel, et soovid selle kirje jäädavalt kustutada?" + }, + "permanentlyDeletedItem": { + "message": "Kirje on jäädavalt kustutatud" + }, + "restoreItem": { + "message": "Taasta kirje" + }, + "restoreItemConfirmation": { + "message": "Oled kindel, et soovid selle kirje taastada?" + }, + "restoredItem": { + "message": "Kirje on taastatud" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Väljalogimine eemaldab hoidlale ligipääsu ning nõuab pärast ajalõpu perioodi uuesti autentimist. Oled kindel, et soovid seda valikut kasutada?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Ajalõpu tegevuse kinnitamine" + }, + "autoFillAndSave": { + "message": "Täida ja salvesta" + }, + "autoFillSuccessAndSavedUri": { + "message": "Kirje täideti ja URI salvestati" + }, + "autoFillSuccess": { + "message": "Kirje täideti" + }, + "setMasterPassword": { + "message": "Määra ülemparool" + }, + "masterPasswordPolicyInEffect": { + "message": "Üks või enam organisatsiooni eeskirja nõuavad, et ülemparool vastaks nendele nõudmistele:" + }, + "policyInEffectMinComplexity": { + "message": "Minimaalne keerulisuse skoor peab olema $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimaalne pikkus peab olema $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Sisaldab üht või enamat suurtähte" + }, + "policyInEffectLowercase": { + "message": "Sisaldab üht või enamat väiketähte" + }, + "policyInEffectNumbers": { + "message": "Sisaldab üht või rohkem numbreid" + }, + "policyInEffectSpecial": { + "message": "Sisaldab üht või enamat järgnevatest märkidest: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Uus ülemparool ei vasta eeskirjades väljatoodud tingimustele." + }, + "acceptPolicies": { + "message": "Märkeruudu markeerimisel nõustud järgnevaga:" + }, + "acceptPoliciesError": { + "message": "Kasutustingimuste ja Privaatsuspoliitikaga pole nõustutud." + }, + "termsOfService": { + "message": "Kasutustingimused" + }, + "privacyPolicy": { + "message": "Privaatsuspoliitika" + }, + "hintEqualsPassword": { + "message": "Parooli vihje ei saa olla sama mis parool ise." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Töölaua sünkroonimise kinnitamine" + }, + "desktopIntegrationVerificationText": { + "message": "Veendu, et töölaua rakendus kuvab järgnevat sõrmejälge: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Brauseri integratsioon ei ole sisse lülitatud" + }, + "desktopIntegrationDisabledDesc": { + "message": "Brauseri integratsioon ei ole Bitwardeni töölaua rakenduses sisse lülitatud. Palun lülita see töölaua rakenduse seadetes sisse." + }, + "startDesktopTitle": { + "message": "Käivita Bitwardeni töölaua rakendus" + }, + "startDesktopDesc": { + "message": "Enne selle funktsiooni sisselülitamist peab käivitama Bitwardeni töölaua rakenduse." + }, + "errorEnableBiometricTitle": { + "message": "Biomeetria sisselülitamine nurjus" + }, + "errorEnableBiometricDesc": { + "message": "Töölaua rakendus tühistas tegevuse" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Töölaua rakendusel ei õnnestunud turvalist ühenduskanalit luua. Palun proovi uuesti" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Suhtlus töölaua rakendusega katkes" + }, + "nativeMessagingWrongUserDesc": { + "message": "Töölaua rakenduses on sisse logitud teise kasutajaga. Veendu, et oled mõlemas rakenduses sisse loginud ühe ja sama kontoga." + }, + "nativeMessagingWrongUserTitle": { + "message": "Kontod ei ühti" + }, + "biometricsNotEnabledTitle": { + "message": "Biomeetria ei ole sisse lülitatud" + }, + "biometricsNotEnabledDesc": { + "message": "Biomeetria kasutamiseks brauseris peab esmalt Bitwardeni töölaua rakenduse seadetes biomeetria lubama." + }, + "biometricsNotSupportedTitle": { + "message": "Biomeetriat ei toetata" + }, + "biometricsNotSupportedDesc": { + "message": "Brauseri biomeetria ei ole selles seadmes toetatud" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Luba puudub" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Puudub luba, et suhelda Bitwardeni töölaua rakendusega. Selle tõttu ei saa brauseri lisas biomeetriat kasutada. Palun proovi uuesti." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Loa taotlemisel ilmnes viga" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Seda tegevust ei saa küljeribal sooritada. Proovi seda sooritada hüpikakna vaates." + }, + "personalOwnershipSubmitError": { + "message": "Ettevõtte poliitika tõttu ei saa sa andmeid oma personaalsesse Hoidlasse salvestada. Vali Omanikuks organisatsioon ja vali mõni saadavaolevatest Kogumikest." + }, + "personalOwnershipPolicyInEffect": { + "message": "Organisatsiooni poliitika on seadnud omaniku valikutele piirangu." + }, + "excludedDomains": { + "message": "Väljajäetud domeenid" + }, + "excludedDomainsDesc": { + "message": "Nendel domeenidel Bitwarden paroolide salvestamise valikut ei paku. Muudatuste jõustamiseks pead lehekülge värskendama." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ ei ole õige domeen.", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Otsi Sende", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Lisa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Tekst" + }, + "sendTypeFile": { + "message": "Fail" + }, + "allSends": { + "message": "Kõik Sendid", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maksimaalne ligipääsude arv on saavutatud", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Aegunud" + }, + "pendingDeletion": { + "message": "Kustutamise ootel" + }, + "passwordProtected": { + "message": "Parooliga kaitstud" + }, + "copySendLink": { + "message": "Kopeeri Sendi link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Eemalda parool" + }, + "delete": { + "message": "Kustuta" + }, + "removedPassword": { + "message": "Eemaldas parooli" + }, + "deletedSend": { + "message": "Kustutas Sendi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Sendi link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Keelatud" + }, + "removePasswordConfirmation": { + "message": "Soovid kindlasti selle parooli eemaldada?" + }, + "deleteSend": { + "message": "Kustuta Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Soovid tõesti selle Sendi kustutada?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Muuda Sendi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Mis tüüpi Send see on?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Sisesta Sendi nimi (kohustuslik).", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Fail, mida soovid saata." + }, + "deletionDate": { + "message": "Kustutamise kuupäev" + }, + "deletionDateDesc": { + "message": "Send kustutatakse määratud kuupäeval ja kellaajal jäädavalt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Aegumiskuupäev" + }, + "expirationDateDesc": { + "message": "Selle valimisel ei pääse sellele Sendile enam pärast määratud kuupäeva ligi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 päev" + }, + "days": { + "message": "$DAYS$ päeva", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Kohandatud" + }, + "maximumAccessCount": { + "message": "Maksimaalne ligipääsude arv" + }, + "maximumAccessCountDesc": { + "message": "Selle valimisel ei saa kasutajad pärast maksimaalse ligipääsude arvu saavutamist sellele Sendile enam ligi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Soovi korral nõua parooli, millega Sendile ligi pääseb.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privaatne märkus selle Sendi kohta.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Keela see Send, et keegi ei pääseks sellele ligi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kopeeri Sendi salvestamisel link lõikelauale.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Tekst, mida soovid saata." + }, + "sendHideText": { + "message": "Vaikeolekus peida selle Sendi tekst.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Hetkeline ligipääsude arv" + }, + "createSend": { + "message": "Loo uus Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Uus Parool" + }, + "sendDisabled": { + "message": "Send on väljalülitatud", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Ettevõtte poliitika kohaselt saad ainult olemasolevat Sendi kustutada.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send on loodud", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Muudetud", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Faili valimiseks ava rakendus külgribal (kui see on võimalik) või kasuta hüpikakent, klikkides sellel bänneril." + }, + "sendFirefoxFileWarning": { + "message": "Faili valimiseks läbi Firefoxi ava Bitwardeni rakendus Firefoxi külgribal või kasuta hüpikakent (klikkides sellel bänneril)." + }, + "sendSafariFileWarning": { + "message": "Faili valimiseks läbi Safari kasuta Bitwardeni hüpikakent (klikkides sellel bänneril)." + }, + "sendFileCalloutHeader": { + "message": "Enne alustamist" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Kalendri stiilis kuupäeva valimiseks", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "kliki siia,", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "et avada Bitwarden uues aknas.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Valitud aegumiskuupäev ei ole õige." + }, + "deletionDateIsInvalid": { + "message": "Valitud kustutamise kuupäev ei ole õige." + }, + "expirationDateAndTimeRequired": { + "message": "Nõutav on aegumiskuupäev ja kellaaeg." + }, + "deletionDateAndTimeRequired": { + "message": "Nõutav on kustutamise kuupäev ja kellaaeg." + }, + "dateParsingError": { + "message": "Kustutamis- ja aegumiskuupäevade salvestamisel ilmnes tõrge." + }, + "hideEmail": { + "message": "Ära näita saajatele minu e-posti aadressi." + }, + "sendOptionsPolicyInEffect": { + "message": "Organisatsiooni seaded mõjutavad sinu Sendi sätteid." + }, + "passwordPrompt": { + "message": "Nõutav on ülemparool" + }, + "passwordConfirmation": { + "message": "Ülemparooli kinnitamine" + }, + "passwordConfirmationDesc": { + "message": "See tegevus on kaitstud. Jätkamiseks sisesta oma ülemparool." + }, + "emailVerificationRequired": { + "message": "Vajalik on e-posti kinnitamine" + }, + "emailVerificationRequiredDesc": { + "message": "Selle funktsiooni kasutamiseks pead kinnitama oma e-posti aadressi. Saad seda teha veebihoidlas." + }, + "updatedMasterPassword": { + "message": "Uuendas ülemparooli" + }, + "updateMasterPassword": { + "message": "Ülemparooli uuendamine" + }, + "updateMasterPasswordWarning": { + "message": "Organisatsiooni administraator muutis hiljuti sinu ülemparooli. Hoidlale ligi pääsemiseks pead seda nüüd uuendama. Jätkates logitakse sind käimasolevast sessioonist välja, misjärel nõutakse uuesti sisselogimist. Teistes seadmetes olevad aktiivsed sessioonid jäävad aktiivseks kuni üheks tunniks." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automaatne liitumine" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Selle organisatsiooni poliitika kohaselt liidetakse sind automaatselt ülemparooli lähtestamise funktsiooniga. Liitumisel saavad organisatsiooni administraatorid sinu ülemparooli muuta." + }, + "selectFolder": { + "message": "Vali kaust..." + }, + "ssoCompleteRegistration": { + "message": "SSO-ga sisselogimise kinnitamiseks tuleb määrata ülemparool. See kaitseb sinu hoidlat ning võimaldab sellele ligi pääseda." + }, + "hours": { + "message": "Tundi" + }, + "minutes": { + "message": "Minutit" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Organisatsiooni poliitikad mõjutavad sinu hoidla ajalõppu. Maksimaalne lubatud hoidla ajalõpp on $HOURS$ tund(i) ja $MINUTES$ minut(it)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Valitud hoidla ajalõpp ei ole organisatsiooni poolt määratud reeglitega kooskõlas. " + }, + "vaultExportDisabled": { + "message": "Hoidla eksportimine on väljalülitatud" + }, + "personalVaultExportPolicyInEffect": { + "message": "Üks või enam organisatsiooni poliitikat ei võimalda sul oma personaalset hoidlat eksportida." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Korrektset välja nime ei õnnestunud tuvastada. Proovi HTML koodi inspekteerimist." + }, + "copyCustomFieldNameNotUnique": { + "message": "Unikaalset identifikaatorit ei leitud." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ kasutab SSO-d koos enda majutatud võtmeserveriga. Selle organisatsiooni liikmed ei pea sisselogimisel enam ülemparooli kasutama.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Lahku organisatsioonist" + }, + "removeMasterPassword": { + "message": "Eemalda ülemparool" + }, + "removedMasterPassword": { + "message": "Ülemparool on eemaldatud." + }, + "leaveOrganizationConfirmation": { + "message": "Kas oled kindel, et soovid sellest organisatsioonist lahkuda?" + }, + "leftOrganization": { + "message": "Oled organisatsioonist lahkunud." + }, + "toggleCharacterCount": { + "message": "Loenda kirjatähtede hulka" + }, + "sessionTimeout": { + "message": "Sessioon on aegunud. Palun mine tagasi ja proovi uuesti sisse logida." + }, + "exportingPersonalVaultTitle": { + "message": "Personaalse hoidla eksportimine" + }, + "exportingPersonalVaultDescription": { + "message": "Ainult personaalsed $EMAIL$ alla kuuluvad kirjed eksportidakse. Organisatsiooni kirjeid ei ekspordita.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Viga" + }, + "regenerateUsername": { + "message": "Genereeri kasutajanimi uuesti" + }, + "generateUsername": { + "message": "Genereeri kasutajanimi" + }, + "usernameType": { + "message": "Kasutajanime tüüp" + }, + "plusAddressedEmail": { + "message": "Lisaks e-post", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Kasuta e-posti teenuspakkuja alamadressimise võimalusi." + }, + "catchallEmail": { + "message": "Kogumisaadress" + }, + "catchallEmailDesc": { + "message": "Kasuta domeenipõhist kogumisaadressi." + }, + "random": { + "message": "Juhuslik" + }, + "randomWord": { + "message": "Juhuslik sõna" + }, + "websiteName": { + "message": "Veebilehe nimi" + }, + "whatWouldYouLikeToGenerate": { + "message": "Mida sa soovid genereerida?" + }, + "passwordType": { + "message": "Parooli tüüp" + }, + "service": { + "message": "Teenus" + } +} diff --git a/apps/browser/src/_locales/fa/messages.json b/apps/browser/src/_locales/fa/messages.json new file mode 100644 index 0000000000..25c2459902 --- /dev/null +++ b/apps/browser/src/_locales/fa/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - مدیریت کلمه عبور رایگان", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "یک مدیریت کننده کلمه عبور رایگان برای تمامی دستگاههایتان.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "وارد شوید یا یک حساب کاربری بسازید تا به گاوصندوق امنتان دسترسی یابید." + }, + "createAccount": { + "message": "ایجاد حساب کاربری" + }, + "login": { + "message": "ورود" + }, + "enterpriseSingleSignOn": { + "message": "ورود به سیستم پروژه" + }, + "cancel": { + "message": "انصراف" + }, + "close": { + "message": "بستن" + }, + "submit": { + "message": "ثبت" + }, + "emailAddress": { + "message": "آدرس ایمیل" + }, + "masterPass": { + "message": "کلمه عبور اصلی" + }, + "masterPassDesc": { + "message": "کلمه عبور اصلی کلمه عبوری است که شما برای دسترسی به گاوصندوق خود استفاده میکنید. بیاد داشتن کلمه عبور اصلی بسیار اهمیت دارد. اگر فراموشش کنید هیچ راهی برای بازگردانی آن وجود ندارد." + }, + "masterPassHintDesc": { + "message": "راهنمای کلمه عبور اصلی می تواند در صورت فراموشی آن را بیاد بیارید." + }, + "reTypeMasterPass": { + "message": "تایپ دوباره کلمه عبور اصلی" + }, + "masterPassHint": { + "message": "راهنمای کلمه عبور اصلی (اختیاری)" + }, + "tab": { + "message": "زبانه" + }, + "myVault": { + "message": "گاوصندوق من" + }, + "tools": { + "message": "ابزار" + }, + "settings": { + "message": "تنظیمات" + }, + "currentTab": { + "message": "زبانه فعلی" + }, + "copyPassword": { + "message": "کپی رمز عبور" + }, + "copyNote": { + "message": "کپی یادداشت" + }, + "copyUri": { + "message": "کپی آدرس اینترنتی" + }, + "copyUsername": { + "message": "کپی نام کاربری" + }, + "copyNumber": { + "message": "کپی شماره" + }, + "copySecurityCode": { + "message": "کپی کد امنیتی" + }, + "autoFill": { + "message": "پر کردن خودکار" + }, + "generatePasswordCopied": { + "message": "ساخت کلمه عبور (کپی شد)" + }, + "copyElementIdentifier": { + "message": "رونوشت نام فیلد سفارشی" + }, + "noMatchingLogins": { + "message": "ورودیها منتطبق نیست." + }, + "unlockVaultMenu": { + "message": "بازکردن گاو‌صندوقتان" + }, + "loginToVaultMenu": { + "message": "وارد شدن به گاو‌صندوقتان" + }, + "autoFillInfo": { + "message": "پرکردن خودکار برای برگه فعلی مرورگر در دسترس نیست." + }, + "addLogin": { + "message": "افزودن ورود جدید" + }, + "addItem": { + "message": "افزودن مورد" + }, + "passwordHint": { + "message": "راهنمای کلمه عبور" + }, + "enterEmailToGetHint": { + "message": "برای دریافت راهنمایی کلمه عبور اصلی خود آدرس ایملیتان را وارد کنید." + }, + "getMasterPasswordHint": { + "message": "دریافت راهنمای کلمه عبور اصلی" + }, + "continue": { + "message": "ادامه" + }, + "sendVerificationCode": { + "message": "ارسال یک کد تأیید به ایمیل شما" + }, + "sendCode": { + "message": "ارسال کد" + }, + "codeSent": { + "message": "کد ارسال شد" + }, + "verificationCode": { + "message": "کد تایید" + }, + "confirmIdentity": { + "message": "برای ادامه هویت خود را تأیید کنید." + }, + "account": { + "message": "حساب" + }, + "changeMasterPassword": { + "message": "تغییر کلمه عبور اصلی" + }, + "fingerprintPhrase": { + "message": "عبارت اثر انگشت", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "عبارت اثر انگشت حساب شما", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "ورود دو مرحله ای" + }, + "logOut": { + "message": "خروج" + }, + "about": { + "message": "درباره ما" + }, + "version": { + "message": "نسخه" + }, + "save": { + "message": "ذخیره" + }, + "move": { + "message": "انتقال" + }, + "addFolder": { + "message": "افزودن پوشه" + }, + "name": { + "message": "نام" + }, + "editFolder": { + "message": "ويرايش پوشه" + }, + "deleteFolder": { + "message": "حذف پوشه" + }, + "folders": { + "message": "پوشه ها" + }, + "noFolders": { + "message": "هیچ موردی برای نمایش وجود ندارد." + }, + "helpFeedback": { + "message": "کمک و بازخورد" + }, + "sync": { + "message": "همگام سازی" + }, + "syncVaultNow": { + "message": "همگام سازی گاوصندوق" + }, + "lastSync": { + "message": "آخرین همگام سازی:" + }, + "passGen": { + "message": "تولید کلمه عبور" + }, + "generator": { + "message": "تولید کننده", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "به طور خودکار کلمه های عبور قوی و منحصر به فرد برای ورود به سیستم خود ایجاد کنید." + }, + "bitWebVault": { + "message": "گاوصندوق وب Bitwarden" + }, + "importItems": { + "message": "واردن کردن موارد" + }, + "select": { + "message": "انتخاب" + }, + "generatePassword": { + "message": "تولید کلمه عبور" + }, + "regeneratePassword": { + "message": "تولید مجدد کلمه عبور" + }, + "options": { + "message": "گزینه ها" + }, + "length": { + "message": "طول" + }, + "uppercase": { + "message": "حروف بزرگ (A-Z)" + }, + "lowercase": { + "message": "حروف کوچک (a-z)" + }, + "numbers": { + "message": "اعداد (‪0-9‬)" + }, + "specialCharacters": { + "message": "نویسه‌های ویژه (!@#$%^&*)" + }, + "numWords": { + "message": "تعداد کلمات" + }, + "wordSeparator": { + "message": "کلمه جداکننده" + }, + "capitalize": { + "message": "بزرگ کردن", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "شامل عدد" + }, + "minNumbers": { + "message": "حداقل اعداد" + }, + "minSpecial": { + "message": "حداقل حرف خاص" + }, + "avoidAmbChar": { + "message": "از کاراکترهای مبهم اجتناب شود" + }, + "searchVault": { + "message": "جستجوی گاوصندوق" + }, + "edit": { + "message": "ویرایش" + }, + "view": { + "message": "مشاهده" + }, + "noItemsInList": { + "message": "هیچ موردی برای نمایش وجود ندارد." + }, + "itemInformation": { + "message": "اطلاعات مورد" + }, + "username": { + "message": "نام کاربری" + }, + "password": { + "message": "کلمه عبور" + }, + "passphrase": { + "message": "کلمه عبور" + }, + "favorite": { + "message": "مورد علاقه" + }, + "notes": { + "message": "یادداشت ها" + }, + "note": { + "message": "یادداشت" + }, + "editItem": { + "message": "ویرایش مورد" + }, + "folder": { + "message": "پوشه" + }, + "deleteItem": { + "message": "حذف مورد" + }, + "viewItem": { + "message": "مشاهده مورد" + }, + "launch": { + "message": "راه اندازی" + }, + "website": { + "message": "وب سایت" + }, + "toggleVisibility": { + "message": "تغییر قابلیت نمایش" + }, + "manage": { + "message": "مدیریت" + }, + "other": { + "message": "ساير" + }, + "rateExtension": { + "message": "به این افزونه امتیاز دهید" + }, + "rateExtensionDesc": { + "message": "لطفاً با یک بررسی خوب به ما کمک کنید!" + }, + "browserNotSupportClipboard": { + "message": "مرورگر شما از کپی کلیپ بورد آسان پشتیبانی نمی کند. به جای آن به صورت دستی کپی کنید." + }, + "verifyIdentity": { + "message": "تأیید هویت" + }, + "yourVaultIsLocked": { + "message": "گاوصندوق شما قفل است. برای ادامه کلمه عبور اصلی خود را وارد کنید." + }, + "unlock": { + "message": "بازکردن" + }, + "loggedInAsOn": { + "message": "وارد شده با $EMAIL$ در $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "کلمه عبور اصلی نامعتبر است" + }, + "vaultTimeout": { + "message": "متوقف شدن گاو‌صندوق" + }, + "lockNow": { + "message": "الان قفل شود" + }, + "immediately": { + "message": "بلافاصله" + }, + "tenSeconds": { + "message": "۱۰ ثانیه" + }, + "twentySeconds": { + "message": "۲۰ ثانیه" + }, + "thirtySeconds": { + "message": "۳۰ ثانیه" + }, + "oneMinute": { + "message": "۱ دقیقه" + }, + "twoMinutes": { + "message": "۲ دقیقه" + }, + "fiveMinutes": { + "message": "۵ دقیقه" + }, + "fifteenMinutes": { + "message": "۱۵ دقیقه" + }, + "thirtyMinutes": { + "message": "۳۰ دقیقه" + }, + "oneHour": { + "message": "۱ ساعت" + }, + "fourHours": { + "message": "4 ساعت" + }, + "onLocked": { + "message": "هنگام قفل سیستم" + }, + "onRestart": { + "message": "هنگام راه اندازی مجدد" + }, + "never": { + "message": "هرگز" + }, + "security": { + "message": "امنیت" + }, + "errorOccurred": { + "message": "خطایی رخ داده است" + }, + "emailRequired": { + "message": "آدرس ایمیل ضروری است." + }, + "invalidEmail": { + "message": "آدرس ایمیل نامعتبر است." + }, + "masterPassRequired": { + "message": "کلمه عبور اصلی ضروری است." + }, + "masterPassLength": { + "message": "طول کلمه عبور اصلی باید حداقل ۸ کاراکتر باشد." + }, + "masterPassDoesntMatch": { + "message": "کلمه عبور اصلی با تکرار کلمه عبور اصلی مطابقت ندارد." + }, + "newAccountCreated": { + "message": "حساب شما ساختته شد! حالا میتوانید وارد شوید." + }, + "masterPassSent": { + "message": "ما یک ایمیل همراه با راهنمای کلمه عبور اصلی برایتان ارسال کردیم." + }, + "verificationCodeRequired": { + "message": "کد تایید مورد نیاز است." + }, + "invalidVerificationCode": { + "message": "کد تایید نامعتبر" + }, + "valueCopied": { + "message": " کپی شده", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "ناتوان در پرکردن خودکار آیتم انتخاب شده در این صفحه. اطلاعات را کپی و جایگذاری کنید." + }, + "loggedOut": { + "message": "خارج شده" + }, + "loginExpired": { + "message": "جلسه ورود شما منقضی شده است." + }, + "logOutConfirmation": { + "message": "آیا مطمئنید که می‌خواهید خارج شوید؟" + }, + "yes": { + "message": "بله" + }, + "no": { + "message": "خیر" + }, + "unexpectedError": { + "message": "یک خطای غیر منتظره رخ داده است." + }, + "nameRequired": { + "message": "نام ضروری است." + }, + "addedFolder": { + "message": "پوشه اضافه شده" + }, + "changeMasterPass": { + "message": "تغییر کلمه عبور اصلی" + }, + "changeMasterPasswordConfirmation": { + "message": "شما می‌توانید کلمه عبور اصلی خود را در bitwarden.com تغییر دهید. آیا می‌خواهید از سایت بازدید کنید؟" + }, + "twoStepLoginConfirmation": { + "message": "ورودی دو مرحله ای باعث می شود که حساب کاربری شما با استفاده از یک دستگاه دیگر مانند کلید امنیتی، برنامه تأیید هویت، پیامک، تماس تلفنی و یا ایمیل، اعتبار خود را با ایمنی بیشتر ثابت کند. ورودی دو مرحله ای می تواند در bitwarden.com فعال شود. آیا می خواهید از سایت بازدید کنید؟" + }, + "editedFolder": { + "message": "پوشه ویرایش شده" + }, + "deleteFolderConfirmation": { + "message": "آیا از حذف این پوشه اطمینان دارید؟" + }, + "deletedFolder": { + "message": "پوشه حذف شده" + }, + "gettingStartedTutorial": { + "message": "آغاز نمودن آموزش" + }, + "gettingStartedTutorialVideo": { + "message": "برای یادگیری بیشتر نحوه استفاده از افزونه مرورگر آموزش شروع به کار را تماشا کنید." + }, + "syncingComplete": { + "message": "همگام سازی کامل شد" + }, + "syncingFailed": { + "message": "همگام سازی شکست خورد" + }, + "passwordCopied": { + "message": "کلمه عبور کپی شد" + }, + "uri": { + "message": "نشانی اینترنتی" + }, + "uriPosition": { + "message": "آدرس اینترنتی $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "آدرس اینترنتی جدید" + }, + "addedItem": { + "message": "مورد افزوده شده" + }, + "editedItem": { + "message": "مورد ویرایش شده" + }, + "deleteItemConfirmation": { + "message": "آیا مطمئن هستید می خواهید این مورد را حذف کنید؟" + }, + "deletedItem": { + "message": "مورد حذف شده" + }, + "overwritePassword": { + "message": "بازنویسی کلمه عبور" + }, + "overwritePasswordConfirmation": { + "message": "آیا از بازنویسی بر روی پسورد فعلی مطمئن هستید؟" + }, + "overwriteUsername": { + "message": "بازنویسی نام کاربری" + }, + "overwriteUsernameConfirmation": { + "message": "آیا از بازنویسی نام کاربری فعلی مطمئن هستید؟" + }, + "searchFolder": { + "message": "جستجوی پوشه" + }, + "searchCollection": { + "message": "جستجوی مجموعه" + }, + "searchType": { + "message": "نوع جستجو" + }, + "noneFolder": { + "message": "بدون پوشه", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "غیرفعال کردن اعلانیه اضافه کردن ورودی" + }, + "addLoginNotificationDesc": { + "message": "\"افزودن اعلانیه ورود\" به صورت خودکار از شما می خواهد هر بار که برای اولین بار وارد سیستم میشوید ورودی های جدید را در گاوصندوق خود ذخیره کنید." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "پاک‌سازی کلیپ‌ برد", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "مقدار های کپی شده را به صورت خودکار از کلیپ برد خود پاک کنید.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "آیا Bitwarden باید این کلمه عبور را برایتان بخاطر بسپارد؟" + }, + "notificationAddSave": { + "message": "بله، ذخیره کن" + }, + "disableChangedPasswordNotification": { + "message": "غیر فعال کردن اعلان تغییر کلمه عبور" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"اعلانیه کلمه عبور تغییر کرده\" بصورت خودکار شما را از بروزرسانی کلمه عبور در گاوصندوق مطلع میکند هر زمان که شما آن را در یک وبسایت تغییر داده باشید." + }, + "notificationChangeDesc": { + "message": "آیا مایل به بروزرسانی این پسورد در Bitwarden هستید؟" + }, + "notificationChangeSave": { + "message": "بله، بروزرسانی کن" + }, + "disableContextMenuItem": { + "message": "غیر فعال کردن گزینه های منوی متن" + }, + "disableContextMenuItemDesc": { + "message": "گزینه های منوی متن دسترسی سریع به ساخت کلمه عبور و ورود به سیستم برای وبسایت در برگه فعلی را برای شما فراهم میکند." + }, + "defaultUriMatchDetection": { + "message": "بازرسی تطابق URL پیشفرض", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "روش پیش فرض اعمال بازرسی تطابق ‌‌URL را هنگامی که عملی را مثل پر کردن خودکار انتخاب کنید." + }, + "theme": { + "message": "پوسته" + }, + "themeDesc": { + "message": "تغییر رنگ پوسته برنامه." + }, + "dark": { + "message": "تاریک", + "description": "Dark color" + }, + "light": { + "message": "روشن", + "description": "Light color" + }, + "solarizedDark": { + "message": "تاریک خورشیدی", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "صادر کردن گاوصندوق" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "اخطار", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "صادرات گاوصندوق را تأیید کنید" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "این صادرات با استفاده از کلید رمزگذاری حساب شما ، اطلاعات شما را رمزگذاری می کند. اگر حتی کلید رمزگذاری حساب خود را بچرخانید ، باید دوباره صادر کنید چون قادر به رمزگشایی این پرونده صادراتی نخواهید بود." + }, + "encExportAccountWarningDesc": { + "message": "کلیدهای رمزگذاری حساب برای هر حساب کاربری Bitwarden منحصر به فرد است ، بنابراین نمی توانید صادرات رمزگذاری شده را به حساب دیگری وارد کنید." + }, + "exportMasterPassword": { + "message": "کلمه عبور اصلی خود را برای صادرات داده ها از گاوصندوقتان وارد کنید." + }, + "shared": { + "message": "اشتراک گذاری شد" + }, + "learnOrg": { + "message": "درباره سازمانها اطلاعات کسب کنید" + }, + "learnOrgConfirmation": { + "message": "Bitwarden به شما اجازه می دهد با استفاده از یک سازمان، موارد گاوصندوق خود را با دیگران به اشتراک بگذارید. آیا مایل به بازدید از وب سایت bitwarden.com برای کسب اطلاعات بیشتر هستید؟" + }, + "moveToOrganization": { + "message": "انتقال به سازمان" + }, + "share": { + "message": "اشتراک گذاری" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ منتقل شد به $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "سازمانی را انتخاب کنید که می خواهید این مورد را به آن منتقل کنید. انتقال به یک سازمان، مالکیت مورد را به آن سازمان منتقل می کند. پس از انتقال این مورد، دیگر مالک مستقیم آن نخواهید بود." + }, + "learnMore": { + "message": "بیشتر بدانید" + }, + "authenticatorKeyTotp": { + "message": "کلید تأیید کننده (TOTP)" + }, + "verificationCodeTotp": { + "message": "کد تأیید (TOTP)" + }, + "copyVerificationCode": { + "message": "کپی کد تأیید" + }, + "attachments": { + "message": "پیوست ها" + }, + "deleteAttachment": { + "message": "حذف پیوست" + }, + "deleteAttachmentConfirmation": { + "message": "آیا از پاک کردن این پیوست مطمئن هستید؟" + }, + "deletedAttachment": { + "message": "حذف پیوست" + }, + "newAttachment": { + "message": "افزودن پیوست جدید" + }, + "noAttachments": { + "message": "بدون پیوست." + }, + "attachmentSaved": { + "message": "پیوست ذخیره شد." + }, + "file": { + "message": "فایل" + }, + "selectFile": { + "message": "انتخاب یک فایل." + }, + "maxFileSize": { + "message": "بیشترین حجم فایل 500 مگابایت است." + }, + "featureUnavailable": { + "message": "ویژگی موجود نیست" + }, + "updateKey": { + "message": "تا زمانی که کد رمزنگاری را بروز نکنید نمیتوانید از این قابلیت استفاده کنید." + }, + "premiumMembership": { + "message": "عضویت پرمیوم" + }, + "premiumManage": { + "message": "مدیریت عضویت" + }, + "premiumManageAlert": { + "message": "شما میتوانید عضویت خود را در نسخه وب گاوصندوق در bitwarden.com مدیریت کنید. آیا مایل به دیدن وبسایت هستید؟" + }, + "premiumRefresh": { + "message": "نوسازی عضویت" + }, + "premiumNotCurrentMember": { + "message": "شما در حال حاظر کاربر پرمیوم نیستید." + }, + "premiumSignUpAndGet": { + "message": "ثبت نام برای عضویت پرمیوم و گرفتن:" + }, + "ppremiumSignUpStorage": { + "message": "۱ گیگابایت فضای ذخیره سازی رمزنگاری شده." + }, + "ppremiumSignUpTwoStep": { + "message": "گزینه های ورود اضافی دو مرحله ای مانند YubiKey, FIDO U2F و Duo." + }, + "ppremiumSignUpReports": { + "message": "بهداشت کلمه عبور، سلامت اکانت و گزارش های نقض اطلاعات تا صندوق شما امن نگه داشته شود." + }, + "ppremiumSignUpTotp": { + "message": "تولید کننده کد تایید (2FA) از نوع TOTP برای ورود به گاوصندوقتان." + }, + "ppremiumSignUpSupport": { + "message": "اولویت پشتیبانی از مشتری." + }, + "ppremiumSignUpFuture": { + "message": "تمام ویژگی های پرمیوم آینده. به زودی بیشتر!" + }, + "premiumPurchase": { + "message": "خرید پرمیوم" + }, + "premiumPurchaseAlert": { + "message": "شما میوانید عضویت پرمیوم را از وب گاوصندوق bitwarden.com خریداری کنید. مایلید اکنون از وبسایت بازید کنید؟" + }, + "premiumCurrentMember": { + "message": "شما یک عضو پرمیوم هستید!" + }, + "premiumCurrentMemberThanks": { + "message": "برای حمایتتان از Bitwarden سپاسگزاریم." + }, + "premiumPrice": { + "message": "تمامش فقط $PRICE$ در سال!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "نوسازی کامل شد" + }, + "disableAutoTotpCopy": { + "message": "غیرفعال کردن کپی خودکار TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "اگر ورود شما دارای یک کلید تأیید کننده است که به آن متصل شده است، هر زمان که بصورت خودکار وارد سایت شوید کد تأیید TOTP به صورت خودکار به کلیپ بورد شما کپی می شود." + }, + "disableAutoBiometricsPrompt": { + "message": "در هنگام راه اندازی، درخواست biometrics نکنید." + }, + "premiumRequired": { + "message": "در نسخه پرمیوم کار میکند" + }, + "premiumRequiredDesc": { + "message": "برای استفاده از این ویژگی عضویت پرمیوم لازم است." + }, + "enterVerificationCodeApp": { + "message": "کد ۶ رقمی تایید را از برنامه تایید کننده وارد کنید." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "ایمیل تایید به $EMAIL$ ارسال شد.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "مرا به خاطر بسپار" + }, + "sendVerificationCodeEmailAgain": { + "message": "ارسال دوباره ایمیل کد تایید" + }, + "useAnotherTwoStepMethod": { + "message": "استفاده از روش ورود دو مرحله ای دیگر" + }, + "insertYubiKey": { + "message": "YubiKey خود را وارد پورت USB رایانه کنید، بعد دکمه آن را بفشارید." + }, + "insertU2f": { + "message": "کلید امنیتی خود را وارد پورت USB رایانه کنید، اگر دکمه ای دارد آن را بفشارید." + }, + "webAuthnNewTab": { + "message": "تأیید WebAuthn 2FA را در برگه جدید ادامه دهید." + }, + "webAuthnNewTabOpen": { + "message": "باز کردن زبانه جدید" + }, + "webAuthnAuthenticate": { + "message": "تأیید اعتبار در WebAuthn" + }, + "loginUnavailable": { + "message": "ورود به سیستم موجود نیست" + }, + "noTwoStepProviders": { + "message": "این حساب با سیستم دو مرحله ورود فعال است، با این حال، هیچ یک از ارائه دهندگان دو مرحله ای پیکربندی شده توسط این مرورگر وب پشتیبانی نمی شوند." + }, + "noTwoStepProviders2": { + "message": "لطفا از یک مرورگر وب پشتیبانی شده (مانند کروم) استفاده کنید و / یا ارائه دهندگان اضافی را که در مرورگر وب بهتر پشتیانی میکنند را اضافه کنید (مانند یک برنامه تأیید کننده هویت)." + }, + "twoStepOptions": { + "message": "گزینه های ورود دو مرحله ای" + }, + "recoveryCodeDesc": { + "message": "دسترسی به تمامی ارائه دهندگان دو مرحله ای را از دست داده اید؟ از کد بازیابی خود برای غیرفعال سازی ارائه دهندگان دو مرحله ای از حسابتان استفاده کنید." + }, + "recoveryCodeTitle": { + "message": "کد بازیابی" + }, + "authenticatorAppTitle": { + "message": "برنامه تأیید کننده" + }, + "authenticatorAppDesc": { + "message": "از یک اپ تایید کننده (همانند Authy یا Google Authenticator) استفاده کنید تا کدهای تایید بر پایه زمان تولید کنید.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "کلید امنیت YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "از یک YubiKey برای دسترسی به حسابتان استفاده کنید. همراه با دستگاه های YubiKey 4،4 Nano، NEO کار میکند." + }, + "duoDesc": { + "message": "تایید کنید همراه با Duo Security از اپ موبایل Dou استفاده کنید، پیامک،تماس تلفنی، یا کلید امنیتی U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo Security را برای سازماندهی خود با استفاده از برنامه Duo Mobile، SMS، تماس تلفنی یا کلید امنیتی U2F تأیید کنید.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn\n" + }, + "webAuthnDesc": { + "message": "برای دسترسی به حساب خود از هر کلید امنیتی فعال شده WebAuthn استفاده کنید." + }, + "emailTitle": { + "message": "ایمیل" + }, + "emailDesc": { + "message": "کد تایید برایتان فرستاده می شود." + }, + "selfHostedEnvironment": { + "message": "محیط خود میزبان" + }, + "selfHostedEnvironmentFooter": { + "message": "آدرس اینترنتی پایه فرضی نصب Bitwarden میزبانی شده را مشخص کنید." + }, + "customEnvironment": { + "message": "محیط های سفارشی" + }, + "customEnvironmentFooter": { + "message": "برای کاربران پیشرفته. شما می توانید آدرس پایه هر سرویس را مستقل تعیین کنید." + }, + "baseUrl": { + "message": "آدرس سرور" + }, + "apiUrl": { + "message": "آدرس سرور API" + }, + "webVaultUrl": { + "message": "آدرس سرور گاوصندوق وب" + }, + "identityUrl": { + "message": "آدرس سرور شناسایی" + }, + "notificationsUrl": { + "message": "اعلانهای آدرس سرور" + }, + "iconsUrl": { + "message": "آدرس سرور آیکون ها" + }, + "environmentSaved": { + "message": "آدرس های اینترنتی محیط ذخیره شد." + }, + "enableAutoFillOnPageLoad": { + "message": "فعال کردن پرکردن خودکار هنگام بارگذاری صفحه" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "اگر یک فرم ورودی شناسایی شود، وقتی صفحه وب بارگذاری می شود، به صورت اتوماتیک انجام می شود." + }, + "experimentalFeature": { + "message": "در حال حاضر این یک ویژگی آزمایشی است. با مسئولیت خود استفاده کنید." + }, + "defaultAutoFillOnPageLoad": { + "message": "تنظیم خودکار پیش فرض برای موارد ورود به سیستم" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "پس از فعال کردن پرکردن خودکار بارگذاری صفحه، می توانید این ویژگی را برای موارد ورود به سیستم جداگانه فعال یا غیرفعال کنید. این تنظیمات پیش فرض برای موارد ورود به سیستم است که به طور جداگانه پیکربندی نشده اند." + }, + "itemAutoFillOnPageLoad": { + "message": "پر کردن خودکار بارگذاری صفحه (درصورت فعال بودن در گزینه ها)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "استفاده از تنظيمات پيشفرض" + }, + "autoFillOnPageLoadYes": { + "message": "بارگذاری صفحه را به طور خودکار پر کن" + }, + "autoFillOnPageLoadNo": { + "message": "بارگذاری صفحه را به طور خودکار پر نکن" + }, + "commandOpenPopup": { + "message": "بازکردن پنجره گاوصندوق" + }, + "commandOpenSidebar": { + "message": "بازکردن گاوصندوق در نوار کناری" + }, + "commandAutofillDesc": { + "message": "آخرین ورودی مورد استفاده برای وب سایت فعلی را به صورت خودکار پر کنید." + }, + "commandGeneratePasswordDesc": { + "message": "یک کلمه عبور تصادفی جدید ایجاد کنید و آن را در کلیپ بورد کپی کنید." + }, + "commandLockVaultDesc": { + "message": "قفل گاوصندوق" + }, + "privateModeWarning": { + "message": "پشتیبانی حالت خصوصی آزمایشی است و برخی از ویژگی‌ها محدود هستند." + }, + "customFields": { + "message": "فیلدهای سفارشی" + }, + "copyValue": { + "message": "کپی مقدار" + }, + "value": { + "message": "مقدار" + }, + "newCustomField": { + "message": "فیلد سفارشی جدید" + }, + "dragToSort": { + "message": "برای مرتب سازی بکشید" + }, + "cfTypeText": { + "message": "متن" + }, + "cfTypeHidden": { + "message": "مخفی" + }, + "cfTypeBoolean": { + "message": "بولین" + }, + "cfTypeLinked": { + "message": "لینک شده", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "ارزش لینک شده", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "در خارج از پنجره پاپ آپ کلیک کنید که ایملیتان بررسی شود برای کد تأییدیه که باعث میشود این پنجره بسته شود. آیا می خواهید این پاپ آپ را در یک پنجره جدید باز کنید تا آن را نبندید؟" + }, + "popupU2fCloseMessage": { + "message": "این مرورگر نمیتواند درخواستهای U2F را در این پنجره پاپ آپ پردازش کند. آیا می خواهید این پنجره را در یک پنجره جدید باز کنید تا بتوانید با استفاده از U2F وارد شوید؟" + }, + "disableFavicon": { + "message": "غیرفعال سازی آیکون های وبسایت" + }, + "disableFaviconDesc": { + "message": "آیکون های وبسایت یک تصویر قابل تشخیص در کنار هر داده ورودی ارائه میدهد." + }, + "disableBadgeCounter": { + "message": "شمارنده نشان را غیرفعال کن" + }, + "disableBadgeCounterDesc": { + "message": "شمارنده نشان، نشان می دهد که چه تعداد ورود به سیستم برای صفحه فعلی در گاو‌صندوق خود دارید." + }, + "cardholderName": { + "message": "نام صاحب کارت" + }, + "number": { + "message": "شماره" + }, + "brand": { + "message": "نام تجاری" + }, + "expirationMonth": { + "message": "ماه انقضاء" + }, + "expirationYear": { + "message": "سال انقضاء" + }, + "expiration": { + "message": "انقضاء" + }, + "january": { + "message": "ژانویه" + }, + "february": { + "message": "فوریه" + }, + "march": { + "message": "مارس" + }, + "april": { + "message": "آوریل" + }, + "may": { + "message": "مِی" + }, + "june": { + "message": "ژوئن" + }, + "july": { + "message": "جولای" + }, + "august": { + "message": "آگوست‌" + }, + "september": { + "message": "سپتامبر" + }, + "october": { + "message": "اکتبر" + }, + "november": { + "message": "نوامبر" + }, + "december": { + "message": "دسامبر" + }, + "securityCode": { + "message": "کد امنیتی" + }, + "ex": { + "message": "سابق." + }, + "title": { + "message": "عنوان" + }, + "mr": { + "message": "آقا" + }, + "mrs": { + "message": "خانم" + }, + "ms": { + "message": "خانم" + }, + "dr": { + "message": "دکتر" + }, + "firstName": { + "message": "نام" + }, + "middleName": { + "message": "نام میانی" + }, + "lastName": { + "message": "نام خانوادگی" + }, + "fullName": { + "message": "نام کامل" + }, + "identityName": { + "message": "نام شناسایی" + }, + "company": { + "message": "شرکت" + }, + "ssn": { + "message": "شماره امنیتی اجتماعی" + }, + "passportNumber": { + "message": "شماره پاسپورت" + }, + "licenseNumber": { + "message": "شماره مجوز" + }, + "email": { + "message": "ایمیل" + }, + "phone": { + "message": "تلفن" + }, + "address": { + "message": "آدرس" + }, + "address1": { + "message": "نشانی ۱" + }, + "address2": { + "message": "نشانی ۲" + }, + "address3": { + "message": "نشانی ۳" + }, + "cityTown": { + "message": "شهر / شهرک" + }, + "stateProvince": { + "message": "ایالت / استان" + }, + "zipPostalCode": { + "message": "کد پستی" + }, + "country": { + "message": "کشور" + }, + "type": { + "message": "نوع" + }, + "typeLogin": { + "message": "ورود" + }, + "typeLogins": { + "message": "ورود" + }, + "typeSecureNote": { + "message": "یادداشت امن" + }, + "typeCard": { + "message": "کارت" + }, + "typeIdentity": { + "message": "مشخصات" + }, + "passwordHistory": { + "message": "تاریخچه کلمه عبور" + }, + "back": { + "message": "بازگشت" + }, + "collections": { + "message": "مجموعه ها" + }, + "favorites": { + "message": "مورد علاقه" + }, + "popOutNewWindow": { + "message": "به یک پنجره جدید پاپ بزنید" + }, + "refresh": { + "message": "تازه کردن" + }, + "cards": { + "message": "کارتها" + }, + "identities": { + "message": "مشخصات" + }, + "logins": { + "message": "ورود" + }, + "secureNotes": { + "message": "یادداشت های امن" + }, + "clear": { + "message": "پاک کردن", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "بررسی اینکه که آیا کلمه عبور افشا شده است." + }, + "passwordExposed": { + "message": "This password has been exposed in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "این کلمه عبور در هیچ رخنه داده ای شناخته نشده است. باید برای امنیت از آن استفاده کنید." + }, + "baseDomain": { + "message": "دامنه پایه", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "نام دامنه", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "میزبان", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "دقیق" + }, + "startsWith": { + "message": "شروع می شود با" + }, + "regEx": { + "message": "عبارت منظم", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "بازرسی تطابق", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "بازرسی تطابق پیشفرض", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "گزینه های تبدیل" + }, + "toggleCurrentUris": { + "message": "تغییر وضعیت نشانی های اینترنتی فعلی", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "نشانی اینترنتی فعلی", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "سازماندهی", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "انواع" + }, + "allItems": { + "message": "تمام موارد" + }, + "noPasswordsInList": { + "message": "هیچ کلمه عبوری در لیست وجود ندارد." + }, + "remove": { + "message": "حذف" + }, + "default": { + "message": "پیش فرض" + }, + "dateUpdated": { + "message": "بروزرسانی شد", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "کلمه عبور بروزرسانی شد", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "آیا جدا میخواهید از گزینه \"هرگز\" استفاده کنید؟ تنظیم کردن کردن گزینه قفل به \"هرگز\" کلیدهای رمزنگاری گاوصندوقتان را بر روی دستگاه شما ذخیره خواهد کرد. اگر از این گزینه استفاده میکنید باید اطمینان داشته باشید که دستگاه شما کاملا محافظت شده است." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "هیچ مجموعه ای برای لیست کردن وجود ندارد." + }, + "ownership": { + "message": "مالکیت" + }, + "whoOwnsThisItem": { + "message": "چه کسی مالک این مورد است؟" + }, + "strong": { + "message": "قوی", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "خوب", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "ضعیف", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "کلمه عبور اصلی ضعیف" + }, + "weakMasterPasswordDesc": { + "message": "کلمه عبور اصلی که شما انتخاب کرده اید ضعیف است. شما باید یک کلمه عبور اصلی قوی انتخاب کنید (یا یک عبارت عبور) تا به درستی از اکانت Bitwarden خود محافظت کنید. آیا مطمئن هستید می‌خواهید از این کلمه عبور اصلی استفاده کنید؟ " + }, + "pin": { + "message": "پین", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "بازکردن با پین" + }, + "setYourPinCode": { + "message": "پین کد خود را برای باز کردن بیت واردن خود استفاده کنید. اگر به صورت کامل از حساب خود خارج شوید تنظیمات پین شما ریست می شود." + }, + "pinRequired": { + "message": "کد پین الزامیست." + }, + "invalidPin": { + "message": "کد پین معتبر نیست. " + }, + "unlockWithBiometrics": { + "message": "با استفاده از بیومتریک باز کنید" + }, + "awaitDesktop": { + "message": "در انتظار تأیید از دسکتاپ" + }, + "awaitDesktopDesc": { + "message": "لطفاً استفاده از بیومتریک را در برنامه دسکتاپ Bitwarden تأیید کنید تا بیومتریک را برای مرورگر فعال کنید." + }, + "lockWithMasterPassOnRestart": { + "message": "در زمان شروع مجدد مرورگر، با رمز اصلی قفل کن" + }, + "selectOneCollection": { + "message": "شما باید حداقل یک مجموعه را انتخاب کنید." + }, + "cloneItem": { + "message": "مورد شبیه" + }, + "clone": { + "message": "شبیه سازی" + }, + "passwordGeneratorPolicyInEffect": { + "message": "یک یا چند خط مشی سازمان بر تنظیمات تولیدکننده شما تأثیر می گذارد." + }, + "vaultTimeoutAction": { + "message": "عمل متوقف شدن گاو‌صندوق" + }, + "lock": { + "message": "قفل", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "زباله‌ها", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "جستجوی زباله‌ها" + }, + "permanentlyDeleteItem": { + "message": "حذف دائمی مورد" + }, + "permanentlyDeleteItemConfirmation": { + "message": "آیا مطمئن هستید که می خواهید این مورد را برای همیشه حذف کنید؟" + }, + "permanentlyDeletedItem": { + "message": "مورد برای همیشه حذف شد" + }, + "restoreItem": { + "message": "بازیابی مورد" + }, + "restoreItemConfirmation": { + "message": "آیا مطمئن هستید می خواهید این مورد را بازیابی کنید؟" + }, + "restoredItem": { + "message": "مورد بازیابی شد" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "خروج از سیستم تمام دسترسی ها به گاو‌صندوق شما را از بین می برد و نیاز به احراز هویت آنلاین پس از مدت زمان توقف دارد. آیا مطمئن هستید که می خواهید از این تنظیمات استفاده کنید؟" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "تایید عمل توقف" + }, + "autoFillAndSave": { + "message": "پرکردن خودکار و ذخیره" + }, + "autoFillSuccessAndSavedUri": { + "message": "مورد خودکار پر شد و آدرس اینترنتی ذخیره شد" + }, + "autoFillSuccess": { + "message": "مورد خودکار پر شد" + }, + "setMasterPassword": { + "message": "تنظیم کلمه عبور اصلی" + }, + "masterPasswordPolicyInEffect": { + "message": "یک یا چند سیاست سازمانی برای تأمین شرایط زیر به کلمه عبور اصلی شما احتیاج دارد:" + }, + "policyInEffectMinComplexity": { + "message": "حداقل نمره پیچیدگی $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "حداقل طول $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "حاوی یک یا چند کاراکتر بزرگ" + }, + "policyInEffectLowercase": { + "message": "حاوی یک یا چند کاراکتر کوچک" + }, + "policyInEffectNumbers": { + "message": "حاوی یک یا چند عدد بیشتر" + }, + "policyInEffectSpecial": { + "message": "حاوی یک یا چند کاراکتر خاص زیر است $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "کلمه عبور اصلی جدید شما از شرایط سیاست پپیروی نمی کند." + }, + "acceptPolicies": { + "message": "با علامت زدن این کادر با موارد زیر موافقت می کنید:" + }, + "acceptPoliciesError": { + "message": "شرایط خدمات و سیاست حفظ حریم خصوصی تأیید نشده است." + }, + "termsOfService": { + "message": "شرایط استفاده از خدمات" + }, + "privacyPolicy": { + "message": "سیاست حفظ حریم خصوصی" + }, + "hintEqualsPassword": { + "message": "نکته کلمه عبور شما نمی تواند همان کلمه عبور شما باشد." + }, + "ok": { + "message": "تایید" + }, + "desktopSyncVerificationTitle": { + "message": "تأیید همگام سازی دسکتاپ" + }, + "desktopIntegrationVerificationText": { + "message": "لطفاً تأیید کنید که برنامه دسکتاپ این اثر انگشت را نشان می دهد:" + }, + "desktopIntegrationDisabledTitle": { + "message": "ادغام مرورگر فعال نیست" + }, + "desktopIntegrationDisabledDesc": { + "message": "ادغام مرورگر در برنامه دسکتاپ Bitwarden فعال نیست. لطفاً آن را در تنظیمات موجود در برنامه دسکتاپ فعال کنید." + }, + "startDesktopTitle": { + "message": "برنامه دسکتاپ Bitwarden را شروع کنید" + }, + "startDesktopDesc": { + "message": "قبل از استفاده از این عملکرد، برنامه دسکتاپ Bitwarden باید شروع شود." + }, + "errorEnableBiometricTitle": { + "message": "بیومتریک فعال نیست" + }, + "errorEnableBiometricDesc": { + "message": "فعالیت توسط برنامه دسکتاپ لغو شد" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "برنامه دسکتاپ کانال ارتباط امن را نامعتبر کرد. لطفاً این عملیات را دوباره امتحان کنید" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "ارتباط دسکتاپ قطع شد" + }, + "nativeMessagingWrongUserDesc": { + "message": "برنامه دسکتاپ به یک حساب دیگر وارد شده است. لطفاً اطمینان حاصل کنید که هر دو برنامه به یک حساب وارد شده اند." + }, + "nativeMessagingWrongUserTitle": { + "message": "عدم تطابق حساب" + }, + "biometricsNotEnabledTitle": { + "message": "بیومتریک فعال نیست" + }, + "biometricsNotEnabledDesc": { + "message": "بیومتریک مرورگر ابتدا نیاز به فعالسازی بیومتریک دسکتاپ در تنظیمات دارد." + }, + "biometricsNotSupportedTitle": { + "message": "بیومتریک پشتیبانی نمی شود" + }, + "biometricsNotSupportedDesc": { + "message": "بیومتریک مرورگر در این دستگاه پشتیبانی نمی شود." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "مجوز ارائه نشده است" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "بدون اجازه ارتباط با برنامه دسکتاپ Bitwarden ، نمی توانیم بیومتریک را در افزونه مرورگر ارائه دهیم. لطفا دوباره تلاش کنید." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "خطای درخواست مجوز" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "این عمل را نمی توان در نوار کناری انجام داد، لطفاً اقدام را در پنجره بازشو یا پنجره بازخوانی کنید." + }, + "personalOwnershipSubmitError": { + "message": "به دلیل خط مشی Enterprise ، برای ذخیره موارد در گاوصندوق شخصی خود محدود شده اید. گزینه مالکیت را به یک سازمان تغییر دهید و مجموعه های موجود را انتخاب کنید." + }, + "personalOwnershipPolicyInEffect": { + "message": "خط مشی سازمانی بر تنظیمات مالکیت شما تأثیر می گذارد." + }, + "excludedDomains": { + "message": "دامنه های مستثنی" + }, + "excludedDomainsDesc": { + "message": "Bitwarden برای ذخیره جزئیات ورود به سیستم این دامنه ها سوال نمی‌کند. برای اینکه تغییرات اعمال شود باید صفحه را تازه کنید." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ دامنه معتبری نیست", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "ارسال", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "ارسال ها را جستجو کن", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "افزودن ارسال", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "متن" + }, + "sendTypeFile": { + "message": "فایل" + }, + "allSends": { + "message": "همه ارسال ها", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "به حداکثر تعداد دسترسی رسیده است", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "منقضی شده" + }, + "pendingDeletion": { + "message": "در انتظار حذف" + }, + "passwordProtected": { + "message": "محافظت ‌شده با کلمه عبور" + }, + "copySendLink": { + "message": "پیوند ارسال را کپی کن", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "حذف کلمه عبور" + }, + "delete": { + "message": "حذف" + }, + "removedPassword": { + "message": "کلمه عبور حذف شد" + }, + "deletedSend": { + "message": "ارسال پاک شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "ارسال پیوند", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "غیرفعال شد" + }, + "removePasswordConfirmation": { + "message": "مطمئنید می‌خواهید این کلمه عبور حذف شود؟" + }, + "deleteSend": { + "message": "ارسال پاک شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "آیا مطمئن هستید می خواهید این ارسال را حذف کنید؟", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "ویرایش ارسال", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "این چه نوع ارسالی است؟", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "یک نام دوستانه برای توصیف این ارسال.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "فایلی که می خواهید ارسال کنید." + }, + "deletionDate": { + "message": "تاریخ حذف" + }, + "deletionDateDesc": { + "message": "ارسال در تاریخ و ساعت مشخص شده برای همیشه حذف خواهد شد.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "تاريخ انقضاء" + }, + "expirationDateDesc": { + "message": "در صورت تنظیم، دسترسی به این ارسال در تاریخ و ساعت مشخص شده منقضی می شود.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "۱ روز" + }, + "days": { + "message": "$DAYS$ روز", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "سفارشی" + }, + "maximumAccessCount": { + "message": "تعداد دسترسی حداکثر" + }, + "maximumAccessCountDesc": { + "message": "در صورت تنظیم، با رسیدن به حداکثر تعداد دسترسی، کاربران دیگر نمی توانند به این ارسال دسترسی پیدا کنند.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "به صورت اختیاری برای دسترسی کاربران به این ارسال به یک کلمه عبور نیاز دارید.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "یادداشت های خصوصی در مورد این ارسال.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "این ارسال را غیرفعال کنید تا کسی نتواند به آن دسترسی پیدا کند.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "پس از ذخیره، این پیوند ارسال را به کلیپ بورد کپی کن.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "متنی که می خواهید ارسال کنید." + }, + "sendHideText": { + "message": "متن این ارسال را به طور پیش فرض پنهان کن.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "تعداد دسترسی فعلی" + }, + "createSend": { + "message": "ساختن ارسال جدید", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "کلمه عبور جدید" + }, + "sendDisabled": { + "message": "ارسال غیرفعال شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "به دلیل خط مشی سازمانی، شما فقط می توانید ارسال موجود را حذف کنید.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "ارسال جدید ساخته شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "ارسال جدید ویرایش شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "برای انتخاب پرونده، پسوند را در نوار کناری باز کنید (در صورت امکان) یا با کلیک بر روی این آگهی به پنجره جدیدی باز شوید." + }, + "sendFirefoxFileWarning": { + "message": "برای انتخاب یک فایل با استفاده از Firefox، افزونه را در نوار کناری باز کنید یا با کلیک بر روی این بنر به پنجره جدید باز شوید." + }, + "sendSafariFileWarning": { + "message": "برای انتخاب فایلی با استفاده از Safari، با کلیک روی این بنر به پنجره جدیدی باز شوید." + }, + "sendFileCalloutHeader": { + "message": "قبل از اینکه شروع کنی" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "برای استفاده از انتخابگر تاریخ به سبک تقویم", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "اینجا کلیک کنید", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "برای خروج از پنجره خود.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "تاریخ انقضا ارائه شده معتبر نیست." + }, + "deletionDateIsInvalid": { + "message": "تاریخ حذف ارائه شده معتبر نیست." + }, + "expirationDateAndTimeRequired": { + "message": "تاریخ انقضا و زمان لازم است." + }, + "deletionDateAndTimeRequired": { + "message": "تاریخ و زمان حذف لازم است." + }, + "dateParsingError": { + "message": "هنگام ذخیره حذف و تاریخ انقضا شما خطایی روی داد." + }, + "hideEmail": { + "message": "آدرس ایمیلم را از گیرندگان مخفی کن." + }, + "sendOptionsPolicyInEffect": { + "message": "یک یا چند سیاست سازمان بر گزینه های ارسال شما تأثیر می گذارد." + }, + "passwordPrompt": { + "message": "کلمه عبور اصلی دوباره تولید می شود" + }, + "passwordConfirmation": { + "message": "تأیید کلمه عبور اصلی" + }, + "passwordConfirmationDesc": { + "message": "این عمل محافظت می شود. برای ادامه، لطفاً کلمه ورود اصلی خود را دوباره وارد کنید تا هویتان را تأیید کنید." + }, + "emailVerificationRequired": { + "message": "تایید ایمیل لازم است" + }, + "emailVerificationRequiredDesc": { + "message": "برای استفاده از این ویژگی باید ایمیل خود را تأیید کنید. می توانید ایمیل خود را در گاوصندوق وب تأیید کنید." + }, + "updatedMasterPassword": { + "message": "کلمه عبور اصلی بروز شد" + }, + "updateMasterPassword": { + "message": "بروزرسانی کلمه عبور اصلی" + }, + "updateMasterPasswordWarning": { + "message": "کلمه عبور اصلی شما اخیراً توسط سرپرست سازمانتان تغییر کرده است. برای دسترسی به گاوصندوق، باید همین حالا کلمه عبور اصلی خود را به روز کنید. در صورت ادامه، شما از نشست فعلی خود خارج می شوید و باید دوباره وارد سیستم شوید. نشست فعال در دستگاه های دیگر ممکن است تا یک ساعت همچنان فعال باقی بمانند." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "ثبت نام خودکار" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "این سازمان دارای خط مشی سازمانی ای است که به طور خودکار شما را در بازنشانی کلمه عبور ثبت نام می کند. این ثبت نام به مدیران سازمان اجازه می دهد تا کلمه عبور اصلی شما را تغییر دهند." + }, + "selectFolder": { + "message": "پوشه را انتخاب کنید..." + }, + "ssoCompleteRegistration": { + "message": "برای تکمیل ورود به سیستم با SSO ، لطفاً یک کلمه عبور اصلی برای دسترسی و محافظت از گاوصندوق خود تنظیم کنید." + }, + "hours": { + "message": "ساعت" + }, + "minutes": { + "message": "دقیقه" + }, + "vaultTimeoutPolicyInEffect": { + "message": "خط مشی های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می گذارد. حداکثر زمان مجاز گاوصندوق $HOURS$ ساعت و $MINUTES$ دقیقه است", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "مهلت زمانی شما بیش از محدودیت های تعیین شده توسط سازمانتان است." + }, + "vaultExportDisabled": { + "message": "صادرات گاوصندوق غیرفعال شده است" + }, + "personalVaultExportPolicyInEffect": { + "message": "یک یا چند خط مشی سازمان از صادرات گاوصندوق شخصی شما جلوگیری می کند." + }, + "copyCustomFieldNameInvalidElement": { + "message": "شناسایی عنصر فرم معتبر امکان پذیر نیست. به جای آن سعی کنید HTML را بررسی کنید." + }, + "copyCustomFieldNameNotUnique": { + "message": "شناسه منحصر به فردی یافت نشد." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ در حال استفاده از SSO با یک سرور کلید خود میزبان است. برای ورود اعضای این سازمان دیگر نیازی به کلمه عبور اصلی نیست.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "ترک سازمان" + }, + "removeMasterPassword": { + "message": "پاک کردن کلمه عبور اصلی" + }, + "removedMasterPassword": { + "message": "کلمه عبور اصلی پاک شد." + }, + "leaveOrganizationConfirmation": { + "message": "آيا مطمئن هستيد که می خواهيد سازمان های انتخاب شده را ترک کنيد؟" + }, + "leftOrganization": { + "message": "شما از سازمان ها خارج شده اید." + }, + "toggleCharacterCount": { + "message": "تغییر تعداد کاراکترها" + }, + "sessionTimeout": { + "message": "زمان نشست شما به پایان رسید. لطفاً برگردید و دوباره وارد سیستم شوید." + }, + "exportingPersonalVaultTitle": { + "message": "صادرات گاو‌صندوق شخصی" + }, + "exportingPersonalVaultDescription": { + "message": "فقط موارد گاو‌صندوق شخصی مرتبط با $EMAIL$ صادر خواهد شد. موارد گاو‌صندوق سازمان شامل نخواهد شد.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "خطا" + }, + "regenerateUsername": { + "message": "ایجاد مجدد نام کاربری" + }, + "generateUsername": { + "message": "ایجاد نام کاربری" + }, + "usernameType": { + "message": "نوع نام کاربری" + }, + "plusAddressedEmail": { + "message": "به علاوه ایمیل آدرس داده شده", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "از قابلیت های آدرس دهی فرعی ارائه دهنده ایمیل خود استفاده کنید." + }, + "catchallEmail": { + "message": "رایانامه همه‌گیر" + }, + "catchallEmailDesc": { + "message": "از صندوق ورودی پیکربندی شده دامنه خود استفاده کنید." + }, + "random": { + "message": "تصادفی" + }, + "randomWord": { + "message": "کلمه تصادفی" + }, + "websiteName": { + "message": "نام وب سایت" + }, + "whatWouldYouLikeToGenerate": { + "message": "چه چیزی دوست دارید تولید کنید؟" + }, + "passwordType": { + "message": "نوع گذرواژه" + }, + "service": { + "message": "خدمت" + } +} diff --git a/apps/browser/src/_locales/fi/messages.json b/apps/browser/src/_locales/fi/messages.json new file mode 100644 index 0000000000..bf604cab16 --- /dev/null +++ b/apps/browser/src/_locales/fi/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden – Ilmainen salasananhallinta", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Turvallinen ja ilmainen salasanojen hallinta kaikille laitteillesi.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Kirjaudu sisään tai luo uusi tili päästäksesi salattuun holviisi." + }, + "createAccount": { + "message": "Luo tili" + }, + "login": { + "message": "Kirjaudu" + }, + "enterpriseSingleSignOn": { + "message": "Yrityksen kertakirjautuminen (SSO)" + }, + "cancel": { + "message": "Peruuta" + }, + "close": { + "message": "Sulje" + }, + "submit": { + "message": "Jatka" + }, + "emailAddress": { + "message": "Sähköpostiosoite" + }, + "masterPass": { + "message": "Pääsalasana" + }, + "masterPassDesc": { + "message": "Pääsalasanalla pääset käsiksi holviisi. On erittäin tärkeää, että muistat pääsalasanasi, koska sen palautus ei ole mahdollista, jos unohdat sen." + }, + "masterPassHintDesc": { + "message": "Pääsalasanan vihje voi auttaa sinua muistamaan unohtamasi salasanan." + }, + "reTypeMasterPass": { + "message": "Syötä pääsalasana uudelleen" + }, + "masterPassHint": { + "message": "Pääsalasanan vihje (valinnainen)" + }, + "tab": { + "message": "Välilehti" + }, + "myVault": { + "message": "Oma holvi" + }, + "tools": { + "message": "Työkalut" + }, + "settings": { + "message": "Asetukset" + }, + "currentTab": { + "message": "Nykyinen välilehti" + }, + "copyPassword": { + "message": "Kopioi salasana" + }, + "copyNote": { + "message": "Kopioi merkinnät" + }, + "copyUri": { + "message": "Kopioi URI" + }, + "copyUsername": { + "message": "Kopioi käyttäjätunnus" + }, + "copyNumber": { + "message": "Kopioi numero" + }, + "copySecurityCode": { + "message": "Kopioi turvakoodi" + }, + "autoFill": { + "message": "Automaattinen täyttö" + }, + "generatePasswordCopied": { + "message": "Luo salasana (leikepöydälle)" + }, + "copyElementIdentifier": { + "message": "Kopioi lisäkentän nimi" + }, + "noMatchingLogins": { + "message": "Ei tunnistettuja kirjautumistietoja." + }, + "unlockVaultMenu": { + "message": "Avaa holvisi" + }, + "loginToVaultMenu": { + "message": "Kirjaudu holviisi" + }, + "autoFillInfo": { + "message": "Selaimen avoimelle välilehdelle ei ole automaattisesti täytettäviä kirjautumistietoja." + }, + "addLogin": { + "message": "Lisää kirjautumistieto" + }, + "addItem": { + "message": "Lisää kohde" + }, + "passwordHint": { + "message": "Salasanavihje" + }, + "enterEmailToGetHint": { + "message": "Syötä tilisi sähköpostiosoite saadaksesi pääsalasanan vihjeen." + }, + "getMasterPasswordHint": { + "message": "Pyydä pääsalasanan vihjettä" + }, + "continue": { + "message": "Jatka" + }, + "sendVerificationCode": { + "message": "Lähetä vahvistuskoodi sähköpostiisi" + }, + "sendCode": { + "message": "Lähetä koodi" + }, + "codeSent": { + "message": "Koodi lähetetty" + }, + "verificationCode": { + "message": "Todennuskoodi" + }, + "confirmIdentity": { + "message": "Vahvista henkilöllisyytesi jatkaaksesi." + }, + "account": { + "message": "Käyttäjätili" + }, + "changeMasterPassword": { + "message": "Vaihda pääsalasana" + }, + "fingerprintPhrase": { + "message": "Tunnistelauseke", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Tilisi tunnistelauseke", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Kaksivaiheinen kirjautuminen" + }, + "logOut": { + "message": "Kirjaudu ulos" + }, + "about": { + "message": "Tietoja" + }, + "version": { + "message": "Versio" + }, + "save": { + "message": "Tallenna" + }, + "move": { + "message": "Siirrä" + }, + "addFolder": { + "message": "Lisää kansio" + }, + "name": { + "message": "Nimi" + }, + "editFolder": { + "message": "Muokkaa kansiota" + }, + "deleteFolder": { + "message": "Poista kansio" + }, + "folders": { + "message": "Kansiot" + }, + "noFolders": { + "message": "Ei näytettäviä kansioita." + }, + "helpFeedback": { + "message": "Tuki ja palaute" + }, + "sync": { + "message": "Synkronointi" + }, + "syncVaultNow": { + "message": "Synkronoi holvi nyt" + }, + "lastSync": { + "message": "Viimeisin synkronointi:" + }, + "passGen": { + "message": "Salasanageneraattori" + }, + "generator": { + "message": "Generaattori", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Luo kirjautumistiedoillesi automaattisesti vahvoja, ainutlaatuisia salasanoja." + }, + "bitWebVault": { + "message": "Bitwardenin verkkoholvi" + }, + "importItems": { + "message": "Tuo kohteita" + }, + "select": { + "message": "Valitse" + }, + "generatePassword": { + "message": "Luo salasana" + }, + "regeneratePassword": { + "message": "Luo uusi salasana" + }, + "options": { + "message": "Lisäasetukset" + }, + "length": { + "message": "Pituus" + }, + "uppercase": { + "message": "Isot kirjaimet (A-Ö)" + }, + "lowercase": { + "message": "Pienet kirjaimet (a-ö)" + }, + "numbers": { + "message": "Numerot (0-9)" + }, + "specialCharacters": { + "message": "Erikoismerkit (!@#$%^&*)" + }, + "numWords": { + "message": "Sanojen määrä" + }, + "wordSeparator": { + "message": "Sanojen erotin" + }, + "capitalize": { + "message": "Sanat isoilla alkukirjaimilla", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Sisällytä numero" + }, + "minNumbers": { + "message": "Numeroita vähintään" + }, + "minSpecial": { + "message": "Erikoismerkkejä vähintään" + }, + "avoidAmbChar": { + "message": "Vältä epäselviä merkkejä" + }, + "searchVault": { + "message": "Hae holvista" + }, + "edit": { + "message": "Muokkaa" + }, + "view": { + "message": "Näytä" + }, + "noItemsInList": { + "message": "Ei näytettäviä kohteita." + }, + "itemInformation": { + "message": "Kohteen tiedot" + }, + "username": { + "message": "Käyttäjätunnus" + }, + "password": { + "message": "Salasana" + }, + "passphrase": { + "message": "Salauslauseke" + }, + "favorite": { + "message": "Suosikki" + }, + "notes": { + "message": "Merkinnät" + }, + "note": { + "message": "Merkintä" + }, + "editItem": { + "message": "Muokkaa kohdetta" + }, + "folder": { + "message": "Kansio" + }, + "deleteItem": { + "message": "Poista kohde" + }, + "viewItem": { + "message": "Näytä kohde" + }, + "launch": { + "message": "Avaa" + }, + "website": { + "message": "Verkkosivusto" + }, + "toggleVisibility": { + "message": "Näytä tai piilota" + }, + "manage": { + "message": "Hallinnoi" + }, + "other": { + "message": "Muut" + }, + "rateExtension": { + "message": "Arvioi laajennus" + }, + "rateExtensionDesc": { + "message": "Harkitse tukemistamme hyvällä arvostelulla!" + }, + "browserNotSupportClipboard": { + "message": "Selaimesi ei tue helppoa leikepöydälle kopiointia. Kopioi kohde manuaalisesti." + }, + "verifyIdentity": { + "message": "Vahvista henkilöllisyys" + }, + "yourVaultIsLocked": { + "message": "Holvisi on lukittu. Vahvista henkilöllisyytesi jatkaaksesi." + }, + "unlock": { + "message": "Avaa" + }, + "loggedInAsOn": { + "message": "Kirjautuneena tunnuksella $EMAIL$ palveluun $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Virheellinen pääsalasana" + }, + "vaultTimeout": { + "message": "Holvin aikakatkaisu" + }, + "lockNow": { + "message": "Lukitse nyt" + }, + "immediately": { + "message": "Välittömästi" + }, + "tenSeconds": { + "message": "10 sekuntia" + }, + "twentySeconds": { + "message": "20 sekuntia" + }, + "thirtySeconds": { + "message": "30 sekuntia" + }, + "oneMinute": { + "message": "1 minuutti" + }, + "twoMinutes": { + "message": "2 minuuttia" + }, + "fiveMinutes": { + "message": "5 minuuttia" + }, + "fifteenMinutes": { + "message": "15 minuuttia" + }, + "thirtyMinutes": { + "message": "30 minuuttia" + }, + "oneHour": { + "message": "1 tunti" + }, + "fourHours": { + "message": "4 tuntia" + }, + "onLocked": { + "message": "Kun järjestelmän lukitaan" + }, + "onRestart": { + "message": "Kun selain käynnistetään uudelleen" + }, + "never": { + "message": "Ei koskaan" + }, + "security": { + "message": "Suojaus" + }, + "errorOccurred": { + "message": "Tapahtui virhe" + }, + "emailRequired": { + "message": "Sähköpostiosoite vaaditaan." + }, + "invalidEmail": { + "message": "Virheellinen sähköpostiosoite." + }, + "masterPassRequired": { + "message": "Pääsalasana vaaditaan." + }, + "masterPassLength": { + "message": "Pääsalasanan on oltava vähintään 8 merkkiä pitkä." + }, + "masterPassDoesntMatch": { + "message": "Pääsalasanan vahvistus ei täsmää." + }, + "newAccountCreated": { + "message": "Uusi käyttäjätilisi on luotu! Voit nyt kirjautua sisään." + }, + "masterPassSent": { + "message": "Lähetimme pääsalasanasi vihjeen sähköpostitse." + }, + "verificationCodeRequired": { + "message": "Todennuskoodi vaaditaan." + }, + "invalidVerificationCode": { + "message": "Virheellinen todennuskoodi" + }, + "valueCopied": { + "message": "$VALUE$ kopioitu", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Valitun kohteen automaattinen täyttö ei onnistu tällä sivulla. Kopioi ja liitä tiedot sen sijaan itse." + }, + "loggedOut": { + "message": "Kirjauduttu ulos" + }, + "loginExpired": { + "message": "Kirjautumisistuntosi on erääntynyt." + }, + "logOutConfirmation": { + "message": "Haluatko varmasti kirjautua ulos?" + }, + "yes": { + "message": "Kyllä" + }, + "no": { + "message": "En" + }, + "unexpectedError": { + "message": "Tapahtui odottamaton virhe." + }, + "nameRequired": { + "message": "Nimi vaaditaan." + }, + "addedFolder": { + "message": "Kansio lisätty" + }, + "changeMasterPass": { + "message": "Vaihda pääsalasana" + }, + "changeMasterPasswordConfirmation": { + "message": "Voit vaihtaa pääsalasanasi bitwarden.com-verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "twoStepLoginConfirmation": { + "message": "Kaksivaiheinen kirjautuminen tekee tilistäsi turvallisemman edellyttämällä salasanan lisäksi kirjautumisen lisätodennusta todennuslaitteen, ‑sovelluksen, tekstiviestin, puhelun tai sähköpostin avulla. Voit ottaa kaksivaiheisen kirjautumisen käyttöön bitwarden.com‑verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "editedFolder": { + "message": "Kansiota muokattu" + }, + "deleteFolderConfirmation": { + "message": "Haluatko varmasti poistaa kansion?" + }, + "deletedFolder": { + "message": "Kansio poistettu" + }, + "gettingStartedTutorial": { + "message": "Aloitusopas" + }, + "gettingStartedTutorialVideo": { + "message": "Ota selainlaajennuksesta kaikki irti katsomalla video-oppaamme." + }, + "syncingComplete": { + "message": "Synkronointi on valmis" + }, + "syncingFailed": { + "message": "Synkronointi epäonnistui" + }, + "passwordCopied": { + "message": "Salasana kopioitu" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Uusi URI" + }, + "addedItem": { + "message": "Kohde lisätty" + }, + "editedItem": { + "message": "Kohdetta muokattu" + }, + "deleteItemConfirmation": { + "message": "Haluatko varmasti siirtää roskakoriin?" + }, + "deletedItem": { + "message": "Kohde siirrettiin roskakoriin" + }, + "overwritePassword": { + "message": "Korvaa salasana" + }, + "overwritePasswordConfirmation": { + "message": "Haluatko varmasti korvata nykyisen salasanan?" + }, + "overwriteUsername": { + "message": "Korvaa käyttäjätunnus" + }, + "overwriteUsernameConfirmation": { + "message": "Haluatko varmasti korvata nykyisen käyttäjätunnuksen?" + }, + "searchFolder": { + "message": "Hae kansiosta" + }, + "searchCollection": { + "message": "Hae kokoelmasta" + }, + "searchType": { + "message": "Hae tyypeistä" + }, + "noneFolder": { + "message": "Ei kansiota", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Älä näytä \"Lisää kirjautumistieto\" -kehotetta" + }, + "addLoginNotificationDesc": { + "message": "\"Lisää kirjautumistieto\" -kehote kysyy, haluatko tallentaa kirjautumistiedot holviisi kun kirjaudut niillä ensimmäistä kertaa." + }, + "dontShowCardsCurrentTab": { + "message": "Älä näytä välilehdille korttiehdotuksia" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Holvissasi olevat kortit tunnistetaan ja näytetään selaimen avoimelle välilehdelle, jotta niiden valinta täyttöä varten on helppoa." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Älä näytä välilehdille henkilöllisyysehdotuksia" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Holvissasi olevat henkilöllisyydet tunnistetaan ja näytetään selaimen avoimelle välilehdelle, jotta niiden valinta täyttöä varten on helppoa." + }, + "clearClipboard": { + "message": "Tyhjennä leikepöytä", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Poista kopioidut arvot leikepöydältä automaattisesti.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Haluatko, että Bitwarden muistaa salasanan puolestasi?" + }, + "notificationAddSave": { + "message": "Tallenna" + }, + "disableChangedPasswordNotification": { + "message": "Älä näytä \"Salasana vaihdettu\" -kehotetta" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Salasana vaihdettu\" -ilmoitus ehdottaa holviisi tallennetun kirjautumistiedon salasanan automaattista päivitystä kun se havaitsee, että olet vaihtanut sen verkkosivustolla." + }, + "notificationChangeDesc": { + "message": "Haluatko päivittää salasanan Bitwardeniin?" + }, + "notificationChangeSave": { + "message": "Päivitä" + }, + "disableContextMenuItem": { + "message": "Älä näytä kontekstivalikon valintoja" + }, + "disableContextMenuItemDesc": { + "message": "Hiiren kakkospainikkeen pikavalikon kautta pääset nopeasti käsiksi salasanojen luontiin ja nykyisellä välilehdellä avoinna olevan sivuston kirjautumisteitoihin." + }, + "defaultUriMatchDetection": { + "message": "URI:n tunnistuksen oletustapa", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Valitse oletustapa, jolla URI tunnistetaan esimerkiksi automaattisen täytön yhteydessä." + }, + "theme": { + "message": "Teema" + }, + "themeDesc": { + "message": "Vaihda sovelluksen väriteemaa." + }, + "dark": { + "message": "Tumma", + "description": "Dark color" + }, + "light": { + "message": "Vaalea", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized, tumma", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Vie holvi" + }, + "fileFormat": { + "message": "Tiedostomuoto" + }, + "warning": { + "message": "VAROITUS", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Vahvista holvin vienti" + }, + "exportWarningDesc": { + "message": "Tämä vienti sisältää holvisi tiedot salaamattomassa muodossa. Sinun ei tulisi säilyttää tai lähettää vietyä tiedostoa suojaamattomien kanavien (kuten sähköpostin) välityksellä. Poista se välittömästi kun sille ei enää ole käyttöä." + }, + "encExportKeyWarningDesc": { + "message": "Tämä vienti salaa tietosi käyttäjätilisi salausavaimella. Jos joskus uudistat tilisi salausavaimen, on tiedot vietävä uudelleen, koska et voi enää purkaa nyt luodun vientitiedoston salausta." + }, + "encExportAccountWarningDesc": { + "message": "Tilin salausavaimet ovat ainutlaatuisia jokaiselle Bitwarden-käyttäjätilille, joten et voi tuoda salattua vientitiedostoa toiselle tilille." + }, + "exportMasterPassword": { + "message": "Syötä pääsalasana viedäksesi holvisi tiedot." + }, + "shared": { + "message": "Jaettu" + }, + "learnOrg": { + "message": "Lisätietoja organisaatioista" + }, + "learnOrgConfirmation": { + "message": "Bitwardenin avulla voit jakaa holvisi sisältöä muiden kanssa organisaatiotiliä käyttäen. Haluatko lukea bitwarden.com-sivustolta lisää?" + }, + "moveToOrganization": { + "message": "Siirrä organisaatiolle" + }, + "share": { + "message": "Jaa" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ siirrettiin organisaatioon $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Valitse organisaatio, jolle haluat siirtää kohteen. Tämä siirtää kohteen organisaation omistukseen, etkä tämän jälkeen ole enää sen suora omistaja." + }, + "learnMore": { + "message": "Lue lisää" + }, + "authenticatorKeyTotp": { + "message": "Todennusmenetelmän avain (TOTP)" + }, + "verificationCodeTotp": { + "message": "Todennuskoodi (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopioi todennuskoodi" + }, + "attachments": { + "message": "Liitteet" + }, + "deleteAttachment": { + "message": "Poista tiedostoliite" + }, + "deleteAttachmentConfirmation": { + "message": "Haluatko varmasti poistaa liitteen?" + }, + "deletedAttachment": { + "message": "Poistettu tiedostoliite" + }, + "newAttachment": { + "message": "Lisää uusi tiedostoliite" + }, + "noAttachments": { + "message": "Ei liitteitä." + }, + "attachmentSaved": { + "message": "Tiedostoliite tallennettiin." + }, + "file": { + "message": "Tiedosto" + }, + "selectFile": { + "message": "Valitse tiedosto." + }, + "maxFileSize": { + "message": "Tiedoston enimmäiskoko on 500 Mt." + }, + "featureUnavailable": { + "message": "Toiminto ei ole käytettävissä" + }, + "updateKey": { + "message": "Et voi käyttää tätä toimintoa ennen kuin päivität salausavaimesi." + }, + "premiumMembership": { + "message": "Premium-jäsenyys" + }, + "premiumManage": { + "message": "Hallitse jäsenyyttä" + }, + "premiumManageAlert": { + "message": "Voit hallita jäsenyyttäsi bitwarden.com-verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "premiumRefresh": { + "message": "Päivitä jäsenyys" + }, + "premiumNotCurrentMember": { + "message": "Et ole tällä hetkellä Premium-jäsen." + }, + "premiumSignUpAndGet": { + "message": "Ryhdy Premium-jäseneksi saadaksesi:" + }, + "ppremiumSignUpStorage": { + "message": "1 Gt salattua tallennustilaa tiedostoliitteille." + }, + "ppremiumSignUpTwoStep": { + "message": "Muita kaksivaiheisen kirjautumisen todennusmenetelmiä kuten YubiKey, FIDO U2F ja Duo Security." + }, + "ppremiumSignUpReports": { + "message": "Salasanahygienian, tilin terveyden ja tietovuotojen raportointitoiminnot pitävät holvisi turvassa." + }, + "ppremiumSignUpTotp": { + "message": "Kaksivaiheisen kirjautumisen (2FA) TOTP-todennuskoodien generaattori holvisi kirjautumistiedoille." + }, + "ppremiumSignUpSupport": { + "message": "Ensisijainen asiakastuki." + }, + "ppremiumSignUpFuture": { + "message": "Kaikki tulossa olevat Premium-toiminnot. Lisää tulossa pian!" + }, + "premiumPurchase": { + "message": "Osta Premium" + }, + "premiumPurchaseAlert": { + "message": "Voit ostaa Premium-jäsenyyden bitwarden.com-verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "premiumCurrentMember": { + "message": "Olet Premium-jäsen!" + }, + "premiumCurrentMemberThanks": { + "message": "Kiitos kun tuet Bitwardenia." + }, + "premiumPrice": { + "message": "Kaikki tämä vain $PRICE$/vuosi!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Päivitys on valmis" + }, + "disableAutoTotpCopy": { + "message": "Älä kopioi TOTP-koodeja automaattisesti" + }, + "disableAutoTotpCopyDesc": { + "message": "Jos kirjautumistietoosi on liitetty kaksivaiheisen todennusmenetelmän avain, kopioidaan kaksivaiheisen kirjautumisen TOTP-todennuskoodi automaattisesti leikepöydälle kun suoritat kohteen automaattisen täytön." + }, + "disableAutoBiometricsPrompt": { + "message": "Älä pyydä biometristä avausta käynnistettäessä." + }, + "premiumRequired": { + "message": "Premium vaaditaan" + }, + "premiumRequiredDesc": { + "message": "Käyttääksesi tätä toimintoa tarvitset Premium-jäsenyyden." + }, + "enterVerificationCodeApp": { + "message": "Syötä 6-numeroinen todennuskoodi todennussovelluksestasi." + }, + "enterVerificationCodeEmail": { + "message": "Syötä 6-numeroinen todennuskoodi, joka lähetettiin sähköpostitse osoitteeseen $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Todennussähköposti lähetettiin osoitteeseen $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Muista minut" + }, + "sendVerificationCodeEmailAgain": { + "message": "Lähetä todennuskoodi sähköpostitse uudelleen" + }, + "useAnotherTwoStepMethod": { + "message": "Käytä toista kaksivaiheisen kirjautumisen todentajaa" + }, + "insertYubiKey": { + "message": "Kytke YubiKey-todennuslaitteesi tietokoneen USB-porttiin ja paina sen painiketta." + }, + "insertU2f": { + "message": "Kytke todennuslaitteesi tietokoneen USB-porttiin. Jos laitteessa on painike, paina sitä." + }, + "webAuthnNewTab": { + "message": "Aloittaaksesi kaksivaiheisen WebAuthn-todennuksen, seuraa alla olevasta painikkeesta uuteen välilehteen avautuvia ohjeita." + }, + "webAuthnNewTabOpen": { + "message": "Avaa uusi välilehti" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn-todennus" + }, + "loginUnavailable": { + "message": "Kirjautuminen ei ole käytettävissä" + }, + "noTwoStepProviders": { + "message": "Tilillä on käytössä kaksivaiheinen kirjautuminen, mutta tämä selain ei tue käytettävissä olevia todentajia." + }, + "noTwoStepProviders2": { + "message": "Käytä tuettua selainta (kuten Chrome) ja lisää/tai ota käyttöön laajemmin tuettu todentaja (kuten todennussovellus)." + }, + "twoStepOptions": { + "message": "Kaksivaiheisen kirjautumisen asetukset" + }, + "recoveryCodeDesc": { + "message": "Etkö pysty käyttämään kaksivaiheisen kirjautumisen todentajiasi? Poista kaikki tilisi todentajat käytöstä palautuskoodillasi." + }, + "recoveryCodeTitle": { + "message": "Palautuskoodi" + }, + "authenticatorAppTitle": { + "message": "Todennussovellus" + }, + "authenticatorAppDesc": { + "message": "Käytä todennussovellusta (kuten Authy, Google tai Microsoft Authenticator) luodaksesi aikarajallisia todennuskoodeja.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP -todennuslaite" + }, + "yubiKeyDesc": { + "message": "Käytä YubiKey-todennuslaitetta tilisi avaukseen. Toimii YubiKey 4, 4 Nano, 4C sekä NEO -laitteiden kanssa." + }, + "duoDesc": { + "message": "Vahvista Duo Securityn avulla käyttäen Duo Mobile ‑sovellusta, tekstiviestiä, puhelua tai U2F-todennuslaitetta.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Vahvista organisaatiollesi Duo Securityn avulla käyttäen Duo Mobile ‑sovellusta, tekstiviestiä, puhelua tai U2F-todennuslaitetta.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Käytä mitä tahansa WebAuthn‑yhteensopivaa todennuslaitetta päästäksesi käsiksi tiliisi." + }, + "emailTitle": { + "message": "Sähköposti" + }, + "emailDesc": { + "message": "Todennuskoodit lähetetään sinulle sähköpostitse." + }, + "selfHostedEnvironment": { + "message": "Oma palvelinympäristö" + }, + "selfHostedEnvironmentFooter": { + "message": "Määritä omassa palvelinympäristössäsi suoritettavan Bitwarden-asennuksen pääverkkotunnus." + }, + "customEnvironment": { + "message": "Mukautettu palvelinympäristö" + }, + "customEnvironmentFooter": { + "message": "Edistyneille käyttäjille. Voit määrittää jokaiselle palvelulle oman pääverkkotunnuksen." + }, + "baseUrl": { + "message": "Palvelimen URL" + }, + "apiUrl": { + "message": "API-palvelimen URL" + }, + "webVaultUrl": { + "message": "Verkkoholvipalvelimen URL" + }, + "identityUrl": { + "message": "Henkilöllisyyspalvelimen URL" + }, + "notificationsUrl": { + "message": "Ilmoituspalvelimen URL" + }, + "iconsUrl": { + "message": "Kuvakepalvelimen URL" + }, + "environmentSaved": { + "message": "Palvelinten URL-osoitteet tallennettiin." + }, + "enableAutoFillOnPageLoad": { + "message": "Täytä automaattisesti sivun avautuessa" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Jos sivulla havaitaan kirjautumislomake, täytetään kirjautumistiedot automaattisesti sivun avautuessa." + }, + "experimentalFeature": { + "message": "Tämä on vielä kokeellinen toiminto. Käytä omalla vastuullasi." + }, + "defaultAutoFillOnPageLoad": { + "message": "Automaattisen täytön oletusasetus kirjautumistiedoille" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Kun \"Täytä automaattisesti sivun avautuessa\" on käytössä, voi sen ottaa käyttöön tai poistaa käytöstä yksittäisille kirjautumistiedoille. Tämä on oletusarvo niille kirjautumistiedoille, joille asetusta ei ole erikseen määritetty." + }, + "itemAutoFillOnPageLoad": { + "message": "Automaattinen täyttö sivun avautuessa (jos kytketty asetuksista käyttöön)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Käytä oletusasetusta" + }, + "autoFillOnPageLoadYes": { + "message": "Täytä automaattisesti sivun avautuessa" + }, + "autoFillOnPageLoadNo": { + "message": "Älä täytä automaattisesti sivun avautuessa" + }, + "commandOpenPopup": { + "message": "Avaa holvin ponnahdusikkuna" + }, + "commandOpenSidebar": { + "message": "Avaa holvi sivupalkissa" + }, + "commandAutofillDesc": { + "message": "Täytä automaattisesti viimeisin nykyisellä sivustolla käytetty kirjautumistieto" + }, + "commandGeneratePasswordDesc": { + "message": "Luo uusi satunnainen salasana ja kopioi se leikepöydälle." + }, + "commandLockVaultDesc": { + "message": "Lukitse holvi" + }, + "privateModeWarning": { + "message": "Yksityisen tilan tuki on kokeellinen ja jotkin ominaisuudet toimivat rajoitetusti." + }, + "customFields": { + "message": "Lisäkentät" + }, + "copyValue": { + "message": "Kopioi arvo" + }, + "value": { + "message": "Arvo" + }, + "newCustomField": { + "message": "Uusi lisäkenttä" + }, + "dragToSort": { + "message": "Järjestä raahaamalla" + }, + "cfTypeText": { + "message": "Teksti" + }, + "cfTypeHidden": { + "message": "Piilotettu" + }, + "cfTypeBoolean": { + "message": "Totuusarvo" + }, + "cfTypeLinked": { + "message": "Linkitetty", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linkitetty arvo", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Klikkaus ponnahdusikkunan ulkopuolelle todennuskoodin sähköpostista noutoa varten sulkee ikkunan. Haluatko avata näkymän uuteen ikkunaan, jotta se pysyy avoinna?" + }, + "popupU2fCloseMessage": { + "message": "Tämä selain ei voi käsitellä U2F-pyyntöjä tässä ponnahdusikkunassa. Haluatko avata näkymän uuteen ikkunaan, jotta voit vahvistaa kirjautumisen U2F-todennuslaitteella?" + }, + "disableFavicon": { + "message": "Älä näytä sivustojen kuvakkeita" + }, + "disableFaviconDesc": { + "message": "Kirjautumistietojen vieressä näytettävät sivustojen kuvakkeet helpottavat kohteiden tunnistusta." + }, + "disableBadgeCounter": { + "message": "Älä näytä kuvakkeen laskuria" + }, + "disableBadgeCounterDesc": { + "message": "Työkalupalkin kuvakkeessa näytetään laskuri, joka kertoo avoimeen sivuun kohdistuvien kirjautumistietojen lukumäärän holvissasi." + }, + "cardholderName": { + "message": "Kortinhaltijan nimi" + }, + "number": { + "message": "Numero" + }, + "brand": { + "message": "Merkki" + }, + "expirationMonth": { + "message": "Erääntymiskuukausi" + }, + "expirationYear": { + "message": "Erääntymisvuosi" + }, + "expiration": { + "message": "Erääntymisaika" + }, + "january": { + "message": "Tammikuu" + }, + "february": { + "message": "Helmikuu" + }, + "march": { + "message": "Maaliskuu" + }, + "april": { + "message": "Huhtikuu" + }, + "may": { + "message": "Toukokuu" + }, + "june": { + "message": "Kesäkuu" + }, + "july": { + "message": "Heinäkuu" + }, + "august": { + "message": "Elokuu" + }, + "september": { + "message": "Syyskuu" + }, + "october": { + "message": "Lokakuu" + }, + "november": { + "message": "Marraskuu" + }, + "december": { + "message": "Joulukuu" + }, + "securityCode": { + "message": "Turvakoodi (CVC/CVV)" + }, + "ex": { + "message": "esim." + }, + "title": { + "message": "Titteli" + }, + "mr": { + "message": "Hra" + }, + "mrs": { + "message": "Rva" + }, + "ms": { + "message": "Nti" + }, + "dr": { + "message": "Tri" + }, + "firstName": { + "message": "Etunimi" + }, + "middleName": { + "message": "Toinen nimi" + }, + "lastName": { + "message": "Sukunimi" + }, + "fullName": { + "message": "Koko nimi" + }, + "identityName": { + "message": "Henkilöllisyyden nimi" + }, + "company": { + "message": "Yritys" + }, + "ssn": { + "message": "Henkilötunnus" + }, + "passportNumber": { + "message": "Passin numero" + }, + "licenseNumber": { + "message": "Ajokortin numero" + }, + "email": { + "message": "Sähköposti" + }, + "phone": { + "message": "Puhelinnumero" + }, + "address": { + "message": "Osoite" + }, + "address1": { + "message": "Osoite 1" + }, + "address2": { + "message": "Osoite 2" + }, + "address3": { + "message": "Osoite 3" + }, + "cityTown": { + "message": "Paikkakunta" + }, + "stateProvince": { + "message": "Osavaltio/maakunta" + }, + "zipPostalCode": { + "message": "Postinumero" + }, + "country": { + "message": "Maa" + }, + "type": { + "message": "Tyyppi" + }, + "typeLogin": { + "message": "Kirjautumistieto" + }, + "typeLogins": { + "message": "Kirjautumistiedot" + }, + "typeSecureNote": { + "message": "Salattu muistio" + }, + "typeCard": { + "message": "Kortti" + }, + "typeIdentity": { + "message": "Henkilöllisyys" + }, + "passwordHistory": { + "message": "Salasanahistoria" + }, + "back": { + "message": "Takaisin" + }, + "collections": { + "message": "Kokoelmat" + }, + "favorites": { + "message": "Suosikit" + }, + "popOutNewWindow": { + "message": "Avaa uuteen ikkunaan" + }, + "refresh": { + "message": "Päivitä" + }, + "cards": { + "message": "Kortit" + }, + "identities": { + "message": "Henkilöllisyydet" + }, + "logins": { + "message": "Kirjautumistiedot" + }, + "secureNotes": { + "message": "Salatut muistiot" + }, + "clear": { + "message": "Tyhjennä", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Tarkasta, onko salasana vuotanut." + }, + "passwordExposed": { + "message": "Salasana on paljastunut $VALUE$ tietovuodossa. Se tulisi vaihtaa.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Tätä salasanaa ei löytynyt yhdestäkään tunnetusta tietovuodosta. Sen pitäisi olla turvallinen." + }, + "baseDomain": { + "message": "Pääverkkotunnus", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Verkkotunnus", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Isäntä", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tarkka" + }, + "startsWith": { + "message": "Alkaa" + }, + "regEx": { + "message": "Säännöllinen lauseke", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Tunnistustapa", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Tunnistuksen oletustapa", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Näytä tai piilota asetukset" + }, + "toggleCurrentUris": { + "message": "Näytä tai piilota nykyiset URI:t", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Nykyinen URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisaatio", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tyypit" + }, + "allItems": { + "message": "Kaikki kohteet" + }, + "noPasswordsInList": { + "message": "Ei näytettäviä salasanoja." + }, + "remove": { + "message": "Poista" + }, + "default": { + "message": "Oletus" + }, + "dateUpdated": { + "message": "Päivitetty", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Salasana päivitetty", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Oletko varma, että haluat käyttää asetusta \"Ei koskaan\"? Tämä valinta tallentaa holvisi salausavaimen laitteellesi. Jos käytät asetusta, varmista että laitteesi on hyvin suojattu." + }, + "noOrganizationsList": { + "message": "Et kuulu mihinkään organisaatioon. Organisaatioiden avulla voit jakaa kohteita turvallisesti muiden käyttäjien kanssa." + }, + "noCollectionsInList": { + "message": "Ei näytettäviä kokoelmia." + }, + "ownership": { + "message": "Omistus" + }, + "whoOwnsThisItem": { + "message": "Kuka omistaa tämän kohteen?" + }, + "strong": { + "message": "Vahva", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Hyvä", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Heikko", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Heikko pääsalasana" + }, + "weakMasterPasswordDesc": { + "message": "Valitsemasi pääsalasana on heikko. Sinun tulisi käyttää vahvaa pääsalasanaa (tai salauslauseketta) suojataksesi Bitwarden-tilisi kunnolla. Haluatko varmasti käyttää tätä pääsalasanaa?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Avaa PIN-koodilla" + }, + "setYourPinCode": { + "message": "Aseta PIN-koodi Bitwardenin avaukselle. PIN-asetukset tyhjentyvät, jos kirjaudut kokonaan ulos laajennuksesta." + }, + "pinRequired": { + "message": "PIN-koodi vaaditaan." + }, + "invalidPin": { + "message": "Virheellinen PIN-koodi." + }, + "unlockWithBiometrics": { + "message": "Avaa biometrialla" + }, + "awaitDesktop": { + "message": "Odottaa vahvistusta työpöydältä" + }, + "awaitDesktopDesc": { + "message": "Vahvista biometrian käyttö Bitwardenin työpöytäsovelluksessa käyttääksesi sitä selaimessa." + }, + "lockWithMasterPassOnRestart": { + "message": "Lukitse pääsalasanalla kun selain käynnistetään uudelleen" + }, + "selectOneCollection": { + "message": "Valitse ainakin yksi kokoelma." + }, + "cloneItem": { + "message": "Kloonaa kohde" + }, + "clone": { + "message": "Kloonaa" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Yksi tai useampi organisaatiokäytäntö vaikuttaa generaattorisi asetuksiin." + }, + "vaultTimeoutAction": { + "message": "Holvin aikakatkaisun toiminto" + }, + "lock": { + "message": "Lukitse", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Roskakori", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Hae roskakorista" + }, + "permanentlyDeleteItem": { + "message": "Poista kohde pysyvästi" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Haluatko varmasti poistaa kohteen pysyvästi?" + }, + "permanentlyDeletedItem": { + "message": "Kohde poistettu pysyvästi" + }, + "restoreItem": { + "message": "Palauta kohde" + }, + "restoreItemConfirmation": { + "message": "Haluatko varmasti palauttaa kohteen?" + }, + "restoredItem": { + "message": "Kohde palautettu" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Uloskirjautuminen estää pääsyn holviisi ja vaatii ajan umpeuduttua todennuksen internet-yhteyden välityksellä. Haluatko varmasti käyttää tätä asetusta?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Aikakatkaisun toiminnon vahvistus" + }, + "autoFillAndSave": { + "message": "Täytä automaattisesti ja tallenna" + }, + "autoFillSuccessAndSavedUri": { + "message": "Kohde täytettiin automaattisesti ja URI tallennettiin" + }, + "autoFillSuccess": { + "message": "Kohde täytettiin automaattisesti" + }, + "setMasterPassword": { + "message": "Aseta pääsalasana" + }, + "masterPasswordPolicyInEffect": { + "message": "Yksi tai useampi organisaatiokäytäntö edellyttää, että pääsalasanasi täyttää seuraavat vaatimukset:" + }, + "policyInEffectMinComplexity": { + "message": "Monimutkaisuuden vähimmäispistemäärä on $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Vähimmäispituus on $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Sisältää yhden tai useamman ison kirjaimen" + }, + "policyInEffectLowercase": { + "message": "Sisältää yhden tai useamman pienen kirjaimen" + }, + "policyInEffectNumbers": { + "message": "Sisältää yhden tai useamman numeron" + }, + "policyInEffectSpecial": { + "message": "Sisältää yhden tai useamman seuraavista erikoismerkeistä $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Uusi pääsalasanasi ei täytä käytännön määrittämiä vaatimuksia." + }, + "acceptPolicies": { + "message": "Valitsemalla tämän ruudun hyväksyt seuraavat:" + }, + "acceptPoliciesError": { + "message": "Käyttöehtoja ja tietosuojakäytäntöä ei ole vahvistettu." + }, + "termsOfService": { + "message": "Käyttöehdot" + }, + "privacyPolicy": { + "message": "Tietosuojakäytäntö" + }, + "hintEqualsPassword": { + "message": "Salasanavihjeesi ei voi olla sama kuin salasanasi." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Työpöytäsynkronoinnin vahvistus" + }, + "desktopIntegrationVerificationText": { + "message": "Varmista, että työpöytäsovellus näyttää tämän tunnistelausekkeen:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Selainintegrointi ei ole käytössä" + }, + "desktopIntegrationDisabledDesc": { + "message": "Selainintegrointi ei ole käytössä Bitwardenin työpöytäsovelluksessa. Ota se käyttöön työpöytäsovelluksen asetuksista." + }, + "startDesktopTitle": { + "message": "Käynnistä Bitwardenin työpöytäsovellus" + }, + "startDesktopDesc": { + "message": "Bitwardenin työpöytäsovellus on käynnistettävä ennen kuin biometristä avausta voidaan käyttää." + }, + "errorEnableBiometricTitle": { + "message": "Biometrian käyttöönotto ei onnistu" + }, + "errorEnableBiometricDesc": { + "message": "Työpöytäsovellus perui toiminnon" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Työpöytäsovellus hyläsi suojatun viestintäväylän. Yritä toimintoa uudelleen" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Työpöytäyhteys keskeytyi" + }, + "nativeMessagingWrongUserDesc": { + "message": "Työpöytäsovellus on kirjautuneena eri tilille. Varmista, että molemmat sovellukset ovat kirjautuneet samalle tilille." + }, + "nativeMessagingWrongUserTitle": { + "message": "Tili ei täsmää" + }, + "biometricsNotEnabledTitle": { + "message": "Biometria ei ole käytössä" + }, + "biometricsNotEnabledDesc": { + "message": "Käyttääksesi biometriaa selaimessa, on biometria otettava käyttöön työpöytäsovelluksen asetuksista." + }, + "biometricsNotSupportedTitle": { + "message": "Biometriaa ei tueta" + }, + "biometricsNotSupportedDesc": { + "message": "Selaimen biometriaa ei tueta tällä laitteella." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Oikeutta ei myönnetty" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Ilman viestintäoikeutta Bitwardenin työpöytäsovelluksen kanssa, ei biometriaa tueta selainlaajennuksessa. Yritä uudelleen." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Käyttöoikeuspyynnön virhe" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Toimintoa ei voi suorittaa sivupalkissa, yritä toimintoa uudelleen ponnahdusvalikossa tai ponnahdusikkunassa." + }, + "personalOwnershipSubmitError": { + "message": "Yrityksen asettaman käytännön johdosta kohteiden tallennus omaan holviisi ei ole mahdollista. Muuta omistusasetus organisaatiolle ja valitse käytettävissä olevista kokoelmista." + }, + "personalOwnershipPolicyInEffect": { + "message": "Organisaatiokäytäntö vaikuttaa omistajuusvalintoihisi." + }, + "excludedDomains": { + "message": "Ohitettavat verkkotunnukset" + }, + "excludedDomainsDesc": { + "message": "Bitwarden ei pyydä kirjautumistietojen tallennusta näille verkkotunnuksille. Päivitä sivu ottaaksesi muutokset käyttöön." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ ei ole kelvollinen verkkotunnus", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Hae Sendeistä", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Lisää Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Teksti" + }, + "sendTypeFile": { + "message": "Tiedosto" + }, + "allSends": { + "message": "Kaikki Sendit", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Käyttökertojen enimmäismäärä saavutettu", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Erääntynyt" + }, + "pendingDeletion": { + "message": "Odottaa poistoa" + }, + "passwordProtected": { + "message": "Salasanasuojattu" + }, + "copySendLink": { + "message": "Kopioi Sendin linkki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Poista salasana" + }, + "delete": { + "message": "Poista" + }, + "removedPassword": { + "message": "Salasana poistettu" + }, + "deletedSend": { + "message": "Poistettu Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send-linkki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Ei käytössä" + }, + "removePasswordConfirmation": { + "message": "Haluatko varmasti poistaa salasanan?" + }, + "deleteSend": { + "message": "Poista Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Haluatko varmasti poistaa Sendin?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Muokkaa Sendiä", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Minkä tyyppinen Send tämä on?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Kuvaava nimi Sendille.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Tiedosto, jonka haluat lähettää." + }, + "deletionDate": { + "message": "Poistoajankohta" + }, + "deletionDateDesc": { + "message": "Send poistuu pysyvästi määritettynä ajankohtana.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Erääntymisajankohta" + }, + "expirationDateDesc": { + "message": "Jos määritetty, Send erääntyy määritettynä ajankohtana.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 päivä" + }, + "days": { + "message": "$DAYS$ päivää", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Mukautettu" + }, + "maximumAccessCount": { + "message": "Käyttöoikeuksien enimmäismäärä" + }, + "maximumAccessCountDesc": { + "message": "Jos määritetty, käyttäjät eivät voi avata Sendiä käyttökertojen enimmäismäärän täytyttyä.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Halutessasi, vaadi käyttäjiä syöttämään salasana Sendin avaamiseksi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Yksityisiä merkintöjä tästä Sendistä.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Poista Send käytöstä, jottei kukaan voi avata sitä.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kopioi Sendin linkki leikepöydälle tallennettaessa.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teksti, jonka haluat lähettää." + }, + "sendHideText": { + "message": "Piilota Sendin teksti oletuksena.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Nykyinen käyttökertojen määrä" + }, + "createSend": { + "message": "Luo uusi Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Uusi salasana" + }, + "sendDisabled": { + "message": "Send on poistettu käytöstä", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Yrityksen käytännön vuoksi voit poistaa vain olemassa olevan Sendin.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send luotu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Sendiä muokattu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Jotta voit valita tiedoston, avaa laajennus sivupalkkiin (jos mahdollista) tai erilliseen ikkunaan klikkaamalla tätä banneria." + }, + "sendFirefoxFileWarning": { + "message": "Jotta voit valita tiedoston käyttäen Firefoxia, avaa laajennus sivupalkkiin tai erilliseen ikkunaan klikkaamalla tätä banneria." + }, + "sendSafariFileWarning": { + "message": "Jotta voit valita tiedoston käyttäen Safaria, avaa laajennus erilliseen ikkunaan klikkaamalla tätä banneria." + }, + "sendFileCalloutHeader": { + "message": "Ennen kuin aloitat" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Käyttääksesi kalenterityylistä päivämäärän valintaa", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klikkaa tästä", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "erillistä valintaa varten.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Määritetty erääntymismisajankohta on virheellinen." + }, + "deletionDateIsInvalid": { + "message": "Määritetty poistoajankohta on virheellinen." + }, + "expirationDateAndTimeRequired": { + "message": "Erääntymispäivä ja -aika vaaditaan." + }, + "deletionDateAndTimeRequired": { + "message": "Poistopäivä ja -aika vaaditaan." + }, + "dateParsingError": { + "message": "Tapahtui virhe tallennettaessa poisto- ja erääntymisajankohtia." + }, + "hideEmail": { + "message": "Piilota sähköpostiosoitteeni vastaanottajilta." + }, + "sendOptionsPolicyInEffect": { + "message": "Yksi tai useampi organisaatiokäytäntö vaikuttaa Send-asetuksiisi." + }, + "passwordPrompt": { + "message": "Pääsalasanan uudelleenkysely" + }, + "passwordConfirmation": { + "message": "Pääsalasanan vahvistus" + }, + "passwordConfirmationDesc": { + "message": "Toiminto on suojattu. Jatkaaksesi, syötä pääsalasanasi uudelleen vahvistaaksesi henkilöllisyytesi." + }, + "emailVerificationRequired": { + "message": "Sähköpostiosoitteen vahvistus vaaditaan" + }, + "emailVerificationRequiredDesc": { + "message": "Sinun on vahvistettava sähköpostiosoitteesi käyttääksesi ominaisuutta. Voit vahvistaa osoitteesi verkkoholvissa." + }, + "updatedMasterPassword": { + "message": "Pääsalasana on päivitetty" + }, + "updateMasterPassword": { + "message": "Päivitä pääsalasana" + }, + "updateMasterPasswordWarning": { + "message": "Organisaatiosi ylläpito on hiljattain vaihtanut pääsalasanasi. Käyttääksesi holvia, on sinun päivitettävä se nyt. Tämä uloskirjaa kaikki nykyiset istunnot pakottaen uudelleenkirjautumisen. Muiden laitteiden aktiiviset istunnot saattavat toimia vielä tunnin ajan." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automaattinen liitos" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Organisaatiolla on käytäntö, joka liittää tilisi automaattisesti salasanan palautusapuun. Liitos sallii organisaation ylläpitäjien vaihtaa pääsalasanasi." + }, + "selectFolder": { + "message": "Valitse kansio..." + }, + "ssoCompleteRegistration": { + "message": "Kirjautuaksesi sisään käyttäen kertakirjautumista (SSO), suojaa holvisi pääsalasanalla." + }, + "hours": { + "message": "Tuntia" + }, + "minutes": { + "message": "Minuuttia" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Organisaatiosi käytännöt vaikuttavat holvisi aikakatkaisuun. Suurin sallittu viive on $HOURS$ tunti(a) ja $MINUTES$ minuutti(a)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Holvisi aikakatkaisuviive ylittää organisaatiosi asettamat rajoitukset." + }, + "vaultExportDisabled": { + "message": "Holvin vienti on poistettu käytöstä" + }, + "personalVaultExportPolicyInEffect": { + "message": "Yksi tai useampi organisaation käytäntö estää henkilökohtaisen holvisi viennin." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Oikeaa lomakkeen elementtiä ei tunnistettu. Yritä sen sijaan HTML-koodin tarkastusta." + }, + "copyCustomFieldNameNotUnique": { + "message": "Yksilöllistä tunnistetta ei löytynyt." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ käyttää kertakirjautumista (SSO) oman avainpalvelimensa kanssa. Organisaation jäsenet eivät enää tarvitse pääsalasanaa kirjautumiseen.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Poistu organisaatiosta" + }, + "removeMasterPassword": { + "message": "Poista pääsalasana" + }, + "removedMasterPassword": { + "message": "Pääsalasana on poistettu." + }, + "leaveOrganizationConfirmation": { + "message": "Haluatko varmasti poistua tästä organisaatiosta?" + }, + "leftOrganization": { + "message": "Olet poistunut organisaatiosta." + }, + "toggleCharacterCount": { + "message": "Näytä merkkimäärän laskuri" + }, + "sessionTimeout": { + "message": "Istuntosi on aikakatkaistu. Palaa takaisin ja yritä kirjautua uudelleen." + }, + "exportingPersonalVaultTitle": { + "message": "Henkilökohtaisen holvin vienti" + }, + "exportingPersonalVaultDescription": { + "message": "Vain tunnukseen $EMAIL$ liitetyt henkilökohtaiset holvin kohteet viedään. Organisaation kohteet eivät sisälly tähän.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Virhe" + }, + "regenerateUsername": { + "message": "Luo uusi käyttäjätunnus" + }, + "generateUsername": { + "message": "Luo käyttäjätunnus" + }, + "usernameType": { + "message": "Käyttäjätunnuksen tyyppi" + }, + "plusAddressedEmail": { + "message": "Plus-osoitteinen sähköposti", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Käytä sähköpostipalvelusi aliosoiteominaisuuksia." + }, + "catchallEmail": { + "message": "Catch-all-sähköpostiosoite" + }, + "catchallEmailDesc": { + "message": "Käytä verkkotunnuksellesi määritettyä catch-all-postilaatikkoa." + }, + "random": { + "message": "Satunnainen" + }, + "randomWord": { + "message": "Satunnainen sana" + }, + "websiteName": { + "message": "Verkkosivuston nimi" + }, + "whatWouldYouLikeToGenerate": { + "message": "Mitä haluat luoda?" + }, + "passwordType": { + "message": "Salasanan tyyppi" + }, + "service": { + "message": "Palvelu" + } +} diff --git a/apps/browser/src/_locales/fil/messages.json b/apps/browser/src/_locales/fil/messages.json new file mode 100644 index 0000000000..c0fc9f75c3 --- /dev/null +++ b/apps/browser/src/_locales/fil/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "login": { + "message": "Log In" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "Cancel" + }, + "close": { + "message": "Close" + }, + "submit": { + "message": "Submit" + }, + "emailAddress": { + "message": "Email Address" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "My Vault" + }, + "tools": { + "message": "Tools" + }, + "settings": { + "message": "Settings" + }, + "currentTab": { + "message": "Current Tab" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number" + }, + "copySecurityCode": { + "message": "Copy Security Code" + }, + "autoFill": { + "message": "Auto-fill" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "Add a Login" + }, + "addItem": { + "message": "Add Item" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "Continue" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "logOut": { + "message": "Log Out" + }, + "about": { + "message": "About" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Save" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Add Folder" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Edit Folder" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "folders": { + "message": "Folders" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "Help & Feedback" + }, + "sync": { + "message": "Sync" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "Select" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Length" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "View" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favorite" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit Item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Delete Item" + }, + "viewItem": { + "message": "View Item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "Manage" + }, + "other": { + "message": "Other" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Browser Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "errorOccurred": { + "message": "An error has occurred" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "Name is required." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Save" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Update" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/fr/messages.json b/apps/browser/src/_locales/fr/messages.json new file mode 100644 index 0000000000..7adfd2cbcd --- /dev/null +++ b/apps/browser/src/_locales/fr/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Un gestionnaire de mots de passe sécurisé et gratuit pour tous vos appareils.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Identifiez-vous ou créez un nouveau compte pour accéder à votre coffre sécurisé." + }, + "createAccount": { + "message": "Créer un compte" + }, + "login": { + "message": "Se connecter" + }, + "enterpriseSingleSignOn": { + "message": "Portail de connexion unique d'entreprise" + }, + "cancel": { + "message": "Annuler" + }, + "close": { + "message": "Fermer" + }, + "submit": { + "message": "Soumettre" + }, + "emailAddress": { + "message": "Adresse e-mail" + }, + "masterPass": { + "message": "Mot de passe maître" + }, + "masterPassDesc": { + "message": "Le mot de passe maître est le mot de passe que vous utilisez pour accéder à votre coffre. Il est très important de ne pas l'oublier. Il n'existe aucun moyen de le récupérer si vous le perdez." + }, + "masterPassHintDesc": { + "message": "Un indice de mot de passe maître peut vous aider à vous rappeler de votre mot de passe en cas d'oubli." + }, + "reTypeMasterPass": { + "message": "Saisissez à nouveau le mot de passe maître" + }, + "masterPassHint": { + "message": "Indice du mot de passe maître (facultatif)" + }, + "tab": { + "message": "Onglet" + }, + "myVault": { + "message": "Mon coffre" + }, + "tools": { + "message": "Outils" + }, + "settings": { + "message": "Paramètres" + }, + "currentTab": { + "message": "Onglet actif" + }, + "copyPassword": { + "message": "Copier le mot de passe" + }, + "copyNote": { + "message": "Copier la note" + }, + "copyUri": { + "message": "Copier l'URI" + }, + "copyUsername": { + "message": "Copier le nom d'utilisateur" + }, + "copyNumber": { + "message": "Copier le numéro" + }, + "copySecurityCode": { + "message": "Copier le code de sécurité" + }, + "autoFill": { + "message": "Remplissage automatique" + }, + "generatePasswordCopied": { + "message": "Générer un mot de passe (copié)" + }, + "copyElementIdentifier": { + "message": "Copier le nom du champ personnalisé" + }, + "noMatchingLogins": { + "message": "Aucun site correspondant." + }, + "unlockVaultMenu": { + "message": "Déverrouillez votre coffre" + }, + "loginToVaultMenu": { + "message": "Connectez-vous à votre coffre" + }, + "autoFillInfo": { + "message": "Il n'existe aucun site disponible pour le remplissage automatique pour l'onglet actuel du navigateur." + }, + "addLogin": { + "message": "Ajouter un identifiant" + }, + "addItem": { + "message": "Ajouter un élément" + }, + "passwordHint": { + "message": "Indice du mot de passe" + }, + "enterEmailToGetHint": { + "message": "Saisissez l'adresse e-mail de votre compte pour recevoir l'indice de votre mot de passe maître." + }, + "getMasterPasswordHint": { + "message": "Obtenir l'indice du mot de passe maître" + }, + "continue": { + "message": "Continuer" + }, + "sendVerificationCode": { + "message": "Envoyer un code de vérification à votre adresse email" + }, + "sendCode": { + "message": "Envoyer le code" + }, + "codeSent": { + "message": "Code envoyé" + }, + "verificationCode": { + "message": "Code de vérification" + }, + "confirmIdentity": { + "message": "Confirmez votre identité pour continuer." + }, + "account": { + "message": "Compte" + }, + "changeMasterPassword": { + "message": "Changer le mot de passe maître" + }, + "fingerprintPhrase": { + "message": "Phrase d'empreinte", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "La phrase d'empreinte de votre compte", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Identification en deux étapes" + }, + "logOut": { + "message": "Se déconnecter" + }, + "about": { + "message": "À propos" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Enregistrer" + }, + "move": { + "message": "Déplacer" + }, + "addFolder": { + "message": "Ajouter un dossier" + }, + "name": { + "message": "Nom" + }, + "editFolder": { + "message": "Modifier le dossier" + }, + "deleteFolder": { + "message": "Supprimer le dossier" + }, + "folders": { + "message": "Dossiers" + }, + "noFolders": { + "message": "Aucun dossier à lister." + }, + "helpFeedback": { + "message": "Aide et commentaires" + }, + "sync": { + "message": "Synchroniser" + }, + "syncVaultNow": { + "message": "Synchroniser le coffre maintenant" + }, + "lastSync": { + "message": "Dernière synchronisation :" + }, + "passGen": { + "message": "Générateur de mot de passe" + }, + "generator": { + "message": "Générateur", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Générer automatiquement des mots de passe forts et uniques pour vos identifiants." + }, + "bitWebVault": { + "message": "Coffre en ligne de Bitwarden" + }, + "importItems": { + "message": "Importer des éléments" + }, + "select": { + "message": "Sélectionner" + }, + "generatePassword": { + "message": "Générer un mot de passe" + }, + "regeneratePassword": { + "message": "Générer un nouveau mot de passe" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Longueur" + }, + "uppercase": { + "message": "Majuscules (A-Z)" + }, + "lowercase": { + "message": "Minuscules (a-z)" + }, + "numbers": { + "message": "Chiffres (0-9)" + }, + "specialCharacters": { + "message": "Caractères spéciaux (!@#$%^&*)" + }, + "numWords": { + "message": "Nombre de mots" + }, + "wordSeparator": { + "message": "Séparateur de mots" + }, + "capitalize": { + "message": "Mettre la première lettre de chaque mot en majuscule", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inclure un chiffre" + }, + "minNumbers": { + "message": "Nombre minimum de chiffres" + }, + "minSpecial": { + "message": "Nombre minimum de caractères spéciaux" + }, + "avoidAmbChar": { + "message": "Éviter les caractères ambigus" + }, + "searchVault": { + "message": "Rechercher dans le coffre" + }, + "edit": { + "message": "Modifier" + }, + "view": { + "message": "Voir" + }, + "noItemsInList": { + "message": "Aucun identifiant à afficher." + }, + "itemInformation": { + "message": "Informations sur l'élément" + }, + "username": { + "message": "Nom d'utilisateur" + }, + "password": { + "message": "Mot de passe" + }, + "passphrase": { + "message": "Phrase de passe" + }, + "favorite": { + "message": "Favori" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Modifier l'élément" + }, + "folder": { + "message": "Dossier" + }, + "deleteItem": { + "message": "Supprimer l'élément" + }, + "viewItem": { + "message": "Afficher l'élément" + }, + "launch": { + "message": "Ouvrir" + }, + "website": { + "message": "Site web" + }, + "toggleVisibility": { + "message": "Afficher/Masquer" + }, + "manage": { + "message": "Gérer" + }, + "other": { + "message": "Autre" + }, + "rateExtension": { + "message": "Noter l'extension" + }, + "rateExtensionDesc": { + "message": "Merci de nous aider en mettant une bonne note !" + }, + "browserNotSupportClipboard": { + "message": "Votre navigateur web ne supporte pas la copie rapide depuis le presse-papier. Copiez-le manuellement à la place." + }, + "verifyIdentity": { + "message": "Confirmer votre identité" + }, + "yourVaultIsLocked": { + "message": "Votre coffre est verrouillé. Vérifiez votre identité pour continuer." + }, + "unlock": { + "message": "Déverrouiller" + }, + "loggedInAsOn": { + "message": "Connecté en tant que $EMAIL$ sur $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Mot de passe maître invalide" + }, + "vaultTimeout": { + "message": "Délai d'expiration du coffre" + }, + "lockNow": { + "message": "Verrouiller maintenant" + }, + "immediately": { + "message": "Immédiatement" + }, + "tenSeconds": { + "message": "10 secondes" + }, + "twentySeconds": { + "message": "20 secondes" + }, + "thirtySeconds": { + "message": "30 secondes" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 heure" + }, + "fourHours": { + "message": "4 heures" + }, + "onLocked": { + "message": "Au verrouillage du système" + }, + "onRestart": { + "message": "Au redémarrage du navigateur" + }, + "never": { + "message": "Jamais" + }, + "security": { + "message": "Sécurité" + }, + "errorOccurred": { + "message": "Une erreur est survenue" + }, + "emailRequired": { + "message": "L'adresse e-mail est requise." + }, + "invalidEmail": { + "message": "Adresse e-mail invalide." + }, + "masterPassRequired": { + "message": "Le mot de passe maître est requis." + }, + "masterPassLength": { + "message": "Le mot de passe maître doit au moins contenir 8 caractères." + }, + "masterPassDoesntMatch": { + "message": "La confirmation du mot de passe maître ne correspond pas." + }, + "newAccountCreated": { + "message": "Votre nouveau compte a été créé ! Vous pouvez maintenant vous authentifier." + }, + "masterPassSent": { + "message": "Nous vous avons envoyé un e-mail contenant votre indice de mot de passe maître." + }, + "verificationCodeRequired": { + "message": "Le code de vérification est requis." + }, + "invalidVerificationCode": { + "message": "Code de vérification invalide" + }, + "valueCopied": { + "message": "$VALUE$ copié", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Impossible de remplir automatiquement le site sélectionné sur cette page. Copiez/collez plutôt votre nom d'utilisateur et/ou votre mot de passe." + }, + "loggedOut": { + "message": "Déconnecté" + }, + "loginExpired": { + "message": "Votre session a expiré." + }, + "logOutConfirmation": { + "message": "Êtes-vous sûr de vouloir vous déconnecter ?" + }, + "yes": { + "message": "Oui" + }, + "no": { + "message": "Non" + }, + "unexpectedError": { + "message": "Une erreur inattendue est survenue." + }, + "nameRequired": { + "message": "Le nom est requis." + }, + "addedFolder": { + "message": "Dossier ajouté" + }, + "changeMasterPass": { + "message": "Modifier le mot de passe maître" + }, + "changeMasterPasswordConfirmation": { + "message": "Vous pouvez modifier votre mot de passe maître depuis le coffre web sur bitwarden.com. Souhaitez-vous visiter le site maintenant ?" + }, + "twoStepLoginConfirmation": { + "message": "L'identification en deux étapes sécurise davantage votre compte en vous demandant à chaque connexion de saisir un code de sécurité obtenu depuis un autre appareil, via une clé de sécurité, une application d'authentification, un SMS, un appel téléphonique, ou un e-mail. L'identification en deux étapes peut être activée depuis le coffre web sur bitwarden.com. Voulez-vous vous visiter le site web maintenant ?" + }, + "editedFolder": { + "message": "Dossier modifié" + }, + "deleteFolderConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer ce dossier ?" + }, + "deletedFolder": { + "message": "Dossier supprimé" + }, + "gettingStartedTutorial": { + "message": "Tutoriel" + }, + "gettingStartedTutorialVideo": { + "message": "Regardez notre didacticiel pour savoir comment parfaitement utiliser l'extension du navigateur." + }, + "syncingComplete": { + "message": "Synchronisation terminée" + }, + "syncingFailed": { + "message": "Échec de la synchronisation" + }, + "passwordCopied": { + "message": "Mot de passe copié" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nouvel URI" + }, + "addedItem": { + "message": "Identifiant ajouté" + }, + "editedItem": { + "message": "Identifiant modifié" + }, + "deleteItemConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer cet identifiant ?" + }, + "deletedItem": { + "message": "L'élément a été envoyé dans la corbeille" + }, + "overwritePassword": { + "message": "Écraser le mot de passe" + }, + "overwritePasswordConfirmation": { + "message": "Êtes-vous sûr de vouloir écraser le mot de passe actuel ?" + }, + "overwriteUsername": { + "message": "Remplacer le nom d'utilisateur" + }, + "overwriteUsernameConfirmation": { + "message": "Êtes-vous sûr(e) de vouloir remplacer le nom d'utilisateur actuel ?" + }, + "searchFolder": { + "message": "Rechercher dans le dossier" + }, + "searchCollection": { + "message": "Rechercher dans la collection" + }, + "searchType": { + "message": "Rechercher dans le type" + }, + "noneFolder": { + "message": "Aucun dossier", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Désactiver la notification d'ajout d'identifiant" + }, + "addLoginNotificationDesc": { + "message": "La \"Notification de demande d'ajout d'identifiant\" apparaît automatiquement pour vous proposer d'enregistrer dans votre coffre les identifiants que vous utilisez pour la première fois." + }, + "dontShowCardsCurrentTab": { + "message": "Ne pas afficher les cartes sur la page Onglet courant" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Les cartes stockées dans votre coffre sont listées sur la page \"Onglet courant\" pour un accès facile lors du remplissage automatique." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Ne pas afficher les identités sur la page Onglet courant" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Les identités stockées dans votre coffre sont listées sur la page \"Onglet courant\" pour un accès facile lors du remplissage automatique." + }, + "clearClipboard": { + "message": "Effacer le presse-papiers", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Effacer automatiquement de votre presse-papiers les valeurs copiées.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Est-ce que Bitwarden doit se souvenir de ce mot de passe pour vous ?" + }, + "notificationAddSave": { + "message": "Enregistrer" + }, + "disableChangedPasswordNotification": { + "message": "Désactiver la notification de changement de mot de passe" + }, + "disableChangedPasswordNotificationDesc": { + "message": "La \"Notification de changement de mot de passe\" vous propose automatiquement de mettre à jour un mot de passe dans votre coffre lorsqu'il est changé sur un site web." + }, + "notificationChangeDesc": { + "message": "Souhaitez-vous mettre à jour ce mot de passe dans Bitwarden ?" + }, + "notificationChangeSave": { + "message": "Mettre à jour" + }, + "disableContextMenuItem": { + "message": "Désactiver les options de menu contextuel" + }, + "disableContextMenuItemDesc": { + "message": "Les options du menu contextuel permettent un accès rapide à la génération de mots de passe et aux identifiants enregistrés pour le site web de l'onglet actuel." + }, + "defaultUriMatchDetection": { + "message": "Détection de correspondance URI par défaut", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choisissez la manière par défaut dont la détection de correspondance URI est gérée pour les connexions lors de l'exécution d'actions telles que le remplissage automatique." + }, + "theme": { + "message": "Thème" + }, + "themeDesc": { + "message": "Modifier le thème de couleur de l'application." + }, + "dark": { + "message": "Sombre", + "description": "Dark color" + }, + "light": { + "message": "Clair", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Exporter le coffre" + }, + "fileFormat": { + "message": "Format de fichier" + }, + "warning": { + "message": "AVERTISSEMENT", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirmer l'export du coffre" + }, + "exportWarningDesc": { + "message": "Cet export contient les données de votre coffre dans un format non chiffré. Vous ne devriez ni le stocker ni l'envoyer via des canaux non sécurisés (tel que l'e-mail). Supprimez-le immédiatement après l'avoir utilisé." + }, + "encExportKeyWarningDesc": { + "message": "Cet export chiffre vos données en utilisant la clé de chiffrement de votre compte. Si jamais vous modifiez la clé de chiffrement de votre compte, vous devriez exporter à nouveau car vous ne pourrez pas déchiffrer ce fichier." + }, + "encExportAccountWarningDesc": { + "message": "Les clés de chiffrement du compte sont spécifiques à chaque utilisateur Bitwarden. Vous ne pouvez donc pas importer d'export chiffré dans un compte différent." + }, + "exportMasterPassword": { + "message": "Saisissez votre mot de passe maître pour exporter les données de votre coffre." + }, + "shared": { + "message": "Partagé" + }, + "learnOrg": { + "message": "En savoir plus sur les organisations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden vous permet de partager des éléments de votre coffre avec d'autres personnes en utilisant un compte d'organisation. Souhaitez-vous visiter le site web bitwarden.com pour en savoir plus ?" + }, + "moveToOrganization": { + "message": "Déplacer vers l'organisation" + }, + "share": { + "message": "Partager" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ a été déplacé vers $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choisissez une organisation vers laquelle vous souhaitez déplacer cet élément. Déplacer un élément vers une organisation transfère la propriété de l'élément à cette organisation. Vous ne serez plus le propriétaire direct de cet élément une fois qu'il aura été déplacé." + }, + "learnMore": { + "message": "En savoir plus" + }, + "authenticatorKeyTotp": { + "message": "Clé d'authentification (TOTP)" + }, + "verificationCodeTotp": { + "message": "Code de vérification (TOTP)" + }, + "copyVerificationCode": { + "message": "Copier le code de vérification" + }, + "attachments": { + "message": "Pièces jointes" + }, + "deleteAttachment": { + "message": "Supprimer la pièce jointe" + }, + "deleteAttachmentConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer cette pièce jointe ?" + }, + "deletedAttachment": { + "message": "Pièce jointe supprimée" + }, + "newAttachment": { + "message": "Ajouter une nouvelle pièce jointe" + }, + "noAttachments": { + "message": "Aucune pièce jointe." + }, + "attachmentSaved": { + "message": "La pièce jointe a été enregistrée." + }, + "file": { + "message": "Fichier" + }, + "selectFile": { + "message": "Sélectionnez un fichier." + }, + "maxFileSize": { + "message": "La taille maximale du fichier est de 500 Mo." + }, + "featureUnavailable": { + "message": "Fonctionnalité non disponible" + }, + "updateKey": { + "message": "Vous ne pouvez pas utiliser cette fonctionnalité avant de mettre à jour votre clé de chiffrement." + }, + "premiumMembership": { + "message": "Adhésion Premium" + }, + "premiumManage": { + "message": "Gérer l'adhésion" + }, + "premiumManageAlert": { + "message": "Vous pouvez gérer votre adhésion depuis le coffre web sur bitwarden.com. Souhaitez-vous visiter le site web maintenant ?" + }, + "premiumRefresh": { + "message": "Actualiser l'adhésion" + }, + "premiumNotCurrentMember": { + "message": "Vous n'êtes actuellement pas un membre premium." + }, + "premiumSignUpAndGet": { + "message": "Devenez un membre premium et obtenez :" + }, + "ppremiumSignUpStorage": { + "message": "1 Go de stockage de fichiers chiffrés." + }, + "ppremiumSignUpTwoStep": { + "message": "Options d'identification en deux étapes additionnelles comme YubiKey, FIDO U2F et Duo." + }, + "ppremiumSignUpReports": { + "message": "Rapports sur l'hygiène des mots de passe, la santé des comptes et les fuites de données pour assurer la sécurité de votre coffre." + }, + "ppremiumSignUpTotp": { + "message": "Génération d'un code de vérification TOTP (2FA) pour les identifiants de votre coffre." + }, + "ppremiumSignUpSupport": { + "message": "Support client prioritaire." + }, + "ppremiumSignUpFuture": { + "message": "Toutes les futures options premium. D'autres suivront prochainement !" + }, + "premiumPurchase": { + "message": "Acheter Premium" + }, + "premiumPurchaseAlert": { + "message": "Vous pouvez opter pour une adhésion premium depuis le coffre web sur bitwarden.com. Souhaitez-vous visiter le site web maintenant ?" + }, + "premiumCurrentMember": { + "message": "Vous êtes un adhérent premium !" + }, + "premiumCurrentMemberThanks": { + "message": "Merci de supporter Bitwarden." + }, + "premiumPrice": { + "message": "Tout pour seulement $PRICE$ /an !", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Actualisation terminée" + }, + "disableAutoTotpCopy": { + "message": "Désactiver la copie automatique du TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Si une clé d'authentification est rattachée à votre identifiant, alors le code de vérification TOTP est automatiquement copié dans le presse-papiers lorsque vous renseignez l'identifiant." + }, + "disableAutoBiometricsPrompt": { + "message": "Ne pas demander de biométrie au démarrage" + }, + "premiumRequired": { + "message": "Adhésion Premium requise" + }, + "premiumRequiredDesc": { + "message": "Une adhésion premium est requise pour utiliser cette fonctionnalité." + }, + "enterVerificationCodeApp": { + "message": "Saisissez le code de vérification à 6 chiffres depuis votre application d'authentification." + }, + "enterVerificationCodeEmail": { + "message": "Saisissez le code de vérification à 6 chiffres qui vous a été envoyé par e-mail à $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mail de vérification envoyé à $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Rester connecté" + }, + "sendVerificationCodeEmailAgain": { + "message": "Envoyer à nouveau l'e-mail du code de vérification" + }, + "useAnotherTwoStepMethod": { + "message": "Utiliser une autre méthode d'identification en deux étapes" + }, + "insertYubiKey": { + "message": "Insérez votre YubiKey dans le port USB de votre ordinateur puis appuyez sur son bouton." + }, + "insertU2f": { + "message": "Insérez votre clé de sécurité dans le port USB de votre ordinateur. S'il dispose d'un bouton, appuyez dessus." + }, + "webAuthnNewTab": { + "message": "Pour démarrer la vérification 2FA WebAuthn, cliquez sur le bouton ci-dessous et suivez les instructions dans le nouvel onglet." + }, + "webAuthnNewTabOpen": { + "message": "Ouvrir un nouvel onglet" + }, + "webAuthnAuthenticate": { + "message": "Authentifier WebAuthn" + }, + "loginUnavailable": { + "message": "Connexion impossible" + }, + "noTwoStepProviders": { + "message": "Ce compte dispose d'une identification en deux étapes. Cependant, aucun service d'identification en deux étapes n'est supporté par ce navigateur web." + }, + "noTwoStepProviders2": { + "message": "Merci d'utiliser un navigateur web compatible (comme Chrome) et/ou d'ajouter des services additionnels d'identification en deux étapes qui sont mieux supportés par les navigateurs web (comme par exemple une application d'authentification)." + }, + "twoStepOptions": { + "message": "Options d'identification en deux étapes" + }, + "recoveryCodeDesc": { + "message": "Accès perdu à tous vos services d'authentification à double facteurs ? Utilisez votre code de récupération pour désactiver tous les services de double authentifications sur votre compte." + }, + "recoveryCodeTitle": { + "message": "Code de récupération" + }, + "authenticatorAppTitle": { + "message": "Application d'authentification" + }, + "authenticatorAppDesc": { + "message": "Utiliser une application d'authentification (comme Authy ou Google Authenticator) pour générer des codes de vérification basés sur le temps.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Clé de sécurité YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utiliser une YubiKey pour accéder à votre compte. Fonctionne avec les appareils YubiKey 4, 4 Nano, 4C et NEO." + }, + "duoDesc": { + "message": "S'authentifier avec Duo Security via l'application Duo Mobile, un SMS, un appel téléphonique, ou une clé de sécurité U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Sécurisez votre organisation avec Duo Security à l'aide de l'application Duo Mobile, l'envoi d'un SMS, un appel vocal ou une clé de sécurité U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "WebAuthn FIDO2" + }, + "webAuthnDesc": { + "message": "Utilisez n'importe quelle clé de sécurité compatible WebAuthn pour accéder à votre compte." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Les codes de vérification vont vous être envoyés par e-mail." + }, + "selfHostedEnvironment": { + "message": "Environnement auto-hébergé" + }, + "selfHostedEnvironmentFooter": { + "message": "Spécifiez l'URL de base de votre installation Bitwarden auto-hébergée." + }, + "customEnvironment": { + "message": "Environnement personnalisé" + }, + "customEnvironmentFooter": { + "message": "Pour utilisateurs avancés. Vous pouvez spécifier une URL de base indépendante pour chaque service." + }, + "baseUrl": { + "message": "URL du serveur" + }, + "apiUrl": { + "message": "URL du serveur de l'API" + }, + "webVaultUrl": { + "message": "URL du serveur du coffre web" + }, + "identityUrl": { + "message": "URL du serveur d'identification" + }, + "notificationsUrl": { + "message": "URL du serveur de notifications" + }, + "iconsUrl": { + "message": "URL du serveur d’icônes" + }, + "environmentSaved": { + "message": "Les URLs d'environnement ont été enregistrées." + }, + "enableAutoFillOnPageLoad": { + "message": "Activer le remplissage automatique au chargement de la page" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Si un formulaire de connexion est détecté, remplir automatiquement les champs au chargement de la page web." + }, + "experimentalFeature": { + "message": "Ceci est actuellement une fonctionnalité expérimentale. À utiliser avec prudence." + }, + "defaultAutoFillOnPageLoad": { + "message": "Paramètre de saisie automatique par défaut pour les identifiants" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Après avoir activé le remplissage automatique au chargement de la page, vous pourrez activer ou désactiver la fonctionnalité pour chaque identifiant. Ceci est le paramètre par défaut pour les identifiants qui ne sont pas configurés individuellement." + }, + "itemAutoFillOnPageLoad": { + "message": "Remplissage automatique au chargement de la page (si activé dans les options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Utiliser le paramètre par défaut" + }, + "autoFillOnPageLoadYes": { + "message": "Remplissage automatique au chargement de la page" + }, + "autoFillOnPageLoadNo": { + "message": "Ne pas remplir automatiquement au chargement de la page" + }, + "commandOpenPopup": { + "message": "Ouvrir la popup du coffre" + }, + "commandOpenSidebar": { + "message": "Ouvrir le coffre dans la barre latérale" + }, + "commandAutofillDesc": { + "message": "Remplir automatiquement le dernier identifiant utilisé pour le site web actuel." + }, + "commandGeneratePasswordDesc": { + "message": "Générer et copier un nouveau mot de passe aléatoire dans le presse-papiers." + }, + "commandLockVaultDesc": { + "message": "Verrouiller le coffre" + }, + "privateModeWarning": { + "message": "La prise en charge de la navigation privée est expérimentale et certaines fonctionnalités sont limitées." + }, + "customFields": { + "message": "Champs personnalisés" + }, + "copyValue": { + "message": "Copier la valeur" + }, + "value": { + "message": "Valeur" + }, + "newCustomField": { + "message": "Nouveau champ personnalisé" + }, + "dragToSort": { + "message": "Glissez pour trier" + }, + "cfTypeText": { + "message": "Texte" + }, + "cfTypeHidden": { + "message": "Masqué" + }, + "cfTypeBoolean": { + "message": "Booléen" + }, + "cfTypeLinked": { + "message": "Lié", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Valeur liée", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Le fait de cliquer à l'extérieur de la fenêtre pop-up pour vérifier votre e-mail avec votre code de vérification fermera cette pop-up. Voulez-vous ouvrir cette pop-up dans une nouvelle fenêtre pour qu'elle ne soit pas fermée ?" + }, + "popupU2fCloseMessage": { + "message": "Ce navigateur ne peut pas traiter les requêtes U2F dans cette popup. Voulez-vous ouvrir cette popup dans une nouvelle fenêtre pour que vous puissiez vous connecter en utilisant U2F ?" + }, + "disableFavicon": { + "message": "Désactiver les icônes des sites web" + }, + "disableFaviconDesc": { + "message": "Les icônes des sites web permettent d'avoir une icône reconnaissable à côté de chaque identifiant dans votre coffre." + }, + "disableBadgeCounter": { + "message": "Désactiver le compteur de badge" + }, + "disableBadgeCounterDesc": { + "message": "Le compteur de badge indique le nombre d'identifiants vous avez pour la page actuelle dans votre coffre." + }, + "cardholderName": { + "message": "Nom du titulaire de la carte" + }, + "number": { + "message": "Numéro" + }, + "brand": { + "message": "Réseau de paiement" + }, + "expirationMonth": { + "message": "Mois d'expiration" + }, + "expirationYear": { + "message": "Année d'expiration" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "Janvier" + }, + "february": { + "message": "Février" + }, + "march": { + "message": "Mars" + }, + "april": { + "message": "Avril" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juin" + }, + "july": { + "message": "Juillet" + }, + "august": { + "message": "Août" + }, + "september": { + "message": "Septembre" + }, + "october": { + "message": "Octobre" + }, + "november": { + "message": "Novembre" + }, + "december": { + "message": "Décembre" + }, + "securityCode": { + "message": "Code de sécurité" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Titre" + }, + "mr": { + "message": "M." + }, + "mrs": { + "message": "Mme" + }, + "ms": { + "message": "Mlle" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Prénom" + }, + "middleName": { + "message": "Deuxième prénom" + }, + "lastName": { + "message": "Nom" + }, + "fullName": { + "message": "Nom et prénom" + }, + "identityName": { + "message": "Identité" + }, + "company": { + "message": "Société" + }, + "ssn": { + "message": "Numéro de sécurité sociale" + }, + "passportNumber": { + "message": "Numéro de passeport" + }, + "licenseNumber": { + "message": "Numéro de permis" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Téléphone" + }, + "address": { + "message": "Adresse" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "Ville" + }, + "stateProvince": { + "message": "État / Région" + }, + "zipPostalCode": { + "message": "Code postal" + }, + "country": { + "message": "Pays" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Identifiant" + }, + "typeLogins": { + "message": "Identifiants" + }, + "typeSecureNote": { + "message": "Note sécurisée" + }, + "typeCard": { + "message": "Carte de paiement" + }, + "typeIdentity": { + "message": "Identité" + }, + "passwordHistory": { + "message": "Historique des mots de passe" + }, + "back": { + "message": "Retour" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favoris" + }, + "popOutNewWindow": { + "message": "Ouvrir dans une nouvelle fenêtre" + }, + "refresh": { + "message": "Actualiser" + }, + "cards": { + "message": "Cartes de paiement" + }, + "identities": { + "message": "Identités" + }, + "logins": { + "message": "Identifiants" + }, + "secureNotes": { + "message": "Notes sécurisées" + }, + "clear": { + "message": "Effacer", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Vérifier si le mot de passe a été exposé." + }, + "passwordExposed": { + "message": "Ce mot de passe a été exposé $VALUE$ fois dans des fuites de données. Vous devriez le changer.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Ce mot de passe n'a été trouvé dans aucune fuite de données connue. Il semble sécurisé." + }, + "baseDomain": { + "message": "Domaine de base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nom de domaine", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Hôte", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Commence par" + }, + "regEx": { + "message": "Expression régulière", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Détection de correspondance", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Détection de correspondance par défaut", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Afficher/masquer les options" + }, + "toggleCurrentUris": { + "message": "Afficher/masquer les URIs actuels", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI actuel", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "Tous les éléments" + }, + "noPasswordsInList": { + "message": "Aucun mot de passe à afficher." + }, + "remove": { + "message": "Supprimer" + }, + "default": { + "message": "Par défaut" + }, + "dateUpdated": { + "message": "Mis à jour", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Mot de passe mis à jour", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Êtes-vous sûr de vouloir utiliser l'option \"Jamais\" ? Définir le verrouillage sur \"Jamais\" stocke la clé de chiffrement de votre coffre sur votre appareil. Si vous utilisez cette option, vous devez vous assurer de correctement protéger votre appareil." + }, + "noOrganizationsList": { + "message": "Vous ne faites partie d'aucune organisation. Les organisations vous permettent de partager des éléments de façon sécurisée avec d'autres utilisateurs." + }, + "noCollectionsInList": { + "message": "Aucune collection à afficher." + }, + "ownership": { + "message": "Propriété" + }, + "whoOwnsThisItem": { + "message": "À qui appartient cet élément ?" + }, + "strong": { + "message": "Fort", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Suffisant", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Faible", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Mot de passe maître faible" + }, + "weakMasterPasswordDesc": { + "message": "Le mot de passe maître que vous avez choisi est faible. Vous devriez utiliser un mot de passe (ou une phrase de passe) fort(e) pour protéger correctement votre compte Bitwarden. Êtes-vous sûr de vouloir utiliser ce mot de passe maître ?" + }, + "pin": { + "message": "Code PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Déverrouiller avec un code PIN" + }, + "setYourPinCode": { + "message": "Définissez votre code PIN pour déverrouiller Bitwarden. Les paramètres relatifs à votre code PIN seront réinitialisés si vous vous déconnectez complètement de l'application." + }, + "pinRequired": { + "message": "Le code PIN est requis." + }, + "invalidPin": { + "message": "Code PIN invalide." + }, + "unlockWithBiometrics": { + "message": "Déverrouiller par biométrie" + }, + "awaitDesktop": { + "message": "En attente de confirmation de l'application de bureau" + }, + "awaitDesktopDesc": { + "message": "Veuillez confirmer l'utilisation de la biométrie dans l'application Bitwarden de bureau pour activer la biométrie dans le navigateur." + }, + "lockWithMasterPassOnRestart": { + "message": "Verrouiller avec le mot de passe maître lors du redémarrage du navigateur." + }, + "selectOneCollection": { + "message": "Vous devez sélectionner au moins une collection." + }, + "cloneItem": { + "message": "Cloner l’élément" + }, + "clone": { + "message": "Cloner" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Une ou plusieurs politiques d'organisation affectent les paramètres de votre générateur." + }, + "vaultTimeoutAction": { + "message": "Action lors de l'expiration du délai du coffre" + }, + "lock": { + "message": "Verrouiller", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Corbeille", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Rechercher dans la corbeille" + }, + "permanentlyDeleteItem": { + "message": "Supprimer définitivement l'élément" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer définitivement cet élément ?" + }, + "permanentlyDeletedItem": { + "message": "Élément supprimé définitivement" + }, + "restoreItem": { + "message": "Restaurer l'élément" + }, + "restoreItemConfirmation": { + "message": "Êtes-vous sûr de vouloir restaurer cet élément ?" + }, + "restoredItem": { + "message": "Élément restauré" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "La déconnexion supprimera tous les accès à votre coffre et nécessite une authentification en ligne après la période d'expiration. Êtes-vous sûr de vouloir utiliser ce paramètre?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmation de l'action lors de l'expiration du délai" + }, + "autoFillAndSave": { + "message": "Remplir automatiquement et enregistrer" + }, + "autoFillSuccessAndSavedUri": { + "message": "Élément rempli automatiquement et URI sauvegardée" + }, + "autoFillSuccess": { + "message": "Élément rempli automatiquement" + }, + "setMasterPassword": { + "message": "Définir le mot de passe maître" + }, + "masterPasswordPolicyInEffect": { + "message": "Une ou plusieurs politiques de l'organisation exigent que votre mot de passe maître réponde aux exigences suivantes :" + }, + "policyInEffectMinComplexity": { + "message": "Score de complexité minimum de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Longueur minimale de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contenir une ou plusieurs majuscules" + }, + "policyInEffectLowercase": { + "message": "Contenir une ou plusieurs minuscules" + }, + "policyInEffectNumbers": { + "message": "Contenir un ou plusieurs chiffres" + }, + "policyInEffectSpecial": { + "message": "Contenir un ou plusieurs des caractères spéciaux suivants $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Votre nouveau mot de passe maître ne répond pas aux exigences de la politique." + }, + "acceptPolicies": { + "message": "En cochant cette case, vous acceptez les éléments suivants :" + }, + "acceptPoliciesError": { + "message": "Les conditions d'utilisation et la politique de confidentialité n'ont pas été acceptées." + }, + "termsOfService": { + "message": "Conditions d'utilisation" + }, + "privacyPolicy": { + "message": "Politique de confidentialité" + }, + "hintEqualsPassword": { + "message": "Votre indice de mot de passe ne peut pas être identique à votre mot de passe." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Vérification de la synchronisation avec l'application de bureau" + }, + "desktopIntegrationVerificationText": { + "message": "Veuillez vérifier que l'application de bureau affiche cette phrase d'empreinte : " + }, + "desktopIntegrationDisabledTitle": { + "message": "L'intégration avec le navigateur n'est pas activée" + }, + "desktopIntegrationDisabledDesc": { + "message": "L'intégration avec le navigateur n'est pas activée dans l'application de bureau Bitwarden. Veuillez l'activer dans les paramètres de l'application de bureau." + }, + "startDesktopTitle": { + "message": "Démarrer l'application de bureau Bitwarden." + }, + "startDesktopDesc": { + "message": "L'application de bureau Bitwarden doit être démarrée avant que le déverrouillage par biométrie puisse être utilisé." + }, + "errorEnableBiometricTitle": { + "message": "Impossible d'activer la biométrie" + }, + "errorEnableBiometricDesc": { + "message": "L'action a été annulée par l'application de bureau" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "L'application de bureau a invalidé le canal de communication sécurisé. Veuillez réessayer cette opération" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Communication interrompue avec l'application de bureau" + }, + "nativeMessagingWrongUserDesc": { + "message": "L'application de bureau est connectée à un autre compte. Veuillez vous assurer que les deux applications sont connectées au même compte." + }, + "nativeMessagingWrongUserTitle": { + "message": "Erreur de correspondance entre les comptes" + }, + "biometricsNotEnabledTitle": { + "message": "Le déverrouillage biométrique n'est pas activé" + }, + "biometricsNotEnabledDesc": { + "message": "Les options de biométrie dans le navigateur nécessitent au préalable l'activation des options de biométrie dans l'application de bureau." + }, + "biometricsNotSupportedTitle": { + "message": "Le déverrouillage biométrique n'est pas pris en charge" + }, + "biometricsNotSupportedDesc": { + "message": "Le déverrouillage biométrique dans le navigateur n’est pas pris en charge sur cet appareil" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission non accordée" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Sans la permission de communiquer avec l'application de bureau Bitwarden, nous ne pouvons pas activer le déverrouillage biométrique dans l'extension navigateur. Veuillez réessayer." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Erreur de demande de permission" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Cette action ne peut pas être effectuée dans la barre latérale, veuillez réessayer l'action dans la popup ou la nouvelle fenêtre." + }, + "personalOwnershipSubmitError": { + "message": "En raison d'une politique d'entreprise, il vous est interdit d'enregistrer des éléments dans votre coffre personnel. Sélectionnez une organisation dans l'option Propriété et choisissez parmi les collections disponibles." + }, + "personalOwnershipPolicyInEffect": { + "message": "Une politique d'organisation affecte vos options de propriété." + }, + "excludedDomains": { + "message": "Domaines exclus" + }, + "excludedDomainsDesc": { + "message": "Bitwarden ne proposera pas d'enregistrer les informations de connexion pour ces domaines. Vous devez actualiser la page pour que les modifications prennent effet." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ n'est pas un domaine valide", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Rechercher dans les Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Ajouter un Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Texte" + }, + "sendTypeFile": { + "message": "Fichier" + }, + "allSends": { + "message": "Tous les Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Nombre maximum d'accès atteint", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expiré" + }, + "pendingDeletion": { + "message": "En attente de suppression" + }, + "passwordProtected": { + "message": "Protégé par un mot de passe" + }, + "copySendLink": { + "message": "Copier le lien du Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Supprimer le mot de passe" + }, + "delete": { + "message": "Supprimer" + }, + "removedPassword": { + "message": "Mot de passe supprimé" + }, + "deletedSend": { + "message": "Send supprimé", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Lien du Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Désactivé" + }, + "removePasswordConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer le mot de passe ?" + }, + "deleteSend": { + "message": "Supprimer le Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer ce Send ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Modifier le Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "De quel type de Send s'agit-il ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Un nom convivial pour décrire ce Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Le fichier que vous voulez envoyer." + }, + "deletionDate": { + "message": "Date de suppression" + }, + "deletionDateDesc": { + "message": "Le Send sera définitivement supprimé à la date et heure spécifiées.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Date d'expiration" + }, + "expirationDateDesc": { + "message": "Si défini, l'accès à ce Send expirera à la date et heure spécifiées.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 jour" + }, + "days": { + "message": "$DAYS$ jours", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Personnalisé" + }, + "maximumAccessCount": { + "message": "Nombre maximum d'accès" + }, + "maximumAccessCountDesc": { + "message": "Si défini, les utilisateurs ne seront plus en mesure d'accéder à ce Send une fois que le nombre maximum d'accès sera atteint.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Vous pouvez, si vous le souhaitez, exiger un mot de passe pour accéder à ce Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notes privées à propos de ce Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Désactiver ce Send pour que personne ne puisse y accéder.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copier dans le presse-papiers le lien de ce Send lors de l'enregistrement.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Le texte que vous voulez envoyer." + }, + "sendHideText": { + "message": "Cacher par défaut le texte de ce Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Nombre d'accès actuel" + }, + "createSend": { + "message": "Créer un nouveau Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nouveau mot de passe" + }, + "sendDisabled": { + "message": "Send désactivé", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "En raison d'une politique d'entreprise, vous ne pouvez que supprimer un Send existant.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send créé", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send modifié", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Pour choisir un fichier, ouvrez l'extension dans la barre latérale (si possible) ou ouvrez une nouvelle fenêtre en cliquant sur cette bannière." + }, + "sendFirefoxFileWarning": { + "message": "Afin de choisir un fichier en utilisant Firefox, ouvrez l'extension dans la barre latérale ou ouvrez une nouvelle fenêtre en cliquant sur cette bannière." + }, + "sendSafariFileWarning": { + "message": "Pour choisir un fichier avec Safari, ouvrez une nouvelle fenêtre en cliquant sur cette bannière." + }, + "sendFileCalloutHeader": { + "message": "Avant de commencer" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Pour utiliser un sélecteur de date en forme de calendrier,", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "cliquez ici", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "pour ouvrir une nouvelle fenêtre.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "La date d'expiration indiquée n'est pas valide." + }, + "deletionDateIsInvalid": { + "message": "La date de suppression indiquée n'est pas valide." + }, + "expirationDateAndTimeRequired": { + "message": "Une date et une heure d'expiration sont requises." + }, + "deletionDateAndTimeRequired": { + "message": "Une date et une heure de suppression sont requises." + }, + "dateParsingError": { + "message": "Une erreur s'est produite lors de l'enregistrement de vos dates de suppression et d'expiration." + }, + "hideEmail": { + "message": "Cacher mon adresse e-mail aux destinataires." + }, + "sendOptionsPolicyInEffect": { + "message": "Une ou plusieurs politiques d'organisation affectent vos options Send." + }, + "passwordPrompt": { + "message": "Ressaisie du mot de passe maître" + }, + "passwordConfirmation": { + "message": "Confirmation du mot de passe maître" + }, + "passwordConfirmationDesc": { + "message": "Cette action est protégée. Pour continuer, veuillez ressaisir votre mot de passe maître pour vérifier votre identité." + }, + "emailVerificationRequired": { + "message": "Vérification de l'adresse e-mail nécessaire" + }, + "emailVerificationRequiredDesc": { + "message": "Vous devez vérifier votre adresse e-mail pour utiliser cette fonctionnalité. Vous pouvez vérifier votre adresse e-mail dans le coffre web." + }, + "updatedMasterPassword": { + "message": "Mot de passe maître mis à jour" + }, + "updateMasterPassword": { + "message": "Mettre à jour le mot de passe maître" + }, + "updateMasterPasswordWarning": { + "message": "Votre mot de passe maître a récemment été modifié par un administrateur de votre organisation. Pour pouvoir accéder au coffre-fort, vous devez mettre à jour votre mot de passe maître maintenant. Poursuivre vous déconnectera de votre session actuelle, vous obligeant à vous reconnecter. Les sessions actives sur d'autres appareils peuvent rester actives jusqu'à une heure." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscription automatique" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Cette organisation a une politique d'entreprise qui vous inscrira automatiquement à la réinitialisation du mot de passe. L'inscription permettra aux administrateurs de l'organisation de changer votre mot de passe maître." + }, + "selectFolder": { + "message": "Sélectionnez un dossier..." + }, + "ssoCompleteRegistration": { + "message": "Afin de terminer la connexion avec SSO, veuillez définir un mot de passe maître pour accéder à votre coffre et le protéger." + }, + "hours": { + "message": "Heures" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Les politiques de votre organisation affectent le délai d'expiration de votre coffre-fort. Le délai d'expiration maximal autorisé est de $HOURS$ heure(s) et $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Le délai d'expiration de votre coffre dépasse les restrictions définies par votre organisation." + }, + "vaultExportDisabled": { + "message": "Export du coffre désactivé" + }, + "personalVaultExportPolicyInEffect": { + "message": "Une ou plusieurs politiques d'organisation vous empêchent d'exporter votre coffre personnel." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Aucun élément de formulaire valide n'a pu être identifié. Essayez plutôt d'inspecter le HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Aucun identifiant unique trouvé." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ utilise SSO avec un serveur de clés auto-hébergé. Un mot de passe maître n'est plus nécessaire aux membres de cette organisation pour se connecter.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Quitter l'organisation" + }, + "removeMasterPassword": { + "message": "Supprimer le mot de passe maître" + }, + "removedMasterPassword": { + "message": "Mot de passe maître supprimé." + }, + "leaveOrganizationConfirmation": { + "message": "Êtes-vous sûr·e de vouloir quitter cette organisation ?" + }, + "leftOrganization": { + "message": "Vous avez quitté l'organisation." + }, + "toggleCharacterCount": { + "message": "Activer/désactiver le compteur de caractères" + }, + "sessionTimeout": { + "message": "Votre session a expiré. Veuillez revenir en arrière et essayer de vous connecter à nouveau." + }, + "exportingPersonalVaultTitle": { + "message": "Export du coffre personnel" + }, + "exportingPersonalVaultDescription": { + "message": "Seuls les éléments du coffre personnel associé à l'adresse e-mail $EMAIL$ seront exportés. Les éléments du coffre de l'organisation ne seront pas inclus.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Erreur" + }, + "regenerateUsername": { + "message": "Régénérer un nom d'utilisateur" + }, + "generateUsername": { + "message": "Générer un nom d'utilisateur" + }, + "usernameType": { + "message": "Type de nom d'utilisateur" + }, + "plusAddressedEmail": { + "message": "E-mail suffixé", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Utilisez les capacités de sous-adressage de votre fournisseur d'e-mail." + }, + "catchallEmail": { + "message": "Collecteur d'e-mail" + }, + "catchallEmailDesc": { + "message": "Utilisez la boîte de réception du collecteur configurée de votre domaine." + }, + "random": { + "message": "Aléatoire" + }, + "randomWord": { + "message": "Mots aléatoire" + }, + "websiteName": { + "message": "Nom du site Web" + }, + "whatWouldYouLikeToGenerate": { + "message": "Que souhaitez-vous générer ?" + }, + "passwordType": { + "message": "Type de mot de passe" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/he/messages.json b/apps/browser/src/_locales/he/messages.json new file mode 100644 index 0000000000..d6c149582a --- /dev/null +++ b/apps/browser/src/_locales/he/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - מנהל סיסמאות חינמי", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "מנהל סיסמאות חינמי ומאובטח עבור כל המכשירים שלך.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "צור חשבון חדש או התחבר כדי לגשת לכספת המאובטחת שלך." + }, + "createAccount": { + "message": "צור חשבון" + }, + "login": { + "message": "התחבר" + }, + "enterpriseSingleSignOn": { + "message": "כניסה אחודה ארגונית" + }, + "cancel": { + "message": "בטל" + }, + "close": { + "message": "סגור" + }, + "submit": { + "message": "שלח" + }, + "emailAddress": { + "message": "כתובת אימייל" + }, + "masterPass": { + "message": "סיסמה ראשית" + }, + "masterPassDesc": { + "message": "הסיסמה הראשית היא הסיסמה שבאמצעותה תיגש לכספת שלך. חשוב מאוד שלא תשכח את הסיסמה הזו. אין שום דרך לשחזר אותה במקרה ושכחת אותה." + }, + "masterPassHintDesc": { + "message": "ניתן להשתמש ברמז לסיסמה הראשית אם שכחת אותה." + }, + "reTypeMasterPass": { + "message": "הקלד שוב סיסמה ראשית" + }, + "masterPassHint": { + "message": "רמז לסיסמה ראשית (אופציונאלי)" + }, + "tab": { + "message": "לשונית" + }, + "myVault": { + "message": "הכספת שלי" + }, + "tools": { + "message": "כלים" + }, + "settings": { + "message": "הגדרות" + }, + "currentTab": { + "message": "לשונית נוכחית" + }, + "copyPassword": { + "message": "העתק סיסמה" + }, + "copyNote": { + "message": "העתק פתק" + }, + "copyUri": { + "message": "העתק שורת כתובת" + }, + "copyUsername": { + "message": "העתק שם משתמש" + }, + "copyNumber": { + "message": "העתק מספר" + }, + "copySecurityCode": { + "message": "העתק קוד אבטחה" + }, + "autoFill": { + "message": "השלמה אוטומטית" + }, + "generatePasswordCopied": { + "message": "צור סיסמה חדשה (והעתק לזיכרון)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "לא נמצאו פרטי כניסה תואמים." + }, + "unlockVaultMenu": { + "message": "שחרור הכספת שלך" + }, + "loginToVaultMenu": { + "message": "כניסה לכספת שלך" + }, + "autoFillInfo": { + "message": "לא נמצאו פרטי כניסה להשלמה אוטומטית בלשונית הנוכחית בדפדפן." + }, + "addLogin": { + "message": "הוסף פרטי כניסה" + }, + "addItem": { + "message": "הוסף פריט" + }, + "passwordHint": { + "message": "רמז לסיסמה" + }, + "enterEmailToGetHint": { + "message": "הכנס את פרטי האימייל שלך לקבלת רמז עבור הסיסמה הראשית." + }, + "getMasterPasswordHint": { + "message": "הצג את הרמז לסיסמה הראשית" + }, + "continue": { + "message": "המשך" + }, + "sendVerificationCode": { + "message": "שליחת קוד אימות לדוא״ל שלך" + }, + "sendCode": { + "message": "שליחת קוד" + }, + "codeSent": { + "message": "קוד נשלח" + }, + "verificationCode": { + "message": "קוד אימות" + }, + "confirmIdentity": { + "message": "יש לאשר את זהותך כדי להמשיך." + }, + "account": { + "message": "חשבון" + }, + "changeMasterPassword": { + "message": "החלף סיסמה ראשית" + }, + "fingerprintPhrase": { + "message": "סיסמת טביעת אצבע", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "הסיסמה של טביעת האצבעות בחשבון שלך", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "התחברות בשני-שלבים" + }, + "logOut": { + "message": "התנתק" + }, + "about": { + "message": "אודות" + }, + "version": { + "message": "גירסה" + }, + "save": { + "message": "שמור" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "הוסף תיקייה" + }, + "name": { + "message": "שם" + }, + "editFolder": { + "message": "ערוך תיקייה" + }, + "deleteFolder": { + "message": "מחק תיקייה" + }, + "folders": { + "message": "תיקיות" + }, + "noFolders": { + "message": "אין תיקיות להצגה." + }, + "helpFeedback": { + "message": "עזרה ומשוב" + }, + "sync": { + "message": "סנכרן" + }, + "syncVaultNow": { + "message": "סנכרן את הכספת עכשיו" + }, + "lastSync": { + "message": "סנכרון אחרון:" + }, + "passGen": { + "message": "יוצר הסיסמאות" + }, + "generator": { + "message": "מייצר", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "צור אוטומטית סיסמאות חזקות ויחודיות עבור פרטי הכניסה שלך." + }, + "bitWebVault": { + "message": "כספת באתר Bitwarden" + }, + "importItems": { + "message": "יבא פריטים" + }, + "select": { + "message": "בחר" + }, + "generatePassword": { + "message": "צור סיסמה" + }, + "regeneratePassword": { + "message": "צור סיסמה חדשה" + }, + "options": { + "message": "אפשרויות" + }, + "length": { + "message": "אורך" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "מספר מילים" + }, + "wordSeparator": { + "message": "מפריד מילים" + }, + "capitalize": { + "message": "הפוך אותיות ראשונות לאותיות גדולות", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "כלול מספרים" + }, + "minNumbers": { + "message": "מינימום ספרות" + }, + "minSpecial": { + "message": "מינימום תוים מיוחדים" + }, + "avoidAmbChar": { + "message": "המנע מאותיות ותוים דומים" + }, + "searchVault": { + "message": "חיפוש בכספת" + }, + "edit": { + "message": "ערוך" + }, + "view": { + "message": "הצג" + }, + "noItemsInList": { + "message": "אין פריטים להצגה." + }, + "itemInformation": { + "message": "מידע על הפריט" + }, + "username": { + "message": "שם משתמש" + }, + "password": { + "message": "סיסמה" + }, + "passphrase": { + "message": "משפט סיסמה" + }, + "favorite": { + "message": "מועדף" + }, + "notes": { + "message": "הערות" + }, + "note": { + "message": "הערה" + }, + "editItem": { + "message": "ערוך פריט" + }, + "folder": { + "message": "תיקייה" + }, + "deleteItem": { + "message": "מחק פריט" + }, + "viewItem": { + "message": "צפה בפריט" + }, + "launch": { + "message": "הפעל" + }, + "website": { + "message": "אתר" + }, + "toggleVisibility": { + "message": "הצג או הסתר" + }, + "manage": { + "message": "נהל" + }, + "other": { + "message": "אחר" + }, + "rateExtension": { + "message": "דירוג הרחבה" + }, + "rateExtensionDesc": { + "message": "אם נהנית מהתוכנה, בבקשה דרג את התוכנה וכתוב דירוג עם חוות דעת טובה!" + }, + "browserNotSupportClipboard": { + "message": "הדפדפן שלך לא תומך בהעתקה ללוח. אנא העתק בצורה ידנית." + }, + "verifyIdentity": { + "message": "אימות זהות" + }, + "yourVaultIsLocked": { + "message": "הכספת שלך נעולה. הזן את הסיסמה הראשית שלך כדי להמשיך." + }, + "unlock": { + "message": "בטל נעילה" + }, + "loggedInAsOn": { + "message": "מחובר כ $EMAIL$ באתר $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "סיסמה ראשית שגויה" + }, + "vaultTimeout": { + "message": "משך זמן מירבי עבור חיבור לכספת" + }, + "lockNow": { + "message": "נעל עכשיו" + }, + "immediately": { + "message": "באופן מיידי" + }, + "tenSeconds": { + "message": "10 שניות" + }, + "twentySeconds": { + "message": "20 שניות" + }, + "thirtySeconds": { + "message": "30 שניות" + }, + "oneMinute": { + "message": "דקה" + }, + "twoMinutes": { + "message": "2 דקות" + }, + "fiveMinutes": { + "message": "5 דקות" + }, + "fifteenMinutes": { + "message": "15 דקות" + }, + "thirtyMinutes": { + "message": "30 דקות" + }, + "oneHour": { + "message": "שעה" + }, + "fourHours": { + "message": "4 שעות" + }, + "onLocked": { + "message": "בזמן נעילת המערכת" + }, + "onRestart": { + "message": "בהפעלת הדפדפן מחדש" + }, + "never": { + "message": "לעולם לא" + }, + "security": { + "message": "אבטחה" + }, + "errorOccurred": { + "message": "אירעה שגיאה" + }, + "emailRequired": { + "message": "נדרשת כתובת אימייל." + }, + "invalidEmail": { + "message": "כתובת אימייל לא תקינה." + }, + "masterPassRequired": { + "message": "יש להזין את הסיסמה הראשית." + }, + "masterPassLength": { + "message": "הסיסמה הראשית חייבת להיות לפחות באורך 8 תווים." + }, + "masterPassDoesntMatch": { + "message": "שדה אימות סיסמה ראשית לא תואם." + }, + "newAccountCreated": { + "message": "החשבון שלך נוצר בהצלחה! כעת ניתן להכנס למערכת." + }, + "masterPassSent": { + "message": "שלחנו לך אימייל עם רמז לסיסמה הראשית." + }, + "verificationCodeRequired": { + "message": "נדרש קוד אימות." + }, + "invalidVerificationCode": { + "message": "קוד אימות שגוי" + }, + "valueCopied": { + "message": "השדה $VALUE$ הועתק לזיכרון", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "לא הצלחנו לבצע פעולת השלמה האוטומטית בעמוד זה. אנא העתק והדבק את המידע הנחוץ בצורה ידנית." + }, + "loggedOut": { + "message": "בוצעה יציאה" + }, + "loginExpired": { + "message": "תוקף החיבור שלך הסתיים." + }, + "logOutConfirmation": { + "message": "האם אתה בטוח שברצונך להתנתק?" + }, + "yes": { + "message": "כן" + }, + "no": { + "message": "לא" + }, + "unexpectedError": { + "message": "אירעה שגיאה לא צפויה." + }, + "nameRequired": { + "message": "דרוש שם." + }, + "addedFolder": { + "message": "נוספה תיקייה" + }, + "changeMasterPass": { + "message": "החלף סיסמה ראשית" + }, + "changeMasterPasswordConfirmation": { + "message": "באפשרותך לשנות את הסיסמה הראשית שלך דרך הכספת באתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "twoStepLoginConfirmation": { + "message": "התחברות בשני-שלבים הופכת את החשבון שלך למאובטח יותר בכך שאתה נדרש לוודא בכל כניסה בעזרת מכשיר אחר כדוגמת מפתח אבטחה, תוכנת אימות, SMS, שיחת טלפון, או אימייל. ניתן להפעיל את \"התחברות בשני-שלבים\" בכספת שבאתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "editedFolder": { + "message": "תיקייה שנערכה" + }, + "deleteFolderConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק את התיקייה?" + }, + "deletedFolder": { + "message": "תיקייה שנמחקה" + }, + "gettingStartedTutorial": { + "message": "מדריך שימוש ראשוני" + }, + "gettingStartedTutorialVideo": { + "message": "צפה במדריך השימוש הראשוני כדי ללמוד איך לנצל את המקסימום שהתוסף לדפדפן יכול להציע." + }, + "syncingComplete": { + "message": "הסינכרון הושלם" + }, + "syncingFailed": { + "message": "הסינכרון נכשל" + }, + "passwordCopied": { + "message": "הסיסמה הועתקה" + }, + "uri": { + "message": "כתובת" + }, + "uriPosition": { + "message": "כתובת $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "כתובת חדשה" + }, + "addedItem": { + "message": "פריט שהתווסף" + }, + "editedItem": { + "message": "פריט שנערך" + }, + "deleteItemConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק פריט זה?" + }, + "deletedItem": { + "message": "פריט נשלח לסל המחזור" + }, + "overwritePassword": { + "message": "דרוס סיסמה" + }, + "overwritePasswordConfirmation": { + "message": "האם אתה בטוח שברצונך לדרוס את הסיסמה הנוכחית?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "חפש תיקייה" + }, + "searchCollection": { + "message": "חפש אוסף" + }, + "searchType": { + "message": "חפש סוג" + }, + "noneFolder": { + "message": "ללא תיקייה", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "בטל את ההודעה \"שמור פרטי כניסה\"" + }, + "addLoginNotificationDesc": { + "message": "ההודעה \"שמור פרטי כניסה\" מופיעה בכל פעם שתכנס לאתר חדש בפעם הראשונה." + }, + "dontShowCardsCurrentTab": { + "message": "אל תציג כרטיסים העמוד הלשונית" + }, + "dontShowCardsCurrentTabDesc": { + "message": "פרטי כרטיס מהכספת שלך מופיעים בעמוד 'הלשונית הנוכחית' לגישה קלה להשלמה האוטומטית." + }, + "dontShowIdentitiesCurrentTab": { + "message": "אל תציג זהויות בעמוד הלשונית" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "פרטי זהות מהכספת שלך מופיעים בעמוד 'הלשונית הנוכחית' לגישה קלה להשלמה האוטומטית." + }, + "clearClipboard": { + "message": "נקה לוח העתקות", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "נקה אוטומטית ערכים שהועתקו ללוח ההעתקות (clipboard).", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "האם ברצונך שתוכנת Bitwarden תזכור סיסמה זו עבורך?" + }, + "notificationAddSave": { + "message": "כן, שמור עכשיו" + }, + "disableChangedPasswordNotification": { + "message": "בטל התראת \"סיסמה שונתה\"" + }, + "disableChangedPasswordNotificationDesc": { + "message": "ההתראה \"סיסמה שונתה\" תופיע בכל פעם שהמערכת מזהה שינוי בסיסמה באתר אם פרטי הכניסה הקודמים שמורים שבכספת." + }, + "notificationChangeDesc": { + "message": "האם ברצונך לעדכן את הסיסמה הזו בתוכנת Bitwarden?" + }, + "notificationChangeSave": { + "message": "כן, עדכן עכשיו" + }, + "disableContextMenuItem": { + "message": "בטל את אפשרויות תפריט ההקשר" + }, + "disableContextMenuItemDesc": { + "message": "אפשרויות תפריט ההקשר מספקים גישה מהירה ליצירת סיסמאות חדשות ולפרטי כניסה לאתר עבור הלשונית הנוכחית בדפדפן." + }, + "defaultUriMatchDetection": { + "message": "ברירת מחדל לזיהוי התאמת כתובות", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "בחר את שיטת ברירת המחדל עבור זיהוי התאמת כתובות כשמבצעים פעולות השלמה אוטומטית." + }, + "theme": { + "message": "ערכת נושא" + }, + "themeDesc": { + "message": "שנה את ערכת הצבע של האפליקציה." + }, + "dark": { + "message": "כהה", + "description": "Dark color" + }, + "light": { + "message": "בהיר", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "יצוא כספת" + }, + "fileFormat": { + "message": "פורמט קובץ" + }, + "warning": { + "message": "אזהרה", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "אישור ייצוא כספת" + }, + "exportWarningDesc": { + "message": "הקובץ מכיל את פרטי הכספת שלך בפורמט לא מוצפן. מומלץ להעביר את הקובץ רק בדרכים מוצפנות, ומאוד לא מומלץ לשמור או לשלוח את הקובץ הזה בדרכים לא מוצפנות (כדוגמת סתם אימייל). מחק את הקובץ מיד לאחר שסיימת את השימוש בו." + }, + "encExportKeyWarningDesc": { + "message": "ייצוא זה מצפין את המידע שלך באמצעות שימוש במפתח ההצפנה של חשבונך. אם אי-פעם תבצע החלפה (רוטציה) למפתח ההצפנה של חשבונך, עליך לבצע ייצוא זה שוב אחרת לא תוכל לפענח קובץ ייצוא זה." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "הזן את הסיסמה הראשית שלך עבור יצוא המידע מהכספת." + }, + "shared": { + "message": "משותף" + }, + "learnOrg": { + "message": "מידע על ארגונים" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "שתף" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ הועבר ל- $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "למידע נוסף" + }, + "authenticatorKeyTotp": { + "message": "מפתח אימות (TOTP)" + }, + "verificationCodeTotp": { + "message": "קוד אימות (TOTP)" + }, + "copyVerificationCode": { + "message": "העתק קוד אימות" + }, + "attachments": { + "message": "קבצים מצורפים" + }, + "deleteAttachment": { + "message": "מחק קובץ מצורף" + }, + "deleteAttachmentConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק קובץ מצורף זה?" + }, + "deletedAttachment": { + "message": "קובץ מצורף שנמחק" + }, + "newAttachment": { + "message": "צרף קובץ חדש" + }, + "noAttachments": { + "message": "אין קבצים מצורפים." + }, + "attachmentSaved": { + "message": "הקובץ המצורף נשמר." + }, + "file": { + "message": "קובץ" + }, + "selectFile": { + "message": "בחר קובץ." + }, + "maxFileSize": { + "message": "גודל הקובץ המירבי הוא 500 מגה." + }, + "featureUnavailable": { + "message": "יכולת זו לא זמינה" + }, + "updateKey": { + "message": "לא ניתן להשתמש ביכולת זו עד שתעדכן את מפתח ההצפנה שלך." + }, + "premiumMembership": { + "message": "חשבון פרימיום" + }, + "premiumManage": { + "message": "נהל חשבון" + }, + "premiumManageAlert": { + "message": "באפשרותך לנהל את החשבון שלך דרך הכספת באתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "premiumRefresh": { + "message": "רענן פרטי חשבון" + }, + "premiumNotCurrentMember": { + "message": "חשבונך אינו חשבון פרמיום כרגע." + }, + "premiumSignUpAndGet": { + "message": "צור חשבון פרמיום לשנה, וקבל:" + }, + "ppremiumSignUpStorage": { + "message": "1 ג'יגה של מקום אחסון עבור קבצים מצורפים." + }, + "ppremiumSignUpTwoStep": { + "message": "אפשרויות כניסה דו שלבית מתקדמות כמו YubiKey, FIDO U2F, וגם Duo." + }, + "ppremiumSignUpReports": { + "message": "היגיינת סיסמאות, מצב בריאות החשבון, ודיווחים מעודכנים על פרצות חדשות בכדי לשמור על הכספת שלך בטוחה." + }, + "ppremiumSignUpTotp": { + "message": "מייצר קודי אימות TOTP עבור כניסות דו-שלביות (2FA) בכספת שלך." + }, + "ppremiumSignUpSupport": { + "message": "קדימות בתמיכה הטכנית." + }, + "ppremiumSignUpFuture": { + "message": "כל יכולות הפרימיום העתידיות שנפתח. עוד יכולות מגיעות בקרוב!" + }, + "premiumPurchase": { + "message": "רכוש פרימיום" + }, + "premiumPurchaseAlert": { + "message": "באפשרותך לרכוש מנוי פרימיום בכספת באתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "premiumCurrentMember": { + "message": "אתה מנוי פרימיום!" + }, + "premiumCurrentMemberThanks": { + "message": "תודה על תמיכתך בBitwarden." + }, + "premiumPrice": { + "message": "הכל רק ב$PRICE$ לשנה!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "הרענון הושלם" + }, + "disableAutoTotpCopy": { + "message": "בטל העתקה אוטומטית של קוד TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "אם פרטי הכניסה שלך מקושרים לאפליקציית אימות, קוד האימות TOTP מועתק אוטומטית ללוח שלך ברגע שמתבצעת ההשלמה האוטומטית לטופס הכניסה." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "נדרש חשבון פרימיום" + }, + "premiumRequiredDesc": { + "message": "בכדי להשתמש ביכולת זו יש צורך בחשבון פרימיום." + }, + "enterVerificationCodeApp": { + "message": "הכנס את קוד האימות בן 6 הספרות מאפליקציית האימות שלך." + }, + "enterVerificationCodeEmail": { + "message": "הכנס את קוד האימות בן 6 הספרות שנשלח ל-$EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "מייל אימות נשלח לכתובת $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "זכור אותי" + }, + "sendVerificationCodeEmailAgain": { + "message": "שלח שוב קוד אימות לאימייל" + }, + "useAnotherTwoStepMethod": { + "message": "השתמש בשיטה אחרת עבור כניסה דו שלבית" + }, + "insertYubiKey": { + "message": "הכנס את ה-YubiKey אל כניסת ה-USB במחשבך, ואז גע בכפתור שלו." + }, + "insertU2f": { + "message": "הכנס את מפתח האבטחה שלך אל כניסת ה-USB במחשבך. אם יש לו כפתור, לחץ עליו." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "פתיחת לשונית חדשה" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "פרטי כניסה לא זמינים" + }, + "noTwoStepProviders": { + "message": "כניסה דו-שלבית פעילה בחשבון זה, אך אף אחד מספקי הכניסה הדו-שלבית לא נתמכים בדפדפן זה." + }, + "noTwoStepProviders2": { + "message": "אנא השתמש בדפדפן נתמך (כמו לדוגמא Chrome) ו\\או הוסף ספק כניסה דו-שלבית הנתמך בדפדפן זה (כמו לדוגמא אפליקצית אימות)." + }, + "twoStepOptions": { + "message": "אפשרויות כניסה דו שלבית" + }, + "recoveryCodeDesc": { + "message": "איבדת גישה לכל ספקי האימות הדו-שלבי שלך? השתמש בקוד השחזור בכדי לבטל את כל ספקי האימות הדו-שלבי דרך החשבון שלך." + }, + "recoveryCodeTitle": { + "message": "קוד שחזור" + }, + "authenticatorAppTitle": { + "message": "אפליקציית אימות" + }, + "authenticatorAppDesc": { + "message": "השתמש באפליקצית אימות (כמו לדוגמא Authy או Google Authenticator) לייצור סיסמאות אימות מבוססות זמן.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "מפתח אבטחה OTP של YubiKey" + }, + "yubiKeyDesc": { + "message": "השתמש בYubiKey עבור גישה לחשבון שלך. עובד עם YubiKey בגירסאות 4, 4C, 4Nano, ומכשירי NEO." + }, + "duoDesc": { + "message": "בצע אימות מול Duo Security באמצעות אפליקצית Duo לפלאפון, SMS, שיחת טלפון, או מפתח אבטחה U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "בצע אימות מול Duo Security עבור הארגון שלך באמצעות אפליקצית Duo לפלאפון, SMS, שיחת טלפון, או מפתח אבטחה U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "אימייל" + }, + "emailDesc": { + "message": "קודי אימות ישלחו לאימייל שלך." + }, + "selfHostedEnvironment": { + "message": "סביבה על שרתים מקומיים" + }, + "selfHostedEnvironmentFooter": { + "message": "הזן את כתובת השרת המקומי של Bitwarden." + }, + "customEnvironment": { + "message": "סביבה מותאמת אישית" + }, + "customEnvironmentFooter": { + "message": "למשתמשים מתקדמים. באפשרותך לציין את כתובת השרת עבור כל שירות בנפרד." + }, + "baseUrl": { + "message": "כתובת שרת" + }, + "apiUrl": { + "message": "כתובת שרת הAPI" + }, + "webVaultUrl": { + "message": "כתובת שרת הכספת" + }, + "identityUrl": { + "message": "כתובת שרת הזהות" + }, + "notificationsUrl": { + "message": "כתובת שרת הודעות" + }, + "iconsUrl": { + "message": "כתובת שרת אייקונים" + }, + "environmentSaved": { + "message": "כתובות הסביבה נשמרו." + }, + "enableAutoFillOnPageLoad": { + "message": "הפעל השלמה אוטומטית בזמן טעינת העמוד" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "אם זוהה טופס כניסה, בצע אוטומטית מילוי-אוטומטי כשהעמוד נטען." + }, + "experimentalFeature": { + "message": "זוהי אופציה נסיונית. השימוש באופציה זו על אחריותך." + }, + "defaultAutoFillOnPageLoad": { + "message": "הגדרת ברירת מחדל למילוי אוטומטי של פרטי התחברות" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "לאחר הפעלת מילוי אוטומטי של פרטים בעת טעינת דפים, אפשר להפעיל או לכבות את האפשרות לפרטי התחברות ספציפיים. זו הגדרת ברירת המחדל לפרטי התחברות שלא הוגדרו בנפרד." + }, + "itemAutoFillOnPageLoad": { + "message": "מילוי אוטומטי בעת טעינת דפים (אם מופעל בהגדרות)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "שימוש בהגדרות ברירת המחדל" + }, + "autoFillOnPageLoadYes": { + "message": "מילוי אוטומטי אחרי טעינת דפים" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "פתיחת כספת בחלונית צפה" + }, + "commandOpenSidebar": { + "message": "פתיחת כספת בסרגל צד" + }, + "commandAutofillDesc": { + "message": "השתמש בהשלמה-האוטומטית האחרונה שבוצעה באתר זה." + }, + "commandGeneratePasswordDesc": { + "message": "צור והעתק סיסמה רנדומלית חדשה." + }, + "commandLockVaultDesc": { + "message": "נעל את הכספת" + }, + "privateModeWarning": { + "message": "המצב הפרטי הוא במסגרת ניסוי וחלק מהיכולות מוגבלות." + }, + "customFields": { + "message": "שדות מותאמים אישית" + }, + "copyValue": { + "message": "העתק ערך" + }, + "value": { + "message": "ערך" + }, + "newCustomField": { + "message": "שדה מותאם אישית חדש" + }, + "dragToSort": { + "message": "גרור כדי למיין" + }, + "cfTypeText": { + "message": "טקסט" + }, + "cfTypeHidden": { + "message": "מוסתר" + }, + "cfTypeBoolean": { + "message": "אמת או שקר" + }, + "cfTypeLinked": { + "message": "מקושר", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "ערך מקושר", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "לחיצה מחוץ לחלונית הצפה שנפתחה בכדי לבדוק את פרטי האימות תגרום לחלונית שנפתחה, להסגר. האם ברצונך להציג את המידע בחלון שאינו נסגר?" + }, + "popupU2fCloseMessage": { + "message": "דפדפן זה לא יכול לעבד בקשות U2F בחלון צף זה. האם ברצונך לפתוח את החלון הצף כחלון חדש רגיל כדי שתוכל להכנס באמצעות U2F?" + }, + "disableFavicon": { + "message": "בטל אייקונים של האתר" + }, + "disableFaviconDesc": { + "message": "יכולת הצג אייקונים-של-האתר מאפשרת הצגה של תמונה או אייקון מוכר ליד פרטי הכניסה שבכספת שלך." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "שם בעל הכרטיס" + }, + "number": { + "message": "מספר" + }, + "brand": { + "message": "מותג" + }, + "expirationMonth": { + "message": "תוקף אשראי - חודש" + }, + "expirationYear": { + "message": "תוקף אשראי - שנה" + }, + "expiration": { + "message": "תוקף" + }, + "january": { + "message": "ינואר" + }, + "february": { + "message": "פברואר" + }, + "march": { + "message": "מרץ" + }, + "april": { + "message": "אפריל" + }, + "may": { + "message": "מאי" + }, + "june": { + "message": "יוני" + }, + "july": { + "message": "יולי" + }, + "august": { + "message": "אוגוסט" + }, + "september": { + "message": "ספטמבר" + }, + "october": { + "message": "אוקטובר" + }, + "november": { + "message": "נובמבר" + }, + "december": { + "message": "דצמבר" + }, + "securityCode": { + "message": "קוד אבטחה" + }, + "ex": { + "message": "לדוגמא" + }, + "title": { + "message": "תואר" + }, + "mr": { + "message": "מר" + }, + "mrs": { + "message": "גברת" + }, + "ms": { + "message": "העלמה" + }, + "dr": { + "message": "דוקטור" + }, + "firstName": { + "message": "שם פרטי" + }, + "middleName": { + "message": "שם אמצעי" + }, + "lastName": { + "message": "שם משפחה" + }, + "fullName": { + "message": "שם מלא" + }, + "identityName": { + "message": "שם זהות" + }, + "company": { + "message": "חברה" + }, + "ssn": { + "message": "מספר ביטוח לאומי" + }, + "passportNumber": { + "message": "מספר דרכון" + }, + "licenseNumber": { + "message": "מספר רשיון" + }, + "email": { + "message": "אימייל" + }, + "phone": { + "message": "טלפון" + }, + "address": { + "message": "כתובת" + }, + "address1": { + "message": "כתובת 1" + }, + "address2": { + "message": "כתובת 2" + }, + "address3": { + "message": "כתובת 3" + }, + "cityTown": { + "message": "עיר \\ יישוב" + }, + "stateProvince": { + "message": "מדינה \\ מחוז" + }, + "zipPostalCode": { + "message": "מיקוד" + }, + "country": { + "message": "מדינה" + }, + "type": { + "message": "סוג" + }, + "typeLogin": { + "message": "פרטי התחברות" + }, + "typeLogins": { + "message": "פרטי התחברות" + }, + "typeSecureNote": { + "message": "פתק מאובטח" + }, + "typeCard": { + "message": "כרטיס" + }, + "typeIdentity": { + "message": "זהות" + }, + "passwordHistory": { + "message": "היסטוריית סיסמאות" + }, + "back": { + "message": "הקודם" + }, + "collections": { + "message": "אוספים" + }, + "favorites": { + "message": "מועדפים" + }, + "popOutNewWindow": { + "message": "פתח כחלון חדש" + }, + "refresh": { + "message": "רענן" + }, + "cards": { + "message": "כרטיסים" + }, + "identities": { + "message": "זהויות" + }, + "logins": { + "message": "פרטי התחברות" + }, + "secureNotes": { + "message": "פתקים מאובטחים" + }, + "clear": { + "message": "נקה", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "בדוק אם הסיסמה נחשפה." + }, + "passwordExposed": { + "message": "סיסמה זו נחשפה $VALUE$ פעמים בפירצות אבטחה. עליך להחליף אותה.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "סיסמה זו לא נמצאה בפירצות אבטחה ידועות. ניתן להמשיך להשתמש בה בבטחה." + }, + "baseDomain": { + "message": "שם בסיס הדומיין", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "שם תחום", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "שרת", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "מדויק" + }, + "startsWith": { + "message": "מתחיל עם" + }, + "regEx": { + "message": "ביטוי רגולרי", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "זיהוי התאמה", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "ברירת מחדל לזיהוי התאמות", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "הצגה\\הסתרה של אפשרויות" + }, + "toggleCurrentUris": { + "message": "שנה מצב הצגת כתובות URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "כתובת מלאה נוכחית", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "ארגון", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "סוגים" + }, + "allItems": { + "message": "כל הפריטים" + }, + "noPasswordsInList": { + "message": "אין סיסמאות להצגה ברשימה." + }, + "remove": { + "message": "הסר" + }, + "default": { + "message": "ברירת מחדל" + }, + "dateUpdated": { + "message": "עודכן", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "הסיסמה עודכנה", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "האם אתה בטוח שברצונך להשתמש באפשרות \"אף פעם לא\"? במצב זה הסיסמה לכספת שלך תשמר על המכשיר שלך. אם תשתמש באפשרות זו עליך לעשות הכל כדי לוודא כי המכשיר מאובטח כראוי." + }, + "noOrganizationsList": { + "message": "אינך משויך לארגון. ניתן לשתף באופן מאובטח פריטים רק עם משתמשים אחרים בתוך ארגון." + }, + "noCollectionsInList": { + "message": "אין אוספים להצגה ברשימה." + }, + "ownership": { + "message": "בעלות" + }, + "whoOwnsThisItem": { + "message": "מי הבעלים של פריט הזה?" + }, + "strong": { + "message": "חזקה", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "טובה", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "חלשה", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "סיסמה ראשית חלשה" + }, + "weakMasterPasswordDesc": { + "message": "הסיסמה הראשית שבחרת חלשה מאוד. עליך לבחור סיסמה חזקה יותר (או להשתמש במשפט במקום מילה אחת) בכדי לאבטח את החשבון שלך. האם אתה בטוח שברצונך להשתמש בסיסמה ראשית זו?" + }, + "pin": { + "message": "קוד PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "בטל נעילה עם קוד PIN" + }, + "setYourPinCode": { + "message": "קבע קוד PIN לביטול נעילת Bitwarden. הגדרות הPIN יאופסו אם תבצע יציאה מהתוכנה." + }, + "pinRequired": { + "message": "נדרש קוד PIN." + }, + "invalidPin": { + "message": "קוד PIN לא תקין." + }, + "unlockWithBiometrics": { + "message": "פתח נעילה עם זיהוי ביומטרי" + }, + "awaitDesktop": { + "message": "ממתין לאישור משולחן העבודה" + }, + "awaitDesktopDesc": { + "message": "אנא אשר בעזרת אמצעים ביומטרים באפליקציית Bitwarden של שולחן העבודה בכדי לאפשר אמצעים ביומטריים בדפדפן." + }, + "lockWithMasterPassOnRestart": { + "message": "נעל בעזרת הסיסמה הראשית בהפעלת הדפדפן מחדש" + }, + "selectOneCollection": { + "message": "עליך לבחור לפחות אוסף אחד." + }, + "cloneItem": { + "message": "שכפול פריט" + }, + "clone": { + "message": "שכפול" + }, + "passwordGeneratorPolicyInEffect": { + "message": "מדיניות ארגונית אחת או יותר משפיעה על הגדרות המחולל שלך." + }, + "vaultTimeoutAction": { + "message": "פעולה לביצוע בכספת בתום זמן החיבור" + }, + "lock": { + "message": "נעילה", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "סל המחזור", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "חפש בסל המחזור" + }, + "permanentlyDeleteItem": { + "message": "מחק לצמיתות פריט שנבחר" + }, + "permanentlyDeleteItemConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק את הפריט הזה?" + }, + "permanentlyDeletedItem": { + "message": "פריט שנמחק לצמיתות" + }, + "restoreItem": { + "message": "שחזר פריט" + }, + "restoreItemConfirmation": { + "message": "האם אתה בטוח שברצונך לשחזר פריט זה?" + }, + "restoredItem": { + "message": "פריט ששוחזר" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "יציאה מהחשבון תסיר את כל הגישה לכספת ויידרש אימות מקוון לאחר משך הזמן שהוקצב. האם אתה בטוח שברצונך להשתמש בהגדרה זו?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "אישור פעולת אימות לאחר חוסר פעילות" + }, + "autoFillAndSave": { + "message": "בצע השלמה אוטומטית ושמור" + }, + "autoFillSuccessAndSavedUri": { + "message": "בוצעה השלמה אוטומטית והכתובת נשמרה" + }, + "autoFillSuccess": { + "message": "בוצעה השלמה אוטומטית" + }, + "setMasterPassword": { + "message": "הגדר סיסמה ראשית" + }, + "masterPasswordPolicyInEffect": { + "message": "אחד או יותר מאילוצי המדיניות של הארגון דורשים שהסיסמה הראשית שלך תעמוד בדרישות הבאות:" + }, + "policyInEffectMinComplexity": { + "message": "ניקוד מורכבות הסיסמה צריך להיות לפחות {0}", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "אורך מינימלי של $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "מכילה אות גדולה אחת או יותר" + }, + "policyInEffectLowercase": { + "message": "מכילה אות קטנה אחת או יותר" + }, + "policyInEffectNumbers": { + "message": "מכילה ספרה אחת או יותר" + }, + "policyInEffectSpecial": { + "message": "מכילה תו אחד או יותר מהתווים הבאים: {0}", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "הסיסמה הראשית החדשה השלך לא עומדת בדרישות המדיניות." + }, + "acceptPolicies": { + "message": "סימון תיבה זו מהווה את הסכמתך לתנאים הבאים:" + }, + "acceptPoliciesError": { + "message": "תנאי השירות ומדיניות הפרטיות לא אושרו." + }, + "termsOfService": { + "message": "תנאי השירות" + }, + "privacyPolicy": { + "message": "מדיניות הפרטיות" + }, + "hintEqualsPassword": { + "message": "רמז הסיסמה שלך לא יכול להיות זהה לסיסמה שלך." + }, + "ok": { + "message": "אישור" + }, + "desktopSyncVerificationTitle": { + "message": "אימות סנכרון מול שולחן העבודה" + }, + "desktopIntegrationVerificationText": { + "message": "אנא ודא כי אפליקציית שולחן העבודה שלך מציגה את טביעת האצבע הזו: " + }, + "desktopIntegrationDisabledTitle": { + "message": "אינטגרציית הדפדפן לא מופעלת" + }, + "desktopIntegrationDisabledDesc": { + "message": "אינטגרציית הדפדפן לא מופעלת באפליקציית Bitwarden בשולחן העבודה. אנא אפשר זאת בהגדרות האפליקציה." + }, + "startDesktopTitle": { + "message": "הפעל את אפליקציית Bitwarden בשולחן העבודה" + }, + "startDesktopDesc": { + "message": "יש להפעיל את אפליקציית Bitwarden בשולחן העבודה בכדי להשתמש בפונקציה זו." + }, + "errorEnableBiometricTitle": { + "message": "לא ניתן להפעיל זיהוי ביומטרי" + }, + "errorEnableBiometricDesc": { + "message": "הפעולה בוטלה על ידי אפליקציית שולחן העבודה" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "אפליקציית שולחן העבודה דחתה את ערוץ התקשורת המאובטח. אנא נסה שנית." + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "התקשורת מול אפליקציית שולחן העבודה נקטעה" + }, + "nativeMessagingWrongUserDesc": { + "message": "המשתמש המחובר לאפליקציית שולחן העבודה שונה מהמשתמש המחובר לאפליקציה בדפדפן. אנא ודא כי אותו משתמש מחובר לשתי האפליקציות." + }, + "nativeMessagingWrongUserTitle": { + "message": "חוסר התאמה בין חשבונות" + }, + "biometricsNotEnabledTitle": { + "message": "אמצעי זיהוי ביומטרים לא מאופשרים" + }, + "biometricsNotEnabledDesc": { + "message": "בכדי להשתמש באמצעים ביומטרים בדפדפן יש לאפשר תכונה זו באפליקציה בשולחן העבודה." + }, + "biometricsNotSupportedTitle": { + "message": "אמצעי זיהוי ביומטרים לא נתמכים" + }, + "biometricsNotSupportedDesc": { + "message": "מכשיר זה לא תומך בזיהוי ביומטרי בדפדפן." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "הרשאה לא סופקה" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "ללא הרשאות לתקשר עם אפליקציית שולחן העבודה אין באפשרותנו לספק תמיכה באמצעים ביומטריים בדפדפן. אנא נסה שוב." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "מדיניות הארגון מונעת ממך לשמור פריטים בכספת האישית. שנה את אפשרות הבעלות לארגוניות ובחר מתוך האוספים הזמינים." + }, + "personalOwnershipPolicyInEffect": { + "message": "מדיניות ארגונית משפיעה על אפשרויות הבעלות שלך." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "הקובץ שברצונך לשלוח." + }, + "deletionDate": { + "message": "תאריך מחיקה" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "תאריך תפוגה" + }, + "expirationDateDesc": { + "message": "במידה ויוגדר, הגישה ל Send זה תושבת בתאריך ובשעה שהוגדרו.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "יום אחד" + }, + "days": { + "message": "$DAYS$ ימים", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "מותאם אישית" + }, + "maximumAccessCount": { + "message": "כמות גישות מרבית" + }, + "maximumAccessCountDesc": { + "message": "במידה ויוגדר, משתמשים לא יוכלו יותר לגשת ל Send זה לאחר שמספר הגישות המרבי יושג.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ משתמשים ב־SSO עם שרת מפתחות באירוח עצמי. סיסמה ראשית לא נחוצה יותר לטובת כניסה לחברי הארגון.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "לעזוב את הארגון" + }, + "removeMasterPassword": { + "message": "הסרת סיסמה ראשית" + }, + "removedMasterPassword": { + "message": "הסיסמה הראשית הוסרה." + }, + "leaveOrganizationConfirmation": { + "message": "לעזוב את הארגון?" + }, + "leftOrganization": { + "message": "עזבת את הארגון." + }, + "toggleCharacterCount": { + "message": "החלפת מצב ספירת תווים" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "הכספת האישית מיוצאת" + }, + "exportingPersonalVaultDescription": { + "message": "רק פריטי הכספת האישית שמשויכת אל $EMAIL$ ייוצאו. פריטי הכספת הארגוניים לא יהיו חלק מהייצוא.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "שגיאה" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "סוג שם משתמש" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/hi/messages.json b/apps/browser/src/_locales/hi/messages.json new file mode 100644 index 0000000000..8e199cd48d --- /dev/null +++ b/apps/browser/src/_locales/hi/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "bitwarden is a secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "अपनी सुरक्षित तिजोरी में प्रवेश करने के लिए नया खाता बनाएं या लॉग इन करें।" + }, + "createAccount": { + "message": "Create Account" + }, + "login": { + "message": "Log In" + }, + "enterpriseSingleSignOn": { + "message": "उद्यम एकल साइन-ऑन" + }, + "cancel": { + "message": "रद्द करें" + }, + "close": { + "message": "बंद करें" + }, + "submit": { + "message": "जमा करें" + }, + "emailAddress": { + "message": "Email Address" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "मास्टर पासवर्ड वह पासवर्ड है जो तिजोरी में प्रवेश के लिए प्रयोग होता है। आप मास्टर पासवर्ड ना भूले, यह अतिआवश्यक है। भूलने की अवस्था में पासवर्ड को दोबारा पाना संभव नहीं होगा।" + }, + "masterPassHintDesc": { + "message": "मास्टर पासवर्ड संकेत आपको भूल जाने की अवस्था में पासवर्ड को याद करने में सहायता करता है।" + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "टैब" + }, + "myVault": { + "message": "My Vault" + }, + "tools": { + "message": "उपकरण" + }, + "settings": { + "message": "सेटिंग्स" + }, + "currentTab": { + "message": "Current Tab" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "URI को कॉपी करें" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number" + }, + "copySecurityCode": { + "message": "Copy Security Code" + }, + "autoFill": { + "message": "स्वत:भरण" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "कोई मेल-मिला लॉगिन नहीं |" + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "इस ब्राउज़र टैब के लिए स्वत: भरण लॉगिन उपलब्ध नहीं है।" + }, + "addLogin": { + "message": "Add a Login" + }, + "addItem": { + "message": "Add Item" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "अपने मास्टर पासवर्ड संकेत प्राप्त करने के लिए अपने खाते का ईमेल पता दर्ज करें।" + }, + "getMasterPasswordHint": { + "message": "मास्टर पासवर्ड संकेत प्राप्त करें" + }, + "continue": { + "message": "जारी रखें" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "खाता" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "आपके खाते का फिंगरप्रिंट वाक्यांश", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "logOut": { + "message": "Log Out" + }, + "about": { + "message": "जानकारी" + }, + "version": { + "message": "संस्करण" + }, + "save": { + "message": "सेव करें" + }, + "move": { + "message": "ले जाएं" + }, + "addFolder": { + "message": "Add Folder" + }, + "name": { + "message": "नाम" + }, + "editFolder": { + "message": "Edit Folder" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "folders": { + "message": "फ़ोल्डर्स" + }, + "noFolders": { + "message": "सूचीबद्ध करने के लिए कोई फ़ोल्डर नहीं हैं।" + }, + "helpFeedback": { + "message": "Help & Feedback" + }, + "sync": { + "message": "सिंक" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "उत्पन्न करें!", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "स्वचालित रूप से अपने लॉगिन के लिए मजबूत, अद्वितीय पासवर्ड उत्पन्न करते हैं।" + }, + "bitWebVault": { + "message": "bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "चयन करें" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "विकल्प" + }, + "length": { + "message": "लंबाई" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "कैपिटलाइज़ करें", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "नंबर शामिल करें" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "वॉल्ट खोजे" + }, + "edit": { + "message": "संपादन करें" + }, + "view": { + "message": "देखें" + }, + "noItemsInList": { + "message": "सूचीबद्ध करने के लिए कोई आइटम नहीं हैं।" + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "उपयोगकर्ता नाम" + }, + "password": { + "message": "पासवर्ड" + }, + "passphrase": { + "message": "पासफ़्रेज़" + }, + "favorite": { + "message": "Favorite" + }, + "notes": { + "message": "नोट्स" + }, + "note": { + "message": "नोट:" + }, + "editItem": { + "message": "Edit Item" + }, + "folder": { + "message": "फ़ोल्डर" + }, + "deleteItem": { + "message": "Delete Item" + }, + "viewItem": { + "message": "View Item" + }, + "launch": { + "message": "खोलें" + }, + "website": { + "message": "वेबसाइट" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "प्रबंधित करना" + }, + "other": { + "message": "अन्य" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "कृपया एक अच्छी समीक्षा के साथ हमारी मदत करने पर विचार करें!" + }, + "browserNotSupportClipboard": { + "message": "आपका वेब ब्राउज़र आसान क्लिपबोर्ड कॉपीिंग का समर्थन नहीं करता है। इसके बजाय इसे मैन्युअल रूप से कॉपी करें।" + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "आपकी वॉल्ट लॉक हो गई है। जारी रखने के लिए अपने मास्टर पासवर्ड को सत्यापित करें।" + }, + "unlock": { + "message": "ताला खोलें" + }, + "loggedInAsOn": { + "message": "पर के रूप में लॉग इन किया ।", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "अमान्य मास्टर पासवर्ड" + }, + "vaultTimeout": { + "message": "वॉल्ट मध्यांतर" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "तत्‍काल" + }, + "tenSeconds": { + "message": "10 सेकंड" + }, + "twentySeconds": { + "message": "20 सेकंड" + }, + "thirtySeconds": { + "message": "30 सेकंड" + }, + "oneMinute": { + "message": "1 मिनट" + }, + "twoMinutes": { + "message": "2 मिनट" + }, + "fiveMinutes": { + "message": "5 मिनट" + }, + "fifteenMinutes": { + "message": "15 मिनट" + }, + "thirtyMinutes": { + "message": "30 मिनट" + }, + "oneHour": { + "message": "1 घंटा" + }, + "fourHours": { + "message": "4 घंटे" + }, + "onLocked": { + "message": "On Locked" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "कभी नहीं" + }, + "security": { + "message": "सुरक्षा" + }, + "errorOccurred": { + "message": "कोई ग़लती हुई।" + }, + "emailRequired": { + "message": "ई-मेल पते की आवश्यकता है।" + }, + "invalidEmail": { + "message": "अमान्य ई-मेल |" + }, + "masterPassRequired": { + "message": "मास्टर पासवर्ड की आवश्यकता है।" + }, + "masterPassLength": { + "message": "मास्टर पासवर्ड कम से कम 8 अक्षर लंबे होने चाहिए।" + }, + "masterPassDoesntMatch": { + "message": "मास्टर पासवर्ड पुष्टि मेल नहीं खाती है।" + }, + "newAccountCreated": { + "message": "आपका नया खाता बनाया गया है! अब आप लॉग इन कर सकते हैं।" + }, + "masterPassSent": { + "message": "हमने आपको अपने मास्टर पासवर्ड संकेत के साथ एक ईमेल भेजा है।" + }, + "verificationCodeRequired": { + "message": "सत्यापन टोकन आवश्यक है" + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": " copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected login on this page. Copy/paste your username and/or password instead." + }, + "loggedOut": { + "message": "लॉग आउट" + }, + "loginExpired": { + "message": "अपने लॉगिन सत्र समाप्त हो गया है।" + }, + "logOutConfirmation": { + "message": "क्या आप वाकई लॉग आउट करना चाहते हैं?" + }, + "yes": { + "message": "हाँ" + }, + "no": { + "message": "नहीं" + }, + "unexpectedError": { + "message": "An unexpected error has occured." + }, + "nameRequired": { + "message": "नाम आवश्यक है" + }, + "addedFolder": { + "message": "जोड़ा गया फ़ोल्डर" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "आप वेब वॉल्ट bitwarden.com पर अपना मास्टर पासवर्ड बदल सकते हैं।क्या आप अब वेबसाइट पर जाना चाहते हैं?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to enter a security code from an authenticator app whenever you log in. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited Folder" + }, + "deleteFolderConfirmation": { + "message": "क्या आप वाकई इस फ़ोल्डर को हटाना चाहते हैं?" + }, + "deletedFolder": { + "message": "हटाए गए फ़ोल्डर" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "ब्राउज़र एक्सटेंशन का सबसे अधिक जानने के लिए हमारे शुरू ट्यूटोरियल देखें।" + }, + "syncingComplete": { + "message": "सिंकिंग पूर्ण" + }, + "syncingFailed": { + "message": "सिंकिंग असफल।" + }, + "passwordCopied": { + "message": "कूटशब्द की नकल हुइ" + }, + "uri": { + "message": "यूआरआइ" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "नया URI" + }, + "addedItem": { + "message": "जोड़ा गया आइटम" + }, + "editedItem": { + "message": "संपादित आइटम " + }, + "deleteItemConfirmation": { + "message": "क्या आप वास्तव में थ्रैश में भेजना चाहते हैं?" + }, + "deletedItem": { + "message": "थ्रैश में भेजे" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "क्या आप सुनिश्चित हैं कि आप वर्तमान पासवर्ड को ओवरराइट करना चाहते हैं?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "फोल्डर में खोजें" + }, + "searchCollection": { + "message": "श्रेणी खोजें" + }, + "searchType": { + "message": "तलाश की विधि" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "क्लिपबोर्ड खाली करें", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "स्वचालित रूप से अपने क्लिपबोर्ड से कॉपी की गई मानों को साफ़ करें।", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Yes, Save Now" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "क्या आप बिटवर्डन में इस पासवर्ड को अपडेट करना चाहते हैं?" + }, + "notificationChangeSave": { + "message": "Yes, Update Now" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "संदर्भ मेनू विकल्प आपके वर्तमान टैब में वेबसाइट के लिए पासवर्ड जनरेशन और लॉगिन तक त्वरित पहुंच प्रदान करते हैं।" + }, + "defaultUriMatchDetection": { + "message": "डिफॉल्ट URI मैच डिटेक्शन", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "ऑटो-फिल जैसे कार्यों को करते समय लॉगिन के लिए URI मैच डिटेक्शन को संभाले जाने का डिफ़ॉल्ट तरीका चुनें। " + }, + "theme": { + "message": "थीम" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "अंधेरा", + "description": "Dark color" + }, + "light": { + "message": "प्रकाश", + "description": "Light color" + }, + "solarizedDark": { + "message": "सौरीकृत अंधेरा", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "चेतावनी", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "वॉल्ट निर्यात की पुष्टि करें" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "यह आपके खाते की एन्क्रिप्शन कुंजी का उपयोग करके आपके डेटा को एन्क्रिप्ट करता है।यदि आप कभी भी अपने खाते की एन्क्रिप्शन कुंजी को खोते हैं तो आपको फिर से निर्यात करना चाहिए क्योंकि आप इस निर्यात फ़ाइल को डिक्रिप्ट करने में सक्षम नहीं होंगे।" + }, + "encExportAccountWarningDesc": { + "message": "खाता एन्क्रिप्शन कुंजी प्रत्येक बिटवर्डन उपयोगकर्ता खाते के लिए अद्वितीय हैं, इसलिए आप एन्क्रिप्टेड निर्यात को किसी अन्य खाते में आयात नहीं कर सकते हैं।" + }, + "exportMasterPassword": { + "message": "अपने वॉल्ट डेटा को निर्यात करने के लिए अपना मास्टर पासवर्ड दर्ज करें।" + }, + "shared": { + "message": "साझा किया गया" + }, + "learnOrg": { + "message": "संगठनों के बारे में जानें" + }, + "learnOrgConfirmation": { + "message": "बिटवर्डन आपको एक संगठन का उपयोग करके अपनी तिजोरी वस्तुओं को दूसरों के साथ साझा करने की अनुमति देता है।क्या आप अधिक जानने के लिए bitwarden.com वेबसाइट पर जाना चाहेंगे?" + }, + "moveToOrganization": { + "message": "संगठन में ले जाएँ" + }, + "share": { + "message": "शेयर करें" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ $ORGNAME$ गया ", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "एक संगठन चुनें जिसे आप इस आइटम को स्थानांतरित करना चाहते हैं।किसी संगठन में जाने से उस संगठन को आइटम का स्वामित्व हस्तांतरित होता है।एक बार इसे स्थानांतरित करने के बाद आप अब इस आइटम के प्रत्यक्ष स्वामी नहीं होंगे।" + }, + "learnMore": { + "message": "अधिक जानें" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "अटॅचमेंट्स" + }, + "deleteAttachment": { + "message": "अटैचमेंट हटाएं" + }, + "deleteAttachmentConfirmation": { + "message": "क्या आप वाकई इस अटैचमेंट को हटाना चाहते हैं?" + }, + "deletedAttachment": { + "message": "हटाए गए अटैचमेंट" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "कोई अटैचमेंट नहीं।" + }, + "attachmentSaved": { + "message": "अटैचमेंट बच गया है।" + }, + "file": { + "message": "फ़ाइल" + }, + "selectFile": { + "message": "फ़ाइल का चयन करें।" + }, + "maxFileSize": { + "message": "अधिकतम फाइल आकार 500 MB है।" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "जब तक आप अपनी एन्क्रिप्शन कुंजी को अपडेट नहीं करते, तब तक आप इस सुविधा का उपयोग नहीं कर सकते हैं।" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "आप वेब वॉल्ट bitwarden.com पर अपनी सदस्यता का प्रबंधन कर सकते हैं।क्या आप अब वेबसाइट पर जाना चाहते हैं?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "आप वर्तमान में प्रीमियम सदस्य नहीं हैं।" + }, + "premiumSignUpAndGet": { + "message": "प्रीमियम सदस्यता के लिए साइन अप करें और प्राप्त करें:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB of encrypted file storage." + }, + "ppremiumSignUpTwoStep": { + "message": "अतिरिक्त दो-चरण लॉगिन विकल्प जैसे YubiKey, FIDO U2F, और डुओ।" + }, + "ppremiumSignUpReports": { + "message": "अपनी वॉल्ट को सुरक्षित रखने के लिए पासवर्ड स्वच्छता, खाता स्वास्थ्य और डेटा उल्लंघन रिपोर्ट।" + }, + "ppremiumSignUpTotp": { + "message": "अपनी तिजोरी में लॉगिन के लिए TOTP सत्यापन कोड (2FA) जनरेटर।" + }, + "ppremiumSignUpSupport": { + "message": "प्राथमिकता ग्राहक सहायता" + }, + "ppremiumSignUpFuture": { + "message": "भविष्य के सभी प्रीमियम फीचर्स। और जल्द ही आ रहा है!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "आप bitwarden.com वेब वॉल्ट पर प्रीमियम सदस्यता खरीद सकते हैं।क्या आप अब वेबसाइट पर जाना चाहते हैं?" + }, + "premiumCurrentMember": { + "message": "आप एक प्रीमियम सदस्य हैं!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting bitwarden." + }, + "premiumPrice": { + "message": "All for just %price% /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "ताज़ा पूरा" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "यदि आपके लॉगिन में एक प्रमाणक कुंजी जुड़ी हुई है, तो जब भी आप लॉगिन को ऑटो-फिल करते हैं तो TOTP सत्यापन कोड स्वचालित रूप से आपके क्लिपबोर्ड पर कॉपी किया जाता है।" + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "इस सुविधा का उपयोग करने के लिए प्रीमियम सदस्यता की आवश्यकता होती है।" + }, + "enterVerificationCodeApp": { + "message": "अपने ऑथेंटिकेटर ऐप से 6 डिजिट वेरिफिकेशन कोड डालें।" + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "ईमेल $EMAIL$ को भेजा गया।", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "मुझे याद रखें" + }, + "sendVerificationCodeEmailAgain": { + "message": "फिर से सत्यापन कोड ईमेल भेजें" + }, + "useAnotherTwoStepMethod": { + "message": "एक और दो-चरण लॉगिन विधि का उपयोग करें" + }, + "insertYubiKey": { + "message": "अपने कंप्यूटर के यूएसबी पोर्ट में अपने YubiKey डालें, फिर इसके बटन को स्पर्श करें।" + }, + "insertU2f": { + "message": "अपने कंप्यूटर के यूएसबी पोर्ट में अपनी सुरक्षा कुंजी डालें। अगर इसमें कोई बटन है तो उसे टच करें।\n" + }, + "webAuthnNewTab": { + "message": "वेबऑथन 2FA सत्यापन शुरू करने के लिए। एक नया टैब खोलने के लिए नीचे दिए गए बटन पर क्लिक करें और नए टैब में दिए गए निर्देशों का पालन करें।" + }, + "webAuthnNewTabOpen": { + "message": "नया टैब खोलें" + }, + "webAuthnAuthenticate": { + "message": "वेबऑथन प्रमाणित करें" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "कृपया एक समर्थित वेब ब्राउज़र (जैसे क्रोम) और/या अतिरिक्त प्रदाताओं का उपयोग करें जो वेब ब्राउज़र (जैसे एक प्रमाणक ऐप) में बेहतर समर्थित हैं।" + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "अपने दो कारक प्रदाताओं के सभी के लिए उपयोग खो दिया है? अपने खाते से सभी दो-कारक प्रदाताओं को अक्षम करने के लिए अपने रिकवरी कोड का उपयोग करें।" + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "समय-आधारित सत्यापन कोड उत्पन्न करने के लिए एक प्रमाणक ऐप (जैसे Authy या Google Authenticator) का उपयोग करें।", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "अपने खाते तक पहुंचने के लिए YubiKey का उपयोग करें। YubiKey 4, 4 नैनो, 4C, और NEO उपकरणों के साथ काम करता है।" + }, + "duoDesc": { + "message": "डुओ मोबाइल ऐप, एसएमएस, फोन कॉल या U2F सुरक्षा कुंजी का उपयोग करके डुओ सिक्योरिटी के साथ सत्यापित करें।", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 वेबऑथन" + }, + "webAuthnDesc": { + "message": "अपने खाते तक पहुंचने के लिए किसी भी WebAuthn सक्षम सुरक्षा कुंजी का उपयोग करें।" + }, + "emailTitle": { + "message": "ईमेल" + }, + "emailDesc": { + "message": "सत्यापन कोड आपको ईमेल किए जाएंगे।" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "उन्नत उपयोगकर्ताओं के लिए। आप स्वतंत्र रूप से प्रत्येक सेवा का आधार URL निर्दिष्ट कर सकते हैं।" + }, + "baseUrl": { + "message": "सर्वर URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "पर्यावरण URL को बचाया गया है।" + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill On Page Load." + }, + "enableAutoFillOnPageLoadDesc": { + "message": "यदि लॉगिन फॉर्म का पता चलता है, तो वेब पेज लोड होने पर स्वचालित रूप से ऑटो-फिल करें।" + }, + "experimentalFeature": { + "message": "यह वर्तमान में एक प्रयोगात्मक विशेषता है। अपने जोखिम पर उपयोग करें।" + }, + "defaultAutoFillOnPageLoad": { + "message": "लॉगिन आइटम के लिए डिफ़ॉल्ट ऑटोफिल सेटिंग" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "पेज लोड पर ऑटो-फिल को सक्षम करने के बाद, आप व्यक्तिगत लॉगिन आइटम के लिए सुविधा को सक्षम या अक्षम कर सकते हैं।यह लॉगिन आइटम के लिए डिफ़ॉल्ट सेटिंग है जो अलग से कॉन्फ़िगर नहीं हैं।" + }, + "itemAutoFillOnPageLoad": { + "message": "पेज लोड पर ऑटो-भरें (यदि विकल्पों में सक्षम हैं)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "डिफ़ॉल्ट सेटिंग का उपयोग करें" + }, + "autoFillOnPageLoadYes": { + "message": "पेज लोड पर ऑटो भरें" + }, + "autoFillOnPageLoadNo": { + "message": "पेज लोड पर ऑटो-फिल न करें" + }, + "commandOpenPopup": { + "message": "ओपन वॉल्ट पॉपअप" + }, + "commandOpenSidebar": { + "message": "साइडबार में वॉल्ट खोले" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website." + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard." + }, + "commandLockVaultDesc": { + "message": "वॉल्ट लॉक करें" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "मूल्य" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "सॉर्ट करने के लिए ड्रैग करें" + }, + "cfTypeText": { + "message": "शब्द" + }, + "cfTypeHidden": { + "message": "छुपा हुआ" + }, + "cfTypeBoolean": { + "message": "बूलियन" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "अपने सत्यापन कोड के लिए अपने ईमेल की जांच करने के लिए पॉपअप विंडो के बाहर क्लिक करने से यह पॉपअप बंद हो जाएगा।क्या आप इस पॉपअप को एक नई विंडो में खोलना चाहते हैं ताकि यह बंद न हो?" + }, + "popupU2fCloseMessage": { + "message": "यह ब्राउज़र इस पॉपअप विंडो में U2F अनुरोधों को संसाधित नहीं कर सकता है।क्या आप इस पॉपअप को एक नई विंडो में खोलना चाहते हैं ताकि आप U2F का उपयोग करके लॉग इन कर सकें?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provides a recognizable icon next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "बैज काउंटर को अक्षम कर दो" + }, + "disableBadgeCounterDesc": { + "message": "बैज काउंटर निर्देश करता है कि आपके वॉल्ट में वर्तमान पृष्ठ के लिए आपके पास कितने लॉगिन हैं।" + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "संख्या" + }, + "brand": { + "message": "ब्रांड" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "समय सीमा समाप्ति" + }, + "january": { + "message": "जनवरी" + }, + "february": { + "message": "फरवरी" + }, + "march": { + "message": "मार्च" + }, + "april": { + "message": "अप्रैल" + }, + "may": { + "message": "मई" + }, + "june": { + "message": "जून" + }, + "july": { + "message": "जुलाई" + }, + "august": { + "message": "अगस्त" + }, + "september": { + "message": "सितम्बर" + }, + "october": { + "message": "अक्टूबर" + }, + "november": { + "message": "नवंबर" + }, + "december": { + "message": "दिसंबर" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "शीर्षक" + }, + "mr": { + "message": "श्री" + }, + "mrs": { + "message": "श्रीमती" + }, + "ms": { + "message": "श्रीमती" + }, + "dr": { + "message": "डॉ" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "कंपनी" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "ईमेल" + }, + "phone": { + "message": "फोन" + }, + "address": { + "message": "पता" + }, + "address1": { + "message": "पता 1" + }, + "address2": { + "message": "पता 2" + }, + "address3": { + "message": "पता 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "देश" + }, + "type": { + "message": "प्रकार" + }, + "typeLogin": { + "message": "लॉग इन" + }, + "typeLogins": { + "message": "लॉग इन" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "कार्ड" + }, + "typeIdentity": { + "message": "पहचान" + }, + "passwordHistory": { + "message": "पासवर्ड इतिहास" + }, + "back": { + "message": "वापस जाएं" + }, + "collections": { + "message": "संग्रह" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "एक नई विंडो के लिए पॉप आउट करें" + }, + "refresh": { + "message": "रीफ्रेश करें" + }, + "cards": { + "message": "कार्ड्स" + }, + "identities": { + "message": "पहचान" + }, + "logins": { + "message": "लॉग इन" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "खाली करें", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "चेक करें कि पासवर्ड सामने आ गया है या नहीं।" + }, + "passwordExposed": { + "message": "This password has been exposed in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "यह पासवर्ड किसी भी ज्ञात डेटा उल्लंघनों में नहीं पाया गया था।इसका उपयोग करना सुरक्षित होना चाहिए।" + }, + "baseDomain": { + "message": "बेस डोमेन", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "मेजबान", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "सटीक" + }, + "startsWith": { + "message": "इससे शुरू होता है" + }, + "regEx": { + "message": "नियमित अभिव्यक्ति", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "डिफॉल्ट मैच डिटेक्शन", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "वर्तमान URI's को टॉगल करें", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "वर्तमान URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "प्रकार" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "सूची के लिए कोई पासवर्ड नहीं हैं।" + }, + "remove": { + "message": "हटाएं" + }, + "default": { + "message": "डिफॉल्ट" + }, + "dateUpdated": { + "message": "अपडेट किया गया", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "क्या आप सुनिश्चित हैं कि आप \"कभी नहीं\" विकल्प का उपयोग करना चाहते हैं?\"कभी नहीं\" के लिए अपने लॉक विकल्प को सेट करना आपके डिवाइस पर आपकी वॉल्ट की एन्क्रिप्शन कुंजी को स्टोर करता है। यदि आप इस विकल्प का उपयोग करते हैं तो आपको यह सुनिश्चित करना चाहिए कि आप अपने डिवाइस को ठीक से सुरक्षित रखें।" + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "सूची में कोई संग्रह नहीं है।" + }, + "ownership": { + "message": "मालिकी" + }, + "whoOwnsThisItem": { + "message": "इस आइटम का मालिक कौन है?" + }, + "strong": { + "message": "मजबूत", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "अच्छा", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "कमजोर", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "आपके द्वारा चुना गया मास्टर पासवर्ड कमजोर है। आपको अपने बिटवर्डन खाते की ठीक से सुरक्षा के लिए एक मजबूत मास्टर पासवर्ड (या पासवाफ्रेज़) का उपयोग करना चाहिए।क्या आप सुनिश्चित हैं कि आप इस मास्टर पासवर्ड का उपयोग करना चाहते हैं?" + }, + "pin": { + "message": "पिन", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "पिन से अनलॉक करें " + }, + "setYourPinCode": { + "message": "बिटवर्डन को अनलॉक करने के लिए अपना पिन कोड सेट करें यदि आप कभी भी आवेदन से पूरी तरह लॉग आउट करते हैं तो आपकी पिन सेटिंग्स रीसेट हो जाएंगी।" + }, + "pinRequired": { + "message": "पिन-कोड आवश्यक है |" + }, + "invalidPin": { + "message": "अमान्य पिन कोड।" + }, + "unlockWithBiometrics": { + "message": "बायोमेट्रिक्स का उपयोग कर अनलॉक करें" + }, + "awaitDesktop": { + "message": "डेस्कटॉप से पुष्टि का इंतजार" + }, + "awaitDesktopDesc": { + "message": "ब्राउज़र के लिए बॉयोमीट्रिक्स सक्षम करने के लिए Bitwarden डेस्कटॉप आवेदन में बॉयोमीट्रिक्स का उपयोग कर पुष्टि करें।" + }, + "lockWithMasterPassOnRestart": { + "message": "ब्राउज़र पुनः आरंभ करने पर मास्टर पासवर्ड के साथ लॉक करें" + }, + "selectOneCollection": { + "message": "आपको कम से कम एक संग्रह का चयन करना होगा।" + }, + "cloneItem": { + "message": "क्लोन आइटम" + }, + "clone": { + "message": "क्लोन" + }, + "passwordGeneratorPolicyInEffect": { + "message": "एक या एक से अधिक संगठन नीतियां आपकी जनरेटर सेटिंग को प्रभावित कर रही हैं।" + }, + "vaultTimeoutAction": { + "message": "वॉल्ट मध्यांतर कार्रवाई" + }, + "lock": { + "message": "लॉक", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "थ्रैश", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "थ्रैश में खोजें" + }, + "permanentlyDeleteItem": { + "message": "स्थायी रूप से आइटम हटाएं" + }, + "permanentlyDeleteItemConfirmation": { + "message": "क्या आप सुनिश्चित हैं कि आप इस आइटम को स्थायी रूप से हटाना चाहते हैं?" + }, + "permanentlyDeletedItem": { + "message": "स्थायी रूप से आइटम हटाएं" + }, + "restoreItem": { + "message": "आइटम बहाल करें" + }, + "restoreItemConfirmation": { + "message": "क्या आप सुनिश्चित हैं कि आप इस आइटम को बहाल करना चाहते हैं?" + }, + "restoredItem": { + "message": "बहाल आइटम" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "लॉग आउट करने से वॉल्टमें प्रवेश संभव नहीं होगा और समय समाप्त होने के बाद ऑनलाइन प्रमाणीकरण की आश्यकता होगी। आप इस सेटिंग्स को प्रयोग करने के लिए विश्वस्त हैं?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "मध्यांतर कार्रवाई की पुष्टि" + }, + "autoFillAndSave": { + "message": "ऑटो फिल और सेव" + }, + "autoFillSuccessAndSavedUri": { + "message": "ऑटो फिल आइटम और सेव URI" + }, + "autoFillSuccess": { + "message": "ऑटो फिल आइटम" + }, + "setMasterPassword": { + "message": "मास्टर पासवर्ड सेट करें" + }, + "masterPasswordPolicyInEffect": { + "message": "एक या एक से अधिक संगठन नीतियों को निम्नलिखित आवश्यकताओं को पूरा करने के लिए आपके मास्टर पासवर्ड की आवश्यकता होती है:" + }, + "policyInEffectMinComplexity": { + "message": "$SCORE$ का न्यूनतम जटिलता स्कोर", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "$LENGTH$ की न्यूनतम लंबाई", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "एक या एक से अधिक ऊपरी अक्षर रखे" + }, + "policyInEffectLowercase": { + "message": "एक या एक से अधिक लोअरकेस अक्षर रखे" + }, + "policyInEffectNumbers": { + "message": "एक या अधिक संख्या रखे" + }, + "policyInEffectSpecial": { + "message": "निम्नलिखित विशेष पात्रों में से एक या अधिक शामिल रखे $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "आपका नया मास्टर पासवर्ड पॉलिसी आवश्यकताओं को पूरा नहीं करता है।" + }, + "acceptPolicies": { + "message": "इस बॉक्स की जांच करके आप निम्नलिखित से सहमत हैं:" + }, + "acceptPoliciesError": { + "message": "सेवा और गोपनीयता नीति की शर्तों को स्वीकार नहीं किया गया है ।" + }, + "termsOfService": { + "message": "सेवा की शर्तें" + }, + "privacyPolicy": { + "message": "प्राइवेसी पोलिसी" + }, + "hintEqualsPassword": { + "message": "आपका पासवर्ड संकेत आपके पासवर्ड के समान नहीं हो सकता है।" + }, + "ok": { + "message": "ठीक है" + }, + "desktopSyncVerificationTitle": { + "message": "डेस्कटॉप सिंक सत्यापन" + }, + "desktopIntegrationVerificationText": { + "message": "कृपया सत्यापित करें कि डेस्कटॉप एप्लिकेशन इस फिंगरप्रिंट को दिखाता है:" + }, + "desktopIntegrationDisabledTitle": { + "message": "ब्राउज़र एकीकरण सक्षम नहीं है" + }, + "desktopIntegrationDisabledDesc": { + "message": "ब्राउज़र एकीकरण बिटवर्डन डेस्कटॉप एप्लिकेशन में सक्षम नहीं है।कृपया इसे डेस्कटॉप एप्लिकेशन के भीतर सेटिंग्स में सक्षम करें।" + }, + "startDesktopTitle": { + "message": "बिटवर्डन डेस्कटॉप एप्लिकेशन शुरू करें" + }, + "startDesktopDesc": { + "message": "इस फ़ंक्शन का उपयोग करने से पहले बिटवर्डन डेस्कटॉप एप्लिकेशन को शुरू करने की आवश्यकता है।" + }, + "errorEnableBiometricTitle": { + "message": "बॉयोमीट्रिक्स सक्षम करने में असमर्थ" + }, + "errorEnableBiometricDesc": { + "message": "डेस्कटॉप एप्लिकेशन द्वारा कार्रवाई रद्द कर दी गई थी" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "डेस्कटॉप एप्लिकेशन ने सुरक्षित संचार चैनल को अमान्य कर दिया। कृपया इस ऑपरेशन को फिर से प्रयास करें" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "डेस्कटॉप संचार बाधित" + }, + "nativeMessagingWrongUserDesc": { + "message": "डेस्कटॉप एप्लिकेशन को एक अलग खाते में लॉग इन किया जाता है। कृपया सुनिश्चित करें कि दोनों आवेदन एक ही खाते में लॉग इन किए गए हैं।" + }, + "nativeMessagingWrongUserTitle": { + "message": "खाता गलत मैच" + }, + "biometricsNotEnabledTitle": { + "message": "बॉयोमीट्रिक्स सक्षम नहीं है" + }, + "biometricsNotEnabledDesc": { + "message": "ब्राउज़र बॉयोमीट्रिक्स पहले सेटिंग्स में सक्षम होने के लिए डेस्कटॉप बॉयोमीट्रिक की आवश्यकता है ।" + }, + "biometricsNotSupportedTitle": { + "message": "बॉयोमीट्रिक्स सक्षम नहीं है" + }, + "biometricsNotSupportedDesc": { + "message": "ब्राउज़र बॉयोमीट्रिक्स इस डिवाइस पर समर्थित नहीं है।" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "अनुमति नहीं दी गयी है" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "बिटवर्डन डेस्कटॉप एप्लिकेशन के साथ संवाद करने की अनुमति के बिना हम ब्राउज़र एक्सटेंशन में बॉयोमीट्रिक्स प्रदान नहीं कर सकते हैं।कृपया फिर से प्रयास करें।" + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "अनुमति अनुरोध त्रुटि" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "यह क्रिया साइडबार में नहीं की जा सकती है, कृपया पॉपअप या पॉपआउट में कार्रवाई का फिर से प्रयास करें।" + }, + "personalOwnershipSubmitError": { + "message": "एंटरप्राइज पॉलिसी के कारण, आप अपनी व्यक्तिगत वॉल्ट में वस्तुओं को सहेजने से प्रतिबंधित हैं।किसी संगठन के स्वामित्व विकल्प को बदलें और उपलब्ध संग्रहों में से चुनें।" + }, + "personalOwnershipPolicyInEffect": { + "message": "एक संगठन नीति आपके स्वामित्व विकल्पों को प्रभावित कर रही है।" + }, + "excludedDomains": { + "message": "बहिष्कृत डोमेन" + }, + "excludedDomainsDesc": { + "message": "बिटवर्डन इन डोमेन के लिए लॉगिन विवरण सहेजने के लिए नहीं कहेगा।परिवर्तनों को प्रभावी बनाने के लिए आपको पृष्ठ को ताज़ा करना होगा |" + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN $ एक वैध डोमेन नहीं है", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "भेजें", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Sends मे खोजे", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Send जोड़ें", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "शब्द" + }, + "sendTypeFile": { + "message": "फ़ाइल" + }, + "allSends": { + "message": "सभी Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "मैक्स एक्सेस काउंट पहुंच गया है", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": " गतावधिक" + }, + "pendingDeletion": { + "message": "हटाना लंबित" + }, + "passwordProtected": { + "message": "पासवर्ड सुरक्षित है" + }, + "copySendLink": { + "message": "कॉपी Send लिंक", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "पासवर्ड हटाएं" + }, + "delete": { + "message": "हटाएं" + }, + "removedPassword": { + "message": "पासवर्ड हटाएं" + }, + "deletedSend": { + "message": " Send हटाए गए", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send लिंक", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "अक्षम" + }, + "removePasswordConfirmation": { + "message": "क्या आप सयमुच पासवर्ड हटाना चाहते हैं?" + }, + "deleteSend": { + "message": " Send हटाए", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "क्या आप वाकई इस Send को मिटाना चाहते हैं?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "एडिट Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "यह किस प्रकार का सेंड है?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "इस सेंड का वर्णन करने के लिए एक दोस्ताना नाम।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "वह फाइल जो आप सेंड करना चाहते हैं।" + }, + "deletionDate": { + "message": "हटाने की तारीख" + }, + "deletionDateDesc": { + "message": " यह सेंड निर्धारित तिथि और समय पर स्थायी रूप से हटा दिया जाएगा।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "समाप्ति तिथि" + }, + "expirationDateDesc": { + "message": "यदि सेट किया जाता है, तो यह सेंड निर्दिष्ट तिथि और समय पर समाप्त हो जाएगा।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 दिन" + }, + "days": { + "message": "#DAYS# दिन", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "कस्टम" + }, + "maximumAccessCount": { + "message": "अधिकतम एक्सेस काउंट" + }, + "maximumAccessCountDesc": { + "message": "यदि सेट किया जाता है, तो अधिकतम एक्सेस काउंट तक पहुंचने के बाद उपयोगकर्ता अब इस सेंड को एक्सेस नहीं कर पाएंगे।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "वैकल्पिक रूप से उपयोगकर्ताओं को इस सेंड तक पहुंचने के लिए पासवर्ड की आवश्यकता होगी।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "इस सेंड के बारे में निजी नोट्स।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "इस सेंड को अक्षम करें ताकि कोई भी इसे एक्सेस न कर सके।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "सेव पर क्लिपबोर्ड पर इस सेंड के लिंक को कॉपी करें।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "वह टेक्स्ट जो आप सेंड करना चाहते हैं।" + }, + "sendHideText": { + "message": "इस सेंड के टेक्स्ट को डिफ़ॉल्ट रूप से छिपाएं।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "वर्तमान एक्सेस काउंट" + }, + "createSend": { + "message": "नया सेंड बनाएं", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "नया पासवर्ड" + }, + "sendDisabled": { + "message": "सेंड अक्षम", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "एक उद्यम नीति के कारण, आप केवल मौजूदा सेंड को हटाने में सक्षम हैं।", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "नया सेंड बनाया गया", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "सेंड एडिट किया गया", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "फ़ाइल चुनने के लिए, साइडबार (यदि संभव हो) में एक्सटेंशन खोलें या इस बैनर पर क्लिक करके एक नई विंडो को पॉप आउट करें।" + }, + "sendFirefoxFileWarning": { + "message": "फ़ायरफ़ॉक्स का उपयोग करके फ़ाइल चुनने के लिए, साइडबार में एक्सटेंशन खोलें या इस बैनर पर क्लिक करके एक नई विंडो को पॉप आउट करें।" + }, + "sendSafariFileWarning": { + "message": "सफारी का उपयोग करके फ़ाइल चुनने के लिए, इस बैनर पर क्लिक करके एक नई विंडो को पॉप आउट करें।" + }, + "sendFileCalloutHeader": { + "message": "शुरू करने से पहले" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "कैलेंडर शैली तिथि बीनने वाले का उपयोग करने के लिए", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "यहां क्लिक करें", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "अपनी विंडो पॉप आउट करने के लिए यहां क्लिक करें।", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "प्रदान की गई समाप्ति तिथि मान्य नहीं है।" + }, + "deletionDateIsInvalid": { + "message": "प्रदान की गई विलोपन तिथि मान्य नहीं है।" + }, + "expirationDateAndTimeRequired": { + "message": "एक समाप्ति तिथि और समय की आवश्यकता है।" + }, + "deletionDateAndTimeRequired": { + "message": "एक विलोपन तिथि और समय की आवश्यकता है।" + }, + "dateParsingError": { + "message": "आपके विलोपन और समाप्ति तिथियों को सहेजने में एक त्रुटि थी।" + }, + "hideEmail": { + "message": "प्राप्तकर्ताओं से मेरा ईमेल पता छिपाएं।" + }, + "sendOptionsPolicyInEffect": { + "message": "एक या एक से अधिक संगठन नीतियां आपके सेंड विकल्पों को प्रभावित कर रही हैं।" + }, + "passwordPrompt": { + "message": "मास्टर पासवर्ड रि-प्रॉम्प्ट" + }, + "passwordConfirmation": { + "message": "मास्टर पासवर्ड पुष्टि" + }, + "passwordConfirmationDesc": { + "message": "यह क्रिया सुरक्षित है। जारी रखने के लिए, कृपया अपनी पहचान सत्यापित करने के लिए अपना मास्टर पासवर्ड फिर से दर्ज करें।" + }, + "emailVerificationRequired": { + "message": "ईमेल सत्यापन आवश्यक है" + }, + "emailVerificationRequiredDesc": { + "message": "इस सुविधा का उपयोग करने के लिए आपको अपने ईमेल को सत्यापित करना होगा। आप वेब वॉल्ट में अपने ईमेल को सत्यापित कर सकते हैं।" + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/hr/messages.json b/apps/browser/src/_locales/hr/messages.json new file mode 100644 index 0000000000..ddc72e26aa --- /dev/null +++ b/apps/browser/src/_locales/hr/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - besplatni upravitelj lozinki", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden je siguran i besplatan upravitelj lozinki za sve tvoje uređaje.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Prijavi se ili stvori novi račun za pristup svojem sigurnom trezoru." + }, + "createAccount": { + "message": "Stvori račun" + }, + "login": { + "message": "Prijava" + }, + "enterpriseSingleSignOn": { + "message": "Jedinstvena prijava na razini tvrtke (SSO)" + }, + "cancel": { + "message": "Odustani" + }, + "close": { + "message": "Zatvori" + }, + "submit": { + "message": "Pošalji" + }, + "emailAddress": { + "message": "Adresa e-pošte" + }, + "masterPass": { + "message": "Glavna lozinka" + }, + "masterPassDesc": { + "message": "Glavnu lozinku koristiš za pristup svom trezoru. Vrlo je važno da ne zaboraviš glavnu lozinku. Ne postoji način za oporavak lozinke u slučaju da ju zaboraviš." + }, + "masterPassHintDesc": { + "message": "Podsjetnik glavne lozinke ti može pomoći da se prisjetiš svoje lozinke ako ju zaboraviš." + }, + "reTypeMasterPass": { + "message": "Ponovno upiši glavnu lozinku" + }, + "masterPassHint": { + "message": "Podsjetnik glavne lozinke (neobavezno)" + }, + "tab": { + "message": "Kartica" + }, + "myVault": { + "message": "Moj trezor" + }, + "tools": { + "message": "Alati" + }, + "settings": { + "message": "Postavke" + }, + "currentTab": { + "message": "Trenutna kartica" + }, + "copyPassword": { + "message": "Kopiraj lozinku" + }, + "copyNote": { + "message": "Kopiraj bilješku" + }, + "copyUri": { + "message": "Kopiraj URI" + }, + "copyUsername": { + "message": "Kopiraj korisničko ime" + }, + "copyNumber": { + "message": "Kopiraj broj" + }, + "copySecurityCode": { + "message": "Kopiraj kontrolni broj" + }, + "autoFill": { + "message": "Auto-ispuna" + }, + "generatePasswordCopied": { + "message": "Generiraj lozinku (i kopiraj)" + }, + "copyElementIdentifier": { + "message": "Kopiranje prilagođenog naziva polja" + }, + "noMatchingLogins": { + "message": "Nema podudarajućih prijava." + }, + "unlockVaultMenu": { + "message": "Otključaj trezor" + }, + "loginToVaultMenu": { + "message": "Prijavite se u svoj trezor" + }, + "autoFillInfo": { + "message": "Nema dostupnih prijava za auto-ispunu na web stranici u ovoj kartici." + }, + "addLogin": { + "message": "Dodaj prijavu" + }, + "addItem": { + "message": "Dodaj stavku" + }, + "passwordHint": { + "message": "Podsjetnik za lozinku" + }, + "enterEmailToGetHint": { + "message": "Unesi adresu e-pošte svog računa za primitak podsjetnika glavne lozinke." + }, + "getMasterPasswordHint": { + "message": "Slanje podsjetnika glavne lozinke" + }, + "continue": { + "message": "Nastavi" + }, + "sendVerificationCode": { + "message": "Slanje verifikacijskog kôda e-poštom" + }, + "sendCode": { + "message": "Pošalji kôd" + }, + "codeSent": { + "message": "Kôd poslan" + }, + "verificationCode": { + "message": "Kôd za provjeru" + }, + "confirmIdentity": { + "message": "Potvrdite lozinku za nastavak." + }, + "account": { + "message": "Račun" + }, + "changeMasterPassword": { + "message": "Promjeni glavnu lozinku" + }, + "fingerprintPhrase": { + "message": "Jedinstvena fraza", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Jedinstvena fraza tvog računa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Prijava u dva koraka" + }, + "logOut": { + "message": "Odjavi se" + }, + "about": { + "message": "O aplikaciji" + }, + "version": { + "message": "Verzija" + }, + "save": { + "message": "Spremi" + }, + "move": { + "message": "Premjesti" + }, + "addFolder": { + "message": "Dodaj mapu" + }, + "name": { + "message": "Naziv" + }, + "editFolder": { + "message": "Uredi mapu" + }, + "deleteFolder": { + "message": "Izbriši mapu" + }, + "folders": { + "message": "Mape" + }, + "noFolders": { + "message": "Nema mapa na popisu." + }, + "helpFeedback": { + "message": "Pomoć i povratne informacije" + }, + "sync": { + "message": "Sinkronizacija" + }, + "syncVaultNow": { + "message": "Odmah sinkroniziraj trezor" + }, + "lastSync": { + "message": "Posljednja sinkronizacija:" + }, + "passGen": { + "message": "Generator lozinki" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatski generiraj jake, jedinstvene lozinke." + }, + "bitWebVault": { + "message": "Bitwarden Web trezor" + }, + "importItems": { + "message": "Uvoz stavki" + }, + "select": { + "message": "Odaberi" + }, + "generatePassword": { + "message": "Generiraj lozinku" + }, + "regeneratePassword": { + "message": "Ponovno generiraj lozinku" + }, + "options": { + "message": "Opcije" + }, + "length": { + "message": "Duljina" + }, + "uppercase": { + "message": "Velika slova (A-Z)" + }, + "lowercase": { + "message": "Mala slova (a-z)" + }, + "numbers": { + "message": "Brojevi (0-9)" + }, + "specialCharacters": { + "message": "Posebni znakovi (!@#$%^&*)" + }, + "numWords": { + "message": "Broj riječi" + }, + "wordSeparator": { + "message": "Razdjelitelj riječi" + }, + "capitalize": { + "message": "Prva slova velika", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Uključi broj" + }, + "minNumbers": { + "message": "Najmanje brojeva" + }, + "minSpecial": { + "message": "Najmanje specijalnih" + }, + "avoidAmbChar": { + "message": "Izbjegavaj dvosmislene znakove" + }, + "searchVault": { + "message": "Pretraži trezor" + }, + "edit": { + "message": "Uredi" + }, + "view": { + "message": "Prikaz" + }, + "noItemsInList": { + "message": "Nema stavki za prikaz." + }, + "itemInformation": { + "message": "Informacije o stavci" + }, + "username": { + "message": "Korisničko ime" + }, + "password": { + "message": "Lozinka" + }, + "passphrase": { + "message": "Frazna lozinka" + }, + "favorite": { + "message": "Favorit" + }, + "notes": { + "message": "Bilješke" + }, + "note": { + "message": "Bilješka" + }, + "editItem": { + "message": "Uredi stavku" + }, + "folder": { + "message": "Mapa" + }, + "deleteItem": { + "message": "Izbriši stavku" + }, + "viewItem": { + "message": "Prikaz stavke" + }, + "launch": { + "message": "Pokreni" + }, + "website": { + "message": "Web stranica" + }, + "toggleVisibility": { + "message": "Prikaži/Sakrij" + }, + "manage": { + "message": "Upravljanje" + }, + "other": { + "message": "Ostalo" + }, + "rateExtension": { + "message": "Ocijeni proširenje" + }, + "rateExtensionDesc": { + "message": "Razmotri da nam pomogneš dobrom recenzijom!" + }, + "browserNotSupportClipboard": { + "message": "Web preglednik ne podržava jednostavno kopiranje međuspremnika. Umjesto toga ručno kopirajte." + }, + "verifyIdentity": { + "message": "Potvrdi identitet" + }, + "yourVaultIsLocked": { + "message": "Tvoj trezor je zaključan. Potvrdi glavnu lozinku za nastavak." + }, + "unlock": { + "message": "Otključaj" + }, + "loggedInAsOn": { + "message": "Korisnički račun: $EMAIL$ na $HOSTNAME$", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Neispravna glavna lozinka" + }, + "vaultTimeout": { + "message": "Istek trezora" + }, + "lockNow": { + "message": "Zaključaj sada" + }, + "immediately": { + "message": "Odmah" + }, + "tenSeconds": { + "message": "10 sekundi" + }, + "twentySeconds": { + "message": "20 sekundi" + }, + "thirtySeconds": { + "message": "30 sekundi" + }, + "oneMinute": { + "message": "1 minuta" + }, + "twoMinutes": { + "message": "2 minute" + }, + "fiveMinutes": { + "message": "5 minuta" + }, + "fifteenMinutes": { + "message": "15 minuta" + }, + "thirtyMinutes": { + "message": "30 minuta" + }, + "oneHour": { + "message": "1 sat" + }, + "fourHours": { + "message": "4 sata" + }, + "onLocked": { + "message": "Pri zaključavanju sustava" + }, + "onRestart": { + "message": "Pri pokretanju preglednika" + }, + "never": { + "message": "Nikad" + }, + "security": { + "message": "Sigurnost" + }, + "errorOccurred": { + "message": "Došlo je do pogreške" + }, + "emailRequired": { + "message": "Adresa e-pošte je obavezna." + }, + "invalidEmail": { + "message": "Neispravna adresa e-pošte." + }, + "masterPassRequired": { + "message": "Potrebna je glavna lozinka." + }, + "masterPassLength": { + "message": "Glavna lozinka mora imati najmanje 8 znakova." + }, + "masterPassDoesntMatch": { + "message": "Potvrda glavne lozinke se ne podudara." + }, + "newAccountCreated": { + "message": "Tvoj novi račun je kreiran! Sada se možeš prijaviti." + }, + "masterPassSent": { + "message": "Poslali smo e-poštu s podsjetnikom glavne lozinke." + }, + "verificationCodeRequired": { + "message": "Potvrdni kôd je obavezan." + }, + "invalidVerificationCode": { + "message": "Nevažeći kôd za provjeru" + }, + "valueCopied": { + "message": " kopirano", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Nije moguće auto-ispuniti odabranu prijavu na ovoj stranici. Umjesto toga kopiraj/zalijepi podatke." + }, + "loggedOut": { + "message": "Odjavljen" + }, + "loginExpired": { + "message": "Sesija je istekla." + }, + "logOutConfirmation": { + "message": "Sigurno se želiš odjaviti?" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Ne" + }, + "unexpectedError": { + "message": "Došlo je do neočekivane pogreške." + }, + "nameRequired": { + "message": "Ime je obavezno." + }, + "addedFolder": { + "message": "Mapa dodana" + }, + "changeMasterPass": { + "message": "Promjeni glavnu lozinku" + }, + "changeMasterPasswordConfirmation": { + "message": "Svoju glavnu lozinku možeš promijeniti na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "twoStepLoginConfirmation": { + "message": "Prijava u dva koraka čini tvoj račun još sigurnijim tako što će zahtijevati da potvrdiš prijavu putem drugog uređaja kao što je sigurnosni ključ, autentifikatorske aplikacije, SMS-om, pozivom ili e-poštom. Prijavu u dva koraka možeš omogućiti na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "editedFolder": { + "message": "Uređena mapa" + }, + "deleteFolderConfirmation": { + "message": "Sigurno želiš izbrisati ovu mapu?" + }, + "deletedFolder": { + "message": "Mapa izbrisana" + }, + "gettingStartedTutorial": { + "message": "Priručnik za početak rada" + }, + "gettingStartedTutorialVideo": { + "message": "Pogledaj naš početni vodič za savjete kako najbolje iskoristiti proširenje preglednika." + }, + "syncingComplete": { + "message": "Sinkronizacija dovršena" + }, + "syncingFailed": { + "message": "Sinkronizacija nije uspjela" + }, + "passwordCopied": { + "message": "Lozinka kopirana" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novi URI" + }, + "addedItem": { + "message": "Stavka dodana" + }, + "editedItem": { + "message": "Stavka izmijenjena" + }, + "deleteItemConfirmation": { + "message": "Želiš li zaista poslati u smeće?" + }, + "deletedItem": { + "message": "Stavka poslana u smeće" + }, + "overwritePassword": { + "message": "Prebriši lozinku" + }, + "overwritePasswordConfirmation": { + "message": "Sigurno želiš prebrisati trenutnu lozinku?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Mapa pretraživanja" + }, + "searchCollection": { + "message": "Pretraživanje zbirke" + }, + "searchType": { + "message": "Tip pretrage" + }, + "noneFolder": { + "message": "Nema mape", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Onemogući upit za dodavanje prijave" + }, + "addLoginNotificationDesc": { + "message": "Upit za dodavanje prijave pojavljuje se kada se otkrije prva prijava na neko web mjesto. Bitwarden će te pitatati želiš li uneseno korisničko ime i lozinku spremiti u svoj trezor." + }, + "dontShowCardsCurrentTab": { + "message": "Ne prikazuj platne kartice" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Ne prikazuje Platne kartice iz tvog trezora prilikom prikaza stavki dostupnih za jednostavnu auto-ispunu." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Ne prikazuj Identitete" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Ne prikazuje Identitete iz tvog trezora prilikom prikaza stavki dostupnih za jednostavnu auto-ispunu." + }, + "clearClipboard": { + "message": "Očisti međuspremnik", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatski očisti kopirane vrijednosti iz međuspremnika.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Treba li Bitwarden zapamtiti ovu lozinku?" + }, + "notificationAddSave": { + "message": "Spremi" + }, + "disableChangedPasswordNotification": { + "message": "Onemogući upit za spremanje ažurirane lozinke" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Upit za spremanje ažurirane lozinke pojavljuje se kada se otkrije da je na nekoj web stranici unesena lozinka drugačija od one spremljene u trezoru. Bitwarden će te pitatati želiš li ažurirati lozinku u trezoru." + }, + "notificationChangeDesc": { + "message": "Želiš li ovu lozinku ažurirati u Bitwarden-u?" + }, + "notificationChangeSave": { + "message": "Ažuriraj" + }, + "disableContextMenuItem": { + "message": "Onemogući kontekstualni izbornik u pregledniku" + }, + "disableContextMenuItemDesc": { + "message": "Kontekstualni izbornik omogućuje brzi pristup korisničkim imenima i lozinkama, kao i generiranje i kopiranje generirane lozinke jednim klikom." + }, + "defaultUriMatchDetection": { + "message": "Zadano otkrivanje URI podudaranja", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Odaberi zadani način na koji će se riješavati otkrivanje URI-ja za prijavu pri izvođenju radnji kao što je auto-ispuna." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Promijeni temu boja." + }, + "dark": { + "message": "Tamna", + "description": "Dark color" + }, + "light": { + "message": "Svijetla", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarizirana Tamna", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Izvezi trezor" + }, + "fileFormat": { + "message": "Format datoteke" + }, + "warning": { + "message": "UPOZORENJE", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potvrdi izvoz trezora" + }, + "exportWarningDesc": { + "message": "Ovaj izvoz sadrži podatke trezora u nešifriranom obliku! Izvezenu datoteku se ne bi smjelo pohranjivati ili slati putem nesigurnih kanala (npr. e-poštom). Izbriši ju odmah nakon završetka korištenja." + }, + "encExportKeyWarningDesc": { + "message": "Ovaj izvoz šifrira tvoje podatke koristeći ključ za šifriranje. Promijeniš li naknadno ključ za šifriranje, potrebno je ponovno napraviti izvoz jer nećeš moći dešifrirati ovu izvezenu datoteku." + }, + "encExportAccountWarningDesc": { + "message": "Ključ za šifriranje jedinstven je za svakog Bitwarden korisnika, kako bi se šifrirani izvoz mogao uvesti u drugi korisnički račun." + }, + "exportMasterPassword": { + "message": "Unesi glavnu lozinku za izvoz podataka iz trezora." + }, + "shared": { + "message": "Dijeljeno" + }, + "learnOrg": { + "message": "Više o organizacijama" + }, + "learnOrgConfirmation": { + "message": "Bitwarden omogućuje dijeljenje trezora s drugima pomoću organizacijskog računa. Želiš li sada posjetiti bitwarden.com za više informacija?" + }, + "moveToOrganization": { + "message": "Premjesti u organizaciju" + }, + "share": { + "message": "Podijeli" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ premješteno u $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Odaberi organizaciju u koju želiš premjestiti ovu stavku. Premještanje prenosi vlasništvo stavke na organizaciju. Nakon premještanja više nećeš biti izravni vlasnik ove stavke." + }, + "learnMore": { + "message": "Saznaj više" + }, + "authenticatorKeyTotp": { + "message": "Ključ autentifikatora (TOTP)" + }, + "verificationCodeTotp": { + "message": "Kôd za provjeru (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopiraj kôd za provjeru" + }, + "attachments": { + "message": "Privitci" + }, + "deleteAttachment": { + "message": "Izbriši privitak" + }, + "deleteAttachmentConfirmation": { + "message": "Sigurno želiš izbrisati ovaj privitak?" + }, + "deletedAttachment": { + "message": "Izbrisani privitak" + }, + "newAttachment": { + "message": "Dodaj novi privitak" + }, + "noAttachments": { + "message": "Nema privitaka." + }, + "attachmentSaved": { + "message": "Privitak je spremljen." + }, + "file": { + "message": "Datoteka" + }, + "selectFile": { + "message": "Odaberi datoteku." + }, + "maxFileSize": { + "message": "Najveća veličina datoteke je 500 MB." + }, + "featureUnavailable": { + "message": "Značajka nije dostupna" + }, + "updateKey": { + "message": "Ne možeš koristiti ovu značajku prije nego ažuriraš ključ za šifriranje." + }, + "premiumMembership": { + "message": "Premium članstvo" + }, + "premiumManage": { + "message": "Upravljaj članstvom" + }, + "premiumManageAlert": { + "message": "Svojim članstvom možeš upravljati na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "premiumRefresh": { + "message": "Osvježi status članstva" + }, + "premiumNotCurrentMember": { + "message": "Trenutno nisi premium član." + }, + "premiumSignUpAndGet": { + "message": "Prijavi se za premium članstvo, čime dobivaš:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB šifriranog prostora za pohranu podataka." + }, + "ppremiumSignUpTwoStep": { + "message": "Dodatne mogućnosti za prijavu u dva koraka kao što su YubiKey, FIDO U2F i Duo." + }, + "ppremiumSignUpReports": { + "message": "Higijenu lozinki, zdravlje računa i izvještaje o krađi podatak radi zaštite svojeg trezora." + }, + "ppremiumSignUpTotp": { + "message": "Generator TOTP kontrolnog koda (2FA) za prijave u tvom trezoru." + }, + "ppremiumSignUpSupport": { + "message": "Prioritetnu korisničku podršku." + }, + "ppremiumSignUpFuture": { + "message": "Sve buduće premium značajke. Uskoro više!" + }, + "premiumPurchase": { + "message": "Kupi premium članstvo" + }, + "premiumPurchaseAlert": { + "message": "Možeš kupiti premium članstvo na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "premiumCurrentMember": { + "message": "Ti si premium član!" + }, + "premiumCurrentMemberThanks": { + "message": "Hvala ti što podupireš Bitwarden." + }, + "premiumPrice": { + "message": "Sve za samo $PRICE$ /godišnje!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Osvježavanje završeno" + }, + "disableAutoTotpCopy": { + "message": "Onemogući automatsko kopiranje TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Ako se za prijavu koristi dvostruka autentifikacija, TOTP kontrolni kôd se automatski kopira u međuspremnik nakon auto-ispune korisničkog imena i lozinke." + }, + "disableAutoBiometricsPrompt": { + "message": "Ne traži biometriju pri pokretanju" + }, + "premiumRequired": { + "message": "Potrebno premium članstvo" + }, + "premiumRequiredDesc": { + "message": "Za korištenje ove značajke potrebno je premium članstvo." + }, + "enterVerificationCodeApp": { + "message": "Unesi 6-znamenkasti kontrolni kôd iz autentifikatorske aplikacije." + }, + "enterVerificationCodeEmail": { + "message": "Unesi 6-znamenkasti kontrolni kôd poslan e-poštom na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-pošta za potvrdu poslana je na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamti me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Ponovno slanje kontrolnog koda e-poštom" + }, + "useAnotherTwoStepMethod": { + "message": "Koristiti drugi način prijave u dva koraka" + }, + "insertYubiKey": { + "message": "Umetni svoj YubiKey u USB priključak računala, a zatim dodirni njegovu tipku." + }, + "insertU2f": { + "message": "Umetni svoj sigurnosni ključ u USB priključak računala. Ako ima tipku, dodirni ju." + }, + "webAuthnNewTab": { + "message": "Nastavi na WebAuthn 2FA verifikaciju u novoj kartici." + }, + "webAuthnNewTabOpen": { + "message": "Otvori novu karticu" + }, + "webAuthnAuthenticate": { + "message": "Ovjeri WebAuthn" + }, + "loginUnavailable": { + "message": "Prijava nije dostupna" + }, + "noTwoStepProviders": { + "message": "Ovaj račun ima omogućenu prijavu u dva koraka, međutim ovaj web preglednik ne podržava niti jednog konfiguriranog pružatelja prijave u dva koraka." + }, + "noTwoStepProviders2": { + "message": "Koristi podržani web-preglednik (npr. Chrome) i/ili dodaj dodatne usluge koje su bolje podržane u web preglednicima (npr. aplikacija Autentifikator)." + }, + "twoStepOptions": { + "message": "Mogućnosti prijave u dva koraka" + }, + "recoveryCodeDesc": { + "message": "Izgubljen je pristup uređaju za dvostruku autentifikaciju? Koristi svoj kôd za oporavak za onemogućavanje svih pružatelja usluga dvostruke autentifikacije na tvojem računu." + }, + "recoveryCodeTitle": { + "message": "Kôd za oporavak" + }, + "authenticatorAppTitle": { + "message": "Autentifikatorska aplikacija" + }, + "authenticatorAppDesc": { + "message": "Koristi autentifikatorsku aplikaciju (npr. Authy ili Google Authentifikator) za generiranje kontrolnih kodova.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP sigurnosni ključ" + }, + "yubiKeyDesc": { + "message": "Koristi YubiKey za pristup svojem računu. Radi s YubiKey 4, 4 Nano, 4C i NEO uređajima." + }, + "duoDesc": { + "message": "Potvrdi s Duo Security pomoću aplikacije Duo Mobile, SMS-om, telefonskim pozivom ili U2F sigurnosnim ključem.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Potvrdi s Duo Security za svoju organizaciju pomoću aplikacije Duo Mobile, SMS-om, telefonskim pozivom ili U2F sigurnosnim ključem.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Koristi WebAuthn sigurnosni ključ za pristup svojem računu." + }, + "emailTitle": { + "message": "E-pošta" + }, + "emailDesc": { + "message": "Verifikacijski kodovi će biti poslani e-poštom." + }, + "selfHostedEnvironment": { + "message": "Vlastito hosting okruženje" + }, + "selfHostedEnvironmentFooter": { + "message": "Navedi osnovni URL svoje lokalno smještene Bitwarden instalacije." + }, + "customEnvironment": { + "message": "Prilagođeno okruženje" + }, + "customEnvironmentFooter": { + "message": "Za napredne korisnike. Samostalno možeš odrediti osnovni URL svake usluge." + }, + "baseUrl": { + "message": "URL poslužitelja" + }, + "apiUrl": { + "message": "URL API poslužitelja" + }, + "webVaultUrl": { + "message": "URL poslužitelja web trezora" + }, + "identityUrl": { + "message": "URL id poslužitelja" + }, + "notificationsUrl": { + "message": "URL poslužitelja obavijesti" + }, + "iconsUrl": { + "message": "URL poslužitelja ikona" + }, + "environmentSaved": { + "message": "URL-ovi okoline su spremljeni." + }, + "enableAutoFillOnPageLoad": { + "message": "Omogući auto-ispunu nakon učitavanja stranice" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Ako se otkrije obrazac za prijavu, samostalno auto-ispuni kada se web stranica učita." + }, + "experimentalFeature": { + "message": "Ovo je trenutno eksperimentalna značajka. Koristi na vlastitu odgovornost." + }, + "defaultAutoFillOnPageLoad": { + "message": "Zadana postvaka Auto-ispune za prijave" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Nakon omogućavanja Auto-ispune kod učitavanja stranice, moguće je uključiti/isključiti ovu značajku za svaku pojedinu prijavu. Ovo je zadana postavka za prijave koje nisu pojedinčano određene." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-ispuna kod učitavanja stranice (ako je uključeno u Postavkama)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Koristi zadane postavke" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-ispuna kod učitavanja" + }, + "autoFillOnPageLoadNo": { + "message": "Ne koristi Auto-ispunu kod učitavanja" + }, + "commandOpenPopup": { + "message": "Otvori iskočni prozor trezora" + }, + "commandOpenSidebar": { + "message": "Otvori trezor u bočnoj traci" + }, + "commandAutofillDesc": { + "message": "Auto-ispuni zadnju korištenu prijavu za trenutnu web stranicu." + }, + "commandGeneratePasswordDesc": { + "message": "Generiraj i kopiraj novu nasumičnu lozinku u međuspremnik." + }, + "commandLockVaultDesc": { + "message": "Zaključaj trezor" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Prilagođena polja" + }, + "copyValue": { + "message": "Kopiraj vrijednost" + }, + "value": { + "message": "Vrijednost" + }, + "newCustomField": { + "message": "Novo prilagođeno polje" + }, + "dragToSort": { + "message": "Povuci za sortiranje" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Skriveno" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Povezano", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Povezana vrijednost", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Ako klikneš izvan iskočnog prozora, za provjeru kontrolnog kôda iz e-pošte, on će se zatvoriti. Želiš li ovaj iskočni prozor otvoriti u novom prozoru kako se ne bi zatvorio?" + }, + "popupU2fCloseMessage": { + "message": "Ovaj preglednik ne može obraditi U2F zahtjeve u ovom iskočnom prozoru. Želiš li otvoriti ovaj iskočni prozor u novom prozoru za prijavu putem U2F?" + }, + "disableFavicon": { + "message": "Onemogući ikone web mjesta" + }, + "disableFaviconDesc": { + "message": "Prepoznatljive ikone web mjesta prikazuju se pored prijava u tvom trezoru." + }, + "disableBadgeCounter": { + "message": "Onemogući brojač znački" + }, + "disableBadgeCounterDesc": { + "message": "Brojač znački prikazuje koliko u tvojem trezoru ima spremljenih prijava za trenutnu stranicu." + }, + "cardholderName": { + "message": "Vlasnik kartice" + }, + "number": { + "message": "Broj" + }, + "brand": { + "message": "Vrsta kartice" + }, + "expirationMonth": { + "message": "Mjesec isteka" + }, + "expirationYear": { + "message": "Godina isteka" + }, + "expiration": { + "message": "Istek" + }, + "january": { + "message": "siječanj" + }, + "february": { + "message": "veljača" + }, + "march": { + "message": "ožujak" + }, + "april": { + "message": "travanj" + }, + "may": { + "message": "svibanj" + }, + "june": { + "message": "lipanj" + }, + "july": { + "message": "srpanj" + }, + "august": { + "message": "kolovoz" + }, + "september": { + "message": "rujan" + }, + "october": { + "message": "listopad" + }, + "november": { + "message": "studeni" + }, + "december": { + "message": "prosinac" + }, + "securityCode": { + "message": "Kontrolni broj" + }, + "ex": { + "message": "npr." + }, + "title": { + "message": "Titula" + }, + "mr": { + "message": "g." + }, + "mrs": { + "message": "gđa." + }, + "ms": { + "message": "gđica." + }, + "dr": { + "message": "dr." + }, + "firstName": { + "message": "Ime" + }, + "middleName": { + "message": "Srednje ime" + }, + "lastName": { + "message": "Prezime" + }, + "fullName": { + "message": "Ime i prezime" + }, + "identityName": { + "message": "Ime identiteta" + }, + "company": { + "message": "Tvrtka" + }, + "ssn": { + "message": "Broj socijalnog osiguranja" + }, + "passportNumber": { + "message": "Broj putovnice" + }, + "licenseNumber": { + "message": "Broj vozačke dozvole" + }, + "email": { + "message": "E-pošta" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresa" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Grad / Mjesto" + }, + "stateProvince": { + "message": "Država / Pokrajina" + }, + "zipPostalCode": { + "message": "Poštanski broj" + }, + "country": { + "message": "Zemlja" + }, + "type": { + "message": "Vrsta" + }, + "typeLogin": { + "message": "Prijava" + }, + "typeLogins": { + "message": "Prijave" + }, + "typeSecureNote": { + "message": "Sigurna bilješka" + }, + "typeCard": { + "message": "Platna kartica" + }, + "typeIdentity": { + "message": "Identitet" + }, + "passwordHistory": { + "message": "Povijest" + }, + "back": { + "message": "Natrag" + }, + "collections": { + "message": "Zbirke" + }, + "favorites": { + "message": "Favoriti" + }, + "popOutNewWindow": { + "message": "Otvori u novom prozoru" + }, + "refresh": { + "message": "Osvježi" + }, + "cards": { + "message": "Platne kartice" + }, + "identities": { + "message": "Identiteti" + }, + "logins": { + "message": "Prijave" + }, + "secureNotes": { + "message": "Sigurne bilješke" + }, + "clear": { + "message": "Očisti", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Provjeri je li lozinka bila ukradena." + }, + "passwordExposed": { + "message": "Ova lozinka je otkrivena $VALUE$ put(a) prilikom krađe podataka. Trebalo bi ju promijeniti.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Lozinka nije pronađena niti u jednoj krađi podataka. Sigurna je za korištenje." + }, + "baseDomain": { + "message": "Primarna domena", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Točno" + }, + "startsWith": { + "message": "Počinje s" + }, + "regEx": { + "message": "Regularni izraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Otkrivanje podudaranja", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Zadano otkrivanje podudaranja", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Uključi/isključi opcije" + }, + "toggleCurrentUris": { + "message": "Uključi/Isključi trenutne URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Trenutni URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organizacija", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Vrste" + }, + "allItems": { + "message": "Sve stavke" + }, + "noPasswordsInList": { + "message": "Nema lozinki na popisu." + }, + "remove": { + "message": "Ukloni" + }, + "default": { + "message": "Zadano" + }, + "dateUpdated": { + "message": "Ažurirano", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Lozinka ažurirana", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Sigurno želiš koristiti opciju „Nikada”? Postavljanje opcija zaključavanja na „Nikada” pohranjuje šifru tvojeg trezora na tvom uređaju. Ako koristiš ovu opciju, trebali bi osigurati da je uređaj pravilno zaštićen." + }, + "noOrganizationsList": { + "message": "Ne pripadaš niti jednoj organizaciji. Organizacije omogućuju sigurno dijeljenje stavki s drugim korisnicima." + }, + "noCollectionsInList": { + "message": "Nema zbirki za prikaz." + }, + "ownership": { + "message": "Vlasništvo" + }, + "whoOwnsThisItem": { + "message": "Tko je vlasnik ove stavke?" + }, + "strong": { + "message": "Jaka", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobra", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slaba", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slaba glavna lozinka" + }, + "weakMasterPasswordDesc": { + "message": "Odabrana glavna lozinka je slaba. Trebaš koristiti jaču glavnu lozinku (ili frazu) kako bi tvoj Bitwarden račun bio pravilno zaštićen. Sigurno želiš koristiti ovakvu, slabu glavnu lozinku?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Otključaj PIN-om" + }, + "setYourPinCode": { + "message": "Postavi svoj PIN kôd za otključavanje Bitwardena. Postavke PIN-a se resetiraju ako se potpuno odjaviš iz aplikacije." + }, + "pinRequired": { + "message": "Potreban je PIN." + }, + "invalidPin": { + "message": "Nerispravan PIN." + }, + "unlockWithBiometrics": { + "message": "Otključaj biometrijom" + }, + "awaitDesktop": { + "message": "Čekanje potvrde iz desktop aplikacije" + }, + "awaitDesktopDesc": { + "message": "Potvrdi korištenje biometrije u Bitwarden desktop aplikaciji za korištenje biometrije u pregledniku." + }, + "lockWithMasterPassOnRestart": { + "message": "Zaključaj glavnom lozinkom kod svakog pokretanja preglednika" + }, + "selectOneCollection": { + "message": "Moraš odabrati barem jednu zbirku." + }, + "cloneItem": { + "message": "Kloniraj stavku" + }, + "clone": { + "message": "Kloniraj" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Jedno ili više pravila organizacije utječe na postavke generatora." + }, + "vaultTimeoutAction": { + "message": "Nakon isteka trezora" + }, + "lock": { + "message": "Zaključaj", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Smeće", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Pretraži smeće" + }, + "permanentlyDeleteItem": { + "message": "Trajno izbriši stavku" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Želiš li zaista trajno izbrisati ovu stavku?" + }, + "permanentlyDeletedItem": { + "message": "Trajno izbrisana stavka" + }, + "restoreItem": { + "message": "Vrati stavku" + }, + "restoreItemConfirmation": { + "message": "Sigurno želiš vratiti ovu stavku?" + }, + "restoredItem": { + "message": "Stavka vraćena" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Odjava će ukloniti pristup tvom trezoru i zahtijevati mrežnu potvrdu identiteta nakon isteka vremenske neaktivnosti. Sigurno želiš koristiti ovu postavku?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potvrda akcije vremenske neaktivnosti" + }, + "autoFillAndSave": { + "message": "Auto-ispuni i spremi" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-ispunjena stavka i spremanje URI" + }, + "autoFillSuccess": { + "message": "Auto-ispunjena stavka" + }, + "setMasterPassword": { + "message": "Postavi glavnu lozinku" + }, + "masterPasswordPolicyInEffect": { + "message": "Jedno ili više pravila organizacije zahtijeva da tvoja glavna lozinka ispunjava sljedeće uvjete:" + }, + "policyInEffectMinComplexity": { + "message": "Minimalna ocjena složenosti od $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Duljina najmanje $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Sadrži jedno ili više velikih slova" + }, + "policyInEffectLowercase": { + "message": "Sadrži jedno ili više malih slova" + }, + "policyInEffectNumbers": { + "message": "Sadrži jedan ili više brojeva" + }, + "policyInEffectSpecial": { + "message": "Sadrži jedan ili više sljedećih posebnih znakova: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Tvoja nova glavna lozinka ne ispunjava zahtjeve." + }, + "acceptPolicies": { + "message": "Označavanjem ove kućice slažete se sa sljedećim:" + }, + "acceptPoliciesError": { + "message": "Uvjeti korištenja i Pravila privatnosti nisu prihvaćeni." + }, + "termsOfService": { + "message": "Uvjeti korištenja" + }, + "privacyPolicy": { + "message": "Pravila privatnosti" + }, + "hintEqualsPassword": { + "message": "Podsjetnik za lozinku ne može biti isti kao lozinka." + }, + "ok": { + "message": "U redu" + }, + "desktopSyncVerificationTitle": { + "message": "Potvrda desktop sinkronizacije" + }, + "desktopIntegrationVerificationText": { + "message": "Provjeri da desktop aplikacija prikazuje ovaj otisak:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Integracija s preglednikom nije omogućena" + }, + "desktopIntegrationDisabledDesc": { + "message": "Integracija s preglednikom nije omogućena u Bitwarden desktop aplikaciji. Omogući integraciju u postavkama desktop aplikacije." + }, + "startDesktopTitle": { + "message": "Pokreni Bitwarden dekstop aplikaciju" + }, + "startDesktopDesc": { + "message": "Bitwarden desktop aplikacija mora biti pokrenuta prije korištenja ove funkcije." + }, + "errorEnableBiometricTitle": { + "message": "Nije moguće omogućiti biometriju" + }, + "errorEnableBiometricDesc": { + "message": "Desktop aplikacija je poništila akciju" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop aplikacija je onemogućila sigurni komunikacijski kanal. Molimo, pokušaj ponovno." + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop komunikacija prekinuta" + }, + "nativeMessagingWrongUserDesc": { + "message": "Desktop aplikacija je prijavljena, ali s drugim korisničkim računom. Provjeri da obje aplikacije koriste isti korisnički račun." + }, + "nativeMessagingWrongUserTitle": { + "message": "Pogrešan korisnički račun" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrija nije omogućena" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrija preglednika zahtijeva prethodno omogućenu biometriju u Bitwarden desktop aplikaciji." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrija nije podržana" + }, + "biometricsNotSupportedDesc": { + "message": "Biometrija preglednika nije podržana na ovom uređaju." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Dopuštenje nije dano" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bez odobrenja za komunikaciju s Bitwarden Desktop aplikacijom nije moguće korištenje biometrije u proširenju preglednika." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Greška zahtjeva dozvole" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Ovu ranju nije moguće napraviti u bočnom meniju. Pokušaj ponovno u iskočnom prozoru." + }, + "personalOwnershipSubmitError": { + "message": "Pravila tvrtke onemogućuju spremanje stavki u osobni trezor. Promijeni vlasništvo stavke na tvrtku i odaberi dostupnu Zbirku." + }, + "personalOwnershipPolicyInEffect": { + "message": "Pravila organizacije utječu na tvoje mogućnosti vlasništva. " + }, + "excludedDomains": { + "message": "Izuzete domene" + }, + "excludedDomainsDesc": { + "message": "Bitwarden neće pitati treba li spremiti prijavne podatke za ove domene. Za primjenu promjena, potrebno je osvježiti stranicu." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ nije valjana domena", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Pretraži Sendove", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Dodaj Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Tekst" + }, + "sendTypeFile": { + "message": "Datoteka" + }, + "allSends": { + "message": "Svi Sendovi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Dostignut najveći broj pristupanja", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Isteklo" + }, + "pendingDeletion": { + "message": "Čeka brisanje" + }, + "passwordProtected": { + "message": "Zaštićeno lozinkom" + }, + "copySendLink": { + "message": "Kopiraj vezu na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Ukloni lozinku" + }, + "delete": { + "message": "Izbriši" + }, + "removedPassword": { + "message": "Lozinka uklonjena" + }, + "deletedSend": { + "message": "Send izbrisan", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Veza na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Onemogućeno" + }, + "removePasswordConfirmation": { + "message": "Sigurno želiš ukloniti lozinku?" + }, + "deleteSend": { + "message": "Izbriši Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Sigurno želiš izbrisati ovaj Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Uredi Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Koja je ovo vrsta Senda?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Nadimak za ovaj Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Datoteka koju želiš poslati" + }, + "deletionDate": { + "message": "Obriši za" + }, + "deletionDateDesc": { + "message": "Send će nakon navedenog vremena biti trajno izbrisan.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Vremenski ograničeni pristup" + }, + "expirationDateDesc": { + "message": "Pristup ovom Sendu neće biti moguć nakon navednog roka.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dan" + }, + "days": { + "message": "$DAYS$ dana", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Prilagođeno" + }, + "maximumAccessCount": { + "message": "Ograničeni broj pristupanja" + }, + "maximumAccessCountDesc": { + "message": "Ako je određen, ovom Sendu će se moći pristupiti samo ograničeni broj puta.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Neobavezno zahtijevaj korisnika lozinku za pristup ovom Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privatne bilješke o Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Onemogući ovaj Send da mu nitko ne može pristupiti.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kopiraj vezu na Send nakon spremanja", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Tekst kojeg želiš poslati" + }, + "sendHideText": { + "message": "Sakrij tekst ovog Senda.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Trenutni broj pristupanja" + }, + "createSend": { + "message": "Stvori novi Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nova lozinka" + }, + "sendDisabled": { + "message": "Send onemogućen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Pravila tvrtke omogućuju brisanje samo postojećeg Senda", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send stvoren", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send uređen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Za odabir datoteke, otvori proširenje u bočnoj traci (ako je moguće) ili u iskočnom prozoru klikom na ovu poruku." + }, + "sendFirefoxFileWarning": { + "message": "Za odabir datoteke u Firefoxu, otvori proširenje u bočnoj traci ili otvori iskočni prozor klikom na ovau poruku." + }, + "sendSafariFileWarning": { + "message": "Za odabir datoteke u Safariju, otvori iskočni prozor klikom na ovu poruku." + }, + "sendFileCalloutHeader": { + "message": "Prije početka" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Biranje datuma na kalendaru", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klikni ovjde", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "za iskočni prozor", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Navedeni rok isteka nije valjan." + }, + "deletionDateIsInvalid": { + "message": "Navedeni datum brisanja nije valjan." + }, + "expirationDateAndTimeRequired": { + "message": "Potrebno je unijeti datum i vrijeme isteka." + }, + "deletionDateAndTimeRequired": { + "message": "Potrebno je unijeti datum i vrijeme brisanja." + }, + "dateParsingError": { + "message": "Došlo je do greške kod spremanja vaših datuma isteka i brisanja." + }, + "hideEmail": { + "message": "Sakrij moju adresu e-pošte od primatelja." + }, + "sendOptionsPolicyInEffect": { + "message": "Jedno ili više pravila organizacije utječe na postavke Senda." + }, + "passwordPrompt": { + "message": "Ponovno zatraži glavnu lozinku" + }, + "passwordConfirmation": { + "message": "Potvrda glavne lozinke" + }, + "passwordConfirmationDesc": { + "message": "Ova radnja je zaštićena. Za nastavak i potvrdu identiteta, unesi svoju glavnu lozinku." + }, + "emailVerificationRequired": { + "message": "Potrebna je potvrda e-pošte" + }, + "emailVerificationRequiredDesc": { + "message": "Moraš ovjeriti svoju e-poštu u mrežnom trezoru za koritšenje ove značajke." + }, + "updatedMasterPassword": { + "message": "Glavna lozinka ažurirana" + }, + "updateMasterPassword": { + "message": "Ažuriraj glavnu lozinku" + }, + "updateMasterPasswordWarning": { + "message": "Tvoju glavnu lozinku je nedavno promijenio administrator tvoje organizacije. Za pristup trezoru, potrebno je ažurirati glavnu lozinku, što će te odjaviti iz trenutne sesije, te ćeš se morati ponovno prijaviti. Aktivne sesije na drugim uređajima mogu ostati aktivne još sat vremena." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatsko učlanjenje" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Pravilo ove organizacija automatski će te učlaniti u ponovno postavljanje lozinke. Učlanjenje će omogućiti administratorima organizacije promjenu tvoje glavne lozinke." + }, + "selectFolder": { + "message": "Odaberi mapu..." + }, + "ssoCompleteRegistration": { + "message": "Za dovršetak jedinstvene prijave na razini tvrtke (SSO), postavi glavnu lozinku za pristup i zaštitu tvog trezora." + }, + "hours": { + "message": "sat(i)" + }, + "minutes": { + "message": "minuta" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Pravilo tvoje organizacije utječe na istek trezora. Najveće dozvoljeno vrijeme isteka je $HOURS$:$MINUTES$ h.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Vrijeme isteka premašuje ograničenje koju je postavila tvoja organizacija." + }, + "vaultExportDisabled": { + "message": "Izvoz trezora onemogućen" + }, + "personalVaultExportPolicyInEffect": { + "message": "Jedno ili više pravila organizacija onemogućuje izvoz osobnog trezora. " + }, + "copyCustomFieldNameInvalidElement": { + "message": "Nije moguće identificirati valjani element formulara. Pokušaj provjeriti HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nije nađen jedinstveni identifikator." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ koristi jedinstvenu prijavu SSO s vlastitim poslužiteljem. Članovima organizacije glavna lozinka više nije potrebna.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Napusti organizaciju" + }, + "removeMasterPassword": { + "message": "Ukloni glavnu lozinku" + }, + "removedMasterPassword": { + "message": "Glavna lozinka uklonjena." + }, + "leaveOrganizationConfirmation": { + "message": "Sigurno želiš napustiti ovu organizaciju?" + }, + "leftOrganization": { + "message": "Organizacija napuštena." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/hu/messages.json b/apps/browser/src/_locales/hu/messages.json new file mode 100644 index 0000000000..29c831c43a --- /dev/null +++ b/apps/browser/src/_locales/hu/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Ingyenes jelszókezelő", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Egy biztonságos és ingyenes jelszókezelő az összes eszközre.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Bejelentkezés vagy új fiók létrehozása a biztonsági széf eléréséhez." + }, + "createAccount": { + "message": "Fiók létrehozása" + }, + "login": { + "message": "Bejelentkezés" + }, + "enterpriseSingleSignOn": { + "message": "Vállalati önálló bejelentkezés" + }, + "cancel": { + "message": "Mégse" + }, + "close": { + "message": "Bezár" + }, + "submit": { + "message": "Beküld" + }, + "emailAddress": { + "message": "Email cím" + }, + "masterPass": { + "message": "Mesterjelszó" + }, + "masterPassDesc": { + "message": "A mesterjelszó az a jelszó amit a széfed eléréséhez fogsz használni. Nagyon fontos, hogy ne felejtsd el a mesterjelszavad, mivel nincs lehetőséged visszaállítani még ha elfejeted is." + }, + "masterPassHintDesc": { + "message": "A mesterjelszó emlékeztető segíthet emlékezni a jelszavadra ha elfejetetted volna." + }, + "reTypeMasterPass": { + "message": "A mesterjelszó ismételt begépelése" + }, + "masterPassHint": { + "message": "Mesterjelszó emlékeztető (nem kötelező)" + }, + "tab": { + "message": "Fül" + }, + "myVault": { + "message": "Saját széf" + }, + "tools": { + "message": "Eszközök" + }, + "settings": { + "message": "Beállítások" + }, + "currentTab": { + "message": "Jelenlegi fül" + }, + "copyPassword": { + "message": "Jelszó másolása" + }, + "copyNote": { + "message": "Jegyzet másolása" + }, + "copyUri": { + "message": "URI másolása" + }, + "copyUsername": { + "message": "Felhasználónév másolása" + }, + "copyNumber": { + "message": "Szám másolása" + }, + "copySecurityCode": { + "message": "Biztonsági kód másolása" + }, + "autoFill": { + "message": "Automatikus kitöltés" + }, + "generatePasswordCopied": { + "message": "Jelszó generálás (másolt)" + }, + "copyElementIdentifier": { + "message": "Egyedi mezőnév másolása" + }, + "noMatchingLogins": { + "message": "Nincsenek egyező bejelentkezések." + }, + "unlockVaultMenu": { + "message": "Széf kinyitása" + }, + "loginToVaultMenu": { + "message": "Bejelentkezés a saját széfbe" + }, + "autoFillInfo": { + "message": "Nincsenek elérhető bejelentkezések ehhez a fülhöz ezért az automatikus kitöltés nem működik." + }, + "addLogin": { + "message": "Bejelentkezés hozzáadása" + }, + "addItem": { + "message": "Elem hozzáadása" + }, + "passwordHint": { + "message": "Jelszó emlékeztető" + }, + "enterEmailToGetHint": { + "message": "Írd be a felhasználóhoz kötött e-mail címed, hogy megkapd a mesterjelszó emlékeztetőt." + }, + "getMasterPasswordHint": { + "message": "Kérj mesterjelszó emlékeztetőt" + }, + "continue": { + "message": "Folytatás" + }, + "sendVerificationCode": { + "message": "Ellenőrző kód elküldése a saját email címre" + }, + "sendCode": { + "message": "Kód küldése" + }, + "codeSent": { + "message": "A kód elküldésre került." + }, + "verificationCode": { + "message": "Ellenőrző kód" + }, + "confirmIdentity": { + "message": "A folytatáshoz meg kell erősíteni a személyazonosságot." + }, + "account": { + "message": "Felhasználó" + }, + "changeMasterPassword": { + "message": "Mesterjelszó módosítása" + }, + "fingerprintPhrase": { + "message": "Ujjlenyomat kifejezés", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fiók ujjlenyomat kifejezés", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Kétlépcsős bejelentkezés" + }, + "logOut": { + "message": "Kijelentkezés" + }, + "about": { + "message": "Névjegy" + }, + "version": { + "message": "Verzió" + }, + "save": { + "message": "Mentés" + }, + "move": { + "message": "Áthelyezés" + }, + "addFolder": { + "message": "Mappa hozzáadása" + }, + "name": { + "message": "Név" + }, + "editFolder": { + "message": "Mappa szerkesztése" + }, + "deleteFolder": { + "message": "Mappa törlése" + }, + "folders": { + "message": "Mappák" + }, + "noFolders": { + "message": "Nincsenek megjeleníthető mappák." + }, + "helpFeedback": { + "message": "Súgó és visszajelzés" + }, + "sync": { + "message": "Szinkronizálás" + }, + "syncVaultNow": { + "message": "Széf szinkronizálása most" + }, + "lastSync": { + "message": "Utolsó szinkronizálás:" + }, + "passGen": { + "message": "Jelszó generátor" + }, + "generator": { + "message": "Generátor", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatikusan létrehoz erős, egyedi jelszavakat a bejelentkezéseidhez." + }, + "bitWebVault": { + "message": "Bitwarden webes széf" + }, + "importItems": { + "message": "Elemek importálása" + }, + "select": { + "message": "Kiválaszt" + }, + "generatePassword": { + "message": "Jelszó generálása" + }, + "regeneratePassword": { + "message": "Jelszó újragenerálása" + }, + "options": { + "message": "Beállítások" + }, + "length": { + "message": "Hossz" + }, + "uppercase": { + "message": "Nagybetűs (A-Z)" + }, + "lowercase": { + "message": "Kisbetűs (a-z)" + }, + "numbers": { + "message": "Számok (0-9)" + }, + "specialCharacters": { + "message": "Speciális karakterek (!@#$%^&*)" + }, + "numWords": { + "message": "Szavak száma" + }, + "wordSeparator": { + "message": "Szó elválasztó" + }, + "capitalize": { + "message": "Nagy kezdőbetű", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Szám is" + }, + "minNumbers": { + "message": "Minimális szám" + }, + "minSpecial": { + "message": "Minimális speciális" + }, + "avoidAmbChar": { + "message": "Félreérthető karakterek mellőzése" + }, + "searchVault": { + "message": "Keresés a széfben" + }, + "edit": { + "message": "Szerkesztés" + }, + "view": { + "message": "Nézet" + }, + "noItemsInList": { + "message": "Nincsenek megjeleníthető tételek." + }, + "itemInformation": { + "message": "Elem információ" + }, + "username": { + "message": "Felhasználónév" + }, + "password": { + "message": "Jelszó" + }, + "passphrase": { + "message": "Kulcskifejezés" + }, + "favorite": { + "message": "Kedvenc" + }, + "notes": { + "message": "Jegyzetek" + }, + "note": { + "message": "Jegyzet" + }, + "editItem": { + "message": "Elem szerkesztése" + }, + "folder": { + "message": "Mappa" + }, + "deleteItem": { + "message": "Elem törlése" + }, + "viewItem": { + "message": "Elem megtekintése" + }, + "launch": { + "message": "Indítás" + }, + "website": { + "message": "Weboldal" + }, + "toggleVisibility": { + "message": "Láthatóság váltása" + }, + "manage": { + "message": "Kezelés" + }, + "other": { + "message": "Egyéb" + }, + "rateExtension": { + "message": "Bővítmény értékelése" + }, + "rateExtensionDesc": { + "message": "Kérlek, fontold meg egy jó értékelés hagyását, ezzel segítve nekünk!" + }, + "browserNotSupportClipboard": { + "message": "A webböngésződ nem támogat könnyű vágólap másolást. Másold manuálisan inkább." + }, + "verifyIdentity": { + "message": "Személyazonosság ellenőrzése" + }, + "yourVaultIsLocked": { + "message": "A páncélszekrény zárva van. A folytatáshoz igazolja személyazonosságát." + }, + "unlock": { + "message": "Feloldás" + }, + "loggedInAsOn": { + "message": "Bejelentkezve mint $EMAIL$ $HOSTNAME$ webhelyen.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Hibás mesterjelszó" + }, + "vaultTimeout": { + "message": "Széf időkifutás" + }, + "lockNow": { + "message": "Zárolás most" + }, + "immediately": { + "message": "Azonnal" + }, + "tenSeconds": { + "message": "10 másodperc" + }, + "twentySeconds": { + "message": "20 másodperc" + }, + "thirtySeconds": { + "message": "30 másodperc" + }, + "oneMinute": { + "message": "1 perc" + }, + "twoMinutes": { + "message": "2 perc" + }, + "fiveMinutes": { + "message": "5 perc" + }, + "fifteenMinutes": { + "message": "15 perc" + }, + "thirtyMinutes": { + "message": "30 perc" + }, + "oneHour": { + "message": "1 óra" + }, + "fourHours": { + "message": "4 óra" + }, + "onLocked": { + "message": "Rendszerzároláskor" + }, + "onRestart": { + "message": "Böngésző újraindításkor" + }, + "never": { + "message": "Soha" + }, + "security": { + "message": "Biztonság" + }, + "errorOccurred": { + "message": "Hiba történt." + }, + "emailRequired": { + "message": "E-mail cím megadása kötelező." + }, + "invalidEmail": { + "message": "Érvénytelen email cím." + }, + "masterPassRequired": { + "message": "Mesterjelszó megadása kötelező." + }, + "masterPassLength": { + "message": "Mesterjelszónak legalább 8 karakter hosszúnak kell lennie." + }, + "masterPassDoesntMatch": { + "message": "A megadott két jelszó nem egyezik meg." + }, + "newAccountCreated": { + "message": "Felhasználódat létrehoztuk. Most már be tudsz jelentkezni." + }, + "masterPassSent": { + "message": "Elküldtünk neked egy mesterjelszó emlékeztetődet tartalmazó E-mailt." + }, + "verificationCodeRequired": { + "message": "Ellenőrző kód szükséges." + }, + "invalidVerificationCode": { + "message": "Érvénytelen ellenőrző kód" + }, + "valueCopied": { + "message": "$VALUE$ másolásra került.", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Nem sikerült automatikusan kitölteni a bejelentkezést ezen a weboldalon. Helyette másold/illeszt be a felhasználóneved és/vagy a jelszavadat." + }, + "loggedOut": { + "message": "Kijelentkezett" + }, + "loginExpired": { + "message": "Bejelentkezési munkamenete lejárt." + }, + "logOutConfirmation": { + "message": "Biztos benne, hogy ki szeretnél jelentkezni?" + }, + "yes": { + "message": "Igen" + }, + "no": { + "message": "Nem" + }, + "unexpectedError": { + "message": "Váratlan hiba történt." + }, + "nameRequired": { + "message": "Név megadása kötelező." + }, + "addedFolder": { + "message": "Hozzáadott mappa" + }, + "changeMasterPass": { + "message": "Mesterjelszó módosítása" + }, + "changeMasterPasswordConfirmation": { + "message": "Mesterjelszavadat a bitwarden.com webes széfén tudod megváltoztatni. Szeretnéd meglátogatni a most a weboldalt?" + }, + "twoStepLoginConfirmation": { + "message": "A kétlépcsős bejelentkezés biztonságosabbá teszi a felhasználódat azáltal, hogy ellenőrizned kell a bejelentkezésedet egy másik készülékkel mint például biztonsági kulcs, hitelesítő alkalmazás, SMS, telefon hívás vagy e-mail. Kétlépcsős bejelentkezést a bitwarden.com webes széfén tudod megváltoztatni. Szeretnéd meglátogatni a most a weboldalt?" + }, + "editedFolder": { + "message": "A mappa módosításra került." + }, + "deleteFolderConfirmation": { + "message": "Biztos, hogy törölni akarod ezt a mappát?" + }, + "deletedFolder": { + "message": "Törölt mappa" + }, + "gettingStartedTutorial": { + "message": "Kezdeti ismertető" + }, + "gettingStartedTutorialVideo": { + "message": "Nézd meg az első lépések oktatóprogramunkat, hogy megtanuld, hogyan hozd ki a legtöbbet a böngésző kiterjesztésből." + }, + "syncingComplete": { + "message": "Szinkronizálás befejezve" + }, + "syncingFailed": { + "message": "Sikertelen szinkronizálás" + }, + "passwordCopied": { + "message": "Jelszó másolva" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Új URI" + }, + "addedItem": { + "message": "Elem hozzáadva" + }, + "editedItem": { + "message": "Elem szerkesztve" + }, + "deleteItemConfirmation": { + "message": "Biztosan törlésre kerüljön ezt az elem?" + }, + "deletedItem": { + "message": "Az elem törlésre került." + }, + "overwritePassword": { + "message": "Jelszó felülírása" + }, + "overwritePasswordConfirmation": { + "message": "Biztosan felül akarod írni a jelenlegi jelszavad?" + }, + "overwriteUsername": { + "message": "Felhasználónév felülírása" + }, + "overwriteUsernameConfirmation": { + "message": "Biztosan felülírásra kerüljön az aktuális felhasználónév?" + }, + "searchFolder": { + "message": "Mappa keresése" + }, + "searchCollection": { + "message": "Gyűjtemény keresése" + }, + "searchType": { + "message": "Típus keresése" + }, + "noneFolder": { + "message": "Nincs mappa", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Bejelentkezés értesítés hozzáadás letiltása" + }, + "addLoginNotificationDesc": { + "message": "A \"Bejelentkezés értesítés hozzáadása\" automatikusan felajánlja a bejelentkezés széfbe mentését az első bejelentkezéskor." + }, + "dontShowCardsCurrentTab": { + "message": "A kártyák ne jelenjenek meg a fül oldalon" + }, + "dontShowCardsCurrentTabDesc": { + "message": "A széf kártyaelemei az 'Aktuális fül' oldalon jelennek meg a könnyű automatikus kitöltéshez." + }, + "dontShowIdentitiesCurrentTab": { + "message": "A személyazonosságok ne jelenjenek meg a Fül oldalon" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "A széf személyazonosság elemei az 'Aktuális fül' oldalon jelennek meg a könnyű automatikus kitöltéshez." + }, + "clearClipboard": { + "message": "Vágólap ürítése", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatikusan törli a vágólapra másolt értékeket.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "A Bitwarden megjegyezze ezt a jelszót?" + }, + "notificationAddSave": { + "message": "Mentés" + }, + "disableChangedPasswordNotification": { + "message": "Megváltozott jelszó értesítés letiltása" + }, + "disableChangedPasswordNotificationDesc": { + "message": "A \"Megváltozott jelszó értesítés\" automatikusan felajánlja a bejelentkezési jelszó frissítését a széfben, ha annak megváltoztatását érzékeli a webhelyen." + }, + "notificationChangeDesc": { + "message": "Frissítésre kerüljön a jelszó a Bitwardenben?" + }, + "notificationChangeSave": { + "message": "Frissítés" + }, + "disableContextMenuItem": { + "message": "Helyi menüopciók kikapcsolása" + }, + "disableContextMenuItemDesc": { + "message": "Helyi menü opciók gyors hozzáférést biztosít jelszó generáláshoz és bejelentkezésekhez a weboldalhoz amin éppen vagy." + }, + "defaultUriMatchDetection": { + "message": "Alapértelmezett URI egyezés érzékelés", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Az URI egyezés érzékelés alapértelmezett módjának kiválasztása a bejelentkezéseknél olyan műveletek esetében mint az automatikus kitöltés." + }, + "theme": { + "message": "Téma" + }, + "themeDesc": { + "message": "Az alkalmazás színtémájának megváltoztatása." + }, + "dark": { + "message": "Sötét", + "description": "Dark color" + }, + "light": { + "message": "Világos", + "description": "Light color" + }, + "solarizedDark": { + "message": "Szolarizált sötét", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Széf exportálása" + }, + "fileFormat": { + "message": "Fájlformátum" + }, + "warning": { + "message": "FIGYELEM", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Széf exportálás megerősítése" + }, + "exportWarningDesc": { + "message": "Ez az exportálás titkosítás nélkül tartalmazza a széfadatokat. Nem célszerű az exportált fájlt nem biztonságos csatornákon tárolni és tovább küldeni (például emailben). A felhasználás után erősen ajánlott a törlés." + }, + "encExportKeyWarningDesc": { + "message": "Ez az exportálás titkosítja az adatokat a fiók titkosítási kulcsával. Ha valaha a diók forgatási kulcsa más lesz, akkor újra exportálni kell, mert nem lehet visszafejteni ezt az exportálási fájlt." + }, + "encExportAccountWarningDesc": { + "message": "A fiók titkosítási kulcsai minden Bitwarden felhasználói fiókhoz egyediek, ezért nem importálhatunk titkosított exportálást egy másik fiókba." + }, + "exportMasterPassword": { + "message": "Add meg a jelszavad a széf adataid exportálásához." + }, + "shared": { + "message": "Megosztott" + }, + "learnOrg": { + "message": "Információ szervezetekről" + }, + "learnOrgConfirmation": { + "message": "A Bitwarden lehetővé teszi a tároló elemeinek megosztását másokkal egy szervezet használatával. Szeretnénk ellátogatni a bitwarden.com webhelyre további információkét?" + }, + "moveToOrganization": { + "message": "Áthelyezés szervezethez" + }, + "share": { + "message": "Megosztás" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ átkerült $ORGNAME$ szervezethez", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Válasszunk egy szervezetet, ahová áthelyezni szeretnénk ezt az elemet. A szervezetbe áthelyezés átruházza az elem tulajdonjogát az adott szervezetre. Az áthelyezés után többé nem leszünk az elem közvetlen tulajdonosa." + }, + "learnMore": { + "message": "Tudjon meg többet" + }, + "authenticatorKeyTotp": { + "message": "Hitelesítő kulcs (egyszeri időalapú)" + }, + "verificationCodeTotp": { + "message": "Ellenőrző kód (egyszeri időalapú)" + }, + "copyVerificationCode": { + "message": "Ellenőrző kód másolása" + }, + "attachments": { + "message": "Mellékletek" + }, + "deleteAttachment": { + "message": "Mellékletek törlése" + }, + "deleteAttachmentConfirmation": { + "message": "Biztos törölni akarod ezt a mellékletet?" + }, + "deletedAttachment": { + "message": "Mellékletek törlése" + }, + "newAttachment": { + "message": "Új melléklet hozzáadása" + }, + "noAttachments": { + "message": "Nincsenek mellékletek." + }, + "attachmentSaved": { + "message": "A melléklet mentésre került." + }, + "file": { + "message": "Fájl" + }, + "selectFile": { + "message": "Válassz ki egy fájlt." + }, + "maxFileSize": { + "message": "A naximális fájlméret 500 MB." + }, + "featureUnavailable": { + "message": "Ez a funkció nem érhető el." + }, + "updateKey": { + "message": "Ez a funkció nem használható, amíg nem frissíted a titkosítási kulcsod." + }, + "premiumMembership": { + "message": "Prémium tagság" + }, + "premiumManage": { + "message": "Tagság kezelése" + }, + "premiumManageAlert": { + "message": "Prémium tagságod a bitwarden.com webes széfén tudod kezelni. Szeretnéd meglátogatni a most a weboldalt?" + }, + "premiumRefresh": { + "message": "Tagság frissítése" + }, + "premiumNotCurrentMember": { + "message": "Pillanatnyilag nem vagy prémium tag." + }, + "premiumSignUpAndGet": { + "message": "Regisztrálj prémium tagságra az alábbi funkciókért:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB titkosított tárhely a fájlmellékleteknek." + }, + "ppremiumSignUpTwoStep": { + "message": "További két lépcsős bejelentkezés lehetőségek, mint például YubiKey, FIDO U2F és Duo." + }, + "ppremiumSignUpReports": { + "message": "Jelszó higiénia, fiók biztonság és adatszivárgási jelentések a széf biztonsága érdekében." + }, + "ppremiumSignUpTotp": { + "message": "TOTP ellenőrző kód (2FA) generátor a széfedben lévő bejelentkezésekhez." + }, + "ppremiumSignUpSupport": { + "message": "Kiemelt ügyfélszolgálati." + }, + "ppremiumSignUpFuture": { + "message": "Minden jövőbeli prémium funkció. Hamarosan jön még több!" + }, + "premiumPurchase": { + "message": "Prémium funkció megvásárlása" + }, + "premiumPurchaseAlert": { + "message": "Prémium tagságot a bitwarden.com webes széfén tudsz venni. Szeretnéd meglátogatni a most a weboldalt?" + }, + "premiumCurrentMember": { + "message": "Te egy prémium tag vagy!" + }, + "premiumCurrentMemberThanks": { + "message": "Köszönjük a Bitwarden támogatását." + }, + "premiumPrice": { + "message": "Mindez csak $PRICE$ /év.", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Frissítés megtörtént" + }, + "disableAutoTotpCopy": { + "message": "Egyszeri jelszó automatikus másolás tiltása" + }, + "disableAutoTotpCopyDesc": { + "message": "Ha a bejelentkezésedhez csatolva van egy hitelesítő kód, a TOTP ellenőrző kód automatikusan másolva lesz a vágólapodra bejelentkezésed automatikus kitöltése esetén." + }, + "disableAutoBiometricsPrompt": { + "message": "Nincs biometrika kérés indításkor" + }, + "premiumRequired": { + "message": "Prémium funkció szükséges" + }, + "premiumRequiredDesc": { + "message": "Prémium tagság szükséges ennek a funkciónak eléréséhez." + }, + "enterVerificationCodeApp": { + "message": "Add meg a 6 számjegyű ellenőrző kódot a hitelesítő alkalmazásodból." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ email címre elküldött 6 számjegyű ellenőrző kód megadása.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Az ellenőrző kód elküldésre került $EMAIL$ email címre.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Emlékezz rám" + }, + "sendVerificationCodeEmailAgain": { + "message": "Megerősítő kód e-mail újra küldése" + }, + "useAnotherTwoStepMethod": { + "message": "Más két lépcsős bejelentkezés használata" + }, + "insertYubiKey": { + "message": "Illeszd be a YubiKey-t a számítógéped egyik USB portjába, majd nyomd meg a gombját." + }, + "insertU2f": { + "message": "Illesz be biztonsági kulcsod a számítógéped egyik USB portjába. Ha van rajta egy gomb, nyomd le." + }, + "webAuthnNewTab": { + "message": "A WebAuthn 2FA ellenőrzés folytatása az új fülön." + }, + "webAuthnNewTabOpen": { + "message": "Új fül megnyitása" + }, + "webAuthnAuthenticate": { + "message": "WebAutn hitelesítés" + }, + "loginUnavailable": { + "message": "A bejelentkezés nem érhető el." + }, + "noTwoStepProviders": { + "message": "Ezen a fiókon kétlépcsős bejelentkezés van engedélyezve, de ez az eszköz nem támogatja egyik beállított kétlépcsős szolgáltatót sem." + }, + "noTwoStepProviders2": { + "message": "Kérlek használj támogatott böngészőt (mint például a Chrome) és/vagy adj hozzá jobban támogatott szolgáltatásokat melyek jobban támogatottak más böngészőkben is (mint például egy hitelesítő alkalmazás)." + }, + "twoStepOptions": { + "message": "Kétlépcsős bejelentkezés opciók" + }, + "recoveryCodeDesc": { + "message": "Elvesztetted a hozzáférésed az összes kétlépcsős szolgáltatásodhoz? Használd a visszaállítókódod a kétlépcsős kiszolgálok kikapcsolásához a felhasználódon." + }, + "recoveryCodeTitle": { + "message": "Helyreállító kód" + }, + "authenticatorAppTitle": { + "message": "Hitelesítő alkalmazás" + }, + "authenticatorAppDesc": { + "message": "Használj egy másik alkalmazást (mint például az Authy vagy a Google Authenticator) idő alapú ellenőrzőkód generálásához.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP biztonsági kulcs" + }, + "yubiKeyDesc": { + "message": "Használj egy YubiKey-t, hogy hozzá férhess a felhasználódhoz. Működik a YubiKey 4, 4 Nano, 4C, és NEO eszközökkel." + }, + "duoDesc": { + "message": "Ellenőrizd Duo Security-val a Duo Mobile alkalmazás, SMS, telefon hívás vagy U2F biztonsági kulcs segítségével.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Ellenőrzés szervezeti Duo Security segítségével a Duo Mobile alkalmazás, SMS, telefonhívás vagy U2F biztonsági kulcs használatával.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Használjunk bármilyen WebAuthn engedélyezett biztonsági kulcsot a saját fiók eléréséhez." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Ellenőrző kódok el lesznek e-mailbe küldve neked." + }, + "selfHostedEnvironment": { + "message": "Saját üzemeltetésű környezet" + }, + "selfHostedEnvironmentFooter": { + "message": "A helyileg működtetett Bitwarden telepítés alap webcímének megadása." + }, + "customEnvironment": { + "message": "Egyedi környezet" + }, + "customEnvironmentFooter": { + "message": "Haladó felhasználóknak. Minden egyes szolgáltatás alap URL-jét külön megadhatod." + }, + "baseUrl": { + "message": "Szerver URL" + }, + "apiUrl": { + "message": "API szerver webcím" + }, + "webVaultUrl": { + "message": "Webes széf szerver webcím" + }, + "identityUrl": { + "message": "Személyazonosság szerver webcím" + }, + "notificationsUrl": { + "message": "Értesítési szerver webcím" + }, + "iconsUrl": { + "message": "Ikonok szerver webcím" + }, + "environmentSaved": { + "message": "A környezet URL-ek mentésre kerültek." + }, + "enableAutoFillOnPageLoad": { + "message": "Automatikus kitöltés engedélyezése oldal betöltéskor" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Ha egy bejelentkezési űrlap észlelésre került, automatikusan töltse ki az adatokat az oldal betöltésekor." + }, + "experimentalFeature": { + "message": "Ez jelenleg egy kísérleti funkció. Csak saját felelősségedre használd." + }, + "defaultAutoFillOnPageLoad": { + "message": "Alapértelmezett beállítások bejelentkezési elemekhez" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Az Automatikus kitöltés engedélyezése az oldalbetöltéskor engedélyezheti vagy letilthatja a funkciót az egyes bejelentkezési elemeknél. Ez az alapértelmezett beállítás a bejelentkezési elemeknéll, amelyek nincsenek külön konfigurálva." + }, + "itemAutoFillOnPageLoad": { + "message": "Automatikus kitöltés oldal betöltésnél (Ha engedélyezett az opcióknál)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Alapbeállítások használata" + }, + "autoFillOnPageLoadYes": { + "message": "Automatikus kitöltés oldalbetöltésnél" + }, + "autoFillOnPageLoadNo": { + "message": "Nincs automatikus kitöltés oldalbetöltéskor" + }, + "commandOpenPopup": { + "message": "Széf megnyitása ablakban" + }, + "commandOpenSidebar": { + "message": "Széf megnyitása oldalsávon" + }, + "commandAutofillDesc": { + "message": "Az aktuális webhelynél az utoljára használt bejelentkezés automatikus kitöltése." + }, + "commandGeneratePasswordDesc": { + "message": "Új véletlenszerű jelszó generálása ás másolása a vágólapra." + }, + "commandLockVaultDesc": { + "message": "A széf zárolása" + }, + "privateModeWarning": { + "message": "A privát mód támogatása kísérleti és néhány funkció korlátozott." + }, + "customFields": { + "message": "Egyedi mezők" + }, + "copyValue": { + "message": "Érték másolása" + }, + "value": { + "message": "Érték" + }, + "newCustomField": { + "message": "Új egyedi mező" + }, + "dragToSort": { + "message": "Húzás a rendezéshez" + }, + "cfTypeText": { + "message": "Szöveg" + }, + "cfTypeHidden": { + "message": "Rejtett" + }, + "cfTypeBoolean": { + "message": "Boolean (Logikai)" + }, + "cfTypeLinked": { + "message": "Csatolva", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Csatolt érték", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Az ellenőrző kódot tartalmazó email egy olyan felugró ablakban nyílik meg, mely a mellette levő területre kattinva bezáródik. Szeretnéd az emailt egy olyan ablakban megnyitni, ami nem záródhat így be?" + }, + "popupU2fCloseMessage": { + "message": "Ez a böngésző nem dolgozza fel az U2F kéréseket ebben a felbukkanó ablakban. Szeretnénk megnyitni a felbukkanó ablakot új böngészőablakban az U2F segítségével történő bejelentkezéshez?" + }, + "disableFavicon": { + "message": "Webhely ikonok letiltása" + }, + "disableFaviconDesc": { + "message": "A webhelyek ikonjai felismerhető ikonként jelennek meg a széf összes eleme mellett." + }, + "disableBadgeCounter": { + "message": "Számláló jelvény letiltása" + }, + "disableBadgeCounterDesc": { + "message": "A jelvényszámláló jelzi az aktuális oldalhoz a bejelentkezések számát a stárolóban." + }, + "cardholderName": { + "message": "Kártyatulajdonos neve" + }, + "number": { + "message": "Szám" + }, + "brand": { + "message": "Márka" + }, + "expirationMonth": { + "message": "Lejárati hónap" + }, + "expirationYear": { + "message": "Lejárati év" + }, + "expiration": { + "message": "Lejárat" + }, + "january": { + "message": "Január" + }, + "february": { + "message": "Február" + }, + "march": { + "message": "Március" + }, + "april": { + "message": "Április" + }, + "may": { + "message": "Május" + }, + "june": { + "message": "Június" + }, + "july": { + "message": "Július" + }, + "august": { + "message": "Augusztus" + }, + "september": { + "message": "Szeptember" + }, + "october": { + "message": "Október" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Biztonsági kód" + }, + "ex": { + "message": "példa:" + }, + "title": { + "message": "Titulus" + }, + "mr": { + "message": "Úr" + }, + "mrs": { + "message": "Asszony" + }, + "ms": { + "message": "Kisasszony" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Személynév" + }, + "middleName": { + "message": "Középső név" + }, + "lastName": { + "message": "Családnév" + }, + "fullName": { + "message": "Teljes név" + }, + "identityName": { + "message": "Személyazonosság megnevezés" + }, + "company": { + "message": "Cég" + }, + "ssn": { + "message": "Társadalombiztosítási szám" + }, + "passportNumber": { + "message": "Útlevélszám" + }, + "licenseNumber": { + "message": "Vezetői engedély száma" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefonszám" + }, + "address": { + "message": "Lakcím" + }, + "address1": { + "message": "Cím 1" + }, + "address2": { + "message": "Cím 2" + }, + "address3": { + "message": "Cím 3" + }, + "cityTown": { + "message": "Település" + }, + "stateProvince": { + "message": "Állam/Megye" + }, + "zipPostalCode": { + "message": "Irányítószám" + }, + "country": { + "message": "Ország" + }, + "type": { + "message": "Típus" + }, + "typeLogin": { + "message": "Bejelentkezés" + }, + "typeLogins": { + "message": "Bejelentkezések" + }, + "typeSecureNote": { + "message": "Biztonságos jegyzet" + }, + "typeCard": { + "message": "Kártya" + }, + "typeIdentity": { + "message": "Személyazonosság" + }, + "passwordHistory": { + "message": "Jelszó előzmények" + }, + "back": { + "message": "Vissza" + }, + "collections": { + "message": "Gyűjtemények" + }, + "favorites": { + "message": "Kedvencek" + }, + "popOutNewWindow": { + "message": "Megnyitás új böngészőablakban" + }, + "refresh": { + "message": "Frissítés" + }, + "cards": { + "message": "Kártyák" + }, + "identities": { + "message": "Személyazonosságok" + }, + "logins": { + "message": "Bejelentkezések" + }, + "secureNotes": { + "message": "Biztonságos jegyzetek" + }, + "clear": { + "message": "Kiürítés", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "A jelszóvédelemi állapot ellenőrzése." + }, + "passwordExposed": { + "message": "Ez a jelszó már $VALUE$ alkalommal volt kitéve az adatszivárgásnak. Célszerű megváltoztatni.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Ez a jelszó nem található egyetlen ismert adatszivárgásban sem. Biztonságos a használata." + }, + "baseDomain": { + "message": "Alap domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Tartománynév", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Kiszolgáló", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Pontos" + }, + "startsWith": { + "message": "Ezzel kezdődik:" + }, + "regEx": { + "message": "Reguláris kifejezés", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Találat érzékelés", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Alapértelmezett találat érzékelés", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Opciók megnyitása" + }, + "toggleCurrentUris": { + "message": "Aktuális URI elemek váltása", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Aktuális URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Szervezet", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Típusok" + }, + "allItems": { + "message": "Összes elem" + }, + "noPasswordsInList": { + "message": "Nincsenek listázható jelszavak." + }, + "remove": { + "message": "Eltávolítás" + }, + "default": { + "message": "Alapértelmezett" + }, + "dateUpdated": { + "message": "A frissítés megtörtént.", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "A jelszó frissítésre került.", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Biztosan szeretnénk használni a \"Soha\" opciót? A zárolási opciók \"Soha\" értékre állítása a széf titkosítási kulcsát az eszközön tárolja. Ennek az opciónak a használatakor célszerű az eszköz megfelelő védettségét biztosítani." + }, + "noOrganizationsList": { + "message": "Még nem tartozunk egyik szervezethez sem. A szervezetek lehetővé teszik az elemek megosztását más felhasználókkal." + }, + "noCollectionsInList": { + "message": "Nincsenek megjeleníthető gyűjtemények." + }, + "ownership": { + "message": "Tulajdonjog" + }, + "whoOwnsThisItem": { + "message": "Ki tulajdonolja ezt az elemet?" + }, + "strong": { + "message": "Erős", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Jó", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Gyenge", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Gyenge mesterjelszó" + }, + "weakMasterPasswordDesc": { + "message": "A választott mesterjelszó gyenge. Erős jelszót (vagy kifejezést) kell használni a Bitwarden fiók megfelelő védelme érdekében. Biztosan ezt a mesterjelszót szeretnénk használni?" + }, + "pin": { + "message": "Pinkód", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Felnyitás pinkóddal" + }, + "setYourPinCode": { + "message": "A pinkód beállítása a Bitwarden feloldásához. A pinkód beállítás alaphelyzetbe kerül, ha teljesen kijelentkezünk az alkalmazásból." + }, + "pinRequired": { + "message": "A pinkód szükséges." + }, + "invalidPin": { + "message": "A pinkód érvénytelen." + }, + "unlockWithBiometrics": { + "message": "Biometrikus feloldás" + }, + "awaitDesktop": { + "message": "Várakozás megerősítésre az asztali alkalmazásból" + }, + "awaitDesktopDesc": { + "message": "Erősítsük meg a biometrikus adatok használatát a Bitwarden asztali alkalmazásban a biometrikus adatok engedélyezéséhez a böngészőben." + }, + "lockWithMasterPassOnRestart": { + "message": "Lezárás mesterjelszóval a böngésző újraindításakor" + }, + "selectOneCollection": { + "message": "Legalább egy gyűjteményt ki kell választani." + }, + "cloneItem": { + "message": "Tétel klónozása" + }, + "clone": { + "message": "Klónozás" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Egy vagy több szervezeti szabály érinti a generátor beállításokat." + }, + "vaultTimeoutAction": { + "message": "Széf időkifutás művelet" + }, + "lock": { + "message": "Lezárás", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Lomtár", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Keresés a lomtárban" + }, + "permanentlyDeleteItem": { + "message": "Az elem végleges törlése" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Biztosan véglegesen törlésre kerüljön ez az elem?" + }, + "permanentlyDeletedItem": { + "message": "Véglegesen törölt elem" + }, + "restoreItem": { + "message": "Elem visszaállítása" + }, + "restoreItemConfirmation": { + "message": "Biztosan visszaállításra kerüljön ezt az elem?" + }, + "restoredItem": { + "message": "Visszaállított elem" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Kijelentkezve az összes széf elérés eltávolításra kerül és webes hitelesítésre van szükség az időkifutás után. Biztosan szeretnénk használni ezt a beállítást?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Időkifutás művelet megerősítés" + }, + "autoFillAndSave": { + "message": "Automatikus kitöltés és mentés" + }, + "autoFillSuccessAndSavedUri": { + "message": "Automatikusan kitöltött elem és mentett URI" + }, + "autoFillSuccess": { + "message": "Automatikusan kitöltött elem" + }, + "setMasterPassword": { + "message": "Mesterjelszó beállítása" + }, + "masterPasswordPolicyInEffect": { + "message": "Egy vagy több szervezeti rendszabályhoz mesterjelszó szükséges a következő követelmények megfeleléséhez:" + }, + "policyInEffectMinComplexity": { + "message": "Minimális összetettségi pontszám $SCORE$ értékhez", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimális hossz $LENGTH$ értékből", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Egy vagy több nagybetűs karaktert tartalmaz" + }, + "policyInEffectLowercase": { + "message": "Egy vagy több kisbetűs karaktert tartalmaz" + }, + "policyInEffectNumbers": { + "message": "Egy vagy több számot tartalmaz" + }, + "policyInEffectSpecial": { + "message": "$CHARS$ speciális karakterekből egyet vagy többet tartalmaz", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Az új mesterjelszó nem felel meg a szabály követelményeknek." + }, + "acceptPolicies": { + "message": "A doboz bejelölésével elfogadjuk a következőket:" + }, + "acceptPoliciesError": { + "message": "A szolgáltatási feltételeket és az adatvédelmi irányelveket nem vették figyelembe." + }, + "termsOfService": { + "message": "Szolgáltatási feltételek" + }, + "privacyPolicy": { + "message": "Adatvédelem" + }, + "hintEqualsPassword": { + "message": "A jelszavas tipp nem lehet azonos a jelszóval." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Asztali szinkronizálás ellenőrzés" + }, + "desktopIntegrationVerificationText": { + "message": "Ellenőrizzük, hogy az asztali alkalmazás megjeleníti-e ezt az ujjlenyomatot: " + }, + "desktopIntegrationDisabledTitle": { + "message": "A böngésző integráció nem engedélyezett." + }, + "desktopIntegrationDisabledDesc": { + "message": "A böngésző integráció nincs engedélyezve a Bitwarden asztali alkalmazásban. Engedélyezzük az asztali alkalmazás beállításai között." + }, + "startDesktopTitle": { + "message": "A Bitwarden asztali alkalmazás indítása" + }, + "startDesktopDesc": { + "message": "A funkció használatához el kell indítani a Bitwarden asztali alkalmazást." + }, + "errorEnableBiometricTitle": { + "message": "Nem lehet engedélyezni a biometrikus adatokat." + }, + "errorEnableBiometricDesc": { + "message": "A műveletet az asztali alkalmazás törölte." + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Az asztali alkalmazás érvénytelenítette a biztonságos kommunikációs csatornát. Próbálkozzunk újra ezzel a művelettel" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Az asztali kommunikáció megszakadt." + }, + "nativeMessagingWrongUserDesc": { + "message": "Az asztali alkalmazás egy másik fiókba van bejelentkezve. Ellenőrizzük, hogy mindkét alkalmazást azonos fiókba van bejelentkezve." + }, + "nativeMessagingWrongUserTitle": { + "message": "A fiók nem egyezik." + }, + "biometricsNotEnabledTitle": { + "message": "A biometrikus adatok nincsenek engedélyezve." + }, + "biometricsNotEnabledDesc": { + "message": "A böngésző biometrikus adataihoz először az asztali biometrikus adatokat kell engedélyezni a beállításokban." + }, + "biometricsNotSupportedTitle": { + "message": "A biometrikus adatok nem támogatottak." + }, + "biometricsNotSupportedDesc": { + "message": "A böngésző biometrikus adatait ez az eszköz nem támogatja." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "A jogosultság nincs megadva." + }, + "nativeMessaginPermissionErrorDesc": { + "message": "A Bitwarden Desktop alkalmazással való kommunikáció engedélye nélkül nem adhatunk meg biometrikus adatokat a böngésző kiterjesztésében. Próbáljuk újra." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Engedélykérési hiba történt." + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Ez a művelet nem hajtható végre az oldalsávon. Próbáljuk meg újra a műveletet a felbukkanó ablakban." + }, + "personalOwnershipSubmitError": { + "message": "Egy vállalati házirend miatt korlátozásra került az elemek személyes tárolóba történő mentése. Módosítsuk a Tulajdon opciót egy szervezetre és válasszunk az elérhető gyűjtemények közül." + }, + "personalOwnershipPolicyInEffect": { + "message": "A szervezeti házirend befolyásolja a tulajdonosi opciókat." + }, + "excludedDomains": { + "message": "Kizárt domainek" + }, + "excludedDomainsDesc": { + "message": "A Bitwarden nem fogja kérni a domainek bejelentkezési adatainak mentését. A változások életbe lépéséhez frissíteni kell az oldalt." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ nem érvényes domain.", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Send keresése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Send hozzáadása", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Szöveg" + }, + "sendTypeFile": { + "message": "Fájl" + }, + "allSends": { + "message": "Összes Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "A maximális hozzáférések száma elérésre került.", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Lejárt" + }, + "pendingDeletion": { + "message": "Függőben lévő törlés" + }, + "passwordProtected": { + "message": "Jelszóval védett" + }, + "copySendLink": { + "message": "Send hivatkozás másolása", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Jelszó eltávolítása" + }, + "delete": { + "message": "Törlés" + }, + "removedPassword": { + "message": "A jelszó eltávolításra került." + }, + "deletedSend": { + "message": "A Send törlésre került.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send hivatkozás", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Letiltva" + }, + "removePasswordConfirmation": { + "message": "Biztosan eltávolításra kerüljön ez a jelszó?" + }, + "deleteSend": { + "message": "Send törlése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Biztosan törlésre kerüljön ez a Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send szerkesztése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Milyen típusú ez a Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Barátságos név a Send leírására.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "A küldendő fájl." + }, + "deletionDate": { + "message": "Törlési dátum" + }, + "deletionDateDesc": { + "message": "A Send véglegesen törölve lesz a meghatározott időpontban.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Lejárati dátum" + }, + "expirationDateDesc": { + "message": "Amennyiben be van állítva, a hozzáférés ehhez a Sendhez a meghatározott időpontban lejár", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 nap" + }, + "days": { + "message": "$DAYS$ nap", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Egyedi" + }, + "maximumAccessCount": { + "message": "Maximális elérési szám" + }, + "maximumAccessCountDesc": { + "message": "Beállítva a Küldés elérhetetlen lesz a meghatározott hozzáférések számának elérése után.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcionálisan megadhatunk egy jelszót a felhasználók számára a Küldés eléréséhez. ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Személyes megjegyzések erről a Küldésről.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "A Send letiltásával senki nem férhet hozzá.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Mentéskor másoljuk a Küldés hivatkozását a vágólapra.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "A küldendő fájl." + }, + "sendHideText": { + "message": "Alapértelmezés szerint elrejti a Küldés szövegét.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Aktuális elérési szám" + }, + "createSend": { + "message": "Új küldés létrehozása", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Új jelszó" + }, + "sendDisabled": { + "message": "A Send kikapcsolásra került", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "A vállalati házirend miatt csak egy meglévő Send törölhető.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "A Send létrejött.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "A Send szerkesztésre került", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "A fájl kiválasztásához nyissuk meg a kiterjesztést az oldalsávon (ha lehetséges) vagy kattintsunk erre a sávra új ablak felbukkanásához." + }, + "sendFirefoxFileWarning": { + "message": "Firefox esetén nyissuk meg a bővítményt az oldalsávon vafy erre a hirdetőtáblára kattintva új felbukkanó ablak nyílik meg." + }, + "sendSafariFileWarning": { + "message": "A fájl kiválasztásához Safariban kattintsunk erre a hirdetőtáblára kattintva új ablak nyílik meg." + }, + "sendFileCalloutHeader": { + "message": "Mielőtt belevágnánk" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Naptár-stílusú dátumválasztáshoz", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "kattintás ide", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "az ablak megnyitásához", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "A megadott lejárati idő nem érvényes." + }, + "deletionDateIsInvalid": { + "message": "A megadott törlési dátum nem érvényes." + }, + "expirationDateAndTimeRequired": { + "message": "Lejárati dátum és idő megadása szükséges." + }, + "deletionDateAndTimeRequired": { + "message": "Törlési dátum és idő megadása szükséges." + }, + "dateParsingError": { + "message": "Hiba történt a törlési és a lejárati dátum mentésekor." + }, + "hideEmail": { + "message": "Saját email cím elrejtése a címzettek elől." + }, + "sendOptionsPolicyInEffect": { + "message": "Egy vagy több szervezeti szabály érinti a Send opciókat." + }, + "passwordPrompt": { + "message": "Mesterjelszó ismételt megadás" + }, + "passwordConfirmation": { + "message": "Mesterjelszó megerősítése" + }, + "passwordConfirmationDesc": { + "message": "Ez a művelet védett. A folytatásért ismételten meg kell adni a mesterjelszőt az személyazonosság ellenőrzéséhez." + }, + "emailVerificationRequired": { + "message": "Email hitelesítés szükséges" + }, + "emailVerificationRequiredDesc": { + "message": "A funkció használatához igazolni kell email címet. Az email cím a webtárban ellenőrizhető." + }, + "updatedMasterPassword": { + "message": "A mesterjelszó frissítésre került." + }, + "updateMasterPassword": { + "message": "Mesterjelszó frissítése" + }, + "updateMasterPasswordWarning": { + "message": "A szervezet egyik adminisztrátora nemrég megváltoztatta a mesterjelszót. A széf eléréséhez most frissíteni kell a mesterjelszót. Továbblépéskor kijelentkezés történik a jelenlegi munkamenetből és újra be kell jelentkezni. Ha van aktív munkamenet más eszközön, az még legfeljebb egy óráig aktív maradhat." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatikus regisztráció" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ennek a szervezetnek van egy vállalati házirendje, amely automatikusan regisztrál a jelszó alaphelyzetbe állítására. A regisztráció lehetővé teszi a szervezet adminisztrátorainak a mesterjelszó megváltoztatását." + }, + "selectFolder": { + "message": "Mappa választása..." + }, + "ssoCompleteRegistration": { + "message": "Az SSO-val történő bejelentkezés befejezéséhez mesterjelszót kell beállítani a széf eléréséhez és védelméhez." + }, + "hours": { + "message": "Óra" + }, + "minutes": { + "message": "Perc" + }, + "vaultTimeoutPolicyInEffect": { + "message": "A szervezeti házirendek hatással vannak a széf időkorlátjára. A széf időkorlátja legfeljebb $HOURS$ óra és $MINUTES$ perc lehet.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "A széf időkorlátja túllépi a szervezet által beállított korlátozást." + }, + "vaultExportDisabled": { + "message": "A széf exportálás nem engedélyezett." + }, + "personalVaultExportPolicyInEffect": { + "message": "Egy vagy több szervezeti házirend tiltja a személyes széf exportálását." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Nem lehet azonosítani egy érvényes űrlapelemet. Ehelyett próbáljuk meg ellenőrizni a HTML -t." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nincs egyedi azonosító." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ jelenleg saját tárolású aláíráskulcsú SSO szervert használ. A mesterjelszó a továbbiakban nem szükséges a szervezeti tagsági bejelentkezéshez.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Szervezet elhagyása" + }, + "removeMasterPassword": { + "message": "Mesterjelszó eltávolítása" + }, + "removedMasterPassword": { + "message": "A mesterjelszó eltávolításra került." + }, + "leaveOrganizationConfirmation": { + "message": "Biztosan kilépünk ebből a szervezetből?" + }, + "leftOrganization": { + "message": "Megtörtént a kilépés a szervezetből." + }, + "toggleCharacterCount": { + "message": "Karakterszámláló váltás" + }, + "sessionTimeout": { + "message": "A munkamenet lejárt. Lépjünk vissza és próbáljunk újra bejelentlezni." + }, + "exportingPersonalVaultTitle": { + "message": "Személyes széf exportálása" + }, + "exportingPersonalVaultDescription": { + "message": "Csak $EMAIL$ email címmel társított személyes széf elemek kerülnek exportálásra. Ebbe nem kerülnek be a szervezeti széf elemek.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Hiba" + }, + "regenerateUsername": { + "message": "Felhasználónév ismételt geneálása" + }, + "generateUsername": { + "message": "Felhasználónév generálása" + }, + "usernameType": { + "message": "Felhasználónév típusa" + }, + "plusAddressedEmail": { + "message": "További címzési email cím", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Használjuk az email cím szolgáltató alcímzési képességeit." + }, + "catchallEmail": { + "message": "Összes email cím begyűjtése" + }, + "catchallEmailDesc": { + "message": "Használjuk a tartomány konfigurált összes befogási bejövő postaládát." + }, + "random": { + "message": "Véletlen" + }, + "randomWord": { + "message": "Véletlenszerű szó" + }, + "websiteName": { + "message": "Webhelynév" + }, + "whatWouldYouLikeToGenerate": { + "message": "Mit szeretnénk generálni?" + }, + "passwordType": { + "message": "Jelszótípus" + }, + "service": { + "message": "Szolgáltatás" + } +} diff --git a/apps/browser/src/_locales/id/messages.json b/apps/browser/src/_locales/id/messages.json new file mode 100644 index 0000000000..970c18a23a --- /dev/null +++ b/apps/browser/src/_locales/id/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Pengelola Sandi Gratis", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden adalah sebuah pengelola sandi yang aman dan gratis untuk semua perangkat Anda.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Masuk atau buat akun baru untuk mengakses brankas Anda." + }, + "createAccount": { + "message": "Buat Akun" + }, + "login": { + "message": "Masuk" + }, + "enterpriseSingleSignOn": { + "message": "Sistem Masuk Tunggal Perusahaan" + }, + "cancel": { + "message": "Batal" + }, + "close": { + "message": "Tutup" + }, + "submit": { + "message": "Kirim" + }, + "emailAddress": { + "message": "Alamat Email" + }, + "masterPass": { + "message": "Sandi Utama" + }, + "masterPassDesc": { + "message": "Kata sandi utama adalah kata sandi yang Anda gunakan untuk mengakses brankas Anda. Sangat penting bahwa Anda tidak lupa kata sandi utama Anda. Tidak ada cara untuk memulihkan kata sandi jika Anda melupakannya." + }, + "masterPassHintDesc": { + "message": "Petunjuk kata sandi utama dapat membantu Anda mengingat kata sandi Anda jika Anda melupakannya." + }, + "reTypeMasterPass": { + "message": "Ketik ulang Kata Sandi Utama" + }, + "masterPassHint": { + "message": "Petunjuk Kata Sandi Utama (pilihan)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "Brankas Saya" + }, + "tools": { + "message": "Alat" + }, + "settings": { + "message": "Setelan" + }, + "currentTab": { + "message": "Tab Saat Ini" + }, + "copyPassword": { + "message": "Salin Kata Sandi" + }, + "copyNote": { + "message": "Salin Catatan" + }, + "copyUri": { + "message": "Salin URI" + }, + "copyUsername": { + "message": "Salin Nama Pengguna" + }, + "copyNumber": { + "message": "Salin Angka" + }, + "copySecurityCode": { + "message": "Salin Kode Keamanan" + }, + "autoFill": { + "message": "Isi otomatis" + }, + "generatePasswordCopied": { + "message": "Membuat Kata Sandi (tersalin)" + }, + "copyElementIdentifier": { + "message": "Salin Nama Kolom Pilihan" + }, + "noMatchingLogins": { + "message": "Tidak ada info masuk yang cocok." + }, + "unlockVaultMenu": { + "message": "Buka brankas Anda" + }, + "loginToVaultMenu": { + "message": "Masuk ke brankas Anda" + }, + "autoFillInfo": { + "message": "Tidak ada info masuk yang tersedia untuk mengisi secara otomatis tab peramban saat ini." + }, + "addLogin": { + "message": "Tambah Info Masuk" + }, + "addItem": { + "message": "Tambah Item" + }, + "passwordHint": { + "message": "Petunjuk Kata Sandi" + }, + "enterEmailToGetHint": { + "message": "Masukkan email akun Anda untuk menerima pentunjuk sandi utama Anda." + }, + "getMasterPasswordHint": { + "message": "Dapatkan petunjuk sandi utama" + }, + "continue": { + "message": "Lanjutkan" + }, + "sendVerificationCode": { + "message": "Kirim kode verifikasi ke email Anda" + }, + "sendCode": { + "message": "Kirim Kode" + }, + "codeSent": { + "message": "Kode Terkirim!" + }, + "verificationCode": { + "message": "Kode Verifikasi" + }, + "confirmIdentity": { + "message": "Konfirmasi identitas Anda untuk melanjutkan." + }, + "account": { + "message": "Akun" + }, + "changeMasterPassword": { + "message": "Ubah Kata Sandi Utama" + }, + "fingerprintPhrase": { + "message": "Frasa Sidik Jari", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frasa sidik jari akun Anda", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Info masuk dua langkah" + }, + "logOut": { + "message": "Keluar" + }, + "about": { + "message": "Tentang" + }, + "version": { + "message": "Versi" + }, + "save": { + "message": "Simpan" + }, + "move": { + "message": "Pindah" + }, + "addFolder": { + "message": "Tambah Folder" + }, + "name": { + "message": "Nama" + }, + "editFolder": { + "message": "Sunting Folder" + }, + "deleteFolder": { + "message": "Hapus Folder" + }, + "folders": { + "message": "Folder" + }, + "noFolders": { + "message": "Tidak ada folder yang dapat dicantumkan." + }, + "helpFeedback": { + "message": "Bantuan & Umpan Balik" + }, + "sync": { + "message": "Sinkronisasi" + }, + "syncVaultNow": { + "message": "Sinkronkan Brankas Sekarang" + }, + "lastSync": { + "message": "Sinkronisasi Terakhir:" + }, + "passGen": { + "message": "Pembuat Kata Sandi" + }, + "generator": { + "message": "Pembuat Sandi", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Secara otomatis membuat sandi yang kuat dan unik untuk info masuk Anda." + }, + "bitWebVault": { + "message": "Brankas Web Bitwarden" + }, + "importItems": { + "message": "Impor Item" + }, + "select": { + "message": "Pilih" + }, + "generatePassword": { + "message": "Buat Kata Sandi" + }, + "regeneratePassword": { + "message": "Buat Ulang Kata Sandi" + }, + "options": { + "message": "Pilihan" + }, + "length": { + "message": "Panjang" + }, + "uppercase": { + "message": "Huruf besar (A-Z)" + }, + "lowercase": { + "message": "Huruf kecil (a-z)" + }, + "numbers": { + "message": "Angka (0-9)" + }, + "specialCharacters": { + "message": "karakter khusus (contoh.! @#$%^&*)" + }, + "numWords": { + "message": "Jumlah Kata" + }, + "wordSeparator": { + "message": "Pemisah Kata" + }, + "capitalize": { + "message": "Huruf Besar", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Sertakan Angka" + }, + "minNumbers": { + "message": "Angka Minimum" + }, + "minSpecial": { + "message": "Spesial Minimum" + }, + "avoidAmbChar": { + "message": "Hindari Karakter Ambigu" + }, + "searchVault": { + "message": "Cari brankas" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "Tampilan" + }, + "noItemsInList": { + "message": "Tidak ada item yang dapat dicantumkan." + }, + "itemInformation": { + "message": "Informasi Item" + }, + "username": { + "message": "Nama Pengguna" + }, + "password": { + "message": "Kata Sandi" + }, + "passphrase": { + "message": "Frasa Sandi" + }, + "favorite": { + "message": "Favorit" + }, + "notes": { + "message": "Catatan" + }, + "note": { + "message": "Catatan" + }, + "editItem": { + "message": "Sunting Item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Hapus Item" + }, + "viewItem": { + "message": "Lihat Item" + }, + "launch": { + "message": "Luncurkan" + }, + "website": { + "message": "Situs Web" + }, + "toggleVisibility": { + "message": "Ubah Visibilitas" + }, + "manage": { + "message": "Kelola" + }, + "other": { + "message": "Lainnya" + }, + "rateExtension": { + "message": "Nilai Ekstensi" + }, + "rateExtensionDesc": { + "message": "Mohon pertimbangkan membantu kami dengan ulasan yang baik!" + }, + "browserNotSupportClipboard": { + "message": "Peramban Anda tidak mendukung menyalin clipboard dengan mudah. Salin secara manual." + }, + "verifyIdentity": { + "message": "Verifikasi Identitas Anda" + }, + "yourVaultIsLocked": { + "message": "Brankas Anda terkunci. Verifikasi kata sandi utama Anda untuk melanjutkan." + }, + "unlock": { + "message": "Buka Kunci" + }, + "loggedInAsOn": { + "message": "Telah masuk sebagai $EMAIL$ di $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Sandi utama tidak valid" + }, + "vaultTimeout": { + "message": "Batas Waktu Brankas" + }, + "lockNow": { + "message": "Kunci Sekarang" + }, + "immediately": { + "message": "Segera" + }, + "tenSeconds": { + "message": "10 detik" + }, + "twentySeconds": { + "message": "20 detik" + }, + "thirtySeconds": { + "message": "30 detik" + }, + "oneMinute": { + "message": "1 menit" + }, + "twoMinutes": { + "message": "2 menit" + }, + "fiveMinutes": { + "message": "5 menit" + }, + "fifteenMinutes": { + "message": "15 menit" + }, + "thirtyMinutes": { + "message": "30 menit" + }, + "oneHour": { + "message": "1 jam" + }, + "fourHours": { + "message": "4 jam" + }, + "onLocked": { + "message": "Saat Komputer Terkunci" + }, + "onRestart": { + "message": "Saat Peramban Dimulai Ulang" + }, + "never": { + "message": "Jangan pernah" + }, + "security": { + "message": "Keamanan" + }, + "errorOccurred": { + "message": "Terjadi kesalahan" + }, + "emailRequired": { + "message": "Alamat email diperlukan." + }, + "invalidEmail": { + "message": "Alamat email tidak valid." + }, + "masterPassRequired": { + "message": "Sandi utama diperlukan." + }, + "masterPassLength": { + "message": "Kata sandi utama sedikitnya harus 8 karakter." + }, + "masterPassDoesntMatch": { + "message": "Konfirmasi sandi utama tidak cocok." + }, + "newAccountCreated": { + "message": "Akun baru Anda telah dibuat! Sekarang Anda bisa masuk." + }, + "masterPassSent": { + "message": "Kami telah mengirimi Anda email dengan petunjuk sandi utama Anda." + }, + "verificationCodeRequired": { + "message": "Kode verifikasi diperlukan." + }, + "invalidVerificationCode": { + "message": "Kode verifikasi tidak valid" + }, + "valueCopied": { + "message": "$VALUE$ disalin", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Tidak dapat mengisi otomatis item yang dipilih pada laman ini. Salin dan tempel informasinya sebagai gantinya." + }, + "loggedOut": { + "message": "Keluar" + }, + "loginExpired": { + "message": "Sesi masuk Anda telah berakhir." + }, + "logOutConfirmation": { + "message": "Anda yakin ingin keluar?" + }, + "yes": { + "message": "Ya" + }, + "no": { + "message": "Tidak" + }, + "unexpectedError": { + "message": "Terjadi kesalahan yang tak diduga." + }, + "nameRequired": { + "message": "Nama diperlukan." + }, + "addedFolder": { + "message": "Tambah Folder" + }, + "changeMasterPass": { + "message": "Ubah Kata Sandi Utama" + }, + "changeMasterPasswordConfirmation": { + "message": "Anda dapat mengubah kata sandi utama Anda di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" + }, + "twoStepLoginConfirmation": { + "message": "Info masuk dua langkah membuat akun Anda lebih aman dengan mengharuskan Anda memverifikasi info masuk Anda dengan peranti lain seperti kode keamanan, aplikasi autentikasi, SMK, panggilan telepon, atau email. Info masuk dua langkah dapat diaktifkan di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" + }, + "editedFolder": { + "message": "Folder yang disunting" + }, + "deleteFolderConfirmation": { + "message": "Anda yakin Anda ingin menghapus folder ini?" + }, + "deletedFolder": { + "message": "Folder dihapus" + }, + "gettingStartedTutorial": { + "message": "Tutorial Perkenalan" + }, + "gettingStartedTutorialVideo": { + "message": "Lihat tutorial perkenalan kami untuk mempelajari bagaimana mendapatkan hasil maksimal dari ekstensi peramban." + }, + "syncingComplete": { + "message": "Sinkronisasi selesai" + }, + "syncingFailed": { + "message": "Gagal menyinkronkan" + }, + "passwordCopied": { + "message": "Sandi disalin" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "URl Baru" + }, + "addedItem": { + "message": "Item yang Ditambahkan" + }, + "editedItem": { + "message": "Item yang Diedit" + }, + "deleteItemConfirmation": { + "message": "Apakah Anda yakin ingin menghapus item ini?" + }, + "deletedItem": { + "message": "Item yang dihapus" + }, + "overwritePassword": { + "message": "Timpa Kata Sandi" + }, + "overwritePasswordConfirmation": { + "message": "Anda yakin ingin menimpa sandi saat ini?" + }, + "overwriteUsername": { + "message": "Menimpa nama pengguna" + }, + "overwriteUsernameConfirmation": { + "message": "Anda yakin ingin menimpa nama pengguna saat ini?" + }, + "searchFolder": { + "message": "Cari folder" + }, + "searchCollection": { + "message": "Cari koleksi" + }, + "searchType": { + "message": "Jenis pencarian" + }, + "noneFolder": { + "message": "Tidak Ada Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Nonaktifkan Notifikasi Penambahan Info Masuk" + }, + "addLoginNotificationDesc": { + "message": "\"Notifikasi Penambahan Info Masuk\" secara otomatis akan meminta Anda untuk menyimpan info masuk baru ke brankas Anda saat Anda masuk untuk pertama kalinya." + }, + "dontShowCardsCurrentTab": { + "message": "Jangan Tampilkan Kartu pada Laman Tab" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Item kartu dari brankas Anda akan ditampilkan pada laman 'Tab' untuk mempermudah akses isi-otomatis." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Jangan Tampilkan Identitas pada Laman Tab" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Item identitas dari brankas Anda akan ditampilkan pada laman 'Tab' untuk mempermudah akses isi-otomatis." + }, + "clearClipboard": { + "message": "Hapus Papan Klip", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Secara otomatis menghapus konten yang disalin dari papan klip Anda.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Haruskah Bitwarden mengingat sandi ini untuk Anda?" + }, + "notificationAddSave": { + "message": "Iya, Simpan Sekarang" + }, + "disableChangedPasswordNotification": { + "message": "Nonaktifkan Notifikasi Perubahan Kata Sandi" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Notifikasi Perubahan Kata Sandi\" secara otomatis akan meminta Anda untuk memperbarui kata sandi info masuk di brankas Anda ketika mendeteksi bahwa Anda telah mengubahnya lewat situs web." + }, + "notificationChangeDesc": { + "message": "Apakah Anda ingin memperbarui kata sandi ini di Bitwarden?" + }, + "notificationChangeSave": { + "message": "Iya, Perbarui Sekarang" + }, + "disableContextMenuItem": { + "message": "Nonaktifkan Opsi Menu Konteks" + }, + "disableContextMenuItemDesc": { + "message": "Pilihan menu konteks menyediakan akses cepat ke pembuat sandi dan info masuk untuk situs web di tab Anda saat ini." + }, + "defaultUriMatchDetection": { + "message": "Deteksi Kecocokan URI Bawaan", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Pilih cara bawaan penanganan pencocokan URI untuk masuk saat melakukan tindakan seperti isi-otomatis." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Ubah tema warna aplikasi." + }, + "dark": { + "message": "Gelap", + "description": "Dark color" + }, + "light": { + "message": "Terang", + "description": "Light color" + }, + "solarizedDark": { + "message": "Gelap Solarized", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Ekspor Brankas" + }, + "fileFormat": { + "message": "Format Berkas" + }, + "warning": { + "message": "PERINGATAN", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Konfirmasi Ekspor Brankas" + }, + "exportWarningDesc": { + "message": "Berkas ekspor ini berisi data brankas Anda dalam format tidak terenkripsi. Jangan pernah menyimpan atau mengirim berkas ini melalui kanal tidak aman (seperti surel). Segera hapus setelah Anda selesai menggunakannya." + }, + "encExportKeyWarningDesc": { + "message": "Ekspor ini mengenkripsi data Anda menggunakan kunci enkripsi akun Anda. Jika Anda pernah merotasi kunci enkripsi akun Anda, Anda harus mengekspor lagi karena Anda tidak akan dapat mendekripsi file ekspor ini." + }, + "encExportAccountWarningDesc": { + "message": "Kunci enkripsi akun unik untuk setiap akun pengguna Bitwarden, jadi Anda tidak dapat mengimpor ekspor terenkripsi ke akun lain." + }, + "exportMasterPassword": { + "message": "Masukkan sandi utama Anda untuk mengekspor data brankas Anda." + }, + "shared": { + "message": "Dibagikan" + }, + "learnOrg": { + "message": "Pelajari tentang Organisasi" + }, + "learnOrgConfirmation": { + "message": "Bitwarden memungkinkan Anda berbagi item brankas Anda dengan orang lain menggunakan organisasi. Maukah Anda mengunjungi laman bitwarden.com untuk mempelajari lebih lanjut?" + }, + "moveToOrganization": { + "message": "Pindah ke Organisasi" + }, + "share": { + "message": "Bagikan" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ pindah ke $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Pilihlah sebuah organisasi yang Anda ingin memindahkan item ini. Memindahkan bearti memberikan kepemilikan kepada organisasi tersebut. Anda tidak akan lagi menjadi pemilik item ini." + }, + "learnMore": { + "message": "Pelajari lebih lanjut" + }, + "authenticatorKeyTotp": { + "message": "Kunci Otentikasi (TOTP)" + }, + "verificationCodeTotp": { + "message": "Kode Verifikasi (TOTP)" + }, + "copyVerificationCode": { + "message": "Salin Kode Verifikasi" + }, + "attachments": { + "message": "Lampiran" + }, + "deleteAttachment": { + "message": "Hapus lampiran" + }, + "deleteAttachmentConfirmation": { + "message": "Anda yakin ingin menghapus lampiran ini?" + }, + "deletedAttachment": { + "message": "Lampiran dihapus" + }, + "newAttachment": { + "message": "Tambah Lampiran Baru" + }, + "noAttachments": { + "message": "Tidak ada lampiran." + }, + "attachmentSaved": { + "message": "Lampiran telah disimpan." + }, + "file": { + "message": "Berkas" + }, + "selectFile": { + "message": "Pilih berkas." + }, + "maxFileSize": { + "message": "Ukuran berkas maksimal adalah 500 MB." + }, + "featureUnavailable": { + "message": "Fitur Tidak Tersedia" + }, + "updateKey": { + "message": "Anda tidak dapat menggunakan fitur ini sampai Anda memperbarui kunci enkripsi Anda." + }, + "premiumMembership": { + "message": "Keanggotaan Premium" + }, + "premiumManage": { + "message": "Kelola Keanggotaan" + }, + "premiumManageAlert": { + "message": "Anda dapat mengelola keanggotaan Anda di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" + }, + "premiumRefresh": { + "message": "Segarkan Keanggotaan" + }, + "premiumNotCurrentMember": { + "message": "Anda saat ini bukan anggota premium." + }, + "premiumSignUpAndGet": { + "message": "Daftar untuk keanggotaan premium dan mendapatkan:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB penyimpanan berkas yang dienkripsi." + }, + "ppremiumSignUpTwoStep": { + "message": "Pilihan info masuk dua langkah tambahan seperti YubiKey, FIDO U2F, dan Duo." + }, + "ppremiumSignUpReports": { + "message": "Kebersihan kata sandi, kesehatan akun, dan laporan kebocoran data untuk tetap menjaga keamanan brankas Anda." + }, + "ppremiumSignUpTotp": { + "message": "Pembuat kode verifikasi TOTP (2FA) untuk masuk di brankas anda." + }, + "ppremiumSignUpSupport": { + "message": "Dukungan pelanggan prioritas." + }, + "ppremiumSignUpFuture": { + "message": "Semua fitur-fitur premium masa depan. Akan segera tiba!" + }, + "premiumPurchase": { + "message": "Beli Keanggotaan Premium" + }, + "premiumPurchaseAlert": { + "message": "Anda dapat membeli keanggotaan premium di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" + }, + "premiumCurrentMember": { + "message": "Anda adalah anggota premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Terima kasih telah mendukung Bitwarden." + }, + "premiumPrice": { + "message": "Semua itu hanya $PRICE$ /tahun!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Penyegaran selesai" + }, + "disableAutoTotpCopy": { + "message": "Nonaktifkan Penyalinan Otomatis TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Jika info masuk Anda memiliki kunci autentikasi yang menyertainya, kode verifikasi TOTP akan disalin secara otomatis ke clipboard Anda setiap kali Anda mengisi info masuk secara otomatis." + }, + "disableAutoBiometricsPrompt": { + "message": "Jangan minta biometrik saat dinyalakan." + }, + "premiumRequired": { + "message": "Membutuhkan Keanggotaan Premium" + }, + "premiumRequiredDesc": { + "message": "Keanggotaan premium diperlukan untuk menggunakan fitur ini." + }, + "enterVerificationCodeApp": { + "message": "Masukkan 6 digit kode verifikasi dari aplikasi autentikasi Anda." + }, + "enterVerificationCodeEmail": { + "message": "Masukkan 6 digit kode verifikasi yang dikirim melalui email ke $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Surel verifikasi telah dikirim ke $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Ingat saya" + }, + "sendVerificationCodeEmailAgain": { + "message": "Kirim ulang email kode verifikasi" + }, + "useAnotherTwoStepMethod": { + "message": "Gunakan metode masuk dua langkah lainnya" + }, + "insertYubiKey": { + "message": "Masukkan YubiKey Anda ke port USB komputer Anda, lalu sentuh tombolnya." + }, + "insertU2f": { + "message": "Masukkan kunci keamanan ke port USB komputer Anda. Jika ada tombolnya, tekanlah." + }, + "webAuthnNewTab": { + "message": "Untuk memulai verifikasi 2FA WebAuthn. Klik tombol di bawah untuk membuka tab baru dan ikuti instruksi yang diberikan." + }, + "webAuthnNewTabOpen": { + "message": "Buka tab baru" + }, + "webAuthnAuthenticate": { + "message": "Autentikasi dengan WebAuthn." + }, + "loginUnavailable": { + "message": "Info Masuk Tidak Tersedia" + }, + "noTwoStepProviders": { + "message": "Akun ini mengaktifkan info masuk dua langkah, namun, tidak satupun dari penyedia dua langkah yang dikonfigurasi didukung oleh peramban web ini." + }, + "noTwoStepProviders2": { + "message": "Silakan gunakan peramban web yang didukung (seperti Chrome) dan/atau tambahkan penyedia tambahan yang didukung di semua peramban web (seperti aplikasi autentikasi)." + }, + "twoStepOptions": { + "message": "Opsi Info Masuk Dua Langkah" + }, + "recoveryCodeDesc": { + "message": "Kehilangan akses ke semua penyedia dua faktor Anda? Gunakan kode pemulihan untuk menonaktifkan semua penyedia dua faktor dari akun Anda." + }, + "recoveryCodeTitle": { + "message": "Kode Pemulihan" + }, + "authenticatorAppTitle": { + "message": "Aplikasi Otentikasi" + }, + "authenticatorAppDesc": { + "message": "Gunakan aplikasi autentikasi (seperti Authy atau Google Authenticator) untuk menghasilkan kode verifikasi berbasis waktu.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Kunci Keamanan OTP YubiKey" + }, + "yubiKeyDesc": { + "message": "Gunakan YubiKey untuk mengakses akun Anda. Bekerja dengan YubiKey 4, 4 Nano, 4C, dan peranti NEO." + }, + "duoDesc": { + "message": "Verifikasi dengan Duo Security menggunakan aplikasi Duo Mobile, SMS, panggilan telepon, atau kunci keamanan U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifikasi dengan Duo Security untuk organisasi Anda menggunakan aplikasi Duo Mobile, SMS, panggilan telepon, atau kunci keamanan U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Gunakan kunci yang mendukung WebAUthn untuk mengakses akun anda." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Kode verifikasi akan dikirim via email kepada Anda." + }, + "selfHostedEnvironment": { + "message": "Lingkungan Penyedia Personal" + }, + "selfHostedEnvironmentFooter": { + "message": "Tetapkan URL dasar penyedia personal pemasangan Bitwarden Anda." + }, + "customEnvironment": { + "message": "Lingkungan Khusus" + }, + "customEnvironmentFooter": { + "message": "Untuk pengguna tingkat lanjut. Anda bisa menentukan basis dari URL masing-masing layanan secara independen." + }, + "baseUrl": { + "message": "URL Server" + }, + "apiUrl": { + "message": "URL Server API" + }, + "webVaultUrl": { + "message": "URL Server Brankas Web" + }, + "identityUrl": { + "message": "URL Server Identitas" + }, + "notificationsUrl": { + "message": "URL Server Notifikasi" + }, + "iconsUrl": { + "message": "URL Server Ikon" + }, + "environmentSaved": { + "message": "URL dari semua lingkungan telah disimpan." + }, + "enableAutoFillOnPageLoad": { + "message": "Aktifkan Isi-Otomatis Saat Memuat Laman" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Jika formulir info masuk terdeteksi, secara otomatis melakukan pengisian otomatis ketika memuat laman web." + }, + "experimentalFeature": { + "message": "Fitur ini saat ini adalah fitur eksperimental. Gunakan dengan risiko Anda sendiri." + }, + "defaultAutoFillOnPageLoad": { + "message": "Konfigurasi autofill standard untuk item login." + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Setelah mengaktifkan Auto-Fill waktu website terbuka, kamu dapat mengaktifkan atau meng-nonaktifkan feature ini untuk setiap item. Ini adalah konfigurasi standard untuk item yang tidak dikonfigurasi terpisah." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill waktu website terbuka (Jika diaktifkan di Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Gunakan pengaturan baku" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-Fill ketika website baru terbuka" + }, + "autoFillOnPageLoadNo": { + "message": "Jangan Auto-Fill ketika website baru terbuka" + }, + "commandOpenPopup": { + "message": "Buka popup brankas" + }, + "commandOpenSidebar": { + "message": "Buka brankas di bilah samping" + }, + "commandAutofillDesc": { + "message": "Isi otomatis info masuk yang digunakan terakhir untuk situs ini" + }, + "commandGeneratePasswordDesc": { + "message": "Buat dan salin kata sandi acak baru ke papan klip." + }, + "commandLockVaultDesc": { + "message": "Kunci brankas" + }, + "privateModeWarning": { + "message": "Dukungan mode pribadi bersifat eksperimental dan beberapa fitur terbatas." + }, + "customFields": { + "message": "Ruas Khusus" + }, + "copyValue": { + "message": "Salin Nilai" + }, + "value": { + "message": "Nilai" + }, + "newCustomField": { + "message": "Ruas Khusus Baru" + }, + "dragToSort": { + "message": "Seret untuk mengurutkan" + }, + "cfTypeText": { + "message": "Teks" + }, + "cfTypeHidden": { + "message": "Tersembunyi" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Terhubung", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Tindakan klik diluar jendela popup untuk memeriksa kode verifikasi di dalam surel Anda akan menyebabkan popup ini ditutup. Apakah Anda ingin membuka popup ini di jendela baru sehingga terus tetap terbuka?" + }, + "popupU2fCloseMessage": { + "message": "Peramban ini tidak bisa memproses permintaan U2F di jendela popup ini. Apakah Anda ingin membuka popup ini di jendela baru sehingga Anda dapat masuk menggunakan U2F?" + }, + "disableFavicon": { + "message": "Nonaktifkan Ikon Situs Web" + }, + "disableFaviconDesc": { + "message": "Ikon Situs Web menyediakan gambar yang mudah dikenali di sebelah item info masuk di dalam brankas Anda." + }, + "disableBadgeCounter": { + "message": "Matikan angka penghitung " + }, + "disableBadgeCounterDesc": { + "message": "Angka penghitung menandakan jumlah login yang kamu punya untuk website saat ini yang ada di dalam vault kamu." + }, + "cardholderName": { + "message": "Nama Pemegang Kartu" + }, + "number": { + "message": "Nomor" + }, + "brand": { + "message": "Merek" + }, + "expirationMonth": { + "message": "Bulan Kedaluwarsa" + }, + "expirationYear": { + "message": "Tahun Kedaluwarsa" + }, + "expiration": { + "message": "Masa Berlaku" + }, + "january": { + "message": "Januari" + }, + "february": { + "message": "Februari" + }, + "march": { + "message": "Maret" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Mei" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "Agustus" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Desember" + }, + "securityCode": { + "message": "Kode Keamanan" + }, + "ex": { + "message": "mis." + }, + "title": { + "message": "Panggilan" + }, + "mr": { + "message": "Tuan" + }, + "mrs": { + "message": "Nyonya" + }, + "ms": { + "message": "Nona" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Nama Depan" + }, + "middleName": { + "message": "Nama Tengah" + }, + "lastName": { + "message": "Nama Belakang" + }, + "fullName": { + "message": "Nama Lengkap" + }, + "identityName": { + "message": "Nama Identitas" + }, + "company": { + "message": "Perusahaan" + }, + "ssn": { + "message": "Nomor Jaminan Sosial" + }, + "passportNumber": { + "message": "Nomor Paspor" + }, + "licenseNumber": { + "message": "Nomor Lisensi" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telepon" + }, + "address": { + "message": "Alamat" + }, + "address1": { + "message": "Alamat 1" + }, + "address2": { + "message": "Alamat 2" + }, + "address3": { + "message": "Alamat 3" + }, + "cityTown": { + "message": "Kota / Kabupaten" + }, + "stateProvince": { + "message": "Negara Bagian / Provinsi" + }, + "zipPostalCode": { + "message": "Kode Pos" + }, + "country": { + "message": "Negara" + }, + "type": { + "message": "Tipe" + }, + "typeLogin": { + "message": "Info Masuk" + }, + "typeLogins": { + "message": "Info Masuk" + }, + "typeSecureNote": { + "message": "Catatan Aman" + }, + "typeCard": { + "message": "Kartu" + }, + "typeIdentity": { + "message": "Identitas" + }, + "passwordHistory": { + "message": "Riwayat Kata Sandi" + }, + "back": { + "message": "Kembali" + }, + "collections": { + "message": "Koleksi" + }, + "favorites": { + "message": "Favorit" + }, + "popOutNewWindow": { + "message": "Buka di jendela baru" + }, + "refresh": { + "message": "Segarkan" + }, + "cards": { + "message": "Kartu" + }, + "identities": { + "message": "Identitas" + }, + "logins": { + "message": "Info Masuk" + }, + "secureNotes": { + "message": "Catatan Aman" + }, + "clear": { + "message": "Bersihkan", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Periksa jika kata sandi telah terekspos." + }, + "passwordExposed": { + "message": "Kata sandi ini telah terekspos $VALUE$ kali dalam insiden kebocoran data. Anda harus memperbaruinya.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Kata sandi ini tidak ditemukan dalam insiden kebocoran data yang ada. Kata sandi tersebut seharusnya aman untuk digunakan." + }, + "baseDomain": { + "message": "Domain basis", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nama Domain", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Hos", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tepat" + }, + "startsWith": { + "message": "Mulai dengan" + }, + "regEx": { + "message": "Ekspresi umum", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Deteksi Kecocokan", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Deteksi kecocokan standar", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Ubah Opsi" + }, + "toggleCurrentUris": { + "message": "Alihkan URI Saat Ini", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI Saat Ini", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisasi", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tipe" + }, + "allItems": { + "message": "Semua Item" + }, + "noPasswordsInList": { + "message": "Tidak ada sandi yang dapat dicantumkan." + }, + "remove": { + "message": "Hapus" + }, + "default": { + "message": "Bawaan" + }, + "dateUpdated": { + "message": "Diperbarui", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Kata Sandi Diperbarui", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Apakah Anda yakin ingin menggunakan opsi \"Jangan Pernah\"? Mengatur opsi penguncian ke \"Jangan Pernah\" akan menyimpan kunci enkripsi brankas Anda di dalam perangkat. Jika Anda menggunakan opsi ini, Anda harus pastikan perangkat Anda dilindungi dengan baik." + }, + "noOrganizationsList": { + "message": "Anda tidak tergabung dalam organisasi apapun. Organisasi memungkinkan Anda secara aman berbagi item dengan pengguna lainnya." + }, + "noCollectionsInList": { + "message": "Tidak ada koleksi untuk ditampilkan." + }, + "ownership": { + "message": "Kepemilikan" + }, + "whoOwnsThisItem": { + "message": "Siapa pemilik item ini?" + }, + "strong": { + "message": "Kuat", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Baik", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Lemah", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Kata Sandi Utama Lemah" + }, + "weakMasterPasswordDesc": { + "message": "Kata sandi utama yang Anda pilih itu lemah. Anda harus menggunakan kata sandi yang kuat (atau frasa sandi) untuk melindungi akun Bitwarden Anda. Apakah Anda yakin ingin menggunakan kata sandi ini?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Buka kunci dengan PIN" + }, + "setYourPinCode": { + "message": "Setel kode PIN Anda untuk membuka kunci Bitwarden. Pengaturan PIN Anda akan diatur ulang jika Anda pernah keluar sepenuhnya dari aplikasi." + }, + "pinRequired": { + "message": "Membutuhkan kode PIN." + }, + "invalidPin": { + "message": "Kode PIN tidak valid." + }, + "unlockWithBiometrics": { + "message": "Buka kunci dengan biometrik" + }, + "awaitDesktop": { + "message": "Menunggu konfirmasi dari desktop" + }, + "awaitDesktopDesc": { + "message": "Silakan konfirmasi menggunakan biometrik di aplikasi Bitwarden Desktop untuk mengaktifkan biometrik untuk peramban." + }, + "lockWithMasterPassOnRestart": { + "message": "Kunci dengan kata sandi utama saat peramban dimulai ulang" + }, + "selectOneCollection": { + "message": "Anda harus memilih setidaknya satu koleksi." + }, + "cloneItem": { + "message": "Duplikat Item" + }, + "clone": { + "message": "Duplikat" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Satu atau lebih kebijakan organisasi mempengaruhi pengaturan pembuat sandi Anda." + }, + "vaultTimeoutAction": { + "message": "Tindakan Batas Waktu Brankas" + }, + "lock": { + "message": "Kunci", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Sampah", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Cari di sampah" + }, + "permanentlyDeleteItem": { + "message": "Hapus Item Secara Permanen" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Apakah Anda yakin ingin menghapus item ini secara permanen?" + }, + "permanentlyDeletedItem": { + "message": "Hapus Item Secara Permanen" + }, + "restoreItem": { + "message": "Pulihkan Item" + }, + "restoreItemConfirmation": { + "message": "Apakah Anda yakin ingin memulihkan item ini?" + }, + "restoredItem": { + "message": "Item Yang Dipulihkan" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Keluar akan menghapus semua akses ke brankas Anda dan membutuhkan otentikasi daring setelah periode batas waktu tertentu. Apakah Anda yakin ingin menggunakan pengaturan ini?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Konfirmasi Tindakan Batas Waktu" + }, + "autoFillAndSave": { + "message": "Isi Otomatis dan Simpan" + }, + "autoFillSuccessAndSavedUri": { + "message": "Item yang Diisi Otomatis dan URI Tersimpan" + }, + "autoFillSuccess": { + "message": "Item Terisi Otomatis" + }, + "setMasterPassword": { + "message": "Atur Kata Sandi Utama" + }, + "masterPasswordPolicyInEffect": { + "message": "Satu atau lebih kebijakan organisasi membutuhkan kata sandi utama Anda untuk memenuhi persyaratan berikut:" + }, + "policyInEffectMinComplexity": { + "message": "Skor kompleksitas minimum $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Panjang minimum $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Berisi satu atau lebih karakter huruf besar" + }, + "policyInEffectLowercase": { + "message": "Berisi satu atau lebih karakter huruf kecil" + }, + "policyInEffectNumbers": { + "message": "Berisi satu atau lebih angka" + }, + "policyInEffectSpecial": { + "message": "Berisi satu atau lebih karakter khusus berikut $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Kata sandi utama Anda yang baru tidak memenuhi persyaratan kebijakan." + }, + "acceptPolicies": { + "message": "Dengan mencentang kotak ini, Anda menyetujui yang berikut:" + }, + "acceptPoliciesError": { + "message": "Persyaratan Layanan dan Kebijakan Privasi belum disetujui." + }, + "termsOfService": { + "message": "Persyaratan Layanan" + }, + "privacyPolicy": { + "message": "Kebijakan Privasi" + }, + "hintEqualsPassword": { + "message": "Petunjuk kata sandi Anda tidak boleh sama dengan kata sandi Anda." + }, + "ok": { + "message": "Oke" + }, + "desktopSyncVerificationTitle": { + "message": "Verifikasi sinkronisasi desktop" + }, + "desktopIntegrationVerificationText": { + "message": "Harap verifikasi bahwa aplikasi desktop menampilkan sidik jari ini: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Integrasi peramban tidak diaktifkan" + }, + "desktopIntegrationDisabledDesc": { + "message": "Integrasi peramban tidak diaktifkan di aplikasi Desktop Bitwarden. Silakan aktifkan di pengaturan di dalam aplikasi desktop." + }, + "startDesktopTitle": { + "message": "Jalankan aplikasi Desktop Bitwarden" + }, + "startDesktopDesc": { + "message": "Aplikasi Desktop Bitwarden harus dijalankan sebelum fungsi ini bisa digunakan." + }, + "errorEnableBiometricTitle": { + "message": "Tidak bisa mengaktifkan biometrik" + }, + "errorEnableBiometricDesc": { + "message": "Tindakan dibatalkan oleh aplikasi desktop" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Aplikasi desktop membatalkan saluran komunikasi aman. Silakan coba lagi proses ini" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Komunikasi desktop terputus" + }, + "nativeMessagingWrongUserDesc": { + "message": "Aplikasi desktop masuk ke akun yang berbeda. Harap pastikan kedua aplikasi masuk ke akun yang sama." + }, + "nativeMessagingWrongUserTitle": { + "message": "Akun tidak cocok" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrik tidak diaktifkan" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrik peramban mengharuskan biometrik desktop diaktifkan di pengaturan terlebih dahulu." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrik tidak didukung" + }, + "biometricsNotSupportedDesc": { + "message": "Biometrik peramban tidak didukung di perangkat ini." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Izin tidak diberikan" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Tanpa adanya izin untuk berkomunikasi dengan Aplikasi Desktop Bitwarden kami tidak bisa menyediakan fitur biometrik di dalam ekstensi peramban. Silakan coba lagi." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Kesalahan permintaan izin" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Tindakan ini tidak dapat dilakukan di sidebar, coba lagi tindakan di pop-up atau pop-out." + }, + "personalOwnershipSubmitError": { + "message": "Karena Kebijakan Perusahaan, Anda dilarang menyimpan item ke brankas personal Anda. Ubah opsi Kepemilikan ke organisasi dan pilih dari Koleksi yang tersedia." + }, + "personalOwnershipPolicyInEffect": { + "message": "Kebijakan organisasi memengaruhi opsi kepemilikan Anda." + }, + "excludedDomains": { + "message": "Domain yang Dikecualikan" + }, + "excludedDomainsDesc": { + "message": "Bitwarden tidak akan meminta untuk menyimpan detail login untuk domain ini. Anda harus menyegarkan halaman agar perubahan diterapkan." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ bukan domain yang valid", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Pencarian Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Tambahkan Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Teks" + }, + "sendTypeFile": { + "message": "Berkas" + }, + "allSends": { + "message": "Semua Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Jumlah akses maksimum tercapai", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Kedaluwarsa" + }, + "pendingDeletion": { + "message": "Penghapusan menunggu keputusan" + }, + "passwordProtected": { + "message": "Dilindungi kata sandi" + }, + "copySendLink": { + "message": "Salin tautan Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Hapus Kata Sandi" + }, + "delete": { + "message": "Hapus" + }, + "removedPassword": { + "message": "Kata Sandi yang Dihapus" + }, + "deletedSend": { + "message": "Send Dihapus", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Tautan Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Dinonaktifkan" + }, + "removePasswordConfirmation": { + "message": "Anda yakin ingin menghapus kata sandi?" + }, + "deleteSend": { + "message": "Hapus Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Anda yakin ingin menghapus Send ini?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Jenis Send apakah ini?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Nama yang bersahabat untuk menggambarkan Send ini.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "File yang ingin Anda kirim." + }, + "deletionDate": { + "message": "Tanggal Penghapusan" + }, + "deletionDateDesc": { + "message": "Send akan dihapus secara permanen pada tanggal dan waktu yang ditentukan.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Tanggal habis tempo" + }, + "expirationDateDesc": { + "message": "Jika disetel, akses ke Send ini akan berakhir pada tanggal dan waktu yang ditentukan.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 hari" + }, + "days": { + "message": "$DAYS$ hari", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Kustom" + }, + "maximumAccessCount": { + "message": "Hitungan Akses Maksimum" + }, + "maximumAccessCountDesc": { + "message": "Jika disetel, pengguna tidak dapat lagi mengakses Send ini setelah jumlah akses maksimum tercapai.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Secara opsional, minta kata sandi bagi pengguna untuk mengakses Send ini.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Catatan pribadi tentang Send ini.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Nonaktifkan Send ini sehingga tidak ada yang dapat mengaksesnya.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Salin tautan Send ini ke papan klip setelah disimpan.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teks yang ingin Anda kirim." + }, + "sendHideText": { + "message": "Sembunyikan teks Send ini secara default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Hitungan Akses Saat Ini" + }, + "createSend": { + "message": "Buat Send Baru", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Kata Sandi baru" + }, + "sendDisabled": { + "message": "Send Dinonaktifkan", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Karena kebijakan perusahaan, Anda hanya dapat menghapus Send yang sudah ada.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send Dibuat ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send diedit", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Untuk memilih file ini, buka Extension di sidebar (jika memungkinkan) atau keluarkan menjadi window baru dengan menekan gambar ini." + }, + "sendFirefoxFileWarning": { + "message": "Untuk memilih file menggunakan Firefox, buka ekstensi di sidebar atau keluar ke jendela baru dengan mengklik banner ini." + }, + "sendSafariFileWarning": { + "message": "Untuk memilih file menggunakan Safari, keluar ke jendela baru dengan mengklik spanduk ini." + }, + "sendFileCalloutHeader": { + "message": "Sebelum kamu memulai" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Untuk menggunakan pemilih tanggal gaya kalender", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klik disini", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "untuk memunculkan jendela Anda.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Tanggal kedaluwarsa yang diberikan tidak valid." + }, + "deletionDateIsInvalid": { + "message": "Tanggal penghapusan yang diberikan tidak valid." + }, + "expirationDateAndTimeRequired": { + "message": "Diperlukan tanggal dan waktu kedaluwarsa." + }, + "deletionDateAndTimeRequired": { + "message": "Tanggal dan waktu penghapusan diperlukan." + }, + "dateParsingError": { + "message": "Terjadi kesalahan saat menyimpan tanggal penghapusan dan kedaluwarsa Anda." + }, + "hideEmail": { + "message": "Sembunyikan alamat surel dari penerima." + }, + "sendOptionsPolicyInEffect": { + "message": "Satu atau lebih kebijakan organisasi mempengaruhi pengaturan feature Send anda." + }, + "passwordPrompt": { + "message": "Master password ditanyakan kembali" + }, + "passwordConfirmation": { + "message": "Konfirmasi sandi utama" + }, + "passwordConfirmationDesc": { + "message": "Aksi ini terproteksi. Untuk melanjutkan, masukkan kembali sandi utama Anda untuk verifikasi identitas." + }, + "emailVerificationRequired": { + "message": "Verifikasi Email Diperlukan" + }, + "emailVerificationRequiredDesc": { + "message": "Anda harus memverifikasi email Anda untuk menggunakan fitur ini. Anda dapat memverifikasi email Anda di brankas web." + }, + "updatedMasterPassword": { + "message": "Kata Sandi Utama Telah Diperbarui" + }, + "updateMasterPassword": { + "message": "Perbarui Kata Sandi Utama" + }, + "updateMasterPasswordWarning": { + "message": "Kata Sandi Utama Anda baru-baru ini diubah oleh administrator organisasi Anda. Untuk mengakses brankas tersebut, Anda diharuskan memperbarui Kata Sandi Utama Anda sekarang. Jika Anda melanjutkan, Anda akan keluar dari sesi saat ini, yang mana mengharuskan Anda untuk login kembali. Sesi yang aktif di perangkat lain akan tetap aktif selama satu jam kedepan." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Pendaftaran Otomatis" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Organisasi ini memiliki kebijakan perusahaan yang secara otomatis mendaftarkan Anda dalam pengaturan ulang kata sandi. Dengan mendaftar, akan memungkinkan administrator organisasi untuk mengubah kata sandi utama Anda." + }, + "selectFolder": { + "message": "Pilih Folder..." + }, + "ssoCompleteRegistration": { + "message": "Untuk menyelesaikan masuk dengan SSO, harap setel kata sandi utama untuk mengakses dan melindungi brankas Anda." + }, + "hours": { + "message": "Jam" + }, + "minutes": { + "message": "Menit" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Kebijakan organisasi Anda memengaruhi waktu tunggu brankas Anda. Batas maksimal Waktu Tunggu Brankas yang diizinkan adalah $HOURS$ jam dan $MINUTES$ menit", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Waktu tunggu brankas Anda melebihi batasan yang diatur organisasi Anda." + }, + "vaultExportDisabled": { + "message": "Ekspor Brankas Dinonaktifkan" + }, + "personalVaultExportPolicyInEffect": { + "message": "Satu atau beberapa kebijakan organisasi mencegah Anda mengekspor brankas pribadi Anda." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Tidak dapat mengidentifikasi elemen yang valid. Coba inspeksi HTML saja." + }, + "copyCustomFieldNameNotUnique": { + "message": "Tidak ada pengidentifikasi unik yang ditemukan." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Tinggalkan Organisasi" + }, + "removeMasterPassword": { + "message": "Hapus Kata Sandi Utama" + }, + "removedMasterPassword": { + "message": "Sandi utama dihapus." + }, + "leaveOrganizationConfirmation": { + "message": "Apakah Anda yakin ingin meninggalkan organisasi ini?" + }, + "leftOrganization": { + "message": "Anda telah keluar dari organisasi." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/it/messages.json b/apps/browser/src/_locales/it/messages.json new file mode 100644 index 0000000000..f1a51e23d0 --- /dev/null +++ b/apps/browser/src/_locales/it/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Gestore di password gratuito", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Un gestore di password sicuro e gratuito per tutti i tuoi dispositivi.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Accedi o crea un nuovo account per accedere alla tua cassaforte." + }, + "createAccount": { + "message": "Crea account" + }, + "login": { + "message": "Accedi" + }, + "enterpriseSingleSignOn": { + "message": "Single Sign-On aziendale" + }, + "cancel": { + "message": "Annulla" + }, + "close": { + "message": "Chiudi" + }, + "submit": { + "message": "Invia" + }, + "emailAddress": { + "message": "Indirizzo email" + }, + "masterPass": { + "message": "Password principale" + }, + "masterPassDesc": { + "message": "La password principale è la password che utilizzi per accedere alla tua cassaforte. È molto importante che tu non la dimentichi. Non c'è modo di recuperare questa password nel caso che tu la dimenticassi." + }, + "masterPassHintDesc": { + "message": "Un suggerimento per la password principale può aiutarti a ricordarla nel caso la dimenticassi." + }, + "reTypeMasterPass": { + "message": "Ri-digita la tua password principale" + }, + "masterPassHint": { + "message": "Suggerimento password principale (facoltativo)" + }, + "tab": { + "message": "Scheda" + }, + "myVault": { + "message": "Cassaforte" + }, + "tools": { + "message": "Strumenti" + }, + "settings": { + "message": "Impostazioni" + }, + "currentTab": { + "message": "Scheda attuale" + }, + "copyPassword": { + "message": "Copia password" + }, + "copyNote": { + "message": "Copia nota" + }, + "copyUri": { + "message": "Copia URI" + }, + "copyUsername": { + "message": "Copia nome utente" + }, + "copyNumber": { + "message": "Copia numero" + }, + "copySecurityCode": { + "message": "Copia codice di sicurezza" + }, + "autoFill": { + "message": "Auto-riempimento" + }, + "generatePasswordCopied": { + "message": "Genera password (copiata)" + }, + "copyElementIdentifier": { + "message": "Copia nome campo personalizzato" + }, + "noMatchingLogins": { + "message": "Nessun login corrispondente." + }, + "unlockVaultMenu": { + "message": "Sblocca la tua cassaforte" + }, + "loginToVaultMenu": { + "message": "Accedi alla tua cassaforte" + }, + "autoFillInfo": { + "message": "Non ci sono login disponibili per completare la scheda attuale del browser." + }, + "addLogin": { + "message": "Aggiungi un login" + }, + "addItem": { + "message": "Aggiungi elemento" + }, + "passwordHint": { + "message": "Suggerimento password" + }, + "enterEmailToGetHint": { + "message": "Inserisci l'indirizzo email del tuo account per ricevere il suggerimento della password principale." + }, + "getMasterPasswordHint": { + "message": "Ottieni il suggerimento della password principale" + }, + "continue": { + "message": "Continua" + }, + "sendVerificationCode": { + "message": "Invia un codice di verifica alla tua email" + }, + "sendCode": { + "message": "Invia codice" + }, + "codeSent": { + "message": "Codice inviato" + }, + "verificationCode": { + "message": "Codice di verifica" + }, + "confirmIdentity": { + "message": "Conferma la tua identità per continuare." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Modifica password principale" + }, + "fingerprintPhrase": { + "message": "Frase impronta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frase impronta dell'account", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Verifica in due passaggi" + }, + "logOut": { + "message": "Esci" + }, + "about": { + "message": "Informazioni" + }, + "version": { + "message": "Versione" + }, + "save": { + "message": "Salva" + }, + "move": { + "message": "Sposta" + }, + "addFolder": { + "message": "Aggiungi cartella" + }, + "name": { + "message": "Nome" + }, + "editFolder": { + "message": "Modifica cartella" + }, + "deleteFolder": { + "message": "Elimina cartella" + }, + "folders": { + "message": "Cartelle" + }, + "noFolders": { + "message": "Non ci sono cartelle da elencare." + }, + "helpFeedback": { + "message": "Aiuto e segnalazioni" + }, + "sync": { + "message": "Sincronizza" + }, + "syncVaultNow": { + "message": "Sincronizza ora la cassaforte" + }, + "lastSync": { + "message": "Ultima sincronizzazione:" + }, + "passGen": { + "message": "Generatore di password" + }, + "generator": { + "message": "Generatore", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Genera automaticamente password complesse e uniche per i tuoi login." + }, + "bitWebVault": { + "message": "Cassaforte web di Bitwarden" + }, + "importItems": { + "message": "Importa elementi" + }, + "select": { + "message": "Seleziona" + }, + "generatePassword": { + "message": "Genera password" + }, + "regeneratePassword": { + "message": "Rigenera password" + }, + "options": { + "message": "Opzioni" + }, + "length": { + "message": "Lunghezza" + }, + "uppercase": { + "message": "Maiuscole (A-Z)" + }, + "lowercase": { + "message": "Minuscole (a-z)" + }, + "numbers": { + "message": "Numeri (0-9)" + }, + "specialCharacters": { + "message": "Caratteri speciali (!@#$%^&*)" + }, + "numWords": { + "message": "Numero di parole" + }, + "wordSeparator": { + "message": "Separatore parole" + }, + "capitalize": { + "message": "Rendi maiuscolo", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Includi numero" + }, + "minNumbers": { + "message": "Minimo di numeri" + }, + "minSpecial": { + "message": "Minimo di speciali" + }, + "avoidAmbChar": { + "message": "Evita caratteri ambigui" + }, + "searchVault": { + "message": "Cerca nella cassaforte" + }, + "edit": { + "message": "Modifica" + }, + "view": { + "message": "Visualizza" + }, + "noItemsInList": { + "message": "Non ci sono elementi da elencare." + }, + "itemInformation": { + "message": "Informazioni sull'elemento" + }, + "username": { + "message": "Nome utente" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Frase segreta" + }, + "favorite": { + "message": "Preferito" + }, + "notes": { + "message": "Note" + }, + "note": { + "message": "Nota" + }, + "editItem": { + "message": "Modifica elemento" + }, + "folder": { + "message": "Cartella" + }, + "deleteItem": { + "message": "Elimina elemento" + }, + "viewItem": { + "message": "Visualizza elemento" + }, + "launch": { + "message": "Avvia" + }, + "website": { + "message": "Sito web" + }, + "toggleVisibility": { + "message": "Mostra/Nascondi" + }, + "manage": { + "message": "Gestisci" + }, + "other": { + "message": "Altro" + }, + "rateExtension": { + "message": "Valuta l'estensione" + }, + "rateExtensionDesc": { + "message": "Prendi in considerazione l'idea di lasciarci una buona recensione!" + }, + "browserNotSupportClipboard": { + "message": "Il tuo browser non supporta la copia dagli appunti. Copiala manualmente." + }, + "verifyIdentity": { + "message": "Verifica l'identità." + }, + "yourVaultIsLocked": { + "message": "La tua cassaforte è bloccata. Inserisci la tua password principale per continuare." + }, + "unlock": { + "message": "Sblocca" + }, + "loggedInAsOn": { + "message": "Accesso effettuato come $EMAIL$ su $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Password principale errata" + }, + "vaultTimeout": { + "message": "Timeout cassaforte" + }, + "lockNow": { + "message": "Blocca ora" + }, + "immediately": { + "message": "Immediatamente" + }, + "tenSeconds": { + "message": "10 secondi" + }, + "twentySeconds": { + "message": "20 secondi" + }, + "thirtySeconds": { + "message": "30 secondi" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minuti" + }, + "fiveMinutes": { + "message": "5 minuti" + }, + "fifteenMinutes": { + "message": "15 minuti" + }, + "thirtyMinutes": { + "message": "30 minuti" + }, + "oneHour": { + "message": "1 ora" + }, + "fourHours": { + "message": "4 ore" + }, + "onLocked": { + "message": "Al blocco del computer" + }, + "onRestart": { + "message": "Al riavvio del browser" + }, + "never": { + "message": "Mai" + }, + "security": { + "message": "Sicurezza" + }, + "errorOccurred": { + "message": "Si è verificato un errore" + }, + "emailRequired": { + "message": "L'indirizzo email è obbligatorio." + }, + "invalidEmail": { + "message": "Indirizzo email non valido." + }, + "masterPassRequired": { + "message": "La password principale è obbligatoria." + }, + "masterPassLength": { + "message": "La password principale deve essere lunga almeno 8 caratteri." + }, + "masterPassDoesntMatch": { + "message": "La conferma della password principale non corrisponde." + }, + "newAccountCreated": { + "message": "Il tuo nuovo account è stato creato! Ora puoi eseguire l'accesso." + }, + "masterPassSent": { + "message": "Ti abbiamo inviato una email con il tuo suggerimento per la password principale." + }, + "verificationCodeRequired": { + "message": "Il codice di verifica è obbligatorio." + }, + "invalidVerificationCode": { + "message": "Codice di verifica non valido." + }, + "valueCopied": { + "message": "$VALUE$ copiata", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Impossibile completare automaticamente il login selezionato per questa pagina. Copia e incolla manualmente le tue credenziali." + }, + "loggedOut": { + "message": "Disconnesso" + }, + "loginExpired": { + "message": "La tua sessione è scaduta." + }, + "logOutConfirmation": { + "message": "Sei sicuro di volerti disconnettere?" + }, + "yes": { + "message": "Sì" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "Si è verificato un errore imprevisto." + }, + "nameRequired": { + "message": "Il nome è obbligatorio." + }, + "addedFolder": { + "message": "Cartella aggiunta" + }, + "changeMasterPass": { + "message": "Modifica password principale" + }, + "changeMasterPasswordConfirmation": { + "message": "Puoi cambiare la tua password principale sulla cassaforte online di bitwarden.com. Vuoi visitare ora il sito?" + }, + "twoStepLoginConfirmation": { + "message": "L'autenticazione in due passaggi rende il tuo account più sicuro richiedendo di verificare il login con un altro dispositivo come una chiave di sicurezza, applicazione di autenticazione, SMS, telefonata o email. Può essere abilitata sulla cassaforte online di bitwarden.com. Vuoi visitare il sito ora?" + }, + "editedFolder": { + "message": "Cartella modificata" + }, + "deleteFolderConfirmation": { + "message": "Sei sicuro di voler modificare questa cartella?" + }, + "deletedFolder": { + "message": "Cartella eliminata" + }, + "gettingStartedTutorial": { + "message": "Guida per iniziare" + }, + "gettingStartedTutorialVideo": { + "message": "Guarda il nostro tutorial iniziale per capire come ottenere il massimo dall'estensione del browser." + }, + "syncingComplete": { + "message": "Sincronizzazione completata" + }, + "syncingFailed": { + "message": "Sincronizzazione non riuscita" + }, + "passwordCopied": { + "message": "Password copiata" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nuovo URI" + }, + "addedItem": { + "message": "Elemento aggiunto" + }, + "editedItem": { + "message": "Elemento modificato" + }, + "deleteItemConfirmation": { + "message": "Sei sicuro di voler cestinare questo elemento?" + }, + "deletedItem": { + "message": "Elemento cestinato" + }, + "overwritePassword": { + "message": "Sovrascrivi password" + }, + "overwritePasswordConfirmation": { + "message": "Sei sicuro di voler sovrascrivere la password corrente?" + }, + "overwriteUsername": { + "message": "Sovrascrivi nome utente" + }, + "overwriteUsernameConfirmation": { + "message": "Sei sicuro di voler sovrascrivere il nome utente attuale?" + }, + "searchFolder": { + "message": "Cerca nella cartella" + }, + "searchCollection": { + "message": "Cerca nella raccolta" + }, + "searchType": { + "message": "Cerca tipo" + }, + "noneFolder": { + "message": "Nessuna cartella", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disabilita notifica di aggiunta login" + }, + "addLoginNotificationDesc": { + "message": "\"Aggiungi notifica di login\" richiede automaticamente di salvare i nuovi login nella tua cassaforte ogni volta che accedi per la prima volta." + }, + "dontShowCardsCurrentTab": { + "message": "Non mostrare le carte nella pagina delle schede" + }, + "dontShowCardsCurrentTabDesc": { + "message": "I dati della carta dalla tua cassaforte sono elencati nella sezione \"Scheda attuale\" per facilitare il riempimento automatico." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Non mostrare le identità nella pagina delle schede" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Le identità della tua cassaforte sono elencati nella sezione \"Scheda attuale\" per facilitare il completamento automatico." + }, + "clearClipboard": { + "message": "Cancella appunti", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Cancella automaticamente dagli appunti i valori copiati.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Vuoi che Bitwarden ricordi questa password per te?" + }, + "notificationAddSave": { + "message": "Sì, salva ora" + }, + "disableChangedPasswordNotification": { + "message": "Disabilita notifica di modifica delle password" + }, + "disableChangedPasswordNotificationDesc": { + "message": "La \"notifica di cambio password\" chiede automaticamente di aggiornare la password di un account della cassaforte ogni qualvolta viene rilevata una modifica su un sito web." + }, + "notificationChangeDesc": { + "message": "Vuoi aggiornare questa password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Sì, aggiorna ora" + }, + "disableContextMenuItem": { + "message": "Disabilita integrazione del menu contestuale" + }, + "disableContextMenuItemDesc": { + "message": "Le opzioni del menu contestuale forniscono accesso rapido alla generazione di password e ai login per il sito web nella scheda corrente." + }, + "defaultUriMatchDetection": { + "message": "Rilevamento corrispondenza URI predefinito", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Scegli il modo predefinito in cui il rilevamento della corrispondenza URI viene gestito per gli accessi quando si eseguono azioni come il riempimento automatico." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Cambia lo schema di colori dell'applicazione." + }, + "dark": { + "message": "Scuro", + "description": "Dark color" + }, + "light": { + "message": "Chiaro", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarizzato scuro", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Esporta cassaforte" + }, + "fileFormat": { + "message": "Formato file" + }, + "warning": { + "message": "ATTENZIONE", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Conferma esportazione della cassaforte" + }, + "exportWarningDesc": { + "message": "Questa esportazione contiene i dati della tua cassaforte in un formato non cifrato. Non salvare o inviare il file esportato su canali non protetti (come la posta elettronica). Eliminalo immediatamente dopo l'utilizzo." + }, + "encExportKeyWarningDesc": { + "message": "Questa esportazione cifra i tuoi dati utilizzando la chiave di cifratura del tuo account. Se cambi la chiave di cifratura del tuo account, non sarai più in grado di decifrare il file esportato e sarà necessario eseguire una nuova esportazione." + }, + "encExportAccountWarningDesc": { + "message": "Le chiavi di cifratura dell'account sono uniche per ogni account utente Bitwarden, quindi non è possibile importare un'esportazione cifrata in un account diverso." + }, + "exportMasterPassword": { + "message": "Inserisci la tua password principale per esportare i dati della tua cassaforte." + }, + "shared": { + "message": "Condiviso" + }, + "learnOrg": { + "message": "Scopri le organizzazioni" + }, + "learnOrgConfirmation": { + "message": "Bitwarden ti permette di condividere gli elementi della tua cassaforte con altri usando un'organizzazione. Vuoi visitare il sito bitwarden.com per saperne di più?" + }, + "moveToOrganization": { + "message": "Sposta in organizzazione" + }, + "share": { + "message": "Condividi" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ spostato in $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Scegli un'organizzazione in cui desideri spostare questo elemento. Spostare in un'organizzazione trasferisce la proprietà dell'elemento all'organizzazione. Non sarai più il proprietario diretto di questo elemento una volta spostato." + }, + "learnMore": { + "message": "Per saperne di più" + }, + "authenticatorKeyTotp": { + "message": "Chiave di autenticazione (TOTP)" + }, + "verificationCodeTotp": { + "message": "Codice di verifica (TOTP)" + }, + "copyVerificationCode": { + "message": "Copia codice di verifica" + }, + "attachments": { + "message": "Allegati" + }, + "deleteAttachment": { + "message": "Elimina allegato" + }, + "deleteAttachmentConfirmation": { + "message": "Sei sicuro di voler eliminare questo allegato?" + }, + "deletedAttachment": { + "message": "Allegato eliminato" + }, + "newAttachment": { + "message": "Aggiungi Nuovo Allegato" + }, + "noAttachments": { + "message": "Nessun allegato." + }, + "attachmentSaved": { + "message": "L'allegato è stato salvato." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Seleziona un file." + }, + "maxFileSize": { + "message": "La dimensione massima del file è 500 MB." + }, + "featureUnavailable": { + "message": "Funzione non disponibile" + }, + "updateKey": { + "message": "Non puoi utilizzare questa funzione finché non aggiorni la tua chiave di cifratura." + }, + "premiumMembership": { + "message": "Abbonamento Premium" + }, + "premiumManage": { + "message": "Gestisci abbonamento" + }, + "premiumManageAlert": { + "message": "Puoi gestire il tuo abbonamento premium online su bitwarden.com. Vuoi visitare ora il sito?" + }, + "premiumRefresh": { + "message": "Aggiorna abbonamento" + }, + "premiumNotCurrentMember": { + "message": "Al momento non sei un membro premium." + }, + "premiumSignUpAndGet": { + "message": "Iscriviti a un abbonamento premium e ottieni:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB di spazio di archiviazione cifrato per gli allegati." + }, + "ppremiumSignUpTwoStep": { + "message": "Opzioni addizionali di login in due passaggi come YubiKey, FIDO U2F, e Duo." + }, + "ppremiumSignUpReports": { + "message": "Sicurezza delle password, integrità dell'account e resoconti sulla violazione di dati per mantenere sicura la tua cassaforte." + }, + "ppremiumSignUpTotp": { + "message": "Generatore di codice di verifica TOTP (2FA) per i login nella tua cassaforte." + }, + "ppremiumSignUpSupport": { + "message": "Supporto clienti prioritario." + }, + "ppremiumSignUpFuture": { + "message": "Tutte le funzioni Premium future. Nuove in arrivo!" + }, + "premiumPurchase": { + "message": "Acquista Premium" + }, + "premiumPurchaseAlert": { + "message": "Puoi acquistare il tuo abbonamento premium online su bitwarden.com. Vuoi visitare ora il sito?" + }, + "premiumCurrentMember": { + "message": "Sei un membro premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Grazie per il tuo supporto a Bitwarden." + }, + "premiumPrice": { + "message": "Il tutto per soli $PRICE$ all'anno!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Aggiornamento completato" + }, + "disableAutoTotpCopy": { + "message": "Disattiva copia TOTP automatica" + }, + "disableAutoTotpCopyDesc": { + "message": "Se il tuo login ha un autenticatore collegato, il codice ti verifica TOTP è automaticamente copiato negli appunti ogni volta che auto-completi il login." + }, + "disableAutoBiometricsPrompt": { + "message": "Non richiedere dati biometrici all'avvio" + }, + "premiumRequired": { + "message": "Premium richiesto" + }, + "premiumRequiredDesc": { + "message": "Un abbonamento premium è richiesto per utilizzare questa funzionalità." + }, + "enterVerificationCodeApp": { + "message": "Inserisci il codice di verifica a 6 cifre dalla tua applicazione di autenticazione." + }, + "enterVerificationCodeEmail": { + "message": "Inserisci il codice di verifica a 6 cifrato inviato a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "L'email di verifica è stata inviata all'indirizzo $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Ricordami" + }, + "sendVerificationCodeEmailAgain": { + "message": "Invia nuovamente l'email con il codice di verifica" + }, + "useAnotherTwoStepMethod": { + "message": "Usa un altro metodo di login in due passaggi" + }, + "insertYubiKey": { + "message": "Inserisci la tua YubiKey nella porta USB del computer, poi premi il suo pulsante." + }, + "insertU2f": { + "message": "Inserisci la tua chiave di sicurezza nella porta USB del tuo computer. Se dispone di un pulsante, premilo." + }, + "webAuthnNewTab": { + "message": "Per avviare la verifica WebAuthn 2FA. Fare clic sul pulsante in basso per aprire una nuova scheda e seguire le istruzioni fornite nella nuova scheda. " + }, + "webAuthnNewTabOpen": { + "message": "Apri nuova scheda" + }, + "webAuthnAuthenticate": { + "message": "Autenticazione WebAuthn" + }, + "loginUnavailable": { + "message": "Login non disponibile" + }, + "noTwoStepProviders": { + "message": "Questo account ha abilitato il login in due passaggi, ma nessuno dei provider configurati è supportato da questo browser web." + }, + "noTwoStepProviders2": { + "message": "Utilizzare un browser web supportato (come Chrome) e/o aggiungere altri provider che sono supportati meglio da tutti i browser web (ad esempio un'applicazione di autenticazione)." + }, + "twoStepOptions": { + "message": "Opzioni di login in due passaggi" + }, + "recoveryCodeDesc": { + "message": "Hai perso l'accesso a tutti i tuoi provider a due passaggi? Usa il tuo codice di recupero per disattivarli dal tuo account." + }, + "recoveryCodeTitle": { + "message": "Codice di recupero" + }, + "authenticatorAppTitle": { + "message": "Applicazione di autenticazione" + }, + "authenticatorAppDesc": { + "message": "Usa un'applicazione di autenticazione (come Authy o Google Authenticator) per generare codici di verifica a tempo.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Chiave di sicurezza YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Usa YubiKey per accedere al tuo account. Funziona con YubiKey 4, 4 Nano, 4C, e dispositivi NEO." + }, + "duoDesc": { + "message": "Verifica con Duo Security usando l'applicazione Duo Mobile, SMS, chiamata telefonica, o chiave di sicurezza U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifica con Duo Security per la tua azienda usando l'applicazione Duo Mobile, SMS, chiamata telefonica, o chiave di sicurezza U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Usa qualsiasi chiave di sicurezza abilitata WebAuthn per accedere al tuo account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "I codici di verifica ti saranno inviati per email." + }, + "selfHostedEnvironment": { + "message": "Ambiente self-hosted" + }, + "selfHostedEnvironmentFooter": { + "message": "Specifica l'URL principale della tua installazione Bitwarden self-hosted." + }, + "customEnvironment": { + "message": "Ambiente personalizzato" + }, + "customEnvironmentFooter": { + "message": "Per utenti avanzati. Puoi specificare l'URL principale di ogni servizio indipendentemente." + }, + "baseUrl": { + "message": "URL del server" + }, + "apiUrl": { + "message": "URL del server API" + }, + "webVaultUrl": { + "message": "URL della cassaforte web" + }, + "identityUrl": { + "message": "URL del server di identità" + }, + "notificationsUrl": { + "message": "URL del server delle notifiche" + }, + "iconsUrl": { + "message": "URL del server di icone" + }, + "environmentSaved": { + "message": "Gli URL dell'ambiente sono stati salvati." + }, + "enableAutoFillOnPageLoad": { + "message": "Abilita l'auto-completamento al caricamento della pagina" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Se viene rilevato un modulo di accesso, effettua un auto-completamento quando la pagina web si carica." + }, + "experimentalFeature": { + "message": "Al momento questa funzionalità è sperimentale. Usala a tuo rischio e pericolo." + }, + "defaultAutoFillOnPageLoad": { + "message": "Impostazioni di completamento automatico predefinito per i login" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Dopo aver abilitato il completamento automatico al caricamento della pagina, è possibile abilitare o disabilitare la funzione per singoli login. Questa è l'impostazione predefinita per i login che non sono configurati separatamente." + }, + "itemAutoFillOnPageLoad": { + "message": "Autocompletamento al caricamento della pagina (se abilitato nelle opzioni)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Usa impostazione predefinita" + }, + "autoFillOnPageLoadYes": { + "message": "Autocompletamento al caricamento della pagina" + }, + "autoFillOnPageLoadNo": { + "message": "Non completare automaticamente al caricamento della pagina" + }, + "commandOpenPopup": { + "message": "Apri popup cassaforte" + }, + "commandOpenSidebar": { + "message": "Apri la cassaforte nella barra laterale" + }, + "commandAutofillDesc": { + "message": "Auto-completa con l'ultimo accesso utilizzato sul sito corrente" + }, + "commandGeneratePasswordDesc": { + "message": "Genera e copia una nuova password casuale negli appunti" + }, + "commandLockVaultDesc": { + "message": "Blocca la cassaforte" + }, + "privateModeWarning": { + "message": "Il supporto della modalità privata è sperimentale e alcune funzionalità sono limitate." + }, + "customFields": { + "message": "Campi personalizzati" + }, + "copyValue": { + "message": "Copia valore" + }, + "value": { + "message": "Valore" + }, + "newCustomField": { + "message": "Nuovo campo personalizzato" + }, + "dragToSort": { + "message": "Trascina per ordinare" + }, + "cfTypeText": { + "message": "Testo" + }, + "cfTypeHidden": { + "message": "Nascosto" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "cfTypeLinked": { + "message": "Collegato", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Valore collegato", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Facendo clic all'esterno della finestra popup per controllare la mail con il codice di verifica chiuderà la finestra di popup. Vuoi aprire questo popup in una nuova finestra?" + }, + "popupU2fCloseMessage": { + "message": "Questo browser non può elaborare richieste U2F in questa finestra a comparsa. Vuoi aprire questo popup in una nuova finestra in modo da poter accedere usando U2F?" + }, + "disableFavicon": { + "message": "Disabilita icone dei siti web" + }, + "disableFaviconDesc": { + "message": "Le icone del sito web forniscono un'immagine riconoscibile accanto a ogni elemento di login della tua cassaforte." + }, + "disableBadgeCounter": { + "message": "Disabilita contatore delle occorrenze" + }, + "disableBadgeCounterDesc": { + "message": "Il contatore delle occorrenze indica quanti accessi hai per la pagina corrente nella tua cassaforte." + }, + "cardholderName": { + "message": "Titolare della carta" + }, + "number": { + "message": "Numero" + }, + "brand": { + "message": "Marca" + }, + "expirationMonth": { + "message": "Mese di scadenza" + }, + "expirationYear": { + "message": "Anno di scadenza" + }, + "expiration": { + "message": "Scadenza" + }, + "january": { + "message": "Gennaio" + }, + "february": { + "message": "Febbraio" + }, + "march": { + "message": "Marzo" + }, + "april": { + "message": "Aprile" + }, + "may": { + "message": "Maggio" + }, + "june": { + "message": "Giugno" + }, + "july": { + "message": "Luglio" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Settembre" + }, + "october": { + "message": "Ottobre" + }, + "november": { + "message": "Novembre" + }, + "december": { + "message": "Dicembre" + }, + "securityCode": { + "message": "Codice di sicurezza" + }, + "ex": { + "message": "es." + }, + "title": { + "message": "Titolo" + }, + "mr": { + "message": "Sig" + }, + "mrs": { + "message": "Sig.ra" + }, + "ms": { + "message": "Sig.ra" + }, + "dr": { + "message": "Dottore" + }, + "firstName": { + "message": "Nome" + }, + "middleName": { + "message": "Secondo nome" + }, + "lastName": { + "message": "Cognome" + }, + "fullName": { + "message": "Nome completo" + }, + "identityName": { + "message": "Nome dell'identità" + }, + "company": { + "message": "Azienda" + }, + "ssn": { + "message": "Codice fiscale/Previdenza sociale" + }, + "passportNumber": { + "message": "Numero del passaporto" + }, + "licenseNumber": { + "message": "Numero della patente" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telefono" + }, + "address": { + "message": "Indirizzo" + }, + "address1": { + "message": "Indirizzo 1" + }, + "address2": { + "message": "Indirizzo 2" + }, + "address3": { + "message": "Indirizzo 3" + }, + "cityTown": { + "message": "Città / Comune" + }, + "stateProvince": { + "message": "Stato / Provincia" + }, + "zipPostalCode": { + "message": "CAP" + }, + "country": { + "message": "Nazione" + }, + "type": { + "message": "Tipo" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Login" + }, + "typeSecureNote": { + "message": "Nota sicura" + }, + "typeCard": { + "message": "Carta" + }, + "typeIdentity": { + "message": "Identità" + }, + "passwordHistory": { + "message": "Cronologia delle password" + }, + "back": { + "message": "Indietro" + }, + "collections": { + "message": "Raccolte" + }, + "favorites": { + "message": "Preferiti" + }, + "popOutNewWindow": { + "message": "Apri in una nuova finestra" + }, + "refresh": { + "message": "Aggiorna" + }, + "cards": { + "message": "Carte" + }, + "identities": { + "message": "Identità" + }, + "logins": { + "message": "Login" + }, + "secureNotes": { + "message": "Note sicure" + }, + "clear": { + "message": "Cancella", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Verifica se la password è stata esposta." + }, + "passwordExposed": { + "message": "Questa password è presente $VALUE$ volta/e in database di violazioni. Dovresti cambiarla.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Questa password non è stata trovata in database di violazioni noti. Dovrebbe essere sicura da usare." + }, + "baseDomain": { + "message": "Dominio di base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nome dominio", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Esatto" + }, + "startsWith": { + "message": "Inizia con" + }, + "regEx": { + "message": "Espressione regolare", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Rilevamento di corrispondenza", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Rilevamento di corrispondenza predefinito", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Attiva/Disattiva opzioni" + }, + "toggleCurrentUris": { + "message": "Mostra/Nascondi URI attuale", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI attuale", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organizzazione", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tipi" + }, + "allItems": { + "message": "Tutti gli elementi" + }, + "noPasswordsInList": { + "message": "Non ci sono password da elencare." + }, + "remove": { + "message": "Rimuovi" + }, + "default": { + "message": "Predefinito" + }, + "dateUpdated": { + "message": "Aggiornato", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password aggiornata", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Sei sicuro di voler usare l'opzione \"Mai\"? Impostando le opzioni di blocco su \"Mai\", la chiave di cifratura della cassaforte sarà salvata sul tuo dispositivo. Se utilizzi questa opzione, assicurati di mantenere il dispositivo adeguatamente protetto." + }, + "noOrganizationsList": { + "message": "Non appartieni ad alcuna organizzazione. Le organizzazioni ti consentono di condividere oggetti in modo sicuro con altri utenti." + }, + "noCollectionsInList": { + "message": "Nessuna raccolta da elencare." + }, + "ownership": { + "message": "Proprietà" + }, + "whoOwnsThisItem": { + "message": "A chi appartiene questo elemento?" + }, + "strong": { + "message": "Forte", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Buona", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Debole", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Password principale debole" + }, + "weakMasterPasswordDesc": { + "message": "La password principale che hai scelto è debole. È necessario utilizzare una password principale forte (o una frase segreta) per proteggere adeguatamente il tuo account Bitwarden. Sei sicuro di voler utilizzare questa password principale?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Sblocca con PIN" + }, + "setYourPinCode": { + "message": "Imposta il tuo codice PIN per sbloccare Bitwarden. Le impostazioni PIN saranno reimpostate se eseguirai una disconnessione completa dall'applicazione." + }, + "pinRequired": { + "message": "È richiesto il PIN." + }, + "invalidPin": { + "message": "Codice PIN non valido." + }, + "unlockWithBiometrics": { + "message": "Sblocca con i dati biometrici" + }, + "awaitDesktop": { + "message": "In attesa di conferma dal desktop" + }, + "awaitDesktopDesc": { + "message": "Conferma utilizzando l'autenticazione biometrica nell'applicazione Bitwarden Desktop per abilitare l'autenticazione biometrica per il browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Blocca con la password principale al riavvio del browser" + }, + "selectOneCollection": { + "message": "Devi selezionare almeno una raccolta." + }, + "cloneItem": { + "message": "Clona elemento" + }, + "clone": { + "message": "Clona" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una o più policy dell'organizzazione controllano le impostazioni del tuo generatore." + }, + "vaultTimeoutAction": { + "message": "Azione timeout cassaforte" + }, + "lock": { + "message": "Blocca", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Cestino", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Cerca nel cestino" + }, + "permanentlyDeleteItem": { + "message": "Elimina definitivamente l'elemento" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Sei sicuro di voler eliminare definitivamente questo elemento?" + }, + "permanentlyDeletedItem": { + "message": "Elemento eliminato definitivamente" + }, + "restoreItem": { + "message": "Ripristina elemento" + }, + "restoreItemConfirmation": { + "message": "Sei sicuro di voler ripristinare questo elemento?" + }, + "restoredItem": { + "message": "Elemento ripristinato" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "La disconnessione rimuove tutti gli accessi alla cassaforte e richiede l'autenticazione online dopo il periodo di timeout. Sei sicuro di voler utilizzare questa impostazione?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Conferma azione di timeout" + }, + "autoFillAndSave": { + "message": "Riempi automaticamente e salva" + }, + "autoFillSuccessAndSavedUri": { + "message": "Elemento riempito automaticamente e URI salvato" + }, + "autoFillSuccess": { + "message": "Elemento riempito automaticamente" + }, + "setMasterPassword": { + "message": "Imposta la password principale" + }, + "masterPasswordPolicyInEffect": { + "message": "La password principale deve avere i seguenti requisiti, stabiliti da una o più regole dell'organizzazione:" + }, + "policyInEffectMinComplexity": { + "message": "Punteggio minimo di complessità di $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Lunghezza minima di $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contiene almeno un carattere maiuscolo" + }, + "policyInEffectLowercase": { + "message": "Contiene almeno un carattere minuscolo" + }, + "policyInEffectNumbers": { + "message": "Contiene almeno una cifra" + }, + "policyInEffectSpecial": { + "message": "Contiene almeno uno dei seguenti caratteri speciali $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "La tua nuova password principale non soddisfa i parametri di sicurezza." + }, + "acceptPolicies": { + "message": "Selezionando la casella accetti quanto segue:" + }, + "acceptPoliciesError": { + "message": "I termini di servizio e l'informativa sulla privacy non sono stati accettati." + }, + "termsOfService": { + "message": "Termini del servizio" + }, + "privacyPolicy": { + "message": "Informativa sulla privacy" + }, + "hintEqualsPassword": { + "message": "Il suggerimento della password non può essere uguale alla password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Verifica sincronizzazione desktop" + }, + "desktopIntegrationVerificationText": { + "message": "Verifica che l'applicazione desktop mostri questa impronta digitale: " + }, + "desktopIntegrationDisabledTitle": { + "message": "L'integrazione del browser non è abilitata" + }, + "desktopIntegrationDisabledDesc": { + "message": "L'integrazione del browser non è abilitata nell'applicazione Bitwarden Desktop. Attivala nelle impostazioni all'interno dell'applicazione desktop." + }, + "startDesktopTitle": { + "message": "Avvia l'applicazione desktop Bitwarden" + }, + "startDesktopDesc": { + "message": "L'applicazione Bitwarden Desktop deve essere avviata prima che questa funzione possa essere utilizzata." + }, + "errorEnableBiometricTitle": { + "message": "Impossibile abilitare l'autenticazione biometrica" + }, + "errorEnableBiometricDesc": { + "message": "L'azione è stata annullata dall'applicazione desktop" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "L'applicazione desktop ha invalidato il canale di comunicazione sicuro. Ritenta l'operazione" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Comunicazione desktop interrotta" + }, + "nativeMessagingWrongUserDesc": { + "message": "L'applicazione desktop è collegata a un account diverso. Assicurati che entrambe le applicazioni siano collegate allo stesso account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account non corrispondente" + }, + "biometricsNotEnabledTitle": { + "message": "Autenticazione biometrica non abilitata" + }, + "biometricsNotEnabledDesc": { + "message": "L'autenticazione biometrica del browser richiede che l'autenticazione biometrica del desktop sia prima abilitata nelle impostazioni." + }, + "biometricsNotSupportedTitle": { + "message": "Autenticazione biometrica non supportata" + }, + "biometricsNotSupportedDesc": { + "message": "L'autenticazione biometrica del browser non è supportata su questo dispositivo." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permesso non fornito" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Senza l'autorizzazione per comunicare con l'applicazione Bitwarden Desktop non è possibile fornire l'autenticazione biometrica nell'estensione del browser. Riprova di nuovo." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Errore richiesta di autorizzazione" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Questa azione non può essere eseguita nella barra laterale, riprova l'azione nel popup o nella finestra." + }, + "personalOwnershipSubmitError": { + "message": "A causa di una policy aziendale, non è possibile salvare elementi nella tua cassaforte personale. Cambia l'opzione proprietà in un'organizzazione e scegli tra le raccolte disponibili." + }, + "personalOwnershipPolicyInEffect": { + "message": "Una policy dell'organizzazione controlla le opzioni di proprietà." + }, + "excludedDomains": { + "message": "Domini esclusi" + }, + "excludedDomainsDesc": { + "message": "Bitwarden non chiederà di salvare i dettagli di accesso per questi domini. È necessario aggiornare la pagina perché le modifiche abbiano effetto." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ non è un dominio valido", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Cerca Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Aggiungi Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Testo" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "Tutti i Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Numero massimo di accessi raggiunto", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Scaduto" + }, + "pendingDeletion": { + "message": "In attesa di eliminazione" + }, + "passwordProtected": { + "message": "Protetto da password" + }, + "copySendLink": { + "message": "Copia collegamento del Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Rimuovi password" + }, + "delete": { + "message": "Elimina" + }, + "removedPassword": { + "message": "Password rimossa" + }, + "deletedSend": { + "message": "Send eliminato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Collegamento del Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabilitato" + }, + "removePasswordConfirmation": { + "message": "Sei sicuro di voler rimuovere la password?" + }, + "deleteSend": { + "message": "Elimina Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Sei sicuro di voler eliminare questo Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Modifica Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Di quale tipo di Send si tratta?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Un nome intuitivo per descrivere questo Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Il file da inviare." + }, + "deletionDate": { + "message": "Data di eliminazione" + }, + "deletionDateDesc": { + "message": "Il Send sarà definitivamente eliminato alla data e ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data di scadenza" + }, + "expirationDateDesc": { + "message": "Se impostato, l'accesso a questo Send scadrà alla data e all'ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 giorno" + }, + "days": { + "message": "$DAYS$ giorni", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Personalizzato" + }, + "maximumAccessCount": { + "message": "Numero massimo di accessi" + }, + "maximumAccessCountDesc": { + "message": "Se impostata, gli utenti non saranno più in grado di accedere a questo Send una volta raggiunto il numero massimo di accessi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Facoltativamente, richiedi una password agli utenti per accedere al Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Note private sul Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disabilita il Send per renderlo inaccessibile.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copia il collegamento del Send negli appunti dopo aver salvato.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Il testo che vuoi inviare." + }, + "sendHideText": { + "message": "Nascondi il testo di questo Send in modo predefinito.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Numero di accessi attuale" + }, + "createSend": { + "message": "Crea nuovo Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nuova password" + }, + "sendDisabled": { + "message": "Send disabilitato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "A causa di una policy aziendale, è possibile eliminare solo un Send esistente.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send creato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send modificato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Per scegliere un file, apri l'estensione nella barra laterale (se possibile) o apri una nuova finestra facendo clic su questo banner." + }, + "sendFirefoxFileWarning": { + "message": "Per scegliere un file utilizzando Firefox, apri l'estensione nella barra laterale o apri una nuova finestra facendo clic sul banner." + }, + "sendSafariFileWarning": { + "message": "Per scegliere un file utilizzando Safari, apri una nuova finestra facendo clic sul banner." + }, + "sendFileCalloutHeader": { + "message": "Prima di iniziare" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Per usare un selettore di date stile calendario", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "fai clic qui", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "per aprire la finestra.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "La data di scadenza fornita non è valida." + }, + "deletionDateIsInvalid": { + "message": "La data di eliminazione fornita non è valida." + }, + "expirationDateAndTimeRequired": { + "message": "È necessario inserire data e ora di scadenza." + }, + "deletionDateAndTimeRequired": { + "message": "È necessario inserire data e ora di eliminazione." + }, + "dateParsingError": { + "message": "Si è verificato un errore durante il salvataggio delle date di eliminazione e scadenza." + }, + "hideEmail": { + "message": "Nascondi il mio indirizzo email dai destinatari." + }, + "sendOptionsPolicyInEffect": { + "message": "Una o più policy dell'organizzazione influenzano le opzioni dei Send." + }, + "passwordPrompt": { + "message": "Nuova richiesta della password principale" + }, + "passwordConfirmation": { + "message": "Conferma della password principale" + }, + "passwordConfirmationDesc": { + "message": "Questa azione è protetta. Per continuare, inserisci nuovamente la tua password principale per verificare la tua identità." + }, + "emailVerificationRequired": { + "message": "Verifica email richiesta" + }, + "emailVerificationRequiredDesc": { + "message": "Devi verificare la tua email per utilizzare questa funzionalità. Puoi verificare la tua email nella cassaforte web." + }, + "updatedMasterPassword": { + "message": "Password principale aggiornata" + }, + "updateMasterPassword": { + "message": "Aggiorna password principale" + }, + "updateMasterPasswordWarning": { + "message": "La tua password principale è stata recentemente modificata da un amministratore nella tua organizzazione. Per accedere alla cassaforte, aggiorna ora la password. Procedendo sarai disconnesso dalla sessione attuale e ti sarà richiesto di effettuare nuovamente l'accesso. Le sessioni attive su altri dispositivi potrebbero continuare a rimanere attive per un massimo di un'ora." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Iscrizione automatica" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Questa organizzazione ha una policy aziendale che ti iscriverà automaticamente al ripristino della password. Ciò permetterà agli amministratori dell'organizzazione di cambiare la tua password principale." + }, + "selectFolder": { + "message": "Seleziona cartella..." + }, + "ssoCompleteRegistration": { + "message": "Per completare l'accesso con SSO, imposta una password principale per accedere e proteggere la cassaforte." + }, + "hours": { + "message": "Ore" + }, + "minutes": { + "message": "Minuti" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Le policy dell'organizzazione stanno influenzando il timeout della tua cassaforte. Il tempo massimo consentito è di $HOURS$ ore e $MINUTES$ minuti", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Il timeout della tua cassaforte supera i limiti impostati dalla tua organizzazione." + }, + "vaultExportDisabled": { + "message": "Esportazione cassaforte disabilitata" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una o più policy dell'organizzazione ti impediscono di esportare la tua cassaforte personale." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Impossibile identificare un elemento del form valido. Prova a ispezionare l'HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nessun identificatore univoco trovato." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ sta usando SSO con un server \"self-hosted\". Non è più richiesta una password principale per accedere per i membri di questa organizzazione.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Lascia l'organizzazione" + }, + "removeMasterPassword": { + "message": "Rimuovi la password principale" + }, + "removedMasterPassword": { + "message": "Password principale rimossa." + }, + "leaveOrganizationConfirmation": { + "message": "Sei sicuro di voler lasciare questa organizzazione?" + }, + "leftOrganization": { + "message": "Hai lasciato l'organizzazione." + }, + "toggleCharacterCount": { + "message": "Attiva/Disattiva conteggio dei caratteri" + }, + "sessionTimeout": { + "message": "La tua sessione è scaduta. Torna indietro e riprova ad accedere." + }, + "exportingPersonalVaultTitle": { + "message": "Esportazione cassaforte personale" + }, + "exportingPersonalVaultDescription": { + "message": "Saranno esportati solo gli oggetti della cassaforte personale associati a $EMAIL$. Gli oggetti della cassaforte dell'organizzazione non saranno inclusi.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Errore" + }, + "regenerateUsername": { + "message": "Rigenera nome utente" + }, + "generateUsername": { + "message": "Genera nome utente" + }, + "usernameType": { + "message": "Tipo di nome utente" + }, + "plusAddressedEmail": { + "message": "Indirizzo email alternativo", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Usa le funzionalità di sub-indirizzamento del tuo fornitore di posta elettronica." + }, + "catchallEmail": { + "message": "Email catch-all" + }, + "catchallEmailDesc": { + "message": "Usa la casella di posta catch-all di dominio." + }, + "random": { + "message": "Casuale" + }, + "randomWord": { + "message": "Parola casuale" + }, + "websiteName": { + "message": "Nome sito web" + }, + "whatWouldYouLikeToGenerate": { + "message": "Cosa vorresti generare?" + }, + "passwordType": { + "message": "Tipo di password" + }, + "service": { + "message": "Servizio" + } +} diff --git a/apps/browser/src/_locales/ja/messages.json b/apps/browser/src/_locales/ja/messages.json new file mode 100644 index 0000000000..d6f5ebd0b2 --- /dev/null +++ b/apps/browser/src/_locales/ja/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - 無料パスワードマネージャー", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden はあらゆる端末で使える、安全な無料パスワードマネージャーです。", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "安全なデータ保管庫へアクセスするためにログインまたはアカウントを作成してください。" + }, + "createAccount": { + "message": "アカウントの作成" + }, + "login": { + "message": "ログイン" + }, + "enterpriseSingleSignOn": { + "message": "組織のシングルサインオン" + }, + "cancel": { + "message": "キャンセル" + }, + "close": { + "message": "閉じる" + }, + "submit": { + "message": "送信" + }, + "emailAddress": { + "message": "メールアドレス" + }, + "masterPass": { + "message": "マスターパスワード" + }, + "masterPassDesc": { + "message": "マスターパスワードは、パスワード保管庫へのアクセスに使用するパスワードです。あなたのマスターパスワードを忘れないように注意してください。忘れた場合、パスワードを回復する方法はありません。" + }, + "masterPassHintDesc": { + "message": "マスターパスワードのヒントは、パスワードを忘れた場合に役立ちます。" + }, + "reTypeMasterPass": { + "message": "新しいパスワードを再入力" + }, + "masterPassHint": { + "message": "マスターパスワードのヒント (省略可能)" + }, + "tab": { + "message": "タブ" + }, + "myVault": { + "message": "保管庫" + }, + "tools": { + "message": "ツール" + }, + "settings": { + "message": "設定" + }, + "currentTab": { + "message": "現在のタブ" + }, + "copyPassword": { + "message": "パスワードをコピー" + }, + "copyNote": { + "message": "メモをコピー" + }, + "copyUri": { + "message": "URI をコピー" + }, + "copyUsername": { + "message": "ユーザー名をコピー" + }, + "copyNumber": { + "message": "番号のコピー" + }, + "copySecurityCode": { + "message": "セキュリティコードをコピー" + }, + "autoFill": { + "message": "自動入力" + }, + "generatePasswordCopied": { + "message": "パスワードを生成 (コピー)" + }, + "copyElementIdentifier": { + "message": "カスタムフィールド名をコピー" + }, + "noMatchingLogins": { + "message": "一致するログインがありません。" + }, + "unlockVaultMenu": { + "message": "保管庫のロックを解除" + }, + "loginToVaultMenu": { + "message": "保管庫にログイン" + }, + "autoFillInfo": { + "message": "現在のブラウザタブに自動入力するログイン情報はありません。" + }, + "addLogin": { + "message": "ログイン情報を追加" + }, + "addItem": { + "message": "アイテムの追加" + }, + "passwordHint": { + "message": "パスワードのヒント" + }, + "enterEmailToGetHint": { + "message": "マスターパスワードのヒントを受信するアカウントのメールアドレスを入力してください。" + }, + "getMasterPasswordHint": { + "message": "マスターパスワードのヒントを取得する" + }, + "continue": { + "message": "続ける" + }, + "sendVerificationCode": { + "message": "確認コードをメールに送信" + }, + "sendCode": { + "message": "コードを送信" + }, + "codeSent": { + "message": "確認コードを送信しました。" + }, + "verificationCode": { + "message": "認証コード" + }, + "confirmIdentity": { + "message": "続行するには本人確認を行ってください。" + }, + "account": { + "message": "アカウント" + }, + "changeMasterPassword": { + "message": "マスターパスワードの変更" + }, + "fingerprintPhrase": { + "message": "パスフレーズ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "アカウントのパスフレーズ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "2段階認証" + }, + "logOut": { + "message": "ログアウト" + }, + "about": { + "message": "アプリについて" + }, + "version": { + "message": "バージョン" + }, + "save": { + "message": "保存" + }, + "move": { + "message": "移動" + }, + "addFolder": { + "message": "フォルダーを追加" + }, + "name": { + "message": "名前" + }, + "editFolder": { + "message": "フォルダーを編集" + }, + "deleteFolder": { + "message": "フォルダーを削除" + }, + "folders": { + "message": "フォルダー" + }, + "noFolders": { + "message": "一覧表示するフォルダーはありません。" + }, + "helpFeedback": { + "message": "ヘルプ&フィードバック" + }, + "sync": { + "message": "同期" + }, + "syncVaultNow": { + "message": "保管庫を同期する" + }, + "lastSync": { + "message": "前回の同期:" + }, + "passGen": { + "message": "パスワード生成ツール" + }, + "generator": { + "message": "パス生成", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "ログインのために強固なユニークパスワードを自動的に生成します。" + }, + "bitWebVault": { + "message": "Bitwarden ウェブ保管庫" + }, + "importItems": { + "message": "アイテムのインポート" + }, + "select": { + "message": "選択" + }, + "generatePassword": { + "message": "パスワードの自動生成" + }, + "regeneratePassword": { + "message": "パスワードの再生成" + }, + "options": { + "message": "オプション" + }, + "length": { + "message": "長さ" + }, + "uppercase": { + "message": "大文字(A-Z)" + }, + "lowercase": { + "message": "小文字(a-z)" + }, + "numbers": { + "message": "数字 (0~9)" + }, + "specialCharacters": { + "message": "特殊文字(!@#$%^&*)" + }, + "numWords": { + "message": "単語数" + }, + "wordSeparator": { + "message": "単語の区切り" + }, + "capitalize": { + "message": "先頭を大文字", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "数字を含む" + }, + "minNumbers": { + "message": "数字の最小数" + }, + "minSpecial": { + "message": "記号の最小数" + }, + "avoidAmbChar": { + "message": "あいまいな文字を省く" + }, + "searchVault": { + "message": "保管庫を検索" + }, + "edit": { + "message": "編集" + }, + "view": { + "message": "表示" + }, + "noItemsInList": { + "message": "表示するアイテムがありません" + }, + "itemInformation": { + "message": "アイテム情報" + }, + "username": { + "message": "ユーザ名" + }, + "password": { + "message": "パスワード" + }, + "passphrase": { + "message": "パスフレーズ" + }, + "favorite": { + "message": "お気に入り" + }, + "notes": { + "message": "メモ" + }, + "note": { + "message": "メモ" + }, + "editItem": { + "message": "アイテムの編集" + }, + "folder": { + "message": "フォルダー" + }, + "deleteItem": { + "message": "アイテムの削除" + }, + "viewItem": { + "message": "アイテムの表示" + }, + "launch": { + "message": "開く" + }, + "website": { + "message": "ウェブサイト" + }, + "toggleVisibility": { + "message": "表示切り替え" + }, + "manage": { + "message": "管理" + }, + "other": { + "message": "その他" + }, + "rateExtension": { + "message": "拡張機能の評価" + }, + "rateExtensionDesc": { + "message": "良いレビューで私たちを助けてください!" + }, + "browserNotSupportClipboard": { + "message": "お使いのブラウザはクリップボードへのコピーに対応していません。手動でコピーしてください" + }, + "verifyIdentity": { + "message": "本人確認を行う" + }, + "yourVaultIsLocked": { + "message": "保管庫がロックされています。開くにはマスターパスワードを入力してください。" + }, + "unlock": { + "message": "ロック解除" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ の $EMAIL$ としてログインしました。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "マスターパスワードが間違っています" + }, + "vaultTimeout": { + "message": "保管庫のタイムアウト" + }, + "lockNow": { + "message": "今すぐロック" + }, + "immediately": { + "message": "すぐに" + }, + "tenSeconds": { + "message": "10秒" + }, + "twentySeconds": { + "message": "20秒" + }, + "thirtySeconds": { + "message": "30秒" + }, + "oneMinute": { + "message": "1分" + }, + "twoMinutes": { + "message": "2分" + }, + "fiveMinutes": { + "message": "5分" + }, + "fifteenMinutes": { + "message": "15分" + }, + "thirtyMinutes": { + "message": "30分" + }, + "oneHour": { + "message": "1時間" + }, + "fourHours": { + "message": "4時間" + }, + "onLocked": { + "message": "ロック時" + }, + "onRestart": { + "message": "ブラウザ再起動時" + }, + "never": { + "message": "なし" + }, + "security": { + "message": "セキュリティ" + }, + "errorOccurred": { + "message": "エラーが発生しました" + }, + "emailRequired": { + "message": "Eメールアドレスは必須項目です。" + }, + "invalidEmail": { + "message": "無効なEメールアドレスです。" + }, + "masterPassRequired": { + "message": "マスターパスワードは必須です。" + }, + "masterPassLength": { + "message": "マスターパスワードは、少なくとも8文字以上で設定してください。" + }, + "masterPassDoesntMatch": { + "message": "マスターパスワードが一致しません。" + }, + "newAccountCreated": { + "message": "新しいアカウントを作成しました!今すぐログインできます。" + }, + "masterPassSent": { + "message": "あなたのマスターパスワードのヒントを記載したメールを送信しました。" + }, + "verificationCodeRequired": { + "message": "認証コードは必須項目です。" + }, + "invalidVerificationCode": { + "message": "認証コードが間違っています" + }, + "valueCopied": { + "message": "$VALUE$ をコピーしました", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "選択したアイテムをこのページで自動入力できませんでした。コピーして貼り付けてください。" + }, + "loggedOut": { + "message": "ログアウトしました" + }, + "loginExpired": { + "message": "ログインセッションの有効期限が切れています。" + }, + "logOutConfirmation": { + "message": "ログアウトしてもよろしいですか?" + }, + "yes": { + "message": "はい" + }, + "no": { + "message": "いいえ" + }, + "unexpectedError": { + "message": "予期せぬエラーが発生しました。" + }, + "nameRequired": { + "message": "名前は必須項目です。" + }, + "addedFolder": { + "message": "フォルダーを追加しました" + }, + "changeMasterPass": { + "message": "マスターパスワードの変更" + }, + "changeMasterPasswordConfirmation": { + "message": "マスターパスワードは bitwarden.com ウェブ保管庫で変更できます。ウェブサイトを開きますか?" + }, + "twoStepLoginConfirmation": { + "message": "2段階認証を使うと、ログイン時にセキュリティキーや認証アプリ、SMS、電話やメールでの認証を必要にすることでアカウントをさらに安全に出来ます。2段階認証は bitwarden.com ウェブ保管庫で有効化できます。ウェブサイトを開きますか?" + }, + "editedFolder": { + "message": "フォルダーを編集しました" + }, + "deleteFolderConfirmation": { + "message": "フォルダーを削除しますか?" + }, + "deletedFolder": { + "message": "フォルダーを削除しました" + }, + "gettingStartedTutorial": { + "message": "使い方のチュートリアル" + }, + "gettingStartedTutorialVideo": { + "message": "ブラウザの拡張機能を最大限に活用するための方法を学習できる、チュートリアルを見てください。" + }, + "syncingComplete": { + "message": "同期が完了しました" + }, + "syncingFailed": { + "message": "同期に失敗しました" + }, + "passwordCopied": { + "message": "パスワードをコピーしました" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "新しい URI" + }, + "addedItem": { + "message": "追加しました" + }, + "editedItem": { + "message": "編集しました" + }, + "deleteItemConfirmation": { + "message": "このアイテムを削除しますか?" + }, + "deletedItem": { + "message": "削除済みのアイテム" + }, + "overwritePassword": { + "message": "パスワードを上書き" + }, + "overwritePasswordConfirmation": { + "message": "現在のパスワードを上書きしてよろしいですか?" + }, + "overwriteUsername": { + "message": "ユーザー名を上書き" + }, + "overwriteUsernameConfirmation": { + "message": "現在のユーザー名を上書きしてもよろしいですか?" + }, + "searchFolder": { + "message": "フォルダーの検索" + }, + "searchCollection": { + "message": "コレクションの検索" + }, + "searchType": { + "message": "検索の種類" + }, + "noneFolder": { + "message": "フォルダーなし", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "ログイン情報追加の通知を無効化" + }, + "addLoginNotificationDesc": { + "message": "初めてログインしたとき保管庫にログイン情報を保存するよう「ログイン情報を追加」通知を自動的に表示します。" + }, + "dontShowCardsCurrentTab": { + "message": "タブページにカードを表示しない" + }, + "dontShowCardsCurrentTabDesc": { + "message": "保管庫にあるカードアイテムは自動入力しやすいよう「タブ」に表示されます。" + }, + "dontShowIdentitiesCurrentTab": { + "message": "タブページに ID を表示しない" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "保管庫にある ID アイテムは自動入力しやすいよう「タブ」に表示されます。" + }, + "clearClipboard": { + "message": "クリップボードの消去", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "選択した時間が経過した後、自動的にクリップボードを消去します。", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "このパスワードを Bitwarden に保存しますか?" + }, + "notificationAddSave": { + "message": "保存する" + }, + "disableChangedPasswordNotification": { + "message": "パスワードの変更通知を無効化" + }, + "disableChangedPasswordNotificationDesc": { + "message": "ウェブサイトでパスワードを変更したことを検出したとき、保管庫のパスワードを更新するために自動的に「パスワードの変更通知」を表示します。" + }, + "notificationChangeDesc": { + "message": "Bitwarden でこのパスワードを更新しますか?" + }, + "notificationChangeSave": { + "message": "今すぐ更新する" + }, + "disableContextMenuItem": { + "message": "コンテキストメニューオプションを無効化" + }, + "disableContextMenuItemDesc": { + "message": "コンテキストメニューのオプションで、現在のタブのウェブサイトのログイン情報やパスワード生成に素早くアクセスできます。" + }, + "defaultUriMatchDetection": { + "message": "デフォルトの URI 一致検出方法", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "自動入力などのアクションをする時に、デフォルトでどの方法で URI の一致を検出するか選択します。" + }, + "theme": { + "message": "テーマ" + }, + "themeDesc": { + "message": "アプリのテーマカラーを変更します。" + }, + "dark": { + "message": "ダーク", + "description": "Dark color" + }, + "light": { + "message": "ライト", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized ダーク", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "保管庫のエクスポート" + }, + "fileFormat": { + "message": "ファイル形式" + }, + "warning": { + "message": "警告", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "保管庫のエクスポートの確認" + }, + "exportWarningDesc": { + "message": "このエクスポートデータは暗号化されていない形式の保管庫データを含んでいます。メールなどのセキュリティ保護されていない方法で共有したり保管したりしないでください。使用した後はすぐに削除してください。" + }, + "encExportKeyWarningDesc": { + "message": "このエクスポートは、アカウントの暗号化キーを使用してデータを暗号化します。 暗号化キーをローテーションした場合は、このエクスポートファイルを復号することはできなくなるため、もう一度エクスポートする必要があります。" + }, + "encExportAccountWarningDesc": { + "message": "アカウント暗号化キーは各 Bitwarden ユーザーアカウントに固有であるため、暗号化されたエクスポートを別のアカウントにインポートすることはできません。" + }, + "exportMasterPassword": { + "message": "保管庫のデータをエクスポートするにはマスターパスワードを入力してください。" + }, + "shared": { + "message": "共有" + }, + "learnOrg": { + "message": "組織について学ぶ" + }, + "learnOrgConfirmation": { + "message": "Bitwarden は組織を使って保管庫アイテムを他の人と共有することができます。詳細は bitwarden.com ウェブサイトをご覧ください。" + }, + "moveToOrganization": { + "message": "組織に移動" + }, + "share": { + "message": "共有" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ を $ORGNAME$ に移動しました", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "このアイテムを移動する組織を選択してください。組織に移動すると、アイテムの所有権がその組織に移行します。 このアイテムが移動された後、あなたはこのアイテムの直接の所有者にはなりません。" + }, + "learnMore": { + "message": "さらに詳しく" + }, + "authenticatorKeyTotp": { + "message": "認証キー (TOTP)" + }, + "verificationCodeTotp": { + "message": "認証コード (TOTP)" + }, + "copyVerificationCode": { + "message": "認証コードのコピー" + }, + "attachments": { + "message": "添付ファイル" + }, + "deleteAttachment": { + "message": "添付ファイルの削除" + }, + "deleteAttachmentConfirmation": { + "message": "この添付ファイルを削除してよろしいですか?" + }, + "deletedAttachment": { + "message": "削除された添付ファイル" + }, + "newAttachment": { + "message": "添付ファイルの追加" + }, + "noAttachments": { + "message": "添付ファイルなし" + }, + "attachmentSaved": { + "message": "添付ファイルを保存しました。" + }, + "file": { + "message": "ファイル" + }, + "selectFile": { + "message": "ファイルを選択してください。" + }, + "maxFileSize": { + "message": "最大ファイルサイズ: 500 MB" + }, + "featureUnavailable": { + "message": "サービスが利用できません" + }, + "updateKey": { + "message": "暗号キーを更新するまでこの機能は使用できません。" + }, + "premiumMembership": { + "message": "プレミアム会員" + }, + "premiumManage": { + "message": "会員情報の管理" + }, + "premiumManageAlert": { + "message": "会員情報は bitwarden.com ウェブ保管庫で管理できます。ウェブサイトを開きますか?" + }, + "premiumRefresh": { + "message": "会員情報の更新" + }, + "premiumNotCurrentMember": { + "message": "あなたは現在プレミアム会員ではありません。" + }, + "premiumSignUpAndGet": { + "message": "プレミアム会員に登録すると以下の特典を得られます:" + }, + "ppremiumSignUpStorage": { + "message": "1GB の暗号化されたファイルストレージ" + }, + "ppremiumSignUpTwoStep": { + "message": "YubiKey、FIDO U2F、Duoなどの追加の2段階認証ログインオプション" + }, + "ppremiumSignUpReports": { + "message": "保管庫を安全に保つための、パスワードやアカウントの健全性、データ侵害に関するレポート" + }, + "ppremiumSignUpTotp": { + "message": "保管庫内での2段階認証コード生成" + }, + "ppremiumSignUpSupport": { + "message": "優先カスタマーサポート" + }, + "ppremiumSignUpFuture": { + "message": "将来のプレミアム機能すべて(詳細は近日公開予定!)" + }, + "premiumPurchase": { + "message": "プレミアム会員に加入" + }, + "premiumPurchaseAlert": { + "message": "プレミアム会員権は bitwarden.com ウェブ保管庫で購入できます。ウェブサイトを開きますか?" + }, + "premiumCurrentMember": { + "message": "あなたはプレミアム会員です!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden を支援いただき、ありがとうございます。" + }, + "premiumPrice": { + "message": "全部でなんと$PRICE$/年だけ!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "更新完了" + }, + "disableAutoTotpCopy": { + "message": "認証コードの自動コピーを無効化" + }, + "disableAutoTotpCopyDesc": { + "message": "ログイン情報に認証キーが添付されている場合、自動入力した時に認証コードが自動的にクリップボードへコピーされます。" + }, + "disableAutoBiometricsPrompt": { + "message": "起動時に生体認証のプロンプトを表示しない" + }, + "premiumRequired": { + "message": "プレミアム会員専用" + }, + "premiumRequiredDesc": { + "message": "この機能を使うにはプレミアム会員になってください。" + }, + "enterVerificationCodeApp": { + "message": "認証アプリに表示された6桁の認証コードを入力してください。" + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$に送信された6桁の認証コードを入力してください。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "$EMAIL$に認証コードを送信しました。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "情報を保存する" + }, + "sendVerificationCodeEmailAgain": { + "message": "確認コードをメールで再送" + }, + "useAnotherTwoStepMethod": { + "message": "他の2段階認証方法を使用" + }, + "insertYubiKey": { + "message": " YubiKey を USB ポートに挿入し、ボタンをタッチしてください。" + }, + "insertU2f": { + "message": "セキュリティキーを USB ポートに挿入し、ボタンがある場合はボタンをタッチしてください。" + }, + "webAuthnNewTab": { + "message": "WebAuthn 2FA 認証を開始するには、下のボタンをクリックして新しいタブを開き、新しいタブの指示に従ってください。" + }, + "webAuthnNewTabOpen": { + "message": "新しいタブを開く" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn の認証" + }, + "loginUnavailable": { + "message": "ログインできません。" + }, + "noTwoStepProviders": { + "message": "このアカウントは2段階認証が有効ですが、このブラウザに対応した2段階認証プロパイダが一つも設定されていません。" + }, + "noTwoStepProviders2": { + "message": "Chrome などの対応したブラウザを使うか、より幅広い端末に対応した認証プロパイダを追加してください。" + }, + "twoStepOptions": { + "message": "2段階認証オプション" + }, + "recoveryCodeDesc": { + "message": "すべての2段階認証プロパイダにアクセスできなくなったときは、リカバリーコードを使用するとアカウントの2段階認証を無効化できます。" + }, + "recoveryCodeTitle": { + "message": "リカバリーコード" + }, + "authenticatorAppTitle": { + "message": "認証アプリ" + }, + "authenticatorAppDesc": { + "message": "Authy や Google 認証システムなどの認証アプリで時限式の認証コードを生成してください。", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP セキュリティキー" + }, + "yubiKeyDesc": { + "message": "YubiKey を使ってアカウントにアクセスできます。 YubiKey 4、4 Nano、4C、NEOに対応しています。" + }, + "duoDesc": { + "message": "Duo Mobile アプリや SMS、電話や U2F セキュリティキーを使って Duo Security で認証します。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "組織の Duo Security を Duo Mobile アプリや SMS、電話、U2F セキュリティーキーを使用して認証します。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "アカウントにアクセスするに WebAuthn 対応のセキュリティキーを使用します。" + }, + "emailTitle": { + "message": "メールアドレス" + }, + "emailDesc": { + "message": "確認コードをメールにお送りします。" + }, + "selfHostedEnvironment": { + "message": "セルフホスティング環境" + }, + "selfHostedEnvironmentFooter": { + "message": "セルフホスティングしている Bitwarden のベース URL を指定してください。" + }, + "customEnvironment": { + "message": "カスタム環境" + }, + "customEnvironmentFooter": { + "message": "上級者向けです。各サービスのベース URL を個別に指定できます。" + }, + "baseUrl": { + "message": "サーバー URL" + }, + "apiUrl": { + "message": "API サーバー URL" + }, + "webVaultUrl": { + "message": "ウェブ保管庫サーバー URL" + }, + "identityUrl": { + "message": "ID サーバー URL" + }, + "notificationsUrl": { + "message": "通知サーバー URL" + }, + "iconsUrl": { + "message": "アイコンのサーバー URL" + }, + "environmentSaved": { + "message": "環境 URL を保存しました。" + }, + "enableAutoFillOnPageLoad": { + "message": "ページ読み込み時の自動入力を有効化" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "ページ読み込み時にログインフォームを検出したとき、ログイン情報を自動入力します。" + }, + "experimentalFeature": { + "message": "これは現在、実験的な機能です。自己責任で使用してください。" + }, + "defaultAutoFillOnPageLoad": { + "message": "ログインアイテムのデフォルトの自動入力設定" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "ページ読み込み時に自動入力を有効にすると、個々のログインアイテムの機能を有効または無効にできます。 これは個別に設定されていないログインアイテムに適用されるデフォルト設定です。" + }, + "itemAutoFillOnPageLoad": { + "message": "ページ読み込み時に自動入力する (オプションで有効な場合)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "デフォルト設定を使用" + }, + "autoFillOnPageLoadYes": { + "message": "ページ読み込み時に自動入力する" + }, + "autoFillOnPageLoadNo": { + "message": "ページ読み込み時に自動入力しない" + }, + "commandOpenPopup": { + "message": "ポップアップで保管庫を開く" + }, + "commandOpenSidebar": { + "message": "サイドバーで保管庫を開く" + }, + "commandAutofillDesc": { + "message": "現在のウェブサイトで前回使用されたログイン情報を自動入力します。" + }, + "commandGeneratePasswordDesc": { + "message": "ランダムなパスワードを生成してクリップボードにコピーします。" + }, + "commandLockVaultDesc": { + "message": "保管庫をロック" + }, + "privateModeWarning": { + "message": "プライベートモードのサポートは実験的であり、一部機能は制限されています。" + }, + "customFields": { + "message": "カスタムフィールド" + }, + "copyValue": { + "message": "値のコピー" + }, + "value": { + "message": "値" + }, + "newCustomField": { + "message": "新規カスタムフィールド" + }, + "dragToSort": { + "message": "ドラッグして並べ替え" + }, + "cfTypeText": { + "message": "テキスト" + }, + "cfTypeHidden": { + "message": "非表示" + }, + "cfTypeBoolean": { + "message": "真偽値" + }, + "cfTypeLinked": { + "message": "リンク済", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "リンクされた値", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "認証コードを確認するためにポップアップの外をクリックすると、このポップアップが閉じてしまいます。閉じてしまわないよう、新しいウインドウでこのポップアップを開きますか?" + }, + "popupU2fCloseMessage": { + "message": "このブラウザーでは U2F 要求をポップアップウインドウでは実行できません。U2F でログインできるよう、新しいウインドウで開き直しますか?" + }, + "disableFavicon": { + "message": "ウェブサイトアイコンの無効化" + }, + "disableFaviconDesc": { + "message": "保管庫のアイテム毎にウェブサイトのアイコンを表示します。" + }, + "disableBadgeCounter": { + "message": "バッジカウンターを無効化" + }, + "disableBadgeCounterDesc": { + "message": "保管庫にある、現在のページのログイン情報をバッジカウンターで表示します。" + }, + "cardholderName": { + "message": "カードの名義人名" + }, + "number": { + "message": "番号" + }, + "brand": { + "message": "ブランド" + }, + "expirationMonth": { + "message": "有効期限月" + }, + "expirationYear": { + "message": "有効期限年" + }, + "expiration": { + "message": "有効期限" + }, + "january": { + "message": "1月" + }, + "february": { + "message": "2月" + }, + "march": { + "message": "3月" + }, + "april": { + "message": "4月" + }, + "may": { + "message": "5月" + }, + "june": { + "message": "6月" + }, + "july": { + "message": "7月" + }, + "august": { + "message": "8月" + }, + "september": { + "message": "9月" + }, + "october": { + "message": "10月" + }, + "november": { + "message": "11月" + }, + "december": { + "message": "12月" + }, + "securityCode": { + "message": "セキュリティコード" + }, + "ex": { + "message": "例:" + }, + "title": { + "message": "敬称" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "名" + }, + "middleName": { + "message": "ミドルネーム" + }, + "lastName": { + "message": "姓" + }, + "fullName": { + "message": "フルネーム" + }, + "identityName": { + "message": "固有名" + }, + "company": { + "message": "会社名" + }, + "ssn": { + "message": "社会保障番号" + }, + "passportNumber": { + "message": "パスポート番号" + }, + "licenseNumber": { + "message": "免許証番号" + }, + "email": { + "message": "メールアドレス" + }, + "phone": { + "message": "電話番号" + }, + "address": { + "message": "住所" + }, + "address1": { + "message": "住所 1" + }, + "address2": { + "message": "住所 2" + }, + "address3": { + "message": "住所 3" + }, + "cityTown": { + "message": "市町村" + }, + "stateProvince": { + "message": "都道府県" + }, + "zipPostalCode": { + "message": "郵便番号" + }, + "country": { + "message": "国" + }, + "type": { + "message": "タイプ" + }, + "typeLogin": { + "message": "ログイン" + }, + "typeLogins": { + "message": "ログイン" + }, + "typeSecureNote": { + "message": "セキュアメモ" + }, + "typeCard": { + "message": "カード" + }, + "typeIdentity": { + "message": "ID" + }, + "passwordHistory": { + "message": "パスワードの履歴" + }, + "back": { + "message": "戻る" + }, + "collections": { + "message": "コレクション" + }, + "favorites": { + "message": "お気に入り" + }, + "popOutNewWindow": { + "message": "新しいウインドウで開く" + }, + "refresh": { + "message": "更新" + }, + "cards": { + "message": "カード" + }, + "identities": { + "message": "ID" + }, + "logins": { + "message": "ログイン" + }, + "secureNotes": { + "message": "セキュアメモ" + }, + "clear": { + "message": "消去する", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "パスワードが漏洩していないか確認する" + }, + "passwordExposed": { + "message": "このパスワードは過去に$VALUE$回漏洩したことがあるため、変更するべきです。", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "このパスワードは過去に漏洩したデータ内にはないため、安全であると思われます。" + }, + "baseDomain": { + "message": "ベースドメイン", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "ドメイン名", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "ホスト", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "完全一致" + }, + "startsWith": { + "message": "前方一致" + }, + "regEx": { + "message": "正規表現", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "一致検出方法", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "デフォルトの一致検出方法", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "オプションの切り替え" + }, + "toggleCurrentUris": { + "message": "現在の URI を切り替え", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "現在の URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "組織", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "種類" + }, + "allItems": { + "message": "全てのアイテム" + }, + "noPasswordsInList": { + "message": "表示するパスワードがありません" + }, + "remove": { + "message": "削除" + }, + "default": { + "message": "デフォルト" + }, + "dateUpdated": { + "message": "更新日", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "パスワード更新日", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "ロックオプションを「なし」に設定してもよろしいですか? ロックオプションを「なし」に設定すると、保管庫の暗号化キーが端末に保存されます。 このオプションを使用する場合は、端末を適切に保護しておく必要があります。" + }, + "noOrganizationsList": { + "message": "あなたはどの組織にも属していません。組織では他のユーザーとアイテムを安全に共有できます。" + }, + "noCollectionsInList": { + "message": "表示するコレクションがありません" + }, + "ownership": { + "message": "所有者" + }, + "whoOwnsThisItem": { + "message": "このアイテムは誰が所有していますか?" + }, + "strong": { + "message": "強力", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "良好", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "脆弱", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "脆弱なマスターパスワード" + }, + "weakMasterPasswordDesc": { + "message": "設定されたマスターパスワードの強度は脆弱です。Bitwarden アカウントを適切に保護するために、強力なマスターパスワード(またはパスフレーズ)を使用すべきです。本当にこのマスターパスワードを使用しますか?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "PIN でロック解除" + }, + "setYourPinCode": { + "message": "Bitwarden のロックを解除するための PIN コードを設定します。アプリから完全にログアウトすると、PIN 設定はリセットされます。" + }, + "pinRequired": { + "message": "PIN コードが必要です。" + }, + "invalidPin": { + "message": "PIN コードが間違っています。" + }, + "unlockWithBiometrics": { + "message": "生体認証でロック解除" + }, + "awaitDesktop": { + "message": "デスクトップからの確認待ち" + }, + "awaitDesktopDesc": { + "message": "ブラウザの生体認証を有効にするには、Bitwarden デスクトップアプリの生体認証を使用してください。" + }, + "lockWithMasterPassOnRestart": { + "message": "ブラウザー再起動時にマスターパスワードでロック" + }, + "selectOneCollection": { + "message": "最低でも一つのコレクションを選んでください。" + }, + "cloneItem": { + "message": "アイテムを複製" + }, + "clone": { + "message": "複製" + }, + "passwordGeneratorPolicyInEffect": { + "message": "一つ以上の組織のポリシーがパスワード生成の設定に影響しています。" + }, + "vaultTimeoutAction": { + "message": "保管庫タイムアウト時のアクション" + }, + "lock": { + "message": "ロック", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "ごみ箱", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "ごみ箱を検索" + }, + "permanentlyDeleteItem": { + "message": "アイテムを完全に削除" + }, + "permanentlyDeleteItemConfirmation": { + "message": "このアイテムを完全に削除してもよろしいですか?" + }, + "permanentlyDeletedItem": { + "message": "完全に削除されたアイテム" + }, + "restoreItem": { + "message": "アイテムをリストア" + }, + "restoreItemConfirmation": { + "message": "このアイテムをリストアしますか?" + }, + "restoredItem": { + "message": "リストアされたアイテム" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "ログアウトすると保管庫へのすべてのアクセスが制限され、タイムアウト期間後にオンライン認証が必要になります。 この設定を使用してもよろしいですか?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "タイムアウトアクションの確認" + }, + "autoFillAndSave": { + "message": "自動入力して保存" + }, + "autoFillSuccessAndSavedUri": { + "message": "アイテムを自動入力して URI を保存しました" + }, + "autoFillSuccess": { + "message": "アイテムを自動入力しました" + }, + "setMasterPassword": { + "message": "マスターパスワードを設定" + }, + "masterPasswordPolicyInEffect": { + "message": "組織が求めるマスターパスワードの要件:" + }, + "policyInEffectMinComplexity": { + "message": "複雑度は最低$SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "長さは最低$LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "大文字が最低1つ必要" + }, + "policyInEffectLowercase": { + "message": "小文字が最低1つ必要" + }, + "policyInEffectNumbers": { + "message": "数字が最低1つ必要" + }, + "policyInEffectSpecial": { + "message": "次の記号から1つ以上:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "新しいマスターパスワードは最低要件を満たしていません。" + }, + "acceptPolicies": { + "message": "以下に同意しチェックします:" + }, + "acceptPoliciesError": { + "message": "利用規約とプライバシーポリシーを確認してください。" + }, + "termsOfService": { + "message": "サービス利用規約" + }, + "privacyPolicy": { + "message": "プライバシーポリシー" + }, + "hintEqualsPassword": { + "message": "パスワードのヒントをパスワードと同じにすることはできません。" + }, + "ok": { + "message": "OK" + }, + "desktopSyncVerificationTitle": { + "message": "デスクトップ同期の検証" + }, + "desktopIntegrationVerificationText": { + "message": "デスクトップアプリにこの指紋が表示されていることを確認してください: " + }, + "desktopIntegrationDisabledTitle": { + "message": "ブラウザ統合が有効になっていません" + }, + "desktopIntegrationDisabledDesc": { + "message": "Bitwarden デスクトップアプリでブラウザ統合が有効になっていません。デスクトップアプリの設定で有効にしてください。" + }, + "startDesktopTitle": { + "message": "Bitwarden デスクトップアプリを起動" + }, + "startDesktopDesc": { + "message": "この機能を使用するには、Bitwarden デスクトップアプリを起動してください。" + }, + "errorEnableBiometricTitle": { + "message": "生体認証を有効にできません" + }, + "errorEnableBiometricDesc": { + "message": "デスクトップアプリによってアクションがキャンセルされました" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "デスクトップアプリが安全な通信チャネルを無効にしました。操作をやり直してください。" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "デスクトップ通信が中断されました" + }, + "nativeMessagingWrongUserDesc": { + "message": "デスクトップアプリは別のアカウントにログインしています。両方のアプリが同じアカウントにログインしているか確認してください。" + }, + "nativeMessagingWrongUserTitle": { + "message": "アカウントが一致しません" + }, + "biometricsNotEnabledTitle": { + "message": "生体認証が有効になっていません" + }, + "biometricsNotEnabledDesc": { + "message": "ブラウザ生体認証を利用するには、まず設定でデスクトップ生体認証を有効にする必要があります。" + }, + "biometricsNotSupportedTitle": { + "message": "生体認証に対応していません" + }, + "biometricsNotSupportedDesc": { + "message": "このデバイスではブラウザの生体認証に対応していません。" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "権限が提供されていません" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bitwarden デスクトップアプリとの通信許可がなければ、ブラウザ拡張機能で生体認証を利用できません。もう一度やり直してください。" + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "権限リクエストエラー" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "この操作はサイドバーでは行えません。ポップアップまたはポップアウトでやり直してください。" + }, + "personalOwnershipSubmitError": { + "message": "組織のポリシーにより、個人の保管庫へのアイテムの保存が制限されています。 所有権を組織に変更し、利用可能なコレクションから選択してください。" + }, + "personalOwnershipPolicyInEffect": { + "message": "組織のポリシーが所有者のオプションに影響を与えています。" + }, + "excludedDomains": { + "message": "除外するドメイン" + }, + "excludedDomainsDesc": { + "message": "Bitwarden はこれらのドメインのログイン情報を保存するよう尋ねません。変更を有効にするにはページを更新する必要があります。" + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ は有効なドメインではありません", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Send を検索", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Send を追加", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "テキスト" + }, + "sendTypeFile": { + "message": "ファイル" + }, + "allSends": { + "message": "すべての Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "最大アクセス数に達しました", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "有効期限切れ" + }, + "pendingDeletion": { + "message": "削除の保留中" + }, + "passwordProtected": { + "message": "パスワード保護あり" + }, + "copySendLink": { + "message": "Send リンクをコピー", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "パスワードを削除" + }, + "delete": { + "message": "削除" + }, + "removedPassword": { + "message": "パスワードを削除" + }, + "deletedSend": { + "message": "削除した Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send リンク", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "無効" + }, + "removePasswordConfirmation": { + "message": "パスワードを削除してもよろしいですか?" + }, + "deleteSend": { + "message": "Send を削除", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "この Send を削除してもよろしいですか?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send を編集", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "この Send の種類は何ですか?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "この Send を説明するわかりやすい名前", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "送信するファイル" + }, + "deletionDate": { + "message": "削除日時" + }, + "deletionDateDesc": { + "message": "Send は指定された日時に完全に削除されます。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "有効期限" + }, + "expirationDateDesc": { + "message": "設定されている場合、この Send へのアクセスは指定された日時に失効します。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1日" + }, + "days": { + "message": "$DAYS$日", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "カスタム" + }, + "maximumAccessCount": { + "message": "最大アクセス数" + }, + "maximumAccessCountDesc": { + "message": "設定されている場合、最大アクセス数に達するとユーザーはこの Send にアクセスできなくなります。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "必要に応じて、ユーザーがこの Send にアクセスするためのパスワードを要求します。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "この Send に関するプライベートメモ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "誰もアクセスできないように、この Send を無効にする", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "保存時にこの Send のリンクをクリップボードにコピーする", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "送信したいテキスト" + }, + "sendHideText": { + "message": "この Send のテキストをデフォルトで非表示にする", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "現在のアクセス数" + }, + "createSend": { + "message": "新しい Send を作成", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "新しいパスワード" + }, + "sendDisabled": { + "message": "Send 無効", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "組織のポリシーにより、既存の Send のみを削除できます。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "作成した Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "編集済みの Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "ファイルを選択するには、可能な場合サイドバーで拡張子を開くか、このバナーをクリックして新しいウィンドウにポップアップしてください。" + }, + "sendFirefoxFileWarning": { + "message": "Firefox を使用してファイルを選択するには、サイドバーで開くか、このバナーをクリックして新しいウィンドウで開いてください。" + }, + "sendSafariFileWarning": { + "message": "Safari を使用してファイルを選択するには、このバナーをクリックして新しいウィンドウで開いてください。" + }, + "sendFileCalloutHeader": { + "message": "はじめる前に" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "カレンダースタイルの日付ピッカーを使用するには", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "こちらをクリック", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "してください。", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "入力された有効期限は正しくありません。" + }, + "deletionDateIsInvalid": { + "message": "入力された削除日時は正しくありません。" + }, + "expirationDateAndTimeRequired": { + "message": "有効期限は必須です。" + }, + "deletionDateAndTimeRequired": { + "message": "削除日時は必須です。" + }, + "dateParsingError": { + "message": "削除と有効期限の保存中にエラーが発生しました。" + }, + "hideEmail": { + "message": "メールアドレスを受信者に表示しない" + }, + "sendOptionsPolicyInEffect": { + "message": "一つ以上の組織ポリシーが Send の設定に影響しています。" + }, + "passwordPrompt": { + "message": "マスターパスワードの再要求" + }, + "passwordConfirmation": { + "message": "マスターパスワードの確認" + }, + "passwordConfirmationDesc": { + "message": "この操作は保護されています。続行するには、確認のためにマスターパスワードを再入力してください。" + }, + "emailVerificationRequired": { + "message": "メールアドレスの確認が必要です" + }, + "emailVerificationRequiredDesc": { + "message": "この機能を使用するにはメールアドレスを確認する必要があります。ウェブ保管庫でメールアドレスを確認できます。" + }, + "updatedMasterPassword": { + "message": "マスターパスワードを更新しました" + }, + "updateMasterPassword": { + "message": "マスターパスワードを更新しました" + }, + "updateMasterPasswordWarning": { + "message": "マスターパスワードは最近組織の管理者によって変更されました。保管庫にアクセスするには、今すぐ更新する必要があります。 続行すると現在のセッションからログアウトし、再度ログインする必要があります。 他のデバイスでのアクティブなセッションは、最大1時間アクティブになり続けることがあります。" + }, + "resetPasswordPolicyAutoEnroll": { + "message": "自動登録" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "この組織には自動的にパスワードリセットに登録するポリシーがあります。登録すると、組織の管理者はマスターパスワードを変更できます。" + }, + "selectFolder": { + "message": "フォルダーを選択..." + }, + "ssoCompleteRegistration": { + "message": "SSO ログインを完了するには、保管庫にアクセス・保護するためのマスターパスワードを設定してください。" + }, + "hours": { + "message": "時間" + }, + "minutes": { + "message": "分" + }, + "vaultTimeoutPolicyInEffect": { + "message": "あなたの組織ポリシーは保管庫のタイムアウトに影響を与えています。最大保管庫のタイムアウト時間は $HOURS$ 時間 $MINUTES$ 分です。", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "保管庫のタイムアウトが組織によって設定された制限を超えています。" + }, + "vaultExportDisabled": { + "message": "保管庫のエクスポートは無効です" + }, + "personalVaultExportPolicyInEffect": { + "message": "1 つまたは複数の組織ポリシーにより、個人の保管庫をエクスポートできません。" + }, + "copyCustomFieldNameInvalidElement": { + "message": "有効なフォーム要素を識別できませんでした。代わりに HTML を調べてみてください。" + }, + "copyCustomFieldNameNotUnique": { + "message": "一意の識別子が見つかりませんでした。" + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ は自己ホストの鍵サーバで SSO を使用しています。この組織のメンバーのログインにマスターパスワードは必要ありません。", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "組織から脱退する" + }, + "removeMasterPassword": { + "message": "マスターパスワードを削除する" + }, + "removedMasterPassword": { + "message": "マスターパスワードを削除しました。" + }, + "leaveOrganizationConfirmation": { + "message": "本当にこの組織から脱退しますか?" + }, + "leftOrganization": { + "message": "組織から脱退しました。" + }, + "toggleCharacterCount": { + "message": "文字カウントを切り替える" + }, + "sessionTimeout": { + "message": "セッションがタイムアウトしました。もう一度ログインしてください。" + }, + "exportingPersonalVaultTitle": { + "message": "個人保管庫のエクスポート" + }, + "exportingPersonalVaultDescription": { + "message": "$EMAIL$ に関連付けられた個人用保管庫アイテムのみがエクスポートされます。組織用保管庫アイテムは含まれません。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "エラー" + }, + "regenerateUsername": { + "message": "ユーザー名を再生成" + }, + "generateUsername": { + "message": "ユーザー名を生成" + }, + "usernameType": { + "message": "ユーザー名の種類" + }, + "plusAddressedEmail": { + "message": "プラス付きのメールアドレス", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "メールプロバイダのエイリアス機能を使用します。" + }, + "catchallEmail": { + "message": "キャッチオールメール" + }, + "catchallEmailDesc": { + "message": "ドメインに設定されたキャッチオール受信トレイを使用します。" + }, + "random": { + "message": "ランダム" + }, + "randomWord": { + "message": "ランダムな単語" + }, + "websiteName": { + "message": "ウェブサイト名" + }, + "whatWouldYouLikeToGenerate": { + "message": "何を生成しますか?" + }, + "passwordType": { + "message": "パスワードの種類" + }, + "service": { + "message": "サービス" + } +} diff --git a/apps/browser/src/_locales/ka/messages.json b/apps/browser/src/_locales/ka/messages.json new file mode 100644 index 0000000000..ca6395e86d --- /dev/null +++ b/apps/browser/src/_locales/ka/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "ანგარიშის შექმნა" + }, + "login": { + "message": "ავტორიზაცია" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "გაუქმება" + }, + "close": { + "message": "დახურვა" + }, + "submit": { + "message": "დადასტურება" + }, + "emailAddress": { + "message": "ელ-ფოსტა" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "My Vault" + }, + "tools": { + "message": "ხელსაწყოები" + }, + "settings": { + "message": "პარამეტრები" + }, + "currentTab": { + "message": "Current Tab" + }, + "copyPassword": { + "message": "პაროლის კოპირება" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "მომხმარებლის სახელის კოპირება" + }, + "copyNumber": { + "message": "Copy Number" + }, + "copySecurityCode": { + "message": "უსაფრთხოების კოდის კოპირება" + }, + "autoFill": { + "message": "თვითშევსება" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "ავტორიზაციის დამატება" + }, + "addItem": { + "message": "Add Item" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "გაგრძელება" + }, + "sendVerificationCode": { + "message": "ვერიფიკაციის კოდის გაგზავნა საკუთარ მეილზე" + }, + "sendCode": { + "message": "კოდის გაგზავნა" + }, + "codeSent": { + "message": "კოდი გაიგზავნა" + }, + "verificationCode": { + "message": "ვერიფიკაციის კოდი" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "ანგარიში" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "ორსაფეხურიანი ავტორიზაცია" + }, + "logOut": { + "message": "გამოსვლა" + }, + "about": { + "message": "შესახებ" + }, + "version": { + "message": "ვერსია" + }, + "save": { + "message": "შენახვა" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "საქაღალდის დამატება" + }, + "name": { + "message": "სახელი" + }, + "editFolder": { + "message": "საქაღალდის რედაქტირება" + }, + "deleteFolder": { + "message": "საქაღალდის წაშლა" + }, + "folders": { + "message": "საქაღალდეები" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "დახმარება & გამოხმაურება" + }, + "sync": { + "message": "სინქრონიზაცია" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "მონიშვნა" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "პარამეტრები" + }, + "length": { + "message": "სიგრძე" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "სიტყვათა რაოდენობა" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "დიდი ასოთი აღნიშვნა", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "შეცვლა" + }, + "view": { + "message": "ნახვა" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "მომხმარებლის სახელი" + }, + "password": { + "message": "პაროლი" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "რჩეული" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit Item" + }, + "folder": { + "message": "საქაღალდე" + }, + "deleteItem": { + "message": "Delete Item" + }, + "viewItem": { + "message": "View Item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "ვებგვერდი" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "მართვა" + }, + "other": { + "message": "სხვა" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "გახსნა" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "დაუყონებლივ" + }, + "tenSeconds": { + "message": "10 წამი" + }, + "twentySeconds": { + "message": "20 წამი" + }, + "thirtySeconds": { + "message": "30 წამი" + }, + "oneMinute": { + "message": "1 წუთი" + }, + "twoMinutes": { + "message": "2 წუთი" + }, + "fiveMinutes": { + "message": "5 წუთი" + }, + "fifteenMinutes": { + "message": "15 წუთი" + }, + "thirtyMinutes": { + "message": "30 წუთი" + }, + "oneHour": { + "message": "1 საათი" + }, + "fourHours": { + "message": "4 საათი" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Browser Restart" + }, + "never": { + "message": "არასოდეს" + }, + "security": { + "message": "უსაფრთხოება" + }, + "errorOccurred": { + "message": "დაფიქსირდა შეცდომა" + }, + "emailRequired": { + "message": "ელექტრონული ფოსტის მისამართი აუცილებელია." + }, + "invalidEmail": { + "message": "არასწორი ელექტრო ფოსტის მისამართი." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "ვერიფიკაციის კოდი აუცილებელია." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "არა" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "სახელი სავალდებულოა." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Save" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Update" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/km/messages.json b/apps/browser/src/_locales/km/messages.json new file mode 100644 index 0000000000..c0fc9f75c3 --- /dev/null +++ b/apps/browser/src/_locales/km/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "login": { + "message": "Log In" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "Cancel" + }, + "close": { + "message": "Close" + }, + "submit": { + "message": "Submit" + }, + "emailAddress": { + "message": "Email Address" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "My Vault" + }, + "tools": { + "message": "Tools" + }, + "settings": { + "message": "Settings" + }, + "currentTab": { + "message": "Current Tab" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number" + }, + "copySecurityCode": { + "message": "Copy Security Code" + }, + "autoFill": { + "message": "Auto-fill" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "Add a Login" + }, + "addItem": { + "message": "Add Item" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "Continue" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "logOut": { + "message": "Log Out" + }, + "about": { + "message": "About" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Save" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Add Folder" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Edit Folder" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "folders": { + "message": "Folders" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "Help & Feedback" + }, + "sync": { + "message": "Sync" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "Select" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Length" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "View" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favorite" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit Item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Delete Item" + }, + "viewItem": { + "message": "View Item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "Manage" + }, + "other": { + "message": "Other" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Browser Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "errorOccurred": { + "message": "An error has occurred" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "Name is required." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Save" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Update" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/kn/messages.json b/apps/browser/src/_locales/kn/messages.json new file mode 100644 index 0000000000..72a2a4a355 --- /dev/null +++ b/apps/browser/src/_locales/kn/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "ಬಿಟ್ವಾರ್ಡೆನ್" + }, + "extName": { + "message": "ಬಿಟ್‌ವಾರ್ಡೆನ್ - ಉಚಿತ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕ", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಿಗೆ ಸುರಕ್ಷಿತ ಮತ್ತು ಉಚಿತ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕ.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "ನಿಮ್ಮ ಸುರಕ್ಷಿತ ವಾಲ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಲಾಗ್ ಇನ್ ಮಾಡಿ ಅಥವಾ ಹೊಸ ಖಾತೆಯನ್ನು ರಚಿಸಿ." + }, + "createAccount": { + "message": "ಖಾತೆ ತೆರೆ" + }, + "login": { + "message": "ಲಾಗಿನ್" + }, + "enterpriseSingleSignOn": { + "message": "ಎಂಟರ್‌ಪ್ರೈಸ್ ಏಕ ಸೈನ್-ಆನ್" + }, + "cancel": { + "message": "ರದ್ದು" + }, + "close": { + "message": "ಮುಚ್ಚಿ" + }, + "submit": { + "message": "ಒಪ್ಪಿಸು" + }, + "emailAddress": { + "message": "ಇಮೇಲ್ ವಿಳಾಸ" + }, + "masterPass": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್" + }, + "masterPassDesc": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಬಳಸುವ ಪಾಸ್ವರ್ಡ್ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಆಗಿದೆ. ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನೀವು ಮರೆಯದಿರುವುದು ಬಹಳ ಮುಖ್ಯ. ನೀವು ಅದನ್ನು ಮರೆತ ಸಂದರ್ಭದಲ್ಲಿ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಪಡೆಯಲು ಯಾವುದೇ ಮಾರ್ಗವಿಲ್ಲ." + }, + "masterPassHintDesc": { + "message": "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನೀವು ಮರೆತರೆ ಅದನ್ನು ನೆನಪಿಟ್ಟುಕೊಳ್ಳಲು ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಸುಳಿವು ನಿಮಗೆ ಸಹಾಯ ಮಾಡುತ್ತದೆ." + }, + "reTypeMasterPass": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಮರು-ಟೈಪ್ ಮಾಡಿ" + }, + "masterPassHint": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಸುಳಿವು (ಐಚ್ಛಿಕ)" + }, + "tab": { + "message": "ಟ್ಯಾಬ್" + }, + "myVault": { + "message": "ನನ್ನ ವಾಲ್ಟ್" + }, + "tools": { + "message": "ಉಪಕರಣ" + }, + "settings": { + "message": "ಸೆಟ್ಟಿಂಗ್‍ಗಳು\n" + }, + "currentTab": { + "message": "ಪ್ರಸ್ತುತ ಟ್ಯಾಬ್" + }, + "copyPassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ನಕಲಿಸಿ" + }, + "copyNote": { + "message": "ಟಿಪ್ಪಣಿ ನಕಲಿಸಿ" + }, + "copyUri": { + "message": "URI ಅನ್ನು ನಕಲಿಸಿ" + }, + "copyUsername": { + "message": "ಬಳಕೆಹೆಸರು ನಕಲಿಸು" + }, + "copyNumber": { + "message": "ನಕಲು ಸಂಖ್ಯೆ" + }, + "copySecurityCode": { + "message": "ಭದ್ರತಾ ಕೋಡ್ ಅನ್ನು ನಕಲಿಸಿ" + }, + "autoFill": { + "message": "ಸ್ವಯಂ ಭರ್ತಿ" + }, + "generatePasswordCopied": { + "message": "ಪಾಸ್ವರ್ಡ್ ರಚಿಸಿ (ನಕಲಿಸಲಾಗಿದೆ)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "ಹೊಂದಾಣಿಕೆಯ ಲಾಗಿನ್‌ಗಳು ಇಲ್ಲ." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "ಪ್ರಸ್ತುತ ಬ್ರೌಸರ್ ಟ್ಯಾಬ್‌ಗಾಗಿ ಸ್ವಯಂ ಭರ್ತಿ ಮಾಡಲು ಯಾವುದೇ ಲಾಗಿನ್‌ಗಳು ಲಭ್ಯವಿಲ್ಲ." + }, + "addLogin": { + "message": "ಲಾಗಿನ್ ಸೇರಿಸಿ" + }, + "addItem": { + "message": "ಐಟಂ ಸೇರಿಸಿ" + }, + "passwordHint": { + "message": "ಪಾಸ್ವರ್ಡ್ ಸುಳಿವು" + }, + "enterEmailToGetHint": { + "message": "ವಿಸ್ತರಣೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಮೆನುವಿನಲ್ಲಿರುವ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಐಕಾನ್ ಟ್ಯಾಪ್ ಮಾಡಿ." + }, + "getMasterPasswordHint": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಸುಳಿವನ್ನು ಪಡೆಯಿರಿ" + }, + "continue": { + "message": "ಮುಂದುವರಿಸಿ" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "ಪರಿಶೀಲನಾ ಕೋಡ್‌ಗಳು" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "ಖಾತೆ" + }, + "changeMasterPassword": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಿ" + }, + "fingerprintPhrase": { + "message": "ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಫ್ರೇಸ್", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "ನಿಮ್ಮ ಖಾತೆಯ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ನುಡಿಗಟ್ಟು", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "ಎರಡು ಹಂತದ ಲಾಗಿನ್" + }, + "logOut": { + "message": "ಲಾಗ್ ಔಟ್" + }, + "about": { + "message": "ಬಗ್ಗೆ" + }, + "version": { + "message": "ಆವೃತ್ತಿ" + }, + "save": { + "message": "ಉಳಿಸಿ" + }, + "move": { + "message": "ಸರಿಸಿ" + }, + "addFolder": { + "message": "ಫೋಲ್ಡರ್ ಸೇರಿಸಿ" + }, + "name": { + "message": "ಹೆಸರು" + }, + "editFolder": { + "message": "ಫೋಲ್ಡರ್ ಸಂಪಾದಿಸಿ" + }, + "deleteFolder": { + "message": "ಫೋಲ್ಡರ್ ಅಳಿಸಿ" + }, + "folders": { + "message": "ಫೋಲ್ಡರ್‌ಗಳು" + }, + "noFolders": { + "message": "ಪಟ್ಟಿ ಮಾಡಲು ಯಾವುದೇ ಫೋಲ್ಡರ್‌ಗಳಿಲ್ಲ." + }, + "helpFeedback": { + "message": "ಸಹಾಯ ಪ್ರತಿಕ್ರಿಯೆ\n" + }, + "sync": { + "message": "ಸಿಂಕ್" + }, + "syncVaultNow": { + "message": "ವಾಲ್ಟ್ ಅನ್ನು ಈಗ ಸಿಂಕ್ ಮಾಡಿ" + }, + "lastSync": { + "message": "ಕೊನೆಯ ಸಿಂಕ್" + }, + "passGen": { + "message": "ಪಾಸ್ವರ್ಡ್ ಜನರೇಟರ್" + }, + "generator": { + "message": "ಜನರೇಟರ್", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "ನಿಮ್ಮ ಲಾಗಿನ್‌ಗಳಿಗಾಗಿ ಬಲವಾದ, ಅನನ್ಯ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ರಚಿಸಿ." + }, + "bitWebVault": { + "message": "ಬಿಟ್ವಾರ್ಡೆನ್ ವೆಬ್ ವಾಲ್ಟ್" + }, + "importItems": { + "message": "ವಸ್ತುಗಳನ್ನು ಆಮದು ಮಾಡಿ" + }, + "select": { + "message": "ಆಯ್ಕೆಮಾಡಿ" + }, + "generatePassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ರಚಿಸಿ" + }, + "regeneratePassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಪುನರುತ್ಪಾದಿಸಿ" + }, + "options": { + "message": "ಆಯ್ಕೆಗಳು" + }, + "length": { + "message": "ಉದ್ದ" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "ಪದಗಳ ಸಂಖ್ಯೆ" + }, + "wordSeparator": { + "message": "ಪದ ವಿಭಜಕ" + }, + "capitalize": { + "message": "ದೊಡ್ಡಕ್ಷರ ಮಾಡಿ", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ" + }, + "minNumbers": { + "message": "ಕನಿಷ್ಠ ಸಂಖ್ಯೆಗಳು" + }, + "minSpecial": { + "message": "ಕನಿಷ್ಠ ವಿಶೇಷ" + }, + "avoidAmbChar": { + "message": "ಅಸ್ಪಷ್ಟ ಅಕ್ಷರಗಳನ್ನು ತಪ್ಪಿಸಿ" + }, + "searchVault": { + "message": "ವಾಲ್ಟ್ ಹುಡುಕಿ" + }, + "edit": { + "message": "ಎಡಿಟ್" + }, + "view": { + "message": "ವೀಕ್ಷಣೆ" + }, + "noItemsInList": { + "message": "ಪಟ್ಟಿ ಮಾಡಲು ಯಾವುದೇ ಐಟಂಗಳಿಲ್ಲ." + }, + "itemInformation": { + "message": "ಐಟಂ ಮಾಹಿತಿ" + }, + "username": { + "message": "ಬಳಕೆದಾರ ಹೆಸರು" + }, + "password": { + "message": "ಪಾಸ್ವರ್ಡ್" + }, + "passphrase": { + "message": "ಪಾಸ್ಫ್ರೇಸ್" + }, + "favorite": { + "message": "ಮೆಚ್ಚಿನ" + }, + "notes": { + "message": "ಟಿಪ್ಪಣಿಗಳು" + }, + "note": { + "message": "ಟಿಪ್ಪಣಿ" + }, + "editItem": { + "message": "ವಸ್ತುಗಳನ್ನು ಸಂಪಾದಿಸಿ" + }, + "folder": { + "message": "ಫೋಲ್ಡರ್" + }, + "deleteItem": { + "message": "ಐಟಂ ಅಳಿಸಿ" + }, + "viewItem": { + "message": "ಐಟಂ ವೀಕ್ಷಿಸಿ" + }, + "launch": { + "message": "ಶುರು" + }, + "website": { + "message": "ಜಾಲತಾಣ" + }, + "toggleVisibility": { + "message": "ಗೋಚರತೆಯನ್ನು ಟಾಗಲ್ ಮಾಡಿ" + }, + "manage": { + "message": "ವ್ಯವಸ್ಥಾಪಕ" + }, + "other": { + "message": "ಇತರೆ" + }, + "rateExtension": { + "message": "ವಿಸ್ತರಣೆಯನ್ನು ರೇಟ್ ಮಾಡಿ" + }, + "rateExtensionDesc": { + "message": "ಉತ್ತಮ ವಿಮರ್ಶೆಯೊಂದಿಗೆ ನಮಗೆ ಸಹಾಯ ಮಾಡಲು ದಯವಿಟ್ಟು ಪರಿಗಣಿಸಿ!" + }, + "browserNotSupportClipboard": { + "message": "ನಿಮ್ಮ ವೆಬ್ ಬ್ರೌಸರ್ ಸುಲಭವಾದ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ನಕಲು ಮಾಡುವುದನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಬದಲಿಗೆ ಅದನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ನಕಲಿಸಿ." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಲಾಕ್ ಆಗಿದೆ. ಮುಂದುವರೆಯಲು ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ." + }, + "unlock": { + "message": "ಅನ್‌ಲಾಕ್ ಮಾಡಿ" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ನಲ್ಲಿ $EMAIL$ಆಗಿ ಲಾಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆ.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "ಅಮಾನ್ಯ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್" + }, + "vaultTimeout": { + "message": "ವಾಲ್ಟ್ ಕಾಲಾವಧಿ" + }, + "lockNow": { + "message": "ಈಗ ಲಾಕ್ ಮಾಡಿ" + }, + "immediately": { + "message": "ತಕ್ಷಣ" + }, + "tenSeconds": { + "message": "೧೦ ಕ್ಷಣ" + }, + "twentySeconds": { + "message": "೨0 ಸೆಕೆಂಡುಗಳು" + }, + "thirtySeconds": { + "message": "೩೦ ಕ್ಷಣ" + }, + "oneMinute": { + "message": "೧ ನಿಮಿಷ" + }, + "twoMinutes": { + "message": "೨ ನಿಮಿಷಗಳು" + }, + "fiveMinutes": { + "message": "೫ ನಿಮಿಷಗಳು" + }, + "fifteenMinutes": { + "message": "೧೫ ನಿಮಿಷಗಳು" + }, + "thirtyMinutes": { + "message": "30 ನಿಮಿಷಗಳು" + }, + "oneHour": { + "message": "೧ ಗಂಟೆ" + }, + "fourHours": { + "message": "೪ ಗಂಟೆಗಳು" + }, + "onLocked": { + "message": "ಸಿಸ್ಟಮ್ ಲಾಕ್‌ನಲ್ಲಿ" + }, + "onRestart": { + "message": "ಬ್ರೌಸರ್ ಮರುಪ್ರಾರಂಭದಲ್ಲಿ" + }, + "never": { + "message": "ಇಲ್ಲವೇ ಇಲ್ಲ" + }, + "security": { + "message": "ಭದ್ರತೆ" + }, + "errorOccurred": { + "message": "ದೋಷ ಸಂಭವಿಸಿದೆ" + }, + "emailRequired": { + "message": "ಇಮೇಲ್ ವಿಳಾಸದ ಅಗತ್ಯವಿದೆ." + }, + "invalidEmail": { + "message": "ಅಮಾನ್ಯ ಇಮೇಲ್ ವಿಳಾಸ." + }, + "masterPassRequired": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಅಗತ್ಯವಿದೆ." + }, + "masterPassLength": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಕನಿಷ್ಠ 8 ಅಕ್ಷರಗಳಷ್ಟು ಉದ್ದವಾಗಿರಬೇಕು." + }, + "masterPassDoesntMatch": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ದೃಢೀಕರಣವು ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ." + }, + "newAccountCreated": { + "message": "ನಿಮ್ಮ ಹೊಸ ಖಾತೆಯನ್ನು ರಚಿಸಲಾಗಿದೆ! ನೀವು ಈಗ ಲಾಗ್ ಇನ್ ಮಾಡಬಹುದು." + }, + "masterPassSent": { + "message": "ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಸುಳಿವಿನೊಂದಿಗೆ ನಾವು ನಿಮಗೆ ಇಮೇಲ್ ಕಳುಹಿಸಿದ್ದೇವೆ." + }, + "verificationCodeRequired": { + "message": "ಪರಿಶೀಲನೆ ಕೋಡ್ ಅಗತ್ಯವಿದೆ." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ ನಕಲಿಸಲಾಗಿದೆ", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "ಈ ಪುಟದಲ್ಲಿ ಆಯ್ದ ಐಟಂ ಅನ್ನು ಸ್ವಯಂ ಭರ್ತಿ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ಬದಲಿಗೆ ಮಾಹಿತಿಯನ್ನು ನಕಲಿಸಿ ಮತ್ತು ಅಂಟಿಸಿ." + }, + "loggedOut": { + "message": "ಲಾಗ್ ಔಟ್" + }, + "loginExpired": { + "message": "ನಿಮ್ಮ ಲಾಗಿನ್ ಸೆಷನ್ ಅವಧಿ ಮೀರಿದೆ." + }, + "logOutConfirmation": { + "message": "ಲಾಗ್ ಔಟ್ ಮಾಡಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "yes": { + "message": "ಹೌದು" + }, + "no": { + "message": "ಇಲ್ಲ" + }, + "unexpectedError": { + "message": "ಅನಿರೀಕ್ಷಿತ ದೋಷ ಸಂಭವಿಸಿದೆ." + }, + "nameRequired": { + "message": "ಹೆಸರೊಂದು ಅಗತ್ಯವಿದೆ." + }, + "addedFolder": { + "message": "ಫೋಲ್ಡರ್ ಸೇರಿಸಿ" + }, + "changeMasterPass": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಿ" + }, + "changeMasterPasswordConfirmation": { + "message": "ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನೀವು bitwarden.com ವೆಬ್ ವಾಲ್ಟ್‌ನಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "twoStepLoginConfirmation": { + "message": "ಭದ್ರತಾ ಕೀ, ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್, ಎಸ್‌ಎಂಎಸ್, ಫೋನ್ ಕರೆ ಅಥವಾ ಇಮೇಲ್‌ನಂತಹ ಮತ್ತೊಂದು ಸಾಧನದೊಂದಿಗೆ ನಿಮ್ಮ ಲಾಗಿನ್ ಅನ್ನು ಪರಿಶೀಲಿಸುವ ಅಗತ್ಯವಿರುವ ಎರಡು ಹಂತದ ಲಾಗಿನ್ ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಹೆಚ್ಚು ಸುರಕ್ಷಿತಗೊಳಿಸುತ್ತದೆ. ಬಿಟ್ವಾರ್ಡೆನ್.ಕಾಮ್ ವೆಬ್ ವಾಲ್ಟ್ನಲ್ಲಿ ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "editedFolder": { + "message": "ಫೋಲ್ಡರ್ ತಿದ್ದಲಾಗಿದೆ" + }, + "deleteFolderConfirmation": { + "message": "ನೀವು ಈ ಕಡತಕೋಶವನ್ನು ಖಚಿತವಾಗಿಯೂ ಅಳಿಸಬಯಸುವಿರಾ?" + }, + "deletedFolder": { + "message": "ಫೋಲ್ಡರ್ ಅಳಿಸಿ" + }, + "gettingStartedTutorial": { + "message": "ಟ್ಯುಟೋರಿಯಲ್ ಪ್ರಾರಂಭಿಸುವುದು" + }, + "gettingStartedTutorialVideo": { + "message": "ಬ್ರೌಸರ್ ವಿಸ್ತರಣೆಯಿಂದ ಹೆಚ್ಚಿನದನ್ನು ಪಡೆಯುವುದು ಹೇಗೆ ಎಂದು ತಿಳಿಯಲು ನಮ್ಮ ಪ್ರಾರಂಭಿಕ ಟ್ಯುಟೋರಿಯಲ್ ವೀಕ್ಷಿಸಿ." + }, + "syncingComplete": { + "message": "ಒಡವಾಗುನಂಟು ಪೂರ್ಣಗೊಂಡಿದೆ" + }, + "syncingFailed": { + "message": "ಸಿಂಕ್ ವಿಫಲಗೊಂಡಿದೆ" + }, + "passwordCopied": { + "message": "ಪಾಸ್ವರ್ಡ್ ನಕಲಿಸಲಾಗಿದೆ" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "ಯುಆರ್ಐ $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "ಹೊಸ ಯುಆರ್ಐ" + }, + "addedItem": { + "message": "ಐಟಂ ಸೇರಿಸಲಾಗಿದೆ" + }, + "editedItem": { + "message": "ಐಟಂ ಸಂಪಾದಿಸಲಾಗಿದೆ" + }, + "deleteItemConfirmation": { + "message": "ನೀವು ನಿಜವಾಗಿಯೂ ಅನುಪಯುಕ್ತಕ್ಕೆ ಕಳುಹಿಸಲು ಬಯಸುವಿರಾ?" + }, + "deletedItem": { + "message": "ಐಟಂ ಅನ್ನು ಅನುಪಯುಕ್ತಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿದೆ" + }, + "overwritePassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಬದಲಿಸಿ" + }, + "overwritePasswordConfirmation": { + "message": "ಪ್ರಸ್ತುತ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ತಿದ್ದಿಬರೆಯಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "ಫೋಲ್ಡರ್ ಹುಡುಕಿ" + }, + "searchCollection": { + "message": "ಸಂಗ್ರಹಣೆ ಹುಡುಕಿ" + }, + "searchType": { + "message": "ಹುಡುಕಾಟ ಪ್ರಕಾರ" + }, + "noneFolder": { + "message": "ಫೋಲ್ಡರ್ ಇಲ್ಲ", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "ಲಾಗಿನ್ ಅಧಿಸೂಚನೆಯನ್ನು ಸೇರಿಸಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + }, + "addLoginNotificationDesc": { + "message": "\"ಲಾಗಿನ್ ಅಧಿಸೂಚನೆಯನ್ನು ಸೇರಿಸಿ\" ನೀವು ಮೊದಲ ಬಾರಿಗೆ ಪ್ರವೇಶಿಸಿದಾಗಲೆಲ್ಲಾ ಹೊಸ ಲಾಗಿನ್‌ಗಳನ್ನು ನಿಮ್ಮ ವಾಲ್ಟ್‌ಗೆ ಉಳಿಸಲು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕೇಳುತ್ತದೆ." + }, + "dontShowCardsCurrentTab": { + "message": "ಟ್ಯಾಬ್ ಪುಟದಲ್ಲಿ ಕಾರ್ಡ್‌ಗಳನ್ನು ತೋರಿಸಬೇಡಿ" + }, + "dontShowCardsCurrentTabDesc": { + "message": "ಸ್ವಯಂ-ಭರ್ತಿ ಸುಲಭ ಪ್ರವೇಶಕ್ಕಾಗಿ ನಿಮ್ಮ ವಾಲ್ಟ್‌ನಿಂದ ಕಾರ್ಡ್ ವಸ್ತುಗಳನ್ನು 'ಪ್ರಸ್ತುತ ಟ್ಯಾಬ್' ಪುಟದಲ್ಲಿ ಪಟ್ಟಿ ಮಾಡಲಾಗಿದೆ." + }, + "dontShowIdentitiesCurrentTab": { + "message": "ಟ್ಯಾಬ್ ಪುಟದಲ್ಲಿ ಗುರುತುಗಳನ್ನು ತೋರಿಸಬೇಡಿ" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "ಸ್ವಯಂ-ಭರ್ತಿ ಸುಲಭ ಪ್ರವೇಶಕ್ಕಾಗಿ ನಿಮ್ಮ ವಾಲ್ಟ್‌ನಿಂದ ಗುರುತಿನ ವಸ್ತುಗಳನ್ನು 'ಪ್ರಸ್ತುತ ಟ್ಯಾಬ್' ಪುಟದಲ್ಲಿ ಪಟ್ಟಿ ಮಾಡಲಾಗಿದೆ." + }, + "clearClipboard": { + "message": "ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ತೆರವುಗೊಳಿಸಿ", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "ನಿಮ್ಮ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಿಂದ ನಕಲಿಸಿದ ಮೌಲ್ಯಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆರವುಗೊಳಿಸಿ.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "ನಿಮಗಾಗಿ ಈ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಬಿಟ್‌ವಾರ್ಡನ್ ನೆನಪಿಸಿಕೊಳ್ಳಬೇಕೇ?" + }, + "notificationAddSave": { + "message": "ಹೌದು, ಈಗ ಉಳಿಸಿ" + }, + "disableChangedPasswordNotification": { + "message": "ಬದಲಾವಣೆ ಪಾಸ್ವರ್ಡ್ ಅಧಿಸೂಚನೆಯನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"ಬದಲಾಯಿಸಿದ ಪಾಸ್ವರ್ಡ್ ಅಧಿಸೂಚನೆ\" ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಿಮ್ಮ ಉತ್ತೇಜಿಸುವ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ನೀವು ವೆಬ್ಸೈಟ್ನಲ್ಲಿ ಬದಲಿಸಿದೆ ಎಂದು ಪತ್ತೆಹಚ್ಚಿದಾಗ ನಿಮ್ಮ ವಾಲ್ಟ್ನಲ್ಲಿ ಲಾಗಿನ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ನವೀಕರಿಸಲು ನಿಮ್ಮನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಅಪೇಕ್ಷಿಸುತ್ತದೆ." + }, + "notificationChangeDesc": { + "message": "ಈ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಬಿಟ್ವರ್ಡ್ನಲ್ಲಿ ನವೀಕರಿಸಲು ನೀವು ಬಯಸುತ್ತೀರಾ?" + }, + "notificationChangeSave": { + "message": "ಹೌದು, ಈಗ ನವೀಕರಿಸಿ" + }, + "disableContextMenuItem": { + "message": "ಸನ್ನಿವೇಶ ಮೆನು ಆಯ್ಕೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + }, + "disableContextMenuItemDesc": { + "message": "ಸನ್ನಿವೇಶ ಮೆನು ಆಯ್ಕೆಗಳು ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಟ್ಯಾಬ್ನಲ್ಲಿ ವೆಬ್ಸೈಟ್ಗೆ ಪಾಸ್ವರ್ಡ್ ಪೀಳಿಗೆಯ ಮತ್ತು ಲಾಗಿನ್ಗಳಿಗೆ ತ್ವರಿತ ಪ್ರವೇಶವನ್ನು ಒದಗಿಸುತ್ತದೆ." + }, + "defaultUriMatchDetection": { + "message": "ಡೀಫಾಲ್ಟ್ ಯುಆರ್ಐ ಹೊಂದಾಣಿಕೆ ಪತ್ತೆ", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "ಸ್ವಯಂ ಭರ್ತಿಯಂತಹ ಕ್ರಿಯೆಗಳನ್ನು ನಿರ್ವಹಿಸುವಾಗ ಲಾಗಿನ್‌ಗಳಿಗಾಗಿ URI ಹೊಂದಾಣಿಕೆ ಪತ್ತೆಹಚ್ಚುವಿಕೆಯನ್ನು ನಿರ್ವಹಿಸುವ ಪೂರ್ವನಿಯೋಜಿತ ಮಾರ್ಗವನ್ನು ಆರಿಸಿ." + }, + "theme": { + "message": "ಥೀಮ್ಸ್" + }, + "themeDesc": { + "message": "ಅಪ್ಲಿಕೇಶನ್‌ನ ಬಣ್ಣ ಥೀಮ್ ಅನ್ನು ಬದಲಾಯಿಸಿ." + }, + "dark": { + "message": "ಡಾರ್ಕ್", + "description": "Dark color" + }, + "light": { + "message": "ಬೆಳಕು", + "description": "Light color" + }, + "solarizedDark": { + "message": "ಡಾರ್ಕ್ ಸೌರ", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "ರಫ್ತು ವಾಲ್ಟ್" + }, + "fileFormat": { + "message": "ಕಡತದ ಮಾದರಿ" + }, + "warning": { + "message": "ಎಚ್ಚರಿಕೆ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "ವಾಲ್ಟ್ ರಫ್ತು ಖಚಿತಪಡಿಸಿ" + }, + "exportWarningDesc": { + "message": "ಈ ರಫ್ತು ನಿಮ್ಮ ವಾಲ್ಟ್ ಡೇಟಾವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡದ ಸ್ವರೂಪದಲ್ಲಿ ಒಳಗೊಂಡಿದೆ. ನೀವು ರಫ್ತು ಮಾಡಿದ ಫೈಲ್ ಅನ್ನು ಅಸುರಕ್ಷಿತ ಚಾನಲ್‌ಗಳಲ್ಲಿ (ಇಮೇಲ್ ನಂತಹ) ಸಂಗ್ರಹಿಸಬಾರದು ಅಥವಾ ಕಳುಹಿಸಬಾರದು. ನೀವು ಅದನ್ನು ಬಳಸಿದ ನಂತರ ಅದನ್ನು ಅಳಿಸಿ." + }, + "encExportKeyWarningDesc": { + "message": "ಈ ರಫ್ತು ನಿಮ್ಮ ಖಾತೆಯ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಲಿಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡುತ್ತದೆ. ನಿಮ್ಮ ಖಾತೆಯ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಲಿಯನ್ನು ನೀವು ಎಂದಾದರೂ ತಿರುಗಿಸಿದರೆ ನೀವು ಈ ರಫ್ತು ಫೈಲ್ ಅನ್ನು ಡೀಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗದ ಕಾರಣ ನೀವು ಮತ್ತೆ ರಫ್ತು ಮಾಡಬೇಕು." + }, + "encExportAccountWarningDesc": { + "message": "ಖಾತೆ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಗಳು ಪ್ರತಿ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಬಳಕೆದಾರ ಖಾತೆಗೆ ಅನನ್ಯವಾಗಿವೆ, ಆದ್ದರಿಂದ ನೀವು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ರಫ್ತು ಬೇರೆ ಖಾತೆಗೆ ಆಮದು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ." + }, + "exportMasterPassword": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಡೇಟಾವನ್ನು ರಫ್ತು ಮಾಡಲು ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನಮೂದಿಸಿ." + }, + "shared": { + "message": "ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ" + }, + "learnOrg": { + "message": "ಸಂಘಟನೆಗಳ ಬಗ್ಗೆ ತಿಳಿಯಿರಿ" + }, + "learnOrgConfirmation": { + "message": "ಸಂಸ್ಥೆಯೊಂದನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಚಾವಣಿ ವಸ್ತುಗಳನ್ನು ಇತರರೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಲು ಬಿಟ್ವರ್ಡ್ಗಳು ನಿಮ್ಮನ್ನು ಅನುಮತಿಸುತ್ತದೆ. ನೀವು ಇನ್ನಷ್ಟು ತಿಳಿಯಲು Bitwarden.com ವೆಬ್ಸೈಟ್ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "moveToOrganization": { + "message": "ಸಂಸ್ಥೆಗೆ ಸರಿಸಿ" + }, + "share": { + "message": "ಹಂಚಿಕೊಳ್ಳಿ" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ ಅನ್ನು $ORGNAME$ ಗೆ ಸರಿಸಲಾಗಿದೆ", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಸರಿಸಲು ನೀವು ಬಯಸುವ ಸಂಸ್ಥೆಯನ್ನು ಆರಿಸಿ. ಸಂಸ್ಥೆಗೆ ಹೋಗುವುದರಿಂದ ವಸ್ತುವಿನ ಮಾಲೀಕತ್ವವನ್ನು ಆ ಸಂಸ್ಥೆಗೆ ವರ್ಗಾಯಿಸುತ್ತದೆ. ಈ ಐಟಂ ಅನ್ನು ಸರಿಸಿದ ನಂತರ ನೀವು ಇನ್ನು ಮುಂದೆ ಅದರ ನೇರ ಮಾಲೀಕರಾಗಿರುವುದಿಲ್ಲ." + }, + "learnMore": { + "message": "ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ" + }, + "authenticatorKeyTotp": { + "message": "ದೃಢೀಕರಣ ಕೀ (TOTP)" + }, + "verificationCodeTotp": { + "message": "ಪರಿಶೀಲನಾ ಕೋಡ್‌ಗಳು" + }, + "copyVerificationCode": { + "message": "ಪರಿಶೀಲನೆ ಕೋಡ್ ನಕಲಿಸಿ" + }, + "attachments": { + "message": "ಲಗತ್ತುಗಳು" + }, + "deleteAttachment": { + "message": "ಲಗತ್ತನ್ನು ಅಳಿಸಿ" + }, + "deleteAttachmentConfirmation": { + "message": "ಈ ಲಗತ್ತನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "deletedAttachment": { + "message": "ಲಗತ್ತು ಅಳಿಸಲಾಗಿದೆ" + }, + "newAttachment": { + "message": "ಹೊಸ ಲಗತ್ತನ್ನು ಸೇರಿಸಿ" + }, + "noAttachments": { + "message": "ಲಗತ್ತುಗಳಿಲ್ಲ." + }, + "attachmentSaved": { + "message": "ಲಗತ್ತನ್ನು ಉಳಿಸಲಾಗಿದೆ." + }, + "file": { + "message": "ಫೈಲ್" + }, + "selectFile": { + "message": "ಕಡತವನ್ನು ಆಯ್ಕೆಮಾಡು." + }, + "maxFileSize": { + "message": "ಗರಿಷ್ಠ ಫೈಲ್ ಗಾತ್ರ 500 ಎಂಬಿ." + }, + "featureUnavailable": { + "message": "ವೈಶಿಷ್ಟ್ಯ ಲಭ್ಯವಿಲ್ಲ" + }, + "updateKey": { + "message": "ನಿಮ್ಮ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಲಿಯನ್ನು ನವೀಕರಿಸುವವರೆಗೆ ನೀವು ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲಾಗುವುದಿಲ್ಲ." + }, + "premiumMembership": { + "message": "ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವ" + }, + "premiumManage": { + "message": "ಸದಸ್ಯತ್ವವನ್ನು ನಿರ್ವಹಿಸಿ" + }, + "premiumManageAlert": { + "message": "ನಿಮ್ಮ ಸದಸ್ಯತ್ವವನ್ನು ನೀವು bitwarden.com ವೆಬ್ ವಾಲ್ಟ್‌ನಲ್ಲಿ ನಿರ್ವಹಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "premiumRefresh": { + "message": "ಸದಸ್ಯತ್ವವನ್ನು ರಿಫ್ರೆಶ್ ಮಾಡಿ" + }, + "premiumNotCurrentMember": { + "message": "ನೀವು ಪ್ರಸ್ತುತ ಪ್ರೀಮಿಯಂ ಸದಸ್ಯರಲ್ಲ." + }, + "premiumSignUpAndGet": { + "message": "ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವಕ್ಕಾಗಿ ಸೈನ್ ಅಪ್ ಮಾಡಿ ಮತ್ತು ಪಡೆಯಿರಿ:" + }, + "ppremiumSignUpStorage": { + "message": "ಫೈಲ್ ಲಗತ್ತುಗಳಿಗಾಗಿ 1 ಜಿಬಿ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಸಂಗ್ರಹ." + }, + "ppremiumSignUpTwoStep": { + "message": "ಹೆಚ್ಚುವರಿ ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ಆಯ್ಕೆಗಳಾದ ಯೂಬಿಕೆ, ಎಫ್‌ಐಡಿಒ ಯು 2 ಎಫ್, ಮತ್ತು ಡ್ಯುವೋ." + }, + "ppremiumSignUpReports": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಅನ್ನು ಸುರಕ್ಷಿತವಾಗಿರಿಸಲು ಪಾಸ್ವರ್ಡ್ ನೈರ್ಮಲ್ಯ, ಖಾತೆ ಆರೋಗ್ಯ ಮತ್ತು ಡೇಟಾ ಉಲ್ಲಂಘನೆ ವರದಿಗಳು." + }, + "ppremiumSignUpTotp": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್‌ನಲ್ಲಿನ ಲಾಗಿನ್‌ಗಳಿಗಾಗಿ TOTP ಪರಿಶೀಲನಾ ಕೋಡ್ (2FA) ಜನರೇಟರ್." + }, + "ppremiumSignUpSupport": { + "message": "ಆದ್ಯತೆಯ ಗ್ರಾಹಕ ಬೆಂಬಲ." + }, + "ppremiumSignUpFuture": { + "message": "ಎಲ್ಲಾ ಭವಿಷ್ಯದ ಪ್ರೀಮಿಯಂ ವೈಶಿಷ್ಟ್ಯಗಳು. ಹೆಚ್ಚು ಶೀಘ್ರದಲ್ಲೇ ಬರಲಿದೆ!" + }, + "premiumPurchase": { + "message": "ಪ್ರೀಮಿಯಂ ಖರೀದಿಸಿ" + }, + "premiumPurchaseAlert": { + "message": "ನೀವು ಬಿಟ್ವಾರ್ಡೆನ್.ಕಾಮ್ ವೆಬ್ ವಾಲ್ಟ್ನಲ್ಲಿ ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವವನ್ನು ಖರೀದಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "premiumCurrentMember": { + "message": "ನೀವು ಪ್ರೀಮಿಯಂ ಸದಸ್ಯರಾಗಿದ್ದೀರಿ!" + }, + "premiumCurrentMemberThanks": { + "message": "ಬಿಟ್ವಾರ್ಡೆನ್ ಅವರನ್ನು ಬೆಂಬಲಿಸಿದ್ದಕ್ಕಾಗಿ ಧನ್ಯವಾದಗಳು." + }, + "premiumPrice": { + "message": "ಎಲ್ಲವೂ ಕೇವಲ $PRICE$ / ವರ್ಷಕ್ಕೆ!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "ರಿಫ್ರೆಶ್ ಪೂರ್ಣಗೊಂಡಿದೆ" + }, + "disableAutoTotpCopy": { + "message": "ಸ್ವಯಂಚಾಲಿತ TOTP ನಕಲನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + }, + "disableAutoTotpCopyDesc": { + "message": "ನಿಮ್ಮ ಲಾಗಿನ್‌ಗೆ ದೃಢೀಕರಣ ಕೀಲಿಯನ್ನು ಲಗತ್ತಿಸಿದ್ದರೆ, ನೀವು ಲಾಗಿನ್ ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಭರ್ತಿ ಮಾಡಿದಾಗಲೆಲ್ಲಾ TOTP ಪರಿಶೀಲನಾ ಕೋಡ್ ನಿಮ್ಮ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ನಕಲಿಸಲ್ಪಡುತ್ತದೆ." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "ಪ್ರೀಮಿಯಂ ಅಗತ್ಯವಿದೆ" + }, + "premiumRequiredDesc": { + "message": "ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವ ಅಗತ್ಯವಿದೆ." + }, + "enterVerificationCodeApp": { + "message": "ನಿಮ್ಮ ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ 6 ಅಂಕಿಯ ಪರಿಶೀಲನಾ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ಗೆ ಇಮೇಲ್ ಮಾಡಲಾದ 6 ಅಂಕಿಯ ಪರಿಶೀಲನಾ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "ಪರಿಶೀಲನೆ ಇಮೇಲ್ $EMAIL$ ಗೆ ಕಳುಹಿಸಲಾಗಿದೆ.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "ನನ್ನನ್ನು ನೆನಪಿನಲ್ಲಿ ಇಡು" + }, + "sendVerificationCodeEmailAgain": { + "message": "ಪರಿಶೀಲನೆ ಕೋಡ್ ಇಮೇಲ್ ಅನ್ನು ಮತ್ತೆ ಕಳುಹಿಸಿ" + }, + "useAnotherTwoStepMethod": { + "message": "ಮತ್ತೊಂದು ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ವಿಧಾನವನ್ನು ಬಳಸಿ" + }, + "insertYubiKey": { + "message": "ನಿಮ್ಮ ಯುಬಿಕಿಯನ್ನು ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನ ಯುಎಸ್‌ಬಿ ಪೋರ್ಟ್ಗೆ ಸೇರಿಸಿ, ನಂತರ ಅದರ ಗುಂಡಿಯನ್ನು ಸ್ಪರ್ಶಿಸಿ." + }, + "insertU2f": { + "message": "ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನ ಯುಎಸ್‌ಬಿ ಪೋರ್ಟ್ಗೆ ನಿಮ್ಮ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಸೇರಿಸಿ. ಅದು ಬಟನ್ ಹೊಂದಿದ್ದರೆ, ಅದನ್ನು ಸ್ಪರ್ಶಿಸಿ." + }, + "webAuthnNewTab": { + "message": "WebAuthn 2FA ಪರಿಶೀಲನೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು. ಹೊಸ ಟ್ಯಾಬ್ ತೆರೆಯಲು ಕೆಳಗಿನ ಬಟನ್ ಕ್ಲಿಕ್ ಮಾಡಿ ಮತ್ತು ಹೊಸ ಟ್ಯಾಬ್‌ನಲ್ಲಿ ಒದಗಿಸಲಾದ ಸೂಚನೆಗಳನ್ನು ಅನುಸರಿಸಿ." + }, + "webAuthnNewTabOpen": { + "message": "ಹೊಸ ಟ್ಯಾಬ್ ತೆರೆಯಿರಿ" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn ಅನ್ನು ಪ್ರಮಾಣಿಕರಿಸು" + }, + "loginUnavailable": { + "message": "ಲಾಗಿನ್ ಲಭ್ಯವಿಲ್ಲ" + }, + "noTwoStepProviders": { + "message": "ಈ ಖಾತೆಯು ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದೆ, ಆದಾಗ್ಯೂ, ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾದ ಎರಡು-ಹಂತದ ಪೂರೈಕೆದಾರರಲ್ಲಿ ಯಾರೂ ಈ ವೆಬ್ ಬ್ರೌಸರ್‌ನಿಂದ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ." + }, + "noTwoStepProviders2": { + "message": "ದಯವಿಟ್ಟು ಬೆಂಬಲಿತ ವೆಬ್ ಬ್ರೌಸರ್ ಅನ್ನು ಬಳಸಿ (Chrome ನಂತಹ) ಮತ್ತು / ಅಥವಾ ವೆಬ್ ಬ್ರೌಸರ್‌ಗಳಲ್ಲಿ (ದೃ hentic ೀಕರಣ ಅಪ್ಲಿಕೇಶನ್‌ನಂತಹ) ಉತ್ತಮವಾಗಿ ಬೆಂಬಲಿತವಾದ ಹೆಚ್ಚುವರಿ ಪೂರೈಕೆದಾರರನ್ನು ಸೇರಿಸಿ." + }, + "twoStepOptions": { + "message": "ಎರಡು ಹಂತದ ಲಾಗಿನ್ ಆಯ್ಕೆಗಳು" + }, + "recoveryCodeDesc": { + "message": "ನಿಮ್ಮ ಎಲ್ಲಾ ಎರಡು ಅಂಶ ಪೂರೈಕೆದಾರರಿಗೆ ಪ್ರವೇಶವನ್ನು ಕಳೆದುಕೊಂಡಿದ್ದೀರಾ? ನಿಮ್ಮ ಖಾತೆಯಿಂದ ಎಲ್ಲಾ ಎರಡು ಅಂಶ ಪೂರೈಕೆದಾರರನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ನಿಮ್ಮ ಮರುಪಡೆಯುವಿಕೆ ಕೋಡ್ ಬಳಸಿ." + }, + "recoveryCodeTitle": { + "message": "ಮರುಪಡೆಯುವಿಕೆ ಕೋಡ್" + }, + "authenticatorAppTitle": { + "message": "ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್" + }, + "authenticatorAppDesc": { + "message": "ಸಮಯ ಆಧಾರಿತ ಪರಿಶೀಲನಾ ಕೋಡ್‌ಗಳನ್ನು ರಚಿಸಲು ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಬಳಸಿ (ಆಥಿ ಅಥವಾ ಗೂಗಲ್ ಅಥೆಂಟಿಕೇಟರ್).", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "ಯುಬಿಕೆ ಒಟಿಪಿ ಭದ್ರತಾ ಕೀ" + }, + "yubiKeyDesc": { + "message": "ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಯುಬಿಕೆ ಬಳಸಿ. ಯುಬಿಕೆ 4, 4 ನ್ಯಾನೋ, 4 ಸಿ ಮತ್ತು ಎನ್ಇಒ ಸಾಧನಗಳೊಂದಿಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ." + }, + "duoDesc": { + "message": "ಡ್ಯುಯೊ ಮೊಬೈಲ್ ಅಪ್ಲಿಕೇಶನ್, ಎಸ್‌ಎಂಎಸ್, ಫೋನ್ ಕರೆ ಅಥವಾ ಯು 2 ಎಫ್ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಬಳಸಿಕೊಂಡು ಡ್ಯುಯೊ ಸೆಕ್ಯುರಿಟಿಯೊಂದಿಗೆ ಪರಿಶೀಲಿಸಿ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "ಡ್ಯುಯೊ ಮೊಬೈಲ್ ಅಪ್ಲಿಕೇಶನ್, ಎಸ್‌ಎಂಎಸ್, ಫೋನ್ ಕರೆ ಅಥವಾ ಯು 2 ಎಫ್ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಸಂಸ್ಥೆಗಾಗಿ ಡ್ಯುಯೊ ಸೆಕ್ಯುರಿಟಿಯೊಂದಿಗೆ ಪರಿಶೀಲಿಸಿ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಯಾವುದೇ ವೆಬ್‌ಆಥ್ನ್ ಸಕ್ರಿಯಗೊಳಿಸಿದ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಬಳಸಿ." + }, + "emailTitle": { + "message": "ಇಮೇಲ್" + }, + "emailDesc": { + "message": "ಪರಿಶೀಲನೆ ಕೋಡ್‌ಗಳನ್ನು ನಿಮಗೆ ಇಮೇಲ್ ಮಾಡಲಾಗುತ್ತದೆ." + }, + "selfHostedEnvironment": { + "message": "ಸ್ವಯಂ ಆತಿಥೇಯ ಪರಿಸರ" + }, + "selfHostedEnvironmentFooter": { + "message": "ನಿಮ್ಮ ಆನ್-ಪ್ರಮೇಯ ಹೋಸ್ಟ್ ಮಾಡಿದ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಸ್ಥಾಪನೆಯ ಮೂಲ URL ಅನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿ." + }, + "customEnvironment": { + "message": "ಕಸ್ಟಮ್ ಪರಿಸರ" + }, + "customEnvironmentFooter": { + "message": "ಸುಧಾರಿತ ಬಳಕೆದಾರರಿಗಾಗಿ. ನೀವು ಪ್ರತಿ ಸೇವೆಯ ಮೂಲ URL ಅನ್ನು ಸ್ವತಂತ್ರವಾಗಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಬಹುದು." + }, + "baseUrl": { + "message": "ಸರ್ವರ್ URL" + }, + "apiUrl": { + "message": "API ಸರ್ವರ್ URL" + }, + "webVaultUrl": { + "message": "ವೆಬ್ ವಾಲ್ಟ್ ಸರ್ವರ್ URL" + }, + "identityUrl": { + "message": "ಗುರುತಿನ ಸರ್ವರ್ URL" + }, + "notificationsUrl": { + "message": "ಅಧಿಸೂಚನೆಗಳು ಸರ್ವರ್ URL" + }, + "iconsUrl": { + "message": "ಚಿಹ್ನೆಗಳು ಸರ್ವರ್ URL" + }, + "environmentSaved": { + "message": "ಪರಿಸರ URL ಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ." + }, + "enableAutoFillOnPageLoad": { + "message": "ಪುಟ ಲೋಡ್‌ನಲ್ಲಿ ಸ್ವಯಂ ಭರ್ತಿ ಸಕ್ರಿಯಗೊಳಿಸಿ" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "ಲಾಗಿನ್ ಫಾರ್ಮ್ ಪತ್ತೆಯಾದಲ್ಲಿ, ವೆಬ್ ಪುಟ ಲೋಡ್ ಆಗುವಾಗ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸ್ವಯಂ ಭರ್ತಿ ಮಾಡಿ." + }, + "experimentalFeature": { + "message": "ಇದು ಪ್ರಸ್ತುತ ಪ್ರಾಯೋಗಿಕ ಲಕ್ಷಣವಾಗಿದೆ. ನಿಮ್ಮ ಸ್ವಂತ ಅಪಾಯದಲ್ಲಿ ಬಳಸಿ." + }, + "defaultAutoFillOnPageLoad": { + "message": "ಲಾಗಿನ್ ಐಟಂಗಳಿಗಾಗಿ ಡೀಫಾಲ್ಟ್ ಆಟೋಫಿಲ್ ಸೆಟ್ಟಿಂಗ್" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "ಪುಟ ಲೋಡ್‌ನಲ್ಲಿ ಸ್ವಯಂ-ಭರ್ತಿ ಸಕ್ರಿಯಗೊಳಿಸಿದ ನಂತರ, ನೀವು ವೈಯಕ್ತಿಕ ಲಾಗಿನ್ ಐಟಂಗಳಿಗಾಗಿ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬಹುದು ಅಥವಾ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಬಹುದು. ಪ್ರತ್ಯೇಕವಾಗಿ ಕಾನ್ಫಿಗರ್ ಮಾಡದ ಲಾಗಿನ್ ಐಟಂಗಳ ಡೀಫಾಲ್ಟ್ ಸೆಟ್ಟಿಂಗ್ ಇದು." + }, + "itemAutoFillOnPageLoad": { + "message": "ಪುಟ ಲೋಡ್‌ನಲ್ಲಿ ಸ್ವಯಂ ಭರ್ತಿ (ಆಯ್ಕೆಗಳಲ್ಲಿ ಸಕ್ರಿಯಗೊಳಿಸಿದ್ದರೆ)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "ಡೀಫಾಲ್ಟ್ ಸೆಟ್ಟಿಂಗ್ ಬಳಸಿ" + }, + "autoFillOnPageLoadYes": { + "message": "ಪುಟ ಲೋಡ್‌ನಲ್ಲಿ ಸ್ವಯಂ ಭರ್ತಿ" + }, + "autoFillOnPageLoadNo": { + "message": "ಪುಟ ಲೋಡ್‌ನಲ್ಲಿ ಸ್ವಯಂ ಭರ್ತಿ ಮಾಡಬೇಡಿ" + }, + "commandOpenPopup": { + "message": "ವಾಲ್ಟ್ ಪಾಪ್ಅಪ್ ತೆರೆಯಿರಿ" + }, + "commandOpenSidebar": { + "message": "ಸೈಡ್ಬಾರ್ನಲ್ಲಿ ವಾಲ್ಟ್ ತೆರೆಯಿರಿ" + }, + "commandAutofillDesc": { + "message": "ಪ್ರಸ್ತುತ ವೆಬ್‌ಸೈಟ್‌ಗಾಗಿ ಕೊನೆಯದಾಗಿ ಬಳಸಿದ ಲಾಗಿನ್ ಅನ್ನು ಸ್ವಯಂ ಭರ್ತಿ ಮಾಡಿ" + }, + "commandGeneratePasswordDesc": { + "message": "ಕ್ಲಿಪ್ಬೋರ್ಡ್ಗೆ ಹೊಸ ಯಾದೃಚ್ಛಿಕ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ರಚಿಸಿ ಮತ್ತು ನಕಲಿಸಿ" + }, + "commandLockVaultDesc": { + "message": "ವಾಲ್ಟ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿ" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "ಕಸ್ಟಮ್ ಕ್ಷೇತ್ರಗಳು" + }, + "copyValue": { + "message": "ಮೌಲ್ಯವನ್ನು ನಕಲಿಸಿ" + }, + "value": { + "message": "ಮೌಲ್ಯ" + }, + "newCustomField": { + "message": "ಹೊಸ ಕಸ್ಟಮ್ ಕ್ಷೇತ್ರ" + }, + "dragToSort": { + "message": "ವಿಂಗಡಿಸಲು ಎಳೆಯಿರಿ" + }, + "cfTypeText": { + "message": "ಪಠ್ಯ" + }, + "cfTypeHidden": { + "message": "ಮರೆಮಾಡಲಾಗಿದೆ" + }, + "cfTypeBoolean": { + "message": "ಬೂಲಿಯನ್" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "ನಿಮ್ಮ ಪರಿಶೀಲನಾ ಕೋಡ್‌ಗಾಗಿ ನಿಮ್ಮ ಇಮೇಲ್ ಪರಿಶೀಲಿಸಲು ಪಾಪ್ಅಪ್ ವಿಂಡೋದ ಹೊರಗೆ ಕ್ಲಿಕ್ ಮಾಡುವುದರಿಂದ ಈ ಪಾಪ್ಅಪ್ ಮುಚ್ಚಲ್ಪಡುತ್ತದೆ. ಈ ಪಾಪ್ಅಪ್ ಅನ್ನು ಮುಚ್ಚದಿರುವಂತೆ ಹೊಸ ವಿಂಡೋದಲ್ಲಿ ತೆರೆಯಲು ನೀವು ಬಯಸುವಿರಾ?" + }, + "popupU2fCloseMessage": { + "message": "ಈ ಬ್ರೌಸರ್ ಈ ಪಾಪ್ಅಪ್ ವಿಂಡೋದಲ್ಲಿ ಯು 2 ಎಫ್ ವಿನಂತಿಗಳನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಈ ಪಾಪ್ಅಪ್ ಅನ್ನು ಹೊಸ ವಿಂಡೋದಲ್ಲಿ ತೆರೆಯಲು ನೀವು ಬಯಸುವಿರಾ, ಇದರಿಂದ ನೀವು ಯು 2 ಎಫ್ ಬಳಸಿ ಲಾಗ್ ಇನ್ ಆಗಬಹುದು." + }, + "disableFavicon": { + "message": "ವೆಬ್‌ಸೈಟ್ ಚಿಹ್ನೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + }, + "disableFaviconDesc": { + "message": "ವೆಬ್‌ಸೈಟ್ ಐಕಾನ್‌ಗಳು ನಿಮ್ಮ ವಾಲ್ಟ್‌ನಲ್ಲಿರುವ ಪ್ರತಿ ಲಾಗಿನ್ ಐಟಂನ ಪಕ್ಕದಲ್ಲಿ ಗುರುತಿಸಬಹುದಾದ ಚಿತ್ರವನ್ನು ಒದಗಿಸುತ್ತದೆ." + }, + "disableBadgeCounter": { + "message": "ಬ್ಯಾಡ್ಜ್ ಕೌಂಟರ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + }, + "disableBadgeCounterDesc": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ನಲ್ಲಿ ಪ್ರಸ್ತುತ ಪುಟಕ್ಕಾಗಿ ನೀವು ಎಷ್ಟು ಲಾಗಿನ್ಗಳನ್ನು ಹೊಂದಿದ್ದೀರಿ ಎಂದು ಬ್ಯಾಡ್ಜ್ ಕೌಂಟರ್ ಸೂಚಿಸುತ್ತದೆ." + }, + "cardholderName": { + "message": "ಕಾರ್ಡುದಾರನ ಹೆಸರು" + }, + "number": { + "message": "ಸಂಖ್ಯೆ" + }, + "brand": { + "message": "ಬ್ರ್ಯಾಂಡ್" + }, + "expirationMonth": { + "message": "ಮುಕ್ತಾಯ ತಿಂಗಳು" + }, + "expirationYear": { + "message": "ಮುಕ್ತಾಯ ವರ್ಷ" + }, + "expiration": { + "message": "ಮುಕ್ತಾಯ" + }, + "january": { + "message": "ಜನವರಿ" + }, + "february": { + "message": "ಫೆಬ್ರವರಿ" + }, + "march": { + "message": "ಮಾರ್ಚ್" + }, + "april": { + "message": "ಏಪ್ರಿಲ್" + }, + "may": { + "message": "ಮೇ" + }, + "june": { + "message": "ಜೂನ್" + }, + "july": { + "message": "ಜುಲೈ" + }, + "august": { + "message": "ಆಗಸ್ಟ್" + }, + "september": { + "message": "ಸೆಪ್ಟೆಂಬರ್" + }, + "october": { + "message": "ಅಕ್ಟೋಬರ್" + }, + "november": { + "message": "ನವೆಂಬರ್" + }, + "december": { + "message": "ಡಿಸೆಂಬರ್" + }, + "securityCode": { + "message": "ಭದ್ರತಾ ಕೋಡ್ " + }, + "ex": { + "message": "ಉದಾಹರಣೆ" + }, + "title": { + "message": "ಶೀರ್ಷಿಕೆ" + }, + "mr": { + "message": "ಶ್ರೀ" + }, + "mrs": { + "message": "ಶ್ರೀಮತಿ" + }, + "ms": { + "message": "ಎಂ.ಎಸ್" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "ಮೊದಲ ಹೆಸರು" + }, + "middleName": { + "message": "ಮಧ್ಯದ ಹೆಸರು" + }, + "lastName": { + "message": "ಕೊನೆ ಹೆಸರು" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "ಹೆಸರು ಗುರುತು" + }, + "company": { + "message": "ಕಂಪನಿ" + }, + "ssn": { + "message": "ಸಾಮಾಜಿಕ ಭದ್ರತೆ ಸಂಖ್ಯೆ" + }, + "passportNumber": { + "message": "ಪಾಸ್ಪೋರ್ಟ್ ಸಂಖ್ಯೆ" + }, + "licenseNumber": { + "message": "ಪರವಾನಗಿ ಸಂಖ್ಯೆ" + }, + "email": { + "message": "ಇಮೇಲ್" + }, + "phone": { + "message": "ಫೋನ್‌" + }, + "address": { + "message": "ವಿಳಾಸ " + }, + "address1": { + "message": "ವಿಳಾಸ 1" + }, + "address2": { + "message": "ವಿಳಾಸ 2" + }, + "address3": { + "message": "ವಿಳಾಸ 3" + }, + "cityTown": { + "message": "ನಗರ / ಪಟ್ಟಣ" + }, + "stateProvince": { + "message": "ರಾಜ್ಯ / ಪ್ರಾಂತ್ಯ" + }, + "zipPostalCode": { + "message": "ಪಿನ್ / ಅಂಚೆ ಕೋಡ್" + }, + "country": { + "message": "ದೇಶ" + }, + "type": { + "message": "ಪ್ರಕಾರ" + }, + "typeLogin": { + "message": "ಲಾಗಿನ್" + }, + "typeLogins": { + "message": "ಲಾಗಿನ್ಸ್" + }, + "typeSecureNote": { + "message": "ಸುರಕ್ಷಿತ ಟಿಪ್ಪಣಿ" + }, + "typeCard": { + "message": "ಕಾರ್ಡ್" + }, + "typeIdentity": { + "message": "ಗುರುತಿಸುವಿಕೆ" + }, + "passwordHistory": { + "message": "ಪಾಸ್ವರ್ಡ್ ಇತಿಹಾಸ" + }, + "back": { + "message": "ಹಿಂದಕ್ಕೆ" + }, + "collections": { + "message": "ಸಂಗ್ರಹಣೆಗಳು" + }, + "favorites": { + "message": "ಮೆಚ್ಚುಗೆಗಳು" + }, + "popOutNewWindow": { + "message": "ಹೊಸ ವಿಂಡೋಗೆ ಪಾಪ್ ಔಟ್ ಮಾಡಿ" + }, + "refresh": { + "message": "ಹೊಸತಾಗಿಸಿ" + }, + "cards": { + "message": "ಕಾರ್ಡ್‌ಗಳು" + }, + "identities": { + "message": "ಗುರುತುಗಳು" + }, + "logins": { + "message": "ಲಾಗಿನ್ಸ್" + }, + "secureNotes": { + "message": "ಸುರಕ್ಷಿತ ಟಿಪ್ಪಣಿಗಳು" + }, + "clear": { + "message": "ಕ್ಲಿಯರ್‌", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ಬಹಿರಂಗಗೊಂಡಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ." + }, + "passwordExposed": { + "message": "ಈ ಗುಪ್ತಪದವು ಡೇಟಾ ಉಲ್ಲಂಘನೆಯಲ್ಲಿ $VALUE$ ಮೌಲ್ಯವನ್ನು (ಗಳು) ಬಹಿರಂಗಪಡಿಸಲಾಗಿದೆ. ನೀವು ಅದನ್ನು ಬದಲಾಯಿಸಬೇಕು.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "ತಿಳಿದಿರುವ ಯಾವುದೇ ಡೇಟಾ ಉಲ್ಲಂಘನೆಗಳಲ್ಲಿ ಈ ಪಾಸ್‌ವರ್ಡ್ ಕಂಡುಬಂದಿಲ್ಲ. ಅದನ್ನು ಬಳಸಲು ಸುರಕ್ಷಿತವಾಗಿರಬೇಕು." + }, + "baseDomain": { + "message": "ಮೂಲ ಡೊಮೇನ್", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "ಅತಿಥೆಯ", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "ನಿಖರವಾಗಿ" + }, + "startsWith": { + "message": "ಇದರೊಂದಿಗೆ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ" + }, + "regEx": { + "message": "ನಿಯಮಿತ ಅಭಿವ್ಯಕ್ತಿ", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "ಹೊಂದಾಣಿಕೆ ಪತ್ತೆ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "ಡೀಫಾಲ್ಟ್ ಪಂದ್ಯ ಪತ್ತೆ", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "ಟಾಗಲ್ ಆಯ್ಕೆಗಳು" + }, + "toggleCurrentUris": { + "message": "ಪ್ರಸ್ತುತ URI ಗಳನ್ನು ಟಾಗಲ್ ಮಾಡಿ", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "ಪ್ರಸ್ತುತ URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "ಸಂಸ್ಥೆ", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "ರೀತಿಯ" + }, + "allItems": { + "message": "ಎಲ್ಲಾ ವಸ್ತುಗಳು" + }, + "noPasswordsInList": { + "message": "ಪಟ್ಟಿ ಮಾಡಲು ಯಾವುದೇ ಪಾಸ್ವರ್ಡ್ಗಳು ಇಲ್ಲ." + }, + "remove": { + "message": "ತೆಗೆ" + }, + "default": { + "message": "ಡಿಫಾಲ್ಟ್" + }, + "dateUpdated": { + "message": "ಅಪ್‌ಡೇಟ್", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "ಪಾಸ್ವರ್ಡ್ ನವೀಕರಿಸಲಾಗಿದೆ", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "ನೀವು \"ನೆವರ್\" ಆಯ್ಕೆಯನ್ನು ಬಳಸಲು ಬಯಸುತ್ತೀರಾ? ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ನಿಮ್ಮ ವಾಲ್ಟ್ನ ಎನ್ಕ್ರಿಪ್ಶನ್ ಕೀಲಿಯನ್ನು \"ಎಂದಿಗೂ\" ಸಂಗ್ರಹಿಸಲು ನಿಮ್ಮ ಲಾಕ್ ಆಯ್ಕೆಗಳನ್ನು ಹೊಂದಿಸಿ. ನೀವು ಈ ಆಯ್ಕೆಯನ್ನು ಬಳಸಿದರೆ ನಿಮ್ಮ ಸಾಧನವನ್ನು ಸರಿಯಾಗಿ ರಕ್ಷಿಸಲಾಗಿದೆ ಎಂದು ನೀವು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಬೇಕು." + }, + "noOrganizationsList": { + "message": "ನೀವು ಯಾವುದೇ ಸಂಸ್ಥೆಗಳಿಗೆ ಸೇರಿಲ್ಲ. ಇತರ ಬಳಕೆದಾರರೊಂದಿಗೆ ವಸ್ತುಗಳನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಹಂಚಿಕೊಳ್ಳಲು ಸಂಘಟನೆಗಳು ನಿಮಗೆ ಅವಕಾಶ ನೀಡುತ್ತವೆ." + }, + "noCollectionsInList": { + "message": "ಪಟ್ಟಿ ಮಾಡಲು ಯಾವುದೇ ಸಂಗ್ರಹಗಳಿಲ್ಲ." + }, + "ownership": { + "message": "ಮಾಲೀಕತ್ವ" + }, + "whoOwnsThisItem": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಯಾರು ಹೊಂದಿದ್ದಾರೆ?" + }, + "strong": { + "message": "ಬಲಶಾಲಿ", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "ಒಳ್ಳೆಯ", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "ದುರ್ಬಲ", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "ದುರ್ಬಲ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್" + }, + "weakMasterPasswordDesc": { + "message": "ನೀವು ಆಯ್ಕೆ ಮಾಡಿದ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ದುರ್ಬಲವಾಗಿದೆ. ನಿಮ್ಮ ಬಿಟ್ವರ್ಡ್ ಖಾತೆಯನ್ನು ಸರಿಯಾಗಿ ರಕ್ಷಿಸಲು ನೀವು ಬಲವಾದ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ (ಅಥವಾ ಪಾಸ್ಫ್ರೇಸ್) ಅನ್ನು ಬಳಸಬೇಕು. ಈ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ನೀವು ಬಳಸಲು ಬಯಸುತ್ತೀರಾ?" + }, + "pin": { + "message": "ಪಿನ್", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "ಪಿನ್‌ನೊಂದಿಗೆ ಅನ್ಲಾಕ್ ಮಾಡಿ" + }, + "setYourPinCode": { + "message": "ಬಿಟ್‌ವಾರ್ಡೆನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮ ಪಿನ್ ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ. ನೀವು ಎಂದಾದರೂ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಸಂಪೂರ್ಣವಾಗಿ ಲಾಗ್ out ಟ್ ಆಗಿದ್ದರೆ ನಿಮ್ಮ ಪಿನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ." + }, + "pinRequired": { + "message": "ಪಿನ್ ಕೋಡ್ ಅಗತ್ಯವಿದೆ." + }, + "invalidPin": { + "message": "ಅಮಾನ್ಯ ಪಿನ್ ಕೋಡ್." + }, + "unlockWithBiometrics": { + "message": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್‌ನೊಂದಿಗೆ ಅನ್ಲಾಕ್ ಮಾಡಿ" + }, + "awaitDesktop": { + "message": "ಡೆಸ್ಕ್‌ಟಾಪ್‌ನಿಂದ ದೃಢೀಕರಣಕ್ಕಾಗಿ ಕಾಯಲಾಗುತ್ತಿದೆ" + }, + "awaitDesktopDesc": { + "message": "ಬ್ರೌಸರ್‌ಗಾಗಿ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ದಯವಿಟ್ಟು ಬಿಟ್‌ವಾರ್ಡೆನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್‌ನಲ್ಲಿ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬಳಸುವುದನ್ನು ಖಚಿತಪಡಿಸಿ." + }, + "lockWithMasterPassOnRestart": { + "message": "ಬ್ರೌಸರ್ ಮರುಪ್ರಾರಂಭದಲ್ಲಿ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್‌ನೊಂದಿಗೆ ಲಾಕ್ ಮಾಡಿ" + }, + "selectOneCollection": { + "message": "ನೀವು ಕನಿಷ್ಠ ಒಂದು ಸಂಗ್ರಹವನ್ನು ಆರಿಸಬೇಕು." + }, + "cloneItem": { + "message": "ಕ್ಲೋನ್ ಐಟಂ" + }, + "clone": { + "message": "ಕ್ಲೋನ್" + }, + "passwordGeneratorPolicyInEffect": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಸ್ಥೆ ನೀತಿಗಳು ನಿಮ್ಮ ಜನರೇಟರ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತವೆ" + }, + "vaultTimeoutAction": { + "message": "ವಾಲ್ಟ್ ಸಮಯ ಮೀರುವ ಕ್ರಿಯೆ" + }, + "lock": { + "message": "ಲಾಕ್‌", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "ಅನುಪಯುಕ್ತ", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "ಅನುಪಯುಕ್ತವನ್ನು ಹುಡುಕಿ" + }, + "permanentlyDeleteItem": { + "message": "ಐಟಂ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಿ" + }, + "permanentlyDeleteItemConfirmation": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "permanentlyDeletedItem": { + "message": "ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಲಾದ ಐಟಂ" + }, + "restoreItem": { + "message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಿ" + }, + "restoreItemConfirmation": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "restoredItem": { + "message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲಾಗಿದೆ" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "ಲಾಗ್ out ಟ್ ಆಗುವುದರಿಂದ ನಿಮ್ಮ ವಾಲ್ಟ್‌ನ ಎಲ್ಲಾ ಪ್ರವೇಶವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ ಮತ್ತು ಕಾಲಾವಧಿ ಅವಧಿಯ ನಂತರ ಆನ್‌ಲೈನ್ ದೃ hentic ೀಕರಣದ ಅಗತ್ಯವಿದೆ. ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬಳಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "ಕಾಲಾವಧಿ ಕ್ರಿಯೆಯ ದೃಢೀಕರಣ" + }, + "autoFillAndSave": { + "message": "ಸ್ವಯಂ ಭರ್ತಿ ಮತ್ತು ಉಳಿಸಿ" + }, + "autoFillSuccessAndSavedUri": { + "message": "ಸ್ವಯಂ ತುಂಬಿದ ಐಟಂ ಮತ್ತು ಉಳಿಸಿದ ಯುಆರ್ಐ" + }, + "autoFillSuccess": { + "message": "ಸ್ವಯಂ ತುಂಬಿದ ಐಟಂ" + }, + "setMasterPassword": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಹೊಂದಿಸಿ" + }, + "masterPasswordPolicyInEffect": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಸ್ಥೆ ನೀತಿಗಳಿಗೆ ಈ ಕೆಳಗಿನ ಅವಶ್ಯಕತೆಗಳನ್ನು ಪೂರೈಸಲು ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅಗತ್ಯವಿದೆ:" + }, + "policyInEffectMinComplexity": { + "message": "$SCORE$ ನ ಕನಿಷ್ಠ ಸಂಕೀರ್ಣತೆಯ ಸ್ಕೋರ್", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "$LENGTH$ನ ಕನಿಷ್ಠ ಉದ್ದ", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ದೊಡ್ಡಕ್ಷರಗಳನ್ನು ಹೊಂದಿರುತ್ತದೆ" + }, + "policyInEffectLowercase": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಣ್ಣ ಅಕ್ಷರಗಳನ್ನು ಹೊಂದಿರುತ್ತದೆ" + }, + "policyInEffectNumbers": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಖ್ಯೆಗಳನ್ನು ಹೊಂದಿರುತ್ತದೆ" + }, + "policyInEffectSpecial": { + "message": "ಕೆಳಗಿನ ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ವಿಶೇಷ ಅಕ್ಷರಗಳನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "ನಿಮ್ಮ ಹೊಸ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ನೀತಿಯ ಅವಶ್ಯಕತೆಗಳನ್ನು ಪೂರೈಸುವುದಿಲ್ಲ." + }, + "acceptPolicies": { + "message": "ಈ ಪೆಟ್ಟಿಗೆಯನ್ನು ಪರಿಶೀಲಿಸುವ ಮೂಲಕ ನೀವು ಈ ಕೆಳಗಿನವುಗಳನ್ನು ಒಪ್ಪುತ್ತೀರಿ:" + }, + "acceptPoliciesError": { + "message": "ಸೇವಾ ನಿಯಮಗಳು ಮತ್ತು ಗೌಪ್ಯತೆ ನೀತಿಯನ್ನು ಅಂಗೀಕರಿಸಲಾಗಿಲ್ಲ." + }, + "termsOfService": { + "message": "ಸೇವಾ ನಿಯಮಗಳು" + }, + "privacyPolicy": { + "message": "ಗೌಪ್ಯತಾ ನೀತಿ" + }, + "hintEqualsPassword": { + "message": "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಸುಳಿವು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ನಂತೆಯೇ ಇರಬಾರದು." + }, + "ok": { + "message": "ಸರಿ" + }, + "desktopSyncVerificationTitle": { + "message": "ಡೆಸ್ಕ್ಟಾಪ್ ಸಿಂಕ್ ಪರಿಶೀಲನೆ" + }, + "desktopIntegrationVerificationText": { + "message": "ಡೆಸ್ಕ್‌ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್ ಈ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಅನ್ನು ತೋರಿಸುತ್ತದೆ ಎಂಬುದನ್ನು ದಯವಿಟ್ಟು ಪರಿಶೀಲಿಸಿ:" + }, + "desktopIntegrationDisabledTitle": { + "message": "ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿಲ್ಲ" + }, + "desktopIntegrationDisabledDesc": { + "message": "ಬಿಟ್‌ವಾರ್ಡೆನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್‌ನಲ್ಲಿ ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿಲ್ಲ. ದಯವಿಟ್ಟು ಅದನ್ನು ಡೆಸ್ಕ್‌ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್‌ನಲ್ಲಿನ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಸಕ್ರಿಯಗೊಳಿಸಿ." + }, + "startDesktopTitle": { + "message": "ಬಿಟ್‌ವಾರ್ಡೆನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರಾರಂಭಿಸಿ" + }, + "startDesktopDesc": { + "message": "ಈ ಕಾರ್ಯವನ್ನು ಬಳಸುವ ಮೊದಲು ಬಿಟ್‌ವಾರ್ಡೆನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಪ್ರಾರಂಭಿಸಬೇಕಾಗಿದೆ." + }, + "errorEnableBiometricTitle": { + "message": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ" + }, + "errorEnableBiometricDesc": { + "message": "ಕ್ರಮವನ್ನು ಡೆಸ್ಕ್ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್ ರದ್ದುಗೊಳಿಸಲಾಯಿತು" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation\n" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "ಡೆಸ್ಕ್ಟಾಪ್ ಸಂವಹನ ಅಡಚಣೆ" + }, + "nativeMessagingWrongUserDesc": { + "message": "ಡೆಸ್ಕ್ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಬೇರೆ ಖಾತೆಗೆ ಲಾಗ್ ಮಾಡಲಾಗಿದೆ. ಎರಡೂ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಒಂದೇ ಖಾತೆಗೆ ಲಾಗ್ ಇನ್ ಆಗಿವೆ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ." + }, + "nativeMessagingWrongUserTitle": { + "message": "ಖಾತೆ ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ" + }, + "biometricsNotEnabledTitle": { + "message": "ಬಯೊಮಿಟ್ರಿಕ್ಸ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿಲ್ಲ" + }, + "biometricsNotEnabledDesc": { + "message": "ಬ್ರೌಸರ್ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಮೊದಲು ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಡೆಸ್ಕ್ಟಾಪ್ ಬಯೋಮೆಟ್ರಿಕ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕಾಗುತ್ತದೆ." + }, + "biometricsNotSupportedTitle": { + "message": "ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ" + }, + "biometricsNotSupportedDesc": { + "message": "ಬ್ರೌಸರ್ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಈ ಸಾಧನದಲ್ಲಿ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "ಅನುಮತಿ ಒದಗಿಸಲಾಗಿಲ್ಲ" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "ಬಿಟ್ವರ್ಡ್ ಡೆಸ್ಕ್ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್ನೊಂದಿಗೆ ಸಂವಹನ ಮಾಡಲು ಅನುಮತಿಯಿಲ್ಲದೆ ನಾವು ಬ್ರೌಸರ್ ವಿಸ್ತರಣೆಯಲ್ಲಿ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಅನ್ನು ಒದಗಿಸುವುದಿಲ್ಲ. ದಯವಿಟ್ಟು ಪುನಃ ಪ್ರಯತ್ನಿಸಿ." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "ಅನುಮತಿ ವಿನಂತಿ ದೋಷ" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "ಈ ಕ್ರಿಯೆಯನ್ನು ಸೈಡ್ಬಾರ್ನಲ್ಲಿ ಮಾಡಲಾಗುವುದಿಲ್ಲ, ದಯವಿಟ್ಟು ಪಾಪ್ಅಪ್ ಅಥವಾ ಪಾಪ್ಔಟ್ನಲ್ಲಿ ಕ್ರಿಯೆಯನ್ನು ಮರುಪ್ರಯತ್ನಿಸಿ." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "ಸಂಸ್ಥೆಯ ನೀತಿಯು ನಿಮ್ಮ ಮಾಲೀಕತ್ವದ ಆಯ್ಕೆಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತಿದೆ." + }, + "excludedDomains": { + "message": "ಹೊರತುಪಡಿಸಿದ ಡೊಮೇನ್ಗಳು" + }, + "excludedDomainsDesc": { + "message": "ಬಿಟ್ವಾರ್ಡ್ ಈ ಡೊಮೇನ್ಗಳಿಗಾಗಿ ಲಾಗಿನ್ ವಿವರಗಳನ್ನು ಉಳಿಸಲು ಕೇಳುವುದಿಲ್ಲ. ಬದಲಾವಣೆಗಳನ್ನು ಜಾರಿಗೆ ತರಲು ನೀವು ಪುಟವನ್ನು ರಿಫ್ರೆಶ್ ಮಾಡಬೇಕು." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ ಮಾನ್ಯವಾದ ಡೊಮೇನ್ ಅಲ್ಲ", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "ಹುಡುಕಾಟ ಕಳುಹಿಸುತ್ತದೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "ಕಳುಹಿಸು ಸೇರಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "ಪಠ್ಯ" + }, + "sendTypeFile": { + "message": "ಫೈಲ್" + }, + "allSends": { + "message": "ಎಲ್ಲಾ ಕಳುಹಿಸುತ್ತದೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "ಗರಿಷ್ಠ ಪ್ರವೇಶ ಎಣಿಕೆ ತಲುಪಿದೆ", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "ಅವಧಿ ಮೀರಿದೆ" + }, + "pendingDeletion": { + "message": "ಅಳಿಸುವಿಕೆ ಬಾಕಿ ಉಳಿದಿದೆ" + }, + "passwordProtected": { + "message": "ಪಾಸ್ವರ್ಡ್ ರಕ್ಷಿತ" + }, + "copySendLink": { + "message": "ಲಿಂಕ್ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ತೆಗೆದುಹಾಕಿ" + }, + "delete": { + "message": "ಅಳಿಸು" + }, + "removedPassword": { + "message": "ತೆಗೆದುಹಾಕಲಾದ ಪಾಸ್ವರ್ಡ್" + }, + "deletedSend": { + "message": "ಅಳಿಸಿದ ಕಳುಹಿಸಲಾಗಿದೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "ಲಿಂಕ್ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" + }, + "removePasswordConfirmation": { + "message": "ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ತೆಗೆದುಹಾಕಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "deleteSend": { + "message": "ಅಳಿಸಿ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "ಈ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "ಕಳುಹಿಸು ಸಂಪಾದಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "ಇದು ಯಾವ ರೀತಿಯ ಕಳುಹಿಸುತ್ತದೆ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "ಇದನ್ನು ಕಳುಹಿಸಲು ವಿವರಿಸಲು ಸ್ನೇಹಪರ ಹೆಸರು.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "ನೀವು ಕಳುಹಿಸಲು ಬಯಸುವ ಫೈಲ್." + }, + "deletionDate": { + "message": "ಅಳಿಸುವ ದಿನಾಂಕ" + }, + "deletionDateDesc": { + "message": "ಕಳುಹಿಸಿದ ದಿನಾಂಕ ಮತ್ತು ಸಮಯದ ಮೇಲೆ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಲಾಗುತ್ತದೆ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "ಮುಕ್ತಾಯ ದಿನಾಂಕ" + }, + "expirationDateDesc": { + "message": "ಹೊಂದಿಸಿದ್ದರೆ, ಈ ಕಳುಹಿಸುವಿಕೆಯ ಪ್ರವೇಶವು ನಿಗದಿತ ದಿನಾಂಕ ಮತ್ತು ಸಮಯದ ಮೇಲೆ ಮುಕ್ತಾಯಗೊಳ್ಳುತ್ತದೆ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 ದಿನ" + }, + "days": { + "message": "$DAYS$ ದಿನಗಳು", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "ಕಸ್ಟಮ್" + }, + "maximumAccessCount": { + "message": "ಗರಿಷ್ಠ ಪ್ರವೇಶ ಎಣಿಕೆ" + }, + "maximumAccessCountDesc": { + "message": "ಹೊಂದಿಸಿದ್ದರೆ, ಗರಿಷ್ಠ ಪ್ರವೇಶ ಎಣಿಕೆ ತಲುಪಿದ ನಂತರ ಬಳಕೆದಾರರಿಗೆ ಈ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "ಈ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಬಳಕೆದಾರರಿಗೆ ಪಾಸ್‌ವರ್ಡ್ ಐಚ್ ಗತ್ಯವಿದೆ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "ಈ ಕಳುಹಿಸುವ ಬಗ್ಗೆ ಖಾಸಗಿ ಟಿಪ್ಪಣಿಗಳು.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "ಇದನ್ನು ಕಳುಹಿಸುವುದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇದರಿಂದ ಯಾರೂ ಅದನ್ನು ಪ್ರವೇಶಿಸಲಾಗುವುದಿಲ್ಲ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "ಉಳಿಸಿದ ನಂತರ ಈ ಕಳುಹಿಸುವ ಲಿಂಕ್ ಅನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ನಕಲಿಸಿ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "ನೀವು ಕಳುಹಿಸಲು ಬಯಸುವ ಪಠ್ಯ." + }, + "sendHideText": { + "message": "ಪೂರ್ವನಿಯೋಜಿತವಾಗಿ ಈ ಕಳುಹಿಸುವ ಪಠ್ಯವನ್ನು ಮರೆಮಾಡಿ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "ಪ್ರಸ್ತುತ ಪ್ರವೇಶ ಎಣಿಕೆ" + }, + "createSend": { + "message": "ಹೊಸ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ರಚಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "ಹೊಸ ಪಾಸ್‌ವರ್ಡ್" + }, + "sendDisabled": { + "message": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "ಕಳುಹಿಸು ರಚಿಸಲಾಗಿದೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "ಕಳುಹಿಸಿದ ಸಂಪಾದನೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "ಫೈಲ್ ಅನ್ನು ಆಯ್ಕೆ ಮಾಡಲು, ಸೈಡ್‌ಬಾರ್‌ನಲ್ಲಿ ವಿಸ್ತರಣೆಯನ್ನು ತೆರೆಯಿರಿ (ಸಾಧ್ಯವಾದರೆ) ಅಥವಾ ಈ ಬ್ಯಾನರ್ ಕ್ಲಿಕ್ ಮಾಡುವ ಮೂಲಕ ಹೊಸ ವಿಂಡೋಗೆ ಪಾಪ್ಔಟ್ ಮಾಡಿ." + }, + "sendFirefoxFileWarning": { + "message": "ಫೈರ್‌ಫಾಕ್ಸ್ ಬಳಸಿ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಲು, ಸೈಡ್‌ಬಾರ್‌ನಲ್ಲಿ ವಿಸ್ತರಣೆಯನ್ನು ತೆರೆಯಿರಿ ಅಥವಾ ಈ ಬ್ಯಾನರ್ ಕ್ಲಿಕ್ ಮಾಡುವ ಮೂಲಕ ಹೊಸ ವಿಂಡೋಗೆ ಪಾಪ್ಔಟ್ ಮಾಡಿ." + }, + "sendSafariFileWarning": { + "message": "ಸಫಾರಿ ಬಳಸಿ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಲು, ಈ ಬ್ಯಾನರ್ ಕ್ಲಿಕ್ ಮಾಡುವ ಮೂಲಕ ಹೊಸ ವಿಂಡೋಗೆ ಪಾಪ್ಔಟ್ ಮಾಡಿ." + }, + "sendFileCalloutHeader": { + "message": "ನೀವು ಪ್ರಾರಂಭಿಸುವ ಮೊದಲು" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "ಕ್ಯಾಲೆಂಡರ್ ಶೈಲಿಯ ದಿನಾಂಕ ಆಯ್ದುಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬಳಸಲು", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "ಕ್ಲಿಕ್ ಮಾಡಿ", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "ನಿಮ್ಮ ವಿಂಡೋವನ್ನು ಪಾಪ್ಔಟ್ ಮಾಡಲು.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "ಒದಗಿಸಿದ ಮುಕ್ತಾಯ ದಿನಾಂಕವು ಮಾನ್ಯವಾಗಿಲ್ಲ." + }, + "deletionDateIsInvalid": { + "message": "ಒದಗಿಸಿದ ಅಳಿಸುವ ದಿನಾಂಕವು ಮಾನ್ಯವಾಗಿಲ್ಲ." + }, + "expirationDateAndTimeRequired": { + "message": "ಮುಕ್ತಾಯ ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ಅಗತ್ಯವಿದೆ." + }, + "deletionDateAndTimeRequired": { + "message": "ಅಳಿಸುವ ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ಅಗತ್ಯವಿದೆ." + }, + "dateParsingError": { + "message": "ನಿಮ್ಮ ಅಳಿಸುವಿಕೆ ಮತ್ತು ಮುಕ್ತಾಯ ದಿನಾಂಕಗಳನ್ನು ಉಳಿಸುವಲ್ಲಿ ದೋಷ ಕಂಡುಬಂದಿದೆ." + }, + "hideEmail": { + "message": "ಸ್ವೀಕರಿಸುವವರಿಂದ ನನ್ನ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ಮರೆಮಾಡಿ." + }, + "sendOptionsPolicyInEffect": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಸ್ಥೆಯ ನೀತಿಗಳು ನಿಮ್ಮ ಕಳುಹಿಸುವ ಆಯ್ಕೆಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತವೆ." + }, + "passwordPrompt": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಮರು-ಪ್ರಾಂಪ್ಟ್" + }, + "passwordConfirmation": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ದೃಢೀಕರಣ" + }, + "passwordConfirmationDesc": { + "message": "ಮುಂದುವರಿಯಲು ಈ ಕ್ರಿಯೆಯನ್ನು ರಕ್ಷಿಸಲಾಗಿದೆ, ದಯವಿಟ್ಟು ನಿಮ್ಮ ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಲು ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರು ನಮೂದಿಸಿ." + }, + "emailVerificationRequired": { + "message": "ಇಮೇಲ್ ಪರಿಶೀಲನೆ ಅಗತ್ಯವಿದೆ" + }, + "emailVerificationRequiredDesc": { + "message": "ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು ನಿಮ್ಮ ಇಮೇಲ್ ಅನ್ನು ನೀವು ಪರಿಶೀಲಿಸಬೇಕು. ವೆಬ್ ವಾಲ್ಟ್ನಲ್ಲಿ ನಿಮ್ಮ ಇಮೇಲ್ ಅನ್ನು ನೀವು ಪರಿಶೀಲಿಸಬಹುದು." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/ko/messages.json b/apps/browser/src/_locales/ko/messages.json new file mode 100644 index 0000000000..639d216961 --- /dev/null +++ b/apps/browser/src/_locales/ko/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - 무료 비밀번호 관리자", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "당신의 모든 기기에서 사용할 수 있는, 안전한 무료 비밀번호 관리자입니다.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "안전 보관함에 접근하려면 로그인하거나 새 계정을 만드세요." + }, + "createAccount": { + "message": "계정 만들기" + }, + "login": { + "message": "로그인" + }, + "enterpriseSingleSignOn": { + "message": "엔터프라이즈 통합 인증 (SSO)" + }, + "cancel": { + "message": "취소" + }, + "close": { + "message": "닫기" + }, + "submit": { + "message": "보내기" + }, + "emailAddress": { + "message": "이메일 주소" + }, + "masterPass": { + "message": "마스터 비밀번호" + }, + "masterPassDesc": { + "message": "마스터 비밀번호는 보관함을 열 때 필요한 비밀번호입니다. 절대 마스터 비밀번호를 잊어버리지 마세요. 잊어버리면 복구할 수 있는 방법이 없습니다." + }, + "masterPassHintDesc": { + "message": "마스터 비밀번호 힌트는 마스터 비밀번호를 잊었을 때 도움이 될 수 있습니다." + }, + "reTypeMasterPass": { + "message": "마스터 비밀번호 다시 입력" + }, + "masterPassHint": { + "message": "마스터 비밀번호 힌트 (선택)" + }, + "tab": { + "message": "탭" + }, + "myVault": { + "message": "내 보관함" + }, + "tools": { + "message": "도구" + }, + "settings": { + "message": "설정" + }, + "currentTab": { + "message": "현재 탭" + }, + "copyPassword": { + "message": "비밀번호 복사" + }, + "copyNote": { + "message": "메모 복사" + }, + "copyUri": { + "message": "URI 복사" + }, + "copyUsername": { + "message": "사용자 이름 복사" + }, + "copyNumber": { + "message": "번호 복사" + }, + "copySecurityCode": { + "message": "보안 코드 복사" + }, + "autoFill": { + "message": "자동 완성" + }, + "generatePasswordCopied": { + "message": "비밀번호 생성 및 클립보드에 복사" + }, + "copyElementIdentifier": { + "message": "사용자 지정 필드 이름 복사" + }, + "noMatchingLogins": { + "message": "사용할 수 있는 로그인이 없습니다." + }, + "unlockVaultMenu": { + "message": "보관함 잠금 해제" + }, + "loginToVaultMenu": { + "message": "보관함에 로그인하기" + }, + "autoFillInfo": { + "message": "이 탭의 자동 완성에 사용할 수 있는 로그인이 없습니다." + }, + "addLogin": { + "message": "로그인 추가" + }, + "addItem": { + "message": "항목 추가" + }, + "passwordHint": { + "message": "비밀번호 힌트" + }, + "enterEmailToGetHint": { + "message": "마스터 비밀번호 힌트를 받으려면 계정의 이메일 주소를 입력하세요." + }, + "getMasterPasswordHint": { + "message": "마스터 비밀번호 힌트 얻기" + }, + "continue": { + "message": "계속" + }, + "sendVerificationCode": { + "message": "이메일로 인증 코드 보내기" + }, + "sendCode": { + "message": "코드 전송" + }, + "codeSent": { + "message": "코드 전송됨" + }, + "verificationCode": { + "message": "인증 코드" + }, + "confirmIdentity": { + "message": "계속하려면 암호를 확인하세요." + }, + "account": { + "message": "계정" + }, + "changeMasterPassword": { + "message": "마스터 비밀번호 변경" + }, + "fingerprintPhrase": { + "message": "지문 구절", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "계정 지문 구절", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "2단계 인증" + }, + "logOut": { + "message": "로그아웃" + }, + "about": { + "message": "정보" + }, + "version": { + "message": "버전" + }, + "save": { + "message": "저장" + }, + "move": { + "message": "이동" + }, + "addFolder": { + "message": "폴더 추가" + }, + "name": { + "message": "이름" + }, + "editFolder": { + "message": "폴더 편집" + }, + "deleteFolder": { + "message": "폴더 삭제" + }, + "folders": { + "message": "폴더" + }, + "noFolders": { + "message": "폴더가 없습니다." + }, + "helpFeedback": { + "message": "도움말 및 의견" + }, + "sync": { + "message": "동기화" + }, + "syncVaultNow": { + "message": "지금 보관함 동기화" + }, + "lastSync": { + "message": "마지막 동기화:" + }, + "passGen": { + "message": "비밀번호 생성기" + }, + "generator": { + "message": "생성기", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "유일무이하고 강력한 비밀번호를 자동으로 생성합니다." + }, + "bitWebVault": { + "message": "Bitwarden 웹 보관함" + }, + "importItems": { + "message": "항목 가져오기" + }, + "select": { + "message": "선택" + }, + "generatePassword": { + "message": "비밀번호 생성" + }, + "regeneratePassword": { + "message": "비밀번호 재생성" + }, + "options": { + "message": "옵션" + }, + "length": { + "message": "길이" + }, + "uppercase": { + "message": "대문자 (A-Z)" + }, + "lowercase": { + "message": "소문자 (a-z)" + }, + "numbers": { + "message": "숫자 (0-9)" + }, + "specialCharacters": { + "message": "특수 문자 (!@#$%^&*)" + }, + "numWords": { + "message": "단어 수" + }, + "wordSeparator": { + "message": "구분 기호" + }, + "capitalize": { + "message": "첫 글자를 대문자로", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "숫자 포함" + }, + "minNumbers": { + "message": "숫자 최소 개수" + }, + "minSpecial": { + "message": "특수 문자 최소 개수" + }, + "avoidAmbChar": { + "message": "모호한 문자 사용 안 함" + }, + "searchVault": { + "message": "보관함 검색" + }, + "edit": { + "message": "편집" + }, + "view": { + "message": "보기" + }, + "noItemsInList": { + "message": "항목이 없습니다." + }, + "itemInformation": { + "message": "항목 정보" + }, + "username": { + "message": "사용자 이름" + }, + "password": { + "message": "비밀번호" + }, + "passphrase": { + "message": "패스프레이즈" + }, + "favorite": { + "message": "즐겨찾기" + }, + "notes": { + "message": "메모" + }, + "note": { + "message": "메모" + }, + "editItem": { + "message": "항목 편집" + }, + "folder": { + "message": "폴더" + }, + "deleteItem": { + "message": "항목 삭제" + }, + "viewItem": { + "message": "항목 보기" + }, + "launch": { + "message": "열기" + }, + "website": { + "message": "웹 사이트" + }, + "toggleVisibility": { + "message": "표시 전환" + }, + "manage": { + "message": "관리" + }, + "other": { + "message": "기타" + }, + "rateExtension": { + "message": "확장 프로그램 평가" + }, + "rateExtensionDesc": { + "message": "좋은 리뷰를 남겨 저희를 도와주세요!" + }, + "browserNotSupportClipboard": { + "message": "사용하고 있는 웹 브라우저가 쉬운 클립보드 복사를 지원하지 않습니다. 직접 복사하세요." + }, + "verifyIdentity": { + "message": "신원 확인" + }, + "yourVaultIsLocked": { + "message": "보관함이 잠겨 있습니다. 마스터 비밀번호를 입력하여 계속하세요." + }, + "unlock": { + "message": "잠금 해제" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ 에 $EMAIL$ 로 로그인했습니다.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "잘못된 마스터 비밀번호" + }, + "vaultTimeout": { + "message": "보관함 시간 제한" + }, + "lockNow": { + "message": "지금 잠그기" + }, + "immediately": { + "message": "즉시" + }, + "tenSeconds": { + "message": "10초" + }, + "twentySeconds": { + "message": "20초" + }, + "thirtySeconds": { + "message": "30초" + }, + "oneMinute": { + "message": "1분" + }, + "twoMinutes": { + "message": "2분" + }, + "fiveMinutes": { + "message": "5분" + }, + "fifteenMinutes": { + "message": "15분" + }, + "thirtyMinutes": { + "message": "30분" + }, + "oneHour": { + "message": "1시간" + }, + "fourHours": { + "message": "4시간" + }, + "onLocked": { + "message": "시스템 잠금 시" + }, + "onRestart": { + "message": "브라우저 다시 시작 시" + }, + "never": { + "message": "잠그지 않음" + }, + "security": { + "message": "보안" + }, + "errorOccurred": { + "message": "오류가 발생했습니다" + }, + "emailRequired": { + "message": "이메일은 반드시 입력해야 합니다." + }, + "invalidEmail": { + "message": "잘못된 이메일 주소입니다." + }, + "masterPassRequired": { + "message": "마스터 비밀번호는 반드시 입력해야 합니다." + }, + "masterPassLength": { + "message": "마스터 비밀번호는 최소 8자 이상이어야 합니다." + }, + "masterPassDoesntMatch": { + "message": "마스터 비밀번호 확인과 마스터 비밀번호가 일치하지 않습니다." + }, + "newAccountCreated": { + "message": "계정 생성이 완료되었습니다! 이제 로그인하실 수 있습니다." + }, + "masterPassSent": { + "message": "마스터 비밀번호 힌트가 담긴 이메일을 보냈습니다." + }, + "verificationCodeRequired": { + "message": "인증 코드는 반드시 입력해야 합니다." + }, + "invalidVerificationCode": { + "message": "유효하지 않은 확인 코드" + }, + "valueCopied": { + "message": "$VALUE$를 클립보드에 복사함", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "선택한 항목을 이 페이지에서 자동 완성할 수 없습니다. 대신 정보를 직접 복사 / 붙여넣기하여 사용하십시오." + }, + "loggedOut": { + "message": "로그아웃됨" + }, + "loginExpired": { + "message": "로그인 세션이 만료되었습니다." + }, + "logOutConfirmation": { + "message": "정말 로그아웃하시겠습니까?" + }, + "yes": { + "message": "예" + }, + "no": { + "message": "아니오" + }, + "unexpectedError": { + "message": "예기치 못한 오류가 발생했습니다." + }, + "nameRequired": { + "message": "이름은 반드시 입력해야 합니다." + }, + "addedFolder": { + "message": "폴더 추가함" + }, + "changeMasterPass": { + "message": "마스터 비밀번호 변경" + }, + "changeMasterPasswordConfirmation": { + "message": "bitwarden.com 웹 보관함에서 마스터 비밀번호를 바꿀 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "twoStepLoginConfirmation": { + "message": "2단계 인증은 보안 키, 인증 앱, SMS, 전화 통화 등의 다른 기기로 사용자의 로그인 시도를 검증하여 사용자의 계정을 더욱 안전하게 만듭니다. 2단계 인증은 bitwarden.com 웹 보관함에서 활성화할 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "editedFolder": { + "message": "폴더 편집함" + }, + "deleteFolderConfirmation": { + "message": "정말 이 폴더를 삭제하시겠습니까?" + }, + "deletedFolder": { + "message": "폴더 삭제함" + }, + "gettingStartedTutorial": { + "message": "시작하기 튜토리얼" + }, + "gettingStartedTutorialVideo": { + "message": "브라우저 확장 프로그램을 최대한 활용하는 방법을 알아보려면 시작하기 튜토리얼을 확인하세요." + }, + "syncingComplete": { + "message": "동기화 완료" + }, + "syncingFailed": { + "message": "동기화 실패" + }, + "passwordCopied": { + "message": "비밀번호를 클립보드에 복사함" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "새 URI" + }, + "addedItem": { + "message": "항목 추가함" + }, + "editedItem": { + "message": "항목 편집함" + }, + "deleteItemConfirmation": { + "message": "정말로 휴지통으로 이동시킬까요?" + }, + "deletedItem": { + "message": "항목 삭제함" + }, + "overwritePassword": { + "message": "비밀번호 덮어쓰기" + }, + "overwritePasswordConfirmation": { + "message": "정말 현재 비밀번호를 덮어쓰시겠습니까?" + }, + "overwriteUsername": { + "message": "아이디 덮어쓰기" + }, + "overwriteUsernameConfirmation": { + "message": "정말 현재 아이디를 덮어쓰시겠습니까?" + }, + "searchFolder": { + "message": "폴더 검색" + }, + "searchCollection": { + "message": "컬렉션 검색" + }, + "searchType": { + "message": "검색 유형" + }, + "noneFolder": { + "message": "폴더 없음", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "로그인 추가 알림 사용 안 함" + }, + "addLoginNotificationDesc": { + "message": "\"로그인 추가 알림\"을 사용하면 새 로그인을 사용할 때마다 보관함에 그 로그인을 추가할 것인지 물어봅니다." + }, + "dontShowCardsCurrentTab": { + "message": "탭 페이지에 카드 표시 안 함" + }, + "dontShowCardsCurrentTabDesc": { + "message": "보관함의 카드 항목은 쉽게 자동 완성할 수 있게끔 '현재 탭' 페이지에 나열되어 있습니다." + }, + "dontShowIdentitiesCurrentTab": { + "message": "탭 페이지에 신원 표시 안 함" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "보관함의 신원 항목은 쉽게 자동 완성할 수 있게끔 '현재 탭' 페이지에 나열되어 있습니다." + }, + "clearClipboard": { + "message": "클립보드 비우기", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "자동으로 클립보드에 복사된 값을 제거합니다.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Bitwarden이 이 비밀번호를 기억하도록 하시겠습니까?" + }, + "notificationAddSave": { + "message": "예, 지금 저장하겠습니다." + }, + "disableChangedPasswordNotification": { + "message": "비밀번호 변경 알림 사용 안 함" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"비밀번호 변경 알림\"을 사용하면 사용자가 웹 사이트에서 비밀번호를 변경했을 경우, 보관함에 저장된 비밀번호를 업데이트할 것인지 자동으로 물어봅니다." + }, + "notificationChangeDesc": { + "message": "Bitwarden에 저장되어 있는 비밀번호를 이 비밀번호로 변경하시겠습니까?" + }, + "notificationChangeSave": { + "message": "예, 지금 변경하겠습니다." + }, + "disableContextMenuItem": { + "message": "오른쪽 클릭 메뉴 옵션 사용 안 함" + }, + "disableContextMenuItemDesc": { + "message": "오른쪽 클릭 메뉴 옵션을 사용하면 비밀번호 생성이나 현재 탭 웹 사이트의 로그인에 빠르게 접근할 수 있습니다." + }, + "defaultUriMatchDetection": { + "message": "기본 URI 일치 인식", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "자동 완성 등의 작업에서 각 로그인 항목의 URI 일치 감지를 처리할 기본 방법을 선택하세요." + }, + "theme": { + "message": "테마" + }, + "themeDesc": { + "message": "애플리케이션의 색상 테마를 변경합니다." + }, + "dark": { + "message": "어두운 테마", + "description": "Dark color" + }, + "light": { + "message": "밝은 테마", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "보관함 내보내기" + }, + "fileFormat": { + "message": "파일 형식" + }, + "warning": { + "message": "경고", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "보관함 내보내기 확인" + }, + "exportWarningDesc": { + "message": "내보내기는 보관함 데이터가 암호화되지 않은 형식으로 포함됩니다. 내보낸 파일을 안전하지 않은 채널(예: 이메일)을 통해 저장하거나 보내지 마십시오. 사용이 끝난 후에는 즉시 삭제하십시오." + }, + "encExportKeyWarningDesc": { + "message": "이 내보내기는 계정의 암호화 키를 사용하여 데이터를 암호화합니다. 추후 계정의 암호화 키를 교체할 경우 다시 내보내기를 진행해야 합니다. 그러지 않을 경우 이 내보내기 파일을 해독할 수 없게 됩니다." + }, + "encExportAccountWarningDesc": { + "message": "모든 Bitwarden 사용자 계정은 고유한 계정 암호화 키를 가지고 있습니다. 따라서, 다른 계정에서는 암호화된 내보내기를 가져올 수 없습니다." + }, + "exportMasterPassword": { + "message": "보관함 데이터를 내보내려면 마스터 비밀번호를 입력하세요." + }, + "shared": { + "message": "공유됨" + }, + "learnOrg": { + "message": "조직에 대해 알아보기" + }, + "learnOrgConfirmation": { + "message": "Bitwarden은 조직용 계정을 사용하면 사용자의 보관함을 타인에게 공유할 수 있습니다. bitwarden.com 웹 사이트를 방문하여 더 자세히 알아보시겠습니까?" + }, + "moveToOrganization": { + "message": "조직으로 이동하기" + }, + "share": { + "message": "공유" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$이(가) $ORGNAME$(으)로 이동됨", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "이 항목을 이동할 조직을 선택하십시오. 항목이 조직으로 이동되면 소유권이 조직으로 이전됩니다. 일단 이동되면, 더는 이동된 항목의 직접적인 소유자가 아니게 됩니다." + }, + "learnMore": { + "message": "더 알아보기" + }, + "authenticatorKeyTotp": { + "message": "인증 키 (TOTP)" + }, + "verificationCodeTotp": { + "message": "인증 코드 (TOTP)" + }, + "copyVerificationCode": { + "message": "인증 코드 복사" + }, + "attachments": { + "message": "첨부 파일" + }, + "deleteAttachment": { + "message": "첨부 파일 삭제" + }, + "deleteAttachmentConfirmation": { + "message": "정말 이 첨부 파일을 삭제하시겠습니까?" + }, + "deletedAttachment": { + "message": "첨부 파일 삭제함" + }, + "newAttachment": { + "message": "새 첨부 파일 추가" + }, + "noAttachments": { + "message": "첨부 파일이 없습니다." + }, + "attachmentSaved": { + "message": "첨부 파일을 저장했습니다." + }, + "file": { + "message": "파일" + }, + "selectFile": { + "message": "파일을 선택하세요." + }, + "maxFileSize": { + "message": "최대 파일 크기는 500MB입니다." + }, + "featureUnavailable": { + "message": "기능 사용할 수 없음" + }, + "updateKey": { + "message": "이 기능을 사용하려면 암호화 키를 업데이트해야 합니다." + }, + "premiumMembership": { + "message": "프리미엄 멤버십" + }, + "premiumManage": { + "message": "멤버십 관리" + }, + "premiumManageAlert": { + "message": "bitwarden.com 웹 보관함에서 멤버십을 관리할 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "premiumRefresh": { + "message": "멤버십 새로 고침" + }, + "premiumNotCurrentMember": { + "message": "프리미엄 사용자가 아닙니다." + }, + "premiumSignUpAndGet": { + "message": "프리미엄 멤버십에 가입하면 얻을 수 있는 것:" + }, + "ppremiumSignUpStorage": { + "message": "1GB의 암호화된 파일 저장소." + }, + "ppremiumSignUpTwoStep": { + "message": "YubiKey나 FIDO U2F, Duo 등의 추가적인 2단계 인증 옵션." + }, + "ppremiumSignUpReports": { + "message": "보관함을 안전하게 유지하기 위한 암호 위생, 계정 상태, 데이터 유출 보고서" + }, + "ppremiumSignUpTotp": { + "message": "보관함에 등록된 로그인 항목을 위한 TOTP 인증 코드(2FA) 생성기." + }, + "ppremiumSignUpSupport": { + "message": "고객 지원 우선 순위 제공." + }, + "ppremiumSignUpFuture": { + "message": "앞으로 추가될 모든 프리미엄 기능을 사용할 수 있습니다. 기대하세요!" + }, + "premiumPurchase": { + "message": "프리미엄 멤버십 구입" + }, + "premiumPurchaseAlert": { + "message": "bitwarden.com 웹 보관함에서 프리미엄 멤버십을 구입할 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "premiumCurrentMember": { + "message": "프리미엄 사용자입니다!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden을 지원해 주셔서 감사합니다." + }, + "premiumPrice": { + "message": "이 모든 기능을 연 $PRICE$에 이용하실 수 있습니다!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "새로 고침 완료" + }, + "disableAutoTotpCopy": { + "message": "TOTP 자동 복사 사용 안 함" + }, + "disableAutoTotpCopyDesc": { + "message": "로그인에 인증 키가 연결되어 있을 경우, 그 로그인을 자동 완성할 때마다 TOTP 인증 코드가 클립보드에 자동으로 복사됩니다." + }, + "disableAutoBiometricsPrompt": { + "message": "시작할 때 생체 인증 요구하지 않음" + }, + "premiumRequired": { + "message": "프리미엄 멤버십 필요" + }, + "premiumRequiredDesc": { + "message": "이 기능을 사용하려면 프리미엄 멤버십이 필요합니다." + }, + "enterVerificationCodeApp": { + "message": "인증 앱에서 6자리 인증 코드를 입력하세요." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ 주소로 전송된 6자리 인증 코드를 입력하세요.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "$EMAIL$ 주소로 인증 이메일을 보냈습니다.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "기억하기" + }, + "sendVerificationCodeEmailAgain": { + "message": "인증 코드 이메일 다시 보내기" + }, + "useAnotherTwoStepMethod": { + "message": "다른 2단계 인증 사용" + }, + "insertYubiKey": { + "message": "YubiKey를 컴퓨터의 USB 포트에 삽입하고 이 버튼을 누르세요." + }, + "insertU2f": { + "message": "보안 키를 컴퓨터의 USB 포트에 삽입하고 버튼이 있는 경우 누르세요." + }, + "webAuthnNewTab": { + "message": "새 탭에서 WebAuthn 2단계 인증을 계속하세요." + }, + "webAuthnNewTabOpen": { + "message": "새 탭 열기" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn 인증" + }, + "loginUnavailable": { + "message": "로그인 불가능" + }, + "noTwoStepProviders": { + "message": "이 계정은 2단계 인증을 사용합니다. 그러나 설정된 2단계 인증 중 이 웹 브라우저에서 지원하는 방식이 없습니다." + }, + "noTwoStepProviders2": { + "message": "지원하는 웹 브라우저(Chrome 등)를 사용하거나 더 많은 브라우저를 지원하는 2단계 인증 방식(인증 앱 등)을 추가하세요." + }, + "twoStepOptions": { + "message": "2단계 인증 옵션" + }, + "recoveryCodeDesc": { + "message": "모든 2단계 인증을 사용할 수 없는 상황인가요? 복구 코드를 사용하여 계정의 모든 2단계 인증을 비활성화할 수 있습니다." + }, + "recoveryCodeTitle": { + "message": "복구 코드" + }, + "authenticatorAppTitle": { + "message": "인증 앱" + }, + "authenticatorAppDesc": { + "message": "인증 앱(Authy, Google OTP 등)을 통하여 일회용 인증 코드를 생성합니다.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP 보안 키" + }, + "yubiKeyDesc": { + "message": "YubiKey를 사용하여 사용자의 계정에 접근합니다. YubiKey 4, 4 Nano, 4C 및 NEO 기기를 사용할 수 있습니다." + }, + "duoDesc": { + "message": "Duo Mobile 앱, SMS, 전화 통화를 사용한 Duo Security 또는 U2F 보안 키를 사용하여 인증하세요.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo Mobile 앱, SMS, 전화 통화를 사용한 조직용 Duo Security 또는 U2F 보안 키를 사용하여 인증하세요.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "WebAuthn이 활성화된 보안 키를 사용하여 계정에 접근하세요." + }, + "emailTitle": { + "message": "이메일" + }, + "emailDesc": { + "message": "인증 코드가 담긴 이메일을 다시 보냅니다." + }, + "selfHostedEnvironment": { + "message": "자체 호스팅 환경" + }, + "selfHostedEnvironmentFooter": { + "message": "온-프레미스 Bitwarden이 호스팅되고 있는 서버의 기본 URL을 지정하세요." + }, + "customEnvironment": { + "message": "사용자 지정 환경" + }, + "customEnvironmentFooter": { + "message": "고급 사용자 전용 설정입니다. 각 서비스의 기본 URL을 개별적으로 지정할 수 있습니다." + }, + "baseUrl": { + "message": "서버 URL" + }, + "apiUrl": { + "message": "API 서버 URL" + }, + "webVaultUrl": { + "message": "웹 보관함 서버 URL" + }, + "identityUrl": { + "message": "ID 서버 URL" + }, + "notificationsUrl": { + "message": "알림 서버 URL" + }, + "iconsUrl": { + "message": "아이콘 서버 URL" + }, + "environmentSaved": { + "message": "환경 URL 값을 저장했습니다." + }, + "enableAutoFillOnPageLoad": { + "message": "페이지 로드 시 자동 완성 사용" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "로그인 양식을 감지하면 웹 페이지 로드 시 자동 완성을 자동으로 수행합니다." + }, + "experimentalFeature": { + "message": "현재 실험 중인 기능입니다. 위험을 감수하여 사용하세요." + }, + "defaultAutoFillOnPageLoad": { + "message": "로그인 항목에 대한 기본 자동 완성 설정" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "페이지 로드 시 자동 완성을 켠 뒤에는 각 로그인 항목별로 이 기능을 켜거나 끌 수 있습니다. 이 옵션은 해당 기능을 개별적으로 구성하지 않은 항목에 사용되는 기본 설정값입니다." + }, + "itemAutoFillOnPageLoad": { + "message": "페이지 로드 시 자동 완성 (옵션에서 켜져 있을 경우)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "기본 설정 사용" + }, + "autoFillOnPageLoadYes": { + "message": "페이지 로드 시 자동 완성" + }, + "autoFillOnPageLoadNo": { + "message": "페이지 로드 시 자동 완성 안 함" + }, + "commandOpenPopup": { + "message": "보관함 팝업 열기" + }, + "commandOpenSidebar": { + "message": "사이드바에서 보관함 열기" + }, + "commandAutofillDesc": { + "message": "현재 웹사이트에서 최근에 사용했던 로그인을 자동 완성합니다." + }, + "commandGeneratePasswordDesc": { + "message": "새 무작위 비밀번호를 만들고 클립보드에 복사합니다." + }, + "commandLockVaultDesc": { + "message": "보관함 잠그기" + }, + "privateModeWarning": { + "message": "시크릿 모드 지원은 실험적이며 일부 기능이 제한됩니다." + }, + "customFields": { + "message": "사용자 지정 필드" + }, + "copyValue": { + "message": "값 복사" + }, + "value": { + "message": "값" + }, + "newCustomField": { + "message": "새 사용자 지정 필드" + }, + "dragToSort": { + "message": "드래그하여 정렬" + }, + "cfTypeText": { + "message": "텍스트" + }, + "cfTypeHidden": { + "message": "숨김" + }, + "cfTypeBoolean": { + "message": "참 / 거짓" + }, + "cfTypeLinked": { + "message": "연결됨", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "연결된 값", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "인증 코드가 담긴 이메일을 확인하기 위해 팝업 창의 바깥쪽을 누르면 이 팝업이 닫힙니다. 팝업 창이 닫히는 것을 방지하기 위해 이 팝업을 새 창에서 다시 여시겠습니까?" + }, + "popupU2fCloseMessage": { + "message": "이 브라우저의 팝업 창에서는 U2F 요청을 처리할 수 없습니다. U2F로 로그인할 수 있도록 이 창을 새 창에서 여시겠습니까?" + }, + "disableFavicon": { + "message": "웹 사이트 아이콘 사용 안 함" + }, + "disableFaviconDesc": { + "message": "웹 사이트 아이콘을 사용하면 보관함 각 항목 옆에 이미지를 보여줍니다." + }, + "disableBadgeCounter": { + "message": "배지에 개수 표시 사용 안 함" + }, + "disableBadgeCounterDesc": { + "message": "배지에는 보관함에 등록된 현재 페이지에 대한 로그인의 개수가 표시됩니다." + }, + "cardholderName": { + "message": "카드 소유자 이름" + }, + "number": { + "message": "번호" + }, + "brand": { + "message": "브랜드" + }, + "expirationMonth": { + "message": "만료 월" + }, + "expirationYear": { + "message": "만료 연도" + }, + "expiration": { + "message": "만료" + }, + "january": { + "message": "1월" + }, + "february": { + "message": "2월" + }, + "march": { + "message": "3월" + }, + "april": { + "message": "4월" + }, + "may": { + "message": "5월" + }, + "june": { + "message": "6월" + }, + "july": { + "message": "7월" + }, + "august": { + "message": "8월" + }, + "september": { + "message": "9월" + }, + "october": { + "message": "10월" + }, + "november": { + "message": "11월" + }, + "december": { + "message": "12월" + }, + "securityCode": { + "message": "보안 코드" + }, + "ex": { + "message": "예)" + }, + "title": { + "message": "제목" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "이름" + }, + "middleName": { + "message": "가운데 이름" + }, + "lastName": { + "message": "성" + }, + "fullName": { + "message": "전체 이름" + }, + "identityName": { + "message": "ID 이름" + }, + "company": { + "message": "회사" + }, + "ssn": { + "message": "주민등록번호" + }, + "passportNumber": { + "message": "여권 번호" + }, + "licenseNumber": { + "message": "면허 번호" + }, + "email": { + "message": "이메일" + }, + "phone": { + "message": "전화번호" + }, + "address": { + "message": "주소" + }, + "address1": { + "message": "주소 1" + }, + "address2": { + "message": "주소 2" + }, + "address3": { + "message": "주소 3" + }, + "cityTown": { + "message": "읍 / 면 / 동" + }, + "stateProvince": { + "message": "시 / 도" + }, + "zipPostalCode": { + "message": "우편번호" + }, + "country": { + "message": "국가" + }, + "type": { + "message": "유형" + }, + "typeLogin": { + "message": "로그인" + }, + "typeLogins": { + "message": "로그인" + }, + "typeSecureNote": { + "message": "보안 메모" + }, + "typeCard": { + "message": "카드" + }, + "typeIdentity": { + "message": "신원" + }, + "passwordHistory": { + "message": "비밀번호 변경 기록" + }, + "back": { + "message": "뒤로" + }, + "collections": { + "message": "컬렉션" + }, + "favorites": { + "message": "즐겨찾기" + }, + "popOutNewWindow": { + "message": "새 창에서 보기" + }, + "refresh": { + "message": "새로 고침" + }, + "cards": { + "message": "카드" + }, + "identities": { + "message": "신원" + }, + "logins": { + "message": "로그인" + }, + "secureNotes": { + "message": "보안 메모" + }, + "clear": { + "message": "삭제", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "비밀번호가 노출되었는지 확인합니다." + }, + "passwordExposed": { + "message": "이 비밀번호는 데이터 유출에 $VALUE$회 노출되었습니다. 비밀번호를 변경하는 것이 좋습니다.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "이 비밀번호는 데이터 유출 목록에 없습니다. 사용하기에 안전한 비밀번호입니다." + }, + "baseDomain": { + "message": "기본 도메인", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "도메인 이름", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "호스트", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "정확히 일치" + }, + "startsWith": { + "message": "...으로 시작" + }, + "regEx": { + "message": "정규 표현식", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "일치 인식", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "기본 일치 인식", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "표시 / 숨기기" + }, + "toggleCurrentUris": { + "message": "현재 URI 전환", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "현재 URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "조직", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "유형" + }, + "allItems": { + "message": "모든 항목" + }, + "noPasswordsInList": { + "message": "비밀번호가 없습니다." + }, + "remove": { + "message": "제거" + }, + "default": { + "message": "기본값" + }, + "dateUpdated": { + "message": "업데이트됨", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "비밀번호 업데이트됨", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "정말 \"잠그지 않음\" 옵션을 사용하시겠습니까? 잠금 옵션을 \"잠그지 않음\"으로 설정하면 사용자 보관함의 암호화 키를 사용자의 기기에 보관합니다. 이 옵션을 사용하기 전에 사용자의 기기가 잘 보호되어 있는 상태인지 확인하십시오." + }, + "noOrganizationsList": { + "message": "속해 있는 조직이 없습니다. 조직에 속하면 다른 사용자들과 항목을 안전하게 공유할 수 있습니다." + }, + "noCollectionsInList": { + "message": "컬렉션이 없습니다." + }, + "ownership": { + "message": "소유자" + }, + "whoOwnsThisItem": { + "message": "이 항목의 소유자는 누구입니까?" + }, + "strong": { + "message": "강함", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "좋음", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "취약", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "취약한 마스터 비밀번호" + }, + "weakMasterPasswordDesc": { + "message": "선택한 마스터 비밀번호는 취약합니다. Bitwarden 계정을 확실히 보호하려면 강력한 마스터 비밀번호(혹은 패스프레이즈)를 사용해야 합니다. 정말 이 마스터 비밀번호를 사용하시겠습니까?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "PIN 코드를 사용하여 잠금 해제" + }, + "setYourPinCode": { + "message": "Bitwarden 잠금해제에 사용될 PIN 코드를 설정합니다. 이 애플리케이션에서 완전히 로그아웃할 경우 PIN 설정이 초기화됩니다." + }, + "pinRequired": { + "message": "PIN 코드가 필요합니다." + }, + "invalidPin": { + "message": "잘못된 PIN 코드입니다." + }, + "unlockWithBiometrics": { + "message": "생체 인식을 사용하여 잠금 해제" + }, + "awaitDesktop": { + "message": "데스크톱으로부터의 확인을 대기 중" + }, + "awaitDesktopDesc": { + "message": "브라우저 생체 인식을 사용하기 위해서는 Bitwarden 데스크톱 앱에서 생체 인식을 이용하여 승인해주세요." + }, + "lockWithMasterPassOnRestart": { + "message": "브라우저 다시 시작 시 마스터 비밀번호로 잠금" + }, + "selectOneCollection": { + "message": "반드시 하나 이상의 컬렉션을 선택해야 합니다." + }, + "cloneItem": { + "message": "항목 복제" + }, + "clone": { + "message": "복제" + }, + "passwordGeneratorPolicyInEffect": { + "message": "하나 이상의 단체 정책이 생성기 규칙에 영항을 미치고 있습니다." + }, + "vaultTimeoutAction": { + "message": "보관함 시간 제한 초과시 동작" + }, + "lock": { + "message": "잠금", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "휴지통", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "휴지통 검색" + }, + "permanentlyDeleteItem": { + "message": "영구적으로 항목 삭제" + }, + "permanentlyDeleteItemConfirmation": { + "message": "정말로 이 항목을 영구적으로 삭제하시겠습니까?" + }, + "permanentlyDeletedItem": { + "message": "영구적으로 삭제된 항목" + }, + "restoreItem": { + "message": "항목 복원" + }, + "restoreItemConfirmation": { + "message": "정말 이 항목을 복원하시겠습니까?" + }, + "restoredItem": { + "message": "복원된 항목" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "로그아웃하면 보관함에 대한 모든 접근이 제거되며 시간 제한을 초과하면 온라인 인증을 요구합니다. 정말로 이 설정을 사용하시겠습니까?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "시간 제한 초과시 동작 확인" + }, + "autoFillAndSave": { + "message": "자동 완성 및 저장" + }, + "autoFillSuccessAndSavedUri": { + "message": "항목을 자동 완성하고 URI를 저장함" + }, + "autoFillSuccess": { + "message": "항목을 자동 완성함" + }, + "setMasterPassword": { + "message": "마스터 비밀번호 설정" + }, + "masterPasswordPolicyInEffect": { + "message": "하나 이상의 단체 정책이 마스터 비밀번호가 다음 사항을 따르도록 요구합니다:" + }, + "policyInEffectMinComplexity": { + "message": "최소 복잡도 점수 $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "최소 길이 $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "하나 이상의 대문자 포함" + }, + "policyInEffectLowercase": { + "message": "하나 이상의 소문자 포함" + }, + "policyInEffectNumbers": { + "message": "하나 이상의 숫자 포함" + }, + "policyInEffectSpecial": { + "message": "하나 이상의 특수문자 포함 $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "새 마스터 비밀번호가 정책 요구 사항을 따르지 않습니다." + }, + "acceptPolicies": { + "message": "이 박스를 체크하면 다음에 동의하는 것으로 간주됩니다:" + }, + "acceptPoliciesError": { + "message": "서비스 약관 및 개인 정보 보호 정책을 확인하지 않았습니다." + }, + "termsOfService": { + "message": "서비스 약관" + }, + "privacyPolicy": { + "message": "개인 정보 보호 정책" + }, + "hintEqualsPassword": { + "message": "비밀번호 힌트는 비밀번호와 같을 수 없습니다." + }, + "ok": { + "message": "확인" + }, + "desktopSyncVerificationTitle": { + "message": "데스크톱과의 동기화 인증" + }, + "desktopIntegrationVerificationText": { + "message": "데스크톱 앱이 다음 지문 구절을 표시하는지 확인해주세요:" + }, + "desktopIntegrationDisabledTitle": { + "message": "브라우저와 연결이 활성화되지 않았습니다" + }, + "desktopIntegrationDisabledDesc": { + "message": "브라우저와 연결이 Bitwarden 데스크톱 앱에서 활성화되지 않았습니다. 데스크톱 앱의 설정에서 브라우저와 연결을 활성화해주세요." + }, + "startDesktopTitle": { + "message": "Bitwarden 데스크톱 앱을 실행하세요" + }, + "startDesktopDesc": { + "message": "이 기능을 사용하기 위해서는 Bitwarden 데스크톱 앱이 먼저 실행되어 있어야 합니다." + }, + "errorEnableBiometricTitle": { + "message": "생체 인식을 활성화할 수 없음" + }, + "errorEnableBiometricDesc": { + "message": "데스크톱 앱에서 작업이 취소되었습니다" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "데스크톱 앱에서 이 보안 통신 채널을 무효화했습니다. 다시 시도해 주세요." + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "데스크톱과의 통신이 중단됨" + }, + "nativeMessagingWrongUserDesc": { + "message": "데스크톱 앱에 다른 계정으로 로그인된 상태입니다. 두 앱에 같은 계정으로 로그인되어 있는지 확인해주세요." + }, + "nativeMessagingWrongUserTitle": { + "message": "계정이 일치하지 않음" + }, + "biometricsNotEnabledTitle": { + "message": "생체 인식이 활성화되지 않음" + }, + "biometricsNotEnabledDesc": { + "message": "브라우저에서 생체 인식을 사용하기 위해서는 설정에서 데스크톱 생체 인식을 먼저 활성화해야 합니다." + }, + "biometricsNotSupportedTitle": { + "message": "생체 인식이 지원되지 않음" + }, + "biometricsNotSupportedDesc": { + "message": "이 기기에서는 생체 인식이 지원되지 않습니다." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "권한이 부여되지 않음" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bitwarden 데스크톱 앱과 통신할 권한이 부여되지 않은 상태에서는 브라우저 확장 프로그램에서 생체 인식을 사용할 수 없습니다. 다시 시도해 주세요." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "권한 요청 오류" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "사이드바에서는 이 동작을 수행할 수 없습니다. 팝업 혹은 새 창으로 열고 다시 시도해 주세요." + }, + "personalOwnershipSubmitError": { + "message": "엔터프라이즈 정책으로 인해 개인 보관함에 항목을 저장할 수 없습니다. 조직에서 소유권 설정을 변경한 다음, 사용 가능한 컬렉션 중에서 선택해주세요." + }, + "personalOwnershipPolicyInEffect": { + "message": "조직의 정책이 소유권 설정에 영향을 미치고 있습니다." + }, + "excludedDomains": { + "message": "제외된 도메인" + }, + "excludedDomainsDesc": { + "message": "Bitwarden은 이 도메인들에 대해 로그인 정보를 저장할 것인지 묻지 않습니다. 페이지를 새로고침해야 변경된 내용이 적용됩니다." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ 도메인은 유효한 도메인이 아닙니다.", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Send 검색", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Send 추가", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "텍스트" + }, + "sendTypeFile": { + "message": "파일" + }, + "allSends": { + "message": "모든 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "최대 접근 횟수 도달", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "만료됨" + }, + "pendingDeletion": { + "message": "삭제 대기 중" + }, + "passwordProtected": { + "message": "비밀번호로 보호됨" + }, + "copySendLink": { + "message": "Send 링크 복사", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "비밀번호 제거" + }, + "delete": { + "message": "삭제" + }, + "removedPassword": { + "message": "비밀번호 제거함" + }, + "deletedSend": { + "message": "Send 삭제함", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "링크 보내기", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "비활성화됨" + }, + "removePasswordConfirmation": { + "message": "비밀번호를 제거하시겠습니까?" + }, + "deleteSend": { + "message": "Send 삭제", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "정말 이 Send를 삭제하시겠습니까?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send 편집", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "어떤 유형의 Send인가요?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "이 Send의 이름", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "전송하려는 파일" + }, + "deletionDate": { + "message": "삭제 날짜" + }, + "deletionDateDesc": { + "message": "이 Send가 정해진 일시에 영구적으로 삭제됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "만료 날짜" + }, + "expirationDateDesc": { + "message": "설정할 경우, 이 Send에 대한 접근 권한이 정해진 일시에 만료됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1일" + }, + "days": { + "message": "$DAYS$일", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "사용자 지정" + }, + "maximumAccessCount": { + "message": "최대 접근 횟수" + }, + "maximumAccessCountDesc": { + "message": "설정할 경우, 최대 접근 횟수에 도달할 때 이 Send에 접근할 수 없게 됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "이 Send에 접근하기 위해 암호를 입력하도록 선택적으로 요구합니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "이 Send에 대한 비공개 메모", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "이 Send를 비활성화하여 아무도 접근할 수 없게 합니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "저장할 때 이 Send의 링크를 클립보드에 복사합니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "전송하려는 텍스트" + }, + "sendHideText": { + "message": "이 Send의 텍스트를 기본적으로 숨김", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "현재 접근 횟수" + }, + "createSend": { + "message": "새 Send 생성", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "새 비밀번호" + }, + "sendDisabled": { + "message": "Send 비활성화됨", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "엔터프라이즈 정책으로 인해 이미 생성된 Send를 삭제하는 것만 허용됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send 생성함", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send 수정함", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "파일을 선택하려면 이 배너를 클릭하여 확장 프로그램을 사이드바에서 열거나, 불가능한 경우 새 창에서 여세요." + }, + "sendFirefoxFileWarning": { + "message": "Firefox에서 파일을 선택할 경우, 이 배너를 클릭하여 확장 프로그램을 사이드바 혹은 새 창에서 여세요." + }, + "sendSafariFileWarning": { + "message": "Safari에서 파일을 선택할 경우, 이 배너를 클릭하여 확장 프로그램을 새 창에서 여세요." + }, + "sendFileCalloutHeader": { + "message": "시작하기 전에" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "달력을 보고 날짜를 선택하려면", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "여기를 클릭하여", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "확장 프로그램을 새 창에서 여세요.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "제공된 만료 날짜가 유효하지 않습니다." + }, + "deletionDateIsInvalid": { + "message": "제공된 삭제 날짜가 유효하지 않습니다." + }, + "expirationDateAndTimeRequired": { + "message": "만료 날짜와 시간은 반드시 입력해야 합니다." + }, + "deletionDateAndTimeRequired": { + "message": "삭제 날짜와 시간은 반드시 입력해야 합니다." + }, + "dateParsingError": { + "message": "삭제 날짜와 만료 날짜를 저장하는 도중 오류가 발생했습니다." + }, + "hideEmail": { + "message": "받는 사람으로부터 나의 이메일 주소 숨기기" + }, + "sendOptionsPolicyInEffect": { + "message": "하나 이상의 단체 정책이 Send 설정에 영향을 미치고 있습니다." + }, + "passwordPrompt": { + "message": "마스터 비밀번호 재확인" + }, + "passwordConfirmation": { + "message": "마스터 비밀번호 확인" + }, + "passwordConfirmationDesc": { + "message": "이 작업은 보호되어 있습니다. 계속하려면 마스터 비밀번호를 입력하여 신원을 인증하세요." + }, + "emailVerificationRequired": { + "message": "이메일 인증 필요함" + }, + "emailVerificationRequiredDesc": { + "message": "이 기능을 사용하려면 이메일 인증이 필요합니다. 웹 보관함에서 이메일을 인증할 수 있습니다." + }, + "updatedMasterPassword": { + "message": "마스터 비밀번호 변경됨" + }, + "updateMasterPassword": { + "message": "마스터 비밀번호 변경" + }, + "updateMasterPasswordWarning": { + "message": "최근에 조직 관리자가 마스터 비밀번호를 변경했습니다. 보관함에 액세스하려면 지금 업데이트해야 합니다. 계속하면 현재 세션에서 로그아웃되며 다시 로그인해야 합니다. 다른 장치의 활성 세션은 최대 1시간 동안 계속 활성 상태로 유지될 수 있습니다." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "자동 등록" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "이 조직에는 자동으로 비밀번호 재설정에 등록하는 기업 정책이 있습니다. 등록하면 조직 관리자가 마스터 암호를 변경할 수 있습니다." + }, + "selectFolder": { + "message": "폴더 선택..." + }, + "ssoCompleteRegistration": { + "message": "SSO 로그인을 하기 위해서 보관함에 접근하고 보호할 수 있도록 마스터 비밀번호를 설정해주세요." + }, + "hours": { + "message": "시" + }, + "minutes": { + "message": "분" + }, + "vaultTimeoutPolicyInEffect": { + "message": "조직 정책이 보관함 제한 시간에 영향을 미치고 있습니다. 최대 허용 보관함 제한 시간은 $HOURS$시간 $MINUTES$분입니다", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "볼트 제한 시간이 조직에서 설정한 제한을 초과합니다." + }, + "vaultExportDisabled": { + "message": "보관함 내보내기 비활성화됨" + }, + "personalVaultExportPolicyInEffect": { + "message": "하나 이상의 조직 정책이 개인 보관함을 내보내는 것을 제한하고 있습니다." + }, + "copyCustomFieldNameInvalidElement": { + "message": "유효한 양식 요소를 식별하지 못했습니다. 대신 HTML을 검사해 보세요." + }, + "copyCustomFieldNameNotUnique": { + "message": "고유 식별자를 찾을 수 없습니다." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ 조직은 자체 호스팅 키 서버로 SSO를 사용하고 있습니다 이 조직의 멤버들은 로그인할 때에 마스터 비밀번호를 필요로 하지 않습니다.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "조직 나가기" + }, + "removeMasterPassword": { + "message": "마스터 비밀번호 제거" + }, + "removedMasterPassword": { + "message": "마스터 비밀번호가 제거되었습니다." + }, + "leaveOrganizationConfirmation": { + "message": "정말 이 조직을 떠나시겠어요?" + }, + "leftOrganization": { + "message": "조직을 떠났습니다." + }, + "toggleCharacterCount": { + "message": "글자 수 표시하기" + }, + "sessionTimeout": { + "message": "세션 시간이 초과되었습니다. 다시 로그인해주세요." + }, + "exportingPersonalVaultTitle": { + "message": "개인 보관함을 내보내는 중" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "오류" + }, + "regenerateUsername": { + "message": "아이디 재생성" + }, + "generateUsername": { + "message": "아이디 생성" + }, + "usernameType": { + "message": "아이디 유형" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "무작위" + }, + "randomWord": { + "message": "무작위 단어" + }, + "websiteName": { + "message": "웹사이트 이름" + }, + "whatWouldYouLikeToGenerate": { + "message": "무엇을 생성하실건가요?" + }, + "passwordType": { + "message": "비밀번호 유형" + }, + "service": { + "message": "서비스" + } +} diff --git a/apps/browser/src/_locales/lt/messages.json b/apps/browser/src/_locales/lt/messages.json new file mode 100644 index 0000000000..3a2dff4064 --- /dev/null +++ b/apps/browser/src/_locales/lt/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Saugi ir nemokama slaptažodžių tvarkyklė visiems įrenginiams.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Prisijunkite arba sukurkite naują paskyrą, kad galėtumėte pasiekti saugyklą." + }, + "createAccount": { + "message": "Sukurti paskyrą" + }, + "login": { + "message": "Prisijungti" + }, + "enterpriseSingleSignOn": { + "message": "Vienkartinis įmonės prisijungimas" + }, + "cancel": { + "message": "Atšaukti" + }, + "close": { + "message": "Uždaryti" + }, + "submit": { + "message": "Išsaugoti" + }, + "emailAddress": { + "message": "El. paštas" + }, + "masterPass": { + "message": "Pagrindinis slaptažodis" + }, + "masterPassDesc": { + "message": "Pagrindinis slaptažodis yra slaptažodis, kurį naudojate norėdami pasiekti savo saugyklą. Labai svarbu nepamiršti pagrindinio slaptažodžio. Negalėsite atkurti slaptažodį, jei jį pamiršote." + }, + "masterPassHintDesc": { + "message": "Pagrindinio slaptažodžio užuomina gali padėti prisiminti slaptažodį, jei jį pamiršite." + }, + "reTypeMasterPass": { + "message": "Pakartokite pagrindinį slaptažodį" + }, + "masterPassHint": { + "message": " Pagrindinio slaptažodžio užuomina (neprivaloma)" + }, + "tab": { + "message": "Skirtukas" + }, + "myVault": { + "message": "Saugykla" + }, + "tools": { + "message": "Įrankiai" + }, + "settings": { + "message": "Nustatymai" + }, + "currentTab": { + "message": "Dabartinis skirtukas" + }, + "copyPassword": { + "message": "Kopijuoti slaptažodį" + }, + "copyNote": { + "message": "Kopijuoti pastabas" + }, + "copyUri": { + "message": "Kopijuoti nuorodą" + }, + "copyUsername": { + "message": "Kopijuoti vartotojo vardą" + }, + "copyNumber": { + "message": "Kopijuoti numerį" + }, + "copySecurityCode": { + "message": "Kopijuoti saugos kodą" + }, + "autoFill": { + "message": "Automatinis užpildymas" + }, + "generatePasswordCopied": { + "message": "Kurti slaptažodį (paruoštas įterpti)" + }, + "copyElementIdentifier": { + "message": "Kopijuoti pritaikyto laukelio pavadinimą" + }, + "noMatchingLogins": { + "message": "Nėra atitinkančių prisijungimų." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "Nėra galimų prisijungimų prie dabartinio naršyklės skirtuko." + }, + "addLogin": { + "message": "Pridėti prisijungimą" + }, + "addItem": { + "message": "Pridėti elementą" + }, + "passwordHint": { + "message": "Slaptažodžio užuomina" + }, + "enterEmailToGetHint": { + "message": "Įveskite savo paskyros el. pašto adresą, kad gautumėte pagrindinio slaptažodžio užuominą." + }, + "getMasterPasswordHint": { + "message": "Gauti pagrindinio slaptažodžio užuominą" + }, + "continue": { + "message": "Tęsti" + }, + "sendVerificationCode": { + "message": "Siųsti patvirtinimo kodą į el. paštą" + }, + "sendCode": { + "message": "Siųsti kodą" + }, + "codeSent": { + "message": "Kodas išsiųstas" + }, + "verificationCode": { + "message": "Patvirtinimo kodas" + }, + "confirmIdentity": { + "message": "Norint tęsti, patvirtinkite tapatybę." + }, + "account": { + "message": "Paskyra" + }, + "changeMasterPassword": { + "message": "Keisti pagrindinį slaptažodį" + }, + "fingerprintPhrase": { + "message": "Dalijimosi slaptažodis", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Jūsų paskiros dalijimosi slaptažodis", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Dviejų žingsnių prisijungimas" + }, + "logOut": { + "message": "Atsijungti" + }, + "about": { + "message": "Apie" + }, + "version": { + "message": "Versija" + }, + "save": { + "message": "Išsaugoti" + }, + "move": { + "message": "Perkelti" + }, + "addFolder": { + "message": "Pridėti katalogą" + }, + "name": { + "message": "Pavadinimas" + }, + "editFolder": { + "message": "Redaguoti aplanką" + }, + "deleteFolder": { + "message": "Šalinti katalogą" + }, + "folders": { + "message": "Aplankai" + }, + "noFolders": { + "message": "Aplankų nėra" + }, + "helpFeedback": { + "message": "Pagalba ir atsiliepimai" + }, + "sync": { + "message": "Sinchronizuoti" + }, + "syncVaultNow": { + "message": "Sinchronizuoti saugyklą dabar" + }, + "lastSync": { + "message": "Sinchronizuota:" + }, + "passGen": { + "message": "Slaptažodžių generatorius" + }, + "generator": { + "message": "Generatorius", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatiškai sukurkite patikimus, unikalius slaptažodžius." + }, + "bitWebVault": { + "message": "„Bitwarden“ žiniatinklio saugykla" + }, + "importItems": { + "message": "Importuoti duomenis" + }, + "select": { + "message": "Pasirinkti" + }, + "generatePassword": { + "message": "Kurti slaptažodį" + }, + "regeneratePassword": { + "message": "Perkurti slaptažodį" + }, + "options": { + "message": "Pasirinkimai" + }, + "length": { + "message": "Ilgis" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Žodžių skaičius" + }, + "wordSeparator": { + "message": "Žodžių skirtukas" + }, + "capitalize": { + "message": "Pradėti didžiosiomis", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Įtraukti skaičius" + }, + "minNumbers": { + "message": "Mažiausiai skaičių" + }, + "minSpecial": { + "message": "Mažiausiai simbolių" + }, + "avoidAmbChar": { + "message": "Vengti dviprasmiškų simbolių" + }, + "searchVault": { + "message": "Ieškoti saugykloje" + }, + "edit": { + "message": "Keisti" + }, + "view": { + "message": "Peržiūrėti" + }, + "noItemsInList": { + "message": "Nėra rodytinų elementų." + }, + "itemInformation": { + "message": "Informacija" + }, + "username": { + "message": "Vartotojo vardas" + }, + "password": { + "message": "Slaptažodis" + }, + "passphrase": { + "message": "Slaptafrazė" + }, + "favorite": { + "message": "Mėgstamas" + }, + "notes": { + "message": "Pastabos" + }, + "note": { + "message": "Pastaba" + }, + "editItem": { + "message": "Redaguoti elementą" + }, + "folder": { + "message": "Aplankas" + }, + "deleteItem": { + "message": "Trinti elementą" + }, + "viewItem": { + "message": "Peržiūrėti elementą" + }, + "launch": { + "message": "Paleisti" + }, + "website": { + "message": "Tinklapis" + }, + "toggleVisibility": { + "message": "Perjungti matomumą" + }, + "manage": { + "message": "Tvarkyti" + }, + "other": { + "message": "Kita" + }, + "rateExtension": { + "message": "Įvertinkite šį plėtinį" + }, + "rateExtensionDesc": { + "message": "Apsvarstykite galimybę mums padėti palikdami gerą atsiliepimą!" + }, + "browserNotSupportClipboard": { + "message": "Jūsų žiniatinklio naršyklė nepalaiko automatinio kopijavimo. Vietoj to nukopijuokite rankiniu būdu." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Jūsų saugykla užrakinta. Norėdami tęsti, patikrinkite pagrindinį slaptažodį." + }, + "unlock": { + "message": "Atrakinti" + }, + "loggedInAsOn": { + "message": "Prisijungta prie $HOSTNAME$ kaip $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Neteisingas pagrindinis slaptažodis" + }, + "vaultTimeout": { + "message": "Atsijungta nuo saugyklos" + }, + "lockNow": { + "message": "Užrakinti dabar" + }, + "immediately": { + "message": "Nedelsiant" + }, + "tenSeconds": { + "message": "10 sekundžių" + }, + "twentySeconds": { + "message": "20 sekundžių" + }, + "thirtySeconds": { + "message": "30 sekundžių" + }, + "oneMinute": { + "message": "1 minutę" + }, + "twoMinutes": { + "message": "2 minučių" + }, + "fiveMinutes": { + "message": "5 minučių" + }, + "fifteenMinutes": { + "message": "15 minučių" + }, + "thirtyMinutes": { + "message": "30 minučių" + }, + "oneHour": { + "message": "1 valandos" + }, + "fourHours": { + "message": "4 valandų" + }, + "onLocked": { + "message": "Užrakinant sistemą" + }, + "onRestart": { + "message": "Paleidus iš naujo naršyklę" + }, + "never": { + "message": "Niekada" + }, + "security": { + "message": "Apsauga" + }, + "errorOccurred": { + "message": "Įvyko klaida" + }, + "emailRequired": { + "message": "Reikalingas el. pašto adresas." + }, + "invalidEmail": { + "message": "Klaidingas el. pašto adresas." + }, + "masterPassRequired": { + "message": "Būtinas pagrindinis slaptažodis." + }, + "masterPassLength": { + "message": "Pagrindinis slaptažodis turi būti bent 8 simbolių ilgio." + }, + "masterPassDoesntMatch": { + "message": "Pagrindinio slaptažodžio patvirtinimas nesutampa." + }, + "newAccountCreated": { + "message": "Jūsų paskyra sukurta! Galite prisijungti." + }, + "masterPassSent": { + "message": "Išsiuntėme jums el. laišką su pagrindinio slaptažodžio užuomina." + }, + "verificationCodeRequired": { + "message": "Būtinas patvirtinimo kodas." + }, + "invalidVerificationCode": { + "message": "Neteisingas patvirtinimo kodas" + }, + "valueCopied": { + "message": "Nukopijuota $VALUE$", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Nepavyko automatiškai užpildyti pasirinkto elemento šiame puslapyje. Nukopijuokite ir įklijuokite informaciją." + }, + "loggedOut": { + "message": "Atsijungta" + }, + "loginExpired": { + "message": "Sesijos laikas baigėsi." + }, + "logOutConfirmation": { + "message": "Ar tikrai norite atsijungti?" + }, + "yes": { + "message": "Taip" + }, + "no": { + "message": "Ne" + }, + "unexpectedError": { + "message": "Įvyko netikėta klaida." + }, + "nameRequired": { + "message": "Pavadinimas yra būtinas." + }, + "addedFolder": { + "message": "Katalogas pridėtas" + }, + "changeMasterPass": { + "message": "Keisti pagrindinį slaptažodį" + }, + "changeMasterPasswordConfirmation": { + "message": "Pagrindinį slaptažodį galite pakeisti bitwarden.com žiniatinklio saugykloje. Ar norite dabar apsilankyti svetainėje?" + }, + "twoStepLoginConfirmation": { + "message": "Prisijungus dviem veiksmais, jūsų paskyra tampa saugesnė, reikalaujant patvirtinti prisijungimą naudojant kitą įrenginį, pvz., Saugos raktą, autentifikavimo programą, SMS, telefono skambutį ar el. Paštą. Dviejų žingsnių prisijungimą galima įjungti „bitwarden.com“ interneto saugykloje. Ar norite dabar apsilankyti svetainėje?" + }, + "editedFolder": { + "message": "Katalogas atnaujintas" + }, + "deleteFolderConfirmation": { + "message": "Ar tikrai norite ištrinti šį aplanką?" + }, + "deletedFolder": { + "message": "Katalogas ištrintas" + }, + "gettingStartedTutorial": { + "message": "Apmokymai" + }, + "gettingStartedTutorialVideo": { + "message": "Peržiūrėkite aomokymus, kad sužinotumėte, kaip išnaudoti visas naršyklės plėtinio galimybes." + }, + "syncingComplete": { + "message": "Sinchronizacija baigta" + }, + "syncingFailed": { + "message": "Sinchronizuoti nepavyko" + }, + "passwordCopied": { + "message": "Slaptažodis nukopijuotas" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI adresas $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Naujas URI" + }, + "addedItem": { + "message": "Pridėtas elementas" + }, + "editedItem": { + "message": "Redaguotas elementas" + }, + "deleteItemConfirmation": { + "message": "Ar tikrai norite perkelti į šiukšlinę?" + }, + "deletedItem": { + "message": "Elementas perkeltas į šiukšlinę" + }, + "overwritePassword": { + "message": "Perrašyti slaptažodį" + }, + "overwritePasswordConfirmation": { + "message": "Ar tikrai norite perrašyti dabartinį slaptažodį?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Ieškoti aplanke" + }, + "searchCollection": { + "message": "Ieškoti rinkinio" + }, + "searchType": { + "message": "Ieškoti tipo" + }, + "noneFolder": { + "message": "Be aplanko", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Išjungti Pridėti prisijungimą pranešimą" + }, + "addLoginNotificationDesc": { + "message": "Prisijungimo pridėjimo pranešimas automatiškai Jūs paragina išsaugoti naujus prisijungimus Jūsų saugykloje, kuomet prisijungiate pirmą kartą." + }, + "dontShowCardsCurrentTab": { + "message": "Nerodyti kortelių skirtuko puslapyje" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Kortelių įrašai yra nurodyti „Dabartinis skirtukas“ puslapyje lengvai laukelių užpildymo prieigai." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Nerodyti tapatybių skirtuko puslapyje" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Saugyklos tapatybių įrašai yra nurodyti „Dabartinis skirtukas“ puslapyje lengvai laukelių užpildymo prieigai." + }, + "clearClipboard": { + "message": "Išvalyti iškarpinę", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatiškai išvalyti nukopijuotas reikšmes iškarpinėje.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Ar „Bitwarden“ turėtų prisiminti šį slaptažodį?" + }, + "notificationAddSave": { + "message": "Taip, išsaugoti dabar" + }, + "disableChangedPasswordNotification": { + "message": "Išjungti pakeisto slaptažodžio pranešimą" + }, + "disableChangedPasswordNotificationDesc": { + "message": "„Pakeisto slaptažodžio pranešimas“ automatiškai ragina atnaujinti slaptažodį saugykloje, kai aptinkamas pakeitimas svetainėje." + }, + "notificationChangeDesc": { + "message": "Ar norite atnaujinti šį slaptažodį „Bitwarden“?" + }, + "notificationChangeSave": { + "message": "Taip, atnaujinti dabar" + }, + "disableContextMenuItem": { + "message": "Išjungti kontekstinio meniu nustatymus" + }, + "disableContextMenuItemDesc": { + "message": "Kontekstinio meniu nustatymai suteikia greitą prieigą prie slaptažodžių generavimo ir svetainės prisijungimų dabartiniame skirtuke." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Pakeisti programos spalvos temą" + }, + "dark": { + "message": "Tamsi", + "description": "Dark color" + }, + "light": { + "message": "Šviesi", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Eksportuoti saugyklą" + }, + "fileFormat": { + "message": "Failo formatas" + }, + "warning": { + "message": "ĮSPĖJIMAS", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Patvirtinti saugyklos eksportą" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Pasidalinti" + }, + "learnOrg": { + "message": "Sužinoti apie organizacijas" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Atnaujinimas įvykdytas" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Prisiminti mane" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Atidaryti naują skirtuką" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "El. paštas" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Serverio URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/lv/messages.json b/apps/browser/src/_locales/lv/messages.json new file mode 100644 index 0000000000..0f71446845 --- /dev/null +++ b/apps/browser/src/_locales/lv/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Drošs bezmaksas paroļu pārvaldnieks visām Tavām ierīcēm.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Pieraksties vai izveido jaunu kontu, lai piekļūtu drošajai glabātavai!" + }, + "createAccount": { + "message": "Izveidot kontu" + }, + "login": { + "message": "Pierakstīties" + }, + "enterpriseSingleSignOn": { + "message": "Uzņēmuma vienotā pierakstīšanās" + }, + "cancel": { + "message": "Atcelt" + }, + "close": { + "message": "Aizvērt" + }, + "submit": { + "message": "Iesniegt" + }, + "emailAddress": { + "message": "E-pasta adrese" + }, + "masterPass": { + "message": "Galvenā parole" + }, + "masterPassDesc": { + "message": "Galvenā parole ir parole, kas tiek izmantota, lai piekļūtu glabātavai. Ir ļoti svarīgi, ka tā netiek aizmirsta, jo tādā gadījumā to nav iespējams atgūt." + }, + "masterPassHintDesc": { + "message": "Galvenās paroles norāde var palīdzēt atcerēties paroli, ja tā ir aizmirsta." + }, + "reTypeMasterPass": { + "message": "Atkārtoti ievadīt galveno paroli " + }, + "masterPassHint": { + "message": "Galvenās paroles norāde (nav nepieciešama)" + }, + "tab": { + "message": "Cilne" + }, + "myVault": { + "message": "Mana glabātava" + }, + "tools": { + "message": "Rīki" + }, + "settings": { + "message": "Iestatījumi" + }, + "currentTab": { + "message": "Pašreizējā cilne" + }, + "copyPassword": { + "message": "Ievietot paroli starpliktuvē" + }, + "copyNote": { + "message": "Ievietot piezīmi starpliktuvē" + }, + "copyUri": { + "message": "Ievietot URI starpliktuvē" + }, + "copyUsername": { + "message": "Ievietot lietotājvārdu starpliktuvē" + }, + "copyNumber": { + "message": "Ievietot numuru starpliktuvē" + }, + "copySecurityCode": { + "message": "Ievietot drošības kodu starpliktuvē" + }, + "autoFill": { + "message": "Automātiskā aizpilde" + }, + "generatePasswordCopied": { + "message": "Veidot paroli (ievietota starpliktuvē)" + }, + "copyElementIdentifier": { + "message": "Pavairot pielāgotā lauka nosaukumu" + }, + "noMatchingLogins": { + "message": "Nav atbilstošu pierakstīšanās vienumu." + }, + "unlockVaultMenu": { + "message": "Atslēgt glabātavu" + }, + "loginToVaultMenu": { + "message": "Pierakstīties glabātavā" + }, + "autoFillInfo": { + "message": "Nav pierakstīšanās vienumu, kurus automātiski ievadīt pašreizējā pārlūka cilnē." + }, + "addLogin": { + "message": "Pievienot pierakstīšanās vienumu" + }, + "addItem": { + "message": "Pievienot vienumu" + }, + "passwordHint": { + "message": "Paroles norāde" + }, + "enterEmailToGetHint": { + "message": "Norādīt konta e-pasta adresi, lai saņemtu galvenās paroles norādi." + }, + "getMasterPasswordHint": { + "message": "Saņemt galvenās paroles norādi" + }, + "continue": { + "message": "Turpināt" + }, + "sendVerificationCode": { + "message": "Sūtīt apstiprinājuma kodu uz e-pastu" + }, + "sendCode": { + "message": "Nosūtīt kodu" + }, + "codeSent": { + "message": "Kods nosūtīts" + }, + "verificationCode": { + "message": "Apstiprināšanas kods" + }, + "confirmIdentity": { + "message": "Apstiprināt identitāti, lai turpinātu." + }, + "account": { + "message": "Konts" + }, + "changeMasterPassword": { + "message": "Mainīt galveno paroli" + }, + "fingerprintPhrase": { + "message": "Atpazīšanas vārdkopa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Konta atpazīšanas vārdkopa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Divpakāpju pierakstīšanās" + }, + "logOut": { + "message": "Izrakstīties" + }, + "about": { + "message": "Par" + }, + "version": { + "message": "Laidiens" + }, + "save": { + "message": "Saglabāt" + }, + "move": { + "message": "Pārvietot" + }, + "addFolder": { + "message": "Pievienot mapi" + }, + "name": { + "message": "Nosaukums" + }, + "editFolder": { + "message": "Labot mapi" + }, + "deleteFolder": { + "message": "Dzēst mapi" + }, + "folders": { + "message": "Mapes" + }, + "noFolders": { + "message": "Nav parādāmu mapju." + }, + "helpFeedback": { + "message": "Palīdzība un atsauksmes" + }, + "sync": { + "message": "Sinhronizēt" + }, + "syncVaultNow": { + "message": "Sinhronizēt glabātavu" + }, + "lastSync": { + "message": "Pēdējā sinhronizācija:" + }, + "passGen": { + "message": "Paroļu veidotājs" + }, + "generator": { + "message": "Veidotājs", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automātiski veido spēcīgas, neatkārtojamas paroles visiem pierakstīšanās vienumiem. " + }, + "bitWebVault": { + "message": "Bitwarden tīmekļa glabātava" + }, + "importItems": { + "message": "Ievietot vienumus" + }, + "select": { + "message": "Atlasīt" + }, + "generatePassword": { + "message": "Veidot paroli" + }, + "regeneratePassword": { + "message": "Pārizveidot paroli" + }, + "options": { + "message": "Iespējas" + }, + "length": { + "message": "Garums" + }, + "uppercase": { + "message": "Lielie burti (A-Z)" + }, + "lowercase": { + "message": "Mazie burti (a-z)" + }, + "numbers": { + "message": "Cipari (0-9)" + }, + "specialCharacters": { + "message": "Īpašās rakstzīmes (!@#$%^&*)" + }, + "numWords": { + "message": "Vārdu skaits" + }, + "wordSeparator": { + "message": "Vārdu atdalītājs" + }, + "capitalize": { + "message": "Izmantot lielos sākumburtus", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Iekļaut ciparu" + }, + "minNumbers": { + "message": "Mazākais pieļaujamais ciparu skaits" + }, + "minSpecial": { + "message": "Mazākais pieļaujamais īpašo rakstzīmju skaits" + }, + "avoidAmbChar": { + "message": "Izvairīties no viegli sajaucamām rakstzīmēm" + }, + "searchVault": { + "message": "Meklēt glabātavā" + }, + "edit": { + "message": "Labot" + }, + "view": { + "message": "Skatīt" + }, + "noItemsInList": { + "message": "Nav vienumu, ko parādīt." + }, + "itemInformation": { + "message": "Vienuma informācija" + }, + "username": { + "message": "Lietotājvārds" + }, + "password": { + "message": "Parole" + }, + "passphrase": { + "message": "Paroles vārdkopa" + }, + "favorite": { + "message": "Izlasē" + }, + "notes": { + "message": "Piezīmes" + }, + "note": { + "message": "Piezīme" + }, + "editItem": { + "message": "Labot vienumu" + }, + "folder": { + "message": "Mape" + }, + "deleteItem": { + "message": "Izdzēst vienumu" + }, + "viewItem": { + "message": "Skatīt vienumu" + }, + "launch": { + "message": "Palaist" + }, + "website": { + "message": "Tīmekļa vietne" + }, + "toggleVisibility": { + "message": "Pārslēgt redzamību" + }, + "manage": { + "message": "Pārvaldīt" + }, + "other": { + "message": "Cits" + }, + "rateExtension": { + "message": "Novērtēt paplašinājumu" + }, + "rateExtensionDesc": { + "message": "Lūdzu, apsver palīdzēt mums ar labu atsauksmi!" + }, + "browserNotSupportClipboard": { + "message": "Tavs tīmekļa pārlūks neatbalsta vienkāršu starpliktuves kopēšanu. Nokopē to pašrocīgi!" + }, + "verifyIdentity": { + "message": "Apstiprināt identitāti" + }, + "yourVaultIsLocked": { + "message": "Glabātava ir slēgta. Nepieciešams norādīt galveno paroli, lai turpinātu." + }, + "unlock": { + "message": "Atslēgt" + }, + "loggedInAsOn": { + "message": "Pierakstījies $HOSTNAME$ kā $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Nederīga galvenā parole" + }, + "vaultTimeout": { + "message": "Glabātavas noildze" + }, + "lockNow": { + "message": "Aizslēgt" + }, + "immediately": { + "message": "Nekavējoties" + }, + "tenSeconds": { + "message": "10 sekundes" + }, + "twentySeconds": { + "message": "20 sekundes" + }, + "thirtySeconds": { + "message": "30 sekundes" + }, + "oneMinute": { + "message": "1 minūte" + }, + "twoMinutes": { + "message": "2 minūtes" + }, + "fiveMinutes": { + "message": "5 minūtes" + }, + "fifteenMinutes": { + "message": "15 minūtes" + }, + "thirtyMinutes": { + "message": "30 minūtes" + }, + "oneHour": { + "message": "1 stunda" + }, + "fourHours": { + "message": "4 stundas" + }, + "onLocked": { + "message": "Pēc sistēmas aizslēgšanas" + }, + "onRestart": { + "message": "Pēc pārlūka pārsāknēšanas" + }, + "never": { + "message": "Nekad" + }, + "security": { + "message": "Drošība" + }, + "errorOccurred": { + "message": "Radusies kļūda" + }, + "emailRequired": { + "message": "E-pasta adrese ir nepieciešama." + }, + "invalidEmail": { + "message": "Nederīga e-pasta adrese." + }, + "masterPassRequired": { + "message": "Galvenā parole ir nepieciešama." + }, + "masterPassLength": { + "message": "Galvenajai parolei ir jābūt vismaz 8 rakstzīmes garai." + }, + "masterPassDoesntMatch": { + "message": "Galvenās paroles apstiprinājums nesakrīt." + }, + "newAccountCreated": { + "message": "Tavs jaunais konts ir izveidots. Tagad Tu vari pierakstīties." + }, + "masterPassSent": { + "message": "Mēs nosūtījām galvenās paroles norādi e-pastā." + }, + "verificationCodeRequired": { + "message": "Apstiprinājuma kods ir nepieciešams." + }, + "invalidVerificationCode": { + "message": "Nederīgs apstiprinājuma kods" + }, + "valueCopied": { + "message": "$VALUE$ ievietota starpliktuvē", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Neizdevās automātiski aizpildīt izvēlēto vienumu šajā lapā. Tā vietā kopē un ielīmē to! " + }, + "loggedOut": { + "message": "Izrakstījies" + }, + "loginExpired": { + "message": "Pierakstīšanās sesija ir beigusies." + }, + "logOutConfirmation": { + "message": "Vai tiešām izrakstīties?" + }, + "yes": { + "message": "Jā" + }, + "no": { + "message": "Nē" + }, + "unexpectedError": { + "message": "Ir radusies neparedzēta kļūda." + }, + "nameRequired": { + "message": "Nosaukums ir nepieciešams." + }, + "addedFolder": { + "message": "Pievienoja mapi" + }, + "changeMasterPass": { + "message": "Mainīt galveno paroli" + }, + "changeMasterPasswordConfirmation": { + "message": "Galveno paroli ir iespējams mainīt bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "twoStepLoginConfirmation": { + "message": "Divpakāpju pieslēgšanās padara kontu krietni drošāku, pieprasot apstiprināt pierakstīšanos ar tādu citu ierīču vai pakalpojumu starpniecību kā drošības atslēga, autentificētāja lietotne, īsziņa, tālruņa zvans vai e-pasts. Divpakāpju pierakstīšanos var iespējot bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "editedFolder": { + "message": "Mape labota" + }, + "deleteFolderConfirmation": { + "message": "Vai tiešām izdzēst šo mapi?" + }, + "deletedFolder": { + "message": "Mape izdzēsta" + }, + "gettingStartedTutorial": { + "message": "Uzsākšanas pamācība" + }, + "gettingStartedTutorialVideo": { + "message": "Noskaties mūsu uzsākšanas pamācību, lai uzzinātu, kā iegūt vislielāko labumu no pārlūka paplašinājuma." + }, + "syncingComplete": { + "message": "Sinhronizācija pabeigta" + }, + "syncingFailed": { + "message": "Sinhronizācija neizdevās" + }, + "passwordCopied": { + "message": "Parole ievietota starpliktuvē" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Jauns URI" + }, + "addedItem": { + "message": "Vienums pievienots" + }, + "editedItem": { + "message": "Vienums labots" + }, + "deleteItemConfirmation": { + "message": "Vai tiešām pārvietot vienumu uz atkritni?" + }, + "deletedItem": { + "message": "Vienums pārvietots uz atkritni" + }, + "overwritePassword": { + "message": "Pārrakstīt paroli" + }, + "overwritePasswordConfirmation": { + "message": "Vai tiešām pārrakstīt esošo paroli?" + }, + "overwriteUsername": { + "message": "Pārrakstīt lietotājvārdu" + }, + "overwriteUsernameConfirmation": { + "message": "Vai tiešām pārrakstīt pašreizējo lietotājvārdu?" + }, + "searchFolder": { + "message": "Meklēt mapē" + }, + "searchCollection": { + "message": "Meklēt krājumā" + }, + "searchType": { + "message": "Meklēšanas veids" + }, + "noneFolder": { + "message": "Nav mapes", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Atspējot piekļuves vienumu pievienošanas paziņojumu" + }, + "addLoginNotificationDesc": { + "message": "Iestatījums \"Piekļuves vienumu pievienošanas paziņojumi\" piedāvā saglabāt jaunus pieslēgšanās ierakstus, kad vien tie tiek izmantoti pirmo reizi ierakstoties." + }, + "dontShowCardsCurrentTab": { + "message": "Nerādīt kartes cilnes lapā" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Glabātavas karšu vienumi tiek attēloti 'Pašreizējā cilne' lapā vieglai piekļūšanai automātiskajai aizpildīšanai." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Nerādīt identitātes cilnes pārskatā" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Glabātavas identitātes vienumi tiek attēloti 'Pašreizējā cilne' lapā vieglai piekļūšanai automātiskajai aizpildīšanai." + }, + "clearClipboard": { + "message": "Notīrīt starpliktuvi", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automātiski noņemt kopētās vērtības no starpliktuves.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Vai Bitwarden atcerēties šo paroli?" + }, + "notificationAddSave": { + "message": "Jā, saglabāt" + }, + "disableChangedPasswordNotification": { + "message": "Atspējot mainītas paroles paziņojumu" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Mainītas paroles paziņojums\" vaicā atjaunināt pieteikšanās vienuma paroli glabātavā, kad vien tiek noteikts, ka tā ir mainīta tīmekļa vietnē." + }, + "notificationChangeDesc": { + "message": "Vai atjaunināt šo paroli Bitwarden?" + }, + "notificationChangeSave": { + "message": "Jā, atjaunināt" + }, + "disableContextMenuItem": { + "message": "Atspējot konteksta izvēlnes iespējas" + }, + "disableContextMenuItemDesc": { + "message": "Konteksta izvēlnes iespējas piedāvā ātru piekļūšanu paroļu veidošanai un tīmekļa vietnes pieteikšanās vienumiem pašreizējā cilnē." + }, + "defaultUriMatchDetection": { + "message": "Noklusējuma URI atbilstības noteikšana", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Izvēlēties noklusējuma veidu, kādā URI atbilstības noteikšana tiek apstrādāta, kad tiek veiktas tādas darbības kā automātiska aizpildīšana." + }, + "theme": { + "message": "Izskats" + }, + "themeDesc": { + "message": "Mainīt lietotnes izskata krāsas." + }, + "dark": { + "message": "Tumšs", + "description": "Dark color" + }, + "light": { + "message": "Gaišs", + "description": "Light color" + }, + "solarizedDark": { + "message": "Tumšs Solarized", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Izgūt glabātavas saturu" + }, + "fileFormat": { + "message": "Datnes veids" + }, + "warning": { + "message": "UZMANĪBU", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Apstiprināt glabātavas satura izgūšanu" + }, + "exportWarningDesc": { + "message": "Šī izguve satur glabātavas datus nešifrētā veidā. Izdoto datni nevajadzētu glabāt vai sūtīt nedrošos veidos (piemēram, e-pastā). Izdzēst to uzreiz pēc izmantošanas." + }, + "encExportKeyWarningDesc": { + "message": "Šī izguve šifrē datus ar konta šifrēšanas atslēgu. Ja tā jebkad tiks mainīta, izvadi vajadzētu veikt vēlreiz, jo vairs nebūs iespējams atšifrēt šo datni." + }, + "encExportAccountWarningDesc": { + "message": "Katram Bitwarden kontam ir neatkārtojamas šifrēšanas atslēgas, tādēļ nav iespējams ievietot šifrētu izguvi citā kontā." + }, + "exportMasterPassword": { + "message": "Ievadīt galveno paroli, lai izgūtu glabātavas saturu." + }, + "shared": { + "message": "Kopīgots" + }, + "learnOrg": { + "message": "Uzzināt par apvienībām" + }, + "learnOrgConfirmation": { + "message": "Bitwarden nodrošina iespēju kopīgot glabātavas vienumus ar citiem, kad tiek izmantota apvienība. Vai apmeklēt bitwarden.com tīmekļa vietni, lai uzzinātu vairāk?" + }, + "moveToOrganization": { + "message": "Pārvietot uz apvienību" + }, + "share": { + "message": "Kopīgot" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ pārvietots uz $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Izvēlies apvienību, uz kuru pārvietot šo vienumu. Pārvietošana nodod šī vienuma piederību apvienībai. Tu vairs nebūsi šī vienuma tiešais īpašnieks pēc tā pārvietošanas." + }, + "learnMore": { + "message": "Uzzināt vairāk" + }, + "authenticatorKeyTotp": { + "message": "Autentificētāja atslēga (TOTP)" + }, + "verificationCodeTotp": { + "message": "Apstiprinājuma kods (TOTP)" + }, + "copyVerificationCode": { + "message": "Ievietot apstiprinājuma kodu starpliktuvē" + }, + "attachments": { + "message": "Pielikumi" + }, + "deleteAttachment": { + "message": "Izdzēst pielikumu" + }, + "deleteAttachmentConfirmation": { + "message": "Vai tiešām izdzēst šo pielikumu?" + }, + "deletedAttachment": { + "message": "Pielikums izdzēsts" + }, + "newAttachment": { + "message": "Pievienot Jaunu Pielikumu" + }, + "noAttachments": { + "message": "Nav pielikumu." + }, + "attachmentSaved": { + "message": "Pielikums tika saglabāts." + }, + "file": { + "message": "Datne" + }, + "selectFile": { + "message": "Atlasīt datni." + }, + "maxFileSize": { + "message": "Lielākais pieļaujamais datnes izmērs ir 500 MB." + }, + "featureUnavailable": { + "message": "Iespēja nav pieejama" + }, + "updateKey": { + "message": "Jūs nevarat izmantot šo funkciju līdz jūs atjaunojat savu šifrēšanas atslēgu." + }, + "premiumMembership": { + "message": "Premium dalība" + }, + "premiumManage": { + "message": "Pārvaldīt dalību" + }, + "premiumManageAlert": { + "message": "Dalību ir iespējams pārvaldīt bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "premiumRefresh": { + "message": "Atjaunot dalību" + }, + "premiumNotCurrentMember": { + "message": "Tu pašlaik neesi Premium dalībnieks." + }, + "premiumSignUpAndGet": { + "message": "Piesakies Premium dalībai un saņem:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB šifrētas krātuves datņu pielikumiem." + }, + "ppremiumSignUpTwoStep": { + "message": "Tādas papildus divpakāpju pierakstīšanās iespējas kā YubiKey, FIDO U2F un Duo." + }, + "ppremiumSignUpReports": { + "message": "Paroļu higiēnas, kontu veselības un datu pārkāpumu pārskati, lai uzturētu glabātavu drošu." + }, + "ppremiumSignUpTotp": { + "message": "TOTP apstiprinājuma kodu (2FA) veidotājs piekļuves ierakstiem glabātavā." + }, + "ppremiumSignUpSupport": { + "message": "Priekšrocīgs lietotāju atbalsts." + }, + "ppremiumSignUpFuture": { + "message": "Visas nākotnes Premium iespējas. Vairāk drīzumā!" + }, + "premiumPurchase": { + "message": "Iegādāties Premium" + }, + "premiumPurchaseAlert": { + "message": "Premium dalību ir iespējams iegādāties bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "premiumCurrentMember": { + "message": "Tu esi Premium dalībnieks!" + }, + "premiumCurrentMemberThanks": { + "message": "Paldies, ka atbalsti Bitwarden!" + }, + "premiumPrice": { + "message": "Viss par tikai $PRICE$ gadā!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Atsvaidzināšana pabeigta" + }, + "disableAutoTotpCopy": { + "message": "Atspējot automātisku TOTP ievietošanu starpliktuvē" + }, + "disableAutoTotpCopyDesc": { + "message": "Ja pierakstīšanās datiem ir pievienota autentificētāja atslēga, TOTP apstiprinājuma kods tiks automātiski pārkopēts uz starpliktuvi, kad vien tiks automātiski aizpildīta pierakstīšanās veidne." + }, + "disableAutoBiometricsPrompt": { + "message": "Palaišanas brīdī nevaicāt par biometriju." + }, + "premiumRequired": { + "message": "Nepieciešams Premium" + }, + "premiumRequiredDesc": { + "message": "Ir nepieciešama Premium dalība, lai izmantotu šo iespēju." + }, + "enterVerificationCodeApp": { + "message": "Ievadi 6 ciparu apstiprinājuma kodu no autentificētāja lietotnes!" + }, + "enterVerificationCodeEmail": { + "message": "Ievadi 6 ciparu apstiprinājuma kodu, kas tika nosūtīts uz $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-pasts apstiprināšanai nosūtīts uz $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Atcerēties mani" + }, + "sendVerificationCodeEmailAgain": { + "message": "Sūtīt apstiprinājuma koda e-pastu vēlreiz" + }, + "useAnotherTwoStepMethod": { + "message": "Izmantot citu divpakāpju pierakstīšanās veidu" + }, + "insertYubiKey": { + "message": "Ievieto savu YubiKey datora USB ligzdā un pieskaries tā pogai!" + }, + "insertU2f": { + "message": "Ievieto savu drošības atslēgu datora USB ligzdā! Ja tai ir poga, pieskaries tai!" + }, + "webAuthnNewTab": { + "message": "Turpināt WebAuthn 2FA apstiprināšanu jaunā cilnē." + }, + "webAuthnNewTabOpen": { + "message": "Atvērt jaunu cilni" + }, + "webAuthnAuthenticate": { + "message": "Autentificēt WebAuthn" + }, + "loginUnavailable": { + "message": "Pierakstīšanās nav pieejama" + }, + "noTwoStepProviders": { + "message": "Šim kontam ir iespējota divpakāpju pierakstīšanās, bet šajā pārlūkā netiek atbalstīts neviens no uzstādītajiem divpakāpju pārbaudes nodrošinātājiem." + }, + "noTwoStepProviders2": { + "message": "Lūgums izmantot atbalstītu tīmekļa pārlūku (piemēram Chrome) un/vai pievienot papildus nodrošinātājus, kas tiek labāk atbalstīti dažādos pārlūkos (piemēram autentificētāja lietotni)." + }, + "twoStepOptions": { + "message": "Divpakāpju pierakstīšanās iespējas" + }, + "recoveryCodeDesc": { + "message": "Zaudēta piekļuve visiem divpakāpju nodrošinātājiem? Izmanto atkopšanas kodus, lai atspējotu visus sava konta divpakāpju nodrošinātājus!" + }, + "recoveryCodeTitle": { + "message": "Atgūšanas kods" + }, + "authenticatorAppTitle": { + "message": "Autentificētāja lietotne" + }, + "authenticatorAppDesc": { + "message": "Izmanto autentificētāja lietotni (piemēram, Authy vai Google autentifikators), lai izveidotu laikā balstītus apstiprinājuma kodus!", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP drošības atslēga" + }, + "yubiKeyDesc": { + "message": "Izmanto YubiKey, lai piekļūtu savam kontam! Darbojas ar YubiKey 4, 4 Nano, 4C un NEO ierīcēm." + }, + "duoDesc": { + "message": "Apstiprini ar Duo Security, izmantojot Duo Mobile lietotni, īsziņu, tālruņa zvanu vai U2F drošības atslēgu!", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Apstiprini ar Duo Security savā apvienībā, izmantojot Duo Mobile lietotni, īsziņu, tālruņa zvanu vai U2F drošības atslēgu!", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Izmantot jebkuru WebAuthn atbalstošu drošības atslēgu, lai piekļūtu kontam." + }, + "emailTitle": { + "message": "E-pasts" + }, + "emailDesc": { + "message": "Apstiprinājuma kodi tiks nosūtīti e-pastā." + }, + "selfHostedEnvironment": { + "message": "Pašuzturēta vide" + }, + "selfHostedEnvironmentFooter": { + "message": "Norādīt pašuzstādīta Bitwarden pamata URL." + }, + "customEnvironment": { + "message": "Pielāgota vide" + }, + "customEnvironmentFooter": { + "message": "Pieredzējušiem lietotājiem. Ir iespējams norādīt URL katram pakalpojumam atsevišķi." + }, + "baseUrl": { + "message": "Servera URL" + }, + "apiUrl": { + "message": "API servera URL" + }, + "webVaultUrl": { + "message": "Tīmekļa glabātavas servera URL" + }, + "identityUrl": { + "message": "Identitātes servera URL" + }, + "notificationsUrl": { + "message": "Paziņojumu servera URL" + }, + "iconsUrl": { + "message": "Ikonu servera URL" + }, + "environmentSaved": { + "message": "Vides URL ir saglabāti." + }, + "enableAutoFillOnPageLoad": { + "message": "Iespējot aizpildīšanu lapas ielādes brīdī" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Ja tiek noteikta pieslēgšanās veidne, tā tiks aizpildīta lapas ielādes brīdī." + }, + "experimentalFeature": { + "message": "Šī iespēja pašlaik ir izmēģināšanā. Izmantošanas atbildība ir katra paša pārziņā. " + }, + "defaultAutoFillOnPageLoad": { + "message": "Noklusējuma automātiskās aizpildes iestatījums pierakstīšanās vienumiem" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Pēc automātiskās aizpildes lapas ielādes brīdī iespējošanas šo iespēju var ieslēgt vai izslēgt atsevišķiem pierakstīšanās vienumiem. Šis ir noklusējuma iestatījums visiem ierakstiem, kuriem nav norādīts šis uzstādījums." + }, + "itemAutoFillOnPageLoad": { + "message": "Automātiski aizpildīt lapas ielādes brīdī (ja iespējots iestatījumos)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Izmantot noklusējuma iestatījumu" + }, + "autoFillOnPageLoadYes": { + "message": "Automātiski aizpildīt lapas ielādes brīdī" + }, + "autoFillOnPageLoadNo": { + "message": "Neaizpildīt lapas ielādes brīdī" + }, + "commandOpenPopup": { + "message": "Atvērt glabātavas uznirstošo logu" + }, + "commandOpenSidebar": { + "message": "Atvērt glabātavu sānu joslā" + }, + "commandAutofillDesc": { + "message": "Automātiski aizpildīt ar iepriekš izmantoto pierakstīšanās vienumu pašreizējā tīmekļa vietnē" + }, + "commandGeneratePasswordDesc": { + "message": "Izveidot jaunu nejaušu paroli un ievietot to starpliktuvē" + }, + "commandLockVaultDesc": { + "message": "Aizslēgt glabātavu" + }, + "privateModeWarning": { + "message": "Personiskā stāvokļa atbalsts ir izmēģinājuma, un dažas iespējas ir ierobežotas." + }, + "customFields": { + "message": "Pielāgoti lauki" + }, + "copyValue": { + "message": "Ievietot vērtību starpliktuvē" + }, + "value": { + "message": "Vērtība" + }, + "newCustomField": { + "message": "Jauns pielāgotais lauks" + }, + "dragToSort": { + "message": "Vilkt, lai kārtotu" + }, + "cfTypeText": { + "message": "Teksts" + }, + "cfTypeHidden": { + "message": "Paslēpts" + }, + "cfTypeBoolean": { + "message": "Patiesuma vērtība" + }, + "cfTypeLinked": { + "message": "Saistīts", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Saistīta vērtība", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Klikšķināšana ārpus uznirstošā loga, lai apskatītu e-pastā apstiprinājuma kodu, to aizvērs. Vai atvērt to atsevišķā logā, lai tas netiktu aizvērts?" + }, + "popupU2fCloseMessage": { + "message": "Šis pārlūks nevar apstrādāt U2F pieprasījumus šajā uznirstošajā logā. Vai atvērt to atsevišķā logā, lai varētu pierakstīties, izmantojot U2F?" + }, + "disableFavicon": { + "message": "Atspējot tīmekļa vietņu ikonas" + }, + "disableFaviconDesc": { + "message": "Tīmekļa vietņu ikonas nodrošina atpazīstamu attēlu pie katra glabātavas pieteikšanās vienuma." + }, + "disableBadgeCounter": { + "message": "Atspējot skaitītāja nozīmīti" + }, + "disableBadgeCounterDesc": { + "message": "Skaitītāja nozīmīte norāda, cik pierakstīšanās vienumu pašreizējai lapai ir atrodami glabātavā." + }, + "cardholderName": { + "message": "Kartes īpašnieka vārds" + }, + "number": { + "message": "Numurs" + }, + "brand": { + "message": "Zīmols" + }, + "expirationMonth": { + "message": "Derīguma mēnesis" + }, + "expirationYear": { + "message": "Derīguma gads" + }, + "expiration": { + "message": "Derīgums" + }, + "january": { + "message": "Janvāris" + }, + "february": { + "message": "Februāris" + }, + "march": { + "message": "Marts" + }, + "april": { + "message": "Aprīlis" + }, + "may": { + "message": "Maijs" + }, + "june": { + "message": "Jūnijs" + }, + "july": { + "message": "Jūlijs" + }, + "august": { + "message": "Augusts" + }, + "september": { + "message": "Septembris" + }, + "october": { + "message": "Oktobris" + }, + "november": { + "message": "Novembris" + }, + "december": { + "message": "Decembris" + }, + "securityCode": { + "message": "Drošības kods" + }, + "ex": { + "message": "piem." + }, + "title": { + "message": "Uzruna" + }, + "mr": { + "message": "K-gs" + }, + "mrs": { + "message": "K-dze" + }, + "ms": { + "message": "Jk-dze" + }, + "dr": { + "message": "Dr." + }, + "firstName": { + "message": "Vārds" + }, + "middleName": { + "message": "Citi vārdi" + }, + "lastName": { + "message": "Uzvārds" + }, + "fullName": { + "message": "Pilnais vārds" + }, + "identityName": { + "message": "Identitātes nosaukums" + }, + "company": { + "message": "Uzņēmums" + }, + "ssn": { + "message": "Personas kods" + }, + "passportNumber": { + "message": "Pases numurs" + }, + "licenseNumber": { + "message": "Autovadītāja apliecības numurs" + }, + "email": { + "message": "E-pasts" + }, + "phone": { + "message": "Tālrunis" + }, + "address": { + "message": "Adrese" + }, + "address1": { + "message": "Adrese 1" + }, + "address2": { + "message": "Adrese 2" + }, + "address3": { + "message": "Adrese 3" + }, + "cityTown": { + "message": "Pilsēta / ciems" + }, + "stateProvince": { + "message": "Novads / pagasts" + }, + "zipPostalCode": { + "message": "Pasta indekss" + }, + "country": { + "message": "Valsts" + }, + "type": { + "message": "Veids" + }, + "typeLogin": { + "message": "Pierakstīšanās vienums" + }, + "typeLogins": { + "message": "Pierakstīšanās vienumi" + }, + "typeSecureNote": { + "message": "Droša piezīme" + }, + "typeCard": { + "message": "Karte" + }, + "typeIdentity": { + "message": "Identitāte" + }, + "passwordHistory": { + "message": "Paroļu vēsture" + }, + "back": { + "message": "Atpakaļ" + }, + "collections": { + "message": "Krājumi" + }, + "favorites": { + "message": "Izlase" + }, + "popOutNewWindow": { + "message": "Atvērt atsevišķā logā" + }, + "refresh": { + "message": "Atsvaidzināt" + }, + "cards": { + "message": "Kartes" + }, + "identities": { + "message": "Identitātes" + }, + "logins": { + "message": "Pierakstīšanās vienumi" + }, + "secureNotes": { + "message": "Drošās piezīmes" + }, + "clear": { + "message": "Notīrīt", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Pārbaudīt, vai parole ir bijusi nopludināta." + }, + "passwordExposed": { + "message": "Šī parole datu pārkāpumos ir atklāta $VALUE$ reizi(es). To vajag mainīt.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Šī parole netika atrasta nevienā no zināmajiem datu pārkāpumiem. Tai vajadzētu būt droši izmantojamai." + }, + "baseDomain": { + "message": "Pamata domēns", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domēna vārds", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Saimniekdators", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tiešs" + }, + "startsWith": { + "message": "Sākas ar" + }, + "regEx": { + "message": "Regulārā izteiksme", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Atbilstības noteikšana", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Noklusētā atbilstības noteikšana", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Pārslēgt iespējas" + }, + "toggleCurrentUris": { + "message": "Pārslēgt pašreizējos URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Pašreizējais URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Apvienība", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Veidi" + }, + "allItems": { + "message": "Visi vienumi" + }, + "noPasswordsInList": { + "message": "Nav paroļu, ko parādīt." + }, + "remove": { + "message": "Noņemt" + }, + "default": { + "message": "Noklusējums" + }, + "dateUpdated": { + "message": "Atjaunināts", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parole atjaunināta", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Vai tiešām izmantot uzstādījumu \"Nekad\"? Uzstādot aizslēgšanas iespēju uz \"Nekad\", šifrēšanas atslēga tiek glabāta ierīcē. Ja šī iespēja tiek izmantota, jāpārliecinās, ka ierīce tiek pienācīgi aizsargāta." + }, + "noOrganizationsList": { + "message": "Tu neesi iekļauts nevienā apvienībā. Apvienības sniedz iespēju droši kopīgot vienumus ar citiem lietotājiem." + }, + "noCollectionsInList": { + "message": "Nav krājumu, ko parādīt." + }, + "ownership": { + "message": "Īpašumtiesības" + }, + "whoOwnsThisItem": { + "message": "Kam pieder šis vienums?" + }, + "strong": { + "message": "Spēcīga", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Laba", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Vāja", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Vāja galvenā parole" + }, + "weakMasterPasswordDesc": { + "message": "Jūsu izvēlētā galvenā parole ir vāja. Jums vajadzētu izmantot drošu galveno paroli (vai paroles vārdkopu), lai pienācīgi aizsargātu savu Bitwarden kontu. Vai tiešām vēlaties izmantot šo galveno paroli?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Atslēgt ar PIN" + }, + "setYourPinCode": { + "message": "Uzstādīt PIN kodu Bitwarden atslēgšanai. PIN iestatījumi tiks atiestatīti, ja jebkad tiks veikta pilnīga izrakstīšanās no lietotnes." + }, + "pinRequired": { + "message": "Ir nepieciešams PIN kods." + }, + "invalidPin": { + "message": "Nederīgs PIN kods." + }, + "unlockWithBiometrics": { + "message": "Atslēgt ar biometriju" + }, + "awaitDesktop": { + "message": "Tiek gaidīts apstiprinājums no darbvirsmas" + }, + "awaitDesktopDesc": { + "message": "Lūgums apstiprināt ar biometriju Bitwarden darbvirsmas lietotnē, lai iespējotu biometriju pārlūkā." + }, + "lockWithMasterPassOnRestart": { + "message": "Aizslēgt ar galveno paroli pēc pārlūka atsāknēšanas" + }, + "selectOneCollection": { + "message": "Ir jāizvēlas vismaz viens krājums." + }, + "cloneItem": { + "message": "Pavairot vienumu" + }, + "clone": { + "message": "Pavairot" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Viens vai vairāki apvienības nosacījumi ietekmē veidotāja iestatījumus." + }, + "vaultTimeoutAction": { + "message": "Glabātavas noildzes darbība" + }, + "lock": { + "message": "Slēgt", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Atkritne", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Meklēt atkritnē" + }, + "permanentlyDeleteItem": { + "message": "Neatgriezeniski izdzēst vienumu" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Vai tiešām neatgriezeniski izdzēst šo vienumu?" + }, + "permanentlyDeletedItem": { + "message": "Vienums ir neatgriezeniski izdzēsts" + }, + "restoreItem": { + "message": "Atjaunot vienumu" + }, + "restoreItemConfirmation": { + "message": "Jūs tiešām atjaunot šo vienumu?" + }, + "restoredItem": { + "message": "Vienums atjaunots" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Izrakstīšanās noņems visu piekļuvi glabātavai un pieprasīs tiešsaistes pieteikšanos pēc noildzes laika. Vai tiešām izmantot šo iestatījumu?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Noildzes darbības apstiprināšana" + }, + "autoFillAndSave": { + "message": "Automātiski aizpildīt un saglabāt" + }, + "autoFillSuccessAndSavedUri": { + "message": "Automātiski aizpildīts vienums un saglabāts URI" + }, + "autoFillSuccess": { + "message": "Automātiski aizpildīts vienums" + }, + "setMasterPassword": { + "message": "Uzstādīt galveno paroli" + }, + "masterPasswordPolicyInEffect": { + "message": "Viena vai vairākas apvienības nosacījumos ir norādīts, lai galvenā parole atbilst šādām prasībām:" + }, + "policyInEffectMinComplexity": { + "message": "Mazākais pieļaujamais sarežģītības novērtējums ir $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Mazākais pieļaujamais garums ir $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Satur vienu vai vairākus lielos burtus" + }, + "policyInEffectLowercase": { + "message": "Satur vienu vai vairākus mazos burtus" + }, + "policyInEffectNumbers": { + "message": "Satur vienu vai vairākus skaitļus" + }, + "policyInEffectSpecial": { + "message": "Satur vienu vai vairākas no šīm īpašajām rakstzīmēm: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Jaunā galvenā parole neatbilst nosacījumu prasībām." + }, + "acceptPolicies": { + "message": "Atzīmējot šo rūtiņu, Tu piekrīti sekojošajam:" + }, + "acceptPoliciesError": { + "message": "Nav pieņemti izmantošanas nosacījumi un privātuma politika." + }, + "termsOfService": { + "message": "Izmantošanas nosacījumi" + }, + "privacyPolicy": { + "message": "Privātuma nosacījumi" + }, + "hintEqualsPassword": { + "message": "Paroles norāde nedrīkst būt tāda pati kā parole." + }, + "ok": { + "message": "Labi" + }, + "desktopSyncVerificationTitle": { + "message": "Darbvirsmas sinhronizācijas apstiprinājums" + }, + "desktopIntegrationVerificationText": { + "message": "Lūgumus pārliecināties, ka darbvirsmas lietotne rāda šo atpazīšanas vārdkopu:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Savienojums ar pārlūku nav iespējots" + }, + "desktopIntegrationDisabledDesc": { + "message": "Savienojums ar pārlūku nav iespējots Bitwarden darbvirsmas lietotnē. Lūgums iespējot to darbvirsmas lietotnes iestatījumos." + }, + "startDesktopTitle": { + "message": "Palaist Bitwarden darbvirsmas lietotni" + }, + "startDesktopDesc": { + "message": "Bitwarden darbvirsmas lietotnei ir jābūt sāknētai, pirms šī iespēja var tikt izmantota." + }, + "errorEnableBiometricTitle": { + "message": "Nevar iespējot biometriju" + }, + "errorEnableBiometricDesc": { + "message": "Darbvirsmas lietotne atcēla darbību" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Darbvirsmas lietotne drošo saziņas avotu padarīja par nederīgu. Lūgums atkārtot šo darbību" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Darbvirsmas saziņa tika pārtraukta" + }, + "nativeMessagingWrongUserDesc": { + "message": "Darbvirsmas lietotne ir pierakstījusies atšķirīgā kontā. Lūgums nodrošināt, ka abas lietotnes ir pierakstījušās vienam un tam pašam kontam." + }, + "nativeMessagingWrongUserTitle": { + "message": "Konta nesaderība" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrija nav iespējota" + }, + "biometricsNotEnabledDesc": { + "message": "Vispirms ir nepieciešams iespējot biometriju darbvirsmas iestatījumos, lai to varētu izmantot pārlūkā." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrija nav nodrošināta" + }, + "biometricsNotSupportedDesc": { + "message": "Šajā ierīcē netiek atbalstīta pārlūka biometrija." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Atļauja nav nodrošināta" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bez atļaujas sazināties ar Bitwarden darbvirsmas lietotni mēs nevaram nodrošināt biometriju pārlūka paplašinājumā. Lūgums mēģināt vēlreiz." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Atļaujas pieprasījuma kļūda" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Šī darbība nav izpildāma sānjoslā, tāpēc lūgums mēģināt to veikt uznirstošajā vai izlecošajā logā." + }, + "personalOwnershipSubmitError": { + "message": "Uzņēmuma nosacījumi liedz saglabāt vienumus privātajā glabātavā. Norādi piederību apvienībai un izvēlies kādu no pieejamajiem krājumiem." + }, + "personalOwnershipPolicyInEffect": { + "message": "Apvienības nosacījumi ietekmē Tavas īpašumtiesību iespējas." + }, + "excludedDomains": { + "message": "Izņēmuma domēni" + }, + "excludedDomainsDesc": { + "message": "Bitwarden nevaicās saglabāt pierakstīšanās datus šiem domēniem. Ir jāpārlādē lapa, lai izmaiņas iedarbotos." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ nav derīgs domēns", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "\"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Meklēt \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Pievienot \"Send'", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Teksts" + }, + "sendTypeFile": { + "message": "Datne" + }, + "allSends": { + "message": "Visi \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Sasniegts lielākais pieļaujamais piekļuvju skaits", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Beidzies izmantošanas laiks" + }, + "pendingDeletion": { + "message": "Gaida dzēšanu" + }, + "passwordProtected": { + "message": "Aizsargāts ar paroli" + }, + "copySendLink": { + "message": "Ievietot \"Send\" saiti starpliktuvē", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Noņemt paroli" + }, + "delete": { + "message": "Dzēst" + }, + "removedPassword": { + "message": "Parole noņemta" + }, + "deletedSend": { + "message": "\"Send\" izdzēsts", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "\"Send\" saite", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Atspējots" + }, + "removePasswordConfirmation": { + "message": "Vai tiešām noņemt paroli?" + }, + "deleteSend": { + "message": "Dzēst \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Vai tiešām izdzēst šo \"Send\"?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Labot \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Kāds veids ir šim \"Send\"?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Lasāms nosaukums, kas apraksta šo \"Send\".", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Datne, kuru ir vēlme nosūtīt." + }, + "deletionDate": { + "message": "Dzēšanas datums" + }, + "deletionDateDesc": { + "message": "\"Send\" tiks pastāvīgi izdzēsts norādītajā dienā un laikā.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Derīguma beigu datums" + }, + "expirationDateDesc": { + "message": "Ja uzstādīts, piekļuve šim \"Send\" beigsies norādītajā dienā un laikā.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 diena" + }, + "days": { + "message": "$DAYS$ dienas", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Pielāgots" + }, + "maximumAccessCount": { + "message": "Lielākais pieļaujamais piekļuvju skaits" + }, + "maximumAccessCountDesc": { + "message": "Ja uzstādīts, lietotāji nevarēs piekļūt šim \"Send\", kad tiks sasniegts lielākais pieļaujamais piekļūšanas reižu skaits.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Pēc izvēles pieprasīt lietotājiem paroli, lai viņi varētu piekļūt šim \"Send\".", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Personīgās piezīmes par šo \"Send\".", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Atspējot šo \"Send\", lai neviens tam nevarētu piekļūt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Saglabājot ievietot šī \"Send\" saiti starpliktuvē.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teksts, kuru ir vēlme nosūtīt." + }, + "sendHideText": { + "message": "Pēc noklusējuma paslēpt šī \"Send\" tekstu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Pašreizējais piekļuvju skaits" + }, + "createSend": { + "message": "Izveidot jaunu \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Jauna parole" + }, + "sendDisabled": { + "message": "\"Send\" atspējots", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Uzņēmuma nosacījumu kopas dēļ ir tikai iespējams dzēst esošu \"Send\".", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "\"Send\" izveidots", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "\"Send\" labots", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Lai izvēlētos datni, paplašinājums ir jāatver sānjoslā (ja iespējams) vai atsevišķā logā, klikšķinot uz šī paziņojuma." + }, + "sendFirefoxFileWarning": { + "message": "Lai izvēlētos datni, ja tiek izmantots Firefox, paplašinājums ir jāatver sānjoslā vai atsevišķā logā, klikšķinot uz šī paziņojuma." + }, + "sendSafariFileWarning": { + "message": "Lai izvēlētos datni, ja tiek izmantots Safari, paplašinājums ir jāatver jaunā logā, klikšķinot uz šī paziņojuma." + }, + "sendFileCalloutHeader": { + "message": "Pirms sākt" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Lai izmantotu kalendāra veida datumu atlasītāju,", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klikšķināt šeit,", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "lai atvērtu jaunā logā.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Norādītais derīguma beigu datums nav derīgs." + }, + "deletionDateIsInvalid": { + "message": "Norādītais dzēšanas datums nav derīgs." + }, + "expirationDateAndTimeRequired": { + "message": "Ir jānorāda derīguma beigu datums un laiks." + }, + "deletionDateAndTimeRequired": { + "message": "Ir jānorāda dzēšanas datums un laiks." + }, + "dateParsingError": { + "message": "Atgadījusies kļūda dzēšanas un derīguma beigu datumu saglabāšanā." + }, + "hideEmail": { + "message": "Slēpt e-pasta adresi no saņēmējiem." + }, + "sendOptionsPolicyInEffect": { + "message": "Viens vai vairāki apvienības nosacījumi ietekmē \"Send\" iestatījumus." + }, + "passwordPrompt": { + "message": "Galvenās paroles pārvaicāšana" + }, + "passwordConfirmation": { + "message": "Galvenās paroles apstiprināšana" + }, + "passwordConfirmationDesc": { + "message": "Šī darbība ir aizsargāta. Lai turpinātu, ir jāievada galvenā parole, lai apstiprinātu identitāti." + }, + "emailVerificationRequired": { + "message": "Nepieciešama e-pasta adreses apstiprināšana" + }, + "emailVerificationRequiredDesc": { + "message": "Ir nepieciešams apstiprināt e-pasta adresi, lai būtu iespējams izmantot šo iespēju. To var izdarīt tīmekļa glabātavā." + }, + "updatedMasterPassword": { + "message": "Galvenā parole atjaunināta" + }, + "updateMasterPassword": { + "message": "Atjaunināt galveno paroli" + }, + "updateMasterPasswordWarning": { + "message": "Apvienības pārvaldnieks nesen nomainīja galveno paroli. Lai piekļūtu glabātavai, tā ir jāatjaunina. Turpinot tiks izbeigta pašreizējā sesija un tiks pieprasīta atkārtota pierakstīšanās. Esošās sesijas citās iekārtās var turpināt darboties līdz vienai stundai." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automātiska ievietošana sarakstā" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Šajā apvienībā ir uzņēmuma nosacījums, kas automātiski ievieto lietotājus paroles atiestatīšanas sarakstā. Tas ļauj apvienības pārvaldniekiem mainīt lietotāju galveno paroli." + }, + "selectFolder": { + "message": "Izvēlēties mapi..." + }, + "ssoCompleteRegistration": { + "message": "Lai pabeigtu vienotās pieteikšanās uzstādīšanu, ir jānorāda galvenā parole, lai piekļūtu glabātavai un aizsargātu to." + }, + "hours": { + "message": "Stundas" + }, + "minutes": { + "message": "Minūtes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Apvienības nosacījumi ietekmē glabātavas noildzi. Lielākā atļautā glabātavas noildze ir $HOURS$ stunda(s) un $MINUTES$ minūte(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Glabātavas noildze pāŗsniedz apvienības uzstādītos ierobežojumus." + }, + "vaultExportDisabled": { + "message": "Glabātavas izgūšana ir atspējota" + }, + "personalVaultExportPolicyInEffect": { + "message": "Viens vai vairāki apvienības nosacījumi neļauj izgūt privātās glabātavas saturu." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Nav iespējams noteikt derīgu veidlapas daļu. Var mēģināt pārbaudīt HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nav atrasts neviens neatkārtojams identifikators" + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ izmanto vienoto pieteikšanos ar pašizvietotu atslēgu serveri. Tās dalībniekiem vairs nav nepieciešama galvenā parole, lai pieslēgtos.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Pamest apvienību" + }, + "removeMasterPassword": { + "message": "Noņemt galveno paroli" + }, + "removedMasterPassword": { + "message": "Galvenā parole noņemta." + }, + "leaveOrganizationConfirmation": { + "message": "Vai tiešām pamest šo apvienību?" + }, + "leftOrganization": { + "message": "Apvienība ir pamesta." + }, + "toggleCharacterCount": { + "message": "Pārslēgt rakstzīmju skaita attēlošanu" + }, + "sessionTimeout": { + "message": "Sesijai iestājās noildze. Lūgums mēģināt pierakstīties vēlreiz." + }, + "exportingPersonalVaultTitle": { + "message": "Izdod personīgo glabātavu" + }, + "exportingPersonalVaultDescription": { + "message": "Tiks izdoti tikai personīgie glabātavas vienumi, kas ir saistīti ar $EMAIL$. Apvienības glabātavas vienumi netiks iekļauti.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Kļūda" + }, + "regenerateUsername": { + "message": "Pārizveidot lietotājvārdu" + }, + "generateUsername": { + "message": "Izveidot lietotājvārdu" + }, + "usernameType": { + "message": "Lietotājvārda veids" + }, + "plusAddressedEmail": { + "message": "E-pasta adrese ar plusu", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Izmantot e-pasta pakalpojuma nodrošinātāja apakšadresēšanas spējas." + }, + "catchallEmail": { + "message": "Visu tveroša e-pasta adrese" + }, + "catchallEmailDesc": { + "message": "Izmantot uzstādīto domēna visu tverošo iesūtni." + }, + "random": { + "message": "Nejauši" + }, + "randomWord": { + "message": "Nejaušs vārds" + }, + "websiteName": { + "message": "Tīmekļa vietnes nosaukums" + }, + "whatWouldYouLikeToGenerate": { + "message": "Ko ir nepieciešams izveidot?" + }, + "passwordType": { + "message": "Paroles veids" + }, + "service": { + "message": "Pakalpojums" + } +} diff --git a/apps/browser/src/_locales/ml/messages.json b/apps/browser/src/_locales/ml/messages.json new file mode 100644 index 0000000000..9ae2ae43b6 --- /dev/null +++ b/apps/browser/src/_locales/ml/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - സൗജന്യ പാസ്സ്‌വേഡ് മാനേജർ ", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങൾക്കും സുരക്ഷിതവും സൗജന്യവുമായ പാസ്‌വേഡ് മാനേജർ.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "നിങ്ങളുടെ സുരക്ഷിത വാൾട്ടിലേക്കു പ്രവേശിക്കാൻ ലോഗിൻ ചെയ്യുക അല്ലെങ്കിൽ ഒരു പുതിയ അക്കൗണ്ട് സൃഷ്ടിക്കുക." + }, + "createAccount": { + "message": "അക്കൗണ്ട് സൃഷ്ടിക്കുക" + }, + "login": { + "message": "ലോഗിൻ" + }, + "enterpriseSingleSignOn": { + "message": "എന്റർപ്രൈസ് സിംഗിൾ സൈൻ-ഓൺ" + }, + "cancel": { + "message": "റദ്ദാക്കുക" + }, + "close": { + "message": "അടയ്ക്കുക" + }, + "submit": { + "message": "സമർപ്പിക്കുക" + }, + "emailAddress": { + "message": "ഈ - മെയില് വിലാസം" + }, + "masterPass": { + "message": "പ്രാഥമിക പാസ്‌വേഡ്" + }, + "masterPassDesc": { + "message": "നിങ്ങളുടെ വാൾട്ടിലേക്ക് പ്രവേശിക്കാൻ ഉപയോഗിക്കുന്ന പാസ്‌വേഡാണ് പ്രാഥമിക പാസ്‌വേഡ്. നിങ്ങളുടെ മാസ്റ്റർ പാസ്‌വേഡ് മറക്കാതിരിക്കുക എന്നത് വളരെ പ്രധാനമാണ്. നിങ്ങൾ പാസ്‌വേഡ് മറന്ന സാഹചര്യത്തിൽ, പാസ്‌വേഡ് വീണ്ടെടുക്കാൻ ഒരു മാർഗവുമില്ല." + }, + "masterPassHintDesc": { + "message": "നിങ്ങളുടെ പാസ്‌വേഡ് മറന്നാൽ അത് ഓർമ്മിക്കാൻ ഒരു പ്രാഥമിക പാസ്‌വേഡ് സൂചന സഹായിക്കും." + }, + "reTypeMasterPass": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് വീണ്ടും ടൈപ്പ്‌ ചെയ്യുക" + }, + "masterPassHint": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സൂചന (ഇഷ്ടാനുസൃതമായ)" + }, + "tab": { + "message": "ടാബ് " + }, + "myVault": { + "message": "എൻ്റെ വാൾട് " + }, + "tools": { + "message": "ഉപകരണങ്ങള്‍" + }, + "settings": { + "message": "ക്രമീകരണങ്ങള്‍" + }, + "currentTab": { + "message": "നിലവിലെ ടാബ്" + }, + "copyPassword": { + "message": "പാസ്‌വേഡ് പകർത്തുക" + }, + "copyNote": { + "message": "കുറിപ്പ് പകർത്തുക" + }, + "copyUri": { + "message": "URI പകർത്തുക" + }, + "copyUsername": { + "message": "ഉപയോക്തൃനാമം പകർത്തുക" + }, + "copyNumber": { + "message": "അക്കം പകർത്തുക" + }, + "copySecurityCode": { + "message": "സുരക്ഷാ കോഡ് പകർത്തുക" + }, + "autoFill": { + "message": "ഓട്ടോഫിൽ" + }, + "generatePasswordCopied": { + "message": "പാസ്‌വേഡ് സൃഷ്ടിക്കുക (പകർത്തുക )" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "പൊരുത്തപ്പെടുന്ന ലോഗിനുകളൊന്നുമില്ല." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "നിലവിലെ ബ്രൌസർ ടാബിന് ഓട്ടോഫിൽ ചെയ്യാൻ പ്രവേശനങ്ങൾ ലഭ്യമല്ല." + }, + "addLogin": { + "message": "പ്രവേശനം ചേർക്കുക" + }, + "addItem": { + "message": " ഇനം ചേർക്കുക" + }, + "passwordHint": { + "message": "പാസ്സ്‌വേഡ് സൂചനാ" + }, + "enterEmailToGetHint": { + "message": "നിങ്ങളുടെ പ്രാഥമിക പാസ്‌വേഡ് സൂചന ലഭിക്കുന്നതിന് നിങ്ങളുടെ അക്കൗണ്ട് ഇമെയിൽ വിലാസം നൽകുക." + }, + "getMasterPasswordHint": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സൂചന നേടുക" + }, + "continue": { + "message": "തുടരുക" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "പരിശോധിച്ചുറപ്പിക്കൽ കോഡ്" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "അക്കൗണ്ട്" + }, + "changeMasterPassword": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് മാറ്റുക" + }, + "fingerprintPhrase": { + "message": "ഫിംഗർപ്രിന്റ് ഫ്രേസ്‌", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "നിങ്ങളുടെ അക്കൗണ്ടിന്റെ ഫിംഗർപ്രിന്റ് ഫ്രേസ്‌", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "രണ്ട്-ഘട്ട ലോഗിൻ" + }, + "logOut": { + "message": "ലോഗ് ഔട്ട്" + }, + "about": { + "message": "ഇതിനെ കുറിച്ച്" + }, + "version": { + "message": "വേർഷൻ " + }, + "save": { + "message": "സംരക്ഷിക്കുക" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "ഫോൾഡർ ചേർക്കുക" + }, + "name": { + "message": "പേര്" + }, + "editFolder": { + "message": "ഫോൾഡർ തിരുത്തുക" + }, + "deleteFolder": { + "message": "ഫോൾഡർ ഇല്ലാതാക്കുക" + }, + "folders": { + "message": "ഫോൾഡറുകൾ" + }, + "noFolders": { + "message": "പ്രദർശിപ്പിക്കാൻ ഫോൾഡറുകളൊന്നുമില്ല." + }, + "helpFeedback": { + "message": "സഹായവും അഭിപ്രായവും" + }, + "sync": { + "message": "സമന്വയിപ്പിക്കുക" + }, + "syncVaultNow": { + "message": "വാൾട് ഇപ്പോൾ സമന്വയിപ്പിക്കുക" + }, + "lastSync": { + "message": "അവസാന സമന്വയം:" + }, + "passGen": { + "message": "പാസ്സ്‌വേഡ് സൃഷ്ടാവ്" + }, + "generator": { + "message": "സ്രഷ്ടാവ്", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "യാന്ത്രികമായി ശക്തമായ പാസ്സ്‌വേർഡുകൾ നിങ്ങളുടെ ലോഗിന് വേണ്ടി നിർമിക്കുക " + }, + "bitWebVault": { + "message": "Bitwarden വെബ് വാൾട് " + }, + "importItems": { + "message": "ഇനങ്ങൾ ഇമ്പോർട് ചെയ്യുക" + }, + "select": { + "message": "തിരഞ്ഞെടുക്കുക" + }, + "generatePassword": { + "message": "പാസ്‌വേഡ് സൃഷ്ടിക്കുക" + }, + "regeneratePassword": { + "message": "പാസ്സ്‌വേഡ് വീണ്ടും സൃഷ്ടിക്കുക" + }, + "options": { + "message": "ഓപ്ഷനുകൾ" + }, + "length": { + "message": "നീളം" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "വാക്കുകളുടെ എണ്ണം" + }, + "wordSeparator": { + "message": "വേര്‍പെടുത്തുക" + }, + "capitalize": { + "message": "വലിയഅക്ഷരമാകുക", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "നമ്പർ ഉൾപ്പെടുത്തുക" + }, + "minNumbers": { + "message": "കുറഞ്ഞ സംഖ്യകൾ" + }, + "minSpecial": { + "message": "കുറഞ്ഞ പ്രത്യേക പ്രതീകങ്ങൾ" + }, + "avoidAmbChar": { + "message": "അവ്യക്തമായ പ്രതീകങ്ങൾ ഒഴിവാക്കുക" + }, + "searchVault": { + "message": "വാൾട് തിരയുക" + }, + "edit": { + "message": "തിരുത്തുക" + }, + "view": { + "message": "കാണുക" + }, + "noItemsInList": { + "message": "പ്രദർശിപ്പിക്കാൻ ഇനങ്ങളൊന്നുമില്ല." + }, + "itemInformation": { + "message": "വിവരം" + }, + "username": { + "message": "ഉപയോക്തൃനാമം" + }, + "password": { + "message": "പാസ്സ്‌വേഡ്‌" + }, + "passphrase": { + "message": "രഹസ്യ വാചകം" + }, + "favorite": { + "message": "പ്രിയങ്കരം" + }, + "notes": { + "message": "കുറിപ്പുകൾ" + }, + "note": { + "message": "കുറിപ്പ്" + }, + "editItem": { + "message": "ഇനം തിരുത്തുക" + }, + "folder": { + "message": "ഫോൾഡർ" + }, + "deleteItem": { + "message": "ഇനം ഇല്ലാതാക്കുക " + }, + "viewItem": { + "message": "ഇനം കാണുക" + }, + "launch": { + "message": "തുറക്കുക" + }, + "website": { + "message": "വെബ്സൈറ്റ്" + }, + "toggleVisibility": { + "message": "ദൃശ്യപരത ടോഗിൾ ചെയ്യുക" + }, + "manage": { + "message": "നിയന്ത്രിക്കുക" + }, + "other": { + "message": "മറ്റുള്ളവ" + }, + "rateExtension": { + "message": "എക്സ്റ്റൻഷൻ റേറ്റ് ചെയ്യുക " + }, + "rateExtensionDesc": { + "message": "ഒരു നല്ല അവലോകനത്തിന് ഞങ്ങളെ സഹായിക്കുന്നത് പരിഗണിക്കുക!" + }, + "browserNotSupportClipboard": { + "message": "നിങ്ങളുടെ ബ്രൌസർ എളുപ്പമുള്ള ക്ലിപ്പ്ബോർഡ് പകർത്തൽ പിന്തുണയ്ക്കത്തില്ല. പകരം അത് സ്വമേധയാ പകർക്കുക ." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "തങ്ങളുടെ വാൾട് പൂട്ടിയിരിക്കുന്നു. തുടരുന്നതിന് നിങ്ങളുടെ പ്രാഥമിക പാസ്‌വേഡ് പരിശോധിക്കുക." + }, + "unlock": { + "message": "അൺലോക്ക്" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ൽ$EMAIL$ലോഗിൻ ചെയ്തിരിക്കുന്നു.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "അസാധുവായ പ്രാഥമിക പാസ്‌വേഡ്" + }, + "vaultTimeout": { + "message": "വാൾട് ടൈംഔട്ട്" + }, + "lockNow": { + "message": "ഇപ്പോൾ ലോക്കുചെയ്യുക" + }, + "immediately": { + "message": "ഉടന്‍തന്നെ" + }, + "tenSeconds": { + "message": "10 സെക്കൻഡ്" + }, + "twentySeconds": { + "message": "20 സെക്കന്റുകള്‍" + }, + "thirtySeconds": { + "message": "30 സെക്കൻഡ്" + }, + "oneMinute": { + "message": "1 മിനിറ്റ്" + }, + "twoMinutes": { + "message": "2 മിനിറ്റ്" + }, + "fiveMinutes": { + "message": "5 മിനിറ്റ്" + }, + "fifteenMinutes": { + "message": "15 മിനിറ്റ്" + }, + "thirtyMinutes": { + "message": "30 മിനിറ്റ്" + }, + "oneHour": { + "message": "1 മണിക്കൂർ" + }, + "fourHours": { + "message": "4 മണിക്കൂർ" + }, + "onLocked": { + "message": "സിസ്റ്റം ലോക്കിൽ" + }, + "onRestart": { + "message": "ബ്രൌസർ പുനരാരംഭിക്കുമ്പോൾ" + }, + "never": { + "message": "ഒരിക്കലും വേണ്ട" + }, + "security": { + "message": "സുരക്ഷ" + }, + "errorOccurred": { + "message": "ഒരു പിഴവ് സംഭവിച്ചിരിക്കുന്നു" + }, + "emailRequired": { + "message": "ഇമെയിൽ അഡ്രസ്സ് നിരബന്ധമാണ്." + }, + "invalidEmail": { + "message": "അസാധുവായ ഇമെയിൽ." + }, + "masterPassRequired": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് നിർബന്ധമാണ്‌." + }, + "masterPassLength": { + "message": "പ്രാഥമിക പാസ്‌വേഡിന് കുറഞ്ഞത് 8 പ്രതീകങ്ങളെങ്കിലും ദൈർഘ്യമുണ്ടായിരിക്കണം." + }, + "masterPassDoesntMatch": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സ്ഥിരീകരണം പൊരുത്തപ്പെടുന്നില്ല." + }, + "newAccountCreated": { + "message": "തങ്ങളുടെ അക്കൗണ്ട് സൃഷ്ടിക്കപ്പെട്ടു! ഇനി താങ്കൾക്ക് ലോഗിൻ ചെയ്യാം." + }, + "masterPassSent": { + "message": "നിങ്ങളുടെ പ്രാഥമിക പാസ്‌വേഡ് സൂചനയുള്ള ഒരു ഇമെയിൽ ഞങ്ങൾ നിങ്ങൾക്ക് അയച്ചു." + }, + "verificationCodeRequired": { + "message": "പരിശോധിച്ചുറപ്പിക്കൽ കോഡ് ആവശ്യമാണ്." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ പകർത്തി", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "ഈ പേജിൽ തിരഞ്ഞെടുത്ത ഇനം യാന്ത്രികമായി പൂരിപ്പിക്കാൻ കഴിയില്ല. പകരം വിവരങ്ങൾ പകർത്തി ഒട്ടിക്കുക." + }, + "loggedOut": { + "message": "ലോഗേഡ് ഔട്ട്" + }, + "loginExpired": { + "message": "നിങ്ങളുടെ പ്രവർത്തന സമയം കഴിഞ്ഞിരിക്കുന്നു." + }, + "logOutConfirmation": { + "message": "നിങ്ങൾക്ക് ലോഗ് ഔട്ട് ചെയ്യണമെന്ന് ഉറപ്പാണോ?" + }, + "yes": { + "message": "ശരി" + }, + "no": { + "message": "തെറ്റ്" + }, + "unexpectedError": { + "message": "ഒരു അപ്രതീക്ഷിത പിശക് സംഭവിച്ചു." + }, + "nameRequired": { + "message": "പേര് നിർബന്ധമാണ്‌." + }, + "addedFolder": { + "message": "ചേർക്കപ്പെട്ട ഫോൾഡർ" + }, + "changeMasterPass": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് മാറ്റുക" + }, + "changeMasterPasswordConfirmation": { + "message": "തങ്ങൾക്കു ബിറ്റ് വാർഡൻ വെബ് വാൾട്ടിൽ പ്രാഥമിക പാസ്‌വേഡ് മാറ്റാൻ സാധിക്കും.വെബ്സൈറ്റ് ഇപ്പോൾ സന്ദർശിക്കാൻ ആഗ്രഹിക്കുന്നുവോ?" + }, + "twoStepLoginConfirmation": { + "message": "സുരക്ഷാ കീ, ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷൻ, SMS, ഫോൺ കോൾ അല്ലെങ്കിൽ ഇമെയിൽ പോലുള്ള മറ്റൊരു ഉപകരണം ഉപയോഗിച്ച് തങ്ങളുടെ ലോഗിൻ സ്ഥിരീകരിക്കാൻ ആവശ്യപ്പെടുന്നതിലൂടെ രണ്ട്-ഘട്ട ലോഗിൻ തങ്ങളുടെ അക്കൗണ്ടിനെ കൂടുതൽ സുരക്ഷിതമാക്കുന്നു. bitwarden.com വെബ് വാൾട്ടിൽ രണ്ട്-ഘട്ട ലോഗിൻ പ്രവർത്തനക്ഷമമാക്കാനാകും.തങ്ങള്ക്കു ഇപ്പോൾ വെബ്സൈറ്റ് സന്ദർശിക്കാൻ ആഗ്രഹമുണ്ടോ?" + }, + "editedFolder": { + "message": "തിരുത്തിയ ഫോൾഡർ" + }, + "deleteFolderConfirmation": { + "message": "ഈ ഫോൾഡർ ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "deletedFolder": { + "message": "ഇല്ലാതാക്കിയ ഫോൾഡർ" + }, + "gettingStartedTutorial": { + "message": "എക്സ്റ്റൻഷൻ ഉപയോഗിയ്ക്കാൻ പരിചയപ്പെടുക" + }, + "gettingStartedTutorialVideo": { + "message": "ബ്രൗസർ എക്സ്റ്റൻഷൻ എങ്ങനെ പരമാവധി പ്രയോജനപ്പെടുത്താമെന്ന് മനസിലാക്കാൻ ഞങ്ങളുടെ ആരംഭ ട്യൂട്ടോറിയൽ കാണുക." + }, + "syncingComplete": { + "message": "സിങ്ക് പൂർത്തിയായി" + }, + "syncingFailed": { + "message": "സിങ്ക് ചെയ്യാൻ പരാജയപെട്ടു" + }, + "passwordCopied": { + "message": "പാസ്സ്‌വേഡ്‌ പകർത്തി" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "പുതിയ URI" + }, + "addedItem": { + "message": "ചേർക്കപ്പെട്ട ഇനം" + }, + "editedItem": { + "message": "തിരുത്തപ്പെട്ട ഇനം" + }, + "deleteItemConfirmation": { + "message": "ഈ ഇനം ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "deletedItem": { + "message": "ഇനം ട്രാഷിലേക്ക് അയച്ചു" + }, + "overwritePassword": { + "message": "പാസ്‌വേഡ് പുനരാലേഖനം ചെയ്യുക" + }, + "overwritePasswordConfirmation": { + "message": "നിലവിലെ പാസ്‌വേഡ് പുനരാലേഖനം ചെയ്യണമെന്ന് നിങ്ങൾക്ക് ഉറപ്പാണോ?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "ഫോൾഡറുകൾ തിരയുക" + }, + "searchCollection": { + "message": "കളക്ഷൻസ് തിരയുക " + }, + "searchType": { + "message": "തരം തിരയുന്നു" + }, + "noneFolder": { + "message": "ഫോൾഡറിൽ ഉൾപ്പെടാത്ത", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "പ്രവേശനം ചേർക്കുക എന്ന അറിയിപ്പ് പ്രവർത്തനരഹിതമാക്കുക" + }, + "addLoginNotificationDesc": { + "message": "നിങ്ങൾ ആദ്യമായി സൈറ്റിൽ പ്രവേശിക്കുമ്പോൾ നിങ്ങളുടെ വാൾട്ടിലേക്കു തനിയെ പ്രവേശനം ഉൾപെടുത്താൻ \"പ്രവേശനം ചേർക്കുക എന്ന അറിയിപ്പ്\" ആവശ്യപ്പെടും." + }, + "dontShowCardsCurrentTab": { + "message": "ടാബ് പേജിൽ കാർഡുകൾ കാണിക്കരുത്" + }, + "dontShowCardsCurrentTabDesc": { + "message": "സ്വപ്രേരിതമായി പൂരിപ്പിക്കുന്നതിന് നിങ്ങളുടെ നിലവറയിൽ നിന്നുള്ള കാർഡ് ഇനങ്ങൾ 'നിലവിലെ ടാബ്' പേജിൽ പട്ടികപ്പെടുത്തിയിട്ടുണ്ട്." + }, + "dontShowIdentitiesCurrentTab": { + "message": "ടാബ് പേജിൽ ഐഡന്റിറ്റികൾ കാണിക്കരുത്" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "സ്വയമേവ എളുപ്പത്തിൽ പൂരിപ്പിക്കുന്നതിന് നിങ്ങളുടെ നിലവറയിൽ നിന്നുള്ള ഐഡന്റിറ്റി ഇനങ്ങൾ 'നിലവിലെ ടാബ്' പേജിൽ പട്ടികപ്പെടുത്തിയിട്ടുണ്ട്." + }, + "clearClipboard": { + "message": "ക്ലിപ്ബോര്‍ഡ് മായ്ക്കുക", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "നിങ്ങളുടെ ക്ലിപ്പ്ബോർഡിൽ നിന്ന് പകർത്തിയ മൂല്യങ്ങൾ യാന്ത്രികമായി മായ്‌ക്കുക.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "നിങ്ങൾ‌ക്കായി ഈ പാസ്‌വേഡ് ബിറ്റ്‌വർ‌ഡൻ‌ ഓർത്തിരിക്കണോ?" + }, + "notificationAddSave": { + "message": "ശരി, ഇപ്പോൾ സംരക്ഷിക്കുക" + }, + "disableChangedPasswordNotification": { + "message": "മാറ്റിയ പാസ്‌വേഡ് അറിയിപ്പ് പ്രവർത്തനരഹിതമാക്കുക" + }, + "disableChangedPasswordNotificationDesc": { + "message": "ഒരു വെബ്‌സൈറ്റിൽ നിങ്ങൾ അത് മാറ്റിയതായി കണ്ടെത്തുമ്പോഴെല്ലാം നിങ്ങളുടെ നിലവറയിൽ ഒരു ലോഗിൻ പാസ്‌വേഡ് അപ്‌ഡേറ്റുചെയ്യാൻ \"മാറ്റിയ പാസ്‌വേഡ് അറിയിപ്പ്\" യാന്ത്രികമായി ആവശ്യപ്പെടുന്നു." + }, + "notificationChangeDesc": { + "message": "ബിറ്റ്വാർഡനിൽ ഈ പാസ്‌വേഡ് അപ്‌ഡേറ്റ് ചെയ്യാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "notificationChangeSave": { + "message": "ശരി, ഇപ്പോൾ അപ്ഡേറ്റ് ചെയ്യുക" + }, + "disableContextMenuItem": { + "message": "സന്ദർഭ മെനു ഓപ്ഷനുകൾ അപ്രാപ്തമാക്കുക" + }, + "disableContextMenuItemDesc": { + "message": "നിങ്ങളുടെ നിലവിലെ ടാബിലെ വെബ്‌സൈറ്റിനായുള്ള പാസ്‌വേഡ് ജനറേഷനിലേക്കും ലോഗിനുകളിലേക്കും സന്ദർഭ മെനു ഓപ്ഷനുകൾ ദ്രുത പ്രവേശനം നൽകുന്നു." + }, + "defaultUriMatchDetection": { + "message": "സാധാരണ URI പൊരുത്തം കണ്ടെത്തൽ", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "യാന്ത്രിക പൂരിപ്പിക്കൽ പോലുള്ള പ്രവർത്തനങ്ങൾ നടത്തുമ്പോൾ ലോഗിനുകൾക്കായി യുആർഐ മാച്ച് ഡിറ്റക്ഷൻ കൈകാര്യം ചെയ്യുന്ന സ്ഥിരസ്ഥിതി മാർഗം തിരഞ്ഞെടുക്കുക." + }, + "theme": { + "message": "തീം" + }, + "themeDesc": { + "message": "അപ്ലിക്കേഷന്റെ തീമും വർണ്ണങ്ങളും മാറ്റുക." + }, + "dark": { + "message": "ഇരുണ്ടത്", + "description": "Dark color" + }, + "light": { + "message": "ലൈറ്റ്", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "വാൾട് എക്സ്പോർട്" + }, + "fileFormat": { + "message": "ഫയൽ ഫോർമാറ്റ്" + }, + "warning": { + "message": "മുന്നറിയിപ്പ്", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "ഈ എക്‌സ്‌പോർട്ടിൽ എൻക്രിപ്റ്റ് ചെയ്യാത്ത ഫോർമാറ്റിൽ നിങ്ങളുടെ വാൾട് ഡാറ്റ അടങ്ങിയിരിക്കുന്നു. എക്‌സ്‌പോർട് ചെയ്ത ഫയൽ സുരക്ഷിതമല്ലാത്ത ചാനലുകളിൽ (ഇമെയിൽ പോലുള്ളവ) നിങ്ങൾ സംഭരിക്കുകയോ അയയ്ക്കുകയോ ചെയ്യരുത്. നിങ്ങൾ ഇത് ഉപയോഗിച്ചുകഴിഞ്ഞാലുടൻ അത് മായ്ച്ചുകളയണം." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "നിങ്ങളുടെ വാൾട് ഡാറ്റ എക്‌സ്‌പോർട്ടുചെയ്യാൻ പ്രാഥമിക പാസ്‌വേഡ് നൽകുക." + }, + "shared": { + "message": "പങ്കിട്ടവ" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "പങ്കിടുക" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "കൂടുതലറിവ് നേടുക" + }, + "authenticatorKeyTotp": { + "message": "ഓതന്റിക്കേറ്റർ കീ (TOTP)" + }, + "verificationCodeTotp": { + "message": "സ്ഥിരീകരണ കോഡ് (TOTP)" + }, + "copyVerificationCode": { + "message": "സ്ഥിരീകരണ കോഡ് പകർത്തുക " + }, + "attachments": { + "message": "അറ്റാച്ചുമെന്റുകൾ" + }, + "deleteAttachment": { + "message": "അറ്റാച്ചുമെന്റ് ഇല്ലാതാക്കുക" + }, + "deleteAttachmentConfirmation": { + "message": "ഈ അറ്റാച്ചുമെന്റ് ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "deletedAttachment": { + "message": "മായ്ച്ച അറ്റാച്ചുമെന്റ്" + }, + "newAttachment": { + "message": "പുതിയ അറ്റാച്ചുമെന്റ് ചേർക്കുക" + }, + "noAttachments": { + "message": "അറ്റാച്ചുമെന്റുകൾ ഇല്ല." + }, + "attachmentSaved": { + "message": "അറ്റാച്ചുമെന്റ് സംരക്ഷിച്ചു." + }, + "file": { + "message": "ഫയൽ" + }, + "selectFile": { + "message": "ഒരു ഫയൽ തിരഞ്ഞെടുക്കുക" + }, + "maxFileSize": { + "message": "പരമാവധി ഫയൽ വലുപ്പം 500 MB ആണ്." + }, + "featureUnavailable": { + "message": "സവിശേഷത ലഭ്യമല്ല" + }, + "updateKey": { + "message": "നിങ്ങളുടെ എൻ‌ക്രിപ്ഷൻ കീ അപ്‌ഡേറ്റ് ചെയ്യുന്നതുവരെ നിങ്ങൾക്ക് ഈ സവിശേഷത ഉപയോഗിക്കാൻ കഴിയില്ല." + }, + "premiumMembership": { + "message": "പ്രീമിയം അംഗത്വം" + }, + "premiumManage": { + "message": "അംഗത്വം നിയന്ത്രിക്കുക" + }, + "premiumManageAlert": { + "message": "നിങ്ങളുടെ അംഗത്വം bitwarden.com വെബ് വാൾട്ടിൽ മാനേജുചെയ്യാൻ കഴിയും. തങ്ങൾക്ക് ഇപ്പോൾ വെബ്സൈറ്റ് സന്ദർശിക്കാൻ ആഗ്രഹമുണ്ടോ?" + }, + "premiumRefresh": { + "message": "അംഗത്വം റിഫ്രഷ് ചെയ്യുക" + }, + "premiumNotCurrentMember": { + "message": "നിങ്ങൾ നിലവിൽ ഒരു പ്രീമിയം അംഗമല്ല." + }, + "premiumSignUpAndGet": { + "message": "ഒരു പ്രീമിയം അംഗത്വത്തിനായി സൈൻ അപ്പ് ചെയ്ത് നേടുക:" + }, + "ppremiumSignUpStorage": { + "message": "ഫയൽ അറ്റാച്ചുമെന്റുകൾക്കായി 1 ജിബി എൻക്രിപ്റ്റുചെയ്‌ത സംഭരണം." + }, + "ppremiumSignUpTwoStep": { + "message": "രണ്ട്-ഘട്ട പ്രവേശന ഓപ്ഷനുകളായ Yubikey, FIDO U2F, Duo." + }, + "ppremiumSignUpReports": { + "message": "നിങ്ങളുടെ വാൾട് സൂക്ഷിക്കുന്നതിന്. പാസ്‌വേഡ് ശുചിത്വം, അക്കൗണ്ട് ആരോഗ്യം, ഡാറ്റ ലംഘന റിപ്പോർട്ടുകൾ." + }, + "ppremiumSignUpTotp": { + "message": "നിങ്ങളുടെ വാൾട്ടിലെ പ്രവേശനങ്ങൾക്കായി TOTP പരിശോധന കോഡ് (2FA) സൃഷ്ടാവ്." + }, + "ppremiumSignUpSupport": { + "message": "മുൻ‌ഗണന ഉപഭോക്തൃ പിന്തുണ." + }, + "ppremiumSignUpFuture": { + "message": "ഭാവിയിലെ എല്ലാ പ്രീമിയം സവിശേഷതകളും. കൂടുതൽ ഉടനെ വരുന്നു !" + }, + "premiumPurchase": { + "message": "പ്രീമിയം വാങ്ങുക" + }, + "premiumPurchaseAlert": { + "message": "നിങ്ങൾക്ക് bitwarden.com വെബ് വാൾട്ടിൽ പ്രീമിയം അംഗത്വം വാങ്ങാം. നിങ്ങൾക്ക് ഇപ്പോൾ വെബ്സൈറ്റ് സന്ദർശിക്കാൻ ആഗ്രഹമുണ്ടോ?" + }, + "premiumCurrentMember": { + "message": "തങ്ങൾ ഒരു പ്രീമിയം അംഗമാണ്!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwardenനെ പിന്തുണച്ചതിന് നന്ദി." + }, + "premiumPrice": { + "message": "എല്ലാം വെറും $PRICE$/ വർഷത്തേക്ക്!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "റിഫ്രഷ് പൂർത്തിയായി" + }, + "disableAutoTotpCopy": { + "message": "ഓട്ടോമാറ്റിക് TOTP പകർപ്പ് പ്രവർത്തനരഹിതമാക്കുക" + }, + "disableAutoTotpCopyDesc": { + "message": "നിങ്ങളുടെ പ്രവേശനം ഒരു ഓതന്റിക്കേറ്റർ കീയുമായി ബന്ധപെടുത്തിയട്ടുടെങ്കിൽ, പ്രവേശനം ഓട്ടോഫിൽ ചെയ്യുമ്പോഴെല്ലാം TOTP സ്ഥിരീകരണ കോഡ് നിങ്ങളുടെ ക്ലിപ്ബോർഡിൽ ഓട്ടോമാറ്റിക്കയായി പകർത്തപ്പെടും." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "പ്രീമിയം അംഗത്വം ആവശ്യമാണ്" + }, + "premiumRequiredDesc": { + "message": "ഈ സവിശേഷത ഉപയോഗിക്കുന്നതിന് പ്രീമിയം അംഗത്വം ആവശ്യമാണ്." + }, + "enterVerificationCodeApp": { + "message": "നിങ്ങളുടെ ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷനിൽ നിന്ന് 6 അക്ക സ്ഥിരീകരണ കോഡ് നൽകുക." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ൽ ഇമെയിൽ ചെയ്ത 6 അക്ക സ്ഥിരീകരണ കോഡ് നൽകുക", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "സ്ഥിരീകരണ ഇമെയിൽ $EMAIL$ ലേക്ക് അയച്ചു.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "എന്നെ ഓർക്കുക" + }, + "sendVerificationCodeEmailAgain": { + "message": "സ്ഥിരീകരണ കോഡ് ഇമെയിൽ വഴി അയയ്ക്കുക" + }, + "useAnotherTwoStepMethod": { + "message": "മറ്റൊരു രണ്ട് ഘട്ട ലോഗിൻ രീതി ഉപയോഗിക്കുക" + }, + "insertYubiKey": { + "message": "നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ യു‌എസ്‌ബി പോർട്ടിലേക്ക് യുബിക്കി ഇടുക, തുടർന്ന് അതിന്റെ ബട്ടൺ അമർത്തുക." + }, + "insertU2f": { + "message": "നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ യുഎസ്ബി പോർട്ടിൽ സുരക്ഷാ കീ ഇടുക. അതിന് ഒരു ബട്ടൺ ഉണ്ടെങ്കിൽ അത് അമർത്തുക." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "പ്രവേശനം ലഭ്യമല്ല" + }, + "noTwoStepProviders": { + "message": "ഈ അക്കൗണ്ടിന് രണ്ട്-ഘട്ട പ്രവേശനം പ്രാപ്തമാക്കിയിട്ടുണ്ട്, എന്നിരുന്നാലും, ക്രമീകരിച്ച രണ്ട്-ഘട്ട ദാതാക്കളെയൊന്നും ഈ ഉപകരണം പിന്തുണയ്ക്കുന്നില്ല." + }, + "noTwoStepProviders2": { + "message": "മികച്ച പിന്തുണയുള്ള, കൂടുതൽ ദാതാക്കളെ ദയവായി ചേർക്കുക (ഒരു ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷൻ പോലുള്ളവ)." + }, + "twoStepOptions": { + "message": "രണ്ട്-ഘട്ട പ്രവേശനം ഓപ്ഷനുകൾ" + }, + "recoveryCodeDesc": { + "message": "നിങ്ങളുടെ രണ്ട്-ഘടക ദാതാക്കളിലേക്കുള്ള ആക്‌സസ്സ് നഷ്‌ടപ്പെട്ടോ? നിങ്ങളുടെ അക്കൗണ്ടിൽ നിന്ന് രണ്ട്-ഘടക ദാതാക്കളെ പ്രവർത്തനരഹിതമാക്കാൻ നിങ്ങളുടെ റിക്കവറി കോഡ് ഉപയോഗിക്കുക." + }, + "recoveryCodeTitle": { + "message": "റിക്കവറി കോഡ്" + }, + "authenticatorAppTitle": { + "message": "ഓതന്റിക്കേറ്റർ ആപ്പ്" + }, + "authenticatorAppDesc": { + "message": "സമയ-അടിസ്ഥാന പരിശോധന കോഡുകൾ സൃഷ്ടിക്കുന്നതിന് ഒരു ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷൻ (ഓത്തി അല്ലെങ്കിൽ Google ഓതന്റിക്കേറ്റർ പോലുള്ളവ) ഉപയോഗിക്കുക.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP സുരക്ഷാ കീ" + }, + "yubiKeyDesc": { + "message": "നിങ്ങളുടെ അക്കൗണ്ട് ആക്സസ് ചെയ്യുന്നതിന് ഒരു യൂബിക്കി ഉപയോഗിക്കുക. YubiKey 4, 4 Nano, 4C, NEO ഉപകരണങ്ങളിൽ പ്രവർത്തിക്കുന്നു." + }, + "duoDesc": { + "message": "Duo Mobile അപ്ലിക്കേഷൻ, എസ്എംഎസ്, ഫോൺ കോൾ അല്ലെങ്കിൽ യു 2 എഫ് സുരക്ഷാ കീ ഉപയോഗിച്ച് Duoസെക്യൂരിറ്റി ഉപയോഗിച്ച് പരിശോധിക്കുക.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo Mobile, എസ്എംഎസ്, ഫോൺ കോൾ അല്ലെങ്കിൽ യു 2 എഫ് സുരക്ഷാ കീ ഉപയോഗിച്ച് നിങ്ങളുടെ ഓർഗനൈസേഷനെ ഡ്യുവോ സെക്യൂരിറ്റി ഉപയോഗിച്ച് പരിശോധിക്കുക.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "ഇമെയിൽ" + }, + "emailDesc": { + "message": "സ്ഥിരീകരണ കോഡുകൾ നിങ്ങൾക്ക് ഇമെയിൽ ചെയ്യും." + }, + "selfHostedEnvironment": { + "message": "സ്വയം ഹോസ്റ്റുചെയ്‌ത എൻവിയോണ്മെന്റ്" + }, + "selfHostedEnvironmentFooter": { + "message": "തങ്ങളുടെ പരിസരത്ത് ചെയ്യുന്ന ബിറ്റ് വാർഡൻ ഇൻസ്റ്റാളേഷന്റെ അടിസ്ഥാന URL വ്യക്തമാക്കുക." + }, + "customEnvironment": { + "message": "ഇഷ്‌ടാനുസൃത എൻവിയോണ്മെന്റ്" + }, + "customEnvironmentFooter": { + "message": "വിപുലമായ ഉപയോക്താക്കൾക്കായി. ഓരോ സേവനത്തിന്റെയും അടിസ്ഥാന URL നിങ്ങൾക്ക് സ്വതന്ത്രമായി വ്യക്തമാക്കാൻ കഴിയും." + }, + "baseUrl": { + "message": "സെർവർ URL" + }, + "apiUrl": { + "message": "API സെർവർ URL" + }, + "webVaultUrl": { + "message": "വെബ് വാൾട് സെർവർ URL" + }, + "identityUrl": { + "message": "ഐഡന്റിറ്റി സെർവർ URL" + }, + "notificationsUrl": { + "message": "API സെർവർ URL" + }, + "iconsUrl": { + "message": "ഐക്കണുകളുടെ സെർവർ URL" + }, + "environmentSaved": { + "message": "എന്വിയാണമെന്റ് URL സംരക്ഷിച്ചു." + }, + "enableAutoFillOnPageLoad": { + "message": "പേജ് ലോഡിൽ യാന്ത്രിക-പൂരിപ്പിക്കൽ പ്രവർത്തനക്ഷമമാക്കുക" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "ഒരു ലോഗിൻ ഫോം കണ്ടെത്തിയാൽ, വെബ് പേജ് ലോഡുചെയ്യുമ്പോൾ യാന്ത്രികമായി ഒരു സ്വയം പൂരിപ്പിക്കൽ നടത്തുക." + }, + "experimentalFeature": { + "message": "ഇത് നിലവിൽ ഒരു പരീക്ഷണാത്മക സവിശേഷതയാണ്. നിങ്ങളുടെ സ്വന്തം ഉത്തരവാദിത്വത്തിൽ ഉപയോഗിക്കുക." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "വോൾട്ട് പോപ്പ്അപ്പ് തുറക്കുക" + }, + "commandOpenSidebar": { + "message": "വാൾട് സൈഡ്ബാറിൽ തുറക്കുക" + }, + "commandAutofillDesc": { + "message": "നിലവിലെ വെബ്‌സൈറ്റിനായി അവസാനമായി ഉപയോഗിച്ച ലോഗിൻ യാന്ത്രികമായി പൂരിപ്പിക്കുക" + }, + "commandGeneratePasswordDesc": { + "message": "ക്ലിപ്പ്ബോർഡിലേക്ക് ഒരു പുതിയ റാൻഡം പാസ്‌വേഡ് സൃഷ്ടിച്ച് പകർത്തുക" + }, + "commandLockVaultDesc": { + "message": "നിലവറ പൂട്ടുക" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "ഇഷ്‌ടാനുസൃത ഫീൽഡുകൾ" + }, + "copyValue": { + "message": "മൂല്യം പകർത്തുക" + }, + "value": { + "message": "മൂല്യം" + }, + "newCustomField": { + "message": "പുതിയ ഇഷ്‌ടാനുസൃത ഫീൽഡ്" + }, + "dragToSort": { + "message": "അടുക്കാൻ വലിച്ചിടുക" + }, + "cfTypeText": { + "message": "വാചകം" + }, + "cfTypeHidden": { + "message": "മറച്ചത്" + }, + "cfTypeBoolean": { + "message": "ബൂളിയൻ" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "നിങ്ങളുടെ സ്ഥിരീകരണ കോഡിനായി നിങ്ങളുടെ ഇമെയിൽ പരിശോധിക്കുന്നതിന് പോപ്പ്അപ്പ് വിൻഡോയ്ക്ക് പുറത്ത് ക്ലിക്കുചെയ്യുന്നത് ഈ പോപ്പ്അപ്പ് അടയ്‌ക്കുന്നതിന് കാരണമാകും. ഈ പോപ്പ്അപ്പ് അടയ്‌ക്കാത്തവിധം ഒരു പുതിയ വിൻ‌ഡോയിൽ‌ തുറക്കാൻ‌ നിങ്ങൾ‌ താൽ‌പ്പര്യപ്പെടുന്നോ?" + }, + "popupU2fCloseMessage": { + "message": "ഈ ബ്ര pop സറിന് ഈ പോപ്പ്അപ്പ് വിൻഡോയിൽ U2F അഭ്യർത്ഥനകൾ പ്രോസസ്സ് ചെയ്യാൻ കഴിയില്ല. യു 2 എഫ് ഉപയോഗിച്ച് ലോഗിൻ ചെയ്യാൻ ഈ പോപ്പ്അപ്പ് ഒരു പുതിയ വിൻഡോയിൽ തുറക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "disableFavicon": { + "message": "വെബ്‌സൈറ്റ് ഐക്കണുകൾ പ്രവർത്തനരഹിതമാക്കുക" + }, + "disableFaviconDesc": { + "message": "വെബ്സൈറ്റ് ഐക്കണുകൾ തങ്ങളുടെ വാൾട്ടിലെ ലോഗിൻ ഇന്നതിന്റ്റെ അടുത്തായി തിരിച്ചറിയുന്ന ഒരു ചിത്രം ഉൾപ്പെടുത്തുന്നു." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "കാർഡ് ഉടമയുടെ പേര്" + }, + "number": { + "message": "നമ്പർ" + }, + "brand": { + "message": "ബ്രാൻഡ്" + }, + "expirationMonth": { + "message": "കാലാവതി കഴിയുന്ന മാസം" + }, + "expirationYear": { + "message": "കാലാവതി കഴിയുന്ന വർഷം" + }, + "expiration": { + "message": "കാലഹരണപ്പെടൽ" + }, + "january": { + "message": "ജനുവരി" + }, + "february": { + "message": "ഫെബ്രുവരി" + }, + "march": { + "message": "മാർച്ച്‌" + }, + "april": { + "message": "ഏപ്രിൽ" + }, + "may": { + "message": "മെയ്‌" + }, + "june": { + "message": "ജൂണ്‍" + }, + "july": { + "message": "ജൂലൈ" + }, + "august": { + "message": "ഓഗസ്റ്റ്" + }, + "september": { + "message": "സെപ്റ്റംബർ" + }, + "october": { + "message": "ഒക്ടോബര്‍" + }, + "november": { + "message": "നവംബർ" + }, + "december": { + "message": "ഡിസംബർ" + }, + "securityCode": { + "message": "സുരക്ഷാ കോഡ്" + }, + "ex": { + "message": "ഉദാഹരണം." + }, + "title": { + "message": "ശീർഷകം" + }, + "mr": { + "message": "ശ്രീ" + }, + "mrs": { + "message": "ശ്രിമതി" + }, + "ms": { + "message": "കുമാരി" + }, + "dr": { + "message": "ഡോ" + }, + "firstName": { + "message": "പേരിന്റെ ആദ്യഭാഗം" + }, + "middleName": { + "message": "മധ്യ നാമം" + }, + "lastName": { + "message": "പേരിന്റെ അവസാന ഭാഗം" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "ഐഡന്റിറ്റിയുടെ പേര്" + }, + "company": { + "message": "കമ്പനി" + }, + "ssn": { + "message": "സാമൂഹിക സുരക്ഷാ നമ്പർ" + }, + "passportNumber": { + "message": "പാസ്പോർട്ട് നമ്പർ" + }, + "licenseNumber": { + "message": "ലൈസൻസ് നമ്പർ" + }, + "email": { + "message": "ഇമെയിൽ" + }, + "phone": { + "message": "ഫോൺ" + }, + "address": { + "message": "മേൽവിലാസം" + }, + "address1": { + "message": "മേൽവിലാസം 1" + }, + "address2": { + "message": "മേൽവിലാസം 2" + }, + "address3": { + "message": "മേൽവിലാസം 3" + }, + "cityTown": { + "message": "നഗരം / പട്ടണം" + }, + "stateProvince": { + "message": "സംസ്ഥാനം/ ദേശം" + }, + "zipPostalCode": { + "message": "പിൻകോഡ്" + }, + "country": { + "message": "രാജ്യം" + }, + "type": { + "message": "തരം" + }, + "typeLogin": { + "message": "പ്രവേശനം" + }, + "typeLogins": { + "message": "പ്രവേശനങ്ങൾ" + }, + "typeSecureNote": { + "message": "സുരക്ഷിത കുറിപ്പ്" + }, + "typeCard": { + "message": "കാർഡ്" + }, + "typeIdentity": { + "message": "ഐഡന്റിറ്റി" + }, + "passwordHistory": { + "message": "പാസ്സ്‌വേഡ് നാൾവഴി" + }, + "back": { + "message": "പുറകോട്ട്" + }, + "collections": { + "message": "കളക്ഷൻസ്" + }, + "favorites": { + "message": "പ്രിയങ്കരങ്ങള്‍" + }, + "popOutNewWindow": { + "message": "ഒരു പുതിയ വിൻ‌ഡോയിലേക്ക് പോപ്പ് out ട്ട് ചെയ്യുക" + }, + "refresh": { + "message": "റിഫ്രഷ് ചെയ്യുക" + }, + "cards": { + "message": "കാർഡുകൾ" + }, + "identities": { + "message": "തിരിച്ചറിയലുകൾ" + }, + "logins": { + "message": "പ്രവേശനങ്ങൾ" + }, + "secureNotes": { + "message": "സുരക്ഷാ കുറിപ്പുകൾ" + }, + "clear": { + "message": "മായ്ക്കുക", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "പാസ്സ്‌വേർഡ് ചോർന്നോ എന്ന് നോക്കുക." + }, + "passwordExposed": { + "message": "ഈ പാസ്‌വേഡ് $VALUE$ ലംഘനങ്ങളിൽ ചോർന്നു. തങ്ങൾ ഇത് മാറ്റണം.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "അറിയപ്പെടുന്ന ഡാറ്റാ ലംഘനങ്ങളിൽ ഈ പാസ്‌വേഡ് കണ്ടെത്തിയില്ല. ഇത് ഉപയോഗിക്കുന്നത് സുരക്ഷിതമായിരിക്കും." + }, + "baseDomain": { + "message": "അടിസ്ഥാന ഡൊമെയ്ൻ", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "ഹോസ്റ്റ്", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "കൃത്യമായി" + }, + "startsWith": { + "message": "തുടങ്ങുന്നത്" + }, + "regEx": { + "message": "പതിവ് പദപ്രയോഗം", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "പൊരുത്തം കണ്ടെത്തൽ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "സ്ഥിരസ്ഥിതി പൊരുത്ത കണ്ടെത്തൽ", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "ഓപ്ഷനുകൾ ടോഗിൾ ചെയ്യുക" + }, + "toggleCurrentUris": { + "message": "നിലവിലെ URIകൾ ടോഗിൾ ചെയ്യുക", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "നിലവിലെ URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "സംഘടന", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "തരങ്ങൾ" + }, + "allItems": { + "message": "എല്ലാ ഇനങ്ങൾ" + }, + "noPasswordsInList": { + "message": "പ്രദർശിപ്പിക്കാൻ പാസ്സ്‌വേഡുകൾ ഒന്നും ഇല്ല." + }, + "remove": { + "message": "നീക്കുക" + }, + "default": { + "message": "സ്ഥിരസ്ഥിതി" + }, + "dateUpdated": { + "message": "പുതുക്കി", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "പാസ്സ്‌വേഡ് പുതുക്കി", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "\"ഒരിക്കലും\" ഓപ്ഷൻ ഉപയോഗിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ? നിങ്ങളുടെ ലോക്ക് ഓപ്ഷനുകൾ \"ഒരിക്കലും\" എന്ന് സജ്ജമാക്കുന്നത് നിങ്ങളുടെ ഉപകരണത്തിൽ നിലവറയുടെ എൻക്രിപ്ഷൻ കീ സംഭരിക്കുന്നു. നിങ്ങൾ ഈ ഓപ്‌ഷൻ ഉപയോഗിക്കുകയാണെങ്കിൽ, നിങ്ങളുടെ ഉപകരണം ശരിയായി പരിരക്ഷിച്ചിട്ടുണ്ടെന്ന് ഉറപ്പാക്കണം." + }, + "noOrganizationsList": { + "message": "താങ്കൾ ഒരു സംഘടനയുടെയും അംഗമല്ല. മറ്റ് ഉപയോക്താക്കളുമായി ഇനങ്ങൾ സുരക്ഷിതമായി പങ്കിടാൻ ഓർഗനൈസേഷനുകൾ നിങ്ങളെ അനുവദിക്കുന്നു." + }, + "noCollectionsInList": { + "message": "പ്രദർശിപ്പിക്കാൻ കളക്ഷൻസ് ഒന്നും ഇല്ല." + }, + "ownership": { + "message": "ഉടമസ്ഥാവകാശം" + }, + "whoOwnsThisItem": { + "message": "ഈ ഇനം ആരുടേതാണ്?" + }, + "strong": { + "message": "ശക്തമാണ്", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "നല്ലതാണ്", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "ദുർബലമാണ്", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "ദുർബലമായ പ്രാഥമിക പാസ്‌വേഡ്" + }, + "weakMasterPasswordDesc": { + "message": "നിങ്ങൾ തിരഞ്ഞെടുത്ത പ്രാഥമിക പാസ്‌വേഡ് ദുർബലമാണ്. നിങ്ങളുടെ Bitwarden അക്കൗണ്ട് ശരിയായി സുരക്ഷിതമാക്കാൻ നിങ്ങൾ ഒരു ശക്തമായ മാസ്റ്റർ പാസ്‌വേഡ് (അല്ലെങ്കിൽ ഒരു പാസ്‌ഫ്രേസ്) ഉപയോഗിക്കണം. ഈ മാസ്റ്റർ പാസ്‌വേഡ് ഉപയോഗിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "pin": { + "message": "പിൻ", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "പിൻ ഉപയോഗിച്ച് അൺലോക്കുചെയ്യുക" + }, + "setYourPinCode": { + "message": "Bitwarden അൺലോക്കുചെയ്യുന്നതിന് തങ്ങളുടെ പിൻ കോഡ് സജ്ജമാക്കുക. തങ്ങൾ എപ്പോഴെങ്കിലും അപ്ലിക്കേഷനിൽ നിന്ന് പൂർണ്ണമായി ലോഗ് ഔട്ട് ചെയ്യുകയാണെങ്കിൽ, പിൻ ക്രമീകരണങ്ങൾ പുനസജ്ജമാക്കും." + }, + "pinRequired": { + "message": "പിൻ കോഡ് നിർബന്ധമാണ്." + }, + "invalidPin": { + "message": " പിൻ കോഡ് അസാധുവാണ്." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "ബ്രൌസർ പുനരാരംഭത്തിൽ പ്രാഥമിക പാസ്‌വേഡ് ഉപയോഗിച്ച് ലോക്ക് ചെയ്യുക" + }, + "selectOneCollection": { + "message": "നിങ്ങൾ ഒരു കളക്ഷനെങ്കിലും തിരഞ്ഞെടുക്കണം." + }, + "cloneItem": { + "message": "ഇനം ക്ലോൺ ചെയ്യുക" + }, + "clone": { + "message": "ക്ലോൺ" + }, + "passwordGeneratorPolicyInEffect": { + "message": "ഒന്നോ അതിലധികമോ സംഘടന നയങ്ങൾ നിങ്ങളുടെ പാസ്സ്‌വേഡ് സൃഷ്ടാവിൻ്റെ ക്രമീകരണങ്ങളെ ബാധിക്കുന്നു" + }, + "vaultTimeoutAction": { + "message": "വാൾട് ടൈം ഔട്ട് ആക്ഷൻ" + }, + "lock": { + "message": "പൂട്ടുക", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "ട്രാഷ്", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "ട്രാഷ് തിരയുന്നു" + }, + "permanentlyDeleteItem": { + "message": "ഇനം ശാശ്വതമായി ഇല്ലാതാക്കുക" + }, + "permanentlyDeleteItemConfirmation": { + "message": "ഈ ഇനം ശാശ്വതമായി ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "permanentlyDeletedItem": { + "message": "ശാശ്വതമായി ഇല്ലാതാക്കിയ ഇനം" + }, + "restoreItem": { + "message": "ഇനം വീണ്ടെടുക്കുക " + }, + "restoreItemConfirmation": { + "message": "ഈ ഇനം വീണ്ടെടുക്കണമെന്ന് ഉറപ്പാണോ?" + }, + "restoredItem": { + "message": "വീണ്ടെടുത്ത ഇനം" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "ലോഗൗട്ട് ചെയ്യുകയാണെങ്കിൽ തങ്ങളുടെ വാൾട്ടിലേക്കുള്ള എല്ലാ ആക്സസും നീക്കംചെയ്യും. കാലയളവിനുശേഷം ഓൺലൈൻ ഓതന്റിക്കേറ്റർ ആവശ്യമാണ്. ഈ ക്രമീകരണം ഉപയോഗിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "ടൈംഔട് ആക്ഷൻ സ്ഥിരീകരണം" + }, + "autoFillAndSave": { + "message": "യാന്ത്രികമായി പൂരിപ്പിച്ച് സംരക്ഷിക്കുക" + }, + "autoFillSuccessAndSavedUri": { + "message": "യാന്ത്രികമായി പൂരിപ്പിച്ച ഇനവും സംരക്ഷിച്ച URI" + }, + "autoFillSuccess": { + "message": "യാന്ത്രികമായി പൂരിപ്പിച്ച ഇനം" + }, + "setMasterPassword": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സജ്ജമാക്കുക" + }, + "masterPasswordPolicyInEffect": { + "message": "ഒന്നോ അതിലധികമോ ഓർഗനൈസേഷൻ നയങ്ങൾക്ക് ഇനിപ്പറയുന്ന ആവശ്യകതകൾ നിറവേറ്റുന്നതിന് നിങ്ങളുടെ മാസ്റ്റർ പാസ്‌വേഡ് ആവശ്യമാണ്:" + }, + "policyInEffectMinComplexity": { + "message": "സങ്കീർണ്ണതയുടെ കുറഞ്ഞ സ്കോർ$SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "കുറഞ്ഞ ദൈർഘ്യം $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "ഒന്നോ അതിലധികമോ വലിയക്ഷരങ്ങൾ അടങ്ങിയിരിക്കുന്ന" + }, + "policyInEffectLowercase": { + "message": "ഒന്നോ അതിലധികമോ ചെറിയക്ഷരങ്ങൾ അടങ്ങിയിരിക്കുന്ന" + }, + "policyInEffectNumbers": { + "message": "ഒന്നോ അതിലധികമോ അക്കങ്ങൾ അടങ്ങിയിരിക്കുന്ന" + }, + "policyInEffectSpecial": { + "message": "ഇനിപ്പറയുന്ന ഒന്നോ അതിലധികമോ പ്രത്യേക പ്രതീകങ്ങൾ അടങ്ങിയിരിക്കണം:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "നിങ്ങളുടെ പുതിയ മാസ്റ്റർ പാസ്‌വേഡ് നയ ആവശ്യകതകൾ നിറവേറ്റുന്നില്ല." + }, + "acceptPolicies": { + "message": "ഈ ബോക്സ് ചെക്കുചെയ്യുന്നതിലൂടെ നിങ്ങൾ ഇനിപ്പറയുന്നവ അംഗീകരിക്കുന്നു:" + }, + "acceptPoliciesError": { + "message": "സേവന നിബന്ധനകളും സ്വകാര്യതാ നയവും അംഗീകരിച്ചിട്ടില്ല." + }, + "termsOfService": { + "message": "സേവന നിബന്ധനകൾ" + }, + "privacyPolicy": { + "message": "സ്വകാര്യതാനയം" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/nb/messages.json b/apps/browser/src/_locales/nb/messages.json new file mode 100644 index 0000000000..3aa141549a --- /dev/null +++ b/apps/browser/src/_locales/nb/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden — Fri passordbehandling", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden er en sikker og fri passordbehandler for alle dine PCer og mobiler.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Logg på eller opprett en ny konto for å få tilgang til ditt sikre hvelv." + }, + "createAccount": { + "message": "Opprett en konto" + }, + "login": { + "message": "Logg inn" + }, + "enterpriseSingleSignOn": { + "message": "Bedriftsinnlogging (SSO)" + }, + "cancel": { + "message": "Lukk" + }, + "close": { + "message": "Lukk" + }, + "submit": { + "message": "Send inn" + }, + "emailAddress": { + "message": "E-postadresse" + }, + "masterPass": { + "message": "Hovedpassord" + }, + "masterPassDesc": { + "message": "Superpassordet er passordet du bruker for å få tilgang til hvelvet ditt. Det er veldig viktig at du aldri glemmer ditt superpassord. Det er ingen måter å få tilbake passordet på dersom du noensinne skulle klare å glemme det." + }, + "masterPassHintDesc": { + "message": "Et hint for superpassordet kan hjelpe deg med å huske på passordet dersom du skulle glemme det." + }, + "reTypeMasterPass": { + "message": "Skriv inn hovedpassordet på nytt" + }, + "masterPassHint": { + "message": "Et hint for hovedpassordet (valgfritt)" + }, + "tab": { + "message": "Fane" + }, + "myVault": { + "message": "Mitt hvelv" + }, + "tools": { + "message": "Verktøy" + }, + "settings": { + "message": "Innstillinger" + }, + "currentTab": { + "message": "Nåværende fane" + }, + "copyPassword": { + "message": "Kopier passordet" + }, + "copyNote": { + "message": "Kopier notatet" + }, + "copyUri": { + "message": "Kopier URIen" + }, + "copyUsername": { + "message": "Kopier brukernavnet" + }, + "copyNumber": { + "message": "Kopier nummeret" + }, + "copySecurityCode": { + "message": "Kopier sikkerhetskoden" + }, + "autoFill": { + "message": "Auto-utfylling" + }, + "generatePasswordCopied": { + "message": "Generer et passord (kopiert)" + }, + "copyElementIdentifier": { + "message": "Kopier egendefinert feltnavn" + }, + "noMatchingLogins": { + "message": "Ingen samsvarende innlogginger." + }, + "unlockVaultMenu": { + "message": "Lås opp hvelvet ditt" + }, + "loginToVaultMenu": { + "message": "Logg inn på hvelvet ditt" + }, + "autoFillInfo": { + "message": "Det er ingen tilgjengelige innlogginger å auto-utfylle med i den nåværende nettleserfanen." + }, + "addLogin": { + "message": "Legg til en innlogging" + }, + "addItem": { + "message": "Legg til en gjenstand" + }, + "passwordHint": { + "message": "Passordhint" + }, + "enterEmailToGetHint": { + "message": "Skriv inn din kontos E-postadresse for å motta hintet til ditt superpassord." + }, + "getMasterPasswordHint": { + "message": "Få et hint om superpassordet" + }, + "continue": { + "message": "Fortsett" + }, + "sendVerificationCode": { + "message": "Send en bekreftelseskode til E-postadressen din" + }, + "sendCode": { + "message": "Send kode" + }, + "codeSent": { + "message": "Kode sendt" + }, + "verificationCode": { + "message": "Verifiseringskode" + }, + "confirmIdentity": { + "message": "Bekreft identiteten din for å fortsette." + }, + "account": { + "message": "Konto" + }, + "changeMasterPassword": { + "message": "Endre hovedpassordet" + }, + "fingerprintPhrase": { + "message": "Fingeravtrykksfrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Din kontos fingeravtrykksfrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "2-trinnsinnlogging" + }, + "logOut": { + "message": "Logg ut" + }, + "about": { + "message": "Om" + }, + "version": { + "message": "Versjon" + }, + "save": { + "message": "Lagre" + }, + "move": { + "message": "Flytt" + }, + "addFolder": { + "message": "Legg til en mappe" + }, + "name": { + "message": "Navn" + }, + "editFolder": { + "message": "Rediger mappen" + }, + "deleteFolder": { + "message": "Slett mappen" + }, + "folders": { + "message": "Mapper" + }, + "noFolders": { + "message": "Det er ingen mapper å liste opp." + }, + "helpFeedback": { + "message": "Hjelp og tilbakemelding" + }, + "sync": { + "message": "Synkroniser" + }, + "syncVaultNow": { + "message": "Synkroniser hvelvet nå" + }, + "lastSync": { + "message": "Forrige synkronisering:" + }, + "passGen": { + "message": "Passordgenerator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Generer automatisk sterke og unike passord for dine innlogginger." + }, + "bitWebVault": { + "message": "Bitwarden netthvelv" + }, + "importItems": { + "message": "Importer gjenstander" + }, + "select": { + "message": "Velg" + }, + "generatePassword": { + "message": "Generer et passord" + }, + "regeneratePassword": { + "message": "Omgenerer et passord" + }, + "options": { + "message": "Alternativer" + }, + "length": { + "message": "Lengde" + }, + "uppercase": { + "message": "Store bokstaver (A–Å)" + }, + "lowercase": { + "message": "Små bokstaver (a-z)" + }, + "numbers": { + "message": "Tall (0-9)" + }, + "specialCharacters": { + "message": "Spesialtegn (!@#$%^&*)" + }, + "numWords": { + "message": "Antall ord" + }, + "wordSeparator": { + "message": "Ordadskiller" + }, + "capitalize": { + "message": "Stor forbokstav", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inkluder nummer" + }, + "minNumbers": { + "message": "Minste antall numre" + }, + "minSpecial": { + "message": "Minste antall spesialtegn" + }, + "avoidAmbChar": { + "message": "Unngå tvetydige tegn" + }, + "searchVault": { + "message": "Søk i hvelvet" + }, + "edit": { + "message": "Rediger" + }, + "view": { + "message": "Vis" + }, + "noItemsInList": { + "message": "Det er ingen gjenstander å liste opp." + }, + "itemInformation": { + "message": "Gjenstandsinformasjon" + }, + "username": { + "message": "Brukernavn" + }, + "password": { + "message": "Passord" + }, + "passphrase": { + "message": "Passfrase" + }, + "favorite": { + "message": "Favoritt" + }, + "notes": { + "message": "Notater" + }, + "note": { + "message": "Notat" + }, + "editItem": { + "message": "Rediger objektet" + }, + "folder": { + "message": "Mappe" + }, + "deleteItem": { + "message": "Slett objektet" + }, + "viewItem": { + "message": "Vis objektet" + }, + "launch": { + "message": "Åpne" + }, + "website": { + "message": "Nettsted" + }, + "toggleVisibility": { + "message": "Juster synlighet" + }, + "manage": { + "message": "Behandle" + }, + "other": { + "message": "Annet" + }, + "rateExtension": { + "message": "Gi denne utvidelsen en vurdering" + }, + "rateExtensionDesc": { + "message": "Tenk gjerne på om du vil skrive en anmeldelse om oss!" + }, + "browserNotSupportClipboard": { + "message": "Nettleseren din støtter ikke kopiering til utklippstavlen på noe enkelt vis. Prøv å kopiere det manuelt i stedet." + }, + "verifyIdentity": { + "message": "Bekreft identitet" + }, + "yourVaultIsLocked": { + "message": "Hvelvet ditt er låst. Kontroller hovedpassordet ditt for å fortsette." + }, + "unlock": { + "message": "Lås opp" + }, + "loggedInAsOn": { + "message": "Logget inn som $EMAIL$ på $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ugyldig superpassord" + }, + "vaultTimeout": { + "message": "Tidsavbrudd i hvelvet" + }, + "lockNow": { + "message": "Lås nå" + }, + "immediately": { + "message": "Umiddelbart" + }, + "tenSeconds": { + "message": "10 sekunder" + }, + "twentySeconds": { + "message": "20 sekunder" + }, + "thirtySeconds": { + "message": "30 sekunder" + }, + "oneMinute": { + "message": "1 minutt" + }, + "twoMinutes": { + "message": "2 minutter" + }, + "fiveMinutes": { + "message": "5 minutter" + }, + "fifteenMinutes": { + "message": "15 minutter" + }, + "thirtyMinutes": { + "message": "30 minutter" + }, + "oneHour": { + "message": "1 time" + }, + "fourHours": { + "message": "4 timer" + }, + "onLocked": { + "message": "Ved maskinlåsing" + }, + "onRestart": { + "message": "Ved nettleseromstart" + }, + "never": { + "message": "Aldri" + }, + "security": { + "message": "Sikkerhet" + }, + "errorOccurred": { + "message": "En feil har oppstått" + }, + "emailRequired": { + "message": "E-postadressen er påkrevd." + }, + "invalidEmail": { + "message": "Ugyldig E-postadresse." + }, + "masterPassRequired": { + "message": "Superpassordet er påkrevd." + }, + "masterPassLength": { + "message": "Superpassordet må være ≥8 tegn lang." + }, + "masterPassDoesntMatch": { + "message": "Superpassord-bekreftelsen er ikke samsvarende." + }, + "newAccountCreated": { + "message": "Din nye konto har blitt opprettet! Du kan nå logge på." + }, + "masterPassSent": { + "message": "Vi har sendt deg en E-post med hintet til superpassordet." + }, + "verificationCodeRequired": { + "message": "En verifiseringskode er påkrevd." + }, + "invalidVerificationCode": { + "message": "Ugyldig bekreftelseskode" + }, + "valueCopied": { + "message": "$VALUE$ er kopiert", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Klarte ikke å auto-utfylle den valgte gjenstanden på denne siden. Kopier og lim inn informasjonen i stedet." + }, + "loggedOut": { + "message": "Logget av" + }, + "loginExpired": { + "message": "Din innloggingsøkt har utløpt." + }, + "logOutConfirmation": { + "message": "Er du sikker på at du vil logge av?" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nei" + }, + "unexpectedError": { + "message": "En uventet feil har oppstått." + }, + "nameRequired": { + "message": "Et navn er påkrevd." + }, + "addedFolder": { + "message": "La til en mappe" + }, + "changeMasterPass": { + "message": "Endre hovedpassordet" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kan endre superpassordet ditt på bitwarden.net-netthvelvet. Vil du besøke det nettstedet nå?" + }, + "twoStepLoginConfirmation": { + "message": "2-trinnsinnlogging gjør kontoen din mer sikker, ved å kreve at du verifiserer din innlogging med en annen enhet, f.eks. en autentiseringsapp, SMS, E-post, telefonsamtale, eller sikkerhetsnøkkel. 2-trinnsinnlogging kan aktiveres på bitwarden.com-netthvelvet. Vil du besøke den nettsiden nå?" + }, + "editedFolder": { + "message": "Redigerte mappen" + }, + "deleteFolderConfirmation": { + "message": "Er du sikker på at du vil slette denne mappen?" + }, + "deletedFolder": { + "message": "Slettet mappen" + }, + "gettingStartedTutorial": { + "message": "Opplæring om å sette i gang" + }, + "gettingStartedTutorialVideo": { + "message": "Se vår opplæringsvideo for å lære hvordan man får mest mulig ut av nettleserutvidelsen." + }, + "syncingComplete": { + "message": "Synkronisering fullført" + }, + "syncingFailed": { + "message": "Synkronisering mislyktes" + }, + "passwordCopied": { + "message": "Passordet er kopiert" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Ny URI" + }, + "addedItem": { + "message": "La til gjenstanden" + }, + "editedItem": { + "message": "Redigerte gjenstanden" + }, + "deleteItemConfirmation": { + "message": "Er du sikker på at du vil slette dette objektet?" + }, + "deletedItem": { + "message": "Slettet objektet" + }, + "overwritePassword": { + "message": "Overskriv passordet" + }, + "overwritePasswordConfirmation": { + "message": "Er du sikker på at du vil overskrive det nåværende passordet?" + }, + "overwriteUsername": { + "message": "Skriv over brukernavn" + }, + "overwriteUsernameConfirmation": { + "message": "Er du sikker på at du vil skrive over det nåværende brukernavnet?" + }, + "searchFolder": { + "message": "Søk i mappe" + }, + "searchCollection": { + "message": "Søk i samling" + }, + "searchType": { + "message": "Søketype" + }, + "noneFolder": { + "message": "Ingen mappe", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Deaktiver «Legg til innlogging»-beskjedene" + }, + "addLoginNotificationDesc": { + "message": "\"Legg til innlogging\"-beskjeden ber deg automatisk om å lagre nye innlogginger til hvelvet ditt hver gang du logger på dem for første gang." + }, + "dontShowCardsCurrentTab": { + "message": "Ikke vis kort på fanesiden" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Kortene fra hvelvet ditt er listet opp på «Nåværende fane»-siden for enkel tilgang til autoutfylling." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Ikke vis identiteter på fanesiden" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identitetene fra hvelvet ditt er listet opp på «Nåværende fane»-siden for enkel autoutfyllingstilgang." + }, + "clearClipboard": { + "message": "Tøm utklippstavlen", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Slett automatisk kopierte verdier fra utklippstavlen.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Skal Bitwarden huske på dette passordet for deg?" + }, + "notificationAddSave": { + "message": "Ja, lagre nå" + }, + "disableChangedPasswordNotification": { + "message": "Deaktiver beskjeder om passordendringer" + }, + "disableChangedPasswordNotificationDesc": { + "message": "«Endret passord»-beskjeden spør deg automatisk om å oppdatere et innloggingspassord i hvelvet ditt, dersom den oppdager at du har endret det på et nettsted." + }, + "notificationChangeDesc": { + "message": "Vil du oppdatere dette passordet i Bitwarden?" + }, + "notificationChangeSave": { + "message": "Ja, oppdater nå" + }, + "disableContextMenuItem": { + "message": "Deaktiver sammenhengsmeny-innstillinger" + }, + "disableContextMenuItemDesc": { + "message": "Sammenhengsmeny-alternativer sørger for rask tilgang til passordgenerering og innlogginger for nettstedet i din nåværende fane." + }, + "defaultUriMatchDetection": { + "message": "Standard URI-samsvarsgjenkjenning", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Velg standardmåten for å håndtere URI-samsvarsgjenkjenning for pålogginger ved f. eks. auto-utfylling." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Endre appens fargetema." + }, + "dark": { + "message": "Mørkt", + "description": "Dark color" + }, + "light": { + "message": "Lyst", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarisert mørk", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Eksporter hvelvet" + }, + "fileFormat": { + "message": "Filformat" + }, + "warning": { + "message": "ADVARSEL", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Bekreft eksport av hvelvet" + }, + "exportWarningDesc": { + "message": "Eksporten inneholder dine hvelvdataer i et ukryptert format. Du burde ikke lagre eller sende den eksporterte filen over usikre tjenester (f.eks. E-post). Slett det umiddelbart etter at du er ferdig med å bruke dem." + }, + "encExportKeyWarningDesc": { + "message": "Denne eksporten krypterer dataene dine ved hjelp av kontoen din sin krypteringsnøkkel. Hvis du noen gang endrer krypteringsnøkkelen til kontoen din, bør du eksportere dataene igjen, ettersom du da ikke vil kunne dekryptere denne eksportfilen." + }, + "encExportAccountWarningDesc": { + "message": "Kontokrypteringsnøkler er unike for hver Bitwarden sin brukerkonto, og du kan ikke importere en kryptert eksport til en annen konto." + }, + "exportMasterPassword": { + "message": "Skriv inn ditt superpassord for å eksportere dine hvelvdataer." + }, + "shared": { + "message": "Delt" + }, + "learnOrg": { + "message": "Lær om organisasjoner" + }, + "learnOrgConfirmation": { + "message": "Bitwarden lar deg dele dine hvelvgjenstander med andre ved å bruke en organisasjon. Vil du besøke bitwarden.com-nettstedet for å lære mer?" + }, + "moveToOrganization": { + "message": "Flytt til organisasjon" + }, + "share": { + "message": "Del" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ flyttet til $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Velg en organisasjon som du ønsker å flytte denne gjenstanden til. Flytting til en organisasjon overfører eierskap til den aktuelle organisasjonen. Du vil ikke lenger være den direkte eieren av denne varen når den er flyttet." + }, + "learnMore": { + "message": "Lær mer" + }, + "authenticatorKeyTotp": { + "message": "Autentiseringsnøkkel (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verifiseringskode (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopier verifiseringskoden" + }, + "attachments": { + "message": "Vedlegg" + }, + "deleteAttachment": { + "message": "Slett vedlegget" + }, + "deleteAttachmentConfirmation": { + "message": "Er du sikker på at du vil slette dette vedlegget?" + }, + "deletedAttachment": { + "message": "Slettet vedlegget" + }, + "newAttachment": { + "message": "Legg til et nytt vedlegg" + }, + "noAttachments": { + "message": "Ingen vedlegg." + }, + "attachmentSaved": { + "message": "Vedlegget har blitt lagret." + }, + "file": { + "message": "Fil" + }, + "selectFile": { + "message": "Velg en fil." + }, + "maxFileSize": { + "message": "Den maksimale filstørrelsen er 500 MB." + }, + "featureUnavailable": { + "message": "Egenskapen er utilgjengelig" + }, + "updateKey": { + "message": "Du kan ikke bruke denne funksjonen før du oppdaterer krypteringsnøkkelen din." + }, + "premiumMembership": { + "message": "Premium-medlemskap" + }, + "premiumManage": { + "message": "Behandle medlemsskapet" + }, + "premiumManageAlert": { + "message": "Du kan behandle medlemskapet ditt på bitwarden.net-netthvelvet. Vil du besøke det nettstedet nå?" + }, + "premiumRefresh": { + "message": "Oppdater medlemskapet" + }, + "premiumNotCurrentMember": { + "message": "Du er ikke for øyeblikket et Premium-medlem." + }, + "premiumSignUpAndGet": { + "message": "Skriv deg opp på et Premium-medlemskap og få:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB med kryptert fillagring for filvedlegg." + }, + "ppremiumSignUpTwoStep": { + "message": "Ytterligere 2-trinnsinnloggingsmuligheter, slik som YubiKey, FIDO U2F, og Duo." + }, + "ppremiumSignUpReports": { + "message": "Passordhygiene, kontohelse, og databruddsrapporter som holder hvelvet ditt trygt." + }, + "ppremiumSignUpTotp": { + "message": "TOTP-verifiseringskodegenerator (2FA) for innlogginger i ditt hvelv." + }, + "ppremiumSignUpSupport": { + "message": "Prioritert kundestøtte." + }, + "ppremiumSignUpFuture": { + "message": "Alle fremtidige Premium-egenskaper. Mere er planlagt snart!" + }, + "premiumPurchase": { + "message": "Kjøp Premium" + }, + "premiumPurchaseAlert": { + "message": "Du kan kjøpe et Premium-medlemskap på bitwarden.net-netthvelvet. Vil du besøke det nettstedet nå?" + }, + "premiumCurrentMember": { + "message": "Du er et Premium-medlem!" + }, + "premiumCurrentMemberThanks": { + "message": "Takk for at du støtter Bitwarden." + }, + "premiumPrice": { + "message": "Og alt det for %price%/år!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Oppfriskning fullført" + }, + "disableAutoTotpCopy": { + "message": "Deaktiver automatisk TOTP-kopiering" + }, + "disableAutoTotpCopyDesc": { + "message": "Dersom din innlogging har en autentiseringsnøkkel knyttet til den, blir TOTP-verifiseringskoden automatisk kopiert til utklippstavlen din når enn du auto-utfyller innloggingen." + }, + "disableAutoBiometricsPrompt": { + "message": "Ikke be om biometri under åpning" + }, + "premiumRequired": { + "message": "Premium er påkrevd" + }, + "premiumRequiredDesc": { + "message": "Et Premium-medlemskap er påkrevd for å bruke denne funksjonen." + }, + "enterVerificationCodeApp": { + "message": "Skriv inn den 6-sifrede verifiseringskoden som står på din autentiseringsapp." + }, + "enterVerificationCodeEmail": { + "message": "Skriv inn den 6-sifrede verifiseringskoden som ble sendt til", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "En verifiserings-E-post har blitt sendt til $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Husk på meg" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send E-posten med verifiseringskoden på nytt" + }, + "useAnotherTwoStepMethod": { + "message": "Bruk en annen 2-trinnsinnloggingsmetode" + }, + "insertYubiKey": { + "message": "Sett inn din YubiKey i din datamaskins USB-uttak, og så trykk på dens knapp." + }, + "insertU2f": { + "message": "Sett din sikkerhetsnøkkel inn i din datamaskins USB-uttak. Dersom den har en knapp, trykk på den." + }, + "webAuthnNewTab": { + "message": "For å starte WebAuthn 2FA bekreftelsen. Klikk på knappen nedenfor for å åpne en ny fane og følge instruksene som er gitt i den nye fanen." + }, + "webAuthnNewTabOpen": { + "message": "Åpne ny fane" + }, + "webAuthnAuthenticate": { + "message": "Autentiser WebAuthn" + }, + "loginUnavailable": { + "message": "Innloggingen er utilgjengelig" + }, + "noTwoStepProviders": { + "message": "Denne kontoen har aktivert 2-trinnsinnlogging, men ingen av de oppsatte 2-trinnsleverandørene er støttet av denne nettleseren." + }, + "noTwoStepProviders2": { + "message": "Vennligst bruk en støttet nettleser (f.eks. Chrome) og/eller legg til flere leverandører som er bedre støttet mellom flere nettlesere (slik som en autentiseringsapp)." + }, + "twoStepOptions": { + "message": "Alternativer for 2-trinnsinnlogging" + }, + "recoveryCodeDesc": { + "message": "Har du mistet tilgang til alle dine 2-trinnsleverandører? Bruk din gjenopprettingskode til å fjerne alle 2-trinnsleverandører fra din konto." + }, + "recoveryCodeTitle": { + "message": "Gjenopprettingskode" + }, + "authenticatorAppTitle": { + "message": "Autentiseringsapp" + }, + "authenticatorAppDesc": { + "message": "Bruk en autentiseringsapp (f.eks. Authy eller Google Authenticator) for å generere tidsbegrensede verifiseringskoder.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP-sikkerhetsnøkkel" + }, + "yubiKeyDesc": { + "message": "Bruk en YubiKey for å få tilgang til kontoen din. Virker med enheter av typene YubiKey 4, 4 Nano, 4C, og NEO." + }, + "duoDesc": { + "message": "Verifiser med Duo Security gjennom Duo Mobile-appen, SMS, telefonsamtale, eller en U2F-sikkerhetsnøkkel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifiser med Duo Security for din organisasjon gjennom Duo Mobile-appen, SMS, telefonsamtale, eller en U2F-sikkerhetsnøkkel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Bruk en hvilken som helst WebAuthn aktivert sikkerhetsnøkkel til å få tilgang til kontoen din." + }, + "emailTitle": { + "message": "E-post" + }, + "emailDesc": { + "message": "Verifiseringskoder vil bli sendt til deg med E-post." + }, + "selfHostedEnvironment": { + "message": "Selvbetjent miljø" + }, + "selfHostedEnvironmentFooter": { + "message": "Spesifiser grunn-nettadressen til din selvbetjente Bitwarden-installasjon." + }, + "customEnvironment": { + "message": "Tilpasset miljø" + }, + "customEnvironmentFooter": { + "message": "For avanserte brukere. Du kan bestemme grunn-nettadressen til hver tjeneste separat." + }, + "baseUrl": { + "message": "Tjener-nettadresse" + }, + "apiUrl": { + "message": "API-tjenernettadresse" + }, + "webVaultUrl": { + "message": "Netthvelvets tjenernettadresse" + }, + "identityUrl": { + "message": "Identitetstjenerens nettadresse" + }, + "notificationsUrl": { + "message": "Varslingstjenerens URL" + }, + "iconsUrl": { + "message": "Ikonenes tjenernettadresse" + }, + "environmentSaved": { + "message": "Miljø-nettadressene har blitt lagret." + }, + "enableAutoFillOnPageLoad": { + "message": "Aktiver auto-utfylling ved sideinnlastning" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Dersom et innloggingskjema blir oppdaget, utfør automatisk en auto-utfylling når nettstedet lastes inn." + }, + "experimentalFeature": { + "message": "Dette er for øyeblikket en eksperimentell egenskap. Bruk det på din egen risiko." + }, + "defaultAutoFillOnPageLoad": { + "message": "Standard autofyll innstilling for innloggingselementer" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Etter aktivering av auto-utfylling på sidelasser, kan du aktivere eller deaktivere funksjonen for individuelle innloggingselementer. Dette er standardinnstillingen for innloggingselementer som ikke er satt opp separat." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-utfyll på sideinnlastning (hvis aktivert i Alternativer)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Bruk standardinnstillinger" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-utfyll ved innlasting av side" + }, + "autoFillOnPageLoadNo": { + "message": "Ikke fyll automatisk når du laster inn siden" + }, + "commandOpenPopup": { + "message": "Åpne hvelv-vindu" + }, + "commandOpenSidebar": { + "message": "Åpne hvelv i sidepanelet" + }, + "commandAutofillDesc": { + "message": "Auto-utfyll den senest brukte innloggingen til den nåværende nettsiden." + }, + "commandGeneratePasswordDesc": { + "message": "Generer og kopier et nytt tilfeldig passord til utklippstavlen." + }, + "commandLockVaultDesc": { + "message": "Lås hvelvet" + }, + "privateModeWarning": { + "message": "Støtte for privatmodus er eksperimentelt, og noen funksjoner er begrenset." + }, + "customFields": { + "message": "Tilpassede felter" + }, + "copyValue": { + "message": "Kopier verdien" + }, + "value": { + "message": "Verdi" + }, + "newCustomField": { + "message": "Nytt egendefinert felt" + }, + "dragToSort": { + "message": "Dra for å sortere" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Skjult" + }, + "cfTypeBoolean": { + "message": "Boolsk verdi" + }, + "cfTypeLinked": { + "message": "Tilkoblet", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Tilkoblet verdi", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Å klikke utenfor dette oppsprettsvinduet for å sjekke E-postinnboksen din for en verifiseringskoden, vil lukke denne oppspretten. Vil du åpne oppsprettet i et nytt vindu sånn at den ikke lukkes?" + }, + "popupU2fCloseMessage": { + "message": "Denne nettleseren kan ikke behandle U2F-forespørsler i dette popup-vinduet. Vil du åpne denne popupen i et nytt vindu, slik at du kan logge deg på med U2F?" + }, + "disableFavicon": { + "message": "Skru av nettstedsikoner" + }, + "disableFaviconDesc": { + "message": "Nettstedsikoner sørger for et gjenkjennelig bilde ved siden av hver innloggingsgjenstand i hvelvet ditt." + }, + "disableBadgeCounter": { + "message": "Deaktiver Badge Teller" + }, + "disableBadgeCounterDesc": { + "message": "Bade-teller indikerer hvor mange innlogginger du har for den nåværende siden i hvelvet ditt." + }, + "cardholderName": { + "message": "Kortholderens navn" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Merke" + }, + "expirationMonth": { + "message": "Utløpsmåned" + }, + "expirationYear": { + "message": "Utløpsår" + }, + "expiration": { + "message": "Utløp" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Mars" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Desember" + }, + "securityCode": { + "message": "Sikkerhetskode" + }, + "ex": { + "message": "f.eks." + }, + "title": { + "message": "Tittel" + }, + "mr": { + "message": "Herr" + }, + "mrs": { + "message": "Fru" + }, + "ms": { + "message": "Frøken" + }, + "dr": { + "message": "Dr." + }, + "firstName": { + "message": "Fornavn" + }, + "middleName": { + "message": "Mellomnavn" + }, + "lastName": { + "message": "Etternavn" + }, + "fullName": { + "message": "Fullt navn" + }, + "identityName": { + "message": "Identitetsnavn" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Personnummer" + }, + "passportNumber": { + "message": "Passnummer" + }, + "licenseNumber": { + "message": "Lisensnummer" + }, + "email": { + "message": "E-post" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresse" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "By / Tettsted" + }, + "stateProvince": { + "message": "Fylke / Region" + }, + "zipPostalCode": { + "message": "Postnummer" + }, + "country": { + "message": "Land" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Innlogging" + }, + "typeLogins": { + "message": "Innlogginger" + }, + "typeSecureNote": { + "message": "Sikker notis" + }, + "typeCard": { + "message": "Kort" + }, + "typeIdentity": { + "message": "Identitet" + }, + "passwordHistory": { + "message": "Passordhistorikk" + }, + "back": { + "message": "Tilbake" + }, + "collections": { + "message": "Samlinger" + }, + "favorites": { + "message": "Favoritter" + }, + "popOutNewWindow": { + "message": "Vis i et nytt vindu" + }, + "refresh": { + "message": "Oppfrisk" + }, + "cards": { + "message": "Kort" + }, + "identities": { + "message": "Identiteter" + }, + "logins": { + "message": "Innlogginger" + }, + "secureNotes": { + "message": "Sikre notiser" + }, + "clear": { + "message": "Tøm", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Sjekk om passordet har blitt utsatt." + }, + "passwordExposed": { + "message": "Dette passordet har blitt utsatt $VALUE$ gang(er) i et databrudd. Du burde endre det.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Dette passordet ble ikke funnet i noen kjente databrudd. Det burde være trygt å bruke." + }, + "baseDomain": { + "message": "Grunndomene", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domenenavn", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Vert", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Nøyaktig" + }, + "startsWith": { + "message": "Starter med" + }, + "regEx": { + "message": "Regulært uttrykk", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match-gjenkjenning", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standard match-gjenkjenning", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Skru av/på innstillinger" + }, + "toggleCurrentUris": { + "message": "Veksle nåværende URI-er", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Gjeldende URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisasjon", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Typer" + }, + "allItems": { + "message": "Alle objekter" + }, + "noPasswordsInList": { + "message": "Det er ingen passord å liste opp." + }, + "remove": { + "message": "Fjern" + }, + "default": { + "message": "Standard" + }, + "dateUpdated": { + "message": "Oppdatert den", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Passordet ble oppdatert den", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Er du sikker på at du vil bruke alternativet «Aldri»? Ved å angi låsemulighetene til «Aldri» lagres hvelvets krypteringsnøkkel på enheten. Hvis du bruker dette alternativet, bør du sørge for at du holder enheten forsvarlig beskyttet." + }, + "noOrganizationsList": { + "message": "Du tilhører ikke noen organisasjoner. Organisasjoner gjør det mulig for deg å sikkert dele objekter med andre brukere." + }, + "noCollectionsInList": { + "message": "Det er ingen samlinger å liste opp." + }, + "ownership": { + "message": "Eierskap" + }, + "whoOwnsThisItem": { + "message": "Hvem eier dette elementet?" + }, + "strong": { + "message": "Sterkt", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bra", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Svakt", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Svakt hovedpassord" + }, + "weakMasterPasswordDesc": { + "message": "Superpassordet du har valgt er svakt. Du bør bruke et sterkt superpassord (eller en passordfrase) for å sikre Bitwarden-kontoen din på en forsvarlig måte. Er du sikker på at du vil bruke dette superpassordet?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Lås opp med PIN-kode" + }, + "setYourPinCode": { + "message": "Angi PIN-koden din for å låse opp Bitwarden. PIN-innstillingene tilbakestilles hvis du logger deg helt ut av programmet." + }, + "pinRequired": { + "message": "PIN-kode er påkrevd." + }, + "invalidPin": { + "message": "Ugyldig PIN-kode." + }, + "unlockWithBiometrics": { + "message": "Lås opp med biometri" + }, + "awaitDesktop": { + "message": "Venter på bekreftelse fra skrivebordsprogrammet" + }, + "awaitDesktopDesc": { + "message": "Bekreft bruk av biometri i Bitwardens skrivebordsprogram for å aktivere biometri for nettleseren." + }, + "lockWithMasterPassOnRestart": { + "message": "Lås med hovedpassordet når du starter nettleseren på nytt" + }, + "selectOneCollection": { + "message": "Du må velge minst én samling." + }, + "cloneItem": { + "message": "Klon objektet" + }, + "clone": { + "message": "Klon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "En eller flere av organisasjonens vilkår påvirker generatorinnstillingene dine." + }, + "vaultTimeoutAction": { + "message": "Handling ved tidsavbrudd i hvelvet" + }, + "lock": { + "message": "Lås", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papirkurv", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Søk i papirkurven" + }, + "permanentlyDeleteItem": { + "message": "Slett objektet permanent" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Er du sikker på at du vil slette dette objektet permanent?" + }, + "permanentlyDeletedItem": { + "message": "Slettet objektet permanent" + }, + "restoreItem": { + "message": "Gjenopprett objekt" + }, + "restoreItemConfirmation": { + "message": "Er du sikker på at du vil gjenopprette dette objektet?" + }, + "restoredItem": { + "message": "Gjenopprettet objekt" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Hvis du logger ut, fjerner du all tilgang til hvelvet ditt og krever online godkjenning etter tidsavbrudd. Er du sikker på at du vil bruke denne innstillingen?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bekreftelse på handling ved tidsavbrudd" + }, + "autoFillAndSave": { + "message": "Autofyll og lagre" + }, + "autoFillSuccessAndSavedUri": { + "message": "Autoutfylt objekt og lagret URI" + }, + "autoFillSuccess": { + "message": "Autoutfylt gjenstand" + }, + "setMasterPassword": { + "message": "Angi hovedpassord" + }, + "masterPasswordPolicyInEffect": { + "message": "Ett eller flere av organisasjonens vilkår krever at hovedpassordet oppfyller følgende krav:" + }, + "policyInEffectMinComplexity": { + "message": "Minimumspoengsum for kompleksistet er $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimumslengde på $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Inneholde én eller flere store bokstaver" + }, + "policyInEffectLowercase": { + "message": "Inneholde én eller flere små bokstaver" + }, + "policyInEffectNumbers": { + "message": "Inneholde ett eller flere tall" + }, + "policyInEffectSpecial": { + "message": "Inneholde ett eller flere av følgende spesialtegn $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Det nye hovedpassordet ditt oppfyller ikke vilkårene." + }, + "acceptPolicies": { + "message": "Ved å merke av denne boksen sier du deg enig i følgende:" + }, + "acceptPoliciesError": { + "message": "Vilkårene for bruk og personvernerklæring er ikke akseptert." + }, + "termsOfService": { + "message": "Vilkår for bruk" + }, + "privacyPolicy": { + "message": "Personvernerklæring" + }, + "hintEqualsPassword": { + "message": "Passordhintet ditt kan ikke være det samme som passordet ditt." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Verifisering av skrivebordssynkronisering" + }, + "desktopIntegrationVerificationText": { + "message": "Kontroller at skrivebordsprogrammet viser dette fingeravtrykket:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Nettleserintegrasjon er ikke aktivert" + }, + "desktopIntegrationDisabledDesc": { + "message": "Nettleserintegrasjon er ikke aktivert i Bitwardens skrivebordsprogram. Du kan aktiver integrasjonen i innstillingene for skrivebordsprogrammet." + }, + "startDesktopTitle": { + "message": "Start Bitwardens skrivebordsprogram." + }, + "startDesktopDesc": { + "message": "Bitwardens skrivebordsprogram må startes før denne funksjonen kan brukes." + }, + "errorEnableBiometricTitle": { + "message": "Kunne ikke aktivere biometrier" + }, + "errorEnableBiometricDesc": { + "message": "Handlingen ble avbrutt av skrivebordsprogrammet" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Skrivebordsprogrammet ugyldiggjorde den sikre kommunikasjonskanalen. Prøv igjen" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Kommunikasjon med skrivebordsprogrammet er avbrutt" + }, + "nativeMessagingWrongUserDesc": { + "message": "Skrivebordsprogrammet er innlogget på en annen konto. Kontroller at både nettleserutvidelsen og skrivebordsprogrammet er innlogget på den samme kontoen." + }, + "nativeMessagingWrongUserTitle": { + "message": "Kontoen eksisterer ikke" + }, + "biometricsNotEnabledTitle": { + "message": "Biometri ikke aktivert" + }, + "biometricsNotEnabledDesc": { + "message": "Biometri i nettleserutvidelsen krever først aktivering i innstillinger i skrivebordsprogrammet." + }, + "biometricsNotSupportedTitle": { + "message": "Biometri støttes ikke" + }, + "biometricsNotSupportedDesc": { + "message": "Biometri i nettleseren støttes ikke på denne enheten." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Tillatelse er ikke gitt" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Uten tillatelse til å kommunisere med Bitwardens skrivebordsprogram kan vi ikke tilgjengeligjøre biometri i nettleserutvidelsen. Prøv igjen." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Feil ved forespørsel om tillatelse" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Denne handlingen kan ikke gjøres i sidestolpen, prøv på nytt i sprettoppvinduet eller popvindu." + }, + "personalOwnershipSubmitError": { + "message": "På grunn av bedrifsretningslinjer er du begrenset fra å lagre objekter til ditt personlige hvelv. Endre alternativ for eierskap til en organisasjon og velg blant tilgjengelige samlinger." + }, + "personalOwnershipPolicyInEffect": { + "message": "En bedriftsretningslinje påvirker dine eierskapsinnstillinger." + }, + "excludedDomains": { + "message": "Ekskluderte domener" + }, + "excludedDomainsDesc": { + "message": "Bitwarden vil ikke be om å lagre innloggingsdetaljer for disse domenene. Du må oppdatere siden for at endringene skal tre i kraft." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ er ikke et gyldig domene", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Søk i Send-ene", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Legg til Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Tekst" + }, + "sendTypeFile": { + "message": "Fil" + }, + "allSends": { + "message": "Alle Send-er", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maksimalt antall tilganger nådd", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Utløpt" + }, + "pendingDeletion": { + "message": "Venter på sletting" + }, + "passwordProtected": { + "message": "Passord beskyttet" + }, + "copySendLink": { + "message": "Kopier Send-lenke", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Fjern passord" + }, + "delete": { + "message": "Slett" + }, + "removedPassword": { + "message": "Fjernet passord" + }, + "deletedSend": { + "message": "Slettet Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send lenke", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Deaktivert" + }, + "removePasswordConfirmation": { + "message": "Er du sikker på at du vil fjerne passordet?" + }, + "deleteSend": { + "message": "Slett Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Er du sikker på at du vil slette denne Send-en?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Rediger Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Hvilken type Send er dette?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Et vennlig navn for å beskrive dette Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Filen du vil send." + }, + "deletionDate": { + "message": "Dato for sletting" + }, + "deletionDateDesc": { + "message": "Send-en vil bli slettet permanent på den angitte dato og klokkeslett.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Utløpsdato" + }, + "expirationDateDesc": { + "message": "Hvis satt, vil tilgang til denne Send gå ut på angitt dato og klokkeslett.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dag" + }, + "days": { + "message": "$DAYS$ dager", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Egendefinert" + }, + "maximumAccessCount": { + "message": "Maksimal antall tilganger" + }, + "maximumAccessCountDesc": { + "message": "Hvis satt, vil ikke brukere lenger ha tilgang til dette Send når maksimal antall tilgang er nådd.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Eventuelt krever et passord for brukere å få tilgang til denne Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notater om denne Send-en.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Deaktiver denne Send-en, slik at ingen får tilgang til den.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kopier denne Send-ens lenke til utklippstavlen når den har blitt lagret.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teksten du ønsker å sende." + }, + "sendHideText": { + "message": "Skjul denne Send-ens tekst som standard.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Antall nåværende tilganger" + }, + "createSend": { + "message": "Lag en ny Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nytt passord" + }, + "sendDisabled": { + "message": "Send er skrudd av", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "På grunn av en virksomhetsregel kan du kun slette en eksisterende Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Opprettet Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Redigerte Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "For å velge en fil, åpne utvidelsen i sidepanelet (hvis mulig) eller poppe ut til et nytt vindu ved å klikke på dette banneret." + }, + "sendFirefoxFileWarning": { + "message": "For å velge en fil med Firefox må du åpne utvidelsen i sidestolpen eller sprette ut til et nytt vindu ved å klikke på dette banneret." + }, + "sendSafariFileWarning": { + "message": "For å velge en fil med Safari, popp ut i et nytt vindu ved å klikke på dette banneret." + }, + "sendFileCalloutHeader": { + "message": "Før du starter" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Hvis du vil bruke en kalenderstil-datovelger", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "kilkk her", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "å pope ut vinduet.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Utløpsdatoen angitt er ikke gyldig." + }, + "deletionDateIsInvalid": { + "message": "Slettingsdatoen som er gitt er ikke gyldig." + }, + "expirationDateAndTimeRequired": { + "message": "Utløps dato og tid er påkrevd." + }, + "deletionDateAndTimeRequired": { + "message": "Det kreves en slettingsdato og -tid." + }, + "dateParsingError": { + "message": "Det oppstod en feil ved lagring av slettingen og utløpsdatoene." + }, + "hideEmail": { + "message": "Skjul min e-postadresse fra mottakere." + }, + "sendOptionsPolicyInEffect": { + "message": "En eller flere av organisasjons retningslinjer påvirker generatorinnstillingene dine." + }, + "passwordPrompt": { + "message": "Forespørsel om hovedpassord på nytt" + }, + "passwordConfirmation": { + "message": "Superpassord bekreftelse" + }, + "passwordConfirmationDesc": { + "message": "Denne handlingen er beskyttet. For å fortsette, skriv inn superpassordet på nytt for å bekrefte identiteten din." + }, + "emailVerificationRequired": { + "message": "E-postbekreftelse kreves" + }, + "emailVerificationRequiredDesc": { + "message": "Du må bekrefte e-posten din for å bruke denne funksjonen. Du kan bekrefte e-postadressen din i netthvelvet." + }, + "updatedMasterPassword": { + "message": "Oppdaterte hovedpassordet" + }, + "updateMasterPassword": { + "message": "Oppdater hovedpassord" + }, + "updateMasterPasswordWarning": { + "message": "Hovedpassordet ditt ble nylig endret av en administrator i organisasjonen din. For å få tilgang til hvelvet, må du oppdatere det nå. Hvis du fortsetter, logges du ut av den nåværende økten, og du må logge på igjen. Aktive økter på andre enheter kan fortsette å være aktive i opptil én time." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatisk registrering" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Denne organisasjonen har en bedriftsoppsettsregel som automatisk innrullerer deg i tilbakestilling av passord. Registrering vil tillate organisasjonsadministratorer å endre hovedpassordet ditt." + }, + "selectFolder": { + "message": "Velg mappe …" + }, + "ssoCompleteRegistration": { + "message": "For å fullføre påloggingen med SSO, vennligst velg et hovedpassord for å få tilgang til og beskytte hvelvet ditt." + }, + "hours": { + "message": "Åpningstider" + }, + "minutes": { + "message": "Minutter" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Organisasjonens retningslinjer påvirker tidsavbruddet for hvelvet ditt. Maksimalt tillatt tidsavbrudd for hvelv er $HOURS$ time(r) og $MINUTES$ minutt(er)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Tidsavbruddet ditt for hvelvet overstiger begrensningene som er satt av organisasjonen din." + }, + "vaultExportDisabled": { + "message": "Hvelveksportering er skrudd av" + }, + "personalVaultExportPolicyInEffect": { + "message": "En eller flere regler i organisasjonsoppsettet forhindrer deg i å eksportere ditt personlige hvelv." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Klarte ikke å identifisere et gyldig skjemaelement. Prøv å inspisere HTML-en i stedet." + }, + "copyCustomFieldNameNotUnique": { + "message": "Ingen unik identifikator ble funnet." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ bruker SSO med en selvdrevet nøkkelserver. Et hovedpassord er ikke lenger nødvendig for å logge inn for medlemmer av denne organisasjonen.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Forlat organisasjonen" + }, + "removeMasterPassword": { + "message": "Fjern hovedpassord" + }, + "removedMasterPassword": { + "message": "Hovedpassordet er fjernet." + }, + "leaveOrganizationConfirmation": { + "message": "Er du sikker på at du vil forlate denne organisasjonen?" + }, + "leftOrganization": { + "message": "Du har forlatt organisasjonen." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Eksporterer personlig hvelv" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Feil" + }, + "regenerateUsername": { + "message": "Regenerer brukernavn" + }, + "generateUsername": { + "message": "Generer brukernavn" + }, + "usernameType": { + "message": "Brukernavntype" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Tilfeldig" + }, + "randomWord": { + "message": "Tilfeldig ord" + }, + "websiteName": { + "message": "Navn på nettside" + }, + "whatWouldYouLikeToGenerate": { + "message": "Hva vil du generere?" + }, + "passwordType": { + "message": "Passordtype" + }, + "service": { + "message": "Tjeneste" + } +} diff --git a/apps/browser/src/_locales/nl/messages.json b/apps/browser/src/_locales/nl/messages.json new file mode 100644 index 0000000000..17e9bc636c --- /dev/null +++ b/apps/browser/src/_locales/nl/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Gratis wachtwoordbeheer", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Een veilige en gratis oplossing voor wachtwoordbeheer voor al je apparaten.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in of maak een nieuw account aan om toegang te krijgen tot je beveiligde kluis." + }, + "createAccount": { + "message": "Account aanmaken" + }, + "login": { + "message": "Inloggen" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "Annuleren" + }, + "close": { + "message": "Sluiten" + }, + "submit": { + "message": "Versturen" + }, + "emailAddress": { + "message": "E-mailadres" + }, + "masterPass": { + "message": "Hoofdwachtwoord" + }, + "masterPassDesc": { + "message": "Het hoofdwachtwoord is het wachtwoord waarmee je toegang krijgt tot je beveiligde kluis. Het is belangrijk dat je het hoofdwachtwoord niet vergeet, want er is geen manier om het te herstellen." + }, + "masterPassHintDesc": { + "message": "Een hoofdwachtwoordhint kan je helpen je wachtwoord te herinneren als je het vergeten bent." + }, + "reTypeMasterPass": { + "message": "Hoofdwachtwoord opnieuw invoeren" + }, + "masterPassHint": { + "message": "Hoofdwachtwoordhint (optioneel)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "Mijn kluis" + }, + "tools": { + "message": "Gereedschap" + }, + "settings": { + "message": "Instellingen" + }, + "currentTab": { + "message": "Huidige tab" + }, + "copyPassword": { + "message": "Wachtwoord kopiëren" + }, + "copyNote": { + "message": "Notitie kopiëren" + }, + "copyUri": { + "message": "URI kopiëren" + }, + "copyUsername": { + "message": "Gebruikersnaam kopiëren" + }, + "copyNumber": { + "message": "Nummer kopiëren" + }, + "copySecurityCode": { + "message": "Beveiligingscode kopiëren" + }, + "autoFill": { + "message": "Auto-invullen" + }, + "generatePasswordCopied": { + "message": "Wachtwoord genereren (op klembord)" + }, + "copyElementIdentifier": { + "message": "Aangepaste veldnaam kopiëren" + }, + "noMatchingLogins": { + "message": "Geen overeenkomstige logins." + }, + "unlockVaultMenu": { + "message": "Ontgrendel je kluis" + }, + "loginToVaultMenu": { + "message": "Log in op je kluis" + }, + "autoFillInfo": { + "message": "Er zijn geen logins beschikbaar om op het huidige browser-tabblad in te vullen." + }, + "addLogin": { + "message": "Login toevoegen" + }, + "addItem": { + "message": "Item toevoegen" + }, + "passwordHint": { + "message": "Wachtwoordhint" + }, + "enterEmailToGetHint": { + "message": "Voer het e-mailadres van je account in om je hoofdwachtwoordhint te ontvangen." + }, + "getMasterPasswordHint": { + "message": "Hoofdwachtwoordhint opvragen" + }, + "continue": { + "message": "Doorgaan" + }, + "sendVerificationCode": { + "message": "Stuur een verificatiecode naar je e-mail" + }, + "sendCode": { + "message": "Code versturen" + }, + "codeSent": { + "message": "Code verstuurd" + }, + "verificationCode": { + "message": "Verificatiecode" + }, + "confirmIdentity": { + "message": "Bevestig je identiteit om door te gaan." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Hoofdwachtwoord wijzigen" + }, + "fingerprintPhrase": { + "message": "Vingerafdrukzin", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Vingerafdrukzin van je account", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Tweestapsaanmelding" + }, + "logOut": { + "message": "Uitloggen" + }, + "about": { + "message": "Over" + }, + "version": { + "message": "Versie" + }, + "save": { + "message": "Opslaan" + }, + "move": { + "message": "Verplaatsen" + }, + "addFolder": { + "message": "Map toevoegen" + }, + "name": { + "message": "Naam" + }, + "editFolder": { + "message": "Map bewerken" + }, + "deleteFolder": { + "message": "Map verwijderen" + }, + "folders": { + "message": "Mappen" + }, + "noFolders": { + "message": "Er zijn geen mappen om weer te geven." + }, + "helpFeedback": { + "message": "Hulp en reacties" + }, + "sync": { + "message": "Synchroniseren" + }, + "syncVaultNow": { + "message": "Kluis nu synchroniseren" + }, + "lastSync": { + "message": "Laatste synchronisatie:" + }, + "passGen": { + "message": "Wachtwoordgenerator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatisch sterke, unieke wachtwoorden voor je logins genereren." + }, + "bitWebVault": { + "message": "Bitwarden Webkluis" + }, + "importItems": { + "message": "Items importeren" + }, + "select": { + "message": "Selecteren" + }, + "generatePassword": { + "message": "Wachtwoord genereren" + }, + "regeneratePassword": { + "message": "Opnieuw genereren" + }, + "options": { + "message": "Opties" + }, + "length": { + "message": "Lengte" + }, + "uppercase": { + "message": "Hoofdletters (A-Z)" + }, + "lowercase": { + "message": "Kleine letters (a-z)" + }, + "numbers": { + "message": "Cijfers (0-9)" + }, + "specialCharacters": { + "message": "Speciale tekens (!@#$%^&*)" + }, + "numWords": { + "message": "Aantal woorden" + }, + "wordSeparator": { + "message": "Scheidingsteken" + }, + "capitalize": { + "message": "Beginhoofdletters", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Cijfer toevoegen" + }, + "minNumbers": { + "message": "Minimum aantal cijfers" + }, + "minSpecial": { + "message": "Minimum aantal speciale tekens" + }, + "avoidAmbChar": { + "message": "Dubbelzinnige tekens vermijden" + }, + "searchVault": { + "message": "Kluis doorzoeken" + }, + "edit": { + "message": "Bewerken" + }, + "view": { + "message": "Weergeven" + }, + "noItemsInList": { + "message": "Er zijn geen items om weer te geven." + }, + "itemInformation": { + "message": "Item" + }, + "username": { + "message": "Gebruikersnaam" + }, + "password": { + "message": "Wachtwoord" + }, + "passphrase": { + "message": "Wachtwoordzin" + }, + "favorite": { + "message": "Favoriet" + }, + "notes": { + "message": "Notities" + }, + "note": { + "message": "Notitie" + }, + "editItem": { + "message": "Item bewerken" + }, + "folder": { + "message": "Map" + }, + "deleteItem": { + "message": "Item verwijderen" + }, + "viewItem": { + "message": "Item weergeven" + }, + "launch": { + "message": "Starten" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Zichtbaarheid wisselen" + }, + "manage": { + "message": "Beheren" + }, + "other": { + "message": "Overig" + }, + "rateExtension": { + "message": "Deze extensie beoordelen" + }, + "rateExtensionDesc": { + "message": "Je kunt ons helpen door een goede recensie achter te laten!" + }, + "browserNotSupportClipboard": { + "message": "Je webbrowser ondersteunt kopiëren naar plakbord niet. Kopieer handmatig." + }, + "verifyIdentity": { + "message": "Identiteit verifiëren" + }, + "yourVaultIsLocked": { + "message": "Je kluis is vergrendeld. Bevestig je identiteit om door te gaan." + }, + "unlock": { + "message": "Ontgrendelen" + }, + "loggedInAsOn": { + "message": "Aangemeld als $EMAIL$ op $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ongeldig hoofdwachtwoord" + }, + "vaultTimeout": { + "message": "Time-out van de kluis" + }, + "lockNow": { + "message": "Nu vergrendelen" + }, + "immediately": { + "message": "Onmiddellijk" + }, + "tenSeconds": { + "message": "10 seconden" + }, + "twentySeconds": { + "message": "20 seconden" + }, + "thirtySeconds": { + "message": "30 seconden" + }, + "oneMinute": { + "message": "1 minuut" + }, + "twoMinutes": { + "message": "2 minuten" + }, + "fiveMinutes": { + "message": "5 minuten" + }, + "fifteenMinutes": { + "message": "15 minuten" + }, + "thirtyMinutes": { + "message": "30 minuten" + }, + "oneHour": { + "message": "1 uur" + }, + "fourHours": { + "message": "4 uur" + }, + "onLocked": { + "message": "Bij systeemvergrendeling" + }, + "onRestart": { + "message": "Bij herstart van de browser" + }, + "never": { + "message": "Nooit" + }, + "security": { + "message": "Beveiliging" + }, + "errorOccurred": { + "message": "Er is een fout opgetreden" + }, + "emailRequired": { + "message": "E-mailadres is vereist." + }, + "invalidEmail": { + "message": "Ongeldig e-mailadres." + }, + "masterPassRequired": { + "message": "Hoofdwachtwoord is vereist." + }, + "masterPassLength": { + "message": "Hoofdwachtwoord moet minstens 8 tekens lang zijn." + }, + "masterPassDoesntMatch": { + "message": "De hoofdwachtwoorden komen niet overeen." + }, + "newAccountCreated": { + "message": "Je nieuwe account is aangemaakt! Je kunt nu inloggen." + }, + "masterPassSent": { + "message": "We hebben je een e-mail gestuurd met je hoofdwachtwoordhint." + }, + "verificationCodeRequired": { + "message": "Verificatiecode is vereist." + }, + "invalidVerificationCode": { + "message": "Ongeldige verificatiecode" + }, + "valueCopied": { + "message": "$VALUE$ gekopieerd", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Automatisch invullen mislukt; kopieer en plak je inloggegevens handmatig." + }, + "loggedOut": { + "message": "Uitgelogd" + }, + "loginExpired": { + "message": "Je inlogsessie is verlopen." + }, + "logOutConfirmation": { + "message": "Weet je zeker dat je wilt uitloggen?" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nee" + }, + "unexpectedError": { + "message": "Er is een onverwachte fout opgetreden." + }, + "nameRequired": { + "message": "Naam is vereist." + }, + "addedFolder": { + "message": "Map is toegevoegd" + }, + "changeMasterPass": { + "message": "Hoofdwachtwoord wijzigen" + }, + "changeMasterPasswordConfirmation": { + "message": "Je kunt je hoofdwachtwoord wijzigen in de kluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "twoStepLoginConfirmation": { + "message": "Tweestapsaanmelding beschermt je account door je inlogpoging te bevestigen met een ander apparaat zoals een beveiligingscode, authenticatie-app, SMS, spraakoproep of e-mail. Je kunt Tweestapsaanmelding inschakelen in de webkluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "editedFolder": { + "message": "Map is bewerkt" + }, + "deleteFolderConfirmation": { + "message": "Weet je zeker dat je deze map wilt verwijderen?" + }, + "deletedFolder": { + "message": "Map is verwijderd" + }, + "gettingStartedTutorial": { + "message": "Aan-de-slag-handleiding" + }, + "gettingStartedTutorialVideo": { + "message": "Bekijk onze aan-de-slag-handleiding om te leren hoe je het meeste haalt uit de browserextensie." + }, + "syncingComplete": { + "message": "Synchronisatie voltooid" + }, + "syncingFailed": { + "message": "Synchronisatie mislukt" + }, + "passwordCopied": { + "message": "Wachtwoord gekopieerd" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nieuwe URI" + }, + "addedItem": { + "message": "Item is toegevoegd" + }, + "editedItem": { + "message": "Item is bewerkt" + }, + "deleteItemConfirmation": { + "message": "Weet je zeker dat je dit naar de prullenbak wilt verplaatsen?" + }, + "deletedItem": { + "message": "Item is verwijderd" + }, + "overwritePassword": { + "message": "Wachtwoord overschrijven" + }, + "overwritePasswordConfirmation": { + "message": "Weet je zeker dat je het huidige wachtwoord wilt overschrijven?" + }, + "overwriteUsername": { + "message": "Gebruikersnaam overschrijven" + }, + "overwriteUsernameConfirmation": { + "message": "Weet je zeker dat je de huidige gebruikersnaam wilt overschrijven?" + }, + "searchFolder": { + "message": "Map doorzoeken" + }, + "searchCollection": { + "message": "Verzameling doorzoeken" + }, + "searchType": { + "message": "Categorie doorzoeken" + }, + "noneFolder": { + "message": "Geen map", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Melding bij nieuwe login uitschakelen" + }, + "addLoginNotificationDesc": { + "message": "\"Melding bij nieuwe login\" vraagt automatisch om nieuwe sites in de kluis op te slaan wanneer je ergens voor de eerste keer inlogt." + }, + "dontShowCardsCurrentTab": { + "message": "Kaarten verbergen op tab" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Kaartitems uit je kluis staan op de pagina 'Huidige Tab' om automatisch invullen te vereenvoudigen." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Identiteiten verbergen op tab" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identiteitsitems uit je kluis staan op de pagina 'Huidige Tab' om automatisch invullen te vereenvoudigen." + }, + "clearClipboard": { + "message": "Klembord wissen", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Gekopieerde waarden automatisch van het klembord wissen.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Moet Bitwarden dit wachtwoord voor je onthouden?" + }, + "notificationAddSave": { + "message": "Ja, nu opslaan" + }, + "disableChangedPasswordNotification": { + "message": "Melding gewijzigd wachtwoord uitschakelen" + }, + "disableChangedPasswordNotificationDesc": { + "message": "De \"Melding gewijzigd wachtwoord\" stelt automatisch voor om een wachtwoord in je kluis bij te werken wanneer het op een website is gewijzigd." + }, + "notificationChangeDesc": { + "message": "Wilt je dit wachtwoord in Bitwarden bijwerken?" + }, + "notificationChangeSave": { + "message": "Ja, nu bijwerken" + }, + "disableContextMenuItem": { + "message": "Contextmenu-opties uitschakelen" + }, + "disableContextMenuItemDesc": { + "message": "Contextmenu-opties bieden snelle toegang tot de wachtwoordgenerator en logins voor de website in de huidige tab." + }, + "defaultUriMatchDetection": { + "message": "Standaard URI-overeenkomstdetectie", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Kies de standaardmethode voor detectie van URI-overeenkomsten voor logins bij acties, zoals automatisch invullen." + }, + "theme": { + "message": "Thema" + }, + "themeDesc": { + "message": "Het kleurenthema van de toepassing wijzigen." + }, + "dark": { + "message": "Donker", + "description": "Dark color" + }, + "light": { + "message": "Licht", + "description": "Light color" + }, + "solarizedDark": { + "message": "Overbelicht donker", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Kluis exporteren" + }, + "fileFormat": { + "message": "Bestandsindeling" + }, + "warning": { + "message": "WAARSCHUWING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Kluisexport bevestigen" + }, + "exportWarningDesc": { + "message": "Deze export bevat jouw kluisgegevens in een niet-versleutelde opmaak. Je moet het geëxporteerde bestand niet opslaan of verzenden over onbeveiligde kanalen (zoals e-mail). Verwijder het exportbestand direct na gebruik." + }, + "encExportKeyWarningDesc": { + "message": "Deze export versleutelt je gegevens met de encryptiesleutel van je account. Als je je encryptiesleutel verandert moet je opnieuw exporteren, omdat je deze export dan niet meer kunt ontcijferen." + }, + "encExportAccountWarningDesc": { + "message": "Encryptiesleutels zijn uniek voor elk Bitwarden-gebruikersaccount. Je kunt een versleutelde export dus niet in een ander account importeren." + }, + "exportMasterPassword": { + "message": "Voer je hoofdwachtwoord in om de kluisgegevens te exporteren." + }, + "shared": { + "message": "Gedeeld" + }, + "learnOrg": { + "message": "Meer over organisaties" + }, + "learnOrgConfirmation": { + "message": "Door een organisatie te gebruiken in Bitwarden kun je kluis-items delen met anderen. Wil je de website van bitwarden.com bezoeken voor meer informatie?" + }, + "moveToOrganization": { + "message": "Naar organisatie verplaatsen" + }, + "share": { + "message": "Delen" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ verplaatst naar $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Kies een organisatie waarnaar je dit item wilt verplaatsen. Door het verplaatsen krijgt de organisatie de eigendomsrechten van het item. Je bent niet langer de directe eigenaar meer van het item als het is verplaatst." + }, + "learnMore": { + "message": "Meer informatie" + }, + "authenticatorKeyTotp": { + "message": "Authenticatiecode (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verificatiecode (TOTP)" + }, + "copyVerificationCode": { + "message": "Verificatiecode kopiëren" + }, + "attachments": { + "message": "Bijlagen" + }, + "deleteAttachment": { + "message": "Bijlage verwijderen" + }, + "deleteAttachmentConfirmation": { + "message": "Weet je zeker dat je deze bijlage wilt verwijderen?" + }, + "deletedAttachment": { + "message": "Bijlage is verwijderd" + }, + "newAttachment": { + "message": "Nieuwe bijlage toevoegen" + }, + "noAttachments": { + "message": "Geen bijlagen." + }, + "attachmentSaved": { + "message": "De bijlage is opgeslagen." + }, + "file": { + "message": "Bestand" + }, + "selectFile": { + "message": "Selecteer een bestand." + }, + "maxFileSize": { + "message": "Maximale bestandsgrootte is 500 MB." + }, + "featureUnavailable": { + "message": "Functionaliteit niet beschikbaar" + }, + "updateKey": { + "message": "Je kunt deze functie pas gebruiken als je je encryptiesleutel bijwerkt." + }, + "premiumMembership": { + "message": "Premium-abonnement" + }, + "premiumManage": { + "message": "Abonnement beheren" + }, + "premiumManageAlert": { + "message": "Je kunt je abonnement aanpassen in de webkluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "premiumRefresh": { + "message": "Abonnement vernieuwen" + }, + "premiumNotCurrentMember": { + "message": "Je bent momenteel geen Premium-lid." + }, + "premiumSignUpAndGet": { + "message": "Meld je aan voor een Premium-abonnement en krijg:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB versleutelde opslag voor bijlagen." + }, + "ppremiumSignUpTwoStep": { + "message": "Extra opties voor tweestapsaanmelding zoals YubiKey, FIDO U2F en Duo." + }, + "ppremiumSignUpReports": { + "message": "Wachtwoordhygiëne, gezondheid van je account en datalekken om je kluis veilig te houden." + }, + "ppremiumSignUpTotp": { + "message": "TOTP-verificatiecodegenerator (2FA) voor logins in uw kluis." + }, + "ppremiumSignUpSupport": { + "message": "Klantondersteuning met hoge prioriteit." + }, + "ppremiumSignUpFuture": { + "message": "Alle toekomstige Premium-functionaliteiten. Binnenkort meer!" + }, + "premiumPurchase": { + "message": "Premium aanschaffen" + }, + "premiumPurchaseAlert": { + "message": "Je kunt een Premium-abonnement aanschaffen in de webkluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "premiumCurrentMember": { + "message": "Je bent Premium-lid!" + }, + "premiumCurrentMemberThanks": { + "message": "Bedankt voor het ondersteunen van Bitwarden." + }, + "premiumPrice": { + "message": "Dit alles voor slechts $PRICE$ per jaar!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Bijwerken voltooid" + }, + "disableAutoTotpCopy": { + "message": "TOTP automatisch kopiëren uitschakelen" + }, + "disableAutoTotpCopyDesc": { + "message": "Als je login gekoppeld is met een authenticatiecode, wordt de TOTP-verificatiecode automatisch naar het klembord gekopieerd bij het automatisch invullen van de login." + }, + "disableAutoBiometricsPrompt": { + "message": "Bij opstarten niet om biometrisch ontgrendelen vragen" + }, + "premiumRequired": { + "message": "Premium is vereist" + }, + "premiumRequiredDesc": { + "message": "Je hebt een Premium-abonnement nodig om deze functie te gebruiken." + }, + "enterVerificationCodeApp": { + "message": "Voer de 6-cijferige verificatiecode uit je authenticatie-app in." + }, + "enterVerificationCodeEmail": { + "message": "Voer de 6-cijferige verificatiecode in die via e-mail is verstuurd naar $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mail met verificatiecode is verzonden naar $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Mijn gegevens onthouden" + }, + "sendVerificationCodeEmailAgain": { + "message": "E-mail met verificatiecode opnieuw versturen" + }, + "useAnotherTwoStepMethod": { + "message": "Gebruik een andere methode voor tweestapsaanmelding" + }, + "insertYubiKey": { + "message": "Plaats je YubiKey in de USB-poort van je computer en druk op de knop." + }, + "insertU2f": { + "message": "Plaats je beveilingssleutel in de USB-poort van je computer. Als het een knop heeft, druk deze dan in." + }, + "webAuthnNewTab": { + "message": "Ga door met WebAuthn 2FA-verificatie in de nieuwe tab." + }, + "webAuthnNewTabOpen": { + "message": "Nieuwe tab openen" + }, + "webAuthnAuthenticate": { + "message": "Authenticeer WebAuthn" + }, + "loginUnavailable": { + "message": "Login niet beschikbaar" + }, + "noTwoStepProviders": { + "message": "Dit account heeft tweestapsaanmelding ingeschakeld, maar deze webbrowser ondersteunt geen van de geconfigureerde aanbieders." + }, + "noTwoStepProviders2": { + "message": "Gebruik een ondersteunde webbrowser (zoals Chrome) en/of voeg extra aanbieders toe die beter worden ondersteund in webbrowsers (zoals een authenticator-app)." + }, + "twoStepOptions": { + "message": "Opties voor tweestapsaanmelding" + }, + "recoveryCodeDesc": { + "message": "Ben je de toegang tot al je tweestapsaanbieders verloren? Gebruik dan je herstelcode om alle tweestapsaanbieders op je account uit te schakelen." + }, + "recoveryCodeTitle": { + "message": "Herstelcode" + }, + "authenticatorAppTitle": { + "message": "Authenticatie-app" + }, + "authenticatorAppDesc": { + "message": "Gebruik een authenticatie-app (zoals Authy of Google Authenticator) om tijdgebaseerde authenticatiecodes te genereren.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP-beveiligingssleutel" + }, + "yubiKeyDesc": { + "message": "Gebruik een YubiKey om toegang te krijgen tot uw account. Werkt met YubiKey 4, 4 Nano, 4C en Neo-apparaten." + }, + "duoDesc": { + "message": "Verificatie met Duo Security middels de Duo Mobile-app, sms, spraakoproep of een U2F-beveiligingssleutel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verificatie met Duo Security middels de Duo Mobile-app, sms, spraakoproep of een U2F-beveiligingssleutel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Gebruik een WebAuthn-beveilingssleutel om toegang te krijgen tot je account." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Je ontvangt verificatiecodes via e-mail." + }, + "selfHostedEnvironment": { + "message": "Zelfgehoste omgeving" + }, + "selfHostedEnvironmentFooter": { + "message": "Geef de basis-URL van jouw zelfgehoste Bitwarden-installatie." + }, + "customEnvironment": { + "message": "Aangepaste omgeving" + }, + "customEnvironmentFooter": { + "message": "Voor gevorderde gebruikers. Je kunt de basis-URL van elke dienst afzonderlijk instellen." + }, + "baseUrl": { + "message": "Server-URL" + }, + "apiUrl": { + "message": "API server-URL" + }, + "webVaultUrl": { + "message": "Webkluis server-URL" + }, + "identityUrl": { + "message": "Identiteitsserver-URL" + }, + "notificationsUrl": { + "message": "Meldingenserver-URL" + }, + "iconsUrl": { + "message": "Pictogrammenserver-URL" + }, + "environmentSaved": { + "message": "De omgeving-URL's zijn opgeslagen." + }, + "enableAutoFillOnPageLoad": { + "message": "Automatisch invullen bij laden van pagina" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Als een inlogformulier wordt gedetecteerd, dan worden de inloggegevens automatisch ingevuld." + }, + "experimentalFeature": { + "message": "Dit is momenteel een experimentele functie; gebruik hiervan is op eigen risico." + }, + "defaultAutoFillOnPageLoad": { + "message": "Standaardinstelling voor automatisch invullen login-items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Na het inschakelen van Automatisch invullen bij laden van pagina, kun je de functie voor individuele inlogitems in- of uitschakelen. Dit is de standaardinstelling voor inlogitems die niet afzonderlijk zijn geconfigureerd." + }, + "itemAutoFillOnPageLoad": { + "message": "Automatisch invullen bij laden van pagina (als ingeschakeld in Opties)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Standaardinstelling gebruiken" + }, + "autoFillOnPageLoadYes": { + "message": "Automatisch invullen bij laden van pagina" + }, + "autoFillOnPageLoadNo": { + "message": "Niet Automatisch invullen bij laden van pagina" + }, + "commandOpenPopup": { + "message": "Open kluis in pop-up" + }, + "commandOpenSidebar": { + "message": "Open kluis in zijbalk" + }, + "commandAutofillDesc": { + "message": "Vul automatisch de laatst gebruikte login in voor de huidige website" + }, + "commandGeneratePasswordDesc": { + "message": "Genereer en kopieer een nieuw willekeurig wachtwoord naar het klembord." + }, + "commandLockVaultDesc": { + "message": "Kluis vergrendelen" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Aangepaste velden" + }, + "copyValue": { + "message": "Waarde kopiëren" + }, + "value": { + "message": "Waarde" + }, + "newCustomField": { + "message": "Nieuw aangepast veld" + }, + "dragToSort": { + "message": "Slepen om te sorteren" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Verborgen" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Gekoppeld", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Gekoppelde waarde", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Als je buiten het pop-upvenster klikt om je e-mail te controleren op een verificatiecode, dan zal de pop-up sluiten. Wil je het pop-upvenster openen in een nieuw scherm, zodat het niet wordt gesloten?" + }, + "popupU2fCloseMessage": { + "message": "Deze browser kan U2F-verzoeken niet verwerken in dit popupvenster. Wilt je deze pop-up openen in een nieuw venster zodat je kunt inloggen met U2F?" + }, + "disableFavicon": { + "message": "Websitepictogrammen uitschakelen" + }, + "disableFaviconDesc": { + "message": "Websitepictogrammen geven een herkenbare afbeelding naast elk item in je kluis weer." + }, + "disableBadgeCounter": { + "message": "Badgeteller uitschakelen" + }, + "disableBadgeCounterDesc": { + "message": "De badgeteller geeft aan hoeveel logins je in je kluis hebt voor de huidige pagina." + }, + "cardholderName": { + "message": "Naam kaarthouder" + }, + "number": { + "message": "Kaartummer" + }, + "brand": { + "message": "Merk" + }, + "expirationMonth": { + "message": "Vervalmaand" + }, + "expirationYear": { + "message": "Vervaljaar" + }, + "expiration": { + "message": "Vervaldatum" + }, + "january": { + "message": "januari" + }, + "february": { + "message": "februari" + }, + "march": { + "message": "maart" + }, + "april": { + "message": "april" + }, + "may": { + "message": "mei" + }, + "june": { + "message": "juni" + }, + "july": { + "message": "juli" + }, + "august": { + "message": "augustus" + }, + "september": { + "message": "september" + }, + "october": { + "message": "oktober" + }, + "november": { + "message": "november" + }, + "december": { + "message": "december" + }, + "securityCode": { + "message": "Beveiligingscode" + }, + "ex": { + "message": "bijv." + }, + "title": { + "message": "Aanhef" + }, + "mr": { + "message": "Dhr." + }, + "mrs": { + "message": "Mevr." + }, + "ms": { + "message": "Mej." + }, + "dr": { + "message": "Dr." + }, + "firstName": { + "message": "Voornaam" + }, + "middleName": { + "message": "Tweede naam" + }, + "lastName": { + "message": "Achternaam" + }, + "fullName": { + "message": "Volledige naam" + }, + "identityName": { + "message": "Identiteitsnaam" + }, + "company": { + "message": "Bedrijf" + }, + "ssn": { + "message": "Burgerservicenummer" + }, + "passportNumber": { + "message": "Paspoortnummer" + }, + "licenseNumber": { + "message": "Rijbewijsnummer" + }, + "email": { + "message": "E-mailadres" + }, + "phone": { + "message": "Telefoonnummer" + }, + "address": { + "message": "Adres" + }, + "address1": { + "message": "Adres 1" + }, + "address2": { + "message": "Adres 2" + }, + "address3": { + "message": "Adres 3" + }, + "cityTown": { + "message": "Stad / gemeente" + }, + "stateProvince": { + "message": "Staat / provincie" + }, + "zipPostalCode": { + "message": "Postcode" + }, + "country": { + "message": "Land" + }, + "type": { + "message": "Categorie" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Veilige notitie" + }, + "typeCard": { + "message": "Kaart" + }, + "typeIdentity": { + "message": "Identiteit" + }, + "passwordHistory": { + "message": "Geschiedenis" + }, + "back": { + "message": "Terug" + }, + "collections": { + "message": "Verzamelingen" + }, + "favorites": { + "message": "Favorieten" + }, + "popOutNewWindow": { + "message": "Openen in een nieuw venster" + }, + "refresh": { + "message": "Verversen" + }, + "cards": { + "message": "Kaarten" + }, + "identities": { + "message": "Identiteiten" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Veilige notities" + }, + "clear": { + "message": "Wissen", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Controleer of wachtwoord is gelekt." + }, + "passwordExposed": { + "message": "Dit wachtwoord is $VALUE$ keer gelekt. Je zou het moeten veranderen.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Dit wachtwoord is niet gevonden in bekende gegevenslekken. Het kan veilig gebruikt worden." + }, + "baseDomain": { + "message": "Basisdomein", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domeinnaam", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Hostnaam", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Begint met" + }, + "regEx": { + "message": "Reguliere expressie", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Overeenkomstdetectie", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standaard overeenkomstdetectie", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Opties schakelen" + }, + "toggleCurrentUris": { + "message": "Huidige URI's wisselen", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Huidige URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisatie", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Categorieën" + }, + "allItems": { + "message": "Alle items" + }, + "noPasswordsInList": { + "message": "Er zijn geen wachtwoorden om weer te geven." + }, + "remove": { + "message": "Verwijderen" + }, + "default": { + "message": "Standaard" + }, + "dateUpdated": { + "message": "Bijgewerkt", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Wachtwoord bijgewerkt", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Weet je zeker dat je de optie \"Nooit\" wilt gebruiken? Met de vergrendelingsoptie \"Nooit\" wordt de coderingssleutel van je kluis op je apparaat bewaard. Als je deze optie gebruikt, moet je ervoor zorgen dat je je apparaat naar behoren beschermt." + }, + "noOrganizationsList": { + "message": "Je behoort niet tot een organisatie. Via organisaties deel je je items veilig met andere gebruikers." + }, + "noCollectionsInList": { + "message": "Er zijn geen verzamelingen om weer te geven." + }, + "ownership": { + "message": "Eigendom" + }, + "whoOwnsThisItem": { + "message": "Wie is eigenaar van dit item?" + }, + "strong": { + "message": "Sterk", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Goed", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Zwak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Zwak hoofdwachtwoord" + }, + "weakMasterPasswordDesc": { + "message": "Je hebt een zwak hoofdwachtwoord gekozen. Gebruik een sterk hoofdwachtwoord (of wachtwoordzin) om jouw Bitwarden-account goed te beschermen. Weet je zeker dat je dit hoofdwachtwoord wilt gebruiken?" + }, + "pin": { + "message": "PIN-code", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Ontgrendelen met PIN" + }, + "setYourPinCode": { + "message": "Stel je PIN-code in voor het ontgrendelen van Bitwarden. Je PIN-code wordt opnieuw ingesteld als je je ooit volledig afmeldt bij de applicatie." + }, + "pinRequired": { + "message": "PIN-code is vereist." + }, + "invalidPin": { + "message": "Ongeldige PIN-code." + }, + "unlockWithBiometrics": { + "message": "Biometrisch ontgrendelen" + }, + "awaitDesktop": { + "message": "Wacht op bevestiging van de desktop" + }, + "awaitDesktopDesc": { + "message": "Bevestig het gebruik van biometrie in de Bitwarden-desktopapplicatie om biometrie voor de browser in te schakelen." + }, + "lockWithMasterPassOnRestart": { + "message": "Vergrendelen met hoofdwachtwoord bij herstart browser" + }, + "selectOneCollection": { + "message": "Je moet tenminste één verzameling selecteren." + }, + "cloneItem": { + "message": "Item dupliceren" + }, + "clone": { + "message": "Dupliceren" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Een of meer organisatiebeleidseisen heeft invloed op de instellingen van je generator." + }, + "vaultTimeoutAction": { + "message": "Actie bij time-out" + }, + "lock": { + "message": "Vergrendelen", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Prullenbak", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Prullenbak doorzoeken" + }, + "permanentlyDeleteItem": { + "message": "Item definitief verwijderen" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Weet je zeker dat je dit item definitief wilt verwijderen?" + }, + "permanentlyDeletedItem": { + "message": "Definitief verwijderd item" + }, + "restoreItem": { + "message": "Item herstellen" + }, + "restoreItemConfirmation": { + "message": "Weet je zeker dat je dit item wilt herstellen?" + }, + "restoredItem": { + "message": "Hersteld item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Uitloggen ontneemt je de toegang tot je kluis en vereist online authenticatie na een periode van time-out. Weet je zeker dat je deze instelling wilt gebruiken?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bevestiging actie bij time-out" + }, + "autoFillAndSave": { + "message": "Automatisch invullen en opslaan" + }, + "autoFillSuccessAndSavedUri": { + "message": "Automatisch gevuld item en opgeslagen URI" + }, + "autoFillSuccess": { + "message": "Automatisch gevuld item" + }, + "setMasterPassword": { + "message": "Hoofdwachtwoord instellen" + }, + "masterPasswordPolicyInEffect": { + "message": "Een of meer organisatiebeleidseisen verlangen dat je hoofdwachtwoord voldoet aan:" + }, + "policyInEffectMinComplexity": { + "message": "Minimale complexiteitsscore van $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimale lengte van $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Bevat een of meer hoofdletters" + }, + "policyInEffectLowercase": { + "message": "Bevat een of meer kleine letters" + }, + "policyInEffectNumbers": { + "message": "Bevat een of meer cijfers" + }, + "policyInEffectSpecial": { + "message": "Bevat een of meer van de volgende speciale tekens $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Je nieuwe hoofdwachtwoord voldoet niet aan de beleidseisen." + }, + "acceptPolicies": { + "message": "Door dit vakje aan te vinken, ga je akkoord met het volgende:" + }, + "acceptPoliciesError": { + "message": "Algemene voorwaarden en privacybeleid zijn nog niet erkend." + }, + "termsOfService": { + "message": "Algemene voorwaarden" + }, + "privacyPolicy": { + "message": "Privacybeleid" + }, + "hintEqualsPassword": { + "message": "Je wachtwoordhint moet anders zijn dan je wachtwoord." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktopsynchronisatieverificatie" + }, + "desktopIntegrationVerificationText": { + "message": "Controleer of de desktopapplicatie deze vingerafdruk weergeeft: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browserintegratie is niet ingeschakeld" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browserintegratie is niet ingeschakeld in de Bitwarden-desktopapplicatie. Schakel deze optie in de instellingen binnen de desktop-applicatie in." + }, + "startDesktopTitle": { + "message": "Bitwarden-desktopapplicatie opstarten" + }, + "startDesktopDesc": { + "message": "Je moet de Bitwarden-desktopapplicatie starten om deze functie te gebruiken." + }, + "errorEnableBiometricTitle": { + "message": "Kon biometrie niet inschakelen" + }, + "errorEnableBiometricDesc": { + "message": "Actie is geannuleerd door de desktopapplicatie" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "De desktopapplicatie heeft het beveiligde communicatiekanaal ongeldig verklaard. Probeer het opnieuw" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktopcommunicatie onderbroken" + }, + "nativeMessagingWrongUserDesc": { + "message": "De desktopapplicatie is aangemeld bij een ander account. Zorg ervoor dat beide applicaties op hetzelfde account zijn aangemeld." + }, + "nativeMessagingWrongUserTitle": { + "message": "Accounts komt niet overeen" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrie niet ingeschakeld" + }, + "biometricsNotEnabledDesc": { + "message": "Voor browserbiometrie moet je eerst desktopbiometrie inschakelen in de instellingen." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrie niet ondersteund" + }, + "biometricsNotSupportedDesc": { + "message": "Dit apparaat ondersteunt geen browserbiometrie." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Toestemming niet verleend" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Zonder toestemming om te communiceren met de Bitwarden Desktop-applicatie, kunnen we biometrisch inloggen in de browserextensie niet leveren. Probeer het opnieuw." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Fout bij toestemmingsaanvraag" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Deze actie kan niet worden uitgevoerd in de zijbalk, probeer de actie opnieuw in de pop-up of pop-out." + }, + "personalOwnershipSubmitError": { + "message": "Wegens bedrijfsbeleid mag je geen wachtwoorden opslaan in je persoonlijke kluis. Verander het eigenaarschap naar een organisatie en kies uit een van de beschikbare collecties." + }, + "personalOwnershipPolicyInEffect": { + "message": "Een organisatiebeleid heeft invloed op je eigendomsopties." + }, + "excludedDomains": { + "message": "Uitgesloten domeinen" + }, + "excludedDomainsDesc": { + "message": "Bitwarden zal voor deze domeinen niet vragen om inloggegevens op te slaan. Je moet de pagina vernieuwen om de wijzigingen toe te passen." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is geen geldig domein", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Sends zoeken", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Send toevoegen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Tekst" + }, + "sendTypeFile": { + "message": "Bestand" + }, + "allSends": { + "message": "Alle Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maximum aantal keren benaderd", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Verlopen" + }, + "pendingDeletion": { + "message": "Wordt verwijderd" + }, + "passwordProtected": { + "message": "Beveiligd met wachtwoord" + }, + "copySendLink": { + "message": "Send-link kopiëren", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Wachtwoord verwijderen" + }, + "delete": { + "message": "Verwijderen" + }, + "removedPassword": { + "message": "Verwijderd wachtwoord" + }, + "deletedSend": { + "message": "Verwijderde Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send-link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Uitgeschakeld" + }, + "removePasswordConfirmation": { + "message": "Weet je zeker dat je het wachtwoord wilt verwijderen?" + }, + "deleteSend": { + "message": "Send verwijderen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Weet je zeker dat je deze Send wilt verwijderen?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send bewerken", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Wat voor soort Send is dit?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Een vriendelijke naam om deze Send te beschrijven.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Het bestand dat je wilt versturen." + }, + "deletionDate": { + "message": "Verwijderingsdatum" + }, + "deletionDateDesc": { + "message": "Deze Send wordt op de aangegeven datum en tijd definitief verwijderd.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Vervaldatum" + }, + "expirationDateDesc": { + "message": "Als dit is ingesteld verloopt deze Send op een specifieke datum en tijd.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dag" + }, + "days": { + "message": "$DAYS$ dagen", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Aangepast" + }, + "maximumAccessCount": { + "message": "Maximum toegangsaantal" + }, + "maximumAccessCountDesc": { + "message": "Als dit is ingesteld kunnen gebruikers deze Send niet meer benaderen zodra het maximale aantal toegang is bereikt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Vereis optioneel een wachtwoord voor gebruikers om toegang te krijgen tot deze Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privénotities over deze Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Schakel deze Send uit zodat niemand hem kan benaderen.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kopieer de link van deze Send bij het opslaan naar het klembord.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "De tekst die je wilt versturen." + }, + "sendHideText": { + "message": "De tekst van deze Send standaard verbergen.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Huidige toegangsaantal" + }, + "createSend": { + "message": "Nieuwe Send aanmaken", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nieuw wachtwoord" + }, + "sendDisabled": { + "message": "Send uitgeschakeld", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Als gevolg van een ondernemingsbeleid kun je alleen een bestaande Send verwijderen.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send aangemaakt", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send bewerkt", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Om een bestand te kiezen open je de extensie in de zijbalk (indien mogelijk) of pop-out naar een nieuw venster door op deze banner te klikken." + }, + "sendFirefoxFileWarning": { + "message": "Om een bestand te kiezen met Firefox, open je de extensie in de zijbalk of als pop-up in een nieuw venster door op deze banner te klikken." + }, + "sendSafariFileWarning": { + "message": "Om een bestand te kiezen met Safari, open je een nieuw pop-up-venster door op deze banner te klikken." + }, + "sendFileCalloutHeader": { + "message": "Voor je begint" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Om een datumkiezer in kalenderstijl te gebruiken", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klik hier", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "om een pop-up te openen.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "De opgegeven vervaldatum is niet geldig." + }, + "deletionDateIsInvalid": { + "message": "De opgegeven verwijderdatum is niet geldig." + }, + "expirationDateAndTimeRequired": { + "message": "Een vervaldatum en -tijd zijn vereist." + }, + "deletionDateAndTimeRequired": { + "message": "Een verwijderingsdatum en -tijd zijn vereist." + }, + "dateParsingError": { + "message": "Er is een fout opgetreden bij het opslaan van je verwijder- en vervaldatum." + }, + "hideEmail": { + "message": "Verberg mijn e-mailadres voor ontvangers." + }, + "sendOptionsPolicyInEffect": { + "message": "Een of meer organisatiebeleidseisen heeft invloed op de mogelijkheden van je Send." + }, + "passwordPrompt": { + "message": "Hoofdwachtwoord opnieuw vragen" + }, + "passwordConfirmation": { + "message": "Hoofdwachtwoord bevestigen" + }, + "passwordConfirmationDesc": { + "message": "Deze actie is beveiligd. Voer je hoofdwachtwoord opnieuw in om je identiteit vast te stellen en door te gaan." + }, + "emailVerificationRequired": { + "message": "E-mailverificatie vereist" + }, + "emailVerificationRequiredDesc": { + "message": "Je moet je e-mailadres verifiëren om deze functie te gebruiken. Je kunt je e-mailadres verifiëren in de kluis." + }, + "updatedMasterPassword": { + "message": "Hoofdwachtwoord bijgewerkt" + }, + "updateMasterPassword": { + "message": "Hoofdwachtwoord bijgewerken" + }, + "updateMasterPasswordWarning": { + "message": "Je hoofdwachtwoord is onlangs veranderd door een beheerder in jouw organisatie. Om toegang te krijgen tot de kluis, moet je deze nu bijwerken. Doorgaan zal je huidige sessie uitloggen, waarna je opnieuw moet inloggen. Actieve sessies op andere apparaten blijven mogelijk nog een uur actief." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatische inschrijving" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Deze organisatie heeft een ondernemingsbeleid dat je automatisch inschrijft bij het resetten van je wachtwoord. Inschrijving stelt organisatiebeheerders in staat om je hoofdwachtwoord te wijzigen." + }, + "selectFolder": { + "message": "Map selecteren..." + }, + "ssoCompleteRegistration": { + "message": "Voor het inloggen met SSO moet je een hoofdwachtwoord instellen voor toegang tot en bescherming van je kluis." + }, + "hours": { + "message": "Uren" + }, + "minutes": { + "message": "Minuten" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Het beleid van je organisatie heeft invloed op de time-out van je kluis. De maximaal toegestane kluis time-out is $HOURS$ uur en $MINUTES$ minuten.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Je kluis time-out is hoger dan het maximum van jouw organisatie." + }, + "vaultExportDisabled": { + "message": "Kluis exporteren uitgeschakeld" + }, + "personalVaultExportPolicyInEffect": { + "message": "Organisatiebeleid voorkomt dat je je persoonlijke kluis exporteert." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Kan geen geldig formulierelement identificeren. Probeer in plaats daarvan de HTML te inspecteren." + }, + "copyCustomFieldNameNotUnique": { + "message": "Geen unieke id gevonden." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ gebruikt SSO met een zelf gehoste sleutelserver. Leden van deze organisatie kunnen inloggen zonder hoofdwachtwoord.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Organisatie verlaten" + }, + "removeMasterPassword": { + "message": "Hoofdwachtwoord verwijderen" + }, + "removedMasterPassword": { + "message": "Hoofdwachtwoord verwijderd." + }, + "leaveOrganizationConfirmation": { + "message": "Weet je zeker dat je deze organisatie wilt verlaten?" + }, + "leftOrganization": { + "message": "Je hebt de organisatie verlaten." + }, + "toggleCharacterCount": { + "message": "Tekentelling in-/uitschakelen" + }, + "sessionTimeout": { + "message": "Je sessie is verlopen. Ga terug en probeer opnieuw in te loggen." + }, + "exportingPersonalVaultTitle": { + "message": "Persoonlijke kluis exporteren" + }, + "exportingPersonalVaultDescription": { + "message": "Exporteert alleen de persoonlijke kluis-items gerelateerd aan $EMAIL$. Geen kluis-items van de organisatie.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Fout" + }, + "regenerateUsername": { + "message": "Gebruikersnaam opnieuw genereren" + }, + "generateUsername": { + "message": "Gebruikersnamen genereren" + }, + "usernameType": { + "message": "Type gebruikersnaam" + }, + "plusAddressedEmail": { + "message": "E-mailadres-met-plus", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Gebruik de subadressen van je e-mailprovider." + }, + "catchallEmail": { + "message": "Catch-all e-mail" + }, + "catchallEmailDesc": { + "message": "Gebruik de catch-all inbox van je domein." + }, + "random": { + "message": "Willekeurig" + }, + "randomWord": { + "message": "Willekeurig woord" + }, + "websiteName": { + "message": "Websitenaam" + }, + "whatWouldYouLikeToGenerate": { + "message": "Wat wil je genereren?" + }, + "passwordType": { + "message": "Type wachtwoord" + }, + "service": { + "message": "Dienst" + } +} diff --git a/apps/browser/src/_locales/nn/messages.json b/apps/browser/src/_locales/nn/messages.json new file mode 100644 index 0000000000..c0fc9f75c3 --- /dev/null +++ b/apps/browser/src/_locales/nn/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "A secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "login": { + "message": "Log In" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "Cancel" + }, + "close": { + "message": "Close" + }, + "submit": { + "message": "Submit" + }, + "emailAddress": { + "message": "Email Address" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "Tab" + }, + "myVault": { + "message": "My Vault" + }, + "tools": { + "message": "Tools" + }, + "settings": { + "message": "Settings" + }, + "currentTab": { + "message": "Current Tab" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number" + }, + "copySecurityCode": { + "message": "Copy Security Code" + }, + "autoFill": { + "message": "Auto-fill" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "No matching logins." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "There are no logins available to auto-fill for the current browser tab." + }, + "addLogin": { + "message": "Add a Login" + }, + "addItem": { + "message": "Add Item" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "continue": { + "message": "Continue" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Account" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "logOut": { + "message": "Log Out" + }, + "about": { + "message": "About" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Save" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Add Folder" + }, + "name": { + "message": "Name" + }, + "editFolder": { + "message": "Edit Folder" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "folders": { + "message": "Folders" + }, + "noFolders": { + "message": "There are no folders to list." + }, + "helpFeedback": { + "message": "Help & Feedback" + }, + "sync": { + "message": "Sync" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "Bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "Select" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "Options" + }, + "length": { + "message": "Length" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "Search vault" + }, + "edit": { + "message": "Edit" + }, + "view": { + "message": "View" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "Favorite" + }, + "notes": { + "message": "Notes" + }, + "note": { + "message": "Note" + }, + "editItem": { + "message": "Edit Item" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Delete Item" + }, + "viewItem": { + "message": "View Item" + }, + "launch": { + "message": "Launch" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "Manage" + }, + "other": { + "message": "Other" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Browser Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "errorOccurred": { + "message": "An error has occurred" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected item on this page. Copy and paste the information instead." + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "nameRequired": { + "message": "Name is required." + }, + "addedFolder": { + "message": "Added folder" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "passwordCopied": { + "message": "Password copied" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Save" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Update" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "Shared" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Share" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "Attachments" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "No attachments." + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "Expiration" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "Login" + }, + "typeLogins": { + "message": "Logins" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Favorites" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/pl/messages.json b/apps/browser/src/_locales/pl/messages.json new file mode 100644 index 0000000000..64351f4ac0 --- /dev/null +++ b/apps/browser/src/_locales/pl/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - darmowy menedżer haseł", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bezpieczny i darmowy menedżer haseł dla wszystkich Twoich urządzeń.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Zaloguj się lub utwórz nowe konto, aby uzyskać dostęp do Twojego bezpiecznego sejfu." + }, + "createAccount": { + "message": "Utwórz konto" + }, + "login": { + "message": "Zaloguj się" + }, + "enterpriseSingleSignOn": { + "message": "Logowanie jednokrotne" + }, + "cancel": { + "message": "Anuluj" + }, + "close": { + "message": "Zamknij" + }, + "submit": { + "message": "Wyślij" + }, + "emailAddress": { + "message": "Adres e-mail" + }, + "masterPass": { + "message": "Hasło główne" + }, + "masterPassDesc": { + "message": "Hasło główne zapewnia dostęp do sejfu. To bardzo ważne, aby je pamiętać, ponieważ zapomnianego hasła nie będzie można odzyskać." + }, + "masterPassHintDesc": { + "message": "Podpowiedź do hasła głównego może pomóc Ci przypomnieć hasło, jeśli je zapomnisz." + }, + "reTypeMasterPass": { + "message": "Wpisz ponownie hasło główne" + }, + "masterPassHint": { + "message": "Podpowiedź do hasła głównego (opcjonalnie)" + }, + "tab": { + "message": "Karta" + }, + "myVault": { + "message": "Mój sejf" + }, + "tools": { + "message": "Narzędzia" + }, + "settings": { + "message": "Ustawienia" + }, + "currentTab": { + "message": "Obecna karta" + }, + "copyPassword": { + "message": "Kopiuj hasło" + }, + "copyNote": { + "message": "Kopiuj notatkę" + }, + "copyUri": { + "message": "Kopiuj URI" + }, + "copyUsername": { + "message": "Kopiuj nazwę użytkownika" + }, + "copyNumber": { + "message": "Kopiuj numer" + }, + "copySecurityCode": { + "message": "Kopiuj kod zabezpieczający" + }, + "autoFill": { + "message": "Autouzupełnianie" + }, + "generatePasswordCopied": { + "message": "Generuj hasło (do schowka)" + }, + "copyElementIdentifier": { + "message": "Kopiuj nazwę pola niestandardowego" + }, + "noMatchingLogins": { + "message": "Brak pasujących danych logowania." + }, + "unlockVaultMenu": { + "message": "Odblokuj sejf" + }, + "loginToVaultMenu": { + "message": "Zaloguj się do sejfu" + }, + "autoFillInfo": { + "message": "Brak dostępnych danych logowania do autouzupełnienia dla obecnej karty przeglądarki." + }, + "addLogin": { + "message": "Dodaj dane logowania" + }, + "addItem": { + "message": "Dodaj element" + }, + "passwordHint": { + "message": "Podpowiedź do hasła" + }, + "enterEmailToGetHint": { + "message": "Wpisz adres e-mail powiązany z kontem, aby otrzymać podpowiedź do hasła głównego." + }, + "getMasterPasswordHint": { + "message": "Uzyskaj podpowiedź do hasła głównego" + }, + "continue": { + "message": "Kontynuuj" + }, + "sendVerificationCode": { + "message": "Wyślij kod weryfikacyjny na adres e-mail" + }, + "sendCode": { + "message": "Wyślij kod" + }, + "codeSent": { + "message": "Kod został wysłany" + }, + "verificationCode": { + "message": "Kod weryfikacyjny" + }, + "confirmIdentity": { + "message": "Potwierdź swoją tożsamość, aby kontynuować." + }, + "account": { + "message": "Konto" + }, + "changeMasterPassword": { + "message": "Zmień hasło główne" + }, + "fingerprintPhrase": { + "message": "Unikalny identyfikator konta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Unikalny identyfikator Twojego konta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Logowanie dwustopniowe" + }, + "logOut": { + "message": "Wyloguj się" + }, + "about": { + "message": "O aplikacji" + }, + "version": { + "message": "Wersja" + }, + "save": { + "message": "Zapisz" + }, + "move": { + "message": "Przenieś" + }, + "addFolder": { + "message": "Dodaj folder" + }, + "name": { + "message": "Nazwa" + }, + "editFolder": { + "message": "Edytuj folder" + }, + "deleteFolder": { + "message": "Usuń folder" + }, + "folders": { + "message": "Foldery" + }, + "noFolders": { + "message": "Brak folderów do wyświetlenia." + }, + "helpFeedback": { + "message": "Pomoc i opinie" + }, + "sync": { + "message": "Synchronizacja" + }, + "syncVaultNow": { + "message": "Synchronizuj sejf" + }, + "lastSync": { + "message": "Ostatnia synchronizacja:" + }, + "passGen": { + "message": "Generator hasła" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatycznie wygeneruj silne, unikatowe hasła dla swoich loginów." + }, + "bitWebVault": { + "message": "Sejf internetowy Bitwarden" + }, + "importItems": { + "message": "Importuj elementy" + }, + "select": { + "message": "Wybierz" + }, + "generatePassword": { + "message": "Generuj hasło" + }, + "regeneratePassword": { + "message": "Wygeneruj hasło ponownie" + }, + "options": { + "message": "Opcje" + }, + "length": { + "message": "Długość" + }, + "uppercase": { + "message": "Wielkie litery (A-Z)" + }, + "lowercase": { + "message": "Małe litery (a-z)" + }, + "numbers": { + "message": "Cyfry (0-9)" + }, + "specialCharacters": { + "message": "Znaki specjalne (!@#$%^&*)" + }, + "numWords": { + "message": "Liczba słów" + }, + "wordSeparator": { + "message": "Separator słów" + }, + "capitalize": { + "message": "Wielkie litery", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Uwzględnij cyfry" + }, + "minNumbers": { + "message": "Minimalna liczba cyfr" + }, + "minSpecial": { + "message": "Minimalna liczba znaków specjalnych" + }, + "avoidAmbChar": { + "message": "Unikaj niejednoznacznych znaków" + }, + "searchVault": { + "message": "Szukaj w sejfie" + }, + "edit": { + "message": "Edytuj" + }, + "view": { + "message": "Zobacz" + }, + "noItemsInList": { + "message": "Brak elementów." + }, + "itemInformation": { + "message": "Informacje o elemencie" + }, + "username": { + "message": "Nazwa użytkownika" + }, + "password": { + "message": "Hasło" + }, + "passphrase": { + "message": "Hasło wyrazowe" + }, + "favorite": { + "message": "Ulubione" + }, + "notes": { + "message": "Notatki" + }, + "note": { + "message": "Notatka" + }, + "editItem": { + "message": "Edytuj element" + }, + "folder": { + "message": "Folder" + }, + "deleteItem": { + "message": "Usuń element" + }, + "viewItem": { + "message": "Zobacz element" + }, + "launch": { + "message": "Uruchom" + }, + "website": { + "message": "Strona" + }, + "toggleVisibility": { + "message": "Pokaż / Ukryj" + }, + "manage": { + "message": "Zarządzaj" + }, + "other": { + "message": "Inne" + }, + "rateExtension": { + "message": "Oceń rozszerzenie" + }, + "rateExtensionDesc": { + "message": "Wesprzyj nas pozytywną opinią!" + }, + "browserNotSupportClipboard": { + "message": "Przeglądarka nie obsługuje łatwego kopiowania schowka. Skopiuj element ręcznie." + }, + "verifyIdentity": { + "message": "Zweryfikuj tożsamość" + }, + "yourVaultIsLocked": { + "message": "Sejf jest zablokowany. Zweryfikuj swoją tożsamość, aby kontynuować." + }, + "unlock": { + "message": "Odblokuj" + }, + "loggedInAsOn": { + "message": "Zalogowano jako $EMAIL$ do $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Hasło główne jest nieprawidłowe" + }, + "vaultTimeout": { + "message": "Blokowanie sejfu" + }, + "lockNow": { + "message": "Zablokuj" + }, + "immediately": { + "message": "Natychmiast" + }, + "tenSeconds": { + "message": "10 sekund" + }, + "twentySeconds": { + "message": "20 sekund" + }, + "thirtySeconds": { + "message": "30 sekund" + }, + "oneMinute": { + "message": "1 minuta" + }, + "twoMinutes": { + "message": "2 minuty" + }, + "fiveMinutes": { + "message": "5 minut" + }, + "fifteenMinutes": { + "message": "15 minut" + }, + "thirtyMinutes": { + "message": "30 minut" + }, + "oneHour": { + "message": "1 godzina" + }, + "fourHours": { + "message": "4 godziny" + }, + "onLocked": { + "message": "Po zablokowaniu komputera" + }, + "onRestart": { + "message": "Po restarcie przeglądarki" + }, + "never": { + "message": "Nigdy" + }, + "security": { + "message": "Zabezpieczenia" + }, + "errorOccurred": { + "message": "Wystąpił błąd" + }, + "emailRequired": { + "message": "Adres e-mail jest wymagany." + }, + "invalidEmail": { + "message": "Adres e-mail jest nieprawidłowy." + }, + "masterPassRequired": { + "message": "Hasło główne jest wymagane." + }, + "masterPassLength": { + "message": "Hasło główne musi zawierać co najmniej 8 znaków." + }, + "masterPassDoesntMatch": { + "message": "Hasła nie pasują do siebie." + }, + "newAccountCreated": { + "message": "Konto zostało utworzone! Teraz możesz się zalogować." + }, + "masterPassSent": { + "message": "Wysłaliśmy Tobie wiadomość e-mail z podpowiedzią do hasła głównego." + }, + "verificationCodeRequired": { + "message": "Kod weryfikacyjny jest wymagany." + }, + "invalidVerificationCode": { + "message": "Kod weryfikacyjny jest nieprawidłowy" + }, + "valueCopied": { + "message": "Skopiowano $VALUE$", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Nie można zastosować autouzupełnienia na tej stronie. Skopiuj i wklej informacje ręcznie." + }, + "loggedOut": { + "message": "Wylogowano" + }, + "loginExpired": { + "message": "Twoja sesja wygasła." + }, + "logOutConfirmation": { + "message": "Czy na pewno chcesz się wylogować?" + }, + "yes": { + "message": "Tak" + }, + "no": { + "message": "Nie" + }, + "unexpectedError": { + "message": "Wystąpił nieoczekiwany błąd." + }, + "nameRequired": { + "message": "Nazwa jest wymagana." + }, + "addedFolder": { + "message": "Folder został dodany" + }, + "changeMasterPass": { + "message": "Zmień hasło główne" + }, + "changeMasterPasswordConfirmation": { + "message": "Hasło główne możesz zmienić na stronie sejfu bitwarden.com. Czy chcesz przejść do tej strony?" + }, + "twoStepLoginConfirmation": { + "message": "Logowanie dwustopniowe sprawia, że konto jest bardziej bezpieczne poprzez wymuszenie potwierdzenia logowania z innego urządzenia, takiego jak z klucza bezpieczeństwa, aplikacji uwierzytelniającej, wiadomości SMS, telefonu lub adresu e-mail. Logowanie dwustopniowe możesz włączyć w sejfie internetowym bitwarden.com. Czy chcesz przejść do tej strony?" + }, + "editedFolder": { + "message": "Folder został zaktualizowany" + }, + "deleteFolderConfirmation": { + "message": "Czy na pewno chcesz usunąć ten folder?" + }, + "deletedFolder": { + "message": "Folder został usunięty" + }, + "gettingStartedTutorial": { + "message": "Samouczek" + }, + "gettingStartedTutorialVideo": { + "message": "Obejrzyj samouczek, aby dowiedzieć się, jak najlepiej wykorzystać rozszerzenie przeglądarki." + }, + "syncingComplete": { + "message": "Synchronizacja została zakończona" + }, + "syncingFailed": { + "message": "Synchronizacja nie powiodła się" + }, + "passwordCopied": { + "message": "Hasło zostało skopiowane" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nowy URI" + }, + "addedItem": { + "message": "Element został dodany" + }, + "editedItem": { + "message": "Element został zaktualizowany" + }, + "deleteItemConfirmation": { + "message": "Czy na pewno chcesz to usunąć?" + }, + "deletedItem": { + "message": "Element został przeniesiony do kosza" + }, + "overwritePassword": { + "message": "Zastąp hasło" + }, + "overwritePasswordConfirmation": { + "message": "Czy na pewno chcesz zastąpić obecne hasło?" + }, + "overwriteUsername": { + "message": "Nadpisz nazwę użytkownika" + }, + "overwriteUsernameConfirmation": { + "message": "Czy na pewno chcesz nadpisać aktualną nazwę użytkownika?" + }, + "searchFolder": { + "message": "Szukaj w folderze" + }, + "searchCollection": { + "message": "Szukaj w kolekcji" + }, + "searchType": { + "message": "Szukaj elementu" + }, + "noneFolder": { + "message": "Nieprzypisane", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Wyłącz powiadomienia automatycznego logowania" + }, + "addLoginNotificationDesc": { + "message": "\"Dodaj powiadomienia logowania\" automatycznie wyświetla monit o zapisanie nowych danych logowania do sejfu przy każdym pierwszym logowaniu." + }, + "dontShowCardsCurrentTab": { + "message": "Nie pokazuj kart w zakładce \"Obecna karta\"" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Karty zapisane w sejfie są wyświetlane w zakładce \"Obecna karta\"." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Nie pokazuj tożsamości w zakładce \"Obecna karta\"" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Tożsamości zapisane w sejfie są wyświetlane w zakładce \"Obecna karta\"." + }, + "clearClipboard": { + "message": "Wyczyść schowek", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatycznie wyczyść skopiowaną wartość ze schowka.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Czy Bitwarden powinien zapisać dla Ciebie to hasło?" + }, + "notificationAddSave": { + "message": "Zapisz" + }, + "disableChangedPasswordNotification": { + "message": "Wyłącz powiadomienie o zmianie hasła" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Powiadomienie o zmianie hasła\" automatycznie zapyta Cię o zaktualizowanie hasła w sejfie za każdym razem, gdy wykryje zmianę hasła na danej stronie." + }, + "notificationChangeDesc": { + "message": "Czy chcesz zaktualizować to hasło w Bitwarden?" + }, + "notificationChangeSave": { + "message": "Zaktualizuj" + }, + "disableContextMenuItem": { + "message": "Wyłącz opcje menu kontekstowego" + }, + "disableContextMenuItemDesc": { + "message": "Opcje menu kontekstowego zapewniają szybki dostęp do generowania haseł oraz do danych logowania dla obecnej karty." + }, + "defaultUriMatchDetection": { + "message": "Domyślne wykrywanie dopasowania", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Wybierz domyślny sposób wykrywania dopasowania adresów dla czynności takich jak autouzupełnianie." + }, + "theme": { + "message": "Motyw" + }, + "themeDesc": { + "message": "Zmień motyw kolorystyczny aplikacji." + }, + "dark": { + "message": "Ciemny", + "description": "Dark color" + }, + "light": { + "message": "Jasny", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Eksportuj sejf" + }, + "fileFormat": { + "message": "Format pliku" + }, + "warning": { + "message": "UWAGA", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potwierdź eksportowanie sejfu" + }, + "exportWarningDesc": { + "message": "Plik zawiera dane sejfu w niezaszyfrowanym formacie. Nie powinieneś go przechowywać, ani przesyłać poprzez niezabezpieczone kanały (takie jak poczta e-mail). Skasuj go natychmiast po użyciu." + }, + "encExportKeyWarningDesc": { + "message": "Dane eksportu zostaną zaszyfrowane za pomocą klucza szyfrowania konta. Jeśli kiedykolwiek zmienisz ten klucz, wyeksportuj dane ponownie, ponieważ nie będziesz w stanie odszyfrować tego pliku." + }, + "encExportAccountWarningDesc": { + "message": "Klucze szyfrowania konta są unikalne dla każdego użytkownika Bitwarden, więc nie możesz zaimportować zaszyfrowanego pliku eksportu na inne konto." + }, + "exportMasterPassword": { + "message": "Wpisz hasło główne, aby wyeksportować dane z sejfu." + }, + "shared": { + "message": "Udostępnione" + }, + "learnOrg": { + "message": "Dowiedz się więcej o organizacjach" + }, + "learnOrgConfirmation": { + "message": "Bitwarden pozwala na udostępnianie zawartości sejfu innym osobom za pośrednictwem organizacji. Czy chcesz odwiedzić stronę bitwarden.com, aby dowiedzieć się więcej?" + }, + "moveToOrganization": { + "message": "Przenieś do organizacji" + }, + "share": { + "message": "Udostępnij" + }, + "movedItemToOrg": { + "message": "Element $ITEMNAME$ został przeniesiony do organizacji $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Wybierz organizację, do której chcesz przenieść ten element. Ta czynność spowoduje utratę własności elementu i przenosi te uprawnienia do organizacji." + }, + "learnMore": { + "message": "Dowiedz się więcej" + }, + "authenticatorKeyTotp": { + "message": "Klucz uwierzytelniający (TOTP)" + }, + "verificationCodeTotp": { + "message": "Kod weryfikacyjny (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopiuj kod weryfikacyjny" + }, + "attachments": { + "message": "Załączniki" + }, + "deleteAttachment": { + "message": "Usuń załącznik" + }, + "deleteAttachmentConfirmation": { + "message": "Czy na pewno chcesz usunąć ten załącznik?" + }, + "deletedAttachment": { + "message": "Załącznik został usunięty" + }, + "newAttachment": { + "message": "Dodaj załącznik" + }, + "noAttachments": { + "message": "Brak załączników." + }, + "attachmentSaved": { + "message": "Załącznik został zapisany." + }, + "file": { + "message": "Plik" + }, + "selectFile": { + "message": "Wybierz plik." + }, + "maxFileSize": { + "message": "Maksymalny rozmiar pliku to 500 MB." + }, + "featureUnavailable": { + "message": "Funkcja jest niedostępna" + }, + "updateKey": { + "message": "Nie możesz używać tej funkcji, dopóki nie zaktualizujesz klucza szyfrowania." + }, + "premiumMembership": { + "message": "Konto Premium" + }, + "premiumManage": { + "message": "Zarządzaj kontem Premium" + }, + "premiumManageAlert": { + "message": "Kontem Premium możesz zarządzać na stronie sejfu bitwarden.com. Czy chcesz otworzyć tę stronę?" + }, + "premiumRefresh": { + "message": "Odśwież konto Premium" + }, + "premiumNotCurrentMember": { + "message": "Nie posiadasz obecnie konta Premium." + }, + "premiumSignUpAndGet": { + "message": "Zarejestruj konto Premium, aby otrzymać:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB miejsca na zaszyfrowane załączniki." + }, + "ppremiumSignUpTwoStep": { + "message": "Dodatkowe opcje logowania dwustopniowego, takie jak klucze YubiKey, FIDO U2F oraz Duo." + }, + "ppremiumSignUpReports": { + "message": "Raporty bezpieczeństwa haseł, stanu konta i raporty wycieków danych, aby Twoje dane były bezpieczne." + }, + "ppremiumSignUpTotp": { + "message": "Generator kodów weryfikacyjnych TOTP (2FA) dla danych logowania w Twoim sejfie." + }, + "ppremiumSignUpSupport": { + "message": "Priorytetowe wsparcie klienta." + }, + "ppremiumSignUpFuture": { + "message": "Wszystkie przyszłe funkcje premium. Więcej już wkrótce!" + }, + "premiumPurchase": { + "message": "Kup konto Premium" + }, + "premiumPurchaseAlert": { + "message": "Konto Premium możesz zakupić na stronie sejfu bitwarden.com. Czy chcesz otworzyć tę stronę?" + }, + "premiumCurrentMember": { + "message": "Posiadasz konto Premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Dziękujemy za wspieranie Bitwarden." + }, + "premiumPrice": { + "message": "Wszystko to jedynie za $PRICE$ /rok!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Odświeżanie zostało zakończone" + }, + "disableAutoTotpCopy": { + "message": "Wyłącz automatyczne kopiowanie kodu TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Jeśli dane logowania posiadają dołączony klucz uwierzytelniający TOTP, kod weryfikacyjny jest automatycznie kopiowany do schowka przy każdym autouzupełnianiu danych logowania." + }, + "disableAutoBiometricsPrompt": { + "message": "Zapamiętaj autoryzację biometryczną" + }, + "premiumRequired": { + "message": "Konto Premium jest wymagane" + }, + "premiumRequiredDesc": { + "message": "Konto Premium jest wymagane, aby skorzystać z tej funkcji." + }, + "enterVerificationCodeApp": { + "message": "Wpisz 6-cyfrowy kod weryfikacyjny z aplikacji uwierzytelniającej." + }, + "enterVerificationCodeEmail": { + "message": "Wpisz 6-cyfrowy kod weryfikacyjny, który został przesłany na adres $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Kod weryfikacyjny został wysłany na adres $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamiętaj mnie" + }, + "sendVerificationCodeEmailAgain": { + "message": "Wyślij ponownie wiadomość z kodem weryfikacyjnym" + }, + "useAnotherTwoStepMethod": { + "message": "Użyj innej metody logowania dwustopniowego" + }, + "insertYubiKey": { + "message": "Włóż klucz YubiKey do portu USB komputera, a następnie dotknij jego przycisku." + }, + "insertU2f": { + "message": "Włóż klucz bezpieczeństwa do portu USB komputera. Jeśli klucz posiada przycisk, dotknij go." + }, + "webAuthnNewTab": { + "message": "Kontynuuj logowanie dwustopniowe WebAuthn w nowej karcie." + }, + "webAuthnNewTabOpen": { + "message": "Otwórz nową kartę" + }, + "webAuthnAuthenticate": { + "message": "Uwierzytelnianie WebAuthn" + }, + "loginUnavailable": { + "message": "Logowanie jest niedostępne" + }, + "noTwoStepProviders": { + "message": "Konto posiada włączoną opcję logowania dwustopniowego, jednak ta przeglądarka nie wspiera żadnego ze skonfigurowanych mechanizmów autoryzacji dwustopniowej." + }, + "noTwoStepProviders2": { + "message": "Proszę użyć obsługiwanej przeglądarki (takiej jak Chrome) i/lub dodać dodatkowych dostawców, którzy są lepiej wspierani przez przeglądarki internetowe (np. aplikacja uwierzytelniająca)." + }, + "twoStepOptions": { + "message": "Opcje logowania dwustopniowego" + }, + "recoveryCodeDesc": { + "message": "Utraciłeś dostęp do wszystkich swoich mechanizmów dwustopniowego logowania? Użyj kodów odzyskiwania, aby wyłączyć dwustopniowe logowanie na Twoim koncie." + }, + "recoveryCodeTitle": { + "message": "Kod odzyskiwania" + }, + "authenticatorAppTitle": { + "message": "Aplikacja uwierzytelniająca" + }, + "authenticatorAppDesc": { + "message": "Użyj aplikacji mobilnej (np. Authy lub Google Authenticator) do generowania czasowych kodów weryfikacyjnych.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Klucz bezpieczeństwa YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Użyj YubiKey jako metody dostępu do konta. Działa z YubiKey 4, 4 Nano, 4C i urządzeniami NEO." + }, + "duoDesc": { + "message": "Weryfikacja z użyciem Duo Security poprzez aplikację Duo Mobile, SMS, połączenie telefoniczne lub klucz bezpieczeństwa U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Weryfikacja dostępu do Twojej organizacji z użyciem Duo Security poprzez aplikację Duo Mobile, SMS, połączenie telefoniczne lub klucz bezpieczeństwa U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Użyj dowolnego klucza bezpieczeństwa WebAuthn, aby uzyskać dostęp do swojego konta." + }, + "emailTitle": { + "message": "Adres e-mail" + }, + "emailDesc": { + "message": "Kody weryfikacyjne zostaną wysłane do Ciebie wiadomością e-mail." + }, + "selfHostedEnvironment": { + "message": "Samodzielnie hostowane środowisko" + }, + "selfHostedEnvironmentFooter": { + "message": "Wpisz podstawowy adres URL hostowanej instalacji Bitwarden." + }, + "customEnvironment": { + "message": "Niestandardowe środowisko" + }, + "customEnvironmentFooter": { + "message": "Dla zaawansowanych użytkowników. Możesz wpisać podstawowy adres URL niezależnie dla każdej usługi." + }, + "baseUrl": { + "message": "Adres URL serwera" + }, + "apiUrl": { + "message": "Adres URL serwera interfejsu API" + }, + "webVaultUrl": { + "message": "Adres URL serwera sejfu internetowego" + }, + "identityUrl": { + "message": "Adres URL serwera tożsamości" + }, + "notificationsUrl": { + "message": "Adres URL serwera powiadomień" + }, + "iconsUrl": { + "message": "Adres URL serwera ikon" + }, + "environmentSaved": { + "message": "Adresy URL środowiska zostały zapisane." + }, + "enableAutoFillOnPageLoad": { + "message": "Włącz autouzupełnianie po załadowaniu strony" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Jeśli zostanie wykryty formularz logowania, automatycznie uzupełnij dane logowania po załadowaniu strony." + }, + "experimentalFeature": { + "message": "Obecnie jest to funkcja eksperymentalna. Używaj na własne ryzyko." + }, + "defaultAutoFillOnPageLoad": { + "message": "Domyślne ustawienie autouzupełniania" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Po włączeniu autouzupełnianiu po załadowaniu strony, możesz włączyć lub wyłączyć tę funkcję dla poszczególnych wpisów." + }, + "itemAutoFillOnPageLoad": { + "message": "Automatycznie uzupełniaj po załadowaniu strony (jeśli włączono w opcjach)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Użyj domyślnego ustawienia" + }, + "autoFillOnPageLoadYes": { + "message": "Automatycznie uzupełniaj po załadowaniu strony" + }, + "autoFillOnPageLoadNo": { + "message": "Nie uzupełniaj automatycznie po załadowaniu strony" + }, + "commandOpenPopup": { + "message": "Otwórz sejf w oknie" + }, + "commandOpenSidebar": { + "message": "Otwórz sejf na pasku bocznym" + }, + "commandAutofillDesc": { + "message": "Autouzupełnianie korzysta z ostatnio używanych danych logowania na tej stronie." + }, + "commandGeneratePasswordDesc": { + "message": "Wygeneruj nowe losowe hasło i skopiuj je do schowka." + }, + "commandLockVaultDesc": { + "message": "Zablokuj sejf" + }, + "privateModeWarning": { + "message": "Obsługa trybu prywatnego jest eksperymentalna, a niektóre funkcje są ograniczone." + }, + "customFields": { + "message": "Pola niestandardowe" + }, + "copyValue": { + "message": "Kopiuj wartość" + }, + "value": { + "message": "Wartość" + }, + "newCustomField": { + "message": "Nowe pole niestandardowe" + }, + "dragToSort": { + "message": "Przeciągnij, aby posortować" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Pole maskowane" + }, + "cfTypeBoolean": { + "message": "Wartość logiczna" + }, + "cfTypeLinked": { + "message": "Powiązane pole", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Powiązana wartość", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Kliknięcie poza okno, w celu sprawdzenia wiadomość z kodem weryfikacyjnym spowoduje, że zostanie ono zamknięte. Czy chcesz otworzyć nowe okno tak, aby się nie zamknęło?" + }, + "popupU2fCloseMessage": { + "message": "Ta przeglądarka nie może przetworzyć żądania U2F w tym oknie. Czy chcesz otworzyć nowe okno przeglądarki, aby zalogować się przy pomocy klucza U2F?" + }, + "disableFavicon": { + "message": "Wyłącz ikony stron" + }, + "disableFaviconDesc": { + "message": "Wyświetlaj rozpoznawalną ikonę serwisu obok danych logowania w sejfie." + }, + "disableBadgeCounter": { + "message": "Wyłącz licznik logowań" + }, + "disableBadgeCounterDesc": { + "message": "Licznik informuje, ile razy zalogowałeś się na obecnej stronie w sejfie." + }, + "cardholderName": { + "message": "Właściciel karty" + }, + "number": { + "message": "Numer" + }, + "brand": { + "message": "Wydawca" + }, + "expirationMonth": { + "message": "Miesiąc wygaśnięcia" + }, + "expirationYear": { + "message": "Rok wygaśnięcia" + }, + "expiration": { + "message": "Data wygaśnięcia" + }, + "january": { + "message": "Styczeń" + }, + "february": { + "message": "Luty" + }, + "march": { + "message": "Marzec" + }, + "april": { + "message": "Kwiecień" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Czerwiec" + }, + "july": { + "message": "Lipiec" + }, + "august": { + "message": "Sierpień" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Październik" + }, + "november": { + "message": "Listopad" + }, + "december": { + "message": "Grudzień" + }, + "securityCode": { + "message": "Kod zabezpieczający" + }, + "ex": { + "message": "np." + }, + "title": { + "message": "Tytuł" + }, + "mr": { + "message": "Pan" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Pani" + }, + "dr": { + "message": "Doktor" + }, + "firstName": { + "message": "Imię" + }, + "middleName": { + "message": "Drugie imię" + }, + "lastName": { + "message": "Nazwisko" + }, + "fullName": { + "message": "Imię i nazwisko" + }, + "identityName": { + "message": "Nazwa profilu" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Numer PESEL" + }, + "passportNumber": { + "message": "Numer paszportu" + }, + "licenseNumber": { + "message": "Numer prawa jazdy" + }, + "email": { + "message": "Adres e-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adres" + }, + "address1": { + "message": "Adres 1" + }, + "address2": { + "message": "Adres 2" + }, + "address3": { + "message": "Adres 3" + }, + "cityTown": { + "message": "Miasto" + }, + "stateProvince": { + "message": "Województwo" + }, + "zipPostalCode": { + "message": "Kod pocztowy" + }, + "country": { + "message": "Kraj" + }, + "type": { + "message": "Rodzaj" + }, + "typeLogin": { + "message": "Dane logowania" + }, + "typeLogins": { + "message": "Dane logowania" + }, + "typeSecureNote": { + "message": "Bezpieczna notatka" + }, + "typeCard": { + "message": "Karta" + }, + "typeIdentity": { + "message": "Tożsamość" + }, + "passwordHistory": { + "message": "Historia haseł" + }, + "back": { + "message": "Powrót" + }, + "collections": { + "message": "Kolekcje" + }, + "favorites": { + "message": "Ulubione" + }, + "popOutNewWindow": { + "message": "Wyświetl w nowym oknie" + }, + "refresh": { + "message": "Odśwież" + }, + "cards": { + "message": "Karty" + }, + "identities": { + "message": "Tożsamości" + }, + "logins": { + "message": "Dane logowania" + }, + "secureNotes": { + "message": "Bezpieczne notatki" + }, + "clear": { + "message": "Wyczyść", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Sprawdź, czy hasło zostało ujawnione." + }, + "passwordExposed": { + "message": "To hasło znajduje się w $VALUE$ wykradzionej(ych) bazie(ach) danych. Należy je zmienić.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "To hasło nie znajduje się w żadnej znanej wykradzionej bazie danych. Powinno być bezpieczne." + }, + "baseDomain": { + "message": "Domena podstawowa", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nazwa domeny", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Dokładnie" + }, + "startsWith": { + "message": "Rozpoczyna się od" + }, + "regEx": { + "message": "Wyrażenie regularne", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Wykrywanie dopasowania", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Domyślne wykrywanie dopasowania", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Zmień opcje" + }, + "toggleCurrentUris": { + "message": "Przełącz obecny URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Obecny URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organizacja", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Rodzaje" + }, + "allItems": { + "message": "Wszystkie elementy" + }, + "noPasswordsInList": { + "message": "Brak haseł." + }, + "remove": { + "message": "Usuń" + }, + "default": { + "message": "Domyślny" + }, + "dateUpdated": { + "message": "Zaktualizowano", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Aktualizacja hasła", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Czy na pewno chcesz użyć opcji \"Nigdy\"? Ustawienie opcji blokady na \"Nigdy\" przechowuje klucz szyfrowania Twojego sejfu na urządzeniu. Jeśli używasz tej opcji upewnij się, że odpowiednio zabezpieczasz swoje urządzenie." + }, + "noOrganizationsList": { + "message": "Nie należysz do żadnej organizacji. Organizacje pozwalają na bezpieczne udostępnianie elementów innym użytkownikom." + }, + "noCollectionsInList": { + "message": "Brak kolekcji do wyświetlenia." + }, + "ownership": { + "message": "Właściciel" + }, + "whoOwnsThisItem": { + "message": "Kto jest właścicielem tego elementu?" + }, + "strong": { + "message": "Silne", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobre", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Słabe", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Słabe hasło główne" + }, + "weakMasterPasswordDesc": { + "message": "Wybrane przez Ciebie hasło główne jest słabe. Powinieneś użyć silniejszego hasła (lub frazy), aby właściwie chronić swoje konto Bitwarden. Czy na pewno chcesz użyć tego hasła głównego?" + }, + "pin": { + "message": "Kod PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Odblokuj kodem PIN" + }, + "setYourPinCode": { + "message": "Ustaw kod PIN do odblokowywania aplikacji Bitwarden. Ustawienia odblokowywania kodem PIN zostaną zresetowane po wylogowaniu." + }, + "pinRequired": { + "message": "Kod PIN jest wymagany." + }, + "invalidPin": { + "message": "Kod PIN jest nieprawidłowy." + }, + "unlockWithBiometrics": { + "message": "Odblokuj danymi biometrycznymi" + }, + "awaitDesktop": { + "message": "Oczekiwanie na potwierdzenie z aplikacji desktopowej" + }, + "awaitDesktopDesc": { + "message": "Włącz dane biometryczne w aplikacji desktopowej Bitwarden, aby włączyć tę samą funkcję w przeglądarce." + }, + "lockWithMasterPassOnRestart": { + "message": "Zablokuj hasłem głównym po uruchomieniu przeglądarki" + }, + "selectOneCollection": { + "message": "Musisz wybrać co najmniej jedną kolekcję." + }, + "cloneItem": { + "message": "Klonuj element" + }, + "clone": { + "message": "Klonuj" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji wpływa na ustawienia generatora." + }, + "vaultTimeoutAction": { + "message": "Sposób blokowania sejfu" + }, + "lock": { + "message": "Zablokuj", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Kosz", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Szukaj w koszu" + }, + "permanentlyDeleteItem": { + "message": "Usuń trwale element" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Czy na pewno chcesz usunąć trwale ten element?" + }, + "permanentlyDeletedItem": { + "message": "Element został trwale usunięty" + }, + "restoreItem": { + "message": "Przywróć element" + }, + "restoreItemConfirmation": { + "message": "Czy na pewno chcesz przywrócić ten element?" + }, + "restoredItem": { + "message": "Element został przywrócony" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Po wylogowaniu się z sejfu musisz ponownie zalogować się, aby uzyskać do niego dostęp. Czy na pewno chcesz użyć tego ustawienia?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potwierdź sposób blokowania sejfu" + }, + "autoFillAndSave": { + "message": "Automatycznie uzupełnij i zapisz" + }, + "autoFillSuccessAndSavedUri": { + "message": "URI został zapisany i automatycznie uzupełniony" + }, + "autoFillSuccess": { + "message": "Element został automatycznie uzupełniony" + }, + "setMasterPassword": { + "message": "Ustaw hasło główne" + }, + "masterPasswordPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji wymaga, aby hasło główne spełniało następujące wymagania:" + }, + "policyInEffectMinComplexity": { + "message": "Minimalny poziom złożoności wynosi $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimalna długość wynosi $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Zawiera co najmniej jedną wielką literę" + }, + "policyInEffectLowercase": { + "message": "Zawiera co najmniej jedną małą literę" + }, + "policyInEffectNumbers": { + "message": "Zawiera co najmniej jedną cyfrę" + }, + "policyInEffectSpecial": { + "message": "Zawiera co najmniej jeden następujący znak specjalny $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Nowe hasło główne nie spełnia wymaganych zasad." + }, + "acceptPolicies": { + "message": "Zaznaczając tę opcję, akceptujesz:" + }, + "acceptPoliciesError": { + "message": "Nie zaakceptowałeś regulaminu i polityki prywatności." + }, + "termsOfService": { + "message": "Regulamin" + }, + "privacyPolicy": { + "message": "Polityka prywatności" + }, + "hintEqualsPassword": { + "message": "Podpowiedź do hasła nie może być taka sama jak hasło." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Weryfikacja synchronizacji z aplikacją desktopową" + }, + "desktopIntegrationVerificationText": { + "message": "Zweryfikuj aplikację desktopową z wyświetlonym identyfikatorem: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Połączenie z przeglądarką jest wyłączone" + }, + "desktopIntegrationDisabledDesc": { + "message": "Połączenie z przeglądarką jest wyłączone. Włącz funkcję w ustawieniach aplikacji desktopowej Bitwarden." + }, + "startDesktopTitle": { + "message": "Uruchom aplikację desktopową Bitwarden" + }, + "startDesktopDesc": { + "message": "Aplikacja desktopowa Bitwarden, przed użyciem tej funkcji, musi zostać ponownie uruchomiona." + }, + "errorEnableBiometricTitle": { + "message": "Nie można włączyć danych biometrycznych" + }, + "errorEnableBiometricDesc": { + "message": "Operacja została anulowana przez aplikację desktopową" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Aplikacja desktopowa unieważniła bezpieczny kanał komunikacji. Spróbuj ponownie wykonać tę operację" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Komunikacja z aplikacją desktopową została przerwana" + }, + "nativeMessagingWrongUserDesc": { + "message": "W aplikacji desktopowej jesteś zalogowany na inne konto. Upewnij się, że w obu aplikacjach jesteś zalogowany na to same konto." + }, + "nativeMessagingWrongUserTitle": { + "message": "Konto jest niezgodne" + }, + "biometricsNotEnabledTitle": { + "message": "Dane biometryczne są wyłączone" + }, + "biometricsNotEnabledDesc": { + "message": "Aby włączyć dane biometryczne w przeglądarce, musisz włączyć tę samą funkcję w ustawianiach aplikacji desktopowej." + }, + "biometricsNotSupportedTitle": { + "message": "Dane biometryczne nie są obsługiwane" + }, + "biometricsNotSupportedDesc": { + "message": "Dane biometryczne przeglądarki nie są obsługiwane na tym urządzeniu." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Uprawnienie nie zostało przyznane" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bez uprawnienia do komunikowania się z aplikacją desktopową Bitwarden nie możemy dostarczyć obsługi danych biometrycznych w rozszerzeniu przeglądarki. Spróbuj ponownie." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Wystąpił błąd żądania uprawnienia" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Ta operacja nie może zostać wykonana na pasku bocznym. Spróbuj ponownie w nowym oknie." + }, + "personalOwnershipSubmitError": { + "message": "Ze względu na zasadę przedsiębiorstwa, nie możesz zapisywać elementów w osobistym sejfie. Zmień właściciela elementu na organizację i wybierz jedną z dostępnych kolekcji." + }, + "personalOwnershipPolicyInEffect": { + "message": "Zasada organizacji ma wpływ na opcję własności elementów." + }, + "excludedDomains": { + "message": "Wykluczone domeny" + }, + "excludedDomainsDesc": { + "message": "Aplikacja Bitwarden nie będzie proponować zapisywania danych logowania dla tych domen. Musisz odświeżyć stronę, aby zastosowywać zmiany." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ nie jest prawidłową nazwą domeny", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Wyślij", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Szukaj w wysyłkach", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Dodaj wysyłkę", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Tekst" + }, + "sendTypeFile": { + "message": "Plik" + }, + "allSends": { + "message": "Wszystkie wysyłki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maksymalna liczba dostępów została osiągnięta", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Wygasła" + }, + "pendingDeletion": { + "message": "Oczekiwanie na usunięcie" + }, + "passwordProtected": { + "message": "Chroniona hasłem" + }, + "copySendLink": { + "message": "Kopiuj link wysyłki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Usuń hasło" + }, + "delete": { + "message": "Usuń" + }, + "removedPassword": { + "message": "Hasło zostało usunięte" + }, + "deletedSend": { + "message": "Wysyłka została usunięta", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Link wysyłki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Wyłączona" + }, + "removePasswordConfirmation": { + "message": "Czy na pewno chcesz usunąć hasło?" + }, + "deleteSend": { + "message": "Usuń wysyłkę", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Czy na pewno chcesz usunąć tę wysyłkę?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edytuj wysyłkę", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Jakiego typu jest to wysyłka?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Nazwa wysyłki.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Plik, który chcesz wysłać." + }, + "deletionDate": { + "message": "Data usunięcia" + }, + "deletionDateDesc": { + "message": "Wysyłka zostanie trwale usunięta w określonym czasie.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data wygaśnięcia" + }, + "expirationDateDesc": { + "message": "Jeśli funkcja jest włączona, dostęp do wysyłki wygaśnie po określonym czasie.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dzień" + }, + "days": { + "message": "$DAYS$ dni", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Niestandardowe" + }, + "maximumAccessCount": { + "message": "Maksymalna liczba dostępów" + }, + "maximumAccessCountDesc": { + "message": "Jeśli funkcja jest włączona, po osiągnięciu maksymalnej liczby dostępów, użytkownicy nie będą mieli dostępu do tej wysyłki.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcjonalne hasło dla użytkownika, aby uzyskać dostęp do wysyłki.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Prywatne notatki o tej wysyłce.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Wyłącz wysyłkę, aby nikt nie miał do niej dostępu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Po zapisaniu wysyłki, skopiuj link do schowka.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Tekst, który chcesz wysłać." + }, + "sendHideText": { + "message": "Ukryj domyślnie tekst wysyłki.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Obecna liczba dostępów" + }, + "createSend": { + "message": "Utwórz nową wysyłkę", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nowe hasło" + }, + "sendDisabled": { + "message": "Wysyłka została wyłączona", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Ze względu na zasadę przedsiębiorstwa, tylko Ty możesz usunąć obecną wysyłkę.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Wysyłka została utworzona", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Wysyłka została zaktualizowana", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Aby wybrać plik, otwórz rozszerzenie na pasku bocznym (jeśli to możliwe) lub w nowym oknie." + }, + "sendFirefoxFileWarning": { + "message": "Aby wybrać plik za pomocą przeglądarki Firefox, otwórz rozszerzenie w nowym oknie." + }, + "sendSafariFileWarning": { + "message": "Aby wybrać plik za pomocą przeglądarki Safari, otwórz rozszerzenie w nowym oknie." + }, + "sendFileCalloutHeader": { + "message": "Zanim zaczniesz" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Aby wybrać datę, ", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "kliknij tutaj", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "w celu otwarcia rozszerzenia w oknie.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Data wygaśnięcia nie jest prawidłowa." + }, + "deletionDateIsInvalid": { + "message": "Data usunięcia nie jest prawidłowa." + }, + "expirationDateAndTimeRequired": { + "message": "Data i czas wygaśnięcia są wymagane." + }, + "deletionDateAndTimeRequired": { + "message": "Data i czas usunięcia są wymagane." + }, + "dateParsingError": { + "message": "Wystąpił błąd podczas zapisywania dat usunięcia i wygaśnięcia." + }, + "hideEmail": { + "message": "Ukryj mój adres e-mail przed odbiorcami." + }, + "sendOptionsPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji wpływa na ustawienia wysyłek." + }, + "passwordPrompt": { + "message": "Potwierdź hasłem głównym" + }, + "passwordConfirmation": { + "message": "Potwierdź hasło główne" + }, + "passwordConfirmationDesc": { + "message": "Ta operacja jest chroniona. Aby kontynuować, wpisz ponownie hasło główne." + }, + "emailVerificationRequired": { + "message": "Weryfikacja adresu e-mail jest wymagana" + }, + "emailVerificationRequiredDesc": { + "message": "Musisz zweryfikować adres e-mail, aby korzystać z tej funkcji. Adres możesz zweryfikować w sejfie internetowym." + }, + "updatedMasterPassword": { + "message": "Hasło główne zostało zaktualizowane" + }, + "updateMasterPassword": { + "message": "Zaktualizuj hasło główne" + }, + "updateMasterPasswordWarning": { + "message": "Hasło główne zostało zmienione przez administratora Twojej organizacji. Musisz je zaktualizować, aby uzyskać dostęp do sejfu. Ta czynność spowoduje wylogowanie z bieżącej sesji, przez co konieczne będzie ponowne zalogowanie się. Aktywne sesje na innych urządzeniach mogą pozostać aktywne przez maksymalnie godzinę." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatyczne rejestrowanie użytkowników do resetowania hasła" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ta organizacja posługuje się zasadą, która automatycznie rejestruje użytkowników do resetowania hasła. Rejestracja umożliwia administratorom organizacji zmianę Twojego hasła głównego." + }, + "selectFolder": { + "message": "Wybierz folder..." + }, + "ssoCompleteRegistration": { + "message": "W celu zakończenia jednokrotnego logowania SSO, ustaw hasło główne, aby uzyskać dostęp do sejfu." + }, + "hours": { + "message": "Godziny" + }, + "minutes": { + "message": "Minuty" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Zasady organizacji mają wpływ czas blokowania sejfu. Maksymalny dozwolony czas wynosi $HOURS$ godz. i $MINUTES$ min.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Czas blokowania sejfu przekracza limit określony przez organizację." + }, + "vaultExportDisabled": { + "message": "Eksportowanie sejfu zostało wyłączone" + }, + "personalVaultExportPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji uniemożliwia wyeksportowanie Twojego sejfu." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Nie można zidentyfikować poprawnego elementu formularza. Spróbuj sprawdzić kod HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nie znaleziono unikatowego identyfikatora." + }, + "convertOrganizationEncryptionDesc": { + "message": "Organizacja $ORGANIZATION$ używa jednokrotnego logowania SSO z własnym serwerem kluczy. Użytkownicy nie muszą logować się za pomocą hasła głównego.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Opuść organizację" + }, + "removeMasterPassword": { + "message": "Usuń hasło główne" + }, + "removedMasterPassword": { + "message": "Hasło główne zostało usunięte." + }, + "leaveOrganizationConfirmation": { + "message": "Czy na pewno chcesz opuścić tę organizację?" + }, + "leftOrganization": { + "message": "Nie należysz już do tej organizacji." + }, + "toggleCharacterCount": { + "message": "Pokaż / Ukryj licznik znaków" + }, + "sessionTimeout": { + "message": "Twoja sesja wygasła. Zaloguj się ponownie." + }, + "exportingPersonalVaultTitle": { + "message": "Eksportowanie osobistego sejfu" + }, + "exportingPersonalVaultDescription": { + "message": "Tylko osobiste elementy sejfu powiązane z adresem $EMAIL$ zostaną wyeksportowane. Elementy sejfu należące do organizacji nie będą uwzględnione.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Błąd" + }, + "regenerateUsername": { + "message": "Wygeneruj ponownie nazwę użytkownika" + }, + "generateUsername": { + "message": "Wygeneruj nazwę użytkownika" + }, + "usernameType": { + "message": "Rodzaj nazwy użytkownika" + }, + "plusAddressedEmail": { + "message": "Adres e-mail z plusem", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Użyj możliwości dodawania aliasów u swojego dostawcy poczty e-mail." + }, + "catchallEmail": { + "message": "Adres catch-all" + }, + "catchallEmailDesc": { + "message": "Użyj skonfigurowanej skrzynki catch-all w swojej domenie." + }, + "random": { + "message": "Losowo" + }, + "randomWord": { + "message": "Losowe słowo" + }, + "websiteName": { + "message": "Nazwa witryny" + }, + "whatWouldYouLikeToGenerate": { + "message": "Co chcesz wygenerować?" + }, + "passwordType": { + "message": "Rodzaj hasła" + }, + "service": { + "message": "Usługa" + } +} diff --git a/apps/browser/src/_locales/pt_BR/messages.json b/apps/browser/src/_locales/pt_BR/messages.json new file mode 100644 index 0000000000..3faa73af94 --- /dev/null +++ b/apps/browser/src/_locales/pt_BR/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Um gerenciador de senhas seguro e gratuito para todos os seus dispositivos.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Inicie a sessão ou crie uma nova conta para acessar seu cofre seguro." + }, + "createAccount": { + "message": "Criar Conta" + }, + "login": { + "message": "Iniciar Sessão" + }, + "enterpriseSingleSignOn": { + "message": "Iniciar Sessão Empresarial Única" + }, + "cancel": { + "message": "Cancelar" + }, + "close": { + "message": "Fechar" + }, + "submit": { + "message": "Enviar" + }, + "emailAddress": { + "message": "Endereço de E-mail" + }, + "masterPass": { + "message": "Senha Mestra" + }, + "masterPassDesc": { + "message": "A senha mestra é a senha que você usa para acessar o seu cofre. É muito importante que você não esqueça sua senha mestra. Não há maneira de recuperar a senha caso você se esqueça." + }, + "masterPassHintDesc": { + "message": "Uma dica de senha mestra pode ajudá-lo(a) a lembrá-lo(a) caso você esqueça." + }, + "reTypeMasterPass": { + "message": "Digite Novamente a Senha Mestra" + }, + "masterPassHint": { + "message": "Dica de Senha Mestra (opcional)" + }, + "tab": { + "message": "Aba" + }, + "myVault": { + "message": "Meu Cofre" + }, + "tools": { + "message": "Ferramentas" + }, + "settings": { + "message": "Configurações" + }, + "currentTab": { + "message": "Aba Atual" + }, + "copyPassword": { + "message": "Copiar Senha" + }, + "copyNote": { + "message": "Copiar Nota" + }, + "copyUri": { + "message": "Copiar URI" + }, + "copyUsername": { + "message": "Copiar Nome de Usuário" + }, + "copyNumber": { + "message": "Copiar Número" + }, + "copySecurityCode": { + "message": "Copiar Código de Segurança" + }, + "autoFill": { + "message": "Autopreencher" + }, + "generatePasswordCopied": { + "message": "Gerar Senha (copiada)" + }, + "copyElementIdentifier": { + "message": "Copiar Nome do Campo Personalizado" + }, + "noMatchingLogins": { + "message": "Sem credenciais correspondentes." + }, + "unlockVaultMenu": { + "message": "Desbloqueie seu cofre" + }, + "loginToVaultMenu": { + "message": "Acesse o seu cofre" + }, + "autoFillInfo": { + "message": "Não há credenciais disponíveis para autopreenchimento para a aba do navegador atual." + }, + "addLogin": { + "message": "Adicionar uma Credencial" + }, + "addItem": { + "message": "Adicionar Item" + }, + "passwordHint": { + "message": "Dica da Senha" + }, + "enterEmailToGetHint": { + "message": "Insira o seu endereço de e-mail para receber a dica da sua senha mestra." + }, + "getMasterPasswordHint": { + "message": "Obter dica da senha mestra" + }, + "continue": { + "message": "Continuar" + }, + "sendVerificationCode": { + "message": "Enviar um código de verificação para o seu e-mail" + }, + "sendCode": { + "message": "Enviar Código" + }, + "codeSent": { + "message": "Código Enviado" + }, + "verificationCode": { + "message": "Código de Verificação" + }, + "confirmIdentity": { + "message": "Confirme a sua identidade para continuar." + }, + "account": { + "message": "Conta" + }, + "changeMasterPassword": { + "message": "Alterar Senha Mestra" + }, + "fingerprintPhrase": { + "message": "Frase de Biometria", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "A sua frase biométrica", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Login em Duas Etapas" + }, + "logOut": { + "message": "Encerrar Sessão" + }, + "about": { + "message": "Sobre" + }, + "version": { + "message": "Versão" + }, + "save": { + "message": "Salvar" + }, + "move": { + "message": "Mover" + }, + "addFolder": { + "message": "Adicionar Pasta" + }, + "name": { + "message": "Nome" + }, + "editFolder": { + "message": "Editar Pasta" + }, + "deleteFolder": { + "message": "Excluir Pasta" + }, + "folders": { + "message": "Pastas" + }, + "noFolders": { + "message": "Não existem pastas para listar." + }, + "helpFeedback": { + "message": "Ajuda & Feedback" + }, + "sync": { + "message": "Sincronizar" + }, + "syncVaultNow": { + "message": "Sincronizar Cofre Agora" + }, + "lastSync": { + "message": "Última Sincronização:" + }, + "passGen": { + "message": "Gerador de Senha" + }, + "generator": { + "message": "Gerador", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Gere automaticamente senhas fortes e únicas para as suas credenciais." + }, + "bitWebVault": { + "message": "Cofre Web do Bitwarden" + }, + "importItems": { + "message": "Importar Itens" + }, + "select": { + "message": "Selecionar" + }, + "generatePassword": { + "message": "Gerar Senha" + }, + "regeneratePassword": { + "message": "Gerar Nova Senha" + }, + "options": { + "message": "Opções" + }, + "length": { + "message": "Comprimento" + }, + "uppercase": { + "message": "Maiúsculas (A-Z)" + }, + "lowercase": { + "message": "Minúsculas (a-z)" + }, + "numbers": { + "message": "Números (0-9)" + }, + "specialCharacters": { + "message": "Caracteres Especiais (!@#$%^&*)" + }, + "numWords": { + "message": "Número de Palavras" + }, + "wordSeparator": { + "message": "Separador de Palavra" + }, + "capitalize": { + "message": "Iniciais em Maiúsculas", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Incluir Número" + }, + "minNumbers": { + "message": "Mínimo de Números" + }, + "minSpecial": { + "message": "Mínimo Especial" + }, + "avoidAmbChar": { + "message": "Evitar Caracteres Ambíguos" + }, + "searchVault": { + "message": "Pesquisar no Cofre" + }, + "edit": { + "message": "Editar" + }, + "view": { + "message": "Ver" + }, + "noItemsInList": { + "message": "Não há itens para listar." + }, + "itemInformation": { + "message": "Informação do Item" + }, + "username": { + "message": "Nome de Usuário" + }, + "password": { + "message": "Senha" + }, + "passphrase": { + "message": "Frase Secreta" + }, + "favorite": { + "message": "Favorito" + }, + "notes": { + "message": "Notas" + }, + "note": { + "message": "Nota" + }, + "editItem": { + "message": "Editar Item" + }, + "folder": { + "message": "Pasta" + }, + "deleteItem": { + "message": "Excluir Item" + }, + "viewItem": { + "message": "Visualizar Item" + }, + "launch": { + "message": "Abrir" + }, + "website": { + "message": "Site" + }, + "toggleVisibility": { + "message": "Alternar Visibilidade" + }, + "manage": { + "message": "Gerenciar" + }, + "other": { + "message": "Outros" + }, + "rateExtension": { + "message": "Avaliar a Extensão" + }, + "rateExtensionDesc": { + "message": "Por favor considere ajudar-nos com uma boa avaliação!" + }, + "browserNotSupportClipboard": { + "message": "O seu navegador web não suporta cópia para a área de transferência. Em alternativa, copie manualmente." + }, + "verifyIdentity": { + "message": "Verificar Identidade" + }, + "yourVaultIsLocked": { + "message": "Seu cofre está trancado. Verifique sua identidade para continuar." + }, + "unlock": { + "message": "Desbloquear" + }, + "loggedInAsOn": { + "message": "Entrou como $EMAIL$ em $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Senha mestra inválida" + }, + "vaultTimeout": { + "message": "Tempo limite do cofre." + }, + "lockNow": { + "message": "Bloquear Agora" + }, + "immediately": { + "message": "Imediatamente" + }, + "tenSeconds": { + "message": "10 segundos" + }, + "twentySeconds": { + "message": "20 segundos" + }, + "thirtySeconds": { + "message": "30 segundos" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minutos" + }, + "fiveMinutes": { + "message": "5 minutos" + }, + "fifteenMinutes": { + "message": "15 minutos" + }, + "thirtyMinutes": { + "message": "30 minutos" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 horas" + }, + "onLocked": { + "message": "Quando o Sistema for Bloqueado" + }, + "onRestart": { + "message": "Ao Reiniciar" + }, + "never": { + "message": "Nunca" + }, + "security": { + "message": "Segurança" + }, + "errorOccurred": { + "message": "Ocorreu um erro" + }, + "emailRequired": { + "message": "O endereço de e-mail é obrigatório." + }, + "invalidEmail": { + "message": "Endereço de e-mail inválido." + }, + "masterPassRequired": { + "message": "A senha mestra é obrigatória." + }, + "masterPassLength": { + "message": "A senha mestra deve ter pelo menos 8 caracteres." + }, + "masterPassDoesntMatch": { + "message": "A confirmação da senha mestra não corresponde." + }, + "newAccountCreated": { + "message": "A sua nova conta foi criada! Agora você pode iniciar a sessão." + }, + "masterPassSent": { + "message": "Enviamos um e-mail com a dica da sua senha mestra." + }, + "verificationCodeRequired": { + "message": "O código de verificação é necessário." + }, + "invalidVerificationCode": { + "message": "Código de verificação inválido" + }, + "valueCopied": { + "message": " copiado", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Não é possível autopreencher o item selecionado nesta página. Em alternativa, copie e cole a informação." + }, + "loggedOut": { + "message": "Sessão encerrada" + }, + "loginExpired": { + "message": "A sua sessão expirou." + }, + "logOutConfirmation": { + "message": "Você tem certeza que deseja sair?" + }, + "yes": { + "message": "Sim" + }, + "no": { + "message": "Não" + }, + "unexpectedError": { + "message": "Ocorreu um erro inesperado." + }, + "nameRequired": { + "message": "O nome é necessário." + }, + "addedFolder": { + "message": "Pasta adicionada" + }, + "changeMasterPass": { + "message": "Alterar Senha Mestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Você pode alterar a sua senha mestra no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "twoStepLoginConfirmation": { + "message": "O login em duas etapas torna a sua conta mais segura ao exigir que você verifique seu login com outro dispositivo como uma chave de segurança, aplicativo de autenticação, SMS, ligação telefônica, ou e-mail. O login em duas etapas pode ser ativado no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "editedFolder": { + "message": "Pasta Editada" + }, + "deleteFolderConfirmation": { + "message": "Você tem certeza que deseja excluir esta pasta?" + }, + "deletedFolder": { + "message": "Pasta excluída" + }, + "gettingStartedTutorial": { + "message": "Tutorial de Introdução" + }, + "gettingStartedTutorialVideo": { + "message": "Assista o nosso tutorial de introdução e saiba como tirar o máximo de proveito da extensão de navegador." + }, + "syncingComplete": { + "message": "Sincronização completa" + }, + "syncingFailed": { + "message": "A Sincronização falhou" + }, + "passwordCopied": { + "message": "Senha copiada" + }, + "uri": { + "message": "URL" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novo URI" + }, + "addedItem": { + "message": "Item adicionado" + }, + "editedItem": { + "message": "Item editado" + }, + "deleteItemConfirmation": { + "message": "Você tem certeza que deseja enviar este item para a lixeira?" + }, + "deletedItem": { + "message": "Enviar item para lixeira" + }, + "overwritePassword": { + "message": "Sobrescrever Senha" + }, + "overwritePasswordConfirmation": { + "message": "Você tem certeza que deseja substituir a senha atual?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Pesquisar pasta" + }, + "searchCollection": { + "message": "Pesquisar coleção" + }, + "searchType": { + "message": "Pesquisar tipo" + }, + "noneFolder": { + "message": "Nenhuma Pasta", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Desativar Notificação de Adicionar Credencial" + }, + "addLoginNotificationDesc": { + "message": "A \"Notificação de Adicionar Login\" pede para salvar automaticamente novas logins para o seu cofre quando você inicia uma sessão em um site pela primeira vez." + }, + "dontShowCardsCurrentTab": { + "message": "Não Mostrar Cartões na Página 'Aba'" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Os itens de cartão do seu cofre estão listados na página 'Aba Atual' para facilitar o acesso ao preenchimento automático." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Não Mostrar Identidades na Página \"Aba\"" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Os itens de identidade do seu cofre estão listados na página 'Aba Atual' para facilitar o acesso ao preenchimento automático." + }, + "clearClipboard": { + "message": "Limpar Área de Transferência", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Limpar automaticamente os valores copiados da sua área de transferência.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "O Bitwarden deve lembrar esta senha para você?" + }, + "notificationAddSave": { + "message": "Salvar" + }, + "disableChangedPasswordNotification": { + "message": "Desativar Notificação de Alteração da Senha" + }, + "disableChangedPasswordNotificationDesc": { + "message": "A \"Notificação de Alteração da Senha\" solicita automaticamente que você atualize a senha de uma credencial no seu cofre quando detecta que você a alterou em um site." + }, + "notificationChangeDesc": { + "message": "Você quer atualizar esta senha no Bitwarden?" + }, + "notificationChangeSave": { + "message": "Atualizar" + }, + "disableContextMenuItem": { + "message": "Desativar Opções do Menu de Contexto" + }, + "disableContextMenuItemDesc": { + "message": "As opções do menu de contexto fornecem acesso rápido à geração de senha e credenciais para o site na sua aba atual." + }, + "defaultUriMatchDetection": { + "message": "Detecção de Correspondência de URI Padrão", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Escolha a maneira padrão pela qual a detecção de correspondência de URI é manipulada para logins ao executar ações como preenchimento automático." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Altere o tema de cores do aplicativo." + }, + "dark": { + "message": "Escuro", + "description": "Dark color" + }, + "light": { + "message": "Claro", + "description": "Light color" + }, + "solarizedDark": { + "message": "Escuro Solarizado", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Exportar Cofre" + }, + "fileFormat": { + "message": "Formato do Arquivo" + }, + "warning": { + "message": "AVISO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirmar Exportação do Cofre" + }, + "exportWarningDesc": { + "message": "Esta exportação contém os dados do seu cofre em um formato não criptografado. Você não deve armazenar ou enviar o arquivo exportado por canais inseguros (como e-mail). Exclua o arquivo imediatamente após terminar de usá-lo." + }, + "encExportKeyWarningDesc": { + "message": "Esta exportação criptografa seus dados usando a chave de criptografia da sua conta. Se você rotacionar a chave de criptografia da sua conta, você deve exportar novamente, já que você não será capaz de descriptografar este arquivo de exportação." + }, + "encExportAccountWarningDesc": { + "message": "As chaves de criptografia são únicas para cada conta de usuário do Bitwarden, então você não pode importar um arquivo de exportação criptografado para uma conta diferente." + }, + "exportMasterPassword": { + "message": "Insira a sua senha mestra para exportar os dados do seu cofre." + }, + "shared": { + "message": "Compartilhado" + }, + "learnOrg": { + "message": "Aprenda mais sobre as Organizações" + }, + "learnOrgConfirmation": { + "message": "O Bitwarden permite compartilhar os seus itens do cofre com outros ao utilizar uma organização. Gostaria de visitar o site bitwarden.com para saber mais?" + }, + "moveToOrganization": { + "message": "Mover para a Organização" + }, + "share": { + "message": "Compartilhar" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ movido para $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Escolha uma organização para a qual deseja mover este item. Mudar para uma organização transfere a propriedade do item para essa organização. Você não será mais o proprietário direto deste item depois que ele for movido." + }, + "learnMore": { + "message": "Saber mais" + }, + "authenticatorKeyTotp": { + "message": "Chave de Autenticação (TOTP)" + }, + "verificationCodeTotp": { + "message": "Código de Verificação (TOTP)" + }, + "copyVerificationCode": { + "message": "Copiar Código de Verificação" + }, + "attachments": { + "message": "Anexos" + }, + "deleteAttachment": { + "message": "Excluir anexo" + }, + "deleteAttachmentConfirmation": { + "message": "Tem a certeza de que deseja excluir este anexo?" + }, + "deletedAttachment": { + "message": "Anexo excluído" + }, + "newAttachment": { + "message": "Adicionar Novo Anexo" + }, + "noAttachments": { + "message": "Sem anexos." + }, + "attachmentSaved": { + "message": "O anexo foi salvo." + }, + "file": { + "message": "Arquivo" + }, + "selectFile": { + "message": "Selecione um arquivo." + }, + "maxFileSize": { + "message": "O tamanho máximo do arquivo é de 500 MB." + }, + "featureUnavailable": { + "message": "Recurso Indisponível" + }, + "updateKey": { + "message": "Você não pode usar este recurso, até você atualizar sua chave de criptografia." + }, + "premiumMembership": { + "message": "Assinatura Premium" + }, + "premiumManage": { + "message": "Gerenciar Plano" + }, + "premiumManageAlert": { + "message": "Você pode gerenciar a sua assinatura premium no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "premiumRefresh": { + "message": "Atualizar Assinatura" + }, + "premiumNotCurrentMember": { + "message": "Você não é um membro premium atualmente." + }, + "premiumSignUpAndGet": { + "message": "Registre-se para uma assinatura premium e obtenha:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB de armazenamento de arquivos encriptados." + }, + "ppremiumSignUpTwoStep": { + "message": "Opções de autenticação de duas etapas adicionais como YubiKey, FIDO U2F, e Duo." + }, + "ppremiumSignUpReports": { + "message": "Higiene de senha, saúde da conta, e relatórios sobre violação de dados para manter o seu cofre seguro." + }, + "ppremiumSignUpTotp": { + "message": "Gerador de códigos de verificação TOTP (2FA) para credenciais no seu cofre." + }, + "ppremiumSignUpSupport": { + "message": "Prioridade no suporte ao cliente." + }, + "ppremiumSignUpFuture": { + "message": "Todos os recursos premium no futuro. Mais em breve!" + }, + "premiumPurchase": { + "message": "Comprar Premium" + }, + "premiumPurchaseAlert": { + "message": "Você pode comprar a assinatura premium no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "premiumCurrentMember": { + "message": "Você é um membro premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Obrigado por apoiar o Bitwarden." + }, + "premiumPrice": { + "message": "Tudo por apenas %price% /ano!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Atualização completa" + }, + "disableAutoTotpCopy": { + "message": "Desativar Cópia Automática de TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Se a sua credencial tiver uma chave de autenticação anexada, o código de verificação TOTP será copiado automaticamente para a área de transferência quando você autopreencher a credencial." + }, + "disableAutoBiometricsPrompt": { + "message": "Não solicitar por biometria na inicialização." + }, + "premiumRequired": { + "message": "Requer Assinatura Premium" + }, + "premiumRequiredDesc": { + "message": "Uma conta premium é necessária para usar esse recurso." + }, + "enterVerificationCodeApp": { + "message": "Insira o código de verificação de 6 dígitos do seu aplicativo de autenticação." + }, + "enterVerificationCodeEmail": { + "message": "Insira o código de verificação de 6 dígitos que foi enviado por e-mail para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mail de verificação enviado para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Lembrar de mim" + }, + "sendVerificationCodeEmailAgain": { + "message": "Enviar código de verificação para o e-mail novamente" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizar outro método de verificação em duas etapas" + }, + "insertYubiKey": { + "message": "Insira a sua YubiKey na porta USB do seu computador, e depois toque no botão da mesma." + }, + "insertU2f": { + "message": "Insira a sua chave de segurança na porta USB do seu computador. Se ele tiver um botão, toque nele." + }, + "webAuthnNewTab": { + "message": "Para iniciar a verificação 2FA WebAuthn. Clique no botão abaixo para abrir uma nova aba e siga as instruções fornecidas na nova aba." + }, + "webAuthnNewTabOpen": { + "message": "Abrir nova aba" + }, + "webAuthnAuthenticate": { + "message": "Autenticar WebAuthn" + }, + "loginUnavailable": { + "message": "Sessão Indisponível" + }, + "noTwoStepProviders": { + "message": "Esta conta tem a verificação em duas etapas ativado, no entanto, nenhum dos provedores de verificação em duas etapas configurados são suportados por este navegador web." + }, + "noTwoStepProviders2": { + "message": "Por favor utilize um navegador web suportado (tal como o Chrome) e/ou inclua provedores adicionais que são melhor suportados entre navegadores web (tal como uma aplicativo de autenticação)." + }, + "twoStepOptions": { + "message": "Opções de Login em Duas Etapas" + }, + "recoveryCodeDesc": { + "message": "Perdeu o acesso a todos os seus provedores de duas etapas? Utilize o seu código de recuperação para desativar todos os provedores de duas etapas da sua conta." + }, + "recoveryCodeTitle": { + "message": "Código de Recuperação" + }, + "authenticatorAppTitle": { + "message": "Aplicativo de Autenticação" + }, + "authenticatorAppDesc": { + "message": "Utilize um aplicativo de autenticação (tal como Authy ou Google Authenticator) para gerar códigos de verificação baseados no tempo.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Chave de Segurança YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utilize uma YubiKey para acessar a sua conta. Funciona com YubiKey 4, 4 Nano, 4C, e dispositivos NEO." + }, + "duoDesc": { + "message": "Verifique com o Duo Security utilizando o aplicativo Duo Mobile, SMS, chamada telefônica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifique com o Duo Security utilizando o aplicativo Duo Mobile, SMS, chamada telefônica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "WebAuthn FIDO2" + }, + "webAuthnDesc": { + "message": "Utilize qualquer chave de segurança ativada por WebAuthn para acessar a sua conta." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Os códigos de verificação vão ser enviados por e-mail para você." + }, + "selfHostedEnvironment": { + "message": "Ambiente Auto-hospedado" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifique a URL de base da sua instalação local do Bitwarden." + }, + "customEnvironment": { + "message": "Ambiente Personalizado" + }, + "customEnvironmentFooter": { + "message": "Para usuários avançados. Você pode especificar a URL de base de cada serviço independentemente." + }, + "baseUrl": { + "message": "URL do Servidor" + }, + "apiUrl": { + "message": "URL do Servidor da API" + }, + "webVaultUrl": { + "message": "URL do Servidor do Cofre Web" + }, + "identityUrl": { + "message": "URL do Servidor de Identidade" + }, + "notificationsUrl": { + "message": "URL do Servidor de Notificações" + }, + "iconsUrl": { + "message": "URL do Servidor de Ícones" + }, + "environmentSaved": { + "message": "As URLs do ambiente foram salvas." + }, + "enableAutoFillOnPageLoad": { + "message": "Ativar o Autopreenchimento ao Carregar a Página" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Se um formulário de login for detectado, realize automaticamente um autopreenchimento quando a página web carregar." + }, + "experimentalFeature": { + "message": "Atualmente, este é um recurso experimental. Utilize por sua conta e risco." + }, + "defaultAutoFillOnPageLoad": { + "message": "Configuração de autopreenchimento padrão para itens de credenciais" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Depois de ativar o Autopreenchimento ao carregar a página, você pode ativar ou desativar o recurso para itens de credenciais individuais. Esta é a configuração padrão para itens de credenciais que não são configurados separadamente." + }, + "itemAutoFillOnPageLoad": { + "message": "Autopreencher no Carregamento da Página (se ativado nas Opções)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Usar configuração padrão" + }, + "autoFillOnPageLoadYes": { + "message": "Autopreencher ao carregar a página" + }, + "autoFillOnPageLoadNo": { + "message": "Não autopreencher ao carregar a página" + }, + "commandOpenPopup": { + "message": "Abrir pop-up do cofre" + }, + "commandOpenSidebar": { + "message": "Abrir cofre na barra lateral" + }, + "commandAutofillDesc": { + "message": "Autopreencher o último login utilizado para o site atual." + }, + "commandGeneratePasswordDesc": { + "message": "Gerar e copiar uma nova senha aleatória para a área de transferência." + }, + "commandLockVaultDesc": { + "message": "Bloquear o cofre" + }, + "privateModeWarning": { + "message": "O suporte para modo privado é experimental e alguns recursos são limitados." + }, + "customFields": { + "message": "Campos Personalizados" + }, + "copyValue": { + "message": "Copiar Valor" + }, + "value": { + "message": "Valor" + }, + "newCustomField": { + "message": "Novo Campo Personalizado" + }, + "dragToSort": { + "message": "Arrastar para ordenar" + }, + "cfTypeText": { + "message": "Texto" + }, + "cfTypeHidden": { + "message": "Ocultado" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "cfTypeLinked": { + "message": "Vinculado", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Valor vinculado", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Ao clicar fora da janela de pop-up para verificar seu e-mail para o seu código de verificação fará com que este pop-up feche. Você deseja abrir este pop-up em uma nova janela para que ele não seja fechado?" + }, + "popupU2fCloseMessage": { + "message": "Este navegador não pode processar requisições U2F nesta janela popup. Você quer abrir este popup em uma nova janela para que você possa entrar usando U2F?" + }, + "disableFavicon": { + "message": "Desativar Ícones de Site" + }, + "disableFaviconDesc": { + "message": "O Ícone do Site fornece uma imagem reconhecível ao lado de cada credencial no seu cofre." + }, + "disableBadgeCounter": { + "message": "Desativar Contador" + }, + "disableBadgeCounterDesc": { + "message": "O contador indica a quantidade de credenciais que você tem para a página atual no seu cofre." + }, + "cardholderName": { + "message": "Titular do Cartão" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Bandeira" + }, + "expirationMonth": { + "message": "Mês de Vencimento" + }, + "expirationYear": { + "message": "Ano de Vencimento" + }, + "expiration": { + "message": "Vencimento" + }, + "january": { + "message": "Janeiro" + }, + "february": { + "message": "Fevereiro" + }, + "march": { + "message": "Março" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Maio" + }, + "june": { + "message": "Junho" + }, + "july": { + "message": "Julho" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Setembro" + }, + "october": { + "message": "Outubro" + }, + "november": { + "message": "Novembro" + }, + "december": { + "message": "Dezembro" + }, + "securityCode": { + "message": "Código de Segurança" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Título" + }, + "mr": { + "message": "Sr" + }, + "mrs": { + "message": "Sra" + }, + "ms": { + "message": "Sra" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Primeiro Nome" + }, + "middleName": { + "message": "Nome do Meio" + }, + "lastName": { + "message": "Sobrenome" + }, + "fullName": { + "message": "Nome Completo" + }, + "identityName": { + "message": "Nome de Identidade" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Cadastro de Pessoas Físicas (CPF)" + }, + "passportNumber": { + "message": "Número do Passaporte" + }, + "licenseNumber": { + "message": "Número da Licença" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefone" + }, + "address": { + "message": "Endereço" + }, + "address1": { + "message": "Endereço 1" + }, + "address2": { + "message": "Endereço 2" + }, + "address3": { + "message": "Endereço 3" + }, + "cityTown": { + "message": "Cidade / Localidade" + }, + "stateProvince": { + "message": "Estado / Província" + }, + "zipPostalCode": { + "message": "CEP / Código Postal" + }, + "country": { + "message": "País" + }, + "type": { + "message": "Tipo" + }, + "typeLogin": { + "message": "Credencial" + }, + "typeLogins": { + "message": "Credenciais" + }, + "typeSecureNote": { + "message": "Nota Segura" + }, + "typeCard": { + "message": "Cartão" + }, + "typeIdentity": { + "message": "Identidade" + }, + "passwordHistory": { + "message": "Histórico de Senha" + }, + "back": { + "message": "Voltar" + }, + "collections": { + "message": "Coleções" + }, + "favorites": { + "message": "Favoritos" + }, + "popOutNewWindow": { + "message": "Abrir em uma nova janela" + }, + "refresh": { + "message": "Atualizar" + }, + "cards": { + "message": "Cartões" + }, + "identities": { + "message": "Identidades" + }, + "logins": { + "message": "Credenciais" + }, + "secureNotes": { + "message": "Notas Seguras" + }, + "clear": { + "message": "Limpar", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Verifique se a senha foi exposta." + }, + "passwordExposed": { + "message": "Esta senha foi exposta $VALUE$ vez(es) em violações de dados. Você deve alterá-la.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Esta senha não foi encontrada em violações de dados conhecidas. Deve ser seguro de usar." + }, + "baseDomain": { + "message": "Domínio de base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Servidor", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exato" + }, + "startsWith": { + "message": "Começa com" + }, + "regEx": { + "message": "Expressão regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Detecção de Correspondência", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detecção de correspondência padrão", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Alternar Opções" + }, + "toggleCurrentUris": { + "message": "Alternar URIs atuais", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI atual", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organização", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tipos" + }, + "allItems": { + "message": "Todos os Itens" + }, + "noPasswordsInList": { + "message": "Não existem senhas para listar." + }, + "remove": { + "message": "Remover" + }, + "default": { + "message": "Padrão" + }, + "dateUpdated": { + "message": "Atualizado", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Senha Atualizada", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Você tem certeza que deseja usar a opção \"Nunca\"? Definir suas opções de bloqueio para \"Nunca\" armazena a chave de criptografia do seu cofre no seu dispositivo. Se você usar esta opção, você deve garantir que irá manter o seu dispositivo devidamente protegido." + }, + "noOrganizationsList": { + "message": "Você pertence a nenhuma organização. As organizações permitem que você compartilhe itens em segurança com outros usuários." + }, + "noCollectionsInList": { + "message": "Não há coleções para listar." + }, + "ownership": { + "message": "Propriedade" + }, + "whoOwnsThisItem": { + "message": "Quem possui este item?" + }, + "strong": { + "message": "Forte", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Boa", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Fraca", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Senha Mestra Fraca" + }, + "weakMasterPasswordDesc": { + "message": "A senha mestra que você selecionou está fraca. Você deve usar uma senha mestra forte (ou uma frase-passe) para proteger a sua conta Bitwarden adequadamente. Tem certeza que deseja usar esta senha mestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloquear com o PIN" + }, + "setYourPinCode": { + "message": "Defina o seu código PIN para desbloquear o Bitwarden. Suas configurações de PIN serão redefinidas se alguma vez você encerrar completamente toda a sessão do aplicativo." + }, + "pinRequired": { + "message": "O código PIN é necessário." + }, + "invalidPin": { + "message": "Código PIN inválido." + }, + "unlockWithBiometrics": { + "message": "Desbloquear com a biometria" + }, + "awaitDesktop": { + "message": "Aguardando confirmação do desktop" + }, + "awaitDesktopDesc": { + "message": "Por favor, confirme o uso de dados biométricos no aplicativo Bitwarden Desktop para ativar a biometria para o navegador." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloquear com senha mestra ao reiniciar o navegador" + }, + "selectOneCollection": { + "message": "Você deve selecionar pelo menos uma coleção." + }, + "cloneItem": { + "message": "Clonar Item" + }, + "clone": { + "message": "Clonar" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Uma ou mais políticas da organização estão afetando as suas configurações do gerador." + }, + "vaultTimeoutAction": { + "message": "Ação de Tempo Limite do Cofre" + }, + "lock": { + "message": "Bloquear", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Lixeira", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Pesquisar na lixeira" + }, + "permanentlyDeleteItem": { + "message": "Excluir o Item Permanentemente" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Você tem certeza que deseja excluir permanentemente esse item?" + }, + "permanentlyDeletedItem": { + "message": "Item Permanentemente Excluído" + }, + "restoreItem": { + "message": "Restaurar Item" + }, + "restoreItemConfirmation": { + "message": "Você tem certeza que deseja restaurar esse item?" + }, + "restoredItem": { + "message": "Item Restaurado" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Sair irá remover todo o acesso ao seu cofre e requer autenticação online após o período de tempo limite. Tem certeza de que deseja usar esta configuração?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmação de Ação de Tempo Limite" + }, + "autoFillAndSave": { + "message": "Autopreencher e Salvar" + }, + "autoFillSuccessAndSavedUri": { + "message": "Item Auto-Preenchido e URI Salvo" + }, + "autoFillSuccess": { + "message": "Item Auto-Preenchido" + }, + "setMasterPassword": { + "message": "Definir Senha Mestra" + }, + "masterPasswordPolicyInEffect": { + "message": "Uma ou mais políticas da organização exigem que a sua senha mestra cumpra aos seguintes requisitos:" + }, + "policyInEffectMinComplexity": { + "message": "Pontuação mínima de complexidade de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Comprimento mínimo de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contém um ou mais caracteres em maiúsculo" + }, + "policyInEffectLowercase": { + "message": "Contém um ou mais caracteres em minúsculo" + }, + "policyInEffectNumbers": { + "message": "Contém um ou mais números" + }, + "policyInEffectSpecial": { + "message": "Contém um ou mais dos seguintes caracteres especiais $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "A sua nova senha mestra não cumpre aos requisitos da política." + }, + "acceptPolicies": { + "message": "Ao marcar esta caixa, você concorda com o seguinte:" + }, + "acceptPoliciesError": { + "message": "Os Termos de Serviço e a Política de Privacidade não foram reconhecidos." + }, + "termsOfService": { + "message": "Termos de Serviço" + }, + "privacyPolicy": { + "message": "Política de Privacidade" + }, + "hintEqualsPassword": { + "message": "Sua dica de senha não pode ser o mesmo que sua senha." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Verificação de sincronização do Desktop" + }, + "desktopIntegrationVerificationText": { + "message": "Por favor, verifique se o aplicativo desktop mostra esta impressão digital: " + }, + "desktopIntegrationDisabledTitle": { + "message": "A integração com o navegador não está ativada" + }, + "desktopIntegrationDisabledDesc": { + "message": "A integração com o navegador não está ativada no aplicativo Bitwarden Desktop. Por favor, ative-a nas configurações do aplicativo desktop." + }, + "startDesktopTitle": { + "message": "Iniciar o aplicativo Bitwarden Desktop" + }, + "startDesktopDesc": { + "message": "O aplicativo Bitwarden Desktop precisa ser iniciado antes que esta função possa ser usada." + }, + "errorEnableBiometricTitle": { + "message": "Não foi possível ativar a biometria" + }, + "errorEnableBiometricDesc": { + "message": "A ação foi cancelada pelo aplicativo desktop" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "O aplicativo desktop invalidou o canal de comunicação seguro. Por favor, tente esta operação novamente" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Comunicação com o desktop interrompida" + }, + "nativeMessagingWrongUserDesc": { + "message": "O aplicativo desktop está conectado em uma conta diferente. Por favor, certifique-se de que ambos os aplicativos estejam conectados na mesma conta." + }, + "nativeMessagingWrongUserTitle": { + "message": "A conta não confere" + }, + "biometricsNotEnabledTitle": { + "message": "Biometria não ativada" + }, + "biometricsNotEnabledDesc": { + "message": "A biometria com o navegador requer que a biometria de desktop seja ativada nas configurações primeiro." + }, + "biometricsNotSupportedTitle": { + "message": "Biometria não suportada" + }, + "biometricsNotSupportedDesc": { + "message": "A biometria com o navegador não é suportada neste dispositivo." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permissão não fornecida" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Sem a permissão para se comunicar com o Aplicativo Bitwarden Desktop, não podemos fornecer dados biométricos na extensão do navegador. Por favor, tente novamente." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Erro ao solicitar permissão" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Esta ação não pode ser feita na barra lateral. Por favor, tente novamente no pop-up ou popout." + }, + "personalOwnershipSubmitError": { + "message": "Devido a uma Política Empresarial, você está restrito de salvar itens para seu cofre pessoal. Altere a opção de Propriedade para uma organização e escolha entre as Coleções disponíveis." + }, + "personalOwnershipPolicyInEffect": { + "message": "Uma política de organização está afetando suas opções de propriedade." + }, + "excludedDomains": { + "message": "Domínios Excluídos" + }, + "excludedDomainsDesc": { + "message": "O Bitwarden não irá pedir para salvar os detalhes de credencial para estes domínios. Você deve atualizar a página para que as alterações entrem em vigor." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ não é um domínio válido", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Pesquisar Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Adicionar Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Texto" + }, + "sendTypeFile": { + "message": "Arquivo" + }, + "allSends": { + "message": "Todos os Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Número máximo de acessos atingido", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expirado" + }, + "pendingDeletion": { + "message": "Exclusão pendente" + }, + "passwordProtected": { + "message": "Protegido por senha" + }, + "copySendLink": { + "message": "Copiar link do Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remover Senha" + }, + "delete": { + "message": "Excluir" + }, + "removedPassword": { + "message": "Senha Removida" + }, + "deletedSend": { + "message": "Send Excluído", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Link do Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Desativado" + }, + "removePasswordConfirmation": { + "message": "Você tem certeza que deseja remover a senha?" + }, + "deleteSend": { + "message": "Excluir Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Você tem certeza que deseja excluir este Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Editar Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Que tipo de Send é este?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Um nome amigável para descrever este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "O arquivo que você deseja enviar." + }, + "deletionDate": { + "message": "Data de Exclusão" + }, + "deletionDateDesc": { + "message": "O Send será eliminado permanentemente na data e hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data de Validade" + }, + "expirationDateDesc": { + "message": "Se definido, o acesso a este Send expirará na data e hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dia" + }, + "days": { + "message": "$DAYS$ dias", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Personalizado" + }, + "maximumAccessCount": { + "message": "Contagem Máxima de Acessos" + }, + "maximumAccessCountDesc": { + "message": "Se atribuído, usuários não poderão mais acessar este Send assim que o número máximo de acessos for atingido.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Exigir opcionalmente uma senha para os usuários acessarem este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notas privadas sobre esse Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Desative este Send para que ninguém possa acessá-lo.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copiar o link deste Send para área de transferência após salvar.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "O texto que você deseja enviar." + }, + "sendHideText": { + "message": "Ocultar o texto deste Send por padrão.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Contagem Atual de Acessos" + }, + "createSend": { + "message": "Criar Novo Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nova Senha" + }, + "sendDisabled": { + "message": "Send Desativado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Devido a uma política corporativa, você só pode excluir um Send existente.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send Criado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send Editado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Para escolher um arquivo, abra a extensão na barra lateral (se possível), ou abra uma nova janela clicando neste banner." + }, + "sendFirefoxFileWarning": { + "message": "Para escolher um arquivo usando o Firefox, abra a extensão na barra lateral ou abra uma nova janela clicando neste banner." + }, + "sendSafariFileWarning": { + "message": "Para escolher um arquivo usando o Safari, abra uma nova janela clicando neste banner." + }, + "sendFileCalloutHeader": { + "message": "Antes de começar" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Para usar um seletor de data no estilo calendário", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "clique aqui", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "para abrir a sua janela.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "A data de validade fornecida não é válida." + }, + "deletionDateIsInvalid": { + "message": "A data de exclusão fornecida não é válida." + }, + "expirationDateAndTimeRequired": { + "message": "Uma data e hora de expiração são obrigatórias." + }, + "deletionDateAndTimeRequired": { + "message": "Uma data e hora de exclusão são obrigatórias." + }, + "dateParsingError": { + "message": "Ocorreu um erro ao salvar as suas datas de exclusão e validade." + }, + "hideEmail": { + "message": "Ocultar meu endereço de e-mail dos destinatários." + }, + "sendOptionsPolicyInEffect": { + "message": "Uma ou mais políticas da organização estão afetando as suas opções de Send." + }, + "passwordPrompt": { + "message": "Solicitação nova de senha mestra" + }, + "passwordConfirmation": { + "message": "Confirmação de senha mestra" + }, + "passwordConfirmationDesc": { + "message": "Esta ação está protegida. Para continuar, por favor, reinsira a sua senha mestra para verificar sua identidade." + }, + "emailVerificationRequired": { + "message": "Verificação de E-mail Necessária" + }, + "emailVerificationRequiredDesc": { + "message": "Você precisa verificar o seu e-mail para usar este recurso. Você pode verificar seu e-mail no cofre web." + }, + "updatedMasterPassword": { + "message": "Senha Mestra Atualizada" + }, + "updateMasterPassword": { + "message": "Atualizar Senha Mestra" + }, + "updateMasterPasswordWarning": { + "message": "Sua Senha Mestra foi alterada recentemente por um administrador de sua organização. Para acessar o cofre, você precisa atualizá-la agora. O processo desconectará você da sessão atual, exigindo que você inicie a sessão novamente. Sessões ativas em outros dispositivos podem continuar ativas por até uma hora." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscrição Automática" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Esta organização possui uma política empresarial que irá inscrevê-lo automaticamente na redefinição de senha. A inscrição permitirá que os administradores da organização alterem sua senha mestra." + }, + "selectFolder": { + "message": "Selecionar pasta..." + }, + "ssoCompleteRegistration": { + "message": "Para concluir o login com o SSO, defina uma senha mestra para acessar e proteger o seu cofre." + }, + "hours": { + "message": "Horas" + }, + "minutes": { + "message": "Minutos" + }, + "vaultTimeoutPolicyInEffect": { + "message": "As políticas da sua organização estão afetando o tempo limite do seu cofre. O Tempo Limite Máximo permitido do Cofre é $HOURS$ hora(s) e $MINUTES$ minuto(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "O tempo limite do seu cofre excede as restrições definidas por sua organização." + }, + "vaultExportDisabled": { + "message": "Exportação de Cofre Desativada" + }, + "personalVaultExportPolicyInEffect": { + "message": "Uma ou mais políticas da organização impedem que você exporte seu cofre pessoal." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Não foi possível identificar um elemento de formulário válido. Em vez disso, tente inspecionar o HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nenhum identificador exclusivo encontrado." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ está usando SSO com um servidor de chaves auto-hospedado. Não é mais necessária uma senha mestra para os membros desta organização entrarem.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Sair da Organização" + }, + "removeMasterPassword": { + "message": "Remover Senha Mestra" + }, + "removedMasterPassword": { + "message": "Senha mestra removida." + }, + "leaveOrganizationConfirmation": { + "message": "Você tem certeza que deseja sair desta organização?" + }, + "leftOrganization": { + "message": "Você saiu da organização." + }, + "toggleCharacterCount": { + "message": "Alternar contagem de caracteres" + }, + "sessionTimeout": { + "message": "Sua sessão expirou. Por favor, volte e tente iniciar a sessão novamente." + }, + "exportingPersonalVaultTitle": { + "message": "Exportando o Cofre Pessoal" + }, + "exportingPersonalVaultDescription": { + "message": "Apenas os itens pessoais do cofre associados com $EMAIL$ serão exportados. Os itens do cofre da organização não serão incluídos.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Erro" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/pt_PT/messages.json b/apps/browser/src/_locales/pt_PT/messages.json new file mode 100644 index 0000000000..407c1933a5 --- /dev/null +++ b/apps/browser/src/_locales/pt_PT/messages.json @@ -0,0 +1,1817 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Um gestor de palavras-passe seguro e gratuito para todos os seus dispositivos.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Inicie sessão ou crie uma nova conta para aceder ao seu cofre seguro." + }, + "createAccount": { + "message": "Criar conta" + }, + "login": { + "message": "Iniciar sessão" + }, + "enterpriseSingleSignOn": { + "message": "Início de Sessão Único da Empresa" + }, + "cancel": { + "message": "Cancelar" + }, + "close": { + "message": "Fechar" + }, + "submit": { + "message": "Submeter" + }, + "emailAddress": { + "message": "Endereço de email" + }, + "masterPass": { + "message": "Palavra-passe mestra" + }, + "masterPassDesc": { + "message": "A palavra-passe mestra é a palavra-passe que utiliza para aceder ao seu cofre. É muito importante que não se esqueça da sua palavra-passe mestra. Não existe maneira de recuperar a palavra-passe no caso de a esquecer." + }, + "masterPassHintDesc": { + "message": "Uma dica da palavra-passe mestra pode ajudar a lembrar-se da sua palavra-passe se a esquecer." + }, + "reTypeMasterPass": { + "message": "Reescreva a palavra-passe mestra" + }, + "masterPassHint": { + "message": "Dica da palavra-passe mestra (opcional)" + }, + "tab": { + "message": "Separador" + }, + "myVault": { + "message": "Meu cofre" + }, + "tools": { + "message": "Ferramentas" + }, + "settings": { + "message": "Definições" + }, + "currentTab": { + "message": "Separador atual" + }, + "copyPassword": { + "message": "Copiar palavra-passe" + }, + "copyNote": { + "message": "Copiar nota" + }, + "copyUri": { + "message": "Copiar URI" + }, + "copyUsername": { + "message": "Copiar nome de utilizador" + }, + "copyNumber": { + "message": "Copiar número" + }, + "copySecurityCode": { + "message": "Copiar código de segurança" + }, + "autoFill": { + "message": "Auto-preencher" + }, + "generatePasswordCopied": { + "message": "Gerar palavra-passe (copiada)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "Sem credencias correspondidas." + }, + "vaultLocked": { + "message": "O cofre está bloqueado." + }, + "vaultLoggedOut": { + "message": "Sessão terminada no cofre." + }, + "autoFillInfo": { + "message": "Não existem credenciais disponíveis para auto-preencher para o separador de navegador atual." + }, + "addLogin": { + "message": "Adicionar uma credencial" + }, + "addItem": { + "message": "Adicionar item" + }, + "passwordHint": { + "message": "Dica da palavra-passe" + }, + "enterEmailToGetHint": { + "message": "Introduza o endereço de email da sua conta para receber a dica da sua palavra-passe mestra." + }, + "getMasterPasswordHint": { + "message": "Obter dica da palavra-passe mestra" + }, + "continue": { + "message": "Continuar" + }, + "verificationCode": { + "message": "Código de verificação" + }, + "account": { + "message": "Conta" + }, + "changeMasterPassword": { + "message": "Alterar palavra-passe mestra" + }, + "fingerprintPhrase": { + "message": "Frase de impressão digital", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "A frase de impressão digital da sua conta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Início de sessão de dois passos" + }, + "logOut": { + "message": "Terminar sessão" + }, + "about": { + "message": "Acerca" + }, + "version": { + "message": "Versão" + }, + "save": { + "message": "Guardar" + }, + "move": { + "message": "Move" + }, + "addFolder": { + "message": "Adicionar pasta" + }, + "name": { + "message": "Nome" + }, + "editFolder": { + "message": "Editar pasta" + }, + "deleteFolder": { + "message": "Eliminar pasta" + }, + "folders": { + "message": "Pastas" + }, + "noFolders": { + "message": "Não existem pastas para listar." + }, + "helpFeedback": { + "message": "Ajuda e feedback" + }, + "sync": { + "message": "Sincronizar" + }, + "syncVaultNow": { + "message": "Sincronizar cofre agora" + }, + "lastSync": { + "message": "Última sincronização:" + }, + "passGen": { + "message": "Gerador de palavras-passe" + }, + "generator": { + "message": "Gerador", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Gera automaticamente palavras-passe fortes e únicas para as suas credenciais." + }, + "bitWebVault": { + "message": "Cofre Web Bitwarden" + }, + "importItems": { + "message": "Importar itens" + }, + "select": { + "message": "Selecionar" + }, + "generatePassword": { + "message": "Gerar palavra-passe" + }, + "regeneratePassword": { + "message": "Regenerar palavra-passe" + }, + "options": { + "message": "Opções" + }, + "length": { + "message": "Comprimento" + }, + "numWords": { + "message": "Número de palavras" + }, + "wordSeparator": { + "message": "Separador de palavras" + }, + "capitalize": { + "message": "Capitalizar", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Incluir número" + }, + "minNumbers": { + "message": "Números mínimos" + }, + "minSpecial": { + "message": "Especiais mínimos" + }, + "avoidAmbChar": { + "message": "Evitar caracteres ambíguos" + }, + "searchVault": { + "message": "Pesquisar cofre" + }, + "edit": { + "message": "Editar" + }, + "view": { + "message": "Ver" + }, + "noItemsInList": { + "message": "Não existem itens para listar." + }, + "itemInformation": { + "message": "Informação do item" + }, + "username": { + "message": "Nome de utilizador" + }, + "password": { + "message": "Palavra-passe" + }, + "passphrase": { + "message": "Frase-passe" + }, + "favorite": { + "message": "Favorito" + }, + "notes": { + "message": "Notas" + }, + "note": { + "message": "Nota" + }, + "editItem": { + "message": "Editar item" + }, + "folder": { + "message": "Pasta" + }, + "deleteItem": { + "message": "Eliminar item" + }, + "viewItem": { + "message": "Ver item" + }, + "launch": { + "message": "Iniciar" + }, + "website": { + "message": "Website" + }, + "toggleVisibility": { + "message": "Alternar visibilidade" + }, + "manage": { + "message": "Gerir" + }, + "other": { + "message": "Outros" + }, + "rateExtension": { + "message": "Avaliar a extensão" + }, + "rateExtensionDesc": { + "message": "Por favor considere ajudar-nos com uma boa análise!" + }, + "browserNotSupportClipboard": { + "message": "O seu navegador web não suporta cópia fácil da área de transferência. Em alternativa, copie manualmente." + }, + "verifyMasterPassword": { + "message": "Verificar palavra-passe mestra" + }, + "yourVaultIsLocked": { + "message": "O seu cofre está bloqueado. Verifique a sua palavra-passe mestra para continuar." + }, + "unlock": { + "message": "Desbloquear" + }, + "loggedInAsOn": { + "message": "Sessão iniciada como $EMAIL$ em $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Palavra-passe mestra inválida" + }, + "vaultTimeout": { + "message": "Expiração do cofre" + }, + "lockNow": { + "message": "Bloquear agora" + }, + "immediately": { + "message": "Imediatamente" + }, + "tenSeconds": { + "message": "10 segundos" + }, + "twentySeconds": { + "message": "20 segundos" + }, + "thirtySeconds": { + "message": "30 segundos" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minutos" + }, + "fiveMinutes": { + "message": "5 minutos" + }, + "fifteenMinutes": { + "message": "15 minutos" + }, + "thirtyMinutes": { + "message": "30 minutos" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 horas" + }, + "onLocked": { + "message": "Quando o sistema está bloqueado" + }, + "onRestart": { + "message": "Quando reiniciar o navegador" + }, + "never": { + "message": "Nunca" + }, + "security": { + "message": "Segurança" + }, + "errorOccurred": { + "message": "Ocorreu um erro" + }, + "emailRequired": { + "message": "O endereço de email é requerido." + }, + "invalidEmail": { + "message": "Endereço de email inválido." + }, + "masterPassRequired": { + "message": "A palavra-passe mestra é requerida." + }, + "masterPassLength": { + "message": "A palavra-passe mestra tem de ter pelo menos 8 caracteres." + }, + "masterPassDoesntMatch": { + "message": "A confirmação da palavra-passe mestra não corresponde." + }, + "newAccountCreated": { + "message": "A sua nova conta foi criada! Agora pode iniciar sessão." + }, + "masterPassSent": { + "message": "Enviámos-lhe um email com a dica da sua palavra-passe mestra." + }, + "verificationCodeRequired": { + "message": "O código de verificação é requerido." + }, + "valueCopied": { + "message": "$VALUE$ copiado(a)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Não é possível auto-preencher o item selecionado nesta página. Em alternativa, copie e cole a informação." + }, + "loggedOut": { + "message": "Sessão terminada" + }, + "loginExpired": { + "message": "A sua sessão expirou." + }, + "logOutConfirmation": { + "message": "Tem a certeza de que pretende terminar sessão?" + }, + "yes": { + "message": "Sim" + }, + "no": { + "message": "Não" + }, + "unexpectedError": { + "message": "Ocorreu um erro inesperado." + }, + "nameRequired": { + "message": "O nome é requerido." + }, + "addedFolder": { + "message": "Pasta adicionada" + }, + "changeMasterPass": { + "message": "Alterar palavra-passe mestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Pode alterar a sua palavra-passe mestra no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "twoStepLoginConfirmation": { + "message": "O início de sessão de dois passos torna a sua conta mais segura ao requerer que verifique o seu início de sessão com outro dispositivo como uma chave de segurança, aplicação de autenticação, SMS, chamada telefónica, ou email. O início de sessão de dois passos pode ser ativado no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "editedFolder": { + "message": "Pasta editada" + }, + "deleteFolderConfirmation": { + "message": "Tem a certeza de que pretende eliminar esta pasta?" + }, + "deletedFolder": { + "message": "Pasta eliminada" + }, + "gettingStartedTutorial": { + "message": "Tutorial de introdução" + }, + "gettingStartedTutorialVideo": { + "message": "Veja o nosso tutorial de introdução e saiba como tirar o máximo partido da extensão de navegador." + }, + "syncingComplete": { + "message": "Sincronização completada" + }, + "syncingFailed": { + "message": "Sincronização falhada" + }, + "passwordCopied": { + "message": "Palavra-passe copiada" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novo URI" + }, + "addedItem": { + "message": "Item adicionado" + }, + "editedItem": { + "message": "Item editado" + }, + "deleteItemConfirmation": { + "message": "Tem a certeza de que pretende apagar este item?" + }, + "deletedItem": { + "message": "Item enviado para o lixo" + }, + "overwritePassword": { + "message": "Sobreescrever palavra-passe" + }, + "overwritePasswordConfirmation": { + "message": "Tem a certeza de que pretende sobreescrever a palavra-passe atual?" + }, + "searchFolder": { + "message": "Pesquisar pasta" + }, + "searchCollection": { + "message": "Pesquisar coleção" + }, + "searchType": { + "message": "Pesquisar tipo" + }, + "noneFolder": { + "message": "Nenhuma pasta", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Desativar notificação de adicionar credencial" + }, + "addLoginNotificationDesc": { + "message": "A \"notificação de adicionar credencial\" solicita-lhe automaticamente a guardar novas credenciais para o seu cofre quando inicia sessão nas mesmas pela primeira vez." + }, + "dontShowCardsCurrentTab": { + "message": "Não mostrar cartões na página do separador" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Os itens de cartões do seu cofre estão listados na página 'Separador atual' para acesso de auto-preenchimento fácil." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Não mostrar identidades na página do separador" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Os itens de identidades do seu cofre estão listados na página 'Separador atual' para acesso de auto-preenchimento fácil." + }, + "clearClipboard": { + "message": "Limpar área de transferência", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Limpar automaticamente valores copiados da sua área de transferência.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Deve o Bitwarden memorizar esta palavra-passe para si?" + }, + "notificationAddSave": { + "message": "Sim, guardar agora" + }, + "notificationNeverSave": { + "message": "Nunca para este site" + }, + "disableChangedPasswordNotification": { + "message": "Desativar notificação de palavra-passe alterada" + }, + "disableChangedPasswordNotificationDesc": { + "message": "A \"notificação de palavra-passe alterada\" solicita-lhe automaticamente para atualizar a palavra-passe de uma credencial no seu cofre quando deteta que a alterou num website." + }, + "notificationChangeDesc": { + "message": "Pretende atualizar esta palavra-passe no Bitwarden?" + }, + "notificationChangeSave": { + "message": "Sim, atualizar agora" + }, + "disableContextMenuItem": { + "message": "Desativar opções do menu de contexto" + }, + "disableContextMenuItemDesc": { + "message": "As opções do menu de contexto providenciam acesso rápido à geração de palavras-passe e credenciais para o website no seu separador atual." + }, + "defaultUriMatchDetection": { + "message": "Deteção de correspondência de URI predefinida", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Escolha a maneira predefinida pela qual a deteção de correspondência de URI é manuseada para credenciais ao realizar ações como auto-preenchimento." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Altere o tema de cor da aplicação." + }, + "dark": { + "message": "Escuro", + "description": "Dark color" + }, + "light": { + "message": "Claro", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Exportar cofre" + }, + "fileFormat": { + "message": "Formato do ficheiro" + }, + "warning": { + "message": "AVISO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "Esta exportação contém os seus dados do cofre num formato desencriptado. Não deve armazenar ou enviar o ficheiro exportado através de canais inseguros (como email). Apague-a imediatamente após a utilizar." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Introduza a sua palavra-passe mestra para exportar os dados do seu cofre." + }, + "shared": { + "message": "Partilhado" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Partilhar" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Saber mais" + }, + "authenticatorKeyTotp": { + "message": "Chave de autenticador (TOTP)" + }, + "verificationCodeTotp": { + "message": "Código de verificação (TOTP)" + }, + "copyVerificationCode": { + "message": "Copiar código de verificação" + }, + "attachments": { + "message": "Anexos" + }, + "deleteAttachment": { + "message": "Eliminar anexo" + }, + "deleteAttachmentConfirmation": { + "message": "Tem a certeza de que deseja eliminar este anexo?" + }, + "deletedAttachment": { + "message": "Anexo eliminado" + }, + "newAttachment": { + "message": "Adicionar novo anexo" + }, + "noAttachments": { + "message": "Sem anexos." + }, + "attachmentSaved": { + "message": "O anexo foi guardado." + }, + "file": { + "message": "Ficheiro" + }, + "selectFile": { + "message": "Selecione um ficheiro." + }, + "maxFileSize": { + "message": "O tamanho máximo do ficheiro é de 500 MB." + }, + "featureUnavailable": { + "message": "Funcionalidade indisponível" + }, + "updateKey": { + "message": "Não pode utilizar esta funcionalidade até atualizar a sua chave de encriptação." + }, + "premiumMembership": { + "message": "Adesão Premium" + }, + "premiumManage": { + "message": "Gerir adesão" + }, + "premiumManageAlert": { + "message": "Pode gerir a sua adesão premium no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "premiumRefresh": { + "message": "Atualizar adesão" + }, + "premiumNotCurrentMember": { + "message": "Não é atualmente um membro premium." + }, + "premiumSignUpAndGet": { + "message": "Registe-se para uma adesão premium e obtenha:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB de armazenamento encriptado para anexos de ficheiros." + }, + "ppremiumSignUpTwoStep": { + "message": "Opções de início de sessão de dois passos adicionais como YubiKey, FIDO U2F, e Duo." + }, + "ppremiumSignUpReports": { + "message": "Higiene de palavras-passe, saúde das contas, e relatórios de brechas de dados para manter o seu cofre seguro." + }, + "ppremiumSignUpTotp": { + "message": "Gerador de códigos de verificação TOTP (2FA) para credenciais no seu cofre." + }, + "ppremiumSignUpSupport": { + "message": "Prioridade no apoio ao cliente." + }, + "ppremiumSignUpFuture": { + "message": "Todas as funcionalidades premium futuras. Mais a chegar brevemente!" + }, + "premiumPurchase": { + "message": "Comprar Premium" + }, + "premiumPurchaseAlert": { + "message": "Pode comprar adesão premium no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "premiumCurrentMember": { + "message": "É um membro premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Obrigado por apoiar o Bitwarden." + }, + "premiumPrice": { + "message": "Tudo por apenas $PRICE$ /ano!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Atualização completada" + }, + "disableAutoTotpCopy": { + "message": "Desativar cópia automática de TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Se a sua credencial tem uma chave de autenticador anexada à mesma, o código de verificação TOTP é copiado automaticamente para a sua área de transferência quando quer que auto-preencha a credencial." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium requerido" + }, + "premiumRequiredDesc": { + "message": "É requerida uma adesão premium para utilizar esta funcionalidade." + }, + "enterVerificationCodeApp": { + "message": "Introduza o código de verificação de 6 dígitos da sua aplicação de autenticador." + }, + "enterVerificationCodeEmail": { + "message": "Introduza o código de verificação de 6 dígitos que foi enviado por email para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Email de verificação enviado para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Memorizar-me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Enviar código de verificação novamente" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizar outro método de início de sessão de dois passos" + }, + "insertYubiKey": { + "message": "Introduza a sua YubiKey na porta USB do seu computador, depois toque no botão da mesma." + }, + "insertU2f": { + "message": "Introduza a sua chave de segurança na porta USB do seu computador. Se tiver um botão, toque no mesmo." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Início de sessão indisponível" + }, + "noTwoStepProviders": { + "message": "Esta conta tem o início de sessão de dois passos ativado, no entanto, nenhum dos provedores de início de sessão de dois passos configurados são suportados por este navegador web." + }, + "noTwoStepProviders2": { + "message": "Por favor utilize um navegador web suportado (tal como o Chrome) e/ou adicione provedores adicionais que são melhor suportados entre navegadores web (tal como uma aplicação de autenticador)." + }, + "twoStepOptions": { + "message": "Opções de início de sessão de dois passos" + }, + "recoveryCodeDesc": { + "message": "Perdeu o acesso a todos os seus provedores de dois passos? Utilize o seu código de recuperação para desativar todos os provedores de dois passos da sua conta." + }, + "recoveryCodeTitle": { + "message": "Código de recuperação" + }, + "authenticatorAppTitle": { + "message": "Aplicação de autenticador" + }, + "authenticatorAppDesc": { + "message": "Utilize uma aplicação de autenticador (tal como Authy ou Google Authenticator) para gerar códigos de verificação baseados na hora.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Chave de segurança YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utilize uma YubiKey para aceder à sua conta. Funciona com YubiKey 4, 4 Nano, 4C, e dispositivos NEO." + }, + "duoDesc": { + "message": "Verifique com Duo Security utilizando a aplicação Duo Mobile, SMS, chamada telefónica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifique com Duo Security para a sua organização utilizando a aplicação Duo Mobile, SMS, chamada telefónica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Os códigos de verificação vão ser enviados para si." + }, + "selfHostedEnvironment": { + "message": "Ambiente auto-hospedado" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifique o URL de base da sua instalação local do Bitwarden alojada nas suas premissas." + }, + "customEnvironment": { + "message": "Ambiente personalizado" + }, + "customEnvironmentFooter": { + "message": "Para utilizadores avançados. Pode especificar o URL de base de cada serviço independentemente." + }, + "baseUrl": { + "message": "URL do servidor" + }, + "apiUrl": { + "message": "URL do servidor da API" + }, + "webVaultUrl": { + "message": "URL do servidor do cofre web" + }, + "identityUrl": { + "message": "URL do servidor de identidade" + }, + "notificationsUrl": { + "message": "URL do servidor de notificações" + }, + "iconsUrl": { + "message": "URL do servidor de ícones" + }, + "environmentSaved": { + "message": "Os URLs de ambiente foram guardados." + }, + "enableAutoFillOnPageLoad": { + "message": "Ativar auto-preenchimento no carregar da página" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Se um formulário de início de sessão for detetado, realizar automaticamente um auto-preenchimento quando a página web carregar." + }, + "experimentalFeature": { + "message": "Esta é atualmente uma funcionalidade experimental. Utilize por sua conta e risco." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Abrir popup do cofre" + }, + "commandOpenSidebar": { + "message": "Abrir cofre na barra lateral" + }, + "commandAutofillDesc": { + "message": "Auto-preencher o último início de sessão utilizado para o website atual" + }, + "commandGeneratePasswordDesc": { + "message": "Gerar e copiar uma nova palavra-passe aleatória para a área de transferência" + }, + "commandLockVaultDesc": { + "message": "Bloquear o cofre" + }, + "privateModeMessage": { + "message": "Infelizmente esta janela não está disponível no modo privado para este navegador." + }, + "customFields": { + "message": "Campos personalizados" + }, + "copyValue": { + "message": "Copiar valor" + }, + "value": { + "message": "Valor" + }, + "newCustomField": { + "message": "Novo campo personalizado" + }, + "dragToSort": { + "message": "Arraste para ordenar" + }, + "cfTypeText": { + "message": "Texto" + }, + "cfTypeHidden": { + "message": "Ocultado" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "popup2faCloseMessage": { + "message": "Clicar fora da janela popup para verificar o seu email pelo código de verificação irá causar com que este popup feche. Deseja abrir este popup numa nova janela para que este não se feche?" + }, + "popupU2fCloseMessage": { + "message": "Este navegador não pode processar solicitações U2F nesta janela popup. Pretende abrir este popup numa nova janela para que inicie sessão utilizando U2F?" + }, + "disableFavicon": { + "message": "Desativar ícones de websites" + }, + "disableFaviconDesc": { + "message": "Os ícones de websites providenciam uma imagem reconhecível ao lado de cada item de credencial no seu cofre." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Titular do cartão" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Marca" + }, + "expirationMonth": { + "message": "Mês de expiração" + }, + "expirationYear": { + "message": "Ano de expiração" + }, + "expiration": { + "message": "Expiração" + }, + "january": { + "message": "Janeiro" + }, + "february": { + "message": "Fevereiro" + }, + "march": { + "message": "Março" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Maio" + }, + "june": { + "message": "Junho" + }, + "july": { + "message": "Julho" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Setembro" + }, + "october": { + "message": "Outubro" + }, + "november": { + "message": "Novembro" + }, + "december": { + "message": "Dezembro" + }, + "securityCode": { + "message": "Código de segurança" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Título" + }, + "mr": { + "message": "Sr" + }, + "mrs": { + "message": "Sra" + }, + "ms": { + "message": "Sra" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Primeiro nome" + }, + "middleName": { + "message": "Nome do meio" + }, + "lastName": { + "message": "Último nome" + }, + "identityName": { + "message": "Nome de identidade" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Número de segurança social" + }, + "passportNumber": { + "message": "Número do passaporte" + }, + "licenseNumber": { + "message": "Número da licença" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telefone" + }, + "address": { + "message": "Endereço" + }, + "address1": { + "message": "Endereço 1" + }, + "address2": { + "message": "Endereço 2" + }, + "address3": { + "message": "Endereço 3" + }, + "cityTown": { + "message": "Cidade / localidade" + }, + "stateProvince": { + "message": "Estado / província" + }, + "zipPostalCode": { + "message": "Código postal" + }, + "country": { + "message": "País" + }, + "type": { + "message": "Tipo" + }, + "typeLogin": { + "message": "Credencial" + }, + "typeLogins": { + "message": "Credenciais" + }, + "typeSecureNote": { + "message": "Nota segura" + }, + "typeCard": { + "message": "Cartão" + }, + "typeIdentity": { + "message": "Identidade" + }, + "passwordHistory": { + "message": "Histórico de palavras-passe" + }, + "back": { + "message": "Retroceder" + }, + "collections": { + "message": "Coleções" + }, + "favorites": { + "message": "Favoritos" + }, + "popOutNewWindow": { + "message": "Enviar para uma nova janela" + }, + "refresh": { + "message": "Atualizar" + }, + "cards": { + "message": "Cartões" + }, + "identities": { + "message": "Identidades" + }, + "logins": { + "message": "Credenciais" + }, + "secureNotes": { + "message": "Notas seguras" + }, + "clear": { + "message": "Limpar", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Verifica se a palavra-passe foi exposta." + }, + "passwordExposed": { + "message": "Esta palavra-passe foi exposta $VALUE$ vez(es) em brechas de dados. Deve alterá-la.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Esta palavra-passe não foi encontrada em nenhuma brecha de dados conhecida. Esta deve ser segura de utilizar." + }, + "baseDomain": { + "message": "Domínio base" + }, + "host": { + "message": "Servidor", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exato" + }, + "startsWith": { + "message": "Começa por" + }, + "regEx": { + "message": "Expressão regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Deteção de correspondência", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Deteção de correspondência predefinida", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Alternar opções" + }, + "toggleCurrentUris": { + "message": "Alternar URIs atuais", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI atual", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organização", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tipos" + }, + "allItems": { + "message": "Todos os itens" + }, + "noPasswordsInList": { + "message": "Não existem palavras-passe para listar." + }, + "remove": { + "message": "Remover" + }, + "default": { + "message": "Predefinido" + }, + "dateUpdated": { + "message": "Atualizado", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Palavra passe atualizada", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Tem a certeza de que pretende utilizar a opção \"Nunca\"? Definir as suas opções de bloqueio para \"Nunca\" armazena a chave de encriptação do seu cofre no seu dispositivo. Se utilizar esta opção deve assegurar-se de que mantém o seu dispositivo devidamente protegido." + }, + "noOrganizationsList": { + "message": "Você não pertence a nenhuma organização. Organizações permitem-lhe partilhar itens em segurança com outros utilizadores." + }, + "noCollectionsInList": { + "message": "Não existem coleções para listar." + }, + "ownership": { + "message": "Propriedade" + }, + "whoOwnsThisItem": { + "message": "Quem é o proprietário deste item?" + }, + "strong": { + "message": "Forte", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Boa", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Fraca", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Palavra-passe mestra fraca" + }, + "weakMasterPasswordDesc": { + "message": "A palavra-passe mestra que escolheu é fraca. Deve utilizar uma palavra-passe mestra forte (ou uma frase-passe) para proteger adequadamente a sua conta Bitwarden. Tem a certeza de que pretende utilizar esta palavra-passe mestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloquear com PIN" + }, + "setYourPinCode": { + "message": "Defina o seu código PIN para desbloquear o Bitwarden. As suas definições PIN serão redefinidas se terminar sessão completamente da aplicação." + }, + "pinRequired": { + "message": "O código PIN é requerido." + }, + "invalidPin": { + "message": "Código PIN inválido." + }, + "verifyPin": { + "message": "Verificar PIN" + }, + "yourVaultIsLockedPinCode": { + "message": "O seu cofre está bloqueado. Verifique o seu PIN para continuar." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloquear com palavra-passe mestra quando reiniciar o navegador" + }, + "selectOneCollection": { + "message": "Tem de selecionar pelo menos uma coleção." + }, + "cloneItem": { + "message": "Clonar item" + }, + "clone": { + "message": "Clonar" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Uma ou mais políticas de organização estão a afetar as suas definições do gerador." + }, + "vaultTimeoutAction": { + "message": "Ação de expiração do cofre" + }, + "lock": { + "message": "Bloquear", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Lixo", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Pesquisar lixo" + }, + "permanentlyDeleteItem": { + "message": "Eliminar item permanentemente" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Tem a certeza de que pretende eliminar este item permanentemente?" + }, + "permanentlyDeletedItem": { + "message": "Item eliminado permanentemente" + }, + "restoreItem": { + "message": "Restaurar item" + }, + "restoreItemConfirmation": { + "message": "Tem a certeza de que pretende restaurar este item?" + }, + "restoredItem": { + "message": "Item restaurado" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Terminar sessão irá remover todos os acessos ao seu cofre e requer autenticação online após o período de expiração. Tem a certeza de que pretende utilizar esta definição?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmação de expiração do cofre" + }, + "autoFillAndSave": { + "message": "Auto-preencher e guardar" + }, + "autoFillSuccessAndSavedUri": { + "message": "Item auto-preenchido e URI guardado" + }, + "autoFillSuccess": { + "message": "Item auto-preenchido" + }, + "setMasterPassword": { + "message": "Definir palavra-passe mestra" + }, + "masterPasswordPolicyInEffect": { + "message": "Uma ou mais políticas da organização requerem que a sua palavra-passe mestra cumpra aos seguintes requisitos:" + }, + "policyInEffectMinComplexity": { + "message": "Pontuação mínima de complexidade de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Comprimento mínimo de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contém um ou mais caracteres em maiúsculas" + }, + "policyInEffectLowercase": { + "message": "Contém um ou mais caracteres em minúsculas" + }, + "policyInEffectNumbers": { + "message": "Contém um ou mais números" + }, + "policyInEffectSpecial": { + "message": "Contém um ou mais dos seguintes caracteres especiais $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "A sua nova palavra-passe mestra não cumpre os requisitos da política." + }, + "acceptPolicies": { + "message": "Ao marcar esta caixa concorda com o seguinte:" + }, + "acceptPoliciesError": { + "message": "Os Termos de Serviço e a Política de Privacidade não foram aceites." + }, + "termsOfService": { + "message": "Termos de serviço" + }, + "privacyPolicy": { + "message": "Política de privacidade" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before this function can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ não é um domínio válido", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Texto" + }, + "sendTypeFile": { + "message": "Ficheiro" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copiar Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remover palavra-passe" + }, + "delete": { + "message": "Eliminar" + }, + "removedPassword": { + "message": "Palavra-passe removida" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + } +} diff --git a/apps/browser/src/_locales/ro/messages.json b/apps/browser/src/_locales/ro/messages.json new file mode 100644 index 0000000000..9bb0a3154d --- /dev/null +++ b/apps/browser/src/_locales/ro/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Manager de parole gratuit", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Un manager de parole sigur și gratuit pentru toate dispozitivele dvs.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Autentificați-vă sau creați un cont nou pentru a accesa seiful dvs. securizat." + }, + "createAccount": { + "message": "Creare cont" + }, + "login": { + "message": "Autentificare" + }, + "enterpriseSingleSignOn": { + "message": "Conectare unică organizație (SSO)" + }, + "cancel": { + "message": "Anulare" + }, + "close": { + "message": "Închidere" + }, + "submit": { + "message": "Trimitere" + }, + "emailAddress": { + "message": "Adresă de e-mail" + }, + "masterPass": { + "message": "Parolă principală" + }, + "masterPassDesc": { + "message": "Parola principală este parola pe care o utilizați pentru a vă accesa seiful. Este foarte important să nu uitați această parolă. Nu există nicio modalitate de a recupera parola în cazul în care ați uitat-o." + }, + "masterPassHintDesc": { + "message": "Un indiciu pentru parola principală vă poate ajuta să v-o reamintiți dacă o uitați." + }, + "reTypeMasterPass": { + "message": "Reintroducere parolă principală" + }, + "masterPassHint": { + "message": "Indiciu pentru parola principală (opțional)" + }, + "tab": { + "message": "Filă" + }, + "myVault": { + "message": "Seiful meu" + }, + "tools": { + "message": "Unelte" + }, + "settings": { + "message": "Setări" + }, + "currentTab": { + "message": "Fila curentă" + }, + "copyPassword": { + "message": "Copiere parolă" + }, + "copyNote": { + "message": "Copiere notă" + }, + "copyUri": { + "message": "Copiere URL" + }, + "copyUsername": { + "message": "Copiere nume utilizator" + }, + "copyNumber": { + "message": "Copiere număr" + }, + "copySecurityCode": { + "message": "Copiere cod de securitate" + }, + "autoFill": { + "message": "Auto-completare" + }, + "generatePasswordCopied": { + "message": "Generare parolă (s-a copiat)" + }, + "copyElementIdentifier": { + "message": "Copiere nume de câmp personalizat" + }, + "noMatchingLogins": { + "message": "Nu există potrivire de autentificări." + }, + "unlockVaultMenu": { + "message": "Deblocați-vă seiful" + }, + "loginToVaultMenu": { + "message": "Conectați-vă la seif" + }, + "autoFillInfo": { + "message": "Nu sunt disponibile autentificări pentru auto-completare în fila curentă a browserului." + }, + "addLogin": { + "message": "Adăugare autentificare" + }, + "addItem": { + "message": "Adăugare articol" + }, + "passwordHint": { + "message": "Indiciu parolă" + }, + "enterEmailToGetHint": { + "message": "Adresa de e-mail a contului pentru primirea indiciului parolei principale." + }, + "getMasterPasswordHint": { + "message": "Obținere indiciu parolă principală" + }, + "continue": { + "message": "Continuare" + }, + "sendVerificationCode": { + "message": "Trimite un cod de verificare la adresa dvs. de e-mail" + }, + "sendCode": { + "message": "Trimitere cod" + }, + "codeSent": { + "message": "Cod trimis" + }, + "verificationCode": { + "message": "Cod de verificare" + }, + "confirmIdentity": { + "message": "Confirmați-vă identitatea pentru a continua." + }, + "account": { + "message": "Cont" + }, + "changeMasterPassword": { + "message": "Schimbare parolă principală" + }, + "fingerprintPhrase": { + "message": "Frază amprentă", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fraza amprentă a contului dvs.", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Autentificare în două etape" + }, + "logOut": { + "message": "Deconectare" + }, + "about": { + "message": "Despre" + }, + "version": { + "message": "Versiune" + }, + "save": { + "message": "Salvare" + }, + "move": { + "message": "Mutare" + }, + "addFolder": { + "message": "Adăugare dosar" + }, + "name": { + "message": "Denumire" + }, + "editFolder": { + "message": "Editare dosar" + }, + "deleteFolder": { + "message": "Ștergere dosar" + }, + "folders": { + "message": "Dosare" + }, + "noFolders": { + "message": "Nu există niciun dosar de afișat." + }, + "helpFeedback": { + "message": "Ajutor și feedback" + }, + "sync": { + "message": "Sincronizare" + }, + "syncVaultNow": { + "message": "Sincronizare seif acum" + }, + "lastSync": { + "message": "Ultima sincronizare:" + }, + "passGen": { + "message": "Generator de parole" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Generează automat parole unice și puternice pentru autentificările dvs." + }, + "bitWebVault": { + "message": "Seif web Bitwarden" + }, + "importItems": { + "message": "Import elemente" + }, + "select": { + "message": "Selectare" + }, + "generatePassword": { + "message": "Generare parolă" + }, + "regeneratePassword": { + "message": "Regenerare parolă" + }, + "options": { + "message": "Opțiuni" + }, + "length": { + "message": "Lungime" + }, + "uppercase": { + "message": "Litere mari (A-Z)" + }, + "lowercase": { + "message": "Litere mici (a-z)" + }, + "numbers": { + "message": "Numere (0-9)" + }, + "specialCharacters": { + "message": "Caractere speciale (!@#$%^&*)" + }, + "numWords": { + "message": "Număr de cuvinte" + }, + "wordSeparator": { + "message": "Separator de cuvinte" + }, + "capitalize": { + "message": "Se folosesc majuscule inițiale", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Se includ cifre" + }, + "minNumbers": { + "message": "Minimum de cifre" + }, + "minSpecial": { + "message": "Minim de caractere speciale" + }, + "avoidAmbChar": { + "message": "Se evită caracterele ambigue" + }, + "searchVault": { + "message": "Căutare în seif" + }, + "edit": { + "message": "Editare" + }, + "view": { + "message": "Afișare" + }, + "noItemsInList": { + "message": "Nu există niciun articol de afișat." + }, + "itemInformation": { + "message": "Informații de autentificare" + }, + "username": { + "message": "Nume utilizator" + }, + "password": { + "message": "Parolă" + }, + "passphrase": { + "message": "Frază de acces" + }, + "favorite": { + "message": "Favorit" + }, + "notes": { + "message": "Note" + }, + "note": { + "message": "Notă" + }, + "editItem": { + "message": "Editare articol" + }, + "folder": { + "message": "Dosar" + }, + "deleteItem": { + "message": "Ștergere articol" + }, + "viewItem": { + "message": "Afișare articol" + }, + "launch": { + "message": "Lansare" + }, + "website": { + "message": "Sait web" + }, + "toggleVisibility": { + "message": "Comutare vizibilitate" + }, + "manage": { + "message": "Gestionare" + }, + "other": { + "message": "Altele" + }, + "rateExtension": { + "message": "Evaluare extensie" + }, + "rateExtensionDesc": { + "message": "Vă rugăm să luați în considerare să ne ajutați cu o recenzie bună!" + }, + "browserNotSupportClipboard": { + "message": "Browserul dvs. nu acceptă copierea în clipboard. Transcrieți datele manual." + }, + "verifyIdentity": { + "message": "Verificare identitate" + }, + "yourVaultIsLocked": { + "message": "Seiful dvs. este blocat. Verificați-vă identitatea pentru a continua." + }, + "unlock": { + "message": "Deblocare" + }, + "loggedInAsOn": { + "message": "Autentificat ca $EMAIL$ în $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Parolă principală incorectă" + }, + "vaultTimeout": { + "message": "Expirare seif" + }, + "lockNow": { + "message": "Blocare imediată" + }, + "immediately": { + "message": "Imediat" + }, + "tenSeconds": { + "message": "10 secunde" + }, + "twentySeconds": { + "message": "20 de secunde" + }, + "thirtySeconds": { + "message": "30 de secunde" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minute" + }, + "fiveMinutes": { + "message": "5 minute" + }, + "fifteenMinutes": { + "message": "15 minute" + }, + "thirtyMinutes": { + "message": "30 de minute" + }, + "oneHour": { + "message": "1 oră" + }, + "fourHours": { + "message": "4 ore" + }, + "onLocked": { + "message": "La blocarea dispozitivului" + }, + "onRestart": { + "message": "La repornirea browserului" + }, + "never": { + "message": "Niciodată" + }, + "security": { + "message": "Securitate" + }, + "errorOccurred": { + "message": "S-a produs o eroare" + }, + "emailRequired": { + "message": "Este necesară adresa de e-mail." + }, + "invalidEmail": { + "message": "Adresă de e-mail greșită." + }, + "masterPassRequired": { + "message": "Este necesară parola principală." + }, + "masterPassLength": { + "message": "Parola principală trebuie să conțină minimum 8 caractere." + }, + "masterPassDoesntMatch": { + "message": "Parola principală și confirmarea ei nu coincid!" + }, + "newAccountCreated": { + "message": "Noul dvs. cont a fost creat! Acum vă puteți autentifica." + }, + "masterPassSent": { + "message": "V-am trimis un e-mail cu indiciul parolei principale." + }, + "verificationCodeRequired": { + "message": "Este necesar codul de verificare." + }, + "invalidVerificationCode": { + "message": "Cod de verificare nevalid" + }, + "valueCopied": { + "message": " $VALUE$ s-a copiat", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Nu se pot auto-completa datele de conectare pentru această pagină. În schimb, puteți copia și lipi aceste date." + }, + "loggedOut": { + "message": "Deconectat" + }, + "loginExpired": { + "message": "Sesiunea de autentificare a expirat." + }, + "logOutConfirmation": { + "message": "Sigur doriți să vă deconectați?" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Nu" + }, + "unexpectedError": { + "message": "A survenit o eroare neașteptată." + }, + "nameRequired": { + "message": "Numele utilizator este obligatoriu." + }, + "addedFolder": { + "message": "Dosar adăugat" + }, + "changeMasterPass": { + "message": "Schimbare parolă principală" + }, + "changeMasterPasswordConfirmation": { + "message": "Puteți modifica parola principală în seiful web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "twoStepLoginConfirmation": { + "message": "Autentificarea în două etape întărește siguranța contului dvs. prin solicitarea unei confirmări de autentificare cu un alt dispozitiv, cum ar fi: o cheie de securitate, o aplicație de autentificare, un SMS, un apel telefonic sau un e-mail. Autentificarea în două etape poate fi activată în seiful web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "editedFolder": { + "message": "Dosar editat" + }, + "deleteFolderConfirmation": { + "message": "Sigur doriți să ștergeți dosarul?" + }, + "deletedFolder": { + "message": "Dosar șters" + }, + "gettingStartedTutorial": { + "message": "Tutorial introductiv" + }, + "gettingStartedTutorialVideo": { + "message": "Urmăriți tutorialul nostru pentru a afla cum să beneficiați cât mai mult de această extensie a browserului." + }, + "syncingComplete": { + "message": "Sincronizare completă" + }, + "syncingFailed": { + "message": "Sincronizare eșuată" + }, + "passwordCopied": { + "message": "Parola s-a copiat" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "URI nou" + }, + "addedItem": { + "message": "Articol adăugat" + }, + "editedItem": { + "message": "Articol editat" + }, + "deleteItemConfirmation": { + "message": "Sigur doriți să trimiteți în coșul de reciclare?" + }, + "deletedItem": { + "message": "Articolul a fost trimis în coșul de reciclare" + }, + "overwritePassword": { + "message": "Modificare parolă" + }, + "overwritePasswordConfirmation": { + "message": "Sigur doriți să modificați parola curentă?" + }, + "overwriteUsername": { + "message": "Suprascrieți numele de utilizator" + }, + "overwriteUsernameConfirmation": { + "message": "Sunteți sigur că doriți să suprascrieți numele de utilizator curent?" + }, + "searchFolder": { + "message": "Căutare în dosar" + }, + "searchCollection": { + "message": "Căutare în colecție" + }, + "searchType": { + "message": "Căutare în tipuri" + }, + "noneFolder": { + "message": "Fără dosar", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Dezactivare \"Notificare de adăugare a autentificărilor\"" + }, + "addLoginNotificationDesc": { + "message": "\"Notificarea de adăugare a autentificării\" vă solicită automat salvarea noilor conturi în seif de fiecare dată când vă conectați la ele pentru prima dată." + }, + "dontShowCardsCurrentTab": { + "message": "Nu se afișează carduri în pagina filei curente" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Informațiile de tip card din seiful dvs. sunt afișate în pagina din \"Fila curentă\" pentru acces ușor la auto-completare." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Nu se afișează identități în pagina filei curente" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Informațiile de tip identitate din seiful dvs. sunt afișate în pagina din \"Fila curentă\" pentru acces ușor la auto-completare." + }, + "clearClipboard": { + "message": "Golire clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Șterge automat valorile copiate din clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Ar trebui ca Bitwarden să memoreze această parolă pentru dvs.?" + }, + "notificationAddSave": { + "message": "Salvare" + }, + "disableChangedPasswordNotification": { + "message": "Dezactivare notificare de modificare a parolei" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Notificarea de modificare a parolei\" vă propune automat să actualizați o parolă din seif oricând se detectează că ați modificat-o pe un sait." + }, + "notificationChangeDesc": { + "message": "Doriți să actualizați această parolă în Bitwarden?" + }, + "notificationChangeSave": { + "message": "Actualizare" + }, + "disableContextMenuItem": { + "message": "Dezactivare opțiuni meniu contextual" + }, + "disableContextMenuItemDesc": { + "message": "Opțiunile din meniul contextual oferă acces rapid la generarea de parole și la autentificările pentru saitul web din fila curentă." + }, + "defaultUriMatchDetection": { + "message": "Detectare de potrivire URI implicită", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Alege modul implicit de gestionare a detectării de potrivire URI pentru conectări când se efectuează acțiuni precum auto-completarea." + }, + "theme": { + "message": "Temă" + }, + "themeDesc": { + "message": "Schimbă tema de culori a aplicației." + }, + "dark": { + "message": "Întunecat", + "description": "Dark color" + }, + "light": { + "message": "Luminos", + "description": "Light color" + }, + "solarizedDark": { + "message": "Întuneric solarizat", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export seif" + }, + "fileFormat": { + "message": "Format fișier" + }, + "warning": { + "message": "AVERTISMENT", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirmare export seif" + }, + "exportWarningDesc": { + "message": "Acest export conține datele dvs. din seif în format necriptat. Nu ar trebui să stocați sau să trimiteți fișierul pe canale nesecurizate (cum ar fi e-mail). Ștergeți-l imediat după ce nu îl mai folosiți." + }, + "encExportKeyWarningDesc": { + "message": "Acest export criptează datele, utilizând cheia de criptare a contului. Dacă revocați vreodată cheia de criptare a contului dvs., ar trebui să exportați din nou, deoarece nu veți putea decripta acest fișier de export." + }, + "encExportAccountWarningDesc": { + "message": "Cheile de criptare a contului sunt unice fiecărui cont de utilizator Bitwarden, astfel încât nu puteți importa un export criptat într-un cont diferit." + }, + "exportMasterPassword": { + "message": "Introduceți parola principală pentru a exporta datele din seif." + }, + "shared": { + "message": "Partajat" + }, + "learnOrg": { + "message": "Aflați despre organizații" + }, + "learnOrgConfirmation": { + "message": "Bitwarden vă permite să vă partajați articolele seifului cu alte persoane utilizând o organizație. Doriți să vizitați site-ul bitwarden.com pentru a afla mai multe?" + }, + "moveToOrganization": { + "message": "Mutare la organizație" + }, + "share": { + "message": "Partajare" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ mutat la $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Alegeți o organizație la care doriți să mutați acest articol. Mutarea într-o organizație transferă proprietatea asupra articolului către organizația respectivă. Nu veți mai fi proprietarul direct al acestui articol odată ce a fost mutat." + }, + "learnMore": { + "message": "Aflați mai multe" + }, + "authenticatorKeyTotp": { + "message": "Cheie autentificare (TOTP)" + }, + "verificationCodeTotp": { + "message": "Cod de verificare (TOTP)" + }, + "copyVerificationCode": { + "message": "Copiere cod de verificare" + }, + "attachments": { + "message": "Atașamente" + }, + "deleteAttachment": { + "message": "Ștergere atașament" + }, + "deleteAttachmentConfirmation": { + "message": "Sigur doriți să ștergeți acest atașament?" + }, + "deletedAttachment": { + "message": "Atașament șters" + }, + "newAttachment": { + "message": "Adăugare atașament nou" + }, + "noAttachments": { + "message": "Niciun atașament." + }, + "attachmentSaved": { + "message": "Atașamentul a fost salvat." + }, + "file": { + "message": "Fișier" + }, + "selectFile": { + "message": "Selectare fișier." + }, + "maxFileSize": { + "message": "Mărimea maximă a fișierului este de 500 MB." + }, + "featureUnavailable": { + "message": "Caracteristică indisponibilă" + }, + "updateKey": { + "message": "Nu puteți utiliza această caracteristică înainte de a actualiza cheia de criptare." + }, + "premiumMembership": { + "message": "Membru Premium" + }, + "premiumManage": { + "message": "Gestionare statut de membru" + }, + "premiumManageAlert": { + "message": "Vă puteți gestiona statutul de membru pe saitul web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "premiumRefresh": { + "message": "Actualizare statut de membru" + }, + "premiumNotCurrentMember": { + "message": "În prezent nu sunteți un membru Premium." + }, + "premiumSignUpAndGet": { + "message": "Înscrieți-vă pentru statutul de membru Premium și obțineți:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB spațiu de stocare criptat pentru atașamente de fișiere." + }, + "ppremiumSignUpTwoStep": { + "message": "Opțiuni adiționale de conectare în două etape, cum ar fi YubiKey, FIDO U2F și Duo." + }, + "ppremiumSignUpReports": { + "message": "Rapoarte privind igiena parolelor, sănătatea contului și breșele de date pentru a vă păstra seiful în siguranță." + }, + "ppremiumSignUpTotp": { + "message": "Generator de cod de verificare TOTP (2FA) pentru autentificările din seif." + }, + "ppremiumSignUpSupport": { + "message": "Asistență prioritară pentru clienți." + }, + "ppremiumSignUpFuture": { + "message": "Toate caracteristicile Premium viitoare. Mai multe în curând!" + }, + "premiumPurchase": { + "message": "Achiziționare abonament Premium" + }, + "premiumPurchaseAlert": { + "message": "Puteți achiziționa un abonament premium pe saitul web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "premiumCurrentMember": { + "message": "Sunteți un membru Premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Vă mulțumim pentru susținerea Bitwarden." + }, + "premiumPrice": { + "message": "Totul pentru doar %price% /an!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Actualizare completă" + }, + "disableAutoTotpCopy": { + "message": "Dezactivare copiere automată a codului TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Dacă autentificarea dvs. are o cheie atașată, codul de verificare TOTP este copiat în clipboard de fiecare dată când efectuați auto-completarea datelor de conectare." + }, + "disableAutoBiometricsPrompt": { + "message": "Nu solicitați datele biometrice la pornire" + }, + "premiumRequired": { + "message": "Este necesară versiunea Premium" + }, + "premiumRequiredDesc": { + "message": "Este necesar statutul de membru Premium pentru a utiliza această caracteristică." + }, + "enterVerificationCodeApp": { + "message": "Introducere cod de verificare din 6 cifre din aplicația de autentificare." + }, + "enterVerificationCodeEmail": { + "message": "Introducere cod de verificare din 6 cifre care a fost trimis prin e-mail la $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mailul de verificare a fost trimis la $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Memorare autentificare" + }, + "sendVerificationCodeEmailAgain": { + "message": "Retrimitere e-mail cu codul de verificare" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizare de metodă diferită de autentificare în două etape" + }, + "insertYubiKey": { + "message": "Introduceți YubiKey în portul USB al calculatorului apoi apăsați butonul acestuia." + }, + "insertU2f": { + "message": "Introduceți cheia de securitate în portul USB al computerului. Dacă are un buton, apăsați-l." + }, + "webAuthnNewTab": { + "message": "Pentru a începe verificarea WebAuthn 2FA. Faceți clic pe butonul de mai jos pentru a deschide o filă nouă și urmați instrucțiunile furnizate în filă nouă." + }, + "webAuthnNewTabOpen": { + "message": "Deschideți o filă nouă" + }, + "webAuthnAuthenticate": { + "message": "Autentificare WebAuthn" + }, + "loginUnavailable": { + "message": "Conectare indisponibilă" + }, + "noTwoStepProviders": { + "message": "Acest cont are activată autentificarea în două etape, dar niciunul dintre furnizorii configurați pentru aceasta nu este acceptat de acest browser web." + }, + "noTwoStepProviders2": { + "message": "Utilizați un browser acceptat (cum ar fi Chrome) și/sau adăugați furnizori suplimentari mai bine susținuți de browserele web (cum ar fi o aplicație de autentificare)." + }, + "twoStepOptions": { + "message": "Opțiuni de autentificare în două etape" + }, + "recoveryCodeDesc": { + "message": "Ați pierdut accesul la toți furnizorii de autentificare în două etape? Utilizați codul de recuperare pentru a dezactiva toți acești furnizori din contul dvs." + }, + "recoveryCodeTitle": { + "message": "Cod de recuperare" + }, + "authenticatorAppTitle": { + "message": "Aplicație de autentificare" + }, + "authenticatorAppDesc": { + "message": "Utilizați o aplicație de autentificare (cum ar fi Authy sau Google Authenticator) pentru a genera codurile de verificare bazate pe timp.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Cheie de securitate YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utilizați YubiKey pentru a accesa contul dvs. Funcționează cu dispozitivele YubiKey 4, 4 Nano, 4C și NEO." + }, + "duoDesc": { + "message": "Verificați cu Duo Security utilizând aplicația Duo Mobile, SMS, apel telefonic sau cheia de securitate U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verificați cu Duo Security pentru organizația dvs. utilizând aplicația Duo Mobile, SMS, apel telefonic sau cheia de securitate U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Utilizați orice cheie de securitate activată WebAuthn pentru a vă accesa contul." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Codurile de verificare vor fi trimise prin e-mail." + }, + "selfHostedEnvironment": { + "message": "Mediu de găzduire personal" + }, + "selfHostedEnvironmentFooter": { + "message": "Specificați URL-ul de bază al implementări Bitwarden găzduită local." + }, + "customEnvironment": { + "message": "Mediu personalizat" + }, + "customEnvironmentFooter": { + "message": "Pentru utilizatorii avansați. Puteți specifica URL-ul de bază al fiecărui serviciu în mod independent." + }, + "baseUrl": { + "message": "URL server" + }, + "apiUrl": { + "message": "URL server API" + }, + "webVaultUrl": { + "message": "URL server seif Web" + }, + "identityUrl": { + "message": "URL server de identificare" + }, + "notificationsUrl": { + "message": "URL server de notificări" + }, + "iconsUrl": { + "message": "URL server de iconuri" + }, + "environmentSaved": { + "message": "URL-urile mediului au fost salvate." + }, + "enableAutoFillOnPageLoad": { + "message": "Activare auto-completare la încărcarea paginii" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Dacă este detectat un formular de autentificare, se efectuează automat o completare a acestuia la încărcarea paginii." + }, + "experimentalFeature": { + "message": "În acest moment, aceasta funcțiune este experimentală. O puteți folosi pe propria răspundere." + }, + "defaultAutoFillOnPageLoad": { + "message": "Setarea implicită de completare automată pentru articole de conectare" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "După activarea completării automate la încărcarea paginii, puteți activa sau dezactiva funcția pentru elementele de conectare individuale. Aceasta este setarea implicită pentru articolele de conectare care nu sunt configurate separat." + }, + "itemAutoFillOnPageLoad": { + "message": "Completare automată la încărcarea paginii (dacă este activată în opțiuni)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Utilizați setarea implicită" + }, + "autoFillOnPageLoadYes": { + "message": "Completare automată la încărcarea paginii" + }, + "autoFillOnPageLoadNo": { + "message": "Nu completați automat la încărcarea paginii" + }, + "commandOpenPopup": { + "message": "Deschidere seif pop-up" + }, + "commandOpenSidebar": { + "message": "Deschidere seif în bara laterală" + }, + "commandAutofillDesc": { + "message": "Auto-completare a ultimei autentificări utilizate pe saitul web curent" + }, + "commandGeneratePasswordDesc": { + "message": "Generare parolă aleatorie și copiere în clipboard" + }, + "commandLockVaultDesc": { + "message": "Blocare seif" + }, + "privateModeWarning": { + "message": "Suportul pentru modul privat este experimental, iar unele caracteristici sunt limitate." + }, + "customFields": { + "message": "Câmpuri particularizate" + }, + "copyValue": { + "message": "Copiere valoare" + }, + "value": { + "message": "Valoare" + }, + "newCustomField": { + "message": "Câmp nou particularizat" + }, + "dragToSort": { + "message": "Tragere pentru sortare" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Ascuns" + }, + "cfTypeBoolean": { + "message": "Valoare logică" + }, + "cfTypeLinked": { + "message": "Conectat", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Valoarea conectată", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Dând clic în afara ferestrei pop-up pentru a vă verifica e-mailul pentru codul de verificare, aceasta se va închide. Doriți să deschideți acest pop-up într-o fereastră nouă, astfel încât aceasta să nu se închidă?" + }, + "popupU2fCloseMessage": { + "message": "Acest browser nu poate procesa cererile U2F în această fereastră pop-up. Doriți să deschideți acest pop-up într-o fereastră nouă, astfel încât să vă puteți conecta utilizând U2F?" + }, + "disableFavicon": { + "message": "Dezactivare iconuri sait" + }, + "disableFaviconDesc": { + "message": "Iconurile saiturilor oferă o imagine identificabilă lângă fiecare element de conectare din seiful dvs." + }, + "disableBadgeCounter": { + "message": "Dezactivați contorul de insigne" + }, + "disableBadgeCounterDesc": { + "message": "Contorul de insigne arată câte conectări aveți în seiful dvs. pentru pagina curentă." + }, + "cardholderName": { + "message": "Deținător card" + }, + "number": { + "message": "Număr card" + }, + "brand": { + "message": "Tip card" + }, + "expirationMonth": { + "message": "Luna expirării" + }, + "expirationYear": { + "message": "Anul expirării" + }, + "expiration": { + "message": "Expirare" + }, + "january": { + "message": "ianuarie" + }, + "february": { + "message": "februarie" + }, + "march": { + "message": "martie" + }, + "april": { + "message": "aprilie" + }, + "may": { + "message": "mai" + }, + "june": { + "message": "iunie" + }, + "july": { + "message": "iulie" + }, + "august": { + "message": "august" + }, + "september": { + "message": "septembrie" + }, + "october": { + "message": "octombrie" + }, + "november": { + "message": "noiembrie" + }, + "december": { + "message": "decembrie" + }, + "securityCode": { + "message": "Cod de securitate (CVV/CVC)" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "Titlu" + }, + "mr": { + "message": "Dl" + }, + "mrs": { + "message": "Dna" + }, + "ms": { + "message": "Dra" + }, + "dr": { + "message": "Dr." + }, + "firstName": { + "message": "Prenume" + }, + "middleName": { + "message": "Al doilea prenume" + }, + "lastName": { + "message": "Nume" + }, + "fullName": { + "message": "Numele complet" + }, + "identityName": { + "message": "Identitate" + }, + "company": { + "message": "Companie" + }, + "ssn": { + "message": "Cod Numeric Personal" + }, + "passportNumber": { + "message": "Număr CI / Pașaport" + }, + "licenseNumber": { + "message": "Număr licență" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresă" + }, + "address1": { + "message": "Adresă 1" + }, + "address2": { + "message": "Adresă 2" + }, + "address3": { + "message": "Adresă 3" + }, + "cityTown": { + "message": "Localitate" + }, + "stateProvince": { + "message": "Județ" + }, + "zipPostalCode": { + "message": "Cod poștal" + }, + "country": { + "message": "Țară" + }, + "type": { + "message": "Tip" + }, + "typeLogin": { + "message": "Conectare" + }, + "typeLogins": { + "message": "Conectări" + }, + "typeSecureNote": { + "message": "Notă protejată" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identitate" + }, + "passwordHistory": { + "message": "Istoric parole" + }, + "back": { + "message": "Înapoi" + }, + "collections": { + "message": "Colecții" + }, + "favorites": { + "message": "Favorite" + }, + "popOutNewWindow": { + "message": "Deschidere într-o fereastră nouă" + }, + "refresh": { + "message": "Reîmprospătare" + }, + "cards": { + "message": "Carduri" + }, + "identities": { + "message": "Identități" + }, + "logins": { + "message": "Conectări" + }, + "secureNotes": { + "message": "Note protejate" + }, + "clear": { + "message": "Ștergere", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Verificați dacă parola a fost dezvăluită." + }, + "passwordExposed": { + "message": "Această parolă a fost dezvăluită de $VALUE$ ori în breșe de date. Ar trebui să o schimbați.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Aceasta parola nu a fost găsită în nicio breșă de date cunoscută. Ar trebui să fie sigură de utilizat." + }, + "baseDomain": { + "message": "Domeniu de bază", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nume de domeniu", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Gazdă", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Începe cu" + }, + "regEx": { + "message": "Expresie regulată", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Detectare de potrivire", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detectare de potrivire implicită", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Activare/dezactivare opțiuni" + }, + "toggleCurrentUris": { + "message": "Comutare URI-uri curente", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI curent", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organizație", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Tipuri" + }, + "allItems": { + "message": "Toate elementele" + }, + "noPasswordsInList": { + "message": "Nicio parolă de afișat." + }, + "remove": { + "message": "Ștergere" + }, + "default": { + "message": "Implicit" + }, + "dateUpdated": { + "message": "S-a actualizat", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parola s-a actualizat", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Sigur doriți să utilizați opțiunea \"Niciodată\"? Setarea opțiunii de blocare pe \"Niciodată\" vă salvează cheia de criptare pe dispozitiv. Dacă utilizați această opțiune ar trebui să vă asigurați că vă păstrați dispozitivul protejat corespunzător." + }, + "noOrganizationsList": { + "message": "Nu aparțineți niciunei organizații. Organizațiile vă permit să partajați în siguranță articole cu alți utilizatori." + }, + "noCollectionsInList": { + "message": "Nu există nicio colecție de afișat." + }, + "ownership": { + "message": "Proprietar" + }, + "whoOwnsThisItem": { + "message": "Cine deține acest element?" + }, + "strong": { + "message": "Puternică", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bună", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slabă", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Parolă principală slabă" + }, + "weakMasterPasswordDesc": { + "message": "Parola principală aleasă este slabă. Ar trebui să folosiți o parolă principală (sau o frază de acces) puternică pentru a vă proteja corespunzător contul Bitwarden. Sigur doriți să folosiți această parolă principală?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Deblocare cu codul PIN" + }, + "setYourPinCode": { + "message": "Stabiliți codul PIN de deblocare Bitwarden. Setările codului PIN vor fi reinițializate dacă vă deconectați vreodată din aplicație." + }, + "pinRequired": { + "message": "Codul PIN este necesar." + }, + "invalidPin": { + "message": "Codul PIN este invalid." + }, + "unlockWithBiometrics": { + "message": "Deblocare folosind biometria" + }, + "awaitDesktop": { + "message": "Se așteaptă confirmarea de la desktop" + }, + "awaitDesktopDesc": { + "message": "Vă rugăm să confirmați utilizarea biometriei în aplicația Bitwarden Desktop pentru a activa biometria pentru browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Blocare cu parola principală la repornirea browserului" + }, + "selectOneCollection": { + "message": "Trebuie să selectați cel puțin o colecție." + }, + "cloneItem": { + "message": "Clonare articol" + }, + "clone": { + "message": "Clonare" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una sau mai multe politici organizaționale vă afectează setările generatorului." + }, + "vaultTimeoutAction": { + "message": "Acțiune la expirarea seifului" + }, + "lock": { + "message": "Blocare", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Coș de reciclare", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Căutare în coșul de reciclare" + }, + "permanentlyDeleteItem": { + "message": "Ștergere definitivă a articolului" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Sigur doriți să ștergeți definitiv acest articol?" + }, + "permanentlyDeletedItem": { + "message": "Articolul a fost șters definitiv" + }, + "restoreItem": { + "message": "Restabilire articol" + }, + "restoreItemConfirmation": { + "message": "Sigur doriți să restabiliți acest articol?" + }, + "restoredItem": { + "message": "Articol restabilit" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "După expirare, accesul la seiful dvs. va fi restricționat și va fi necesară autentificarea online. Sigur doriți să utilizați această setare?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmare acțiune la expirare" + }, + "autoFillAndSave": { + "message": "Auto-completare și Salvare" + }, + "autoFillSuccessAndSavedUri": { + "message": "Articolul s-a completat automat și URl-ul s-a salvat" + }, + "autoFillSuccess": { + "message": "Articolul s-a completat automat" + }, + "setMasterPassword": { + "message": "Setare parolă principală" + }, + "masterPasswordPolicyInEffect": { + "message": "Una sau mai multe politici ale organizației necesită ca parola principală să îndeplinească următoarele cerințe:" + }, + "policyInEffectMinComplexity": { + "message": "Scor minim de complexitate de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Lungime minimă de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Unul sau mai multe caractere majuscule" + }, + "policyInEffectLowercase": { + "message": "Unul sau mai multe caractere minuscule" + }, + "policyInEffectNumbers": { + "message": "Una sau mai multe cifre" + }, + "policyInEffectSpecial": { + "message": "Unul sau mai multe din următoarele caractere: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Noua dvs. parolă principală nu îndeplinește cerințele politicii." + }, + "acceptPolicies": { + "message": "Dacă bifați această casetă sunteți de acord cu următoarele:" + }, + "acceptPoliciesError": { + "message": "Termenii de utilizare și Politica de confidențialitate nu au fost recunoscute." + }, + "termsOfService": { + "message": "Termeni de utilizare" + }, + "privacyPolicy": { + "message": "Politică de confidențialitate" + }, + "hintEqualsPassword": { + "message": "Indiciul dvs. de parolă nu poate fi același cu parola dvs." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Verificare sincronizare desktop" + }, + "desktopIntegrationVerificationText": { + "message": "Verificați dacă aplicația desktop afișează această amprentă digitală:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Integrarea browserului nu este activată" + }, + "desktopIntegrationDisabledDesc": { + "message": "Integrarea browserului nu este activată în aplicația Bitwarden Desktop. Vă rugăm să o activați în setările din aplicația desktop." + }, + "startDesktopTitle": { + "message": "Porniți aplicația Bitwarden Desktop" + }, + "startDesktopDesc": { + "message": "Aplicația Bitwarden Desktop trebuie să fie pornită înainte de a putea fi utilizată deblocarea cu date biometrice." + }, + "errorEnableBiometricTitle": { + "message": "Nu se poate activa biometria" + }, + "errorEnableBiometricDesc": { + "message": "Acțiunea a fost anulată de aplicația desktop" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Aplicația desktop a invalidat canalul de comunicare securizată. Reîncercați această operație" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Comunicare desktop întreruptă" + }, + "nativeMessagingWrongUserDesc": { + "message": "Aplicația desktop este conectată la un alt cont. Vă rugăm să vă asigurați că ambele aplicații sunt înregistrate în același cont." + }, + "nativeMessagingWrongUserTitle": { + "message": "Eroare de cont" + }, + "biometricsNotEnabledTitle": { + "message": "Biometria nu a fost activată" + }, + "biometricsNotEnabledDesc": { + "message": "Biometria browserului necesită activarea mai întâi a biometriei de pe desktop în setări." + }, + "biometricsNotSupportedTitle": { + "message": "Biometria nu este acceptată" + }, + "biometricsNotSupportedDesc": { + "message": "Biometria browserului nu este acceptată pe acest dispozitiv." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permisiunea nu a fost furnizată" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Fără permisiunea de comunicare cu aplicația Bitwarden Desktop nu putem furniza date biometrice în extensia browserului. Încercați din nou." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Eroare solicitare permisiune" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Această acțiune nu se poate efectua în bara laterală, vă rugăm să reîncercați acțiunea în fereastra pop-up sau popup." + }, + "personalOwnershipSubmitError": { + "message": "Datorită unei politici pentru întreprinderi, vă este restricționată salvarea de elemente în seiful dvs. personal. Schimbați opțiunea de proprietate la o organizație și alegeți dintre colecțiile disponibile." + }, + "personalOwnershipPolicyInEffect": { + "message": "O politică de organizație vă afectează opțiunile de proprietate." + }, + "excludedDomains": { + "message": "Domenii excluse" + }, + "excludedDomainsDesc": { + "message": "Bitwarden nu va cere să salveze detaliile de conectare pentru aceste domenii. Trebuie să reîmprospătați pagina pentru ca modificările să intre în vigoare." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ nu este un domeniu valid", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Căutare Send-uri", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Adăugare Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "Fișier" + }, + "allSends": { + "message": "Toate Send-urile", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "S-a atins numărul maxim de accesări", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expirat" + }, + "pendingDeletion": { + "message": "Ștergere în așteptare" + }, + "passwordProtected": { + "message": "Protejat cu parolă" + }, + "copySendLink": { + "message": "Copiere link Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Eliminare parolă" + }, + "delete": { + "message": "Ștergere" + }, + "removedPassword": { + "message": "Parola a fost eliminată" + }, + "deletedSend": { + "message": "Send-ul a fost șters", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Link Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Dezactivat" + }, + "removePasswordConfirmation": { + "message": "Sigur doriți să eliminați parola?" + }, + "deleteSend": { + "message": "Ștergere Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Sigur doriți să ștergeți acest Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Editare Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Ce fel de Send este acesta?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Un nume prietenos pentru a descrie acest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Fișierul pe care doriți să-l trimiteți." + }, + "deletionDate": { + "message": "Data ștergerii" + }, + "deletionDateDesc": { + "message": "Send-ul va fi șters definitiv la data și ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data expirării" + }, + "expirationDateDesc": { + "message": "Dacă este setat, accesul la acest Send va expira la data și ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 zi" + }, + "days": { + "message": "$DAYS$ zile", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Personalizat" + }, + "maximumAccessCount": { + "message": "Număr maxim de accesări" + }, + "maximumAccessCountDesc": { + "message": "Dacă este configurat, utilizatorii nu vor mai putea accesa acest Send când a fost atins numărul maxim de accesări.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opțional, este necesară o parolă pentru ca utilizatorii să acceseze acest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Note private despre acest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Dezactivează acest Send astfel încât nimeni să nu-l poată accesa.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copiază acest link de Send în clipboard la salvare.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Textul pe care doriți să-l trimiteți." + }, + "sendHideText": { + "message": "Ascunde în mod implicit textul acestui Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Număr actual de accesări" + }, + "createSend": { + "message": "Creare de nou Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Parolă nouă" + }, + "sendDisabled": { + "message": "Send dezactivat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Datorită unei politici de întreprindere, puteți șterge numai un Send existent.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send creat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send editat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Pentru a alege un fișier, deschideți extensia în bara laterală (dacă este posibil) sau deschideți-o într-o fereastră nouă, făcând clic pe acest banner." + }, + "sendFirefoxFileWarning": { + "message": "Pentru a alege un fișier folosind Firefox, deschideți extensia din bara laterală sau deschideți o fereastră nouă făcând clic pe acest banner." + }, + "sendSafariFileWarning": { + "message": "Pentru a alege un fișier folosind Safari, deschideți o fereastră nouă făcând clic pe acest banner." + }, + "sendFileCalloutHeader": { + "message": "Înainte de a începe" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Pentru a utiliza un selector de date în stil calendar,", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "faceți clic aici", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "pentru ca fereastra dvs să apară.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Data de expirare furnizată nu este validă." + }, + "deletionDateIsInvalid": { + "message": "Data de ștergere furnizată nu este validă." + }, + "expirationDateAndTimeRequired": { + "message": "Sunt necesare o dată și o oră de expirare." + }, + "deletionDateAndTimeRequired": { + "message": "Sunt necesare o dată și o oră de ștergere." + }, + "dateParsingError": { + "message": "A survenit o eroare la salvarea datelor de ștergere și de expirare." + }, + "hideEmail": { + "message": "Ascundeți adresa mea de e-mail de la destinatari." + }, + "sendOptionsPolicyInEffect": { + "message": "Una sau mai multe politici organizaționale vă afectează opțiunile Send-ului." + }, + "passwordPrompt": { + "message": "Re-solicitare parolă principală" + }, + "passwordConfirmation": { + "message": "Confirmare parolă principală" + }, + "passwordConfirmationDesc": { + "message": "Această acțiune este protejată. Pentru a continua, vă rugăm să reintroduceți parola principală pentru a vă verifica identitatea." + }, + "emailVerificationRequired": { + "message": "Este necesară verificarea adresei de e-mail" + }, + "emailVerificationRequiredDesc": { + "message": "Trebuie să vă verificați e-mailul pentru a utiliza această caracteristică. Puteți verifica e-mailul în seiful web." + }, + "updatedMasterPassword": { + "message": "Parolă principală actualizată" + }, + "updateMasterPassword": { + "message": "Actualizare parolă principală" + }, + "updateMasterPasswordWarning": { + "message": "Parola dvs. principală a fost modificată recent de unul din administratorii organizației dvs. Pentru a accesa seiful, trebuie să o actualizați acum. Procedura vă va deconecta de la sesiunea curentă, necesitând să vă reconectați. Sesiunile active de pe alte dispozitive pot continua să rămână active timp de până la o oră." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Înregistrare automată" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Această organizație are o politică de întreprindere care vă va înregistra automat la resetarea parolei. Înregistrarea va permite administratorilor organizației să vă modifice parola principală." + }, + "selectFolder": { + "message": "Selectare folder..." + }, + "ssoCompleteRegistration": { + "message": "Pentru a finaliza conectarea cu SSO, vă rugăm să setați o parolă principală pentru a vă accesa și proteja seiful." + }, + "hours": { + "message": "Ore" + }, + "minutes": { + "message": "Minute" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Politicile organizației dvs vă afectează expirarea seifului. Timpul maxim permis de expirare a seifului este $HOURS$ oră (ore) și $MINUTES$ minut(e)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Timpul de expirare a seifului depășește restricțiile stabilite de organizația dvs." + }, + "vaultExportDisabled": { + "message": "Export de seif dezactivat" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una sau mai multe politici ale organizației vă împiedică să exportați seiful personal." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Imposibil de identificat un element de formular valid. Încercați să inspectați codul HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nu a fost găsit niciun identificator unic." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ folosește SSO cu un server de chei auto-găzduit. Membrii acestei organizații nu mai au nevoie de o parolă principală pentru autentificare.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Părăsire organizație" + }, + "removeMasterPassword": { + "message": "Eliminare parolă principală" + }, + "removedMasterPassword": { + "message": "Parolă principală eliminată." + }, + "leaveOrganizationConfirmation": { + "message": "Sigur doriți să părăsiți această organizație?" + }, + "leftOrganization": { + "message": "Ați părăsit organizația." + }, + "toggleCharacterCount": { + "message": "Comutare pe contorizare de caractere" + }, + "sessionTimeout": { + "message": "Sesiunea dvs. a expirat. Vă rugăm reveniți și încercați să vă autentificați din nou." + }, + "exportingPersonalVaultTitle": { + "message": "Exportarea seifului personal" + }, + "exportingPersonalVaultDescription": { + "message": "Numai elementele personale din seif asociate cu $EMAIL$ vor fi exportate. Elementele seifului organizației nu vor fi incluse.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Eroare" + }, + "regenerateUsername": { + "message": "Regenerare nume de utilizator" + }, + "generateUsername": { + "message": "Generare nume de utilizator" + }, + "usernameType": { + "message": "Tip de nume de utilizator" + }, + "plusAddressedEmail": { + "message": "Plus e-mail adresat", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Utilizați capacitățile de subadresare ale furnizorului dvs. de e-mail." + }, + "catchallEmail": { + "message": "E-mail Catch-all" + }, + "catchallEmailDesc": { + "message": "Utilizați inbox-ul catch-all configurat pentru domeniul dvs." + }, + "random": { + "message": "Aleatoriu" + }, + "randomWord": { + "message": "Cuvânt aleatoriu" + }, + "websiteName": { + "message": "Numele site-ului web" + }, + "whatWouldYouLikeToGenerate": { + "message": "Ce doriți să generați?" + }, + "passwordType": { + "message": "Tip de parolă" + }, + "service": { + "message": "Serviciu" + } +} diff --git a/apps/browser/src/_locales/ru/messages.json b/apps/browser/src/_locales/ru/messages.json new file mode 100644 index 0000000000..76e56a6084 --- /dev/null +++ b/apps/browser/src/_locales/ru/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - бесплатный менеджер паролей", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Защищенный и бесплатный менеджер паролей для всех ваших устройств.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Войдите или создайте новый аккаунт для доступа к вашему защищенному хранилищу." + }, + "createAccount": { + "message": "Создать аккаунт" + }, + "login": { + "message": "Войти" + }, + "enterpriseSingleSignOn": { + "message": "Единая корпоративная авторизация (SSO)" + }, + "cancel": { + "message": "Отмена" + }, + "close": { + "message": "Закрыть" + }, + "submit": { + "message": "Отправить" + }, + "emailAddress": { + "message": "Адрес email" + }, + "masterPass": { + "message": "Мастер-пароль" + }, + "masterPassDesc": { + "message": "Мастер-пароль – это ключ к вашему защищенному хранилищу. Он очень важен, поэтому не забывайте его. Восстановить мастер-пароль невозможно." + }, + "masterPassHintDesc": { + "message": "Подсказка к мастер-паролю может помочь вам его вспомнить." + }, + "reTypeMasterPass": { + "message": "Введите мастер-пароль повторно" + }, + "masterPassHint": { + "message": "Подсказка к мастер-паролю (необяз.)" + }, + "tab": { + "message": "Вкладка" + }, + "myVault": { + "message": "Хранилище" + }, + "tools": { + "message": "Инструменты" + }, + "settings": { + "message": "Настройки" + }, + "currentTab": { + "message": "Текущая вкладка" + }, + "copyPassword": { + "message": "Скопировать пароль" + }, + "copyNote": { + "message": "Скопировать заметку" + }, + "copyUri": { + "message": "Скопировать URI" + }, + "copyUsername": { + "message": "Скопировать имя пользователя" + }, + "copyNumber": { + "message": "Скопировать номер" + }, + "copySecurityCode": { + "message": "Скопировать код безопасности" + }, + "autoFill": { + "message": "Автозаполнение" + }, + "generatePasswordCopied": { + "message": "Сгенерировать пароль (с копированием)" + }, + "copyElementIdentifier": { + "message": "Скопировать название пользовательского поля" + }, + "noMatchingLogins": { + "message": "Нет подходящих логинов." + }, + "unlockVaultMenu": { + "message": "Разблокировать хранилище" + }, + "loginToVaultMenu": { + "message": "Войти в хранилище" + }, + "autoFillInfo": { + "message": "Нет доступных логинов для автозаполнения на текущей вкладке браузера." + }, + "addLogin": { + "message": "Добавить логин" + }, + "addItem": { + "message": "Добавить элемент" + }, + "passwordHint": { + "message": "Подсказка к паролю" + }, + "enterEmailToGetHint": { + "message": "Введите email аккаунта для получения подсказки к мастер-паролю." + }, + "getMasterPasswordHint": { + "message": "Получить подсказку к мастер-паролю" + }, + "continue": { + "message": "Продолжить" + }, + "sendVerificationCode": { + "message": "Отправить код подтверждения на ваш email" + }, + "sendCode": { + "message": "Отправить код" + }, + "codeSent": { + "message": "Код отправлен" + }, + "verificationCode": { + "message": "Код подтверждения" + }, + "confirmIdentity": { + "message": "Подтвердите вашу личность, чтобы продолжить." + }, + "account": { + "message": "Аккаунт" + }, + "changeMasterPassword": { + "message": "Изменить мастер-пароль" + }, + "fingerprintPhrase": { + "message": "Фраза отпечатка", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Фраза отпечатка вашего аккаунта", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Двухфакторная аутентификация" + }, + "logOut": { + "message": "Выйти" + }, + "about": { + "message": "О Bitwarden" + }, + "version": { + "message": "Версия" + }, + "save": { + "message": "Сохранить" + }, + "move": { + "message": "Переместить" + }, + "addFolder": { + "message": "Добавить папку" + }, + "name": { + "message": "Название" + }, + "editFolder": { + "message": "Изменить папку" + }, + "deleteFolder": { + "message": "Удалить папку" + }, + "folders": { + "message": "Папки" + }, + "noFolders": { + "message": "Нет папок для отображения." + }, + "helpFeedback": { + "message": "Помощь и обратная связь" + }, + "sync": { + "message": "Синхронизация" + }, + "syncVaultNow": { + "message": "Синхронизировать сейчас" + }, + "lastSync": { + "message": "Последняя синхронизация:" + }, + "passGen": { + "message": "Генератор паролей" + }, + "generator": { + "message": "Генератор", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Автоматическая генерация сильных и уникальных паролей для ваших логинов." + }, + "bitWebVault": { + "message": "Веб-хранилище Bitwarden" + }, + "importItems": { + "message": "Импорт элементов" + }, + "select": { + "message": "Выбрать" + }, + "generatePassword": { + "message": "Сгенерировать пароль" + }, + "regeneratePassword": { + "message": "Создать новый пароль" + }, + "options": { + "message": "Опции" + }, + "length": { + "message": "Длина" + }, + "uppercase": { + "message": "Прописные буквы (A-Z)" + }, + "lowercase": { + "message": "Строчные буквы (a-z)" + }, + "numbers": { + "message": "Цифры (0-9)" + }, + "specialCharacters": { + "message": "Специальные символы (!@#$%^&*)" + }, + "numWords": { + "message": "Количество слов" + }, + "wordSeparator": { + "message": "Разделитель слов" + }, + "capitalize": { + "message": "С заглавной буквы", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Добавить цифру" + }, + "minNumbers": { + "message": "Минимум цифр" + }, + "minSpecial": { + "message": "Минимум символов" + }, + "avoidAmbChar": { + "message": "Избегать неоднозначных символов" + }, + "searchVault": { + "message": "Поиск в хранилище" + }, + "edit": { + "message": "Изменить" + }, + "view": { + "message": "Просмотр" + }, + "noItemsInList": { + "message": "Нет элементов для отображения." + }, + "itemInformation": { + "message": "Информация об элементе" + }, + "username": { + "message": "Имя пользователя" + }, + "password": { + "message": "Пароль" + }, + "passphrase": { + "message": "Парольная фраза" + }, + "favorite": { + "message": "Избранный" + }, + "notes": { + "message": "Заметки" + }, + "note": { + "message": "Заметка" + }, + "editItem": { + "message": "Изменение элемента" + }, + "folder": { + "message": "Папка" + }, + "deleteItem": { + "message": "Удалить элемент" + }, + "viewItem": { + "message": "Просмотр элемента" + }, + "launch": { + "message": "Перейти" + }, + "website": { + "message": "Веб-сайт" + }, + "toggleVisibility": { + "message": "Вкл/выкл видимость" + }, + "manage": { + "message": "Управление" + }, + "other": { + "message": "Прочее" + }, + "rateExtension": { + "message": "Оценить расширение" + }, + "rateExtensionDesc": { + "message": "Пожалуйста, подумайте о том, чтобы помочь нам хорошим отзывом!" + }, + "browserNotSupportClipboard": { + "message": "Ваш браузер не поддерживает копирование данных в буфер обмена. Скопируйте вручную." + }, + "verifyIdentity": { + "message": "Подтвердить личность" + }, + "yourVaultIsLocked": { + "message": "Ваше хранилище заблокировано. Подтвердите свою личность, чтобы продолжить" + }, + "unlock": { + "message": "Разблокировать" + }, + "loggedInAsOn": { + "message": "Выполнен вход на $HOSTNAME$ как $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Неверный мастер-пароль" + }, + "vaultTimeout": { + "message": "Тайм-аут хранилища" + }, + "lockNow": { + "message": "Заблокировать сейчас" + }, + "immediately": { + "message": "Немедленно" + }, + "tenSeconds": { + "message": "10 секунд" + }, + "twentySeconds": { + "message": "20 секунд" + }, + "thirtySeconds": { + "message": "30 секунд" + }, + "oneMinute": { + "message": "1 минута" + }, + "twoMinutes": { + "message": "2 минуты" + }, + "fiveMinutes": { + "message": "5 минут" + }, + "fifteenMinutes": { + "message": "15 минут" + }, + "thirtyMinutes": { + "message": "30 минут" + }, + "oneHour": { + "message": "1 час" + }, + "fourHours": { + "message": "4 часа" + }, + "onLocked": { + "message": "Вместе с компьютером" + }, + "onRestart": { + "message": "При перезапуске" + }, + "never": { + "message": "Никогда" + }, + "security": { + "message": "Безопасность" + }, + "errorOccurred": { + "message": "Произошла ошибка" + }, + "emailRequired": { + "message": "Необходимо указать email." + }, + "invalidEmail": { + "message": "Неверный адрес email." + }, + "masterPassRequired": { + "message": "Необходимо ввести мастер-пароль." + }, + "masterPassLength": { + "message": "Мастер-пароль должен содержать не менее 8 символов." + }, + "masterPassDoesntMatch": { + "message": "Мастер-пароли не совпадают." + }, + "newAccountCreated": { + "message": "Ваш аккаунт создан! Теперь вы можете войти в систему." + }, + "masterPassSent": { + "message": "Мы отправили вам письмо с подсказкой к мастер-паролю." + }, + "verificationCodeRequired": { + "message": "Необходимо ввести код подтверждения." + }, + "invalidVerificationCode": { + "message": "Неверный код подтверждения" + }, + "valueCopied": { + "message": "$VALUE$ скопировано", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Не удалось автоматически заполнить выбранный элемент на этой странице. Скопируйте и вставьте логин/пароль из своего хранилища." + }, + "loggedOut": { + "message": "Вы вышли из хранилища" + }, + "loginExpired": { + "message": "Истек срок действия вашей сессии." + }, + "logOutConfirmation": { + "message": "Вы действительно хотите выйти?" + }, + "yes": { + "message": "Да" + }, + "no": { + "message": "Нет" + }, + "unexpectedError": { + "message": "Произошла непредвиденная ошибка." + }, + "nameRequired": { + "message": "Необходимо название." + }, + "addedFolder": { + "message": "Папка добавлена" + }, + "changeMasterPass": { + "message": "Изменить мастер-пароль" + }, + "changeMasterPasswordConfirmation": { + "message": "Вы можете изменить свой мастер-пароль на bitwarden.com. Перейти на сайт сейчас?" + }, + "twoStepLoginConfirmation": { + "message": "Двухфакторная аутентификация делает ваш аккаунт более защищенным, требуя подтверждения входа на другом устройстве, например, ключом безопасности, приложением-аутентификатором, SMS, телефонным звонком или письмом. Двухфакторная аутентификация включается на bitwarden.com. Перейти на сайт сейчас?" + }, + "editedFolder": { + "message": "Папка отредактирована" + }, + "deleteFolderConfirmation": { + "message": "Удалить эту папку?" + }, + "deletedFolder": { + "message": "Папка удалена" + }, + "gettingStartedTutorial": { + "message": "Учебник по началу работы" + }, + "gettingStartedTutorialVideo": { + "message": "Посмотрите небольшой обучающий материал, чтобы узнать, как получить максимальную отдачу от расширения браузера." + }, + "syncingComplete": { + "message": "Синхронизация завершена" + }, + "syncingFailed": { + "message": "Ошибка синхронизации" + }, + "passwordCopied": { + "message": "Пароль скопирован" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Новый URI" + }, + "addedItem": { + "message": "Элемент добавлен" + }, + "editedItem": { + "message": "Элемент изменен" + }, + "deleteItemConfirmation": { + "message": "Вы действительно хотите отправить в корзину?" + }, + "deletedItem": { + "message": "Элемент отправлен в корзину" + }, + "overwritePassword": { + "message": "Перезаписать пароль" + }, + "overwritePasswordConfirmation": { + "message": "Вы хотите перезаписать текущий пароль?" + }, + "overwriteUsername": { + "message": "Перезаписать имя пользователя" + }, + "overwriteUsernameConfirmation": { + "message": "Вы хотите перезаписать текущее имя пользователя?" + }, + "searchFolder": { + "message": "Поиск в папке" + }, + "searchCollection": { + "message": "Поиск в коллекции" + }, + "searchType": { + "message": "Тип поиска" + }, + "noneFolder": { + "message": "Без папки", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Отключить уведомление о добавлении логина" + }, + "addLoginNotificationDesc": { + "message": "Уведомление о добавлении логина автоматически предложит вам сохранить новые логины в хранилище." + }, + "dontShowCardsCurrentTab": { + "message": "Не показывать карты на вкладке" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Карты из вашего хранилища перечислены на 'Текущей вкладке' для упрощения доступа к автозаполнению." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Не показывать Личности на вкладке" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Личности из вашего хранилища перечислены на 'Текущей вкладке' для упрощения доступа к автозаполнению." + }, + "clearClipboard": { + "message": "Очистка буфера обмена", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Автоматически очищать скопированные значения в вашем буфере обмена.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Должен ли Bitwarden запомнить этот пароль?" + }, + "notificationAddSave": { + "message": "Сохранить" + }, + "disableChangedPasswordNotification": { + "message": "Отключить уведомление об изменении пароля" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Уведомление об изменении пароля автоматически предложит вам обновить пароль входа в хранилище, когда обнаружит, что вы изменили его на веб-сайте." + }, + "notificationChangeDesc": { + "message": "Обновить этот пароль в Bitwarden?" + }, + "notificationChangeSave": { + "message": "Обновить" + }, + "disableContextMenuItem": { + "message": "Отключить опции контекстного меню" + }, + "disableContextMenuItemDesc": { + "message": "Опции контекстного меню обеспечивают быстрый доступ к генератору паролей и логинам для сайта на текущей вкладке." + }, + "defaultUriMatchDetection": { + "message": "Обнаружение совпадения URI по умолчанию", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Выберите стандартный способ определения соответствия URI для логинов при выполнении таких действий, как автоматическое заполнение." + }, + "theme": { + "message": "Тема" + }, + "themeDesc": { + "message": "Изменение цветовой темы приложения." + }, + "dark": { + "message": "Темная", + "description": "Dark color" + }, + "light": { + "message": "Светлая", + "description": "Light color" + }, + "solarizedDark": { + "message": "Солнечная темная", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Экспорт хранилища" + }, + "fileFormat": { + "message": "Формат файла" + }, + "warning": { + "message": "ВНИМАНИЕ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Подтвердить экспорт хранилища" + }, + "exportWarningDesc": { + "message": "Экспортируемый файл содержит данные вашего хранилища в незашифрованном формате. Его не следует хранить или отправлять по небезопасным каналам (например, по электронной почте). Удалите его сразу после использования." + }, + "encExportKeyWarningDesc": { + "message": "При экспорте данные шифруются при помощи ключа шифрования учетной записи. Если вы решите сменить ключ шифрования, вам следует экспортировать данные повторно, поскольку вы не сможете расшифровать этот файл экспорта." + }, + "encExportAccountWarningDesc": { + "message": "Ключи шифрования уникальны для каждой учетной записи Bitwarden, поэтому нельзя импортировать зашифрованное хранилище в другой аккаунт." + }, + "exportMasterPassword": { + "message": "Для экспорта данных из хранилища введите мастер-пароль." + }, + "shared": { + "message": "Общие" + }, + "learnOrg": { + "message": "Узнать об организациях" + }, + "learnOrgConfirmation": { + "message": "Bitwarden позволяет делиться элементами вашего хранилища с другими пользователями с помощью организации. Хотите посетить сайт bitwarden.com, чтобы узнать больше?" + }, + "moveToOrganization": { + "message": "Переместить в организацию" + }, + "share": { + "message": "Поделиться" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ перемещен в $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Выберите организацию, в которую вы хотите переместить этот элемент. При перемещении в организацию право собственности на элемент переходит к этой организации. Вы больше не будете прямым владельцем этого элемента после его перемещения." + }, + "learnMore": { + "message": "Подробнее" + }, + "authenticatorKeyTotp": { + "message": "Ключ проверки подлинности (TOTP)" + }, + "verificationCodeTotp": { + "message": "Код подтверждения (TOTP)" + }, + "copyVerificationCode": { + "message": "Скопировать код подтверждения" + }, + "attachments": { + "message": "Вложения" + }, + "deleteAttachment": { + "message": "Удалить вложение" + }, + "deleteAttachmentConfirmation": { + "message": "Вы действительно хотите удалить это вложение?" + }, + "deletedAttachment": { + "message": "Вложение удалено" + }, + "newAttachment": { + "message": "Добавить новое вложение" + }, + "noAttachments": { + "message": "Без вложений." + }, + "attachmentSaved": { + "message": "Вложение сохранено." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Выберите файл." + }, + "maxFileSize": { + "message": "Максимальный размер файла 500 МБ." + }, + "featureUnavailable": { + "message": "Функция недоступна" + }, + "updateKey": { + "message": "Вы не можете использовать эту функцию, пока не обновите свой ключ шифрования." + }, + "premiumMembership": { + "message": "Премиум" + }, + "premiumManage": { + "message": "Управление Премиум" + }, + "premiumManageAlert": { + "message": "Вы можете управлять Премиум на bitwarden.com. Перейти на сайт сейчас?" + }, + "premiumRefresh": { + "message": "Обновить Премиум" + }, + "premiumNotCurrentMember": { + "message": "На текущий момент у вас отсутствует Премиум." + }, + "premiumSignUpAndGet": { + "message": "Подпишитесь на Премиум и получите:" + }, + "ppremiumSignUpStorage": { + "message": "1 ГБ зашифрованного хранилища для вложенных файлов." + }, + "ppremiumSignUpTwoStep": { + "message": "Дополнительные варианты двухфакторной аутентификации, такие как YubiKey, FIDO U2F и Duo." + }, + "ppremiumSignUpReports": { + "message": "Гигиена паролей, здоровье аккаунта и отчеты об утечках данных для обеспечения безопасности вашего хранилища." + }, + "ppremiumSignUpTotp": { + "message": "TOTP-генератор кодов (2ФА) для логинов в хранилище." + }, + "ppremiumSignUpSupport": { + "message": "Приоритетная поддержка." + }, + "ppremiumSignUpFuture": { + "message": "Все будущие функции Премиум. Их будет больше!" + }, + "premiumPurchase": { + "message": "Купить Премиум" + }, + "premiumPurchaseAlert": { + "message": "Вы можете купить Премиум на bitwarden.com. Перейти на сайт сейчас?" + }, + "premiumCurrentMember": { + "message": "У вас есть Премиум!" + }, + "premiumCurrentMemberThanks": { + "message": "Благодарим вас за поддержку Bitwarden." + }, + "premiumPrice": { + "message": "Всего лишь $PRICE$ в год!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Обновление завершено" + }, + "disableAutoTotpCopy": { + "message": "Отключить автоматическое копирование TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Если к вашему логину прикреплен ключ проверки подлинности, то код подтверждения TOTP будет скопирован при автозаполнении логина." + }, + "disableAutoBiometricsPrompt": { + "message": "Не запрашивать биометрию при запуске" + }, + "premiumRequired": { + "message": "Необходим Премиум" + }, + "premiumRequiredDesc": { + "message": "Для использования этой функции необходим Премиум." + }, + "enterVerificationCodeApp": { + "message": "Введите 6-значный код подтверждения из вашего приложения-аутентификатора." + }, + "enterVerificationCodeEmail": { + "message": "Введите 6-значный код подтверждения, который был отправлен на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Отправлено письмо подтверждения на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запомнить меня" + }, + "sendVerificationCodeEmailAgain": { + "message": "Отправить код подтверждения еще раз" + }, + "useAnotherTwoStepMethod": { + "message": "Использовать другой метод двухфакторной аутентификации" + }, + "insertYubiKey": { + "message": "Вставьте свой YubiKey в USB-порт компьютера и нажмите его кнопку." + }, + "insertU2f": { + "message": "Вставьте ключ безопасности в USB-порт компьютера. Если у ключа есть кнопка, нажмите ее." + }, + "webAuthnNewTab": { + "message": "Продолжить верификацию 2ФА WebAuthn в новой вкладке." + }, + "webAuthnNewTabOpen": { + "message": "Открыть новую вкладку" + }, + "webAuthnAuthenticate": { + "message": "Аутентификация WebAutn" + }, + "loginUnavailable": { + "message": "Вход недоступен" + }, + "noTwoStepProviders": { + "message": "У этой учетной записи включена двухфакторная аутентификация, однако ни один из настроенных вариантов не поддерживается этим веб-браузером." + }, + "noTwoStepProviders2": { + "message": "Используйте поддерживаемый веб-браузер (например, Chrome) и/или добавьте дополнительные варианты аутентификации, которые поддерживаются в веб-браузерах (например, приложение-аутентификатор)." + }, + "twoStepOptions": { + "message": "Настройки двухфакторной аутентификации" + }, + "recoveryCodeDesc": { + "message": "Потеряли доступ ко всем вариантам двухфакторной аутентификации? Используйте код восстановления, чтобы отключить двухфакторную аутентификацию для вашей учетной записи." + }, + "recoveryCodeTitle": { + "message": "Код восстановления" + }, + "authenticatorAppTitle": { + "message": "Приложение-аутентификатор" + }, + "authenticatorAppDesc": { + "message": "Используйте приложение-аутентификатор (например, Authy или Google Authenticator) для создания кодов проверки на основе времени.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Ключ безопасности YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Используйте YubiKey для доступа к вашей учетной записи. Работает с устройствами YubiKey 4 серии, 5 серии и NEO." + }, + "duoDesc": { + "message": "Подтвердите с помощью Duo Security, используя приложение Duo Mobile, SMS, телефонный звонок или ключ безопасности U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Подтвердите с помощью Duo Security для вашей организации, используя приложение Duo Mobile, SMS, телефонный звонок или ключ безопасности U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Используйте любой ключ безопасности с поддержкой WebAuthn для доступа к своей учетной записи." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Коды подтверждения будут отправлены вам по электронной почте." + }, + "selfHostedEnvironment": { + "message": "Среда собственного хостинга" + }, + "selfHostedEnvironmentFooter": { + "message": "Укажите URL-адрес Bitwarden на вашем сервере." + }, + "customEnvironment": { + "message": "Пользовательское окружение" + }, + "customEnvironmentFooter": { + "message": "Для опытных пользователей. Можно указать URL отдельно для каждой службы." + }, + "baseUrl": { + "message": "URL-адрес сервера" + }, + "apiUrl": { + "message": "API URL-адреса сервера" + }, + "webVaultUrl": { + "message": "URL-адрес сервера веб-хранилища" + }, + "identityUrl": { + "message": "URL-адрес сервера идентификации" + }, + "notificationsUrl": { + "message": "URL-адрес сервера уведомлений" + }, + "iconsUrl": { + "message": "URL-адрес сервера значков" + }, + "environmentSaved": { + "message": "URL-адреса среды сохранены." + }, + "enableAutoFillOnPageLoad": { + "message": "Включить автозаполнение при загрузке страницы" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "При обнаружении формы входа выполняется автозаполнение во время загрузки веб-страницы." + }, + "experimentalFeature": { + "message": "Это экспериментальная функция. Используйте на свой страх и риск." + }, + "defaultAutoFillOnPageLoad": { + "message": "Настройка автозаполнения по умолчанию для логинов" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "После включения автозаполнения при загрузке страницы вы можете включить или отключить эту функцию для отдельных логинов. Это настройка по умолчанию для логинов, которые не были настроены отдельно." + }, + "itemAutoFillOnPageLoad": { + "message": "Автозаполнение при загрузке страницы (если включено в настройках)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Использовать настройки по умолчанию" + }, + "autoFillOnPageLoadYes": { + "message": "Автозаполнение при загрузке страницы" + }, + "autoFillOnPageLoadNo": { + "message": "Не заполнять автоматически при загрузке страницы" + }, + "commandOpenPopup": { + "message": "Открыть хранилище во всплывающем окне" + }, + "commandOpenSidebar": { + "message": "Открыть хранилище в боковой панели" + }, + "commandAutofillDesc": { + "message": "Автозаполнение последнего использованного логина для текущего веб-сайта." + }, + "commandGeneratePasswordDesc": { + "message": "Сгенерировать и скопировать новый случайный пароль в буфер обмена." + }, + "commandLockVaultDesc": { + "message": "Заблокировать хранилище" + }, + "privateModeWarning": { + "message": "Частный режим - экспериментальный, некоторые функции ограничены." + }, + "customFields": { + "message": "Пользовательские поля" + }, + "copyValue": { + "message": "Скопировать значение" + }, + "value": { + "message": "Значение" + }, + "newCustomField": { + "message": "Новое пользовательское поле" + }, + "dragToSort": { + "message": "Перетащите для сортировки" + }, + "cfTypeText": { + "message": "Текстовое" + }, + "cfTypeHidden": { + "message": "Скрытое" + }, + "cfTypeBoolean": { + "message": "Логическое" + }, + "cfTypeLinked": { + "message": "Связано", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Связанное значение", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Щелчок за пределами этого окна для просмотра кода проверки из электронной почты приведет к его закрытию. Открыть bitwarden в новом окне?" + }, + "popupU2fCloseMessage": { + "message": "Этот браузер не может обрабатывать запросы U2F в этом всплывающем окне. Вы хотите открыть это всплывающее окно в новом окне, чтобы иметь возможность войти в систему, используя U2F?" + }, + "disableFavicon": { + "message": "Отключить значки веб-сайтов" + }, + "disableFaviconDesc": { + "message": "Значки веб-сайтов отображаются рядом с каждым элементом в вашем хранилище." + }, + "disableBadgeCounter": { + "message": "Отключить счетчик значка" + }, + "disableBadgeCounterDesc": { + "message": "Счетчик значка показывает, сколько в вашем хранилище логинов для текущей страницы." + }, + "cardholderName": { + "message": "Имя владельца карты" + }, + "number": { + "message": "Номер" + }, + "brand": { + "message": "Тип карты" + }, + "expirationMonth": { + "message": "Месяц" + }, + "expirationYear": { + "message": "Год" + }, + "expiration": { + "message": "Срок действия" + }, + "january": { + "message": "Январь" + }, + "february": { + "message": "Февраль" + }, + "march": { + "message": "Март" + }, + "april": { + "message": "Апрель" + }, + "may": { + "message": "Май" + }, + "june": { + "message": "Июнь" + }, + "july": { + "message": "Июль" + }, + "august": { + "message": "Август" + }, + "september": { + "message": "Сентябрь" + }, + "october": { + "message": "Октябрь" + }, + "november": { + "message": "Ноябрь" + }, + "december": { + "message": "Декабрь" + }, + "securityCode": { + "message": "Код безопасности" + }, + "ex": { + "message": "напр." + }, + "title": { + "message": "Обращение" + }, + "mr": { + "message": "Г-н" + }, + "mrs": { + "message": "Г-жа" + }, + "ms": { + "message": "Проф." + }, + "dr": { + "message": "Тов." + }, + "firstName": { + "message": "Имя" + }, + "middleName": { + "message": "Отчество" + }, + "lastName": { + "message": "Фамилия" + }, + "fullName": { + "message": "Полное имя" + }, + "identityName": { + "message": "Имя" + }, + "company": { + "message": "Компания" + }, + "ssn": { + "message": "Номер социального страхования" + }, + "passportNumber": { + "message": "Номер паспорта" + }, + "licenseNumber": { + "message": "ИНН" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адрес" + }, + "address1": { + "message": "Строка адреса 1" + }, + "address2": { + "message": "Строка адреса 2" + }, + "address3": { + "message": "Строка адреса 3" + }, + "cityTown": { + "message": "Город/Поселок" + }, + "stateProvince": { + "message": "Регион / Область" + }, + "zipPostalCode": { + "message": "Почтовый индекс" + }, + "country": { + "message": "Страна" + }, + "type": { + "message": "Тип" + }, + "typeLogin": { + "message": "Логин" + }, + "typeLogins": { + "message": "Логины" + }, + "typeSecureNote": { + "message": "Защищенная заметка" + }, + "typeCard": { + "message": "Карта" + }, + "typeIdentity": { + "message": "Личная информация" + }, + "passwordHistory": { + "message": "История паролей" + }, + "back": { + "message": "Назад" + }, + "collections": { + "message": "Коллекции" + }, + "favorites": { + "message": "Избранные" + }, + "popOutNewWindow": { + "message": "Перейти в новое окно" + }, + "refresh": { + "message": "Обновить" + }, + "cards": { + "message": "Карты" + }, + "identities": { + "message": "Личные данные" + }, + "logins": { + "message": "Логины" + }, + "secureNotes": { + "message": "Защищенные заметки" + }, + "clear": { + "message": "Очистить", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Проверьте, не скомпрометирован ли пароль." + }, + "passwordExposed": { + "message": "Этот пароль был скомпрометирован $VALUE$ раз(а). Вам следует его изменить.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Этот пароль не обнаружен в известных базах утечек. Можно продолжать его использовать." + }, + "baseDomain": { + "message": "Основной домен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Доменное имя", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Хост", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Точно" + }, + "startsWith": { + "message": "Начинается с" + }, + "regEx": { + "message": "Регулярное выражение", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Обнаружение совпадений", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Метод обнаружения по умолчанию", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Переключить настройки" + }, + "toggleCurrentUris": { + "message": "Переключить текущий URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Текущий URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Организация", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Типы элементов" + }, + "allItems": { + "message": "Все элементы" + }, + "noPasswordsInList": { + "message": "Нет паролей для отображения." + }, + "remove": { + "message": "Удалить" + }, + "default": { + "message": "По умолчанию" + }, + "dateUpdated": { + "message": "Обновлено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Пароль обновлен", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Вы действительно хотите отключить блокировку хранилища? В этом случае ключ шифрования вашего хранилища будет сохранен на вашем устройстве. Отключая блокировку, вы должны убедиться, что ваше устройство надежно защищено." + }, + "noOrganizationsList": { + "message": "Вы не являетесь членом какой-либо организации. Организации позволяют безопасно обмениваться элементами с другими пользователями." + }, + "noCollectionsInList": { + "message": "Нет коллекций для отображения." + }, + "ownership": { + "message": "Владелец" + }, + "whoOwnsThisItem": { + "message": "Кому принадлежит этот элемент?" + }, + "strong": { + "message": "Сильный", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Хороший", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабый", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слабый мастер-пароль" + }, + "weakMasterPasswordDesc": { + "message": "Вы выбрали слабый мастер-пароль. Для надежной защиты аккаунта Bitwarden следует использовать сильный мастер-пароль (или парольную фразу). Вы действительно хотите использовать этот мастер-пароль?" + }, + "pin": { + "message": "PIN-код", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Разблокировать с помощью PIN-кода" + }, + "setYourPinCode": { + "message": "Установите PIN-код для разблокировки Bitwarden. Настройки PIN-кода будут сброшены, если вы когда-либо полностью выйдете из приложения." + }, + "pinRequired": { + "message": "Необходим PIN-код." + }, + "invalidPin": { + "message": "Неверный PIN-код." + }, + "unlockWithBiometrics": { + "message": "Разблокировать с помощью биометрии" + }, + "awaitDesktop": { + "message": "Ожидание подтверждения с компьютера" + }, + "awaitDesktopDesc": { + "message": "Для включения биометрии в браузере, подтвердите это в приложении Bitwarden для компьютера." + }, + "lockWithMasterPassOnRestart": { + "message": "Блокировать мастер-паролем при перезапуске браузера" + }, + "selectOneCollection": { + "message": "Необходимо выбрать хотя бы одну коллекцию." + }, + "cloneItem": { + "message": "Клонировать элемент" + }, + "clone": { + "message": "Клонировать" + }, + "passwordGeneratorPolicyInEffect": { + "message": "На настройки генератора влияют одна или несколько политик организации." + }, + "vaultTimeoutAction": { + "message": "Действие по тайм-ауту хранилища" + }, + "lock": { + "message": "Заблокировать", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Корзина", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Поиск в корзине" + }, + "permanentlyDeleteItem": { + "message": "Окончательно удалить элемент" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Вы уверены, что хотите окончательно удалить этот элемент?" + }, + "permanentlyDeletedItem": { + "message": "Элемент удален навсегда" + }, + "restoreItem": { + "message": "Восстановить элемент" + }, + "restoreItemConfirmation": { + "message": "Вы уверены, что хотите восстановить этот элемент?" + }, + "restoredItem": { + "message": "Элемент восстановлен" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "По истечении тайм-аута будет выполнен выход, что приведет к отмене всех прав доступа к вашему хранилищу и потребует онлайн-аутентификации. Вы уверены, что хотите использовать этот параметр?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Подтверждение действия по тайм-ауту" + }, + "autoFillAndSave": { + "message": "Заполнить и сохранить" + }, + "autoFillSuccessAndSavedUri": { + "message": "Автозаполненный элемент и сохраненный URI" + }, + "autoFillSuccess": { + "message": "Автозаполненный элемент" + }, + "setMasterPassword": { + "message": "Задать мастер-пароль" + }, + "masterPasswordPolicyInEffect": { + "message": "Согласно одной или нескольким политикам организации необходимо, чтобы ваш мастер-пароль отвечал следующим требованиям:" + }, + "policyInEffectMinComplexity": { + "message": "Минимальный уровень сложности $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Минимальная длина $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Содержать хотя бы одну заглавную букву" + }, + "policyInEffectLowercase": { + "message": "Содержать хотя бы одну строчную букву" + }, + "policyInEffectNumbers": { + "message": "Содержать хотя бы одну цифру" + }, + "policyInEffectSpecial": { + "message": "Содержать хотя бы один из следующих специальных символов $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваш новый мастер-пароль не соответствует требованиям политики." + }, + "acceptPolicies": { + "message": "Отметив этот флажок, вы соглашаетесь со следующим:" + }, + "acceptPoliciesError": { + "message": "Условия предоставления услуг и Политика конфиденциальности не были подтверждены." + }, + "termsOfService": { + "message": "Условия предоставления услуг" + }, + "privacyPolicy": { + "message": "Политика конфиденциальности" + }, + "hintEqualsPassword": { + "message": "Подсказка для пароля не может совпадать с паролем." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Проверка синхронизации на компьютере" + }, + "desktopIntegrationVerificationText": { + "message": "Пожалуйста, убедитесь, что приложение для компьютера отображает этот отпечаток: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Интеграция с браузером не включена" + }, + "desktopIntegrationDisabledDesc": { + "message": "Пожалуйста, включите интеграцию с браузером в настройках приложения Bitwarden для компьютера." + }, + "startDesktopTitle": { + "message": "Запустить приложение Bitwarden для компьютера" + }, + "startDesktopDesc": { + "message": "Перед использованием разблокировки с помощью биометрии необходимо запустить приложение Bitwarden для компьютера." + }, + "errorEnableBiometricTitle": { + "message": "Не удается включить биометрию" + }, + "errorEnableBiometricDesc": { + "message": "Действие было отменено приложением для компьютера" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Приложению для компьютера не удалось создать защищенный канал подключения. Пожалуйста, попробуйте еще раз" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Соединение с приложением для компьютера прервано" + }, + "nativeMessagingWrongUserDesc": { + "message": "Приложение для компьютера авторизовано под другим аккаунтом. Необходимо чтобы оба приложения были авторизованы под одной учетной записью." + }, + "nativeMessagingWrongUserTitle": { + "message": "Несоответствие аккаунта" + }, + "biometricsNotEnabledTitle": { + "message": "Биометрия не включена" + }, + "biometricsNotEnabledDesc": { + "message": "Для активации биометрии в браузере сначала необходимо включить биометрию в приложении для компьютера." + }, + "biometricsNotSupportedTitle": { + "message": "Биометрия не поддерживается" + }, + "biometricsNotSupportedDesc": { + "message": "Биометрия в браузере не поддерживается этом устройстве." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Разрешение не представлено" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Без разрешения на взаимодействие с Bitwarden для компьютера биометрия в расширении браузера работать не сможет. Попробуйте еще раз." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Ошибка при запросе разрешения" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Это действие невозможно выполнить в боковой панели. Попробуйте снова в всплывающем или отдельном окне." + }, + "personalOwnershipSubmitError": { + "message": "В соответствии с корпоративной политикой вам запрещено сохранять элементы в личном хранилище. Измените владельца на организацию и выберите из доступных Коллекций." + }, + "personalOwnershipPolicyInEffect": { + "message": "Политика организации влияет на ваши варианты владения." + }, + "excludedDomains": { + "message": "Исключенные домены" + }, + "excludedDomainsDesc": { + "message": "Bitwarden не будет предлагать сохранить логины для этих доменов. Для вступления изменений в силу необходимо обновить страницу." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ – некорректно указанный домен", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Поиск Send’ов", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Добавить Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Текст" + }, + "sendTypeFile": { + "message": "Файл" + }, + "allSends": { + "message": "Все Send’ы", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Достигнут максимум обращений", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Срок истек" + }, + "pendingDeletion": { + "message": "Ожидание удаления" + }, + "passwordProtected": { + "message": "Защищено паролем" + }, + "copySendLink": { + "message": "Скопировать ссылку на Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Удалить пароль" + }, + "delete": { + "message": "Удалить" + }, + "removedPassword": { + "message": "Пароль удален" + }, + "deletedSend": { + "message": "Удаленная Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Ссылка на Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Отключено" + }, + "removePasswordConfirmation": { + "message": "Вы уверены, что хотите удалить пароль?" + }, + "deleteSend": { + "message": "Удалить Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Вы действительно хотите удалить эту Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Изменить Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Выберите тип Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Понятное имя для описания этой Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Файл, который вы хотите отправить." + }, + "deletionDate": { + "message": "Срок удаления" + }, + "deletionDateDesc": { + "message": "Эта Send будет окончательно удалена в указанные дату и время.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Срок истечения" + }, + "expirationDateDesc": { + "message": "Если задано, доступ к этой Send истечет в указанные дату и время.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 день" + }, + "days": { + "message": "$DAYS$ дн.", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Пользовательский" + }, + "maximumAccessCount": { + "message": "Максимум обращений" + }, + "maximumAccessCountDesc": { + "message": "Если задано, пользователи больше не смогут получить доступ к этой Send, как только будет достигнуто максимальное количество обращений.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "По возможности запрашивать у пользователей пароль для доступа к этой Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Личные заметки об этой Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Отключить эту Send, чтобы никто не мог получить к ней доступ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Скопировать ссылку на эту Send в буфер обмена после сохранения.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст, который вы хотите отправить." + }, + "sendHideText": { + "message": "Скрыть текст этой Send по умолчанию.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Текущих обращений" + }, + "createSend": { + "message": "Создание новой Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Новый пароль" + }, + "sendDisabled": { + "message": "Send отключена", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "В соответствии с корпоративной политикой вы можете удалить только существующую Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Созданная Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Измененная Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Для выбора файла откройте расширение в боковой панели (если возможно) или перейдите в новое окно, нажав на этот баннер." + }, + "sendFirefoxFileWarning": { + "message": "Для выбора файла с помощью Firefox, откройте расширение в боковой панели или перейдите в новое окно, нажав на этот баннер." + }, + "sendSafariFileWarning": { + "message": "Для выбора файла с помощью Safari, перейдите в новое окно, нажав на этот баннер." + }, + "sendFileCalloutHeader": { + "message": "Перед тем, как начать" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Для использования календарного стиля выбора даты,", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "нажмите здесь", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "для открытия в новом окне.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Срок истечения указан некорректно." + }, + "deletionDateIsInvalid": { + "message": "Срок удаления указан некорректно." + }, + "expirationDateAndTimeRequired": { + "message": "Необходимо указать дату и время срока истечения." + }, + "deletionDateAndTimeRequired": { + "message": "Необходимо указать дату и время срока удаления." + }, + "dateParsingError": { + "message": "Произошла ошибка при сохранении данных о сроках удаления и истечения." + }, + "hideEmail": { + "message": "Скрыть мой адрес email от получателей." + }, + "sendOptionsPolicyInEffect": { + "message": "На параметры Send влияют одна или несколько политик организации." + }, + "passwordPrompt": { + "message": "Повторный запрос мастер-пароля" + }, + "passwordConfirmation": { + "message": "Подтверждение мастер-пароля" + }, + "passwordConfirmationDesc": { + "message": "Это действие защищено. Для продолжения введите свой мастер-пароль, чтобы подтвердить свою личность." + }, + "emailVerificationRequired": { + "message": "Требуется подтверждение электронной почты" + }, + "emailVerificationRequiredDesc": { + "message": "Для использования этой функции необходимо подтвердить ваш email. Вы можете это сделать в веб-хранилище." + }, + "updatedMasterPassword": { + "message": "Мастер-пароль обновлен" + }, + "updateMasterPassword": { + "message": "Обновить мастер-пароль" + }, + "updateMasterPasswordWarning": { + "message": "Мастер-пароль недавно был изменен администратором вашей организации. Чтобы получить доступ к хранилищу, вы должны обновить его сейчас. В результате текущая сессия будет завершена, потребуется повторный вход. Активные сессии на других устройствах могут оставаться активными в течение одного часа." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Автоматическая регистрация" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "В этой организации действует корпоративная политика, которая автоматически зарегистрирует вас на сброс пароля. Регистрация позволит администраторам организации изменить ваш мастер-пароль." + }, + "selectFolder": { + "message": "Выберите папку..." + }, + "ssoCompleteRegistration": { + "message": "Для завершения процесса авторизации при помощи SSO, установите мастер-пароль для доступа к вашему хранилищу и его защиты." + }, + "hours": { + "message": "Час." + }, + "minutes": { + "message": "Мин." + }, + "vaultTimeoutPolicyInEffect": { + "message": "Политики вашей организации влияют на тайм-аут хранилища. Максимально допустимый тайм-аут хранилища составляет $HOURS$ час. и $MINUTES$ мин.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Время ожидания превышает ограничения, установленные вашей организацией." + }, + "vaultExportDisabled": { + "message": "Экспорт хранилища отключен" + }, + "personalVaultExportPolicyInEffect": { + "message": "Экспорт вашего личного хранилища запрещен одной или несколькими политиками организации." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Невозможно определить элемент формы. Попробуйте вместо этого проверить HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Уникальный идентификатор не найден." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ использует SSO с собственным сервером ключей. Для авторизации членам этой организации больше не требуется мастер-пароль.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Покинуть организацию" + }, + "removeMasterPassword": { + "message": "Удалить мастер-пароль" + }, + "removedMasterPassword": { + "message": "Мастер-пароль удален." + }, + "leaveOrganizationConfirmation": { + "message": "Вы действительно хотите покинуть эту организацию?" + }, + "leftOrganization": { + "message": "Вы покинули организацию." + }, + "toggleCharacterCount": { + "message": "Показать количество символов" + }, + "sessionTimeout": { + "message": "Время вашей сессии истекло. Пожалуйста, вернитесь и попробуйте войти снова." + }, + "exportingPersonalVaultTitle": { + "message": "Экспорт личного хранилища" + }, + "exportingPersonalVaultDescription": { + "message": "Будут экспортированы только личные элементы хранилища, связанные с $EMAIL$. Элементы хранилища организации включены не будут.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Ошибка" + }, + "regenerateUsername": { + "message": "Пересоздать имя пользователя" + }, + "generateUsername": { + "message": "Создать имя пользователя" + }, + "usernameType": { + "message": "Тип имени пользователя" + }, + "plusAddressedEmail": { + "message": "Плюс-адресованные email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Использовать возможности суб-адресации вашего провайдера электронной почты." + }, + "catchallEmail": { + "message": "Catch-all-адрес электронной почты" + }, + "catchallEmailDesc": { + "message": "Использовать настроенную в вашем домене почту catch-all." + }, + "random": { + "message": "Случайно" + }, + "randomWord": { + "message": "Случайное слово" + }, + "websiteName": { + "message": "Название сайта" + }, + "whatWouldYouLikeToGenerate": { + "message": "Что вы хотите сгенерировать?" + }, + "passwordType": { + "message": "Тип пароля" + }, + "service": { + "message": "Служба" + } +} diff --git a/apps/browser/src/_locales/si/messages.json b/apps/browser/src/_locales/si/messages.json new file mode 100644 index 0000000000..d2209e31b4 --- /dev/null +++ b/apps/browser/src/_locales/si/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "බිට්වාඩන්" + }, + "extName": { + "message": "බිට්වාඩන් - නොමිලේ මුරපදය කළමනාකරු", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "ඔබගේ සියලු උපාංග සඳහා ආරක්ෂිත සහ නොමිලේ මුරපද කළමණාකරුවෙකු.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "ඔබගේ ආරක්ෂිත සුරක්ෂිතාගාරය වෙත පිවිසීමට හෝ නව ගිණුමක් නිර්මාණය කරන්න." + }, + "createAccount": { + "message": "ගිණුමක් සාදන්න" + }, + "login": { + "message": "පිවිසෙන්න" + }, + "enterpriseSingleSignOn": { + "message": "ව්යවසාය තනි සංඥා මත" + }, + "cancel": { + "message": "අවලංගු කරන්න" + }, + "close": { + "message": "වසන්න" + }, + "submit": { + "message": "යොමන්න" + }, + "emailAddress": { + "message": "වි-තැපැල් ලිපිනය" + }, + "masterPass": { + "message": "ප්රධාන මුරපදය" + }, + "masterPassDesc": { + "message": "ප්රධාන මුරපදය යනු ඔබේ සුරක්ෂිතාගාරය වෙත ප්රවේශ වීමට ඔබ භාවිතා කරන මුරපදයයි. ඔබ ඔබේ ප්රධාන මුරපදය අමතක නොකිරීම ඉතා වැදගත් වේ. ඔබට එය අමතක වූ අවස්ථාවකදී මුරපදය නැවත ලබා ගැනීමට ක්රමයක් නොමැත." + }, + "masterPassHintDesc": { + "message": "ඔබ එය අමතක නම් ඔබේ මුරපදය මතක තබා ගැනීමට ප්රධාන මුරපද ඉඟියක් ඔබට උපකාර කළ හැකිය." + }, + "reTypeMasterPass": { + "message": "නැවත වර්ගය මාස්ටර් මුරපදය" + }, + "masterPassHint": { + "message": "ප්රධාන මුරපදය ඉඟියක් (විකල්ප)" + }, + "tab": { + "message": "ටැබ්" + }, + "myVault": { + "message": "මගේ සුරක්ෂිතාගාරය" + }, + "tools": { + "message": "මෙවලම්" + }, + "settings": { + "message": "සැකසුම්" + }, + "currentTab": { + "message": "වත්මන් ටැබ්" + }, + "copyPassword": { + "message": "මුරපදය පිටපත් කරන්න" + }, + "copyNote": { + "message": "සටහන පිටපත් කරන්න" + }, + "copyUri": { + "message": "පිටපත් කරන්න" + }, + "copyUsername": { + "message": "පරිශීලකනාමය පිටපත් කරන්න" + }, + "copyNumber": { + "message": "අංකය පිටපත් කරන්න" + }, + "copySecurityCode": { + "message": "ආරක්ෂක කේතය පිටපත් කරන්න" + }, + "autoFill": { + "message": "ස්වයං-පිරවීම" + }, + "generatePasswordCopied": { + "message": "මුරපදය ජනනය (පිටපත්)" + }, + "copyElementIdentifier": { + "message": "අභිරුචි ක්ෂේත්ර නම පිටපත් කරන්න" + }, + "noMatchingLogins": { + "message": "ගැලපෙන පිවිසුම් නොමැත." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "වත්මන් බ්රව්සර් ටැබය සඳහා ස්වයංක්රීයව පිරවීම සඳහා කිසිදු පිවිසුම් නොමැත." + }, + "addLogin": { + "message": "පිවිසුමක් එකතු කරන්න" + }, + "addItem": { + "message": "අයිතමය එකතු කරන්න" + }, + "passwordHint": { + "message": "මුරපදය ඉඟිය" + }, + "enterEmailToGetHint": { + "message": "ඔබගේ ප්රධාන මුරපදය ඉඟියක් ලබා ගැනීමට ඔබගේ ගිණුම ඊ-තැපැල් ලිපිනය ඇතුලත් කරන්න." + }, + "getMasterPasswordHint": { + "message": "ප්රධාන මුරපදය ඉඟියක් ලබා ගන්න" + }, + "continue": { + "message": "ඉදිරියට" + }, + "sendVerificationCode": { + "message": "ඔබගේ විද්යුත් තැපෑලට සත්යාපන කේතයක් යවන්න" + }, + "sendCode": { + "message": "කේතය යවන්න" + }, + "codeSent": { + "message": "යවන ලද කේතය" + }, + "verificationCode": { + "message": "සත්යාපන කේතය" + }, + "confirmIdentity": { + "message": "දිගටම කරගෙන යාමට ඔබගේ අනන්යතාවය තහවුරු කරන්න." + }, + "account": { + "message": "ගිණුම" + }, + "changeMasterPassword": { + "message": "ප්රධාන මුරපදය වෙනස්" + }, + "fingerprintPhrase": { + "message": "ඇඟිලි සලකුණු වාක්ය ඛණ්ඩය", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "ඔබගේ ගිණුමේ ඇඟිලි සලකුණු වාක්ය ඛණ්ඩය", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "ද්වි-පියවර ලොගින් වන්න" + }, + "logOut": { + "message": "නික්මෙන්න" + }, + "about": { + "message": "පිලිබඳව" + }, + "version": { + "message": "අනුවාදය" + }, + "save": { + "message": "සුරකින්න" + }, + "move": { + "message": "ගෙනයන්න" + }, + "addFolder": { + "message": "බහාලුම එකතු කරන්න" + }, + "name": { + "message": "නම" + }, + "editFolder": { + "message": "බහාලුම සංස්කරණය" + }, + "deleteFolder": { + "message": "ෆෝල්ඩරය මකන්න" + }, + "folders": { + "message": "බහාලුම්" + }, + "noFolders": { + "message": "ලැයිස්තු ගත කිරීමට ෆෝල්ඩර නොමැත." + }, + "helpFeedback": { + "message": "උදව් සහ ප්රතිපෝෂණ" + }, + "sync": { + "message": "සමමුහූර්තනය" + }, + "syncVaultNow": { + "message": "සුරක්ෂිතාගාරය දැන් සමමුහුර්ත කරන්න" + }, + "lastSync": { + "message": "අවසන් සමමුහුර්ත කරන්න:" + }, + "passGen": { + "message": "රහස් පදය උත්පාදක යන්ත්රය" + }, + "generator": { + "message": "උත්පාදක යන්ත්රය", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "ඔබේ පිවිසුම් සඳහා ශක්තිමත්, අද්විතීය මුරපද ස්වයංක්රීයව ජනනය කරන්න." + }, + "bitWebVault": { + "message": "බිට්වර්ඩන් වෙබ් සුරක්ෂිතාගාරය" + }, + "importItems": { + "message": "ආනයන අයිතම" + }, + "select": { + "message": "තෝරන්න" + }, + "generatePassword": { + "message": "මුරපදය ජනනය කරන්න" + }, + "regeneratePassword": { + "message": "මුරපදය ප්රතිජනනය" + }, + "options": { + "message": "විකල්ප" + }, + "length": { + "message": "දිග" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "වචන ගණන" + }, + "wordSeparator": { + "message": "වචනය ෙවන්" + }, + "capitalize": { + "message": "ප්රාග්ධනීකරණය", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "අංකය ඇතුළත් කරන්න" + }, + "minNumbers": { + "message": "අවම අංක" + }, + "minSpecial": { + "message": "අවම විශේෂ" + }, + "avoidAmbChar": { + "message": "අපැහැදිලි චරිත වලින් වළකින්න" + }, + "searchVault": { + "message": "සුරක්ෂිතාගාරය සොයන්න" + }, + "edit": { + "message": "සංස්කරණය" + }, + "view": { + "message": "දකින්න" + }, + "noItemsInList": { + "message": "ලැයිස්තු ගත කිරීමට අයිතම නොමැත." + }, + "itemInformation": { + "message": "අයිතම තොරතුරු" + }, + "username": { + "message": "පරිශීලක නාමය" + }, + "password": { + "message": "මුරපදය" + }, + "passphrase": { + "message": "පැස්ප්රස්" + }, + "favorite": { + "message": "ප්‍රියතමය" + }, + "notes": { + "message": "සටහන්" + }, + "note": { + "message": "සටහන" + }, + "editItem": { + "message": "අයිතම සංස්කරණය කරන්න" + }, + "folder": { + "message": "බහාලුම" + }, + "deleteItem": { + "message": "අයිතමය මකන්න" + }, + "viewItem": { + "message": "දැක්ම අයිතමය" + }, + "launch": { + "message": "දියත්කරන්න" + }, + "website": { + "message": "වියමන අඩවිය" + }, + "toggleVisibility": { + "message": "දෘශ්යතාව ටොගල් කරන්න" + }, + "manage": { + "message": "කළමනාකරණය" + }, + "other": { + "message": "වෙනත්" + }, + "rateExtension": { + "message": "දිගුව අනුපාතය" + }, + "rateExtensionDesc": { + "message": "කරුණාකර හොඳ සමාලෝචනයකින් අපට උදව් කිරීම ගැන සලකා බලන්න!" + }, + "browserNotSupportClipboard": { + "message": "ඔබේ වෙබ් බ්රව්සරය පහසු පසුරු පුවරුවක් පිටපත් කිරීමට සහාය නොදක්වයි. ඒ වෙනුවට එය අතින් පිටපත් කරන්න." + }, + "verifyIdentity": { + "message": "අනන්යතාවය සත්යාපනය කරන්න" + }, + "yourVaultIsLocked": { + "message": "ඔබේ සුරක්ෂිතාගාරය අගුළු දමා ඇත. දිගටම කරගෙන යාමට ඔබේ අනන්යතාවය සත්යාපනය කරන්න." + }, + "unlock": { + "message": "අගුලුහරින්න" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$මත $EMAIL$ ලෙස ලොගින් වී ඇත.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "වලංගු නොවන ප්රධාන මුරපදය" + }, + "vaultTimeout": { + "message": "සුරක්ෂිතාගාරය වේලාව" + }, + "lockNow": { + "message": "දැන් අගුලුදමන්න" + }, + "immediately": { + "message": "වහාම" + }, + "tenSeconds": { + "message": "තත්පර 10" + }, + "twentySeconds": { + "message": "තත්පර 20" + }, + "thirtySeconds": { + "message": "තත්පර 30" + }, + "oneMinute": { + "message": "විනාඩි 1" + }, + "twoMinutes": { + "message": "විනාඩි 2" + }, + "fiveMinutes": { + "message": "විනාඩි 5" + }, + "fifteenMinutes": { + "message": "විනාඩි 15" + }, + "thirtyMinutes": { + "message": "විනාඩි 30" + }, + "oneHour": { + "message": "පැය 1" + }, + "fourHours": { + "message": "පැය 4" + }, + "onLocked": { + "message": "පද්ධතිය ලොක් මත" + }, + "onRestart": { + "message": "බ්රව්සරය නැවත ආරම්භ" + }, + "never": { + "message": "කිසි විටෙකත්" + }, + "security": { + "message": "ආරක්ෂාව" + }, + "errorOccurred": { + "message": "දෝෂයක් සිදුවී ඇත" + }, + "emailRequired": { + "message": "විද්යුත් තැපැල් ලිපිනය අවශ්ය වේ." + }, + "invalidEmail": { + "message": "වලංගු නොවන විද්යුත් තැපැල් ලිපිනය." + }, + "masterPassRequired": { + "message": "ප්රධාන මුරපදය අවශ්ය වේ." + }, + "masterPassLength": { + "message": "ප්රධාන මුරපදය අවම වශයෙන් අක්ෂර 8 ක් දිගු විය යුතුය." + }, + "masterPassDoesntMatch": { + "message": "ප්රධාන මුරපදය තහවුරු කිරීම නොගැලපේ." + }, + "newAccountCreated": { + "message": "ඔබගේ නව ගිණුම නිර්මාණය කර ඇත! ඔබට දැන් ලොග් විය හැකිය." + }, + "masterPassSent": { + "message": "ඔබගේ ප්රධාන මුරපදය ඉඟියක් සමඟ අපි ඔබට විද්යුත් තැපෑලක් යවා ඇත්තෙමු." + }, + "verificationCodeRequired": { + "message": "සත්යාපන කේතය අවශ්ය වේ." + }, + "invalidVerificationCode": { + "message": "වලංගු නොවන සත්යාපන කේතය" + }, + "valueCopied": { + "message": "$VALUE$ පිටපත් කරන ලදි", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "මෙම පිටුවේ තෝරාගත් අයිතමය ස්වයංක්රීයව පිරවිය නොහැක. ඒ වෙනුවට තොරතුරු පිටපත් කර අලවන්න." + }, + "loggedOut": { + "message": "ලොගින් වී" + }, + "loginExpired": { + "message": "ඔබගේ පිවිසුම් සැසිය කල් ඉකුත් වී ඇත." + }, + "logOutConfirmation": { + "message": "ඔබට ලොග් වීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "yes": { + "message": "ඔව්" + }, + "no": { + "message": "නැත" + }, + "unexpectedError": { + "message": "අනපේක්ෂිත දෝෂයක් සිදුවී ඇත." + }, + "nameRequired": { + "message": "නම අවශ්ය වේ." + }, + "addedFolder": { + "message": "එකතු කරන ලද ෆෝල්ඩරය" + }, + "changeMasterPass": { + "message": "ප්රධාන මුරපදය වෙනස්" + }, + "changeMasterPasswordConfirmation": { + "message": "bitwarden.com වෙබ් සුරක්ෂිතාගාරයේ ඔබේ ප්රධාන මුරපදය වෙනස් කළ හැකිය. ඔබට දැන් වෙබ් අඩවියට පිවිසීමට අවශ්යද?" + }, + "twoStepLoginConfirmation": { + "message": "ආරක්ෂක යතුරක්, සත්යාපන යෙදුම, කෙටි පණිවුඩ, දුරකථන ඇමතුමක් හෝ විද්යුත් තැපෑල වැනි වෙනත් උපාංගයක් සමඟ ඔබේ පිවිසුම සත්යාපනය කිරීමට ඔබට අවශ්ය වීමෙන් ද්වි-පියවර පිවිසුම ඔබගේ ගිණුම වඩාත් සුරක්ෂිත කරයි. බිට්වොන්.com වෙබ් සුරක්ෂිතාගාරයේ ද්වි-පියවර පිවිසුම සක්රීය කළ හැකිය. ඔබට දැන් වෙබ් අඩවියට පිවිසීමට අවශ්යද?" + }, + "editedFolder": { + "message": "සංස්කරණය ෆෝල්ඩරය" + }, + "deleteFolderConfirmation": { + "message": "ඔබට මෙම ෆෝල්ඩරය මකා දැමීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "deletedFolder": { + "message": "මකාදැමූ ෆෝල්ඩරය" + }, + "gettingStartedTutorial": { + "message": "ආරම්භ නිබන්ධනය ලබා ගැනීම" + }, + "gettingStartedTutorialVideo": { + "message": "බ්රව්සර් දිගුවෙන් උපරිම ප්රයෝජන ලබා ගන්නේ කෙසේදැයි ඉගෙන ගැනීමට අපගේ ආරම්භ නිබන්ධනය බලන්න." + }, + "syncingComplete": { + "message": "සම්පූර්ණ සමමුහුර්ත" + }, + "syncingFailed": { + "message": "සමමුහුර්ත කිරීම අසාර්ථකයි" + }, + "passwordCopied": { + "message": "මුරපදය පිටපත්" + }, + "uri": { + "message": "වර්ගය" + }, + "uriPosition": { + "message": "යූරි $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "නව වර්ගය" + }, + "addedItem": { + "message": "එකතු කරන ලද අයිතමය" + }, + "editedItem": { + "message": "සංස්කරණය කරන ලද අයිතමය" + }, + "deleteItemConfirmation": { + "message": "ඔබට ඇත්තටම කුණු කූඩයට යැවීමට අවශ්යද?" + }, + "deletedItem": { + "message": "කුණු කූඩයට යවන ලද අයිතමය" + }, + "overwritePassword": { + "message": "මුරපදය නැවත ලියන්න" + }, + "overwritePasswordConfirmation": { + "message": "ඔබට වත්මන් මුරපදය නැවත ලිවීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "බහාලුම සොයන්න" + }, + "searchCollection": { + "message": "සෙවුම් එකතුව" + }, + "searchType": { + "message": "සෙවුම් වර්ගය" + }, + "noneFolder": { + "message": "බහලුමක් නැත", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "අක්රීය කරන්න ලොගින් වන්න නිවේදනය" + }, + "addLoginNotificationDesc": { + "message": "මෙම “ලොගින් වන්න නිවේදනය එකතු කරන්න” ස්වයංක්රීයව ඔබ පළමු වරට ඔවුන් තුලට ප්රවිෂ්ට සෑම අවස්ථාවකදීම ඔබගේ සුරක්ෂිතාගාරය නව පිවිසුම් බේරා ගැනීමට ඔබෙන් විමසනු." + }, + "dontShowCardsCurrentTab": { + "message": "ටැබ් පිටුවේ කාඩ්පත් පෙන්වන්න එපා" + }, + "dontShowCardsCurrentTabDesc": { + "message": "ඔබගේ සුරක්ෂිතාගාරයේ කාඩ්පත් අයිතම පහසුවෙන් ස්වයංක්රීයව පිරවීමේ ප්රවේශය සඳහා 'වත්මන් ටැබ් 'පිටුවේ ලැයිස්තුගත කර ඇත." + }, + "dontShowIdentitiesCurrentTab": { + "message": "ටැබ් පිටුවේ අනන්යතා පෙන්වන්න එපා" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "ඔබගේ සුරක්ෂිතාගාරයේ අනන්යතා අයිතම පහසුවෙන් ස්වයංක්රීය-පිරවීමේ ප්රවේශය සඳහා 'වත්මන් ටැබ්' පිටුවේ ලැයිස්තුගත කර ඇත." + }, + "clearClipboard": { + "message": "පසුරු පුවරුවට පැහැදිලි", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "ඔබගේ පසුරු පුවරුවේ සිට පිටපත් කළ අගයන් ස්වයංක්රීයව ඉවත් කරන්න.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Bitwarden ඔබ වෙනුවෙන් මෙම මුරපදය මතක තබා ගත යුතුද?" + }, + "notificationAddSave": { + "message": "සුරකින්න" + }, + "disableChangedPasswordNotification": { + "message": "වෙනස් කළ මුරපද නිවේදනය අක්රීය කරන්න" + }, + "disableChangedPasswordNotificationDesc": { + "message": "මෙම “වෙනස් මුරපදය නිවේදනය” ස්වයංක්රීයව ඔබ වෙබ් අඩවිය මත එය වෙනස් කර ඇති බව හඳුනාගන්නා සෑම අවස්ථාවකදීම ඔබගේ සුරක්ෂිතාගාරයේ පිවිසුම් මුරපදය යාවත්කාලීන කිරීමට ඔබෙන් විමසනු ඇත." + }, + "notificationChangeDesc": { + "message": "Bitwarden හි මෙම මුරපදය යාවත්කාලීන කිරීමට ඔබට අවශ්යද?" + }, + "notificationChangeSave": { + "message": "යාවත්කාල" + }, + "disableContextMenuItem": { + "message": "සන්දර්භය මෙනු විකල්ප අක්රීය කරන්න" + }, + "disableContextMenuItemDesc": { + "message": "සන්දර්භය මෙනු විකල්පයන් ඔබගේ වත්මන් පටිත්තෙහි ඇති වෙබ් අඩවිය සඳහා මුරපද උත්පාදනය සහ පිවිසුම් සඳහා ඉක්මන් ප්රවේශයක් ලබා දෙයි." + }, + "defaultUriMatchDetection": { + "message": "පෙරනිමි URI තරග හඳුනා", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "එවැනි ස්වයංක්රීය-පිරවීම ලෙස ක්රියා සිදු කරන විට URI තරගය හඳුනා පිවිසුම් සඳහා කටයුතු කරන බව පෙරනිමි මාර්ගය තෝරන්න." + }, + "theme": { + "message": "තේමාව" + }, + "themeDesc": { + "message": "යෙදුමේ වර්ණ තේමාව වෙනස් කරන්න." + }, + "dark": { + "message": "අඳුරු", + "description": "Dark color" + }, + "light": { + "message": "ආලෝකය", + "description": "Light color" + }, + "solarizedDark": { + "message": "අඳුරු අඳුරු", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "අපනයන සුරක්ෂිතාගාරය" + }, + "fileFormat": { + "message": "ගොනු ආකෘතිය" + }, + "warning": { + "message": "අවවාදයයි", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "සුරක්ෂිතාගාරය අපනයන තහවුරු" + }, + "exportWarningDesc": { + "message": "මෙම නිර්යාත ඔබගේ සුරක්ෂිතාගාරය දත්ත සංකේතනය නොකළ ආකෘතියකින් අඩංගු වේ. අනාරක්ෂිත නාලිකා හරහා අපනයනය කරන ලද ගොනුව ගබඩා කිරීම හෝ යැවීම නොකළ යුතුය (විද්යුත් තැපෑල වැනි). ඔබ එය භාවිතා කිරීමෙන් වහාම එය මකන්න." + }, + "encExportKeyWarningDesc": { + "message": "මෙම අපනයනය ඔබගේ ගිණුමේ ගුප්තකේතන යතුර භාවිතා කරමින් ඔබගේ දත්ත සංකේතනය කරයි. ඔබ කවදා හෝ ඔබගේ ගිණුමේ ගුප්තකේතන යතුර භ්රමණය කරන්නේ නම්, ඔබට මෙම අපනයන ගොනුව විකේතනය කිරීමට නොහැකි වනු ඇති බැවින් ඔබ නැවත අපනයනය කළ යුතුය." + }, + "encExportAccountWarningDesc": { + "message": "ගිණුම් සංකේතාංකන යතුරු එක් එක් Bitwarden පරිශීලක ගිණුමට අද්විතීය වේ, එබැවින් ඔබට සංකේතාත්මක අපනයනයක් වෙනත් ගිණුමකට ආනයනය කළ නොහැක." + }, + "exportMasterPassword": { + "message": "ඔබගේ සුරක්ෂිතාගාරය දත්ත අපනයනය කිරීමට ඔබගේ ප්රධාන මුරපදය ඇතුලත් කරන්න." + }, + "shared": { + "message": "බෙදාගත්" + }, + "learnOrg": { + "message": "සංවිධාන ගැන ඉගෙන ගන්න" + }, + "learnOrgConfirmation": { + "message": "සංවිධානයක් භාවිතා කිරීමෙන් ඔබේ සුරක්ෂිතාගාරය අයිතම අන් අය සමඟ බෙදා ගැනීමට Bitwarden ඔබට ඉඩ දෙයි. වැඩි විස්තර දැනගැනීම සඳහා bitwarden.com වෙබ් අඩවියට පිවිසීමට ඔබ කැමතිද?" + }, + "moveToOrganization": { + "message": "සංවිධානය වෙත ගෙනයන්න" + }, + "share": { + "message": "බෙදාගන්න" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ $ORGNAME$වෙත ගෙන ගියේය", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "ඔබ මෙම අයිතමය ගෙන යාමට කැමති සංවිධානයක් තෝරන්න. සංවිධානයක් වෙත යාම එම අයිතමයේ හිමිකාරිත්වය එම සංවිධානයට පැවරේ. එය ගෙන ගිය පසු ඔබ තවදුරටත් මෙම අයිතමයේ සෘජු හිමිකරු වනු ඇත." + }, + "learnMore": { + "message": "වැඩිදුර ඉගෙන ගන්න" + }, + "authenticatorKeyTotp": { + "message": "සත්යාපන යතුර (TOTP)" + }, + "verificationCodeTotp": { + "message": "සත්යාපන කේතය (TOTP)" + }, + "copyVerificationCode": { + "message": "සත්යාපන කේතය පිටපත් කරන්න" + }, + "attachments": { + "message": "ඇමුණුම්" + }, + "deleteAttachment": { + "message": "ඇමුණුම මකන්න" + }, + "deleteAttachmentConfirmation": { + "message": "ඔබට මෙම ඇමුණුම මකා දැමීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "deletedAttachment": { + "message": "මකාදැමූ ඇමුණු" + }, + "newAttachment": { + "message": "නව ඇමුණුමක් එකතු කරන්න" + }, + "noAttachments": { + "message": "ඇමුණුම් නොමැත." + }, + "attachmentSaved": { + "message": "ඇමුණුම ගැලවීම කර ඇත." + }, + "file": { + "message": "ගොනුව" + }, + "selectFile": { + "message": "ගොනුවක් තෝරන්න." + }, + "maxFileSize": { + "message": "උපරිම ගොනු ප්රමාණය 500 MB වේ." + }, + "featureUnavailable": { + "message": "විශේෂාංගය ලබාගත නොහැක" + }, + "updateKey": { + "message": "ඔබ ඔබේ සංකේතාංකන යතුර යාවත්කාලීන කරන තුරු ඔබට මෙම අංගය භාවිතා කළ නොහැක." + }, + "premiumMembership": { + "message": "වාරික සාමාජිකත්වය" + }, + "premiumManage": { + "message": "සාමාජිකත්වය කළමනාකරණය කරන්න" + }, + "premiumManageAlert": { + "message": "බිට්වොන්.com වෙබ් සුරක්ෂිතාගාරයේ ඔබේ සාමාජිකත්වය කළමනාකරණය කළ හැකිය. ඔබට දැන් වෙබ් අඩවියට පිවිසීමට අවශ්යද?" + }, + "premiumRefresh": { + "message": "සාමාජිකත්වය නැවුම් කරන්න" + }, + "premiumNotCurrentMember": { + "message": "ඔබ දැනට වාරික සාමාජිකයෙකු නොවේ." + }, + "premiumSignUpAndGet": { + "message": "වාරික සාමාජිකත්වය සඳහා ලියාපදිංචි වී ලබා ගන්න:" + }, + "ppremiumSignUpStorage": { + "message": "ගොනු ඇමුණුම් සඳහා 1 GB සංකේතාත්මක ගබඩා." + }, + "ppremiumSignUpTwoStep": { + "message": "එවැනි YuBiKey, FIDO U2F, සහ Duo ලෙස අතිරේක පියවර දෙකක් පිවිසුම් විකල්ප." + }, + "ppremiumSignUpReports": { + "message": "ඔබගේ සුරක්ෂිතාගාරය ආරක්ෂිතව තබා ගැනීම සඳහා මුරපදය සනීපාරක්ෂාව, ගිණුම් සෞඛ්යය සහ දත්ත උල්ලං ach නය වාර්තා කරයි." + }, + "ppremiumSignUpTotp": { + "message": "TOTP සත්යාපන කේතය (2FA) ඔබගේ සුරක්ෂිතාගාරයේ පිවිසුම් සඳහා ජනකය." + }, + "ppremiumSignUpSupport": { + "message": "ප්රමුඛතා පාරිභෝගික සහාය." + }, + "ppremiumSignUpFuture": { + "message": "සියලුම අනාගත වාරික විශේෂාංග. තවත් ළඟදීම!" + }, + "premiumPurchase": { + "message": "වාරික මිලදී" + }, + "premiumPurchaseAlert": { + "message": "ඔබට bitwarden.com වෙබ් සුරක්ෂිතාගාරයේ වාරික සාමාජිකත්වය මිලදී ගත හැකිය. ඔබට දැන් වෙබ් අඩවියට පිවිසීමට අවශ්යද?" + }, + "premiumCurrentMember": { + "message": "ඔබ වාරික සාමාජිකයෙක්!" + }, + "premiumCurrentMemberThanks": { + "message": "බිට්වර්ඩන්ට සහාය වීම ගැන ස්තූතියි." + }, + "premiumPrice": { + "message": "සියල්ල $PRICE$ /අවුරුද්ද සඳහා!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "සම්පූර්ණ නැවුම් කරන්න" + }, + "disableAutoTotpCopy": { + "message": "ස්වයංක්රීය TOTP පිටපත් අක්රීය" + }, + "disableAutoTotpCopyDesc": { + "message": "ඔබගේ පිවිසුමට සත්යාපන යතුරක් අමුණා තිබේ නම්, ඔබ පිවිසුම ස්වයංක්රීයව පුරවන සෑම අවස්ථාවකදීම TOTP සත්යාපන කේතය ස්වයංක්රීයව ඔබගේ පසුරු පුවරුවට පිටපත් කරනු ලැබේ." + }, + "disableAutoBiometricsPrompt": { + "message": "දියත් කිරීම සඳහා ජෛව මිතික විද්යාව සඳහා විමසුම් නොකරන්න" + }, + "premiumRequired": { + "message": "වාරික අවශ්ය" + }, + "premiumRequiredDesc": { + "message": "මෙම අංගය භාවිතා කිරීම සඳහා වාරික සාමාජිකත්වයක් අවශ්ය වේ." + }, + "enterVerificationCodeApp": { + "message": "ඔබගේ සත්යාපන යෙදුමෙන් 6 ඉලක්කම් සත්යාපන කේතය ඇතුළත් කරන්න." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$වෙත ඊමේල් කරන ලද 6 ඉලක්කම් සත්යාපන කේතය ඇතුළත් කරන්න.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "සත්යාපන විද්යුත් තැපෑල $EMAIL$වෙත යවා ඇත.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "මාව මතක තබා ගන්න" + }, + "sendVerificationCodeEmailAgain": { + "message": "සත්යාපන කේතය නැවත විද්යුත් තැපෑල යවන්න" + }, + "useAnotherTwoStepMethod": { + "message": "තවත් පියවර දෙකක පිවිසුම් ක්රමයක් භාවිතා කරන්න" + }, + "insertYubiKey": { + "message": "ඔබේ පරිගණකයේ USB පෝට් එකට ඔබගේ YuBiKey ඇතුල් කරන්න, ඉන්පසු එහි බොත්තම ස්පර්ශ කරන්න." + }, + "insertU2f": { + "message": "ඔබේ ආරක්ෂක යතුර ඔබේ පරිගණකයේ USB පෝට් එකට ඇතුල් කරන්න. එයට බොත්තමක් තිබේ නම් එය ස්පර්ශ කරන්න." + }, + "webAuthnNewTab": { + "message": "WebAUTN 2FA සත්යාපනය ආරම්භ කිරීමට. නව පටිත්තක් විවෘත කිරීමට පහත බොත්තම ක්ලික් කර නව පටිත්තෙහි ඇති උපදෙස් අනුගමනය කරන්න." + }, + "webAuthnNewTabOpen": { + "message": "නව ටැබය විවෘත කරන්න" + }, + "webAuthnAuthenticate": { + "message": "සත්‍යවත් වෙබ් සත්‍යවත් කරන්න" + }, + "loginUnavailable": { + "message": "ලොගින් වන්න ලබාගත නොහැක" + }, + "noTwoStepProviders": { + "message": "මෙම ගිණුමේ පියවර දෙකක පිවිසුම් සක්රීය කර ඇත, කෙසේ වෙතත්, වින්යාසගත කළ පියවර දෙකක සපයන්නන් කිසිවක් මෙම වෙබ් බ්රව්සරයේ සහාය නොදක්වයි." + }, + "noTwoStepProviders2": { + "message": "කරුණාකර සහාය දක්වන වෙබ් බ්රව්සරයක් (Chrome වැනි) භාවිතා කරන්න සහ/හෝ වෙබ් බ්රව්සර් හරහා වඩා හොඳ සහය දක්වන අතිරේක සැපයුම්කරුවන් එකතු කරන්න (සත්යාපන යෙදුමක් වැනි)." + }, + "twoStepOptions": { + "message": "ද්වි-පියවර ලොගින් වන්න විකල්ප" + }, + "recoveryCodeDesc": { + "message": "ඔබගේ ද්වි-සාධක සපයන්නන් සියලු ප්රවේශ අහිමි? ඔබගේ ගිණුමෙන් සියලුම ද්වි-සාධක සපයන්නන් අක්රීය කිරීමට ඔබගේ ප්රතිසාධන කේතය භාවිතා කරන්න." + }, + "recoveryCodeTitle": { + "message": "ප්රතිසාධන කේතය" + }, + "authenticatorAppTitle": { + "message": "සත්යාපන යෙදුම" + }, + "authenticatorAppDesc": { + "message": "කාලය මත පදනම් වූ සත්යාපන කේත ජනනය කිරීම සඳහා සත්යාපන යෙදුමක් (සත්යාපන හෝ ගූගල් සත්යාපන වැනි) භාවිතා කරන්න.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP ආරක්ෂක යතුර" + }, + "yubiKeyDesc": { + "message": "ඔබගේ ගිණුමට ප්රවේශ වීමට YuBiKey භාවිතා කරන්න. YuBiKey 4, 4 නැනෝ, 4C, සහ NEO උපාංග සමඟ ක්රියා කරයි." + }, + "duoDesc": { + "message": "Duo ජංගම යෙදුම, කෙටි පණිවුඩ, දුරකථන ඇමතුමක්, හෝ U2F ආරක්ෂක යතුර භාවිතා කරමින් Duo ආරක්ෂක සමඟ තහවුරු කරන්න.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo ජංගම යෙදුම, කෙටි පණිවුඩ, දුරකථන ඇමතුමක්, හෝ U2F ආරක්ෂක යතුර භාවිතා ඔබේ සංවිධානය සඳහා Duo ආරක්ෂක සමඟ තහවුරු කරන්න.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 වෙබ්සත්ටින්" + }, + "webAuthnDesc": { + "message": "ඔබගේ ගිණුමට ප්රවේශ වීමට ඕනෑම WebAUTUN සක්රීය ආරක්ෂක යතුරක් භාවිතා කරන්න." + }, + "emailTitle": { + "message": "ඊ-තැපැල්" + }, + "emailDesc": { + "message": "සත්යාපන කේත ඔබට විද්යුත් තැපැල් කරනු ඇත." + }, + "selfHostedEnvironment": { + "message": "ස්වයං සත්කාරක පරිසරය" + }, + "selfHostedEnvironmentFooter": { + "message": "බිට්වර්ඩන් ස්ථාපනය සත්කාරකත්වය දරනු ලබන ඔබගේ පරිශ්රයේ මූලික URL එක සඳහන් කරන්න." + }, + "customEnvironment": { + "message": "අභිරුචි පරිසරය" + }, + "customEnvironmentFooter": { + "message": "උසස් පරිශීලකයින් සඳහා. එක් එක් සේවාවෙහි මූලික URL එක ස්වාධීනව සඳහන් කළ හැකිය." + }, + "baseUrl": { + "message": "සේවාදායකය URL" + }, + "apiUrl": { + "message": "API සේවාදායකය URL" + }, + "webVaultUrl": { + "message": "වෙබ් සුරක්ෂිතාගාරය සේවාදායකය URL" + }, + "identityUrl": { + "message": "අනන්යතා සේවාදායකය URL" + }, + "notificationsUrl": { + "message": "සේවාදායක URL දැනුම්දීම්" + }, + "iconsUrl": { + "message": "අයිකන සර්වර් URL" + }, + "environmentSaved": { + "message": "පරිසර URL සුරකිනු ඇත." + }, + "enableAutoFillOnPageLoad": { + "message": "පිටු පැටවුම් මත ස්වයංක්රීය-පිරවීම සක්රීය" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "පිවිසුම් පෝරමයක් අනාවරණය කර ඇත්නම්, වෙබ් පිටුව පැටවුම් කරන විට ස්වයංක්රීයව ස්වයංක්රීයව පිරවීම සිදු කරන්න." + }, + "experimentalFeature": { + "message": "මෙය දැනට පර්යේෂණාත්මක ලක්ෂණයකි. ඔබේම අවදානමකින් භාවිතා කරන්න." + }, + "defaultAutoFillOnPageLoad": { + "message": "පිවිසුම් අයිතම සඳහා පෙරනිමි autofill සැකසුම" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "පිටු පැටවුම් මත වාහන-පිරවීම සක්රීය කිරීමෙන් පසු, ඔබ තනි පිවිසුම් අයිතම සඳහා විශේෂාංගය සක්රිය හෝ අක්රිය කළ හැකිය. වෙන වෙනම වින්යාස කර නොමැති පිවිසුම් අයිතම සඳහා පෙරනිමි සැකසුම මෙයයි." + }, + "itemAutoFillOnPageLoad": { + "message": "පිටු පැටවුම් මත ස්වයංක්රීය-පිරවීම (විකල්ප සක්රීය නම්)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "පෙරනිමි සැකසුම භාවිතා" + }, + "autoFillOnPageLoadYes": { + "message": "පිටු බර මත ස්වයංක්රීයව පුරවන්න" + }, + "autoFillOnPageLoadNo": { + "message": "පිටු බර මත ස්වයංක්රීයව පුරවන්න එපා" + }, + "commandOpenPopup": { + "message": "විවෘත සුරක්ෂිතාගාරය උත්පතන" + }, + "commandOpenSidebar": { + "message": "පැති තීරුවේ විවෘත සුරක්ෂිතාගාරය" + }, + "commandAutofillDesc": { + "message": "වත්මන් වෙබ් අඩවිය සඳහා අවසන් වරට භාවිතා කරන ලද පිවිසුම ස්වයංක්රීය-පුරවන්න" + }, + "commandGeneratePasswordDesc": { + "message": "පසුරු පුවරුවට නව අහඹු මුරපදයක් ජනනය කර පිටපත් කරන්න" + }, + "commandLockVaultDesc": { + "message": "සුරක්ෂිතාගාරය ලොක් කරන්න" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "අභිරුචි ක්ෂේත්ර" + }, + "copyValue": { + "message": "පිටපත් වටිනාකම" + }, + "value": { + "message": "වටිනාකම" + }, + "newCustomField": { + "message": "නව රේගු ක්ෂේත්ර" + }, + "dragToSort": { + "message": "වර්ග කිරීමට ඇද දමන්න" + }, + "cfTypeText": { + "message": "පෙළ" + }, + "cfTypeHidden": { + "message": "සැඟවුනු" + }, + "cfTypeBoolean": { + "message": "බූලියන්" + }, + "cfTypeLinked": { + "message": "සම්බන්ධිත", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "සම්බන්ධිත අගය", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "ඔබගේ සත්යාපන කේතය සඳහා ඔබගේ ඊ-තැපැල් පරීක්ෂා කිරීමට උත්පතන කවුළුවෙන් පිටත ක්ලික් කිරීමෙන් මෙම උත්පතන වසා දැමීමට හේතු වේ. මෙම උත්පතන නව කවුළුවක විවෘත කිරීමට ඔබට අවශ්යද?" + }, + "popupU2fCloseMessage": { + "message": "මෙම බ්රවුසරයට මෙම උත්පතන කවුළුව තුළ U2F ඉල්ලීම් සැකසීමට නොහැක. ඔබට U2F භාවිතයෙන් පිවිසිය හැකි වන පරිදි නව කවුළුවක මෙම උත්පතන විවෘත කිරීමට අවශ්යද?" + }, + "disableFavicon": { + "message": "වෙබ් අඩවි අයිකන අක්රීය කරන්න" + }, + "disableFaviconDesc": { + "message": "වෙබ් අඩවි අයිකන ඔබගේ සුරක්ෂිතාගාරයේ එක් එක් පිවිසුම් අයිතමයට යාබදව හඳුනාගත හැකි රූපයක් ලබා දෙයි." + }, + "disableBadgeCounter": { + "message": "බැජ් කවුන්ටරය අක්රීය කරන්න" + }, + "disableBadgeCounterDesc": { + "message": "බැජ් කවුන්ටරය ඔබ ඔබේ සුරක්ෂිතාගාරයේ වත්මන් පිටුව සඳහා කොපමණ පිවිසුම් පෙන්නුම් කරයි." + }, + "cardholderName": { + "message": "කාඞ්පත් හිමි නම" + }, + "number": { + "message": "අංකය" + }, + "brand": { + "message": "වෙළඳ නාමය" + }, + "expirationMonth": { + "message": "කල් ඉකුත්වන මාසය" + }, + "expirationYear": { + "message": "කල් ඉකුත්වන වසර" + }, + "expiration": { + "message": "කල් ඉකුත්" + }, + "january": { + "message": "දුරුතු" + }, + "february": { + "message": "නවම්" + }, + "march": { + "message": "මැදින්" + }, + "april": { + "message": "බක්" + }, + "may": { + "message": "වෙසක්" + }, + "june": { + "message": "පොසොන්" + }, + "july": { + "message": "ඇසළ" + }, + "august": { + "message": "නිකිණි" + }, + "september": { + "message": "බිනර" + }, + "october": { + "message": "වප්" + }, + "november": { + "message": "ඉල්" + }, + "december": { + "message": "උඳුවප්" + }, + "securityCode": { + "message": "ආරක්ෂක කේතය" + }, + "ex": { + "message": "හිටපු." + }, + "title": { + "message": "මාතෘකාව" + }, + "mr": { + "message": "මහතා" + }, + "mrs": { + "message": "මහත්මිය" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "ආචාර්ය" + }, + "firstName": { + "message": "මුල් නම" + }, + "middleName": { + "message": "මැද නම" + }, + "lastName": { + "message": "අවසාන නම" + }, + "fullName": { + "message": "සම්පූර්ණ නම" + }, + "identityName": { + "message": "අනන්යතා නාමය" + }, + "company": { + "message": "සමාගම" + }, + "ssn": { + "message": "සමාජ ආරක්ෂණ අංකය" + }, + "passportNumber": { + "message": "ගමන් බලපත්ර අංකය" + }, + "licenseNumber": { + "message": "බලපත්ර අංකය" + }, + "email": { + "message": "ඊ-තැපැල්" + }, + "phone": { + "message": "දුරකථන" + }, + "address": { + "message": "ලිපිනය" + }, + "address1": { + "message": "ලිපිනය 1" + }, + "address2": { + "message": "ලිපිනය 2" + }, + "address3": { + "message": "ලිපිනය 3" + }, + "cityTown": { + "message": "නගරය/නගරය" + }, + "stateProvince": { + "message": "රාජ්ය/පළාත" + }, + "zipPostalCode": { + "message": "Zip/තැපැල් කේතය" + }, + "country": { + "message": "රට" + }, + "type": { + "message": "වර්ගය" + }, + "typeLogin": { + "message": "ලොගින් වන්න" + }, + "typeLogins": { + "message": "ලොගින් වන්න" + }, + "typeSecureNote": { + "message": "ආරක්ෂිත සටහන" + }, + "typeCard": { + "message": "කාඩ්" + }, + "typeIdentity": { + "message": "අනන්යතාවය" + }, + "passwordHistory": { + "message": "මුරපද ඉතිහාසය" + }, + "back": { + "message": "ආපසු" + }, + "collections": { + "message": "එකතුව" + }, + "favorites": { + "message": "ප්රියතම දැන්වීම්" + }, + "popOutNewWindow": { + "message": "නව කවුළුවකට පොප්" + }, + "refresh": { + "message": "නැවුම් කරන්න" + }, + "cards": { + "message": "කාඩ්" + }, + "identities": { + "message": "අනන්යතා" + }, + "logins": { + "message": "ලොගින් වන්න" + }, + "secureNotes": { + "message": "ආරක්ෂිත සටහන්" + }, + "clear": { + "message": "පැහැදිලි", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "මුරපදය නිරාවරණය වී ඇත්දැයි පරීක්ෂා කරන්න." + }, + "passwordExposed": { + "message": "මෙම මුරපදය නිරාවරණය කර ඇත $VALUE$ කාලය (ය) දත්ත උල්ලං aches නය කිරීම් වලදී. ඔබ එය වෙනස් කළ යුතුය.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "මෙම මුරපදය දන්නා දත්ත උල්ලං aches නය කිරීම් වලින් සොයාගත නොහැකි විය. එය භාවිතා කිරීමට ආරක්ෂිත විය යුතුය." + }, + "baseDomain": { + "message": "මූලික වසම", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "සත්කාරක", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "නිශ්චිතවම" + }, + "startsWith": { + "message": "සමඟ ආරම්භ වේ" + }, + "regEx": { + "message": "නිතිපතා ප්රකාශනය", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "තරගය හඳුනා", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "පෙරනිමි තරගය හඳුනා", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "ටොගල් කරන්න විකල්ප" + }, + "toggleCurrentUris": { + "message": "ටොගල් කරන්න වත්මන් URis", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "වත්මන් වර්ගය", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "සංවිධානය", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "වර්ග" + }, + "allItems": { + "message": "සියලු අයිතම" + }, + "noPasswordsInList": { + "message": "ලැයිස්තු ගත කිරීමට මුරපද නොමැත." + }, + "remove": { + "message": "ඉවත් කරන්න" + }, + "default": { + "message": "පෙරනිමි" + }, + "dateUpdated": { + "message": "යාවත්කාලීන", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "මුරපදය යාවත්කාලීන කිරීම", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "ඔබට “කිසි විටෙකත්” විකල්පය භාවිතා කිරීමට අවශ්ය බව ඔබට විශ්වාසද? ඔබගේ අගුළු විකල්පයන් “කිසි විටෙකත්” ඔබගේ උපාංගයේ ඔබගේ සුරක්ෂිතාගාරයේ සංකේතාංකන යතුර ගබඩා කරයි. ඔබ මෙම විකල්පය භාවිතා කරන්නේ නම් ඔබ ඔබේ උපාංගය නිසි ලෙස ආරක්ෂා කර ඇති බවට සහතික විය යුතුය." + }, + "noOrganizationsList": { + "message": "ඔබ කිසිදු සංවිධානයකට අයත් නොවේ. වෙනත් පරිශීලකයින් සමඟ අයිතම ආරක්ෂිතව බෙදා ගැනීමට සංවිධාන ඔබට ඉඩ දෙයි." + }, + "noCollectionsInList": { + "message": "ලැයිස්තු ගත කිරීම සඳහා එකතු කිරීම් නොමැත." + }, + "ownership": { + "message": "හිමිකාරිත්වය" + }, + "whoOwnsThisItem": { + "message": "මෙම අයිතමය අයිති කවුද?" + }, + "strong": { + "message": "ශක්තිමත්", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "හොඳ", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "දුර්වලයි", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "දුර්වල මාස්ටර් මුරපදය" + }, + "weakMasterPasswordDesc": { + "message": "ඔබ තෝරාගත් ප්රධාන මුරපදය දුර්වලයි. ඔබේ Bitwarden ගිණුම නිසි ලෙස ආරක්ෂා කිරීම සඳහා ඔබ ශක්තිමත් ප්රධාන මුරපදයක් (හෝ passphrase) භාවිතා කළ යුතුය. ඔබට මෙම ප්රධාන මුරපදය භාවිතා කිරීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "pin": { + "message": "පින්", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "PIN අංකය සමඟ විවෘත" + }, + "setYourPinCode": { + "message": "බිට්වර්ඩන් අගුළු ඇරීමට ඔබේ PIN අංකය කේතය සකසන්න. ඔබ කවදා හෝ යෙදුමෙන් සම්පූර්ණයෙන්ම පුරනය වී ඇත්නම් ඔබගේ PIN සැකසුම් නැවත සකසනු ඇත." + }, + "pinRequired": { + "message": "PIN කේතය අවශ්ය වේ." + }, + "invalidPin": { + "message": "වලංගු නොවන PIN කේතය." + }, + "unlockWithBiometrics": { + "message": "ජෛව විද්යාව සමඟ අගුළු ඇරීම" + }, + "awaitDesktop": { + "message": "ඩෙස්ක්ටොප් සිට තහවුරු කිරීම බලාපොරොත්තුවෙන්" + }, + "awaitDesktopDesc": { + "message": "බ්රව්සරය සඳහා biometrics සක්රීය කිරීම සඳහා Bitwarden ඩෙස්ක්ටොප් යෙදුමේ biometrics භාවිතා කිරීම තහවුරු කරන්න." + }, + "lockWithMasterPassOnRestart": { + "message": "බ්රව්සරය නැවත ආරම්භ මත ප්රධාන මුරපදය සමග අගුළු" + }, + "selectOneCollection": { + "message": "ඔබ අවම වශයෙන් එක් එකතුවක්වත් තෝරා ගත යුතුය." + }, + "cloneItem": { + "message": "ක්ලෝන අයිතම" + }, + "clone": { + "message": "ක්ලෝන" + }, + "passwordGeneratorPolicyInEffect": { + "message": "සංවිධාන ප්රතිපත්ති එකක් හෝ වැඩි ගණනක් ඔබේ උත්පාදක සැකසුම් වලට බලපායි." + }, + "vaultTimeoutAction": { + "message": "සුරක්ෂිතාගාරය කාලය ක්රියාකාරී" + }, + "lock": { + "message": "අගුල", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "කුණු කූඩයට", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "කුණු කූඩය සොයන්න" + }, + "permanentlyDeleteItem": { + "message": "ස්ථිරවම මකන්න" + }, + "permanentlyDeleteItemConfirmation": { + "message": "ඔබට මෙම අයිතමය ස්ථිරවම මකා දැමීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "permanentlyDeletedItem": { + "message": "ස්ථිරව මකා දැමූ අයිතමය" + }, + "restoreItem": { + "message": "අයිතමය යළි පිහිටුවන්න" + }, + "restoreItemConfirmation": { + "message": "ඔබට මෙම අයිතමය යථා තත්වයට පත් කිරීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "restoredItem": { + "message": "ප්රතිෂ්ඨාපනය අයිතමය" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "පිටතට පිවිසීමෙන් ඔබගේ සුරක්ෂිතාගාරය වෙත ඇති සියලුම ප්රවේශය ඉවත් කරනු ඇති අතර කාල සීමාව පසු මාර්ගගත සත්යාපනය අවශ්ය වේ. ඔබට මෙම සැකසුම භාවිතා කිරීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "කාලය ක්රියාත්මක කිරීම තහවුරු කිරීම" + }, + "autoFillAndSave": { + "message": "ස්වයංක්රීය-පිරවීම සහ සුරකින්න" + }, + "autoFillSuccessAndSavedUri": { + "message": "ස්වයංක්රීය-පිරවූ අයිතමය සහ සුරකින ලද URI" + }, + "autoFillSuccess": { + "message": "ස්වයංක්රීය-පිරවූ අයිතමය" + }, + "setMasterPassword": { + "message": "මාස්ටර් මුරපදය සකසන්න" + }, + "masterPasswordPolicyInEffect": { + "message": "සංවිධාන ප්රතිපත්ති එකක් හෝ වැඩි ගණනක් පහත සඳහන් අවශ්යතා සපුරාලීම සඳහා ඔබේ ප්රධාන මුරපදය අවශ්ය වේ:" + }, + "policyInEffectMinComplexity": { + "message": "අවම සංකීර්ණත්වය ලකුණු $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "අවම දිග $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "ඉහළ අක්ෂර එකක් හෝ කිහිපයක් අඩංගු" + }, + "policyInEffectLowercase": { + "message": "සිම්පල් අක්ෂර එකක් හෝ කිහිපයක් අඩංගු කරන්න" + }, + "policyInEffectNumbers": { + "message": "අංක එකක් හෝ වැඩි ගණනක් අඩංගු කරන්න" + }, + "policyInEffectSpecial": { + "message": "පහත දැක්වෙන විශේෂ අක්ෂර වලින් එකක් හෝ කිහිපයක් අඩංගු කරන්න $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "ඔබගේ නව ප්රධාන මුරපදය ප්රතිපත්ති අවශ්යතා සපුරාලන්නේ නැත." + }, + "acceptPolicies": { + "message": "මෙම කොටුව පරීක්ෂා කිරීමෙන් ඔබ පහත සඳහන් දෑ වලට එකඟ වේ:" + }, + "acceptPoliciesError": { + "message": "සේවා කොන්දේසි සහ රහස්යතා ප්රතිපත්තිය පිළිගෙන නොමැත." + }, + "termsOfService": { + "message": "සේවා කොන්දේසි" + }, + "privacyPolicy": { + "message": "රහස්යතා ප්රතිපත්තිය" + }, + "hintEqualsPassword": { + "message": "ඔබගේ මුරපද ඉඟිය ඔබගේ මුරපදයට සමාන විය නොහැක." + }, + "ok": { + "message": "හරි" + }, + "desktopSyncVerificationTitle": { + "message": "ඩෙස්ක්ටොප් සමමුහුර්ත සත්යාපනය" + }, + "desktopIntegrationVerificationText": { + "message": "ඩෙස්ක්ටොප් යෙදුම මෙම ඇඟිලි සලකුණ පෙන්වන බව කරුණාකර තහවුරු කරන්න: " + }, + "desktopIntegrationDisabledTitle": { + "message": "බ්රව්සර් ඒකාබද්ධ සක්රීය කර නැත" + }, + "desktopIntegrationDisabledDesc": { + "message": "බිට්වර්ඩන් ඩෙස්ක්ටොප් යෙදුම තුළ බ්රව්සර් ඒකාබද්ධ කිරීම සක්රීය කර නොමැත. කරුණාකර ඩෙස්ක්ටොප් යෙදුම තුළ සැකසුම් තුළ එය සක්රීය කරන්න." + }, + "startDesktopTitle": { + "message": "බිට්වර්ඩන් ඩෙස්ක්ටොප් යෙදුම ආරම්භ කරන්න" + }, + "startDesktopDesc": { + "message": "මෙම ශ්රිතය භාවිතා කිරීමට පෙර බිට්වර්ඩන් ඩෙස්ක්ටොප් යෙදුම ආරම්භ කළ යුතුය." + }, + "errorEnableBiometricTitle": { + "message": "ජෛව විද්යාත්මක සක්රීය කිරීමට නොහැකි විය" + }, + "errorEnableBiometricDesc": { + "message": "ඩෙස්ක්ටොප් යෙදුම මගින් ක්රියාව අවලංගු කරන ලදී" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "ඩෙස්ක්ටොප් යෙදුම ආරක්ෂිත සන්නිවේදන නාලිකාව අවලංගු කළේය. කරුණාකර මෙම මෙහෙයුම නැවත උත්සාහ කරන්න" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "ඩෙස්ක්ටොප් සන්නිවේදනය බාධා" + }, + "nativeMessagingWrongUserDesc": { + "message": "ඩෙස්ක්ටොප් යෙදුම වෙනත් ගිණුමකට ලොගින් වී ඇත. කරුණාකර අයදුම්පත් දෙකම එකම ගිණුමකට ලොගින් වී ඇති බවට සහතික වන්න." + }, + "nativeMessagingWrongUserTitle": { + "message": "ගිණුම මිස්ගැලච්" + }, + "biometricsNotEnabledTitle": { + "message": "ජීව විද්යාව සක්රීය කර නැත" + }, + "biometricsNotEnabledDesc": { + "message": "බ්රව්සරය biometrics පළමු සැකසුම් සක්රීය කිරීමට ඩෙස්ක්ටොප් ජීව අවශ්ය වේ." + }, + "biometricsNotSupportedTitle": { + "message": "ජෛව විද්යාව සඳහා සහය නොදක්වයි" + }, + "biometricsNotSupportedDesc": { + "message": "බ්රව්සර් biometrics මෙම උපාංගය මත සහය නොදක්වයි." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "අවසර ලබා දී නැත" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "බිට්වර්ඩන් ඩෙස්ක්ටොප් යෙදුම සමඟ සන්නිවේදනය කිරීමට අවසරයකින් තොරව අපට බ්රව්සර් දිගුවේ ජෛව මිතික ලබා දිය නොහැක. කරුණාකර නැවත උත්සාහ කරන්න." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "අවසර ඉල්ලීමේ දෝෂය" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "මෙම ක්රියාව පැති තීරුවේ කළ නොහැක, කරුණාකර උත්පතන හෝ උත්පතන තුළ ක්රියාව නැවත උත්සාහ කරන්න." + }, + "personalOwnershipSubmitError": { + "message": "ව්යවසාය ප්රතිපත්තියක් හේතුවෙන්, ඔබේ පුද්ගලික සුරක්ෂිතාගාරය වෙත භාණ්ඩ ඉතිරි කිරීම සීමා කර ඇත. හිමිකාරිත්ව විකල්පය සංවිධානයකට වෙනස් කර ලබා ගත හැකි එකතුවෙන් තෝරා ගන්න." + }, + "personalOwnershipPolicyInEffect": { + "message": "සංවිධාන ප්රතිපත්තියක් ඔබේ හිමිකාරිත්ව විකල්පයන් කෙරෙහි බලපායි." + }, + "excludedDomains": { + "message": "බැහැර වසම්" + }, + "excludedDomainsDesc": { + "message": "බිට්වර්ඩන් මෙම වසම් සඳහා පිවිසුම් තොරතුරු සුරැකීමට ඉල්ලා නොසිටිනු ඇත. බලාත්මක කිරීම සඳහා වෙනස්කම් සඳහා ඔබ පිටුව නැවුම් කළ යුතුය." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ වලංගු වසමක් නොවේ", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "යවන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "සෙවුම් යවයි", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "යවන්න එකතු කරන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "පෙළ" + }, + "sendTypeFile": { + "message": "ගොනුව" + }, + "allSends": { + "message": "සියලු යවයි", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "මැක්ස් ප්රවේශ ගණන ළඟා", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "කල් ඉකුත්" + }, + "pendingDeletion": { + "message": "මකාදැමීම" + }, + "passwordProtected": { + "message": "මුරපදය ආරක්ෂා" + }, + "copySendLink": { + "message": "සබැඳිය යවන්න පිටපත් කරන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "මුරපදය ඉවත් කරන්න" + }, + "delete": { + "message": "මකන්න" + }, + "removedPassword": { + "message": "ඉවත් කරන ලද මුරපදය" + }, + "deletedSend": { + "message": "මකාදැමූ යවන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "සබැඳිය යවන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "අබල කර ඇත" + }, + "removePasswordConfirmation": { + "message": "ඔබට මුරපදය ඉවත් කිරීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "deleteSend": { + "message": "යවන්න මකන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "ඔබට මෙය මකා දැමීමට අවශ්ය බව ඔබට විශ්වාසද?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "යැවීම සංස්කරණය", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "මෙය කුමන ආකාරයේ යවන්න ද?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "මෙම යවන්න විස්තර කිරීමට මිත්රශීලී නමක්.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "ඔබට යැවීමට අවශ්ය ගොනුව." + }, + "deletionDate": { + "message": "මකාදැමීමේ දිනය" + }, + "deletionDateDesc": { + "message": "නියම කරන ලද දිනය හා වේලාව මත Send ස්ථිරවම මකා දමනු ලැබේ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "කල් ඉකුත්වන දිනය" + }, + "expirationDateDesc": { + "message": "සකසා ඇත්නම්, මෙම යවන්න වෙත ප්රවේශය නිශ්චිත දිනය හා වේලාව කල් ඉකුත් වනු ඇත.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "දින 1" + }, + "days": { + "message": "$DAYS$ දින", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "අභිරුචි" + }, + "maximumAccessCount": { + "message": "උපරිම ප්රවේශ ගණන්" + }, + "maximumAccessCountDesc": { + "message": "සකසා ඇත්නම්, උපරිම ප්රවේශ ගණන ළඟා වූ පසු පරිශීලකයින්ට මෙම Send වෙත ප්රවේශ වීමට තවදුරටත් නොහැකි වනු ඇත.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "විකල්පයක් ලෙස පරිශීලකයින්ට මෙම යවන්න වෙත ප්රවේශ වීමට මුරපදයක් අවශ්ය වේ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "මේ ගැන පෞද්ගලික සටහන් යවන්න.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "මෙය අක්රීය කරන්න යවන්න එවිට කිසිවෙකුට එයට ප්රවේශ විය නොහැක.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "සුරකින්න මත මෙම යවන්න ගේ සබැඳිය පසුරු පුවරුවට පිටපත් කරන්න.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "ඔබට යැවීමට අවශ්ය පෙළ." + }, + "sendHideText": { + "message": "මෙම යවන්න පෙළ පෙරනිමියෙන් සඟවන්න.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "වත්මන් ප්රවේශ ගණන්" + }, + "createSend": { + "message": "නව යවන්න නිර්මාණය", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "නව මුරපදය" + }, + "sendDisabled": { + "message": "ආබාධිත යවන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "ව්යවසාය ප්රතිපත්තියක් නිසා, ඔබට දැනට පවතින Send මකා දැමිය හැකිය.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "නිර්මාණය යවන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "සංස්කරණය යවන්න", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "ගොනුවක් තෝරා ගැනීම සඳහා, පැති තීරුවේ දිගුව විවෘත කරන්න (හැකි නම්) හෝ මෙම බැනරය ක්ලික් කිරීමෙන් නව කවුළුවකට පොප් කරන්න." + }, + "sendFirefoxFileWarning": { + "message": "ෆයර්ෆොක්ස් භාවිතයෙන් ගොනුවක් තෝරා ගැනීම සඳහා, පැති තීරුවේ දිගුව විවෘත කරන්න හෝ මෙම බැනරය ක්ලික් කිරීමෙන් නව කවුළුවකට පොප් කරන්න." + }, + "sendSafariFileWarning": { + "message": "සෆාරි භාවිතා ගොනුවක් තෝරා ගැනීම සඳහා, මෙම බැනරය ක්ලික් කිරීමෙන් නව කවුළුවකට දිස්වේ." + }, + "sendFileCalloutHeader": { + "message": "ඔබ ආරම්භ කිරීමට පෙර" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "දින දර්ශනය ශෛලිය දිනය ජීව අත්බෝම්බයක් සමග භාවිතා කිරීමට", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "මෙහි ක්ලික් කරන්න", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "ඔබේ කවුළුව දිස්වේ.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "ලබා දී ඇති කල් ඉකුත්වන දිනය වලංගු නොවේ." + }, + "deletionDateIsInvalid": { + "message": "ලබා දී ඇති මකාදැමීමේ දිනය වලංගු නොවේ." + }, + "expirationDateAndTimeRequired": { + "message": "කල් ඉකුත්වන දිනය සහ වේලාව අවශ්ය වේ." + }, + "deletionDateAndTimeRequired": { + "message": "මකාදැමීමේ දිනය සහ වේලාව අවශ්ය වේ." + }, + "dateParsingError": { + "message": "ඔබගේ මකාදැමීම සහ කල් ඉකුත් වීමේ දිනයන් ඉතිරි කිරීමේ දෝෂයක් තිබුණි." + }, + "hideEmail": { + "message": "ලබන්නන්ගෙන් මගේ විද්යුත් තැපැල් ලිපිනය සඟවන්න." + }, + "sendOptionsPolicyInEffect": { + "message": "සංවිධාන ප්රතිපත්ති එකක් හෝ කිහිපයක් ඔබගේ Send විකල්පයන්ට බලපායි." + }, + "passwordPrompt": { + "message": "ප්රධාන මුරපදය නැවත විමසුමක්" + }, + "passwordConfirmation": { + "message": "ප්රධාන මුරපදය තහවුරු" + }, + "passwordConfirmationDesc": { + "message": "මෙම ක්රියාව ආරක්ෂා කර ඇත. දිගටම කරගෙන යාම සඳහා, කරුණාකර ඔබේ අනන්යතාවය තහවුරු කර ගැනීම සඳහා ඔබේ ප්රධාන මුරපදය නැවත ඇතුළත් කරන්න." + }, + "emailVerificationRequired": { + "message": "ඊමේල් සත්යාපනය අවශ්ය වේ" + }, + "emailVerificationRequiredDesc": { + "message": "මෙම අංගය භාවිතා කිරීම සඳහා ඔබේ විද්යුත් තැපෑල සත්යාපනය කළ යුතුය. වෙබ් සුරක්ෂිතාගාරයේ ඔබගේ විද්යුත් තැපෑල සත්යාපනය කළ හැකිය." + }, + "updatedMasterPassword": { + "message": "යාවත්කාලීන කරන ලද මාස්ටර් මුරපදය" + }, + "updateMasterPassword": { + "message": "මාස්ටර් මුරපදය යාවත්කාලීන" + }, + "updateMasterPasswordWarning": { + "message": "ඔබේ ප්රධාන මුරපදය මෑතකදී ඔබේ සංවිධානයේ පරිපාලක විසින් වෙනස් කරන ලදී. සුරක්ෂිතාගාරය වෙත ප්රවේශ වීම සඳහා, ඔබ දැන් එය යාවත්කාලීන කළ යුතුය. ඔබගේ වර්තමාන සැසියෙන් ඔබව ප්රවිෂ්ට වනු ඇත, ඔබ නැවත ප්රවිෂ්ට වීමට අවශ්ය. වෙනත් උපාංගවල ක්රියාකාරී සැසි පැයක් දක්වා ක්රියාකාරීව පැවතිය හැකිය." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "ස්වයංක්රීය බඳවා ගැනීම" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "මෙම සංවිධානයට ව්යවසාය ප්රතිපත්තියක් ඇති අතර එමඟින් මුරපදය නැවත සකස් කිරීමේදී ඔබව ස්වයංක්රීයව ඇතුළත් වේ. බඳවා ගැනීම සංවිධාන පරිපාලකයින්ට ඔබේ ප්රධාන මුරපදය වෙනස් කිරීමට ඉඩ සලසයි." + }, + "selectFolder": { + "message": "ෆෝල්ඩරය තෝරන්න..." + }, + "ssoCompleteRegistration": { + "message": "SSG සමග ලොග් වීම සම්පූර්ණ කිරීම සඳහා, කරුණාකර ඔබේ සුරක්ෂිතාගාරය වෙත ප්රවේශ වීමට සහ ආරක්ෂා කිරීමට ප්රධාන මුරපදයක් සකසන්න." + }, + "hours": { + "message": "පැය" + }, + "minutes": { + "message": "විනාඩි" + }, + "vaultTimeoutPolicyInEffect": { + "message": "ඔබේ සංවිධාන ප්රතිපත්ති ඔබගේ සුරක්ෂිතාගාරය කාලය කෙරෙහි බලපායි. උපරිම අවසර ලත් සුරක්ෂිතාගාරය කාලය පැය $HOURS$ (ය) සහ විනාඩි $MINUTES$ (ය)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "ඔබේ සුරක්ෂිතාගාරය කාලය ඔබේ සංවිධානය විසින් නියම කර ඇති සීමාවන් ඉක්මවා යයි." + }, + "vaultExportDisabled": { + "message": "ආබාධිත අපනයන සුරක්ෂිතාගාරය" + }, + "personalVaultExportPolicyInEffect": { + "message": "සංවිධාන ප්රතිපත්ති එකක් හෝ කිහිපයක් ඔබේ පුද්ගලික සුරක්ෂිතාගාරය අපනයනය කිරීමෙන් වළක්වයි." + }, + "copyCustomFieldNameInvalidElement": { + "message": "වලංගු ආකෘති මූලද්රව්යයක් හඳුනා ගැනීමට නොහැකි විය. ඒ වෙනුවට HTML පරීක්ෂා කිරීමට උත්සාහ කරන්න." + }, + "copyCustomFieldNameNotUnique": { + "message": "අද්විතීය හඳුනාගැනීමක් සොයාගත නොහැකි විය." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ ස්වයං සත්කාරක යතුරු සේවාදායකයක් සමඟ SSO භාවිතා කරයි. මෙම සංවිධානයේ සාමාජිකයන් සඳහා ප්රවිෂ්ට වීමට ප්රධාන මුරපදයක් තවදුරටත් අවශ්ය නොවේ.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "සංවිධානය හැරයන්න" + }, + "removeMasterPassword": { + "message": "ප්රධාන මුරපදය ඉවත් කරන්න" + }, + "removedMasterPassword": { + "message": "ප්රධාන මුරපදය ඉවත් කර ඇත." + }, + "leaveOrganizationConfirmation": { + "message": "ඔබට මෙම සංවිධානයෙන් ඉවත් වීමට අවශ්ය බව ඔබට විශ්වාසද?" + }, + "leftOrganization": { + "message": "ඔබ සංවිධානයෙන් ඉවත් වී ඇත." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/sk/messages.json b/apps/browser/src/_locales/sk/messages.json new file mode 100644 index 0000000000..56652cccd7 --- /dev/null +++ b/apps/browser/src/_locales/sk/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Bezplatný správca hesiel", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "bitwarden je bezpečný a bezplatný správca hesiel pre všetky vaše zariadenia.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Prihláste sa, alebo vytvorte nový účet pre prístup k vášmu bezpečnému trezoru." + }, + "createAccount": { + "message": "Vytvoriť účet" + }, + "login": { + "message": "Prihlásiť sa" + }, + "enterpriseSingleSignOn": { + "message": "Prihlásenie cez prihlasovací formulár spoločnosti (SSO)" + }, + "cancel": { + "message": "Zrušiť" + }, + "close": { + "message": "Zavrieť" + }, + "submit": { + "message": "Potvrdiť" + }, + "emailAddress": { + "message": "Emailová adresa" + }, + "masterPass": { + "message": "Hlavné heslo" + }, + "masterPassDesc": { + "message": "Hlavné heslo je heslo, ktoré použijete na prístup k svojmu trezoru. Je veľmi dôležité, aby ste svoje hlavné heslo nezabudli. Neexistuje možnosť, ako heslo obnoviť v prípade, že ho zabudnete." + }, + "masterPassHintDesc": { + "message": "Nápoveda k hlavnému heslu vám môže pomôcť spomenúť si na heslo, ak ho zabudnete." + }, + "reTypeMasterPass": { + "message": "Znovu zadajte hlavné heslo" + }, + "masterPassHint": { + "message": "Nápoveda k hlavnému heslu (voliteľné)" + }, + "tab": { + "message": "Karta" + }, + "myVault": { + "message": "Môj trezor" + }, + "tools": { + "message": "Nástroje" + }, + "settings": { + "message": "Nastavenia" + }, + "currentTab": { + "message": "Aktuálna karta" + }, + "copyPassword": { + "message": "Kopírovať heslo" + }, + "copyNote": { + "message": "Kopírovať poznámku" + }, + "copyUri": { + "message": "Kopírovať URI" + }, + "copyUsername": { + "message": "Kopírovať používateľské meno" + }, + "copyNumber": { + "message": "Kopírovať číslo" + }, + "copySecurityCode": { + "message": "Kopírovať bezpečnostný kód" + }, + "autoFill": { + "message": "Automatické vypĺňanie" + }, + "generatePasswordCopied": { + "message": "Vygenerovať heslo (skopírované)" + }, + "copyElementIdentifier": { + "message": "Kopírovať názov vlastného poľa" + }, + "noMatchingLogins": { + "message": "Žiadne zodpovedajúce prihlasovacie údaje." + }, + "unlockVaultMenu": { + "message": "Odomknúť trezor" + }, + "loginToVaultMenu": { + "message": "Prihláste sa do trezora" + }, + "autoFillInfo": { + "message": "Nie sú prístupné žiadne prihlasovacie údaje na automatické vyplnenie pre aktuálnu kartu." + }, + "addLogin": { + "message": "Pridať prihlasovacie údaje" + }, + "addItem": { + "message": "Pridať položku" + }, + "passwordHint": { + "message": "Nápoveda k heslu" + }, + "enterEmailToGetHint": { + "message": "Zadajte emailovú adresu na zaslanie nápovedy pre vaše hlavné heslo." + }, + "getMasterPasswordHint": { + "message": "Získať nápovedu k hlavnému heslu" + }, + "continue": { + "message": "Pokračovať" + }, + "sendVerificationCode": { + "message": "Poslať overovací kód na váš e-mail" + }, + "sendCode": { + "message": "Odoslať kód" + }, + "codeSent": { + "message": "Kód bol odoslaný" + }, + "verificationCode": { + "message": "Overovací kód" + }, + "confirmIdentity": { + "message": "Ak chcete pokračovať, potvrďte svoju identitu." + }, + "account": { + "message": "Účet" + }, + "changeMasterPassword": { + "message": "Zmeniť hlavné heslo" + }, + "fingerprintPhrase": { + "message": "Fráza odtlačku", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fráza odtlačku vášho účtu", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Dvojstupňové prihlásenie" + }, + "logOut": { + "message": "Odhlásiť sa" + }, + "about": { + "message": "O aplikácii" + }, + "version": { + "message": "Verzia" + }, + "save": { + "message": "Uložiť" + }, + "move": { + "message": "Presunúť" + }, + "addFolder": { + "message": "Pridať priečinok" + }, + "name": { + "message": "Meno" + }, + "editFolder": { + "message": "Upraviť priečinok" + }, + "deleteFolder": { + "message": "Odstrániť priečinok" + }, + "folders": { + "message": "Priečinky" + }, + "noFolders": { + "message": "V zozname sa nenachádzajú žiadne priečinky." + }, + "helpFeedback": { + "message": "Pomoc a spätná väzba" + }, + "sync": { + "message": "Synchronizácia" + }, + "syncVaultNow": { + "message": "Synchronizovať trezor teraz" + }, + "lastSync": { + "message": "Posledná synchronizácia:" + }, + "passGen": { + "message": "Generátor hesla" + }, + "generator": { + "message": "Generátor", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automaticky generovať silné a unikátne heslá k prihlasovacím údajom." + }, + "bitWebVault": { + "message": "Webový trezor Bitwarden" + }, + "importItems": { + "message": "Importovať položky" + }, + "select": { + "message": "Vybrať" + }, + "generatePassword": { + "message": "Generovať heslo" + }, + "regeneratePassword": { + "message": "Vygenerovať nové heslo" + }, + "options": { + "message": "Možnosti" + }, + "length": { + "message": "Dĺžka" + }, + "uppercase": { + "message": "Veľké písmená (A-Z)" + }, + "lowercase": { + "message": "Malé písmená (a-z)" + }, + "numbers": { + "message": "Čísla (0-9)" + }, + "specialCharacters": { + "message": "Špeciálne znaky (!@#$%^&*)" + }, + "numWords": { + "message": "Počet slov" + }, + "wordSeparator": { + "message": "Oddeľovač slov" + }, + "capitalize": { + "message": "Prvé písmeno veľkým", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Zahrnúť číslo" + }, + "minNumbers": { + "message": "Minimum číslic" + }, + "minSpecial": { + "message": "Minimum špec. znakov" + }, + "avoidAmbChar": { + "message": "Vyhnúť sa zameniteľným znakom" + }, + "searchVault": { + "message": "Prehľadávať trezor" + }, + "edit": { + "message": "Upraviť" + }, + "view": { + "message": "Zobraziť" + }, + "noItemsInList": { + "message": "Neexistujú žiadne položky na zobrazenie." + }, + "itemInformation": { + "message": "Informácie o položke" + }, + "username": { + "message": "Používateľské meno" + }, + "password": { + "message": "Heslo" + }, + "passphrase": { + "message": "Prístupová fráza" + }, + "favorite": { + "message": "Obľúbené" + }, + "notes": { + "message": "Poznámky" + }, + "note": { + "message": "Poznámka" + }, + "editItem": { + "message": "Upraviť položku" + }, + "folder": { + "message": "Priečinok" + }, + "deleteItem": { + "message": "Zmazať položku" + }, + "viewItem": { + "message": "Zobraziť položku" + }, + "launch": { + "message": "Spustiť" + }, + "website": { + "message": "Webstránka" + }, + "toggleVisibility": { + "message": "Prepnúť viditeľnosť" + }, + "manage": { + "message": "Spravovať" + }, + "other": { + "message": "Ostatné" + }, + "rateExtension": { + "message": "Ohodnotiť rozšírenie" + }, + "rateExtensionDesc": { + "message": "Prosíme, zvážte napísanie pozitívnej recenzie!" + }, + "browserNotSupportClipboard": { + "message": "Váš webový prehliadač nepodporuje automatické kopírovanie do schránky. Kopírujte manuálne." + }, + "verifyIdentity": { + "message": "Overiť identitu" + }, + "yourVaultIsLocked": { + "message": "Váš trezor je uzamknutý. Ak chcete pokračovať, overte svoju identitu." + }, + "unlock": { + "message": "Odomknúť" + }, + "loggedInAsOn": { + "message": "Prihlásený ako $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Neplatné hlavné heslo" + }, + "vaultTimeout": { + "message": "Časový limit pre trezor vypršal" + }, + "lockNow": { + "message": "Uzamknúť teraz" + }, + "immediately": { + "message": "Okamžite" + }, + "tenSeconds": { + "message": "10 sekúnd" + }, + "twentySeconds": { + "message": "20 sekúnd" + }, + "thirtySeconds": { + "message": "30 sekúnd" + }, + "oneMinute": { + "message": "1 minúta" + }, + "twoMinutes": { + "message": "2 minúty" + }, + "fiveMinutes": { + "message": "5 minút" + }, + "fifteenMinutes": { + "message": "15 minút" + }, + "thirtyMinutes": { + "message": "30 minút" + }, + "oneHour": { + "message": "1 hodina" + }, + "fourHours": { + "message": "4 hodiny" + }, + "onLocked": { + "message": "Pri uzamknutí" + }, + "onRestart": { + "message": "Po reštarte" + }, + "never": { + "message": "Nikdy" + }, + "security": { + "message": "Zabezpečenie" + }, + "errorOccurred": { + "message": "Vyskytla sa chyba" + }, + "emailRequired": { + "message": "Emailová adresa je povinná." + }, + "invalidEmail": { + "message": "Neplatná emailová adresa." + }, + "masterPassRequired": { + "message": "Hlavné heslo je povinné." + }, + "masterPassLength": { + "message": "Hlavné heslo musí obsahovať aspoň 8 znakov." + }, + "masterPassDoesntMatch": { + "message": "Potvrdenie hlavného hesla sa nezhoduje." + }, + "newAccountCreated": { + "message": "Váš nový účet bol vytvorený! Teraz sa môžete prihlásiť." + }, + "masterPassSent": { + "message": "Poslali sme vám email s nápovedou k hlavnému heslu." + }, + "verificationCodeRequired": { + "message": "Overovací kód je povinný." + }, + "invalidVerificationCode": { + "message": "Neplatný verifikačný kód" + }, + "valueCopied": { + "message": " skopírované", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Na tejto stránke sa nedajú automaticky vyplniť prihlasovacie údaje. Namiesto toho skopírujte/vložte prihlasovacie údaje manuálne." + }, + "loggedOut": { + "message": "Odhlásený" + }, + "loginExpired": { + "message": "Vaša relácia vypršala." + }, + "logOutConfirmation": { + "message": "Naozaj sa chcete odhlásiť?" + }, + "yes": { + "message": "Áno" + }, + "no": { + "message": "Nie" + }, + "unexpectedError": { + "message": "Vyskytla sa neočakávaná chyba." + }, + "nameRequired": { + "message": "Meno je povinné." + }, + "addedFolder": { + "message": "Pridaný priečinok" + }, + "changeMasterPass": { + "message": "Zmeniť hlavné heslo" + }, + "changeMasterPasswordConfirmation": { + "message": "Teraz si môžete zmeniť svoje hlavné heslo vo webovom trezore bitwarden.com. Chcete navštíviť túto stránku teraz?" + }, + "twoStepLoginConfirmation": { + "message": "Dvojstupňové prihlasovanie robí váš účet bezpečnejším vďaka vyžadovaniu bezpečnostného kódu z overovacej aplikácie vždy, keď sa prihlásite. Dvojstupňové prihlasovanie môžete povoliť vo webovom trezore bitwarden.com. Chcete navštíviť túto stránku teraz?" + }, + "editedFolder": { + "message": "Priečinok upravený" + }, + "deleteFolderConfirmation": { + "message": "Naozaj chcete odstrániť tento priečinok?" + }, + "deletedFolder": { + "message": "Odstránený priečinok" + }, + "gettingStartedTutorial": { + "message": "Začiatočnícka príručka" + }, + "gettingStartedTutorialVideo": { + "message": "Sledujte našu začiatočnícku príručku, aby ste sa naučili, ako získať maximum z nášho rozšírenia prehliadača." + }, + "syncingComplete": { + "message": "Synchronizácia kompletná" + }, + "syncingFailed": { + "message": "Synchronizácia zlyhala" + }, + "passwordCopied": { + "message": "Heslo skopírované" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nové URI" + }, + "addedItem": { + "message": "Položka pridaná" + }, + "editedItem": { + "message": "Položka upravená" + }, + "deleteItemConfirmation": { + "message": "Naozaj chcete odstrániť túto položku?" + }, + "deletedItem": { + "message": "Položka odstránená do koša" + }, + "overwritePassword": { + "message": "Prepísať heslo" + }, + "overwritePasswordConfirmation": { + "message": "Naozaj chcete prepísať aktuálne heslo?" + }, + "overwriteUsername": { + "message": "Prepísať používateľské meno" + }, + "overwriteUsernameConfirmation": { + "message": "Naozaj chcete prepísať aktuálne používateľské meno?" + }, + "searchFolder": { + "message": "Prehľadávať priečinok" + }, + "searchCollection": { + "message": "Vyhľadať zbierku" + }, + "searchType": { + "message": "Typ vyhľadávania" + }, + "noneFolder": { + "message": "Žiadny priečinok", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Vypnúť notifikáciu Pridať prihlasovacie údaje" + }, + "addLoginNotificationDesc": { + "message": "\"Notifikácia Pridať prihlasovacie údaje\" vás automaticky upozorní na uloženie nových údajov do vášho trezoru vždy, keď sa s nimi prihlasujete poprvýkrát." + }, + "dontShowCardsCurrentTab": { + "message": "Nezobrazovať platobné karty na stránke \"Aktuálna karta\"" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Položky kariet sa zobrazujú na stránke „Aktuálna karta“ pre ľahšie automatické vypĺňanie." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Nezobrazovať identity na stránke Karta" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity z vášho trezoru sa zobrazujú na stránke \"Aktuálna karta\" pre ľahké automatické vypĺňanie." + }, + "clearClipboard": { + "message": "Vymazať schránku", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automaticky vymazať skopírované hodnoty zo schránky.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Má si pre vás Bitwarden zapamätať toto heslo?" + }, + "notificationAddSave": { + "message": "Uložiť" + }, + "disableChangedPasswordNotification": { + "message": "Vypnúť oznámenie o zmene hesla" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Oznámenie o zmene hesla sa vás automaticky opýta na aktualizáciu prihlasovacích údajov vo vašom trezore vždy, keď zistí, že ste ho zmenili na stránke." + }, + "notificationChangeDesc": { + "message": "Chcete aktualizovať toto heslo v Bitwarden?" + }, + "notificationChangeSave": { + "message": "Aktualizovať" + }, + "disableContextMenuItem": { + "message": "Vypnúť možnosti kontextového menu" + }, + "disableContextMenuItemDesc": { + "message": "Možnosti kontextového menu ponúkajú rýchly prístup k prihlasovacím údajom a generovaniu hesiel pre stránku vo vašej aktuálnej karte." + }, + "defaultUriMatchDetection": { + "message": "Predvolené mapovanie", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Vyberte si predvolený spôsob mapovania, ktorý bude použitý pre prihlasovacie údaje pri využití funkcí ako je napríklad automatické vypĺňanie hesiel." + }, + "theme": { + "message": "Motív" + }, + "themeDesc": { + "message": "Zmeniť motív aplikácie." + }, + "dark": { + "message": "Tmavý", + "description": "Dark color" + }, + "light": { + "message": "Svetlý", + "description": "Light color" + }, + "solarizedDark": { + "message": "Tmavá –⁠ Solarized", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export trezoru" + }, + "fileFormat": { + "message": "Formát Súboru" + }, + "warning": { + "message": "UPOZORNENIE", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potvrdiť export trezoru" + }, + "exportWarningDesc": { + "message": "Tento export obsahuje vaše dáta v nešifrovanom formáte. Nemali by ste ich ukladať, ani posielať cez nezabezpečené kanály (napr. email). Okamžite ho odstráňte, keď ho prestanete používať." + }, + "encExportKeyWarningDesc": { + "message": "Tento export zašifruje vaše údaje pomocou šifrovacieho kľúča vášho účtu. Ak niekedy budete rotovať šifrovací kľúč svojho účtu, mali by ste exportovať znova, pretože nebudete môcť dešifrovať tento exportovaný súbor." + }, + "encExportAccountWarningDesc": { + "message": "Šifrovacie kľúče účtu sú jedinečné pre každý používateľský účet Bitwarden, takže nemôžete importovať šifrovaný export do iného účtu." + }, + "exportMasterPassword": { + "message": "Zadajte vaše hlavné heslo pre export údajov trezoru." + }, + "shared": { + "message": "Zdieľané" + }, + "learnOrg": { + "message": "Zistiť viac o organizáciách" + }, + "learnOrgConfirmation": { + "message": "Bitwarden vám umožňuje zdieľať vaše položky trezora s ostatnými pomocou organizácie. Chcete navštíviť webovú stránku bitwarden.com a dozvedieť sa viac?" + }, + "moveToOrganization": { + "message": "Presunúť do organizácie" + }, + "share": { + "message": "Zdieľať" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ presunuté do $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vyberte organizáciu, do ktorej chcete presunúť túto položku. Presunom do organizácie sa vlastníctvo položky prenáša na túto organizáciu. Po presunutí už nebudete priamym vlastníkom danej položky." + }, + "learnMore": { + "message": "Zistiť viac" + }, + "authenticatorKeyTotp": { + "message": "Kľúč overovateľa (TOTP)" + }, + "verificationCodeTotp": { + "message": "Overovací kód (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopírovať overovací kód" + }, + "attachments": { + "message": "Prílohy" + }, + "deleteAttachment": { + "message": "Odstrániť prílohu" + }, + "deleteAttachmentConfirmation": { + "message": "Naozaj chcete odstrániť túto prílohu?" + }, + "deletedAttachment": { + "message": "Odstránená príloha" + }, + "newAttachment": { + "message": "Pridať novú prílohu" + }, + "noAttachments": { + "message": "Žiadne prílohy." + }, + "attachmentSaved": { + "message": "Príloha bola uložená." + }, + "file": { + "message": "Súbor" + }, + "selectFile": { + "message": "Vybrať súbor." + }, + "maxFileSize": { + "message": "Maximálna veľkosť súboru je 500 MB." + }, + "featureUnavailable": { + "message": "Funkcia nie je k dispozícii" + }, + "updateKey": { + "message": "Túto funkciu nemožno použiť, pokým neaktualizujete svoj šifrovací kľúč." + }, + "premiumMembership": { + "message": "Prémiové členstvo" + }, + "premiumManage": { + "message": "Spravovať členstvo" + }, + "premiumManageAlert": { + "message": "Svoje členstvo môžete spravovať vo webovom trezore bitwarden.com. Chcete navštíviť túto stránku teraz?" + }, + "premiumRefresh": { + "message": "Obnoviť členstvo" + }, + "premiumNotCurrentMember": { + "message": "Momentálne nie ste prémiovým členom." + }, + "premiumSignUpAndGet": { + "message": "Zaregistrujte sa pre prémiové členstvo a získajte:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB šifrovaného úložiska." + }, + "ppremiumSignUpTwoStep": { + "message": "Ďalšie možnosti dvojstupňového prihlásenia ako YubiKey, FIDO U2F a Duo." + }, + "ppremiumSignUpReports": { + "message": "Správy o sile hesla, zabezpečení účtov a únikoch dát ktoré vám pomôžu udržať vaše kontá v bezpečí." + }, + "ppremiumSignUpTotp": { + "message": "Generátor TOTP verifikačného kódu (2FA) pre prihlásenie do vášho trezora." + }, + "ppremiumSignUpSupport": { + "message": "Prioritná zákaznícka podpora." + }, + "ppremiumSignUpFuture": { + "message": "Všetky budúce prémiové funkcie. Viac už čoskoro!" + }, + "premiumPurchase": { + "message": "Zakúpiť Prémiový účet" + }, + "premiumPurchaseAlert": { + "message": "Svoje prémiové členstvo môžete zakúpiť vo webovom trezore bitwarden.com. Chcete navštíviť túto stránku teraz?" + }, + "premiumCurrentMember": { + "message": "Ste prémiovým členom!" + }, + "premiumCurrentMemberThanks": { + "message": "Ďakujeme, že podporujete Bitwarden." + }, + "premiumPrice": { + "message": "Všetko len za %price% /rok!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Obnova kompletná" + }, + "disableAutoTotpCopy": { + "message": "Vypnúť automatické kopírovanie TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Ak je kľúč overovateľa spojený s vašim prihlásením, TOTP verifikačný kód bude automaticky skopírovaný do schránky vždy, keď použijete automatické vypĺňanie." + }, + "disableAutoBiometricsPrompt": { + "message": "Pri spustení nevyžadovať biometrické údaje" + }, + "premiumRequired": { + "message": "Vyžaduje prémiový účet" + }, + "premiumRequiredDesc": { + "message": "Pre použitie tejto funkcie je potrebné prémiové členstvo." + }, + "enterVerificationCodeApp": { + "message": "Zadajte 6-miestny verifikačný kód z vašej overovacej aplikácie." + }, + "enterVerificationCodeEmail": { + "message": "Zadajte 6-miestny verifikačný kód, ktorý vám bol zaslaný emailom", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Overovací e-mail odoslaný na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamätať si ma" + }, + "sendVerificationCodeEmailAgain": { + "message": "Znovu zaslať overovací kód emailom" + }, + "useAnotherTwoStepMethod": { + "message": "Použiť inú dvojstupňovú metódu prihlásenia" + }, + "insertYubiKey": { + "message": "Vložte váš YubiKey do USB portu počítača a stlačte jeho tlačidlo." + }, + "insertU2f": { + "message": "Vložte váš bezpečnostný kľúč do USB portu počítača. Ak má tlačidlo, stlačte ho." + }, + "webAuthnNewTab": { + "message": "V overovaní cez WebAuthn 2FA pokračujte na ďalšej záložke." + }, + "webAuthnNewTabOpen": { + "message": "Otvoriť v novej karte" + }, + "webAuthnAuthenticate": { + "message": "Overiť cez WebAuthn" + }, + "loginUnavailable": { + "message": "Prihlasovací údaj nedostupný" + }, + "noTwoStepProviders": { + "message": "Tento účet má povolené dvojstupňové prihlásenie, ale žiadny z nakonfigurovaných poskytovateľov nie je podporovaný týmto prehliadačom." + }, + "noTwoStepProviders2": { + "message": "Prosím, použite podporovaný prehliadač (napríklad Chrome) a/alebo pridajte iných poskytovateľov, ktorí sú lepšie podporovaní prehliadačmi (ako napríklad overovacia aplikácia)." + }, + "twoStepOptions": { + "message": "Možnosti dvojstupňového prihlásenia" + }, + "recoveryCodeDesc": { + "message": "Stratili ste prístup ku všetkým vašim dvojstupňovým poskytovateľom? Použite váš záchranný kód pre vypnutie všetkých poskytovateľov vo vašom účte." + }, + "recoveryCodeTitle": { + "message": "Záchranný kód" + }, + "authenticatorAppTitle": { + "message": "Overovacia aplikácia" + }, + "authenticatorAppDesc": { + "message": "Použite overovaciu aplikáciu (napríklad Authy alebo Google Authenticator) na generovanie časovo obmedzených overovacích kódov.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP bezpečnostný kľúč" + }, + "yubiKeyDesc": { + "message": "Použiť YubiKey pre prístup k vášmu účtu. Pracuje s YubiKey 4, 4 Nano, 4C a s NEO zariadeniami." + }, + "duoDesc": { + "message": "Overiť s Duo Security použitím Duo Mobile aplikácie, SMS, telefonátu alebo U2F bezpečnostným kľúčom.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Overiť s Duo Security vašej organizácie použitím Duo Mobile aplikácie, SMS, telefonátu alebo U2F bezpečnostným kľúčom.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Použiť akýkoľvek WebAuthn bezpečnostný kľúč pre prístup k vášmu účtu." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verifikačné kódy vám budú zaslané emailom." + }, + "selfHostedEnvironment": { + "message": "Sebou hosťované prostredie" + }, + "selfHostedEnvironmentFooter": { + "message": "Zadajte základnú URL adresu lokálne hosťovanej inštalácie Bitwarden." + }, + "customEnvironment": { + "message": "Vlastné prostredie" + }, + "customEnvironmentFooter": { + "message": "Pre pokročilých používateľov. Môžete špecifikovať základnú URL pre každú službu nezávisle." + }, + "baseUrl": { + "message": "URL servera" + }, + "apiUrl": { + "message": "URL API servera" + }, + "webVaultUrl": { + "message": "URL servera webového trezora" + }, + "identityUrl": { + "message": "URL servera identít" + }, + "notificationsUrl": { + "message": "URL adresa servera pre oznámenia" + }, + "iconsUrl": { + "message": "URL servera ikôn" + }, + "environmentSaved": { + "message": "URL prostredia boli uložené." + }, + "enableAutoFillOnPageLoad": { + "message": "Povoliť automatické vypĺňanie pri načítaní stránky" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Ak je prihlasovací formulár detegovaný, automaticky vykonať vypĺňanie pri načítaní stránky." + }, + "experimentalFeature": { + "message": "Toto je zatiaľ experimentálna funkcia. Použite na vlastné riziko." + }, + "defaultAutoFillOnPageLoad": { + "message": "Predvolené nastavenie automatického vypĺňania pre prihlasovacie položky" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Po zapnutí funkcie Automatické vypĺňanie pri načítaní stránky môžete túto funkciu zapnúť alebo vypnúť pre jednotlivé položky prihlásenia. Toto je predvolené nastavenie pre prihlasovacie položky, ktoré nie sú samostatne nakonfigurované." + }, + "itemAutoFillOnPageLoad": { + "message": "Automatické vypĺňanie pri načítaní stránky (ak je povolené v možnostiach)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Pôvodné nastavenia" + }, + "autoFillOnPageLoadYes": { + "message": "Automatické vypĺňanie pri načítaní stránky" + }, + "autoFillOnPageLoadNo": { + "message": "Nevypĺňať automaticky pri načítaní stránky" + }, + "commandOpenPopup": { + "message": "Otvoriť vyskakovacie okno trezora" + }, + "commandOpenSidebar": { + "message": "Otvoriť trezor v bočnom paneli" + }, + "commandAutofillDesc": { + "message": "Automaticky vyplniť naposledy použité prihlasovacie údaje pre túto stránku" + }, + "commandGeneratePasswordDesc": { + "message": "Vygenerovať a skopírovať nové náhodné heslo do schránky" + }, + "commandLockVaultDesc": { + "message": "Zamknúť trezor" + }, + "privateModeWarning": { + "message": "Podpora privátneho režimu je experimentálna a niektoré funkcie sú obmedzené." + }, + "customFields": { + "message": "Vlastné polia" + }, + "copyValue": { + "message": "Kopírovať hodnotu" + }, + "value": { + "message": "Hodnota" + }, + "newCustomField": { + "message": "Nové vlastné pole" + }, + "dragToSort": { + "message": "Zoradiť presúvaním" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Skryté" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Prepojené", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Prepojená hodnota", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Kliknutie mimo popup okna na prezretie vášho emailu pre overovací kód spôsobí zavretie tohto popupu. Chcete otvoriť tento popup v novom okne tak, aby sa nezavrel?" + }, + "popupU2fCloseMessage": { + "message": "Tento prehliadač nedokáže spracovať U2F požiadavku v popup okne. Chcete ho otvoriť v novom okne aby ste sa mohli prihlásiť pomocou U2F?" + }, + "disableFavicon": { + "message": "Nezobrazovať ikony stránok" + }, + "disableFaviconDesc": { + "message": "Ikony stránok poskytujú rozoznateľný obrázok vedľa každého prihlasovacieho údaju vo webovom trezore." + }, + "disableBadgeCounter": { + "message": "Zakázať počítadlo na ikone" + }, + "disableBadgeCounterDesc": { + "message": "Zakáže počítadlo na ikone, ktoré zobrazuje počet prihlasovacích údajov v trezore pre aktuálnu stránku." + }, + "cardholderName": { + "message": "Meno vlastníka karty" + }, + "number": { + "message": "Číslo" + }, + "brand": { + "message": "Značka" + }, + "expirationMonth": { + "message": "Mesiac expirácie" + }, + "expirationYear": { + "message": "Rok expirácie" + }, + "expiration": { + "message": "Expirácia" + }, + "january": { + "message": "Január" + }, + "february": { + "message": "Február" + }, + "march": { + "message": "Marec" + }, + "april": { + "message": "Apríl" + }, + "may": { + "message": "Máj" + }, + "june": { + "message": "Jún" + }, + "july": { + "message": "Júl" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Október" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Bezpečnostný kód" + }, + "ex": { + "message": "napr." + }, + "title": { + "message": "Oslovenie" + }, + "mr": { + "message": "Pán" + }, + "mrs": { + "message": "Pani" + }, + "ms": { + "message": "Slečna" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Krstné meno" + }, + "middleName": { + "message": "Druhé meno" + }, + "lastName": { + "message": "Priezvisko" + }, + "fullName": { + "message": "Celé meno" + }, + "identityName": { + "message": "Názov identity" + }, + "company": { + "message": "Spoločnosť" + }, + "ssn": { + "message": "Číslo poistenca sociálnej poisťovne" + }, + "passportNumber": { + "message": "Číslo pasu" + }, + "licenseNumber": { + "message": "Číslo vodičského preukazu" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telefón" + }, + "address": { + "message": "Adresa" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Mesto" + }, + "stateProvince": { + "message": "Región" + }, + "zipPostalCode": { + "message": "PSČ" + }, + "country": { + "message": "Krajina" + }, + "type": { + "message": "Typ" + }, + "typeLogin": { + "message": "Prihlásenie" + }, + "typeLogins": { + "message": "Prihlasovacie údaje" + }, + "typeSecureNote": { + "message": "Zabezpečená poznámka" + }, + "typeCard": { + "message": "Karta" + }, + "typeIdentity": { + "message": "Identita" + }, + "passwordHistory": { + "message": "História hesla" + }, + "back": { + "message": "Späť" + }, + "collections": { + "message": "Zbierky" + }, + "favorites": { + "message": "Obľúbené" + }, + "popOutNewWindow": { + "message": "Otvoriť v novom okne" + }, + "refresh": { + "message": "Obnoviť" + }, + "cards": { + "message": "Karty" + }, + "identities": { + "message": "Identity" + }, + "logins": { + "message": "Prihlasovacie údaje" + }, + "secureNotes": { + "message": "Zabezpečené poznámky" + }, + "clear": { + "message": "Vyčistiť", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Overiť či došlo k úniku hesla." + }, + "passwordExposed": { + "message": "Toto heslo uniklo $VALUE$ krát. Mali by ste ho zmeniť.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Heslo nebolo nájdene v žiadnom úniku dát. Malo by byť bezpečné." + }, + "baseDomain": { + "message": "Základná doména", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Názov domény", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Hostiteľ", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Presný" + }, + "startsWith": { + "message": "Začína na" + }, + "regEx": { + "message": "Regulárny výraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Spôsob mapovania", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Predvolené mapovanie", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Voľby prepínača" + }, + "toggleCurrentUris": { + "message": "Prepnúť zobrazovanie aktuálnej URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Aktuálna URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organizácia", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Typy" + }, + "allItems": { + "message": "Všetky položky" + }, + "noPasswordsInList": { + "message": "Neboli nájdené žiadne heslá." + }, + "remove": { + "message": "Odstrániť" + }, + "default": { + "message": "Predvolené" + }, + "dateUpdated": { + "message": "Aktualizované", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Heslo bolo aktualizované", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Ste si istí, že chcete použiť možnosť \"Nikdy\"? Táto predvoľba ukladá šifrovací kľúč od trezora priamo na zariadení. Ak použijete túto možnosť, mali by ste svoje zariadenie náležite zabezpečiť." + }, + "noOrganizationsList": { + "message": "Nie ste členom žiadnej organizácie. Organizácie umožňujú bezpečne zdieľať položky s ostatnými používateľmi." + }, + "noCollectionsInList": { + "message": "Neexistujú žiadne zbierky na zobrazenie." + }, + "ownership": { + "message": "Vlastníctvo" + }, + "whoOwnsThisItem": { + "message": "Kto vlastní túto položku?" + }, + "strong": { + "message": "Silné", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobré", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slabé", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slabé hlavné heslo" + }, + "weakMasterPasswordDesc": { + "message": "Hlavné heslo, ktoré ste zadali, je slabé. Mali by ste použiť silné heslo (alebo frázu), aby ste spoľahlivo ochránili váš Bitwarden účet. Naozaj chcete použiť toto heslo?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Odomknúť s PIN" + }, + "setYourPinCode": { + "message": "Nastaviť kód PIN na odomykanie Bitwardenu. Nastavenie PIN sa vynuluje, ak sa úplne odhlásite z aplikácie." + }, + "pinRequired": { + "message": "Kód PIN je povinný." + }, + "invalidPin": { + "message": "Neplatný PIN kód." + }, + "unlockWithBiometrics": { + "message": "Odomknúť pomocou biometrie" + }, + "awaitDesktop": { + "message": "Čaká sa na potvrdenie z desktopu" + }, + "awaitDesktopDesc": { + "message": "Ak chcete povoliť biometriu pre prehliadač, potvrďte použitie biometrie v aplikácii Bitwarden Desktop." + }, + "lockWithMasterPassOnRestart": { + "message": "Pri reštarte prehliadača zamknúť s hlavným heslom" + }, + "selectOneCollection": { + "message": "Musíte vybrať aspoň jednu zbierku." + }, + "cloneItem": { + "message": "Klonovať položku" + }, + "clone": { + "message": "Klonovať" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Jedno alebo viac nastavení organizácie ovplyvňujú vaše nastavenia generátora." + }, + "vaultTimeoutAction": { + "message": "Akcia pri vypršaní času pre trezor" + }, + "lock": { + "message": "Uzamknúť", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Kôš", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Hľadať v koši" + }, + "permanentlyDeleteItem": { + "message": "Natrvalo odstrániť položku" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Naozaj chcete narvalo odstrániť túto položku?" + }, + "permanentlyDeletedItem": { + "message": "Natrvalo odstrániť položku" + }, + "restoreItem": { + "message": "Obnoviť položku" + }, + "restoreItemConfirmation": { + "message": "Naozaj chcete obnoviť túto položku?" + }, + "restoredItem": { + "message": "Obnovená položka" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Odhlásenie bude vyžadovať online prihlásenie po vypršaní časového limitu. Naozaj chcete použiť toto nastavenie?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potvrdenie akcie pre vypršaný časový limit" + }, + "autoFillAndSave": { + "message": "Auto-vyplniť a Uložiť" + }, + "autoFillSuccessAndSavedUri": { + "message": "Automatické vypĺnenie a uloženie úspešné" + }, + "autoFillSuccess": { + "message": "Automaticky vyplnené" + }, + "setMasterPassword": { + "message": "Nastaviť hlavné heslo" + }, + "masterPasswordPolicyInEffect": { + "message": "Jedno alebo viac pravidiel organizácie požadujú aby vaše hlavné heslo spĺňalo nasledujúce požiadavky:" + }, + "policyInEffectMinComplexity": { + "message": "Minimálna úroveň zložitosti $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimálna dĺžka $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Obsahuje aspoň jedno veľké písmeno" + }, + "policyInEffectLowercase": { + "message": "Obsahuje aspoň jedno malé písmeno" + }, + "policyInEffectNumbers": { + "message": "Obsahuje aspoň jednu číslicu" + }, + "policyInEffectSpecial": { + "message": "Obsahuje aspoň jeden z následujúcich špeciálnych znakov $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Vaše nové heslo nespĺňa pravidlá." + }, + "acceptPolicies": { + "message": "Označením tohto políčka súhlasíte s nasledovným:" + }, + "acceptPoliciesError": { + "message": "Neboli akceptované Podmienky používania a zásady Ochrany osobných údajov." + }, + "termsOfService": { + "message": "Podmienky používania" + }, + "privacyPolicy": { + "message": "Zásady ochrany osobných údajov" + }, + "hintEqualsPassword": { + "message": "Nápoveda pre heslo nemôže byť rovnaká ako heslo." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Overenie synchronizácie desktopu" + }, + "desktopIntegrationVerificationText": { + "message": "Prosím, overte, že desktopová aplikácia zobrazuje tento odtlačok: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Integrácia v prehliadači nie je povolená" + }, + "desktopIntegrationDisabledDesc": { + "message": "Integrácia v prehliadači nie je povolená v aplikácii Bitwarden Desktop. Prosím, povoľte ju v nastaveniach desktopovej aplikácie." + }, + "startDesktopTitle": { + "message": "Spustiť desktopovú aplikáciu Bitwarden Desktop" + }, + "startDesktopDesc": { + "message": "Aplikácia Bitwarden Desktop musí byť pred použitím odomknutia pomocou biometrických údajov spustená." + }, + "errorEnableBiometricTitle": { + "message": "Nie je môžné povoliť biometriu" + }, + "errorEnableBiometricDesc": { + "message": "Akcia bola zrušená desktopovou aplikáciou" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktopová aplikácia pre počítač zneplatnila zabezpečený komunikačný kanál. Skúste túto operáciu znova" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Komunikácia s desktopom prerušená" + }, + "nativeMessagingWrongUserDesc": { + "message": "Táto desktopová aplikácia je prihlásená do iného účtu. Zaistite, aby boli obe aplikácie prihlásené do rovnakého účtu." + }, + "nativeMessagingWrongUserTitle": { + "message": "Nezhoda účtu" + }, + "biometricsNotEnabledTitle": { + "message": "Biometria nie je povolená" + }, + "biometricsNotEnabledDesc": { + "message": "Biometria v prehliadači vyžaduje, aby bola povolená biometria v desktopovej aplikácii." + }, + "biometricsNotSupportedTitle": { + "message": "Biometria nie je podporovaná" + }, + "biometricsNotSupportedDesc": { + "message": "Biometria v prehliadači nie je podporovaná na tomto zariadení." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Povolenie nebolo udelené" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bez oprávnenia komunikovať s aplikáciou Bitwarden Desktop nemôžeme poskytnúť biometriu v rozšírení prehliadača. Skúste to znova." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Chyba žiadosti o povolenie" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Túto akciu nie je možné vykonať na bočnom paneli. Skúste to znova vo vyskakovacom alebo samostatnom okne." + }, + "personalOwnershipSubmitError": { + "message": "Z dôvodu podnikovej politiky máte obmedzené ukladanie položiek do osobného trezora. Zmeňte možnosť vlastníctvo na organizáciu a vyberte si z dostupných zbierok." + }, + "personalOwnershipPolicyInEffect": { + "message": "Politika organizácie ovplyvňuje vaše možnosti vlastníctva." + }, + "excludedDomains": { + "message": "Vylúčené domény" + }, + "excludedDomainsDesc": { + "message": "Bitwarden nebude požadovať ukladanie prihlasovacích údajov pre tieto domény. Aby sa zmeny prejavili, musíte stránku obnoviť." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ nie je platná doména", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Odoslať", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Hľadať Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Pridať Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "Súbor" + }, + "allSends": { + "message": "Všetky Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Bol dosiahnutý maximálny počet prístupov", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expirované" + }, + "pendingDeletion": { + "message": "Čakajúce odstránenie" + }, + "passwordProtected": { + "message": "Chránené heslom" + }, + "copySendLink": { + "message": "Kopírovať odkaz na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Odstrániť heslo" + }, + "delete": { + "message": "Odstrániť" + }, + "removedPassword": { + "message": "Heslo odstránené" + }, + "deletedSend": { + "message": "Odstrániť Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Odkaz na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Zakázané" + }, + "removePasswordConfirmation": { + "message": "Ste si istý, že chcete odstrániť heslo?" + }, + "deleteSend": { + "message": "Odstrániť Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Ste si istý, že chcete odstrániť Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Upraviť Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Aký typ Sendu to je?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Priateľský názov pre popísanie tohto Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Súbor, ktorý chcete odoslať." + }, + "deletionDate": { + "message": "Dátum odstránenia" + }, + "deletionDateDesc": { + "message": "Send bude natrvalo odstránený v zadaný dátum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Dátum exspirácie" + }, + "expirationDateDesc": { + "message": "Ak je nastavené, prístup k tomuto Sendu vyprší v zadaný dátum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 deň" + }, + "days": { + "message": "$DAYS$ dní", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Vlastné" + }, + "maximumAccessCount": { + "message": "Maximálny počet prístupov" + }, + "maximumAccessCountDesc": { + "message": "Ak je nastavené, používatelia už nebudú mať prístup k tomuto Sendu po dosiahnutí maximálneho počtu prístupov.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Voliteľne môžete vyžadovať heslo pre používateľov na prístup k tomuto Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Zabezpečená poznámka o tomto Sende.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Vypnúť tento Send, aby k nemu nikto nemal prístup.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Pri uložení kopírovať odkaz na Send do schránky.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Text, ktorý chcete odoslať." + }, + "sendHideText": { + "message": "Predvolene skryť text tohto Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Súčasný počet prístupov" + }, + "createSend": { + "message": "Vytvoriť nový Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nové heslo" + }, + "sendDisabled": { + "message": "Send zakázaný", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Z dôvodu podnikovej politiky môžete odstrániť iba existujúci Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send vytvorený", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send upravený", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Ak chcete zvoliť súbor, otvorte rozšírenie v bočnom paneli (ak je to možné) alebo kliknite do tohto okna kliknutím na tento banner." + }, + "sendFirefoxFileWarning": { + "message": "Ak chcete zvoliť súbor pomocou prehliadača Firefox, otvorte rozšírenie v bočnom paneli alebo kliknite do tohto okna kliknutím na tento banner." + }, + "sendSafariFileWarning": { + "message": "Ak chcete zvoliť súbor pomocou Safari, kliknite na tento banner a otvorte nové okno." + }, + "sendFileCalloutHeader": { + "message": "Skôr než začnete" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Ak chcete použiť pre výber dátumu štýl kalendára", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "kliknite sem", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "a vysunie sa.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Uvedený dátum exspirácie nie je platný." + }, + "deletionDateIsInvalid": { + "message": "Uvedený dátum odstránenia nie je platný." + }, + "expirationDateAndTimeRequired": { + "message": "Vyžaduje sa dátum a čas vypršania platnosti." + }, + "deletionDateAndTimeRequired": { + "message": "Vyžaduje sa dátum a čas odstránenia." + }, + "dateParsingError": { + "message": "Pri ukladaní dátumov odstránenia a vypršania platnosti sa vyskytla chyba." + }, + "hideEmail": { + "message": "Skryť moju emailovú adresu pred príjemcami." + }, + "sendOptionsPolicyInEffect": { + "message": "Jedno alebo viac pravidiel organizácie ovplyvňujú vaše možnosti funkcie Send." + }, + "passwordPrompt": { + "message": "Znova zadajte hlavné heslo" + }, + "passwordConfirmation": { + "message": "Potvrdenie hlavného hesla" + }, + "passwordConfirmationDesc": { + "message": "Táto akcia je chránená. Ak chcete pokračovať, znova zadajte hlavné heslo a overte svoju totožnosť." + }, + "emailVerificationRequired": { + "message": "Vyžaduje sa overenie e-mailu" + }, + "emailVerificationRequiredDesc": { + "message": "Na použitie tejto funkcie musíte overiť svoj e-mail. Svoj e-mail môžete overiť vo webovom trezore." + }, + "updatedMasterPassword": { + "message": "Hlavné heslo aktualizované" + }, + "updateMasterPassword": { + "message": "Aktualizovať hlavné heslo" + }, + "updateMasterPasswordWarning": { + "message": "Vaše hlavné heslo nedávno zmenil správca vo vašej organizácii. Ak chcete získať prístup k trezoru, musíte ho teraz aktualizovať. Pokračovaním sa odhlásite z aktuálnej relácie a budete sa musieť znova prihlásiť. Aktívne relácie na iných zariadeniach môžu zostať aktívne až jednu hodinu." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatická registrácia" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Táto organizácia má podnikovú politiku, ktorá vás automaticky zaregistruje na obnovenia hesla. Registrácia umožní správcom organizácie zmeniť vaše hlavné heslo." + }, + "selectFolder": { + "message": "Vybrať priečinok..." + }, + "ssoCompleteRegistration": { + "message": "Aby ste dokončili nastavenie prihlasovacieho portálu (SSO), prosím nastavte hlavné heslo na prístup a ochranu vášho trezora." + }, + "hours": { + "message": "Hodiny" + }, + "minutes": { + "message": "Minúty" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Zásady vašej organizácie ovplyvňujú časový limit trezoru. Maximálny povolený časový limit trezoru je $HOURS$ h a $MINUTES$ m", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Časový limit vášho trezora prekračuje obmedzenia nastavené vašou organizáciou." + }, + "vaultExportDisabled": { + "message": "Export trezoru je zakázaný" + }, + "personalVaultExportPolicyInEffect": { + "message": "Jedna alebo viacero zásad organizácie vám bráni exportovať váš osobný trezor." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Nie je možné identifikovať platný prvok formulára. Skúste namiesto toho preskúmať HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Nenašiel sa žiadny jedinečný identifikátor." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ používa SSO s vlastným kľúčovým serverom. Na prihlásenie členov tejto organizácie už nie je potrebné hlavné heslo.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Opustiť organizáciu" + }, + "removeMasterPassword": { + "message": "Odstrániť hlavné heslo" + }, + "removedMasterPassword": { + "message": "Hlavné heslo bolo odstránené." + }, + "leaveOrganizationConfirmation": { + "message": "Naozaj chcete opustiť túto organizáciu?" + }, + "leftOrganization": { + "message": "Opustili ste organizáciu." + }, + "toggleCharacterCount": { + "message": "Prepnúť počítadlo znakov" + }, + "sessionTimeout": { + "message": "Vaša relácia vypršala. Vráťte sa späť a skúste sa prihlásiť znova." + }, + "exportingPersonalVaultTitle": { + "message": "Exportovanie osobného trezora" + }, + "exportingPersonalVaultDescription": { + "message": "Exportované budú iba položy osobného trezora spojené s $EMAIL$. Položky trezora organizácie nebudú zahrnuté.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Chyba" + }, + "regenerateUsername": { + "message": "Vygenerovať nové používateľské meno" + }, + "generateUsername": { + "message": "Vygenerovať používateľské meno" + }, + "usernameType": { + "message": "Typ používateľského mena" + }, + "plusAddressedEmail": { + "message": "E-mail s plusovým aliasom", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Použiť možnosti subadresovania svojho poskytovateľa e-mailu." + }, + "catchallEmail": { + "message": "Catch-all e-mail" + }, + "catchallEmailDesc": { + "message": "Použiť doručenú poštu typu catch-all nastavenú na doméne." + }, + "random": { + "message": "Náhodné" + }, + "randomWord": { + "message": "Náhodné slovo" + }, + "websiteName": { + "message": "Názov stránky" + }, + "whatWouldYouLikeToGenerate": { + "message": "Čo by ste chceli vygenerovať?" + }, + "passwordType": { + "message": "Typ hesla" + }, + "service": { + "message": "Služba" + } +} diff --git a/apps/browser/src/_locales/sl/messages.json b/apps/browser/src/_locales/sl/messages.json new file mode 100644 index 0000000000..213e8e397f --- /dev/null +++ b/apps/browser/src/_locales/sl/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Brezplačen upravitelj gesel", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Varen in brezplačen upravitelj gesel za vse vaše naprave.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Prijavite se ali ustvarite nov račun za dostop do vašega varnega trezorja." + }, + "createAccount": { + "message": "Ustvari račun" + }, + "login": { + "message": "Prijavi se" + }, + "enterpriseSingleSignOn": { + "message": "Enkratna podjetniška prijava." + }, + "cancel": { + "message": "Prekliči" + }, + "close": { + "message": "Zapri" + }, + "submit": { + "message": "Pošlji" + }, + "emailAddress": { + "message": "Elektronski naslov" + }, + "masterPass": { + "message": "Glavno geslo" + }, + "masterPassDesc": { + "message": "Glavno geslo je geslo, ki ga uporabljate za dostop do vašega trezorja. Zelo pomembno je, da ne pozabite vaše glavno geslo. Gesla ni mogoče obnoviti v primeru, če ga pozabite." + }, + "masterPassHintDesc": { + "message": "Namig glavnega gesla vam lahko pomaga, da se spomnite vašega gesla, če ga pozabite." + }, + "reTypeMasterPass": { + "message": "Ponovno vnesite glavno geslo" + }, + "masterPassHint": { + "message": "Namig za glavno geslo (neobvezno)" + }, + "tab": { + "message": "Zavihek" + }, + "myVault": { + "message": "Moj trezor" + }, + "tools": { + "message": "Orodja" + }, + "settings": { + "message": "Nastavitve" + }, + "currentTab": { + "message": "Trenutni zavihek" + }, + "copyPassword": { + "message": "Kopiraj geslo" + }, + "copyNote": { + "message": "Kopiraj opombo" + }, + "copyUri": { + "message": "Kopiraj URL" + }, + "copyUsername": { + "message": "Kopiraj uporabniško ime" + }, + "copyNumber": { + "message": "Kopiraj številko" + }, + "copySecurityCode": { + "message": "Kopiraj varnostno kodo" + }, + "autoFill": { + "message": "samodejno zapolni" + }, + "generatePasswordCopied": { + "message": "Generiraj geslo (kopirano)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "Nobenih ujemajočih prijav." + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "Nobene prijave ni na voljo za auto-izpolnitev za trenutni zavihek." + }, + "addLogin": { + "message": "Dodaj prijavo" + }, + "addItem": { + "message": "Dodal element" + }, + "passwordHint": { + "message": "Namig za geslo" + }, + "enterEmailToGetHint": { + "message": "Vnesite epoštni naslov vašega računa, da prejmete namig za vaše glavno geslo." + }, + "getMasterPasswordHint": { + "message": "Pridobi namig za glavno geslo" + }, + "continue": { + "message": "Nadaljuj" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verifikacijska koda" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "account": { + "message": "Račun" + }, + "changeMasterPassword": { + "message": "Spremeni glavno geslo" + }, + "fingerprintPhrase": { + "message": "Fingerprint fraza", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fingerprint fraza vašega računa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Prijava v dveh korakih" + }, + "logOut": { + "message": "Odjava" + }, + "about": { + "message": "O programu" + }, + "version": { + "message": "Različica" + }, + "save": { + "message": "Shrani" + }, + "move": { + "message": "Premakni" + }, + "addFolder": { + "message": "Dodaj mapo" + }, + "name": { + "message": "Naziv" + }, + "editFolder": { + "message": "Uredi mapo" + }, + "deleteFolder": { + "message": "Izbriši mapo" + }, + "folders": { + "message": "Mape" + }, + "noFolders": { + "message": "Ni map za prikazat." + }, + "helpFeedback": { + "message": "Pomoč in povratne informacije" + }, + "sync": { + "message": "Sinhronizacija" + }, + "syncVaultNow": { + "message": "Sinhroniziraj trezor zdaj" + }, + "lastSync": { + "message": "Zadnja sinhronizacija:" + }, + "passGen": { + "message": "Generator gesel" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Avtomatično generiraj močna, edinstvena gesla za vaše prijave." + }, + "bitWebVault": { + "message": "Bitwarden spletni trezor" + }, + "importItems": { + "message": "Uvozi predmete" + }, + "select": { + "message": "Izberi" + }, + "generatePassword": { + "message": "Generiraj geslo" + }, + "regeneratePassword": { + "message": "Regeneriraj geslo" + }, + "options": { + "message": "Možnosti" + }, + "length": { + "message": "Dolžina" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Število besed" + }, + "wordSeparator": { + "message": "Ločilo besed" + }, + "capitalize": { + "message": "Velika začetnica", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Vključi številko" + }, + "minNumbers": { + "message": "Minimalno števil" + }, + "minSpecial": { + "message": "Minimalno posebnih znakov" + }, + "avoidAmbChar": { + "message": "Izogibaj se dvoumnim znakom" + }, + "searchVault": { + "message": "Išči v trezorju" + }, + "edit": { + "message": "Uredi" + }, + "view": { + "message": "Pogled" + }, + "noItemsInList": { + "message": "Ni predmetov za prikazat." + }, + "itemInformation": { + "message": "Informacije o izdelku" + }, + "username": { + "message": "Uporabniško ime" + }, + "password": { + "message": "Geslo" + }, + "passphrase": { + "message": "Parafraza" + }, + "favorite": { + "message": "Priljubljeni" + }, + "notes": { + "message": "Opombe" + }, + "note": { + "message": "Opomba" + }, + "editItem": { + "message": "Uredi vnos" + }, + "folder": { + "message": "Mapa" + }, + "deleteItem": { + "message": "Izbiši vnos" + }, + "viewItem": { + "message": "Ogled vnosa" + }, + "launch": { + "message": "Zaženi" + }, + "website": { + "message": "Spletna stran" + }, + "toggleVisibility": { + "message": "Preklopi vidljivost" + }, + "manage": { + "message": "Upravljaj" + }, + "other": { + "message": "Drugo" + }, + "rateExtension": { + "message": "Ocenite to razširitev" + }, + "rateExtensionDesc": { + "message": "Premislite če nam želite pomagati z dobro oceno!" + }, + "browserNotSupportClipboard": { + "message": "Vaš spletni brskalnik ne podpira enostavno kopiranje odložišča. Kopirajte ročno." + }, + "verifyIdentity": { + "message": "Verify Identity" + }, + "yourVaultIsLocked": { + "message": "Vaš trezor je zaklenjen. Potrdite vaše glavno geslo za nadaljevanje." + }, + "unlock": { + "message": "Odkleni" + }, + "loggedInAsOn": { + "message": "Prijavljeni kot $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Napačno glavno geslo" + }, + "vaultTimeout": { + "message": "Časovna omejitev trezorja" + }, + "lockNow": { + "message": "Zakleni zdaj" + }, + "immediately": { + "message": "Takoj" + }, + "tenSeconds": { + "message": "10 sekund" + }, + "twentySeconds": { + "message": "20 sekund" + }, + "thirtySeconds": { + "message": "30 sekund" + }, + "oneMinute": { + "message": "1 minuta" + }, + "twoMinutes": { + "message": "2 minuti" + }, + "fiveMinutes": { + "message": "5 minut" + }, + "fifteenMinutes": { + "message": "15 minut" + }, + "thirtyMinutes": { + "message": "30 minut" + }, + "oneHour": { + "message": "1 ura" + }, + "fourHours": { + "message": "4 ure" + }, + "onLocked": { + "message": "Ob sistemskem zaklepu" + }, + "onRestart": { + "message": "Ob ponovnem zagonu spletnega brskalnika" + }, + "never": { + "message": "Nikoli" + }, + "security": { + "message": "Varnost" + }, + "errorOccurred": { + "message": "Prišlo je do napake" + }, + "emailRequired": { + "message": "Epoštni naslov je obvezen." + }, + "invalidEmail": { + "message": "Neveljaven epoštni naslov." + }, + "masterPassRequired": { + "message": "Glavno geslo je obvezno." + }, + "masterPassLength": { + "message": "Glavno geslo mora biti dolgo najmanj 8 znakov." + }, + "masterPassDoesntMatch": { + "message": "Potrditev glavnega gesla se ne ujema." + }, + "newAccountCreated": { + "message": "Vaš nov račun je bil ustvarjen! Sedaj se lahko prijavite." + }, + "masterPassSent": { + "message": "Poslali smo vam epoštno spročilo z namigom za vaše glavno geslo." + }, + "verificationCodeRequired": { + "message": "Verifikacijska koda je obvezna." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "valueCopied": { + "message": "$VALUE$ kopirano", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Ni mogoče avto-izpolniti izbrazno prijavo na tej spletni strani. Namesto tega kopirajte in prilepite podatke." + }, + "loggedOut": { + "message": "Odjavljen" + }, + "loginExpired": { + "message": "Vaša seja je potekla." + }, + "logOutConfirmation": { + "message": "Ste prepričani, da se želite odjaviti?" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Ne" + }, + "unexpectedError": { + "message": "Prišlo je do nepričakovane napake." + }, + "nameRequired": { + "message": "Ime je obvezno." + }, + "addedFolder": { + "message": "Dodana mapa" + }, + "changeMasterPass": { + "message": "Spremeni glavno geslo" + }, + "changeMasterPasswordConfirmation": { + "message": "Svoje glavno geslo lahko spremenite v bitwarden.com spletnem trezorju. Želite obiskati spletno stran zdaj?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Urejena mapa" + }, + "deleteFolderConfirmation": { + "message": "Ste prepričani, da želite izbrisati to mapo?" + }, + "deletedFolder": { + "message": "Izbrisana mapa" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "Sinhronizacija končana" + }, + "syncingFailed": { + "message": "Sinhronizacija ni uspela" + }, + "passwordCopied": { + "message": "Geslo je bilo kopirano" + }, + "uri": { + "message": "URL" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nov URL" + }, + "addedItem": { + "message": "Dodan vnos" + }, + "editedItem": { + "message": "Urejen vnos" + }, + "deleteItemConfirmation": { + "message": "Ali ste prepričani, da želite izbrisati?" + }, + "deletedItem": { + "message": "Pošlji vnos v smeti" + }, + "overwritePassword": { + "message": "Prepiši geslo" + }, + "overwritePasswordConfirmation": { + "message": "Ali ste prepričani, da želite prepisati vaše trenutno geslo?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Preišči mapo" + }, + "searchCollection": { + "message": "Preišči zbirko" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "Brez mape", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Ne prikazuj identitete" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Počisti odložišče", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should Bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Da, shrani zdaj" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Do you want to update this password in Bitwarden?" + }, + "notificationChangeSave": { + "message": "Da, posodobi zdaj" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Spremeni temo aplikacije." + }, + "dark": { + "message": "Temno", + "description": "Dark color" + }, + "light": { + "message": "Svetlo", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Izvoz trezorja" + }, + "fileFormat": { + "message": "Format datoteke" + }, + "warning": { + "message": "OPOZORILO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potrdite izvoz trezorja" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "Ta izvoz šifrira vaše podatke z uporabo ključa za šifriranje. Če boste kdaj zamenjali ključ za šifriranje, je potrebno, da ponovno naredite izvoz, ker ne boste mogli dešifrirati to izvoženo datoteko." + }, + "encExportAccountWarningDesc": { + "message": "Ključ za šifriranje je edinstven za vsak Bitwarden račun, zato ni mogoče da se uvozi šifrirana datoteka v drugi račun." + }, + "exportMasterPassword": { + "message": "Vnesite vaše glavno geslo za izvoz podatkov iz vašega trezorja." + }, + "shared": { + "message": "V skupni rabi" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "Deli" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Več o tem" + }, + "authenticatorKeyTotp": { + "message": "Ključ avtentikatorja (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verifikacijska koda (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopiraj verifikacijsko kodo" + }, + "attachments": { + "message": "Priponke" + }, + "deleteAttachment": { + "message": "Izbriši priponke" + }, + "deleteAttachmentConfirmation": { + "message": "Ste prepričani, da želite izbrisati to priponko?" + }, + "deletedAttachment": { + "message": "Izbrisana priponka" + }, + "newAttachment": { + "message": "Dodaj novo priponko" + }, + "noAttachments": { + "message": "Ni priponk." + }, + "attachmentSaved": { + "message": "Priponka je bila shranjena." + }, + "file": { + "message": "Datoteka" + }, + "selectFile": { + "message": "Izberite datoteko." + }, + "maxFileSize": { + "message": "Največja velikost datoteke je 500 MB." + }, + "featureUnavailable": { + "message": "Funkcija ni na voljo." + }, + "updateKey": { + "message": "Ne morete koristiti to funkcijo dokler ne posodobite vaš ključ za šifriranje." + }, + "premiumMembership": { + "message": "Premium članstvo" + }, + "premiumManage": { + "message": "Upravljanje članstva" + }, + "premiumManageAlert": { + "message": "S svojim članstvom lahko upravljate na bitwarden.com spletnem trezorju. Želite obiskati spletno stran zdaj?" + }, + "premiumRefresh": { + "message": "Osvežite članstvo" + }, + "premiumNotCurrentMember": { + "message": "Trenutno niste premium član." + }, + "premiumSignUpAndGet": { + "message": "Prijavite se za premium članstvo in dobite:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB šifriranog prostora za shrambo podatkov." + }, + "ppremiumSignUpTwoStep": { + "message": "Dodatne možnosti za prijavo v dveh korakih kot so YubiKey, FIDO U2F in Duo." + }, + "ppremiumSignUpReports": { + "message": "Higiena gesel, zdravje računa in poročila o kraji podatkov, da lahko ohranite vaš trezor varen." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verifikacijska koda (2FA) generator za prijave v vašem trezorju." + }, + "ppremiumSignUpSupport": { + "message": "Prioritetna podpora strankam." + }, + "ppremiumSignUpFuture": { + "message": "Vse bodoče premium ugodnosti. Kmalu še več!" + }, + "premiumPurchase": { + "message": "Kupite premium članstvo" + }, + "premiumPurchaseAlert": { + "message": "Premium članstvo lahko kupite na bitwarden.com spletnem trezoju. Želite obiskati spletno stran zdaj?" + }, + "premiumCurrentMember": { + "message": "Ste premium član!" + }, + "premiumCurrentMemberThanks": { + "message": "Hvala da podpirate Bitwarden." + }, + "premiumPrice": { + "message": "Vse za samo $PRICE$ /leto!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Osveževanje zaključeno" + }, + "disableAutoTotpCopy": { + "message": "Onemogočite avtomatsko kopiranje TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Če za prijavo uporabljate avtentikacijski ključ je TOTP verifikacijska koda avtomatično kopirana v vaše odložišče kadarkoli avto-izpolnite prijavo." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium članstvo je potrebno" + }, + "premiumRequiredDesc": { + "message": "Premium članstvo je potrebno za uporabo te funkcije." + }, + "enterVerificationCodeApp": { + "message": "Vnesite 6-mestno verifikacijsko kodo iz vaše verifikacijske aplikacije." + }, + "enterVerificationCodeEmail": { + "message": "Vnesite 6-mestno verifikacijsko kodo, ki vam je bila poslana na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapomni si me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Ponovno pošlji verifikacijsko kodo na email" + }, + "useAnotherTwoStepMethod": { + "message": "Uporabi drugi način prijave v dveh korakih" + }, + "insertYubiKey": { + "message": "Priključi svoj YubiKey v USB priključek, nato pa pritisni na njegovo tipko." + }, + "insertU2f": { + "message": "Priključi svoj varnostni ključ v USB priključek. Če ima tipko, se jo dotaknite." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Prijava ni na voljo" + }, + "noTwoStepProviders": { + "message": "Ta račun ima omogočemo prijavo v dveh korakih, ampak, nobena izmed konfiguriranih prijav v dveh korakih ni podprta v teb spletnem brskalniku." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Koda za obnovitev" + }, + "authenticatorAppTitle": { + "message": "Aplikacija za avtentikacijo" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "E-pošta" + }, + "emailDesc": { + "message": "Potrditvene kode vam bodo posredovane po e-pošti." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "URL naslov strežnika" + }, + "apiUrl": { + "message": "URL naslov API strežnika" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill on Page Load" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Uporabi privzete nastavitve" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website" + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard" + }, + "commandLockVaultDesc": { + "message": "Lock the vault" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "Value" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Besedilo" + }, + "cfTypeHidden": { + "message": "Skrito" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Če kliknete izven pojavnega okna, da preverite vašo epošto za vašo verifikacijsko kodo, bo to povročilo, da se je pojavno okno zapre. Želite odpreti to pojavno okno v novem oknu, tako, da se ne bo zaprlo?" + }, + "popupU2fCloseMessage": { + "message": "Ta spletni brskalnik ne more obdelati U2F zahteve v tem pojavnem oknu. Želite odpreti to pojavno okno v novem oknu, tako, da se lahko prijavite z U2F?" + }, + "disableFavicon": { + "message": "Onemogoči ikone spletnih mest" + }, + "disableFaviconDesc": { + "message": "Ikone spletnih mest ponujajo prepoznavne ikone zraven prijav v vašem trezorju." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Ime imetnika kartice" + }, + "number": { + "message": "Številka" + }, + "brand": { + "message": "Znamka" + }, + "expirationMonth": { + "message": "Mesec poteka" + }, + "expirationYear": { + "message": "Leto poteka" + }, + "expiration": { + "message": "Potek" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Marec" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Junij" + }, + "july": { + "message": "Julij" + }, + "august": { + "message": "Avgust" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Varnostna koda" + }, + "ex": { + "message": "npr." + }, + "title": { + "message": "Naziv" + }, + "mr": { + "message": "G." + }, + "mrs": { + "message": "Ga." + }, + "ms": { + "message": "Gdč." + }, + "dr": { + "message": "Dr." + }, + "firstName": { + "message": "Ime" + }, + "middleName": { + "message": "Srednje ime" + }, + "lastName": { + "message": "Priimek" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Ime identitete" + }, + "company": { + "message": "Podjetje" + }, + "ssn": { + "message": "EMŠO" + }, + "passportNumber": { + "message": "Številka potnega lista" + }, + "licenseNumber": { + "message": "Številka vozniškega dovoljenja" + }, + "email": { + "message": "E-pošta" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Naslov" + }, + "address1": { + "message": "Naslov 1" + }, + "address2": { + "message": "Naslov 2" + }, + "address3": { + "message": "Naslov 3" + }, + "cityTown": { + "message": "Mesto / Naselje" + }, + "stateProvince": { + "message": "Država / Regija" + }, + "zipPostalCode": { + "message": "Poštna številka" + }, + "country": { + "message": "Država" + }, + "type": { + "message": "Vrsta" + }, + "typeLogin": { + "message": "Prijava" + }, + "typeLogins": { + "message": "Prijave" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "passwordHistory": { + "message": "Password History" + }, + "back": { + "message": "Back" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "Priljubljeno" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Osveži" + }, + "cards": { + "message": "Plačilne kartice" + }, + "identities": { + "message": "Identitete" + }, + "logins": { + "message": "Prijave" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Počisti", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Current URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "All Items" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "Remove" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Add Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "File" + }, + "allSends": { + "message": "All Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Remove Password" + }, + "delete": { + "message": "Delete" + }, + "removedPassword": { + "message": "Removed Password" + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "Are you sure you want to remove the password?" + }, + "deleteSend": { + "message": "Delete Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 day" + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/sr/messages.json b/apps/browser/src/_locales/sr/messages.json new file mode 100644 index 0000000000..e5cb6ff47f --- /dev/null +++ b/apps/browser/src/_locales/sr/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Бесплатни Менаџер Лозинки", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Сигурни и бесплатни менаџер лозинке за све ваше уређаје.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Пријавите се или креирајте нови налог за приступ Сефу." + }, + "createAccount": { + "message": "Креирај налог" + }, + "login": { + "message": "Пријавите се" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Једна Пријава" + }, + "cancel": { + "message": "Откажи" + }, + "close": { + "message": "Затвори" + }, + "submit": { + "message": "Пошаљи" + }, + "emailAddress": { + "message": "Адреса е-поште" + }, + "masterPass": { + "message": "Главна Лозинка" + }, + "masterPassDesc": { + "message": "Главна Лозинка је лозинка коју користите за приступ Вашем сефу. Врло је важно да је не заборавите. Не постоји начин да повратите лозинку у случају да је заборавите." + }, + "masterPassHintDesc": { + "message": "Савет Главне Лозинке може да Вам помогне да се потсетите ако је заборавите." + }, + "reTypeMasterPass": { + "message": "Поновите Главну Лозинку" + }, + "masterPassHint": { + "message": "Савет Главне Лозинке (опционо)" + }, + "tab": { + "message": "Језичак" + }, + "myVault": { + "message": "Мој Сеф" + }, + "tools": { + "message": "Алатке" + }, + "settings": { + "message": "Подешавања" + }, + "currentTab": { + "message": "Тренутни језичак" + }, + "copyPassword": { + "message": "Копирај лозинку" + }, + "copyNote": { + "message": "Копирај белешку" + }, + "copyUri": { + "message": "Копирај УРЛ" + }, + "copyUsername": { + "message": "Копирај име" + }, + "copyNumber": { + "message": "Копирај број" + }, + "copySecurityCode": { + "message": "Копирај сигурносни код" + }, + "autoFill": { + "message": "Аутоматско допуњавање" + }, + "generatePasswordCopied": { + "message": "Генериши Лозинку (копирано)" + }, + "copyElementIdentifier": { + "message": "Копирај назив прилагођеног поља" + }, + "noMatchingLogins": { + "message": "Нема одговарајућих пријављивања." + }, + "unlockVaultMenu": { + "message": "Откључај свој сеф" + }, + "loginToVaultMenu": { + "message": "Пријавите се на свој налог" + }, + "autoFillInfo": { + "message": "Нема доступне пријаве за аутоматско допуњавање за тренутни језичак прегледача." + }, + "addLogin": { + "message": "Додај Пријаву" + }, + "addItem": { + "message": "Додај ставку" + }, + "passwordHint": { + "message": "Савет лозинке" + }, + "enterEmailToGetHint": { + "message": "Унесите Ваш имејл да би добили савет за Вашу Главну Лозинку." + }, + "getMasterPasswordHint": { + "message": "Добити савет за Главну Лозинку" + }, + "continue": { + "message": "Настави" + }, + "sendVerificationCode": { + "message": "Пошаљите верификациони код на вашу е-пошту" + }, + "sendCode": { + "message": "Пошаљи код" + }, + "codeSent": { + "message": "Код послан" + }, + "verificationCode": { + "message": "Верификациони код" + }, + "confirmIdentity": { + "message": "Потврдите свој идентитет да би наставили." + }, + "account": { + "message": "Налог" + }, + "changeMasterPassword": { + "message": "Промени главну лозинку" + }, + "fingerprintPhrase": { + "message": "Сигурносна Фраза Сефа", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Ваша Сигурносна Фраза Сефа", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Пријава у два корака" + }, + "logOut": { + "message": "Одјави се" + }, + "about": { + "message": "О апликацији" + }, + "version": { + "message": "Верзија" + }, + "save": { + "message": "Сачувај" + }, + "move": { + "message": "Премести" + }, + "addFolder": { + "message": "Додај фасциклу" + }, + "name": { + "message": "Име" + }, + "editFolder": { + "message": "Уреди фасциклу" + }, + "deleteFolder": { + "message": "Избриши фасциклу" + }, + "folders": { + "message": "Фасцикле" + }, + "noFolders": { + "message": "Нема фасцикле за приказивање." + }, + "helpFeedback": { + "message": "Помоћ и подршка" + }, + "sync": { + "message": "Синхронизација" + }, + "syncVaultNow": { + "message": "Одмах синхронизуј сеф" + }, + "lastSync": { + "message": "Задња синронизација:" + }, + "passGen": { + "message": "Генератор Лозинке" + }, + "generator": { + "message": "Генератор", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Аутоматски генеришите јаке, јединствене лозинке за ваше пријаве." + }, + "bitWebVault": { + "message": "Bitwarden Интернет Сеф" + }, + "importItems": { + "message": "Увоз ставки" + }, + "select": { + "message": "Изабери" + }, + "generatePassword": { + "message": "Генерисање лозинке" + }, + "regeneratePassword": { + "message": "Поново генериши лозинку" + }, + "options": { + "message": "Опције" + }, + "length": { + "message": "Дужина" + }, + "uppercase": { + "message": "Велика слова (A-Z)" + }, + "lowercase": { + "message": "Мала слова (a-z)" + }, + "numbers": { + "message": "Цифре (0-9)" + }, + "specialCharacters": { + "message": "Специјална слова (!@#$%^&*)" + }, + "numWords": { + "message": "Број речи" + }, + "wordSeparator": { + "message": "Одвајач речи" + }, + "capitalize": { + "message": "Прво слово велико", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Убаци број" + }, + "minNumbers": { + "message": "Минимално Бројева" + }, + "minSpecial": { + "message": "Минимално специјалних знакова" + }, + "avoidAmbChar": { + "message": "Избегавај двосмислене карактере" + }, + "searchVault": { + "message": "Претражи сеф" + }, + "edit": { + "message": "Уреди" + }, + "view": { + "message": "Приказ" + }, + "noItemsInList": { + "message": "Нема ставке у листи." + }, + "itemInformation": { + "message": "Инфо о ставци" + }, + "username": { + "message": "Корисничко име" + }, + "password": { + "message": "Лозинка" + }, + "passphrase": { + "message": "Фраза лозинке" + }, + "favorite": { + "message": "Омиљено" + }, + "notes": { + "message": "Белешке" + }, + "note": { + "message": "Белешка" + }, + "editItem": { + "message": "Уреди ставку" + }, + "folder": { + "message": "Фасцикла" + }, + "deleteItem": { + "message": "Обриши ставку" + }, + "viewItem": { + "message": "Види ставку" + }, + "launch": { + "message": "Отвори" + }, + "website": { + "message": "Веб сајт" + }, + "toggleVisibility": { + "message": "Пребаци видљивост" + }, + "manage": { + "message": "Управљати" + }, + "other": { + "message": "Остало" + }, + "rateExtension": { + "message": "Оцени овај додатак" + }, + "rateExtensionDesc": { + "message": "Молимо вас да размотрите да нам помогнете уз добру оцену!" + }, + "browserNotSupportClipboard": { + "message": "Ваш прегледач не подржава једноставно копирање у привремену меморију. Уместо тога копирајте га ручно." + }, + "verifyIdentity": { + "message": "Проверити идентитет" + }, + "yourVaultIsLocked": { + "message": "Сеф је закључан. Унесите главну лозинку за наставак." + }, + "unlock": { + "message": "Откључај" + }, + "loggedInAsOn": { + "message": "Пријављено са $EMAIL$ на $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Погрешна главна лозинка" + }, + "vaultTimeout": { + "message": "Тајмаут сефа" + }, + "lockNow": { + "message": "Закључај одмах" + }, + "immediately": { + "message": "Одмах" + }, + "tenSeconds": { + "message": "10 секунди" + }, + "twentySeconds": { + "message": "20 секунди" + }, + "thirtySeconds": { + "message": "30 секунди" + }, + "oneMinute": { + "message": "1 минут" + }, + "twoMinutes": { + "message": "2 минута" + }, + "fiveMinutes": { + "message": "5 минута" + }, + "fifteenMinutes": { + "message": "15 минута" + }, + "thirtyMinutes": { + "message": "30 минута" + }, + "oneHour": { + "message": "1 сат" + }, + "fourHours": { + "message": "4 сата" + }, + "onLocked": { + "message": "На закључавање система" + }, + "onRestart": { + "message": "На покретање прегледача" + }, + "never": { + "message": "Никада" + }, + "security": { + "message": "Сигурност" + }, + "errorOccurred": { + "message": "Дошло је до грешке!" + }, + "emailRequired": { + "message": "Имејл је неопходан." + }, + "invalidEmail": { + "message": "Неисправан имејл." + }, + "masterPassRequired": { + "message": "Главна Лозинка је неопходна." + }, + "masterPassLength": { + "message": "Главна Лозинка треба имати бар 8 знака." + }, + "masterPassDoesntMatch": { + "message": "Потврђена Главна Лозинка се не подудара." + }, + "newAccountCreated": { + "message": "Ваш налог је креиран! Сада се можете пријавити." + }, + "masterPassSent": { + "message": "Послали смо Вам поруку са саветом главне лозинке." + }, + "verificationCodeRequired": { + "message": "Верификациони код је обавезан." + }, + "invalidVerificationCode": { + "message": "Неисправан верификациони код" + }, + "valueCopied": { + "message": "$VALUE$ копиран(а/о)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Није могуће аутоматско допуњавање одабране ставке на овој страници. Уместо тога копирајте и налепите информације." + }, + "loggedOut": { + "message": "Одјављено" + }, + "loginExpired": { + "message": "Ваша сесија је истекла." + }, + "logOutConfirmation": { + "message": "Заиста желите да се одјавите?" + }, + "yes": { + "message": "Да" + }, + "no": { + "message": "Не" + }, + "unexpectedError": { + "message": "Дошло је до неочекиване грешке." + }, + "nameRequired": { + "message": "Име је неопходно." + }, + "addedFolder": { + "message": "Фасцикла додата" + }, + "changeMasterPass": { + "message": "Промени главну лозинку" + }, + "changeMasterPasswordConfirmation": { + "message": "Можете променити главну лозинку у Вашем сефу на bitwarden.com. Да ли желите да посетите веб страницу сада?" + }, + "twoStepLoginConfirmation": { + "message": "Пријава у два корака чини ваш налог сигурнијим захтевом да верификујете своје податке помоћу другог уређаја, као што су безбедносни кључ, апликација, СМС-а, телефонски позив или имејл. Пријављивање у два корака може се омогућити на веб сефу. Да ли желите да посетите веб страницу сада?" + }, + "editedFolder": { + "message": "Фасцикла измењена" + }, + "deleteFolderConfirmation": { + "message": "Сигурно обрисати ову фасциклу?" + }, + "deletedFolder": { + "message": "Фасцикла обрисана" + }, + "gettingStartedTutorial": { + "message": "Туторијал" + }, + "gettingStartedTutorialVideo": { + "message": "Погледајте наш туторијал да бисте сазнали како да максимално искористите додатак прегледача." + }, + "syncingComplete": { + "message": "Синхронизација је завршена" + }, + "syncingFailed": { + "message": "Синхронизација није успела" + }, + "passwordCopied": { + "message": "Лозинка копирана" + }, + "uri": { + "message": "Линк" + }, + "uriPosition": { + "message": "Линк $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Нови линк" + }, + "addedItem": { + "message": "Ставка додата" + }, + "editedItem": { + "message": "Ставка уређена" + }, + "deleteItemConfirmation": { + "message": "Сигурно послати ову ставку у отпад?" + }, + "deletedItem": { + "message": "Ставка послата у Отпад" + }, + "overwritePassword": { + "message": "Препиши лозинку" + }, + "overwritePasswordConfirmation": { + "message": "Сигурно преписати тренутну лозинку?" + }, + "overwriteUsername": { + "message": "Препиши име" + }, + "overwriteUsernameConfirmation": { + "message": "Сигурно преписати тренутно име?" + }, + "searchFolder": { + "message": "Претражи фасциклу" + }, + "searchCollection": { + "message": "Претражи колекцију" + }, + "searchType": { + "message": "Тип претраге" + }, + "noneFolder": { + "message": "Без фасцикле", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Онемогући обавештење Додај Пријаву" + }, + "addLoginNotificationDesc": { + "message": "„Нотификације Додај Лозинку“ аутоматски тражи да сачувате нове пријаве у сефу кад год се први пут пријавите на њих." + }, + "dontShowCardsCurrentTab": { + "message": "Не приказуј кредитне картице на страници" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Ставке кредитне картице из вашег сефа наведене су на страници „Тренутна картица“ ради једноставног приступа аутоматског попуњавања." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Не приказуј идентитете на страници" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Идентитети из вашег сефа наведени су на страници „Тренутна картица“ ради једноставног приступа аутоматског попуњавања." + }, + "clearClipboard": { + "message": "Обриши привремену меморију", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Аутоматски обришите копиране вредности из привремене меморије.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Да ли Bitwarden треба да запамти ову лозинку?" + }, + "notificationAddSave": { + "message": "Сачувај" + }, + "disableChangedPasswordNotification": { + "message": "Онемогући обавештење о промењеним лозинкама" + }, + "disableChangedPasswordNotificationDesc": { + "message": "„Нотификација Промењена Лозинка“ аутоматски тражи да ажурирате лозинку за пријављивање у сефу сваки пут када открије да сте је променили на веб сајту." + }, + "notificationChangeDesc": { + "message": "Да ли желите да ажурирате ову лозинку за Bitwarden?" + }, + "notificationChangeSave": { + "message": "Ажурирај" + }, + "disableContextMenuItem": { + "message": "Онемогући опције у контекстном менију" + }, + "disableContextMenuItemDesc": { + "message": "Опције контекстуалног менија пружају брз приступ генерисању лозинки и пријавама за веб сајт на вашом тренутном језичку." + }, + "defaultUriMatchDetection": { + "message": "Стандардно налажење УРЛ", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Изаберите подразумевани начин на који се поступа са откривањем УРЛ за пријаве приликом извођења радњи као што је ауто-попуњавање." + }, + "theme": { + "message": "Тема" + }, + "themeDesc": { + "message": "Промени боје апликације" + }, + "dark": { + "message": "Тамна", + "description": "Dark color" + }, + "light": { + "message": "Светла", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized црно", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Извоз сефа" + }, + "fileFormat": { + "message": "Формат датотеке" + }, + "warning": { + "message": "УПОЗОРЕЊЕ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Потврдите извоз сефа" + }, + "exportWarningDesc": { + "message": "Овај извоз садржи податке сефа у нешифрираном формату. Не бисте смели да сачувате или шаљете извезену датотеку преко несигурних канала (као што је имејл). Избришите датотеку одмах након што завршите са коришћењем." + }, + "encExportKeyWarningDesc": { + "message": "Овај извоз шифрује податке користећи кључ за шифровање вашег налога. Ако икада промените кључ за шифровање свог налога, требало би да поново извезете, јер нећете моћи да дешифрујете овај извоз." + }, + "encExportAccountWarningDesc": { + "message": "Кључеви за шифровање налога јединствени су за сваки кориснички налог Bitwarden-а, тако да не можете да увезете шифровани извоз на други налог." + }, + "exportMasterPassword": { + "message": "Унети главну лозинку за извоз сефа." + }, + "shared": { + "message": "Дељено" + }, + "learnOrg": { + "message": "Сазнајте о организацијама" + }, + "learnOrgConfirmation": { + "message": "Bitwarden вам омогућава да делите ставке сефа са другима користећи организацију. Да ли желите да посетите веб локацију bitwarden.com да бисте сазнали више?" + }, + "moveToOrganization": { + "message": "Премести у организацију" + }, + "share": { + "message": "Подели" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ премештен у $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Изаберите организацију у коју желите да преместите овај предмет. Прелазак на организацију преноси власништво над ставком у ту организацију. Више нећете бити директни власник ове ставке након што је премештена." + }, + "learnMore": { + "message": "Сазнај више" + }, + "authenticatorKeyTotp": { + "message": "Једнократни код" + }, + "verificationCodeTotp": { + "message": "Једнократни код" + }, + "copyVerificationCode": { + "message": "Копирај верификациони код" + }, + "attachments": { + "message": "Прилози" + }, + "deleteAttachment": { + "message": "Обриши прилог" + }, + "deleteAttachmentConfirmation": { + "message": "Сигурно обрисати овај прилог?" + }, + "deletedAttachment": { + "message": "Прилог обрисан" + }, + "newAttachment": { + "message": "Додај нови прилог" + }, + "noAttachments": { + "message": "Без прилога." + }, + "attachmentSaved": { + "message": "Прилог је сачуван." + }, + "file": { + "message": "Датотека" + }, + "selectFile": { + "message": "Изабери датотеку." + }, + "maxFileSize": { + "message": "Максимална величина је 500МБ." + }, + "featureUnavailable": { + "message": "Функција је недоступна" + }, + "updateKey": { + "message": "Не можете да користите ову способност док не промените Ваш кључ за шифровање." + }, + "premiumMembership": { + "message": "Премијум чланство" + }, + "premiumManage": { + "message": "Управљање чланством" + }, + "premiumManageAlert": { + "message": "Можете управљати вашом претплатом на bitwarden.com. Да ли желите да посетите веб сајт сада?" + }, + "premiumRefresh": { + "message": "Освежите чланство" + }, + "premiumNotCurrentMember": { + "message": "Тренутно нисте премијум члан." + }, + "premiumSignUpAndGet": { + "message": "Пријавите се за премијум чланство и добијте:" + }, + "ppremiumSignUpStorage": { + "message": "1ГБ шифровано складиште за прилоге." + }, + "ppremiumSignUpTwoStep": { + "message": "Додатне опције пријаве у два корака као што су YubiKey, FIDO U2F, и Duo." + }, + "ppremiumSignUpReports": { + "message": "Извештаји о хигијени лозинки, здравственом стању налога и кршењу података да бисте заштитили сеф." + }, + "ppremiumSignUpTotp": { + "message": "Генератор једнократног кода (2FA) за пријаве из сефа." + }, + "ppremiumSignUpSupport": { + "message": "Приоритетна корисничка подршка." + }, + "ppremiumSignUpFuture": { + "message": "Све будуће премијум функције. Више долазе ускоро!" + }, + "premiumPurchase": { + "message": "Купити премијум" + }, + "premiumPurchaseAlert": { + "message": "Можете купити премијум претплату на bitwarden.com. Да ли желите да посетите веб сајт сада?" + }, + "premiumCurrentMember": { + "message": "Ви сте премијум члан!" + }, + "premiumCurrentMemberThanks": { + "message": "Хвала Вам за подршку Bitwarden-а." + }, + "premiumPrice": { + "message": "Све за само $PRICE$ годишње!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Освежавање је завршено" + }, + "disableAutoTotpCopy": { + "message": "Угаси аутоматско копирање једнократног кода" + }, + "disableAutoTotpCopyDesc": { + "message": "Ако је за вашу пријаву приложен аутентификациони кључ, једнократни код се аутоматски копира у вашој привременој меморији кад год ауто-попуните пријаву." + }, + "disableAutoBiometricsPrompt": { + "message": "Не тражи биометрику након покретања." + }, + "premiumRequired": { + "message": "Потребан Премијум" + }, + "premiumRequiredDesc": { + "message": "Премијум чланство је неопходно за употребу ове опције." + }, + "enterVerificationCodeApp": { + "message": "Унесите шестоцифрени верификациони код из апликације за утврђивање аутентичности." + }, + "enterVerificationCodeEmail": { + "message": "Унесите шестоцифрени верификациони код који је послан на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Провера имејла послата на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запамти ме" + }, + "sendVerificationCodeEmailAgain": { + "message": "Поново послати верификациони код на имејл" + }, + "useAnotherTwoStepMethod": { + "message": "Користите другу методу пријављивања у два корака" + }, + "insertYubiKey": { + "message": "Убаците свој YubiKey у УСБ порт рачунара, а затим додирните његово дугме." + }, + "insertU2f": { + "message": "Убаците свој сигурносни кључ у УСБ порт рачунара, и ако има дугме , додирните га." + }, + "webAuthnNewTab": { + "message": "Да бисте започели WebAuthn верификацију у два корака. Кликните на дугме испод за отваранје новог језичка и пратите упутства у нјему." + }, + "webAuthnNewTabOpen": { + "message": "Отвори нови језичак " + }, + "webAuthnAuthenticate": { + "message": "WebAutn аутентификација" + }, + "loginUnavailable": { + "message": "Пријава недоступна" + }, + "noTwoStepProviders": { + "message": "Овај налог има омогућено пријављивање у два корака, међутим овај веб прегледач не подржава ниједног од конфигурисаних добављача." + }, + "noTwoStepProviders2": { + "message": "Користите подржани веб прегледач (као што је Chrome) и/или додајте додатне добављаче који су боље подржани у веб прегледачима (као што је апликација за аутентификацију)." + }, + "twoStepOptions": { + "message": "Опције дво-коракне пријаве" + }, + "recoveryCodeDesc": { + "message": "Изгубили сте приступ свим својим двофакторским добављачима? Употребите код за опоравак да онемогућите све двофакторске добављаче из налога." + }, + "recoveryCodeTitle": { + "message": "Шифра за опоравак" + }, + "authenticatorAppTitle": { + "message": "Апликација Аутентификатор" + }, + "authenticatorAppDesc": { + "message": "Користите апликацију за аутентификацију (као што је Authy или Google Authenticator) за генерисање верификационих кодова.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP сигурносни кључ" + }, + "yubiKeyDesc": { + "message": "Користите YubiKey за приступ налогу. Ради са YubiKey 4, 4 Nano, 4C, и NEO уређајима." + }, + "duoDesc": { + "message": "Провери са Duo Security користећи Duo Mobile апликацију, СМС, телефонски позив, или U2F кључ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Провери са Duo Security за вашу организацију користећи Duo Mobile апликацију, СМС, телефонски позив, или U2F кључ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Користите било који WebAuthn сигурносни кључ за присту налогу." + }, + "emailTitle": { + "message": "Е-пошта" + }, + "emailDesc": { + "message": "Верификациони кодови ће вам бити послати имејлом." + }, + "selfHostedEnvironment": { + "message": "Самостално окружење" + }, + "selfHostedEnvironmentFooter": { + "message": "Наведите основни УРЛ ваше локалне Bitwarden инсталације." + }, + "customEnvironment": { + "message": "Прилагођено окружење" + }, + "customEnvironmentFooter": { + "message": "За напредне кориснике. Можете да одредите независно основни УРЛ сваког сервиса." + }, + "baseUrl": { + "message": "УРЛ Сервера" + }, + "apiUrl": { + "message": "УРЛ АПИ Сервера" + }, + "webVaultUrl": { + "message": "УРЛ сервера Сефа" + }, + "identityUrl": { + "message": "УРЛ сервера идентитета" + }, + "notificationsUrl": { + "message": "УРЛ сервера обавештења" + }, + "iconsUrl": { + "message": "УРЛ сервера иконица" + }, + "environmentSaved": { + "message": "УРЛ адресе окружења су сачуване." + }, + "enableAutoFillOnPageLoad": { + "message": "Омогући аутоматско попуњавање након учитавања странице" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Ако се открије образац за пријаву, извршите аутоматско попуњавање када се веб страница учита." + }, + "experimentalFeature": { + "message": "Ово је тренутно експериментална способност. Користите на властиту одговорност." + }, + "defaultAutoFillOnPageLoad": { + "message": "Подразумевано подешавање аутопуњења за пријаве" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Након што омогућите ауто-попуњавање странице, можете омогућити или онемогућити функцију за појединачне ставке за пријаву. Ово је подразумевана поставка за ставке за пријаву које нису различито конфигурисане." + }, + "itemAutoFillOnPageLoad": { + "message": "Ауто-попуњавање након учитавања странице (ако је омогућено у опцијама)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Користи подразумевано подешавање" + }, + "autoFillOnPageLoadYes": { + "message": "Аутоматско попуњавање наконг учитавања странице" + }, + "autoFillOnPageLoadNo": { + "message": "Без аутоматског попуњавања након учитавања странице" + }, + "commandOpenPopup": { + "message": "Отвори искачући прозор сефа" + }, + "commandOpenSidebar": { + "message": "Отвори сеф у бочну траку" + }, + "commandAutofillDesc": { + "message": "Аутоматско попуњавање последњу коришћену пријаву за тренутну веб страницу" + }, + "commandGeneratePasswordDesc": { + "message": "Генеришите и копирајте нову случајну лозинку у привремену меморију" + }, + "commandLockVaultDesc": { + "message": "Закључај сеф" + }, + "privateModeWarning": { + "message": "Подршка за приватни режим је експериментална и неке функције су ограничене." + }, + "customFields": { + "message": "Прилагођена Поља" + }, + "copyValue": { + "message": "Копирај вредност" + }, + "value": { + "message": "Вредност" + }, + "newCustomField": { + "message": "Ново прилагођено поље" + }, + "dragToSort": { + "message": "Превуците за сортирање" + }, + "cfTypeText": { + "message": "Текст" + }, + "cfTypeHidden": { + "message": "Сакривено" + }, + "cfTypeBoolean": { + "message": "Булове" + }, + "cfTypeLinked": { + "message": "Повезано", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Вредност повезана", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Ако кликнете изван искачућег прозора да бисте проверили имејл за верификациони код, овај прозор ће се затворити. Да ли желите да отворите овај прозор у новом прозору да се не би затворио?" + }, + "popupU2fCloseMessage": { + "message": "Овај прегледач не може да обрађује U2F захтеве у овом искачућем прозору. Да ли желите да отворите овај искачући прозор у новом прозору како бисте могли да се пријавите користећи U2F?" + }, + "disableFavicon": { + "message": "Онемогући иконице сајта" + }, + "disableFaviconDesc": { + "message": "Иконе веб сајта пружају препознатљиву слику поред сваке пријаве у сефу." + }, + "disableBadgeCounter": { + "message": "Онемогући бројач на иконици" + }, + "disableBadgeCounterDesc": { + "message": "Бројач иконице указује колико пријава имате за тренутну страницу у вашем сефу." + }, + "cardholderName": { + "message": "Име Власника Картице" + }, + "number": { + "message": "Број" + }, + "brand": { + "message": "Произвођач" + }, + "expirationMonth": { + "message": "Месец истека" + }, + "expirationYear": { + "message": "Година истека" + }, + "expiration": { + "message": "Истек" + }, + "january": { + "message": "Јануар" + }, + "february": { + "message": "Фебруар" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "Април" + }, + "may": { + "message": "Мај" + }, + "june": { + "message": "Јун" + }, + "july": { + "message": "Јул" + }, + "august": { + "message": "Август" + }, + "september": { + "message": "Септембар" + }, + "october": { + "message": "Октобар" + }, + "november": { + "message": "Новембар" + }, + "december": { + "message": "Децембар" + }, + "securityCode": { + "message": "Сигурносни код" + }, + "ex": { + "message": "нпр." + }, + "title": { + "message": "Наслов" + }, + "mr": { + "message": "Г." + }, + "mrs": { + "message": "Гђц." + }, + "ms": { + "message": "Гђа." + }, + "dr": { + "message": "Др" + }, + "firstName": { + "message": "Име" + }, + "middleName": { + "message": "Средње име" + }, + "lastName": { + "message": "Презиме" + }, + "fullName": { + "message": "Пуно име" + }, + "identityName": { + "message": "Име идентитета" + }, + "company": { + "message": "Предузеће" + }, + "ssn": { + "message": "Број социјалног осигурања" + }, + "passportNumber": { + "message": "Број пасоша" + }, + "licenseNumber": { + "message": "Број возачке дозволе" + }, + "email": { + "message": "Имејл" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адреса" + }, + "address1": { + "message": "Адреса 1" + }, + "address2": { + "message": "Адреса 2" + }, + "address3": { + "message": "Адреса 3" + }, + "cityTown": { + "message": "Град" + }, + "stateProvince": { + "message": "Држава / покрајина" + }, + "zipPostalCode": { + "message": "Поштански број" + }, + "country": { + "message": "Земља" + }, + "type": { + "message": "Тип" + }, + "typeLogin": { + "message": "Пријава" + }, + "typeLogins": { + "message": "Пријаве" + }, + "typeSecureNote": { + "message": "Сигурносна белешка" + }, + "typeCard": { + "message": "Кредитна Картица" + }, + "typeIdentity": { + "message": "Идентитет" + }, + "passwordHistory": { + "message": "Историја Лозинке" + }, + "back": { + "message": "Назад" + }, + "collections": { + "message": "Колекције" + }, + "favorites": { + "message": "Омиљени" + }, + "popOutNewWindow": { + "message": "Отворите у нови прозор" + }, + "refresh": { + "message": "Освежи" + }, + "cards": { + "message": "Кредитне Картице" + }, + "identities": { + "message": "Идентитети" + }, + "logins": { + "message": "Пријаве" + }, + "secureNotes": { + "message": "Сигурносне белешке" + }, + "clear": { + "message": "Очисти", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Проверите да ли је лозинка изложена." + }, + "passwordExposed": { + "message": "Ова лозинка је изложена $VALUE$ пута. Требали би да је промените.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Ова лозинка није никада изложена. Треба да је сигурна за употребу." + }, + "baseDomain": { + "message": "Главни домен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Име домена", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Хост", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Тачно" + }, + "startsWith": { + "message": "Почиње са" + }, + "regEx": { + "message": "Регуларни израз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Налажење УРЛ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Стандардно налажење", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Пребацити опције" + }, + "toggleCurrentUris": { + "message": "Укључи/искључи тренутне УРЛ", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Тренутни УРЛ", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Организација", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Врсте" + }, + "allItems": { + "message": "Све ставке" + }, + "noPasswordsInList": { + "message": "Нема лозинки у листи." + }, + "remove": { + "message": "Уклони" + }, + "default": { + "message": "Подразумевано" + }, + "dateUpdated": { + "message": "Промењено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Лозинка ажурирана", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Да ли сте сигурни да желите да користите опцију „Никад“? Ако поставите опције закључавања на „Никада“, на вашем уређају се чува кључ за шифровање сефа. Ако користите ову опцију, осигурајте да је уређај правилно заштићен." + }, + "noOrganizationsList": { + "message": "Не припадате ниједној организацији. Организације вам омогућавају да безбедно делите ставке са другим корисницима." + }, + "noCollectionsInList": { + "message": "Нема колекције у листи." + }, + "ownership": { + "message": "Власништво" + }, + "whoOwnsThisItem": { + "message": "Ко је власник ове ставке?" + }, + "strong": { + "message": "Јако", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Добро", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабо", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слаба Главна Лозинка" + }, + "weakMasterPasswordDesc": { + "message": "Главна лозинка коју сте одабрали је слаба. Требали бисте користити јаку главну лозинку (или фразу лозинке) да бисте правилно заштитили свој налог. Да ли сте сигурни да желите да користите ову главну лозинку?" + }, + "pin": { + "message": "ПИН", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Откључај са ПИН" + }, + "setYourPinCode": { + "message": "Поставите свој ПИН код за откључавање Bitwarden-а. Поставке ПИН-а ће се ресетовати ако се икада потпуно одјавите из апликације." + }, + "pinRequired": { + "message": "ПИН је обавезан." + }, + "invalidPin": { + "message": "Погрешан ПИН код." + }, + "unlockWithBiometrics": { + "message": "Откључавајте помоћу биометрије" + }, + "awaitDesktop": { + "message": "Чекање потврде са десктопа" + }, + "awaitDesktopDesc": { + "message": "Потврдити са биометриком у Bitwarden Desktop апликацији да би омогућили биометрику у претраживачу." + }, + "lockWithMasterPassOnRestart": { + "message": "Закључајте са главном лозинком при поновном покретању прегледача" + }, + "selectOneCollection": { + "message": "Морате одабрати макар једну колекцију." + }, + "cloneItem": { + "message": "Клонирај ставку" + }, + "clone": { + "message": "Клонирај" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Једна или више смерница организације утичу на поставке вашег генератора." + }, + "vaultTimeoutAction": { + "message": "Акција на тајмаут сефа" + }, + "lock": { + "message": "Закључај", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Отпад", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Тражи отпад" + }, + "permanentlyDeleteItem": { + "message": "Трајно избрисати ставку" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Да ли сте сигурни да желите да трајно избришете ову ставку?" + }, + "permanentlyDeletedItem": { + "message": "Трајно избрисана ставка" + }, + "restoreItem": { + "message": "Врати ставку" + }, + "restoreItemConfirmation": { + "message": "Да ли сте сигурни да желите да вратите ову ставку?" + }, + "restoredItem": { + "message": "Ставка враћена" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Одјава ће уклонити сваки приступ вашем сефу и захтева мрежну потврду идентитета након истека тајмаута. Да ли сте сигурни да желите да користите ову поставку?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Потврда акције тајмаута" + }, + "autoFillAndSave": { + "message": "Аутоматско попуњавање и чување" + }, + "autoFillSuccessAndSavedUri": { + "message": "Аутоматски попуњена ставка и сачуван УРЛ" + }, + "autoFillSuccess": { + "message": "Ставка ауто-попуњена" + }, + "setMasterPassword": { + "message": "Постави Главну Лозинку" + }, + "masterPasswordPolicyInEffect": { + "message": "Једна или више смерница организације захтевају да ваша главна лозинка испуни следеће захтеве:" + }, + "policyInEffectMinComplexity": { + "message": "Оцена минималне сложености од $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Минимална дужина од $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Садржи једно или више великих слова" + }, + "policyInEffectLowercase": { + "message": "Садржи једно или више малих слова" + }, + "policyInEffectNumbers": { + "message": "Садржи један или више бројева" + }, + "policyInEffectSpecial": { + "message": "Садржи један или више ових специјалних знакова $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваша нова главна лозинка не испуњава захтеве смерница." + }, + "acceptPolicies": { + "message": "Означавањем овог поља пристајете на следеће:" + }, + "acceptPoliciesError": { + "message": "Услови услуге и Политика приватности нису прихваћени." + }, + "termsOfService": { + "message": "Услови коришћења услуге" + }, + "privacyPolicy": { + "message": "Политика приватности" + }, + "hintEqualsPassword": { + "message": "Ваш савет за лозинку не може да буде исти као лозинка." + }, + "ok": { + "message": "У реду" + }, + "desktopSyncVerificationTitle": { + "message": "Провера синхронизације Desktop-а" + }, + "desktopIntegrationVerificationText": { + "message": "Проверите да десктоп апликација показује овај отисак: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Интеграција претраживача није омогућена" + }, + "desktopIntegrationDisabledDesc": { + "message": "Интеграција претраживача није омогућена у Bitwarden Desktop. Омогућите је у подешавањима из Bitwarden Desktop апликације." + }, + "startDesktopTitle": { + "message": "Покрени Bitwarden Desktop апликацију" + }, + "startDesktopDesc": { + "message": "Bitwarden Desktop апликација треба да се покрене пре употребе ове функције." + }, + "errorEnableBiometricTitle": { + "message": "Није могуће омогућити биометрику" + }, + "errorEnableBiometricDesc": { + "message": "Desktop апликација је поништила акцију" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop апликација је онемогућила безбедни комуникациони канал. Поновите ову операцију" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop комуникација прекинута" + }, + "nativeMessagingWrongUserDesc": { + "message": "Desktop апликација је пријављена на други налог. Проверите да су обе апликације са истим налогом." + }, + "nativeMessagingWrongUserTitle": { + "message": "Неподударање налога" + }, + "biometricsNotEnabledTitle": { + "message": "Биометрија није омогућена" + }, + "biometricsNotEnabledDesc": { + "message": "Биометрија прегледача захтева да у поставкама прво буде омогућена биометрија desktop-а." + }, + "biometricsNotSupportedTitle": { + "message": "Биометрија није подржана" + }, + "biometricsNotSupportedDesc": { + "message": "Биометрија прегледача није подржана на овом уређају." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Дозвола није дата" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Без дозволе за комуникацију са Bitwarden Desktop апликацијом, не можемо пружити биометријске податке у екстензији прегледача. Молимо вас, покушајте поново." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Грешка у захтеву за дозволу" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Ову радњу није могуће извршити на бочној траци, покушајте поново у искачућем прозору." + }, + "personalOwnershipSubmitError": { + "message": "Због смерница за предузећа, ограничено вам је чување предмета у вашем личном трезору. Промените опцију власништва у организацију и изаберите из доступних колекција." + }, + "personalOwnershipPolicyInEffect": { + "message": "смернице организације утичу на ваше могућности власништва." + }, + "excludedDomains": { + "message": "Изузети домени" + }, + "excludedDomainsDesc": { + "message": "Bitwarden неће тражити да сачува податке за пријављивање за ове домене. Морате освежити страницу да би промене ступиле на снагу." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ није важећи домен", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Тражи „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Додај „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Текст" + }, + "sendTypeFile": { + "message": "Датотека" + }, + "allSends": { + "message": "Све „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Достигнут максималан број приступа", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Истекло" + }, + "pendingDeletion": { + "message": "Брисање на чекању" + }, + "passwordProtected": { + "message": "Заштићено лозинком" + }, + "copySendLink": { + "message": "Копирај УРЛ „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Уклони лозинку" + }, + "delete": { + "message": "Обриши" + }, + "removedPassword": { + "message": "Лозинка уклоњена" + }, + "deletedSend": { + "message": "„Send“ обрисано", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "УРЛ „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Онемогућено" + }, + "removePasswordConfirmation": { + "message": "Да ли сте сигурни да желите уклонити лозинку?" + }, + "deleteSend": { + "message": "Избриши „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Сигурно избрисати овај „Send“?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Уреди „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Који је ово тип „Send“-a?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Име да се опише овај „Send“.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Датотека коју желиш да пошаљеш." + }, + "deletionDate": { + "message": "Брисање после" + }, + "deletionDateDesc": { + "message": "„Send“ ће бити трајно избрисан наведеног датума и времена.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Рок употребе" + }, + "expirationDateDesc": { + "message": "Ако је постављено, приступ овом „Send“ истиче на наведени датум и време.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 дан" + }, + "days": { + "message": "$DAYS$ дана", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Друго" + }, + "maximumAccessCount": { + "message": "Максималан број приступа" + }, + "maximumAccessCountDesc": { + "message": "Ако је постављено, корисници више неће моћи да приступе овом „Send“ када се достигне максимални број приступа.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Опционално захтевајте лозинку за приступ корисницима „Send“-у.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Приватне белешке о овом „Send“.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Онемогућите овај „Send“ да нико не би могао да му приступи.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Након чувања, копирај УРЛ за овај „Send“ у привремену меморију.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст који желиш да пошаљеш." + }, + "sendHideText": { + "message": "Подразумевано сакриј текст за овај „Send“.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Тренутни број приступа" + }, + "createSend": { + "message": "Креирај нови „Send“", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Нова лозинка" + }, + "sendDisabled": { + "message": "„Send“ онемогућен", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Због полисе компаније, можеш само да бришеш постојећа слања.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Креирано слање", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Измењено слање", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Да бисте изабрали датотеку, отворите екстензију на бочној траци (ако је могуће) или отворите у нови прозор кликом на овај банер." + }, + "sendFirefoxFileWarning": { + "message": "Да бисте изабрали датотеку са Firefox-ом, отворите екстензију на бочној траци или отворите у нови прозор кликом на овај банер." + }, + "sendSafariFileWarning": { + "message": "Да бисте изабрали датотеку са Safari-ом, отворите у нови прозор кликом на овај банер." + }, + "sendFileCalloutHeader": { + "message": "Пре него што почнеш" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Да би користио бирање датума кроз календар", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "кликните овде", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "Да бисте приказали искачући прозор.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Наведени датум истека није исправан." + }, + "deletionDateIsInvalid": { + "message": "Наведени датум брисања није исправан." + }, + "expirationDateAndTimeRequired": { + "message": "Неопходни су датум и време истека." + }, + "deletionDateAndTimeRequired": { + "message": "Неопходни су датум и време брисања." + }, + "dateParsingError": { + "message": "Појавила се грешка при чувању датума брисања и истека." + }, + "hideEmail": { + "message": "Сакриј моју е-адресу од примаоца." + }, + "sendOptionsPolicyInEffect": { + "message": "Једна или више смерница организације утичу на опције „Send“-а." + }, + "passwordPrompt": { + "message": "Поновно тражење главне лозинке" + }, + "passwordConfirmation": { + "message": "Потврда главне лозинке" + }, + "passwordConfirmationDesc": { + "message": "Ова акција је заштићена. Да бисте наставили, поново унесите своју главну лозинку да бисте проверили идентитет." + }, + "emailVerificationRequired": { + "message": "Потребна је верификација е-поште" + }, + "emailVerificationRequiredDesc": { + "message": "Морате да потврдите е-пошту да бисте користили ову функцију. Можете да потврдите е-пошту у веб сефу." + }, + "updatedMasterPassword": { + "message": "Главна лозинка ажурирана" + }, + "updateMasterPassword": { + "message": "Ажурирај главну лозинку" + }, + "updateMasterPasswordWarning": { + "message": "Ваша главна лозинка је недавно промењена од стране администратора организације. Како бисте приступили сефу, морате да је ажурирате. Ако наставите бићете одјављени из ваше тренутне сесије, што ће захтевати да се поново пријавите. Активне сесије на другим уређајима ће можда наставити да раде до сат времена." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Ауто пријављивање" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ова организација има полису која ће вас аутоматски пријавити за ресетовање лозинке. Пријава ће дозволити администраторима ваше организације да промене главну лозинку." + }, + "selectFolder": { + "message": "Изаберите фасциклу..." + }, + "ssoCompleteRegistration": { + "message": "Да бисте довршили пријављивање помоћу SSO, молимо да поставите главну лозинку за приступ и заштиту вашег сефа." + }, + "hours": { + "message": "Сата" + }, + "minutes": { + "message": "Минута" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Полиса ваше организације утиче на време истека сефа. Максимално дозвољено време истека је $HOURS$ сат(и) и $MINUTES$ minut(а)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Време истека вашег сефа је премашило дозвољена ограничења од стране ваше организације." + }, + "vaultExportDisabled": { + "message": "Извоз сефа онемогућен" + }, + "personalVaultExportPolicyInEffect": { + "message": "Једна или више полиса ваше организације вас спречава да извезете ваш сеф." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Није могуће идентификовати валидан елемент обрасца. Покушајте уместо тога да прегледате HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Није пронађен ниједан јединствени идентификатор." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ користи SSO уз сопствени сервер за кључеве. Главна лозинка за пријаву више није неопходна за чланове ове организације.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Напусти организацију" + }, + "removeMasterPassword": { + "message": "Уклони главну лозинку" + }, + "removedMasterPassword": { + "message": "Главна лозинка уклоњена." + }, + "leaveOrganizationConfirmation": { + "message": "Да ли сте сигурни да желите да напустите ову организацију?" + }, + "leftOrganization": { + "message": "Напустили сте организацију." + }, + "toggleCharacterCount": { + "message": "Пребаци бројање слова" + }, + "sessionTimeout": { + "message": "Ваша сесија је истекла. Вратите се и покушајте поново да се пријавите." + }, + "exportingPersonalVaultTitle": { + "message": "Извоз личног сефа" + }, + "exportingPersonalVaultDescription": { + "message": "Само предмети личног сефа повезани са $EMAIL$ биће извезени. Ставке организационог сефа неће бити укључене.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Грешка" + }, + "regenerateUsername": { + "message": "Поново генериши име" + }, + "generateUsername": { + "message": "Генериши име" + }, + "usernameType": { + "message": "Тип имена" + }, + "plusAddressedEmail": { + "message": "Плус имејл адресе", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Користите могућности подадресирања вашег добављача е-поште." + }, + "catchallEmail": { + "message": "„Ухвати све“ е-порука" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Случајно" + }, + "randomWord": { + "message": "Случајна реч" + }, + "websiteName": { + "message": "Име Вашег веб-сајта" + }, + "whatWouldYouLikeToGenerate": { + "message": "Шта желите да генеришете?" + }, + "passwordType": { + "message": "Тип лозинке" + }, + "service": { + "message": "Сервис" + } +} diff --git a/apps/browser/src/_locales/sv/messages.json b/apps/browser/src/_locales/sv/messages.json new file mode 100644 index 0000000000..7537ff2954 --- /dev/null +++ b/apps/browser/src/_locales/sv/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Gratis lösenordshanterare", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden är en säker och gratis lösenordshanterare för alla dina enheter.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Logga in eller skapa ett nytt konto för att komma åt dina lösenord." + }, + "createAccount": { + "message": "Skapa konto" + }, + "login": { + "message": "Logga in" + }, + "enterpriseSingleSignOn": { + "message": "Single Sign-On för företag" + }, + "cancel": { + "message": "Avbryt" + }, + "close": { + "message": "Stäng" + }, + "submit": { + "message": "Skicka" + }, + "emailAddress": { + "message": "E-postadress" + }, + "masterPass": { + "message": "Huvudlösenord" + }, + "masterPassDesc": { + "message": "Huvudlösenordet är det lösenord som du använder för att komma åt ditt valv. Det är väldigt viktigt att du inte glömmer bort ditt huvudlösenord, eftersom det inte går att återställa lösenordet om du skulle glömma bort det." + }, + "masterPassHintDesc": { + "message": "En huvudlösenordsledtråd kan hjälpa dig att komma ihåg ditt lösenord om du glömmer bort det." + }, + "reTypeMasterPass": { + "message": "Ange huvudlösenordet igen" + }, + "masterPassHint": { + "message": "Huvudlösenordsledtråd (frivillig)" + }, + "tab": { + "message": "Flik" + }, + "myVault": { + "message": "Mitt valv" + }, + "tools": { + "message": "Verktyg" + }, + "settings": { + "message": "Inställningar" + }, + "currentTab": { + "message": "Nuvarande flik" + }, + "copyPassword": { + "message": "Kopiera lösenord" + }, + "copyNote": { + "message": "Kopiera anteckning" + }, + "copyUri": { + "message": "Kopiera URI" + }, + "copyUsername": { + "message": "Kopiera användarnamn" + }, + "copyNumber": { + "message": "Kopiera nummer" + }, + "copySecurityCode": { + "message": "Kopiera säkerhetskod" + }, + "autoFill": { + "message": "Fyll i automatiskt" + }, + "generatePasswordCopied": { + "message": "Skapa lösenord (kopierad)" + }, + "copyElementIdentifier": { + "message": "Kopiera anpassat fältnamn" + }, + "noMatchingLogins": { + "message": "Inga matchande inloggningar." + }, + "unlockVaultMenu": { + "message": "Lås upp ditt valv" + }, + "loginToVaultMenu": { + "message": "Logga in i ditt valv" + }, + "autoFillInfo": { + "message": "Det finns inga inloggningar tillgängliga för automatisk ifyllnad på den nuvarande fliken." + }, + "addLogin": { + "message": "Lägg till en inloggning" + }, + "addItem": { + "message": "Lägg till objekt" + }, + "passwordHint": { + "message": "Lösenordsledtråd" + }, + "enterEmailToGetHint": { + "message": "Ange din e-postadress för att hämta din huvudlösenordsledtråd." + }, + "getMasterPasswordHint": { + "message": "Hämta huvudlösenordsledtråd" + }, + "continue": { + "message": "Fortsätt" + }, + "sendVerificationCode": { + "message": "Skicka en verifieringskod till din e-postadress" + }, + "sendCode": { + "message": "Skicka kod" + }, + "codeSent": { + "message": "Kod har skickats" + }, + "verificationCode": { + "message": "Verifieringskod" + }, + "confirmIdentity": { + "message": "Bekräfta din identitet för att fortsätta." + }, + "account": { + "message": "Konto" + }, + "changeMasterPassword": { + "message": "Ändra huvudlösenord" + }, + "fingerprintPhrase": { + "message": "Fingeravtrycksfras", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Ditt kontos fingeravtrycksfras", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Tvåstegsverifiering" + }, + "logOut": { + "message": "Logga ut" + }, + "about": { + "message": "Om" + }, + "version": { + "message": "Version" + }, + "save": { + "message": "Spara" + }, + "move": { + "message": "Flytta" + }, + "addFolder": { + "message": "Skapa mapp" + }, + "name": { + "message": "Namn" + }, + "editFolder": { + "message": "Redigera mapp" + }, + "deleteFolder": { + "message": "Radera mapp" + }, + "folders": { + "message": "Mappar" + }, + "noFolders": { + "message": "Det finns inga mappar att lista." + }, + "helpFeedback": { + "message": "Hjälp & Feedback" + }, + "sync": { + "message": "Synkronisera" + }, + "syncVaultNow": { + "message": "Synkronisera valv nu" + }, + "lastSync": { + "message": "Senaste synkronisering:" + }, + "passGen": { + "message": "Lösenordsgenerator" + }, + "generator": { + "message": "Generator", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Skapa starka och unika lösenord automatiskt för dina inloggningar." + }, + "bitWebVault": { + "message": "Bitwardens webbvalv" + }, + "importItems": { + "message": "Importera objekt" + }, + "select": { + "message": "Välj" + }, + "generatePassword": { + "message": "Skapa lösenord" + }, + "regeneratePassword": { + "message": "Skapa nytt lösenord" + }, + "options": { + "message": "Alternativ" + }, + "length": { + "message": "Längd" + }, + "uppercase": { + "message": "Versaler (A-Ö)" + }, + "lowercase": { + "message": "Gemener (a-ö)" + }, + "numbers": { + "message": "Siffror (0-9)" + }, + "specialCharacters": { + "message": "Specialtecken (!@#$%^&*)" + }, + "numWords": { + "message": "Antal ord" + }, + "wordSeparator": { + "message": "Ordseparator" + }, + "capitalize": { + "message": "Versalisera", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inkludera siffra" + }, + "minNumbers": { + "message": "Minst antal nummer" + }, + "minSpecial": { + "message": "Minst antal speciella tecken" + }, + "avoidAmbChar": { + "message": "Undvik mångtydiga tecken" + }, + "searchVault": { + "message": "Sök i valvet" + }, + "edit": { + "message": "Redigera" + }, + "view": { + "message": "Visa" + }, + "noItemsInList": { + "message": "Det finns inga objekt att visa." + }, + "itemInformation": { + "message": "Objektinformation" + }, + "username": { + "message": "Användarnamn" + }, + "password": { + "message": "Lösenord" + }, + "passphrase": { + "message": "Lösenordsfras" + }, + "favorite": { + "message": "Favorit" + }, + "notes": { + "message": "Anteckningar" + }, + "note": { + "message": "Anteckning" + }, + "editItem": { + "message": "Redigera objekt" + }, + "folder": { + "message": "Mapp" + }, + "deleteItem": { + "message": "Radera objekt" + }, + "viewItem": { + "message": "Visa objekt" + }, + "launch": { + "message": "Öppna" + }, + "website": { + "message": "Webbsida" + }, + "toggleVisibility": { + "message": "Växla synlighet" + }, + "manage": { + "message": "Hantera" + }, + "other": { + "message": "Annat" + }, + "rateExtension": { + "message": "Betygsätt tillägget" + }, + "rateExtensionDesc": { + "message": "Överväg gärna att hjälpa oss genom att ge oss en bra recension!" + }, + "browserNotSupportClipboard": { + "message": "Din webbläsare har inte stöd för att enkelt kopiera till urklipp. Kopiera till urklipp manuellt istället." + }, + "verifyIdentity": { + "message": "Verifiera identitet" + }, + "yourVaultIsLocked": { + "message": "Ditt valv är låst. Verifiera din identitet för att fortsätta." + }, + "unlock": { + "message": "Lås upp" + }, + "loggedInAsOn": { + "message": "Inloggad som $EMAIL$ på $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Felaktigt huvudlösenord" + }, + "vaultTimeout": { + "message": "Valvets tidsgräns" + }, + "lockNow": { + "message": "Lås nu" + }, + "immediately": { + "message": "Omedelbart" + }, + "tenSeconds": { + "message": "10 sekunder" + }, + "twentySeconds": { + "message": "20 sekunder" + }, + "thirtySeconds": { + "message": "30 sekunder" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minuter" + }, + "fiveMinutes": { + "message": "5 minuter" + }, + "fifteenMinutes": { + "message": "15 minuter" + }, + "thirtyMinutes": { + "message": "30 minuter" + }, + "oneHour": { + "message": "1 timme" + }, + "fourHours": { + "message": "4 timmar" + }, + "onLocked": { + "message": "Vid låsning av datorn" + }, + "onRestart": { + "message": "Vid omstart" + }, + "never": { + "message": "Aldrig" + }, + "security": { + "message": "Säkerhet" + }, + "errorOccurred": { + "message": "Ett fel har uppstått" + }, + "emailRequired": { + "message": "E-postadress krävs." + }, + "invalidEmail": { + "message": "Ogiltig e-postadress." + }, + "masterPassRequired": { + "message": "Huvudlösenord krävs." + }, + "masterPassLength": { + "message": "Huvudlösenordet måste vara minst 8 tecken långt." + }, + "masterPassDoesntMatch": { + "message": "Bekräftelsen för huvudlösenordet stämde ej." + }, + "newAccountCreated": { + "message": "Ditt nya konto har blivit skapat! Du kan nu logga in." + }, + "masterPassSent": { + "message": "Vi har skickat ett mejl till dig med din huvudlösenordsledtråd." + }, + "verificationCodeRequired": { + "message": "Verifieringskod krävs." + }, + "invalidVerificationCode": { + "message": "Ogiltig verifieringskod" + }, + "valueCopied": { + "message": "$VALUE$ kopierat", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Kunde inte automatiskt fylla i det valda objektet på den här webbsidan. Klipp/klistra informationen istället." + }, + "loggedOut": { + "message": "Loggade ut" + }, + "loginExpired": { + "message": "Din inloggningssession har utgått." + }, + "logOutConfirmation": { + "message": "Är du säker på att du vill logga ut?" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nej" + }, + "unexpectedError": { + "message": "Ett okänt fel har inträffat." + }, + "nameRequired": { + "message": "Namn krävs." + }, + "addedFolder": { + "message": "Skapade mapp" + }, + "changeMasterPass": { + "message": "Ändra huvudlösenord" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kan ändra ditt huvudlösenord på bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "twoStepLoginConfirmation": { + "message": "Tvåstegsverifiering gör ditt konto säkrare genom att kräva att du verifierar din inloggning med en annan enhet, till exempel genom en säkerhetsnyckel, autentiseringsapp, SMS, telefonsamtal eller mejl. Tvåstegsverifiering kan aktiveras på bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "editedFolder": { + "message": "Ändrade mapp" + }, + "deleteFolderConfirmation": { + "message": "Är du säker på att du vill ta bort den här mappen?" + }, + "deletedFolder": { + "message": "Tog bort mapp" + }, + "gettingStartedTutorial": { + "message": "Komma igång - Handledning" + }, + "gettingStartedTutorialVideo": { + "message": "Titta på vår 'Komma igång - Handledning'-video för att lära dig hur du får ut det mesta av webbläsartillägget." + }, + "syncingComplete": { + "message": "Synkronisering genomförd" + }, + "syncingFailed": { + "message": "Synkroniseringen misslyckades" + }, + "passwordCopied": { + "message": "Lösenord kopierat" + }, + "uri": { + "message": "URI (länk)" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Ny URI" + }, + "addedItem": { + "message": "Skapade objekt" + }, + "editedItem": { + "message": "Ändrade objekt" + }, + "deleteItemConfirmation": { + "message": "Är du säker på att du vill radera detta objekt?" + }, + "deletedItem": { + "message": "Raderade objekt" + }, + "overwritePassword": { + "message": "Skriv över lösenord" + }, + "overwritePasswordConfirmation": { + "message": "Är du säker på att du vill skriva över det nuvarande lösenordet?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Sök i mapp" + }, + "searchCollection": { + "message": "Sök i samling" + }, + "searchType": { + "message": "Sök efter typ" + }, + "noneFolder": { + "message": "Ingen mapp", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Inaktivera aviseringar för nya inloggningar" + }, + "addLoginNotificationDesc": { + "message": "Aviseringar för nya inloggningar frågar dig om du vill lägga till en inloggning automatiskt till ditt valv, när du använder en inloggning som inte redan finns i ditt valv." + }, + "dontShowCardsCurrentTab": { + "message": "Visa inte kort på fliksida" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Kortobjekt från ditt valv listas på 'nuvarande flik'-sidan för enkel automatisk ifyllnad." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Visa inte identiteter på fliksidan" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identitetsobjekt från ditt valv listas på 'nuvarande flik'-sidan för enkel automatisk ifyllnad." + }, + "clearClipboard": { + "message": "Rensa urklipp", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Rensa automatiskt kopierade värden från urklipp.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Ska Bitwarden komma ihåg det här lösenordet åt dig?" + }, + "notificationAddSave": { + "message": "Spara" + }, + "disableChangedPasswordNotification": { + "message": "Inaktivera notifikation för ändrade lösenord" + }, + "disableChangedPasswordNotificationDesc": { + "message": "”Notifikation för ändrade lösenord” uppmanar dig automatiskt att uppdatera ett lösenord i ditt valv när den upptäcker att du har ändrat det på en webbplats." + }, + "notificationChangeDesc": { + "message": "Vill du uppdatera det här lösenordet i Bitwarden?" + }, + "notificationChangeSave": { + "message": "Uppdatera" + }, + "disableContextMenuItem": { + "message": "Inaktivera innehållsmenyn" + }, + "disableContextMenuItemDesc": { + "message": "Innehållsmenyn (högerklick) ger dig snabbare åtkomst för att skapa ett slumpmässigt lösenord, och för att fylla i en inloggning i den nuvarande fliken." + }, + "defaultUriMatchDetection": { + "message": "Standardmatchning för URI", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Välj standardalternativet för hur matchning av URI är hanterat för inloggningar när du utför operationer såsom automatisk ifyllnad." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Ändra programmets färgtema." + }, + "dark": { + "message": "Mörkt", + "description": "Dark color" + }, + "light": { + "message": "Ljust", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Exportera valv" + }, + "fileFormat": { + "message": "Filformat" + }, + "warning": { + "message": "VARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Bekräfta export av valv" + }, + "exportWarningDesc": { + "message": "Den här exporten innehåller ditt valvs okrypterade data i .csv-format. Du bör inte lagra eller skicka filen över osäkra anslutningar (genom t.ex. mejl). Radera filen efter du är färdig med den." + }, + "encExportKeyWarningDesc": { + "message": "Denna export krypterar dina data med kontots krypteringsnyckel. Om du någonsin roterar kontots krypteringsnyckel bör du exportera igen eftersom du inte kommer att kunna dekryptera denna exportfil." + }, + "encExportAccountWarningDesc": { + "message": "Kypteringsnycklar är unika för varje Bitwarden-konto, så du kan inte importera en krypterad export till ett annat konto." + }, + "exportMasterPassword": { + "message": "Ange ditt huvudlösenord för att exportera ditt valv." + }, + "shared": { + "message": "Delad" + }, + "learnOrg": { + "message": "Lär dig om organisationer" + }, + "learnOrgConfirmation": { + "message": "Bitwarden gör det möjligt för dig att objekt i valvet med andra genom att använda en organisation. Vill du besöka bitwarden.com för att lära dig mer?" + }, + "moveToOrganization": { + "message": "Flytta till organisation" + }, + "share": { + "message": "Dela" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ flyttades till $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Välj en organisation som du vill flytta detta objektet till. Flytt till en organisation överför ägandet av objektet till den organisationen. Du kommer inte längre att vara direkt ägare till detta objekt när det har flyttats." + }, + "learnMore": { + "message": "Läs mer" + }, + "authenticatorKeyTotp": { + "message": "Autentiseringsnyckel (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verifieringskod (TOTP)" + }, + "copyVerificationCode": { + "message": "Kopiera verifieringskod" + }, + "attachments": { + "message": "Bifogade filer" + }, + "deleteAttachment": { + "message": "Ta bort bilaga" + }, + "deleteAttachmentConfirmation": { + "message": "Är du säker på att du vill ta bort bilagan?" + }, + "deletedAttachment": { + "message": "Tog bort bilaga" + }, + "newAttachment": { + "message": "Bifoga ny fil" + }, + "noAttachments": { + "message": "Inga bilagor." + }, + "attachmentSaved": { + "message": "Den bifogade filen har sparats." + }, + "file": { + "message": "Fil" + }, + "selectFile": { + "message": "Välj en fil." + }, + "maxFileSize": { + "message": "Filen får vara maximalt 500 MB." + }, + "featureUnavailable": { + "message": "Funktionen är inte tillgänglig" + }, + "updateKey": { + "message": "Du kan inte använda denna funktion förrän du uppdaterar din krypteringsnyckel." + }, + "premiumMembership": { + "message": "Premium-medlemskap" + }, + "premiumManage": { + "message": "Hantera medlemskap" + }, + "premiumManageAlert": { + "message": "Du kan hantera ditt medlemskap på bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "premiumRefresh": { + "message": "Uppdatera medlemskap" + }, + "premiumNotCurrentMember": { + "message": "Du är för närvarande inte en premium-medlem." + }, + "premiumSignUpAndGet": { + "message": "Registrera dig för ett premium-medlemskap och få:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB lagring av krypterade filer." + }, + "ppremiumSignUpTwoStep": { + "message": "Ytterligare alternativ för tvåstegsverifiering såsom YubiKey, FIDO U2F och Duo." + }, + "ppremiumSignUpReports": { + "message": "Lösenordshygien, kontohälsa och dataintrångsrapporter för att hålla ditt valv säkert." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verifieringskod-generator (2FA) för inloggningar i ditt valv." + }, + "ppremiumSignUpSupport": { + "message": "Prioriterad kundsupport." + }, + "ppremiumSignUpFuture": { + "message": "Alla framtida premium-funktioner. Mer kommer snart!" + }, + "premiumPurchase": { + "message": "Köp Premium" + }, + "premiumPurchaseAlert": { + "message": "Du kan köpa premium-medlemskap på bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "premiumCurrentMember": { + "message": "Du är en premium-medlem!" + }, + "premiumCurrentMemberThanks": { + "message": "Tack för att du stödjer Bitwarden." + }, + "premiumPrice": { + "message": "Allt för endast $PRICE$/år!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Uppdatering färdig" + }, + "disableAutoTotpCopy": { + "message": "Inaktivera automatisk TOTP-kopiering" + }, + "disableAutoTotpCopyDesc": { + "message": "Om din inloggning har en autentiseringsnyckel kopplad till den, kommer TOTP-verifieringskoden att automatiskt kopieras till urklipp när du automatiskt fyller i inloggningen." + }, + "disableAutoBiometricsPrompt": { + "message": "Fråga inte efter biometri vid uppstart" + }, + "premiumRequired": { + "message": "Premium krävs" + }, + "premiumRequiredDesc": { + "message": "Ett premium-medlemskap krävs för att använda den här funktionen." + }, + "enterVerificationCodeApp": { + "message": "Ange den 6-siffriga verifieringskoden från din autentiseringsapp." + }, + "enterVerificationCodeEmail": { + "message": "Ange den 6-siffriga verifieringskoden som skickades till $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verifieringsmejl skickat till $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Kom ihåg mig" + }, + "sendVerificationCodeEmailAgain": { + "message": "Skicka verifieringskod-mejlet igen" + }, + "useAnotherTwoStepMethod": { + "message": "Använd en annan inloggningsmetod för tvåstegsverifiering" + }, + "insertYubiKey": { + "message": "Sätt i din YubiKey i en av datorns USB-portar och sätt fingret på knappen." + }, + "insertU2f": { + "message": "Sätt i din säkerhetsnyckel i en av datorns USB-portar. Om nyckeln har en knapp, sätt fingret på den." + }, + "webAuthnNewTab": { + "message": "För att påbörja verifieringen av WebAuthn 2FA. Klicka på knappen nedan för att öppna en ny flik och följ instruktionerna i den nya fliken." + }, + "webAuthnNewTabOpen": { + "message": "Öppna ny flik" + }, + "webAuthnAuthenticate": { + "message": "Autentisera WebAuthn" + }, + "loginUnavailable": { + "message": "Inloggning inte tillgänglig" + }, + "noTwoStepProviders": { + "message": "Detta konto har tvåstegsverifiering aktiverat, men inget av de aktiverade alternativen stöds av den här webbläsaren." + }, + "noTwoStepProviders2": { + "message": "Vänligen använd en webbläsare som stöds (till exempel Chrome) och/eller lägg till fler alternativ som stöds bättre över webbläsare (till exempel en autentiseringsapp)." + }, + "twoStepOptions": { + "message": "Alternativ för tvåstegsverifiering" + }, + "recoveryCodeDesc": { + "message": "Förlorat åtkomst till alla dina tvåstegsverifierings-alternativ? Använd din återställningskod för att inaktivera tvåstegsverifiering på ditt konto." + }, + "recoveryCodeTitle": { + "message": "Återställningskod" + }, + "authenticatorAppTitle": { + "message": "Autentiseringsapp" + }, + "authenticatorAppDesc": { + "message": "Använd en autentiseringsapp (till exempel Authy eller Google Authenticator) för att skapa tidsbaserade verifieringskoder.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP säkerhetsnyckel" + }, + "yubiKeyDesc": { + "message": "Använd en YubiKey för att få åtkomst till ditt konto. Fungerar med YubiKey 4, 4 Nano, 4C och NEO enheter." + }, + "duoDesc": { + "message": "Verifiera med Duo Security genom att använda Duo Mobile-appen, SMS, telefonsamtal eller en U2F säkerhetsnyckel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifiera med Duo Security för din organisation genom att använda Duo Mobile-appen, SMS, telefonsamtal eller en U2F säkerhetsnyckel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Använd en WebAuthn-aktiverad säkerhetsnyckel för att komma åt ditt konto." + }, + "emailTitle": { + "message": "E-post" + }, + "emailDesc": { + "message": "Verifieringskoder kommer att skickas till dig." + }, + "selfHostedEnvironment": { + "message": "Egen-hostad miljö" + }, + "selfHostedEnvironmentFooter": { + "message": "Ange bas-URL:en för din \"on-premise\"-hostade Bitwarden-installation." + }, + "customEnvironment": { + "message": "Anpassad miljö" + }, + "customEnvironmentFooter": { + "message": "För avancerade användare. Du kan ange bas-URL:en för varje tjänst oberoende av varandra." + }, + "baseUrl": { + "message": "Server-URL" + }, + "apiUrl": { + "message": "API server-URL" + }, + "webVaultUrl": { + "message": "Webbvalv server-URL" + }, + "identityUrl": { + "message": "Identitetsserver-URL" + }, + "notificationsUrl": { + "message": "URL för notifieringsserver" + }, + "iconsUrl": { + "message": "Ikoner Server-URL" + }, + "environmentSaved": { + "message": "Miljö-URL:er har sparats." + }, + "enableAutoFillOnPageLoad": { + "message": "Aktivera automatisk ifyllnad vid sidhämtning" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Utför automatisk ifyllnad om ett inloggningsformulär upptäcks när webbsidan laddas." + }, + "experimentalFeature": { + "message": "Detta är för närvarande en experimentell funktion. Använd på egen risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Standardinställning för autofyll för inloggningsobjekt" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Efter att du har aktiverat automatisk ifyllnad vid sidhämtning kan du aktivera eller inaktivera funktionen för enskilda inloggningsobjekt. Detta är standardinställningen för inloggningsobjekt som inte är konfigurerade separat." + }, + "itemAutoFillOnPageLoad": { + "message": "Automatisk ifyllning vid sidhämtning (om aktiverat i Alternativ)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Använd standardinställningen" + }, + "autoFillOnPageLoadYes": { + "message": "Fyll i automatiskt vid sidladdning" + }, + "autoFillOnPageLoadNo": { + "message": "Fyll inte i automatiskt vid sidladdning" + }, + "commandOpenPopup": { + "message": "Öppna valvet i ett popupfönster" + }, + "commandOpenSidebar": { + "message": "Öppna valvet i sidofältet" + }, + "commandAutofillDesc": { + "message": "Fyll automatiskt i den senast använda inloggningen för den aktuella webbsidan" + }, + "commandGeneratePasswordDesc": { + "message": "Skapa och kopiera ett nytt slumpmässigt lösenord till urklipp." + }, + "commandLockVaultDesc": { + "message": "Lås valvet" + }, + "privateModeWarning": { + "message": "Stöd för privat läge är experimentellt och vissa funktioner är begränsade." + }, + "customFields": { + "message": "Anpassade fält" + }, + "copyValue": { + "message": "Kopiera värde" + }, + "value": { + "message": "Värde" + }, + "newCustomField": { + "message": "Nytt anpassat fält" + }, + "dragToSort": { + "message": "Dra för att sortera" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Dold" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Länkat", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Länkat värde", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Om du klickar utanför popup-fönstret för att kontrollera din email efter din verifieringskod så stängs popup-fönstret. Vill du öppna popup-fönstret i ett nytt fönster, så att det inte stängs?" + }, + "popupU2fCloseMessage": { + "message": "Den här webbläsaren kan inte bearbeta U2F-förfrågningar i detta popup-fönster. Vill du öppna ett nytt fönster så att du kan logga in med U2F?" + }, + "disableFavicon": { + "message": "Inaktivera webbplatsikoner" + }, + "disableFaviconDesc": { + "message": "Webbplatsikoner ger en igenkännbar ikon bredvid varje inloggningsobjekt i ditt valv." + }, + "disableBadgeCounter": { + "message": "Inaktivera märkesräknare" + }, + "disableBadgeCounterDesc": { + "message": "Märkesräknare visar hur många inloggningar du har för den aktuella sidan i ditt valv." + }, + "cardholderName": { + "message": "Kortinnehavarens namn" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Märke" + }, + "expirationMonth": { + "message": "Förfallomånad" + }, + "expirationYear": { + "message": "Förfalloår" + }, + "expiration": { + "message": "Utgång" + }, + "january": { + "message": "Januari" + }, + "february": { + "message": "Februari" + }, + "march": { + "message": "Mars" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "Augusti" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "securityCode": { + "message": "Säkerhetskod" + }, + "ex": { + "message": "t.ex." + }, + "title": { + "message": "Titel" + }, + "mr": { + "message": "Herr" + }, + "mrs": { + "message": "Fru" + }, + "ms": { + "message": "Fröken" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Förnamn" + }, + "middleName": { + "message": "Mellannamn" + }, + "lastName": { + "message": "Efternamn" + }, + "fullName": { + "message": "Fullständigt namn" + }, + "identityName": { + "message": "Identitetsnamn" + }, + "company": { + "message": "Företag" + }, + "ssn": { + "message": "Personnummer" + }, + "passportNumber": { + "message": "Passnummer" + }, + "licenseNumber": { + "message": "Licensnummer" + }, + "email": { + "message": "E-post" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adress" + }, + "address1": { + "message": "Adress 1" + }, + "address2": { + "message": "Adress 2" + }, + "address3": { + "message": "Adress 3" + }, + "cityTown": { + "message": "Ort" + }, + "stateProvince": { + "message": "Län" + }, + "zipPostalCode": { + "message": "Postnummer" + }, + "country": { + "message": "Land" + }, + "type": { + "message": "Typ" + }, + "typeLogin": { + "message": "Inloggning" + }, + "typeLogins": { + "message": "Inloggningar" + }, + "typeSecureNote": { + "message": "Säker anteckning" + }, + "typeCard": { + "message": "Kort" + }, + "typeIdentity": { + "message": "Identitet" + }, + "passwordHistory": { + "message": "Lösenordshistorik" + }, + "back": { + "message": "Tillbaka" + }, + "collections": { + "message": "Samlingar" + }, + "favorites": { + "message": "Favoriter" + }, + "popOutNewWindow": { + "message": "Poppa ut till ett nytt fönster" + }, + "refresh": { + "message": "Uppdatera" + }, + "cards": { + "message": "Kort" + }, + "identities": { + "message": "Identiteter" + }, + "logins": { + "message": "Inloggningar" + }, + "secureNotes": { + "message": "Säkra anteckningar" + }, + "clear": { + "message": "Rensa", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Kontrollera om lösenord har avslöjats." + }, + "passwordExposed": { + "message": "Detta lösenord har avslöjats $VALUE$ gång(er) i dataintrång. Du bör ändra det.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Detta lösenord hittades inte i något känt dataintrång. Det bör vara säkert att använda." + }, + "baseDomain": { + "message": "Basdomän", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domännamn", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Värd", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exakt" + }, + "startsWith": { + "message": "Börjar med" + }, + "regEx": { + "message": "Reguljärt uttryck", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Matchning", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standardmatchning", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Växla alternativ" + }, + "toggleCurrentUris": { + "message": "Växla nuvarande URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Nuvarande URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Typer" + }, + "allItems": { + "message": "Alla objekt" + }, + "noPasswordsInList": { + "message": "Det finns inga lösenord att lista." + }, + "remove": { + "message": "Ta bort" + }, + "default": { + "message": "Standard" + }, + "dateUpdated": { + "message": "Uppdaterad", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Lösenord uppdaterat", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Är du säker på att du vill använda alternativet ”Aldrig”? Att ställa in låsnings-alternativet till ”Aldrig” lagrar valvets krypteringsnyckel på datorn. Om du använder det här alternativet bör du se till att du håller datorn ordentligt skyddad." + }, + "noOrganizationsList": { + "message": "Du tillhör inte någon organisation. Organisationer möjliggör säker delning av objekt med andra användare." + }, + "noCollectionsInList": { + "message": "Det finns inga samlingar att visa." + }, + "ownership": { + "message": "Ägarskap" + }, + "whoOwnsThisItem": { + "message": "Vem äger detta objekt?" + }, + "strong": { + "message": "Starkt", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bra", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Svagt", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Svagt huvudlösenord" + }, + "weakMasterPasswordDesc": { + "message": "Huvudlösenordet du har valt är svagt. Du bör använda ett starkt huvudlösenord (eller en lösenfras) för att skydda ditt Bitwarden-konto ordentligt. Är du säker på att du vill använda detta huvudlösenord?" + }, + "pin": { + "message": "PIN-kod", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Lås upp med PIN-kod" + }, + "setYourPinCode": { + "message": "Ange en PIN-kod för att låsa upp Bitwarden. Dina PIN-inställningar återställs om du någonsin loggar ut helt från programmet." + }, + "pinRequired": { + "message": "PIN-kod krävs." + }, + "invalidPin": { + "message": "Ogiltig PIN-kod." + }, + "unlockWithBiometrics": { + "message": "Lås upp med biometri" + }, + "awaitDesktop": { + "message": "Väntar på bekräftelse från skrivbordsprogrammet" + }, + "awaitDesktopDesc": { + "message": "Säkerställ att du använder biometri i Bitwardens skrivbordsprogram för att aktivera biometri för webbläsaren." + }, + "lockWithMasterPassOnRestart": { + "message": "Lås med huvudlösenordet vid omstart av webbläsaren" + }, + "selectOneCollection": { + "message": "Du måste markera minst en samling." + }, + "cloneItem": { + "message": "Klona objekt" + }, + "clone": { + "message": "Klona" + }, + "passwordGeneratorPolicyInEffect": { + "message": "En eller flera organisationspolicyer påverkar dina generatorinställningar." + }, + "vaultTimeoutAction": { + "message": "Åtgärd när valvets tidsgräns överskrids" + }, + "lock": { + "message": "Lås", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papperskorgen", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Sök i papperskorgen" + }, + "permanentlyDeleteItem": { + "message": "Radera objekt permanent" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Är du säker på att du vill radera detta objekt permanent?" + }, + "permanentlyDeletedItem": { + "message": "Raderade objekt permanent" + }, + "restoreItem": { + "message": "Återställ objekt" + }, + "restoreItemConfirmation": { + "message": "Är du säker på att du vill återställa detta objekt?" + }, + "restoredItem": { + "message": "Återställde objekt" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Genom att logga ut upphör all åtkomst till valvet och onlineautentisering krävs efter att tidsgränsen överskridits. Är du säker på att du vill använda denna inställning?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bekräftelse av åtgärd när valvets tidsgräns överskrids" + }, + "autoFillAndSave": { + "message": "Fyll i automatiskt och spara" + }, + "autoFillSuccessAndSavedUri": { + "message": "Fyllde i objektet automatiskt och sparade URI:n" + }, + "autoFillSuccess": { + "message": "Fyllde i objektet automatiskt" + }, + "setMasterPassword": { + "message": "Ange huvudlösenord" + }, + "masterPasswordPolicyInEffect": { + "message": "En eller flera organisationspolicyer kräver att ditt huvudlösenord uppfyller följande krav:" + }, + "policyInEffectMinComplexity": { + "message": "Minsta komplexitetspoäng på $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minsta längd på $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Innehålla en eller flera versaler" + }, + "policyInEffectLowercase": { + "message": "Innehålla en eller flera gemener" + }, + "policyInEffectNumbers": { + "message": "Innehålla en eller flera siffror" + }, + "policyInEffectSpecial": { + "message": "Innehålla ett eller flera av följande specialtecken: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ditt nya huvudlösenord uppfyller inte kraven i policyn." + }, + "acceptPolicies": { + "message": "Genom att markera denna ruta godkänner du följande:" + }, + "acceptPoliciesError": { + "message": "Användarvillkoren och Integritetspolicyn har inte accepterats." + }, + "termsOfService": { + "message": "Användarvillkor" + }, + "privacyPolicy": { + "message": "Integritetspolicy" + }, + "hintEqualsPassword": { + "message": "Din lösenordsledtråd får inte vara samma som ditt lösenord." + }, + "ok": { + "message": "OK" + }, + "desktopSyncVerificationTitle": { + "message": "Verifiering av synkronisering med skrivbordsprogrammet" + }, + "desktopIntegrationVerificationText": { + "message": "Vänligen bekräfta att skrivbordsprogrammet visar det här fingeravtrycket: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Webbläsarintegration är inte aktiverad" + }, + "desktopIntegrationDisabledDesc": { + "message": "Webbläsarintegration är inte aktiverad i Bitwardens skrivbordsprogram. Aktivera det i inställningarna i skrivbordsprogrammet." + }, + "startDesktopTitle": { + "message": "Starta Bitwardens skrivbordsprogram" + }, + "startDesktopDesc": { + "message": "Bitwardens skrivbordsprogram måste köras innan denna funktion kan användas." + }, + "errorEnableBiometricTitle": { + "message": "Det gick inte att aktivera biometri" + }, + "errorEnableBiometricDesc": { + "message": "Åtgärden avbröts av skrivbordsprogrammet" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Skrivbordsprogrammet ogiltigförklarade den säkra kommunikationskanalen. Försök igen" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Kommunikationen med skrivbordsprogrammet avbröts" + }, + "nativeMessagingWrongUserDesc": { + "message": "Skrivbordsprogrammet är inloggat på ett annat konto. Se till att båda applikationerna är inloggade på samma konto." + }, + "nativeMessagingWrongUserTitle": { + "message": "Kontoavvikelse" + }, + "biometricsNotEnabledTitle": { + "message": "Biometri är inte aktiverat" + }, + "biometricsNotEnabledDesc": { + "message": "Biometri i webbläsaren kräver att biometri på skrivbordet aktiveras i inställningarna först." + }, + "biometricsNotSupportedTitle": { + "message": "Biometri stöds inte" + }, + "biometricsNotSupportedDesc": { + "message": "Biometri i webbläsaren stöds inte på den här enheten." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Behörighet ej beviljad" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Utan behörighet att kommunicera med Bitwardens skrivbordsprogram kan vi inte tillhandahålla biometri i webbläsartillägget. Försök igen." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Fel vid behörighetsbegäran" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Denna åtgärd kan inte utföras i sidofältet. Försök igen i popup- eller popout-fönstret." + }, + "personalOwnershipSubmitError": { + "message": "På grund av en av företagets policyer är du begränsad från att spara objekt till ditt personliga valv. Ändra ägarskap till en organisation och välj från tillgängliga samlingar." + }, + "personalOwnershipPolicyInEffect": { + "message": "En organisationspolicy påverkar dina ägarskapsalternativ." + }, + "excludedDomains": { + "message": "Exkluderade domäner" + }, + "excludedDomainsDesc": { + "message": "Bitwarden kommer inte att fråga om att få spara inloggningsuppgifter för dessa domäner. Du måste uppdatera sidan för att ändringarna ska träda i kraft." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ är inte en giltig domän", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Sök bland Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Lägg till Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Text" + }, + "sendTypeFile": { + "message": "Fil" + }, + "allSends": { + "message": "Alla Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Det maximala antalet åtkomster har uppnåtts", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Utgången" + }, + "pendingDeletion": { + "message": "Väntar på radering" + }, + "passwordProtected": { + "message": "Lösenordsskyddad" + }, + "copySendLink": { + "message": "Kopiera länk till Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Ta bort lösenord" + }, + "delete": { + "message": "Radera" + }, + "removedPassword": { + "message": "Tog bort lösenord" + }, + "deletedSend": { + "message": "Raderade Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Länk till Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Inaktiverad" + }, + "removePasswordConfirmation": { + "message": "Är du säker på att du vill ta bort lösenordet?" + }, + "deleteSend": { + "message": "Radera Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Är du säker på att du vill radera denna Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Redigera Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Vilken typ av Send är detta?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Ett eget namn för att beskriva denna Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Filen du vill skicka." + }, + "deletionDate": { + "message": "Raderingsdatum" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Utgångsdatum" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 dag" + }, + "days": { + "message": "$DAYS$ dagar", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Anpassad" + }, + "maximumAccessCount": { + "message": "Maximalt antal åtkomster" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Kräv eventuellt lösenord av användare för att komma åt denna Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privata anteckningar om denna Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Inaktivera denna Send så att ingen kan komma åt den.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Texten du vill skicka." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Nuvarande antal åtkomster" + }, + "createSend": { + "message": "Skapa ny Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nytt lösenord" + }, + "sendDisabled": { + "message": "Send inaktiverad", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "För att välja en fil, öppna tillägget i sidofältet (om möjligt) eller skapa ett nytt fönster genom att klicka på denna banner." + }, + "sendFirefoxFileWarning": { + "message": "För att välja en fil med Firefox, öppna tillägget i sidofältet eller öppna ett nytt fönster genom att klicka på denna banner." + }, + "sendSafariFileWarning": { + "message": "För att välja en fil med Safari, öppna ett nytt fönster genom att klicka på denna banner." + }, + "sendFileCalloutHeader": { + "message": "Innan du börjar" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "För att använda en datumväljare med kalenderstil", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "klicka här", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "för att öppna ett nytt fönster.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Det angivna utgångsdatumet är inte giltigt." + }, + "deletionDateIsInvalid": { + "message": "Det angivna raderingsdatumet är inte giltigt." + }, + "expirationDateAndTimeRequired": { + "message": "Ett utgångsdatum och tid krävs." + }, + "deletionDateAndTimeRequired": { + "message": "Ett raderingsdatum och tid krävs." + }, + "dateParsingError": { + "message": "Det gick inte att spara raderings- och utgångsdatum." + }, + "hideEmail": { + "message": "Dölj min e-postadress för mottagare." + }, + "sendOptionsPolicyInEffect": { + "message": "En eller flera organisationsriktlinjer påverkar dina Send-inställningar." + }, + "passwordPrompt": { + "message": "Återupprepa huvudlösenord" + }, + "passwordConfirmation": { + "message": "Bekräfta huvudlösenord" + }, + "passwordConfirmationDesc": { + "message": "Denna åtgärd är skyddad. För att fortsätta, vänligen verifiera din identitet genom att ange ditt huvudlösenord." + }, + "emailVerificationRequired": { + "message": "E-postverifiering krävs" + }, + "emailVerificationRequiredDesc": { + "message": "Du måste verifiera din e-postadress för att använda den här funktionen. Du kan verifiera din e-postadress i webbvalvet." + }, + "updatedMasterPassword": { + "message": "Huvudlösenord uppdaterades " + }, + "updateMasterPassword": { + "message": "Uppdatera huvudlösenord" + }, + "updateMasterPasswordWarning": { + "message": "Ditt huvudlösenord ändrades nyligen av en administratör i din organisation. För att få tillgång till valvet måste du uppdatera det nu. Om du fortsätter kommer du att loggas ut från din nuvarande session, vilket kräver att du loggar in igen. Aktiva sessioner på andra enheter kan komma att vara aktiva i upp till en timme." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatiskt deltagande" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Denna organisation har en företagspolicy som automatiskt registrerar dig för lösenordsåterställning. Deltagandet gör det möjligt för organisationsadministratörer att ändra ditt huvudlösenord." + }, + "selectFolder": { + "message": "Välj mapp…" + }, + "ssoCompleteRegistration": { + "message": "För att slutföra inloggning med SSO, ange ett huvudlösenord för att komma åt och skydda ditt valv." + }, + "hours": { + "message": "Timmar" + }, + "minutes": { + "message": "Minuter" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Dina organisationsprinciper påverkar ditt valvs tid för timeout. Maximal tillåten tid innan timeout är $HOURS$ timmar och $MINUTES$ minuter", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Ditt valvs tid för timeout överskrider de begränsningar som fastställts av din organisation." + }, + "vaultExportDisabled": { + "message": "Valvexport inaktiverad" + }, + "personalVaultExportPolicyInEffect": { + "message": "En eller flera organisationsprinciper hindrar dig från att exportera ditt personliga valv." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Det gick inte att identifiera något giltigt formulärelement. Prova att inspektera HTML-koden istället." + }, + "copyCustomFieldNameNotUnique": { + "message": "Ingen unik identifierare hittades." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ använder SSO med en egen nyckelserver. Ett huvudlösenord krävs inte längre för att logga in för medlemmar i denna organisation.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Lämna organisation" + }, + "removeMasterPassword": { + "message": "Ta bort huvudlösenord" + }, + "removedMasterPassword": { + "message": "Huvudlösenord togs bort." + }, + "leaveOrganizationConfirmation": { + "message": "Är du säker på att du vill lämna denna organisation?" + }, + "leftOrganization": { + "message": "Du har lämnat organisationen." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Din session har gått ut. Gå tillbaka och försök logga in igen." + }, + "exportingPersonalVaultTitle": { + "message": "Exportera personligt valv" + }, + "exportingPersonalVaultDescription": { + "message": "Endast de personliga valvobjekt som är associerade med $EMAIL$ kommer att exporteras. Organisationens valv kommer inte att inkluderas.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Fel" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/th/messages.json b/apps/browser/src/_locales/th/messages.json new file mode 100644 index 0000000000..4a02eb6ef6 --- /dev/null +++ b/apps/browser/src/_locales/th/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "bitwarden" + }, + "extName": { + "message": "bitwarden - Free Password Manager", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "bitwarden is a secure and free password manager for all of your devices.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "ล็อกอิน หรือ สร้างบัญชีใหม่ เพื่อใช้งานตู้นิรภัยของคุณ" + }, + "createAccount": { + "message": "สร้างบัญชี" + }, + "login": { + "message": "เข้าสู่ระบบ" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "cancel": { + "message": "ยกเลิก" + }, + "close": { + "message": "ปิด" + }, + "submit": { + "message": "ส่งข้อมูล" + }, + "emailAddress": { + "message": "ที่อยู่อีเมล" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "รหัสผ่านหลัก คือ รหัสผ่านที่ใช้เข้าถึงตู้นิรภัยของคุณ สิ่งสำคัญมาก คือ คุณจะต้องไม่ลืมรหัสผ่านหลักโดยเด็ดขาด เพราะหากคุณลืมแล้วล่ะก็ จะไม่มีวิธีที่สามารถกู้รหัสผ่านของคุณได้เลย" + }, + "masterPassHintDesc": { + "message": "คำใบ้เกี่ยวกับรหัสผ่านหลักสามารถช่วยให้คุณนึกรหัสผ่านหลักออกได้หากลืม" + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "tab": { + "message": "แท็บ" + }, + "myVault": { + "message": "My Vault" + }, + "tools": { + "message": "เครื่องมือ" + }, + "settings": { + "message": "การตั้งค่า" + }, + "currentTab": { + "message": "แท็บปัจจุบัน" + }, + "copyPassword": { + "message": "คัดลอกรหัสผ่าน" + }, + "copyNote": { + "message": "Copy Note" + }, + "copyUri": { + "message": "คัดลอก URI" + }, + "copyUsername": { + "message": "คัดลอกชื่อผู้ใช้" + }, + "copyNumber": { + "message": "คัดลอกหมายเลข" + }, + "copySecurityCode": { + "message": "คัดลอกรหัสรักษาความปลอดภัย" + }, + "autoFill": { + "message": "กรอกข้อมูลอัตโนมัติ" + }, + "generatePasswordCopied": { + "message": "Generate Password (copied)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "ไม่พบข้อมูลล็อกอินที่ตรงกัน" + }, + "unlockVaultMenu": { + "message": "Unlock your vault" + }, + "loginToVaultMenu": { + "message": "Log in to your vault" + }, + "autoFillInfo": { + "message": "ไม่พบข้อมูลล็อกอินเพื่อใช้กรอกข้อมูลอัตโนมัติ สำหรับแท็บปัจจุบันของเบราว์เซอร์" + }, + "addLogin": { + "message": "Add a Login" + }, + "addItem": { + "message": "เพิ่มรายการ" + }, + "passwordHint": { + "message": "คำใบ้รหัสผ่าน" + }, + "enterEmailToGetHint": { + "message": "กรอกอีเมลของบัญชีของคุณ เพื่อรับคำใบ้เกี่ยวกับรหัสผ่านหลักของคุณ" + }, + "getMasterPasswordHint": { + "message": "รับคำใบ้เกี่ยวกับรหัสผ่านหลักของคุณ" + }, + "continue": { + "message": "ดำเนินการต่อไป" + }, + "sendVerificationCode": { + "message": "ส่งโค้ดยืนยันไปยังอีเมลของคุณ" + }, + "sendCode": { + "message": "ส่งโค้ด" + }, + "codeSent": { + "message": "ส่งโค้ดแล้ว" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "ยืนยันตัวตนของคุณเพื่อดำเนินการต่อ" + }, + "account": { + "message": "บัญชี" + }, + "changeMasterPassword": { + "message": "Change Master Password" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "logOut": { + "message": "ออกจากระบบ" + }, + "about": { + "message": "เกี่ยวกับ" + }, + "version": { + "message": "เวอร์ชัน" + }, + "save": { + "message": "บันทึก" + }, + "move": { + "message": "ย้าย" + }, + "addFolder": { + "message": "เพิ่มโฟลเดอร์" + }, + "name": { + "message": "ชื่อ" + }, + "editFolder": { + "message": "แก้ไขโฟลเดอร์" + }, + "deleteFolder": { + "message": "ลบโฟลเดอร์" + }, + "folders": { + "message": "โฟลเดอร์" + }, + "noFolders": { + "message": "ไม่มีโฟลเดอร์" + }, + "helpFeedback": { + "message": "Help & Feedback" + }, + "sync": { + "message": "ซิงค์" + }, + "syncVaultNow": { + "message": "Sync Vault Now" + }, + "lastSync": { + "message": "Last Sync:" + }, + "passGen": { + "message": "Password Generator" + }, + "generator": { + "message": "สุ่มรหัส", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Automatically generate strong, unique passwords for your logins." + }, + "bitWebVault": { + "message": "bitwarden Web Vault" + }, + "importItems": { + "message": "Import Items" + }, + "select": { + "message": "เลือก" + }, + "generatePassword": { + "message": "Generate Password" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "options": { + "message": "ตัวเลือก" + }, + "length": { + "message": "ความยาว" + }, + "uppercase": { + "message": "ตัวพิมพ์ใหญ่ (A-Z)" + }, + "lowercase": { + "message": "ตัวพิมพ์เล็ก (a-z)" + }, + "numbers": { + "message": "ตัวเลข (0-9)" + }, + "specialCharacters": { + "message": "อักขระพิเศษ (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "ขึ้นต้นด้วยตัวพิมพ์ใหญ่", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "ต่อท้ายด้วยตัวเลข" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special" + }, + "avoidAmbChar": { + "message": "Avoid Ambiguous Characters" + }, + "searchVault": { + "message": "ค้นหาในตู้นิรภัย" + }, + "edit": { + "message": "แก้ไข" + }, + "view": { + "message": "แสดง" + }, + "noItemsInList": { + "message": "ไม่มีรายการ" + }, + "itemInformation": { + "message": "Item Information" + }, + "username": { + "message": "ชื่อผู้ใช้" + }, + "password": { + "message": "รหัสผ่าน" + }, + "passphrase": { + "message": "Passphrase" + }, + "favorite": { + "message": "รายการโปรด" + }, + "notes": { + "message": "โน้ต" + }, + "note": { + "message": "โน้ต" + }, + "editItem": { + "message": "แก้ไขรายการ" + }, + "folder": { + "message": "โฟลเดอร์" + }, + "deleteItem": { + "message": "ลบรายการ" + }, + "viewItem": { + "message": "ดูรายการ" + }, + "launch": { + "message": "เริ่ม" + }, + "website": { + "message": "เว็บไซต์" + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "manage": { + "message": "จัดการ" + }, + "other": { + "message": "อื่น ๆ" + }, + "rateExtension": { + "message": "Rate the Extension" + }, + "rateExtensionDesc": { + "message": "Please consider helping us out with a good review!" + }, + "browserNotSupportClipboard": { + "message": "Your web browser does not support easy clipboard copying. Copy it manually instead." + }, + "verifyIdentity": { + "message": "ยืนยันตัวตน" + }, + "yourVaultIsLocked": { + "message": "ตู้เซฟของคุณถูกล็อก ยืนยันตัวตนของคุณเพื่อดำเนินการต่อ" + }, + "unlock": { + "message": "ปลดล็อค" + }, + "loggedInAsOn": { + "message": "ล็อกอินด้วย $EMAIL$ บน $HOSTNAME$", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "รหัสผ่านหลักไม่ถูกต้อง" + }, + "vaultTimeout": { + "message": "ระยะเวลาล็อกตู้เซฟ" + }, + "lockNow": { + "message": "Lock Now" + }, + "immediately": { + "message": "ทันที" + }, + "tenSeconds": { + "message": "10 วินาที" + }, + "twentySeconds": { + "message": "20 วินาที" + }, + "thirtySeconds": { + "message": "30 วินาที" + }, + "oneMinute": { + "message": "1 นาที" + }, + "twoMinutes": { + "message": "2 นาที" + }, + "fiveMinutes": { + "message": "5 นาที" + }, + "fifteenMinutes": { + "message": "15 นาที" + }, + "thirtyMinutes": { + "message": "30 นาที" + }, + "oneHour": { + "message": "1 ชั่วโมง" + }, + "fourHours": { + "message": "4 ชั่วโมง" + }, + "onLocked": { + "message": "On Locked" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "ไม่อีกเลย" + }, + "security": { + "message": "ความปลอดภัย" + }, + "errorOccurred": { + "message": "พบข้อผิดพลาด" + }, + "emailRequired": { + "message": "ต้องระบุอีเมล" + }, + "invalidEmail": { + "message": "ที่อยู่อีเมลไม่ถูกต้อง" + }, + "masterPassRequired": { + "message": "ต้องระบุรหัสผ่านหลัก" + }, + "masterPassLength": { + "message": "รหัสผ่านหลักต้องมีความยาวอย่างน้อย 8 อักขระ" + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "verificationCodeRequired": { + "message": "ต้องระบุโค้ดยืนยัน" + }, + "invalidVerificationCode": { + "message": "โค้ดยืนยันไม่ถูกต้อง" + }, + "valueCopied": { + "message": " copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Unable to auto-fill the selected login on this page. Copy/paste your username and/or password instead." + }, + "loggedOut": { + "message": "ออกจากระบบ" + }, + "loginExpired": { + "message": "เซสชันของคุณหมดอายุแล้ว" + }, + "logOutConfirmation": { + "message": "คุณต้องการล็อกเอาต์ใช่หรือไม่?" + }, + "yes": { + "message": "ใช่" + }, + "no": { + "message": "ไม่ใช่" + }, + "unexpectedError": { + "message": "An unexpected error has occured." + }, + "nameRequired": { + "message": "ต้องระบุชื่อ" + }, + "addedFolder": { + "message": "เพิ่มโฟลเดอร์แล้ว" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "คุณสามารถเปลี่ยนรหัสผ่านหลักได้ที่เว็บตู้เซฟ bitwarden.com คุณต้องการเปิดเว็บไซต์เลยหรือไม่?" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to enter a security code from an authenticator app whenever you log in. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "editedFolder": { + "message": "Edited Folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "ลบโฟลเดอร์แล้ว" + }, + "gettingStartedTutorial": { + "message": "Getting Started Tutorial" + }, + "gettingStartedTutorialVideo": { + "message": "Watch our getting started tutorial to learn how to get the most out of the browser extension." + }, + "syncingComplete": { + "message": "การซิงก์เสร็จสมบูรณ์" + }, + "syncingFailed": { + "message": "การซิงก์ล้มเหลว" + }, + "passwordCopied": { + "message": "คัดลอกรหัสผ่านแล้ว" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "เพิ่ม URI ใหม่" + }, + "addedItem": { + "message": "เพิ่มรายการแล้ว" + }, + "editedItem": { + "message": "แก้ไขรายการแล้ว" + }, + "deleteItemConfirmation": { + "message": "คุณต้องการส่งไปยังถังขยะใช่หรือไม่?" + }, + "deletedItem": { + "message": "ส่งรายการไปยังถังขยะแล้ว" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "overwritePasswordConfirmation": { + "message": "คุณต้องการเขียนทับรหัสผ่านปัจจุบันใช่หรือไม่?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "ค้นหาในโพลเดอร์" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchType": { + "message": "Search type" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Disable Add Login Notification" + }, + "addLoginNotificationDesc": { + "message": "The \"Add Login Notification\" automatically prompts you to save new logins to your vault whenever you log into them for the first time." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "ล้างคลิปบอร์ด", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Should bitwarden remember this password for you?" + }, + "notificationAddSave": { + "message": "Yes, Save Now" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "คุณต้องการอัปเดตรหัสผ่านนี้ใน Bitwarden หรือไม่?" + }, + "notificationChangeSave": { + "message": "Yes, Update Now" + }, + "disableContextMenuItem": { + "message": "Disable Context Menu Options" + }, + "disableContextMenuItemDesc": { + "message": "Context menu options provide quick access to password generation and logins for the website in your current tab." + }, + "defaultUriMatchDetection": { + "message": "Default URI Match Detection", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Choose the default way that URI match detection is handled for logins when performing actions such as auto-fill." + }, + "theme": { + "message": "ธีม" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "มืด", + "description": "Dark color" + }, + "light": { + "message": "สว่าง", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "คำเตือน", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "shared": { + "message": "แชร์แล้ว" + }, + "learnOrg": { + "message": "Learn about Organizations" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "share": { + "message": "แชร์" + }, + "movedItemToOrg": { + "message": "ย้าย $ITEMNAME$ ไปยัง $ORGNAME$ แล้ว", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Learn more" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "copyVerificationCode": { + "message": "Copy Verification Code" + }, + "attachments": { + "message": "ไฟล์แนบ" + }, + "deleteAttachment": { + "message": "ลบไฟล์แนบ" + }, + "deleteAttachmentConfirmation": { + "message": "คุณต้องการลบไฟล์แนบนี้ใช่หรือไม่?" + }, + "deletedAttachment": { + "message": "ลบไฟล์แนบแล้ว" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "noAttachments": { + "message": "ไม่มีไฟล์แนบ" + }, + "attachmentSaved": { + "message": "บันทึกไฟล์แนบแล้ว" + }, + "file": { + "message": "ไฟล์" + }, + "selectFile": { + "message": "เลือกไฟล์" + }, + "maxFileSize": { + "message": "ขนาดไฟล์สูงสุด คือ 500 MB" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB of encrypted file storage." + }, + "ppremiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "ppremiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "ppremiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "ppremiumSignUpSupport": { + "message": "Priority customer support." + }, + "ppremiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting bitwarden." + }, + "premiumPrice": { + "message": "All for just %price% /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "disableAutoTotpCopy": { + "message": "Disable Automatic TOTP Copy" + }, + "disableAutoTotpCopyDesc": { + "message": "If your login has an authenticator key attached to it, the TOTP verification code is automatically copied to your clipboard whenever you auto-fill the login." + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "ส่งโค้ดยืนยันไปยังอีเมล $EMAIL$ แล้ว", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "ส่งโค้ดยืนยันไปยังอีเมลอีกครั้ง" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Open new tab" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this web browser." + }, + "noTwoStepProviders2": { + "message": "Please use a supported web browser (such as Chrome) and/or add additional providers that are better supported across web browsers (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "อีเมล" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "URL ของเซิร์ฟเวอร์" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "enableAutoFillOnPageLoad": { + "message": "Enable Auto-fill On Page Load." + }, + "enableAutoFillOnPageLoadDesc": { + "message": "If a login form is detected, automatically perform an auto-fill when the web page loads." + }, + "experimentalFeature": { + "message": "This is currently an experimental feature. Use at your own risk." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Auto-fill on Page Load (if enabled in Options)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Use default setting" + }, + "autoFillOnPageLoadYes": { + "message": "Auto-fill on page load" + }, + "autoFillOnPageLoadNo": { + "message": "Do not auto-fill on page load" + }, + "commandOpenPopup": { + "message": "Open vault popup" + }, + "commandOpenSidebar": { + "message": "Open vault in sidebar" + }, + "commandAutofillDesc": { + "message": "Auto-fill the last used login for the current website." + }, + "commandGeneratePasswordDesc": { + "message": "Generate and copy a new random password to the clipboard." + }, + "commandLockVaultDesc": { + "message": "ล็อกตู้เซฟ" + }, + "privateModeWarning": { + "message": "Private mode support is experimental and some features are limited." + }, + "customFields": { + "message": "Custom Fields" + }, + "copyValue": { + "message": "Copy Value" + }, + "value": { + "message": "ค่า" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "ข้อความ" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Clicking outside the popup window to check your email for your verification code will cause this popup to close. Do you want to open this popup in a new window so that it does not close?" + }, + "popupU2fCloseMessage": { + "message": "This browser cannot process U2F requests in this popup window. Do you want to open this popup in a new window so that you can log in using U2F?" + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provides a recognizable icon next to each login item in your vault." + }, + "disableBadgeCounter": { + "message": "Disable Badge Counter" + }, + "disableBadgeCounterDesc": { + "message": "Badge counter indicates how many logins you have for the current page in your vault." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "หมายเลข" + }, + "brand": { + "message": "Brand" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "expiration": { + "message": "วันหมดอายุ" + }, + "january": { + "message": "มกราคม" + }, + "february": { + "message": "กุมภาพันธ์" + }, + "march": { + "message": "มีนาคม" + }, + "april": { + "message": "เมษายน" + }, + "may": { + "message": "พฤษภาคม" + }, + "june": { + "message": "มิถุนายน" + }, + "july": { + "message": "กรกฎาคม" + }, + "august": { + "message": "สิงหาคม" + }, + "september": { + "message": "กันยายน" + }, + "october": { + "message": "ตุลาคม" + }, + "november": { + "message": "พฤศจิกายน" + }, + "december": { + "message": "ธันวาคม" + }, + "securityCode": { + "message": "Security Code" + }, + "ex": { + "message": "ex." + }, + "title": { + "message": "คำนำหน้า" + }, + "mr": { + "message": "นาย" + }, + "mrs": { + "message": "นาง" + }, + "ms": { + "message": "นางสาว" + }, + "dr": { + "message": "ดร." + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "บริษัท" + }, + "ssn": { + "message": "หมายเลขประกันสังคม" + }, + "passportNumber": { + "message": "หมายเลขหนังสือเดินทาง" + }, + "licenseNumber": { + "message": "หมายเลขใบอนุญาต" + }, + "email": { + "message": "อีเมล" + }, + "phone": { + "message": "โทรศัพท์" + }, + "address": { + "message": "ที่อยู่" + }, + "address1": { + "message": "ที่อยู่ 1" + }, + "address2": { + "message": "ที่อยู่ 2" + }, + "address3": { + "message": "ที่อยู่ 3" + }, + "cityTown": { + "message": "เมือง" + }, + "stateProvince": { + "message": "รัฐ / จังหวัด" + }, + "zipPostalCode": { + "message": "รหัสไปรษณีย์" + }, + "country": { + "message": "ประเทศ" + }, + "type": { + "message": "Type" + }, + "typeLogin": { + "message": "ล็อกอิน" + }, + "typeLogins": { + "message": "ล็อกอิน" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "typeCard": { + "message": "บัตรเครดิต" + }, + "typeIdentity": { + "message": "ข้อมูลระบุตัวตน" + }, + "passwordHistory": { + "message": "ประวัติของรหัสผ่าน" + }, + "back": { + "message": "ย้อนกลับ" + }, + "collections": { + "message": "Collections" + }, + "favorites": { + "message": "รายการโปรด" + }, + "popOutNewWindow": { + "message": "Pop out to a new window" + }, + "refresh": { + "message": "Refresh" + }, + "cards": { + "message": "Cards" + }, + "identities": { + "message": "Identities" + }, + "logins": { + "message": "Logins" + }, + "secureNotes": { + "message": "Secure Notes" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "toggleCurrentUris": { + "message": "Toggle Current URIs", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI ปัจจุบัน", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "องค์กร", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Types" + }, + "allItems": { + "message": "รายการทั้งหมด" + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "remove": { + "message": "ลบ" + }, + "default": { + "message": "Default" + }, + "dateUpdated": { + "message": "อัปเดตแล้ว", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "อัปเดต Password แล้ว", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Are you sure you want to use the \"Never\" option? Setting your lock options to \"Never\" stores your vault's encryption key on your device. If you use this option you should ensure that you keep your device properly protected." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "เจ้าของ" + }, + "whoOwnsThisItem": { + "message": "ใครเป็นเจ้าของรายการนี้?" + }, + "strong": { + "message": "แข็งแรง", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "ไม่เลว", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "ง่ายเกินไป", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "ปลดล็อกด้วย PIN" + }, + "setYourPinCode": { + "message": "ตั้ง PIN เพื่อใช้ปลดล็อก Bitwarden ทั้งนี้ หากคุณล็อกเอาต์ออกจากแอปโดยสมบูรณ์จะเป็นการลบการตั้งค่า PIN ของคุณด้วย" + }, + "pinRequired": { + "message": "ต้องระบุ PIN" + }, + "invalidPin": { + "message": "PIN ไม่ถูกต้อง" + }, + "unlockWithBiometrics": { + "message": "Unlock with biometrics" + }, + "awaitDesktop": { + "message": "Awaiting confirmation from desktop" + }, + "awaitDesktopDesc": { + "message": "Please confirm using biometrics in the Bitwarden Desktop application to enable biometrics for browser." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on browser restart" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "cloneItem": { + "message": "Clone Item" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "lock": { + "message": "ล็อก", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "ถังขยะ", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "ค้นหาในถังขยะ" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "autoFillAndSave": { + "message": "Auto-fill and Save" + }, + "autoFillSuccessAndSavedUri": { + "message": "Auto-filled Item and Saved URI" + }, + "autoFillSuccess": { + "message": "Auto-filled Item" + }, + "setMasterPassword": { + "message": "ตั้งรหัสผ่านหลัก" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "ความยาวอย่างน้อย $LENGTH$ อักขระ", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "มีตัวพิมพ์ใหญ่อย่างน้อย 1 ตัว" + }, + "policyInEffectLowercase": { + "message": "มีตัวพิมพ์เล็กอย่างน้อย 1 ตัว" + }, + "policyInEffectNumbers": { + "message": "มีตัวเลขอย่างน้อย 1 ตัว" + }, + "policyInEffectSpecial": { + "message": "มีอักขระพิเศษต่อไปนี้อย่างน้อย 1 อักขระ: $CHARS$ ", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "ok": { + "message": "ตกลง" + }, + "desktopSyncVerificationTitle": { + "message": "Desktop sync verification" + }, + "desktopIntegrationVerificationText": { + "message": "Please verify that the desktop application shows this fingerprint: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Browser integration is not enabled" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Start the Bitwarden Desktop application" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Unable to enable biometrics" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Account missmatch" + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Biometrics not supported" + }, + "biometricsNotSupportedDesc": { + "message": "Browser biometrics is not supported on this device." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Permission not provided" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Permission request error" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "ค้นหาใน Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "เพิ่ม Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "ข้อความ" + }, + "sendTypeFile": { + "message": "ไฟล์" + }, + "allSends": { + "message": "Send ทั้งหมด", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "passwordProtected": { + "message": "Password protected" + }, + "copySendLink": { + "message": "Copy Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "ลบรหัสผ่าน" + }, + "delete": { + "message": "ลบ" + }, + "removedPassword": { + "message": "รหัสผ่านถูกลบแล้ว" + }, + "deletedSend": { + "message": "Send ถูกลบแล้ว", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "ลิงก์ Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Disabled" + }, + "removePasswordConfirmation": { + "message": "คุณต้องการลบรหัสผ่านนี้ใช่หรือไม่" + }, + "deleteSend": { + "message": "ลบ Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "คุณต้องการลบ Send นี้ใช่หรือไม่?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "แก้ไข Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "A friendly name to describe this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 วัน" + }, + "days": { + "message": "$DAYS$ วัน", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Custom" + }, + "maximumAccessCount": { + "message": "Maximum Access Count" + }, + "maximumAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "ข้อความที่คุณต้องการส่ง" + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "sendDisabled": { + "message": "Send Disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Before you start" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "click here", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature. You can verify your email in the web vault." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/tr/messages.json b/apps/browser/src/_locales/tr/messages.json new file mode 100644 index 0000000000..a29e01b8e3 --- /dev/null +++ b/apps/browser/src/_locales/tr/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - Ücretsiz Parola Yöneticisi", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Tüm cihazlarınız için güvenli ve ücretsiz bir parola yöneticisi.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Güvenli kasanıza ulaşmak için giriş yapın veya yeni bir hesap oluşturun." + }, + "createAccount": { + "message": "Hesap oluştur" + }, + "login": { + "message": "Giriş yap" + }, + "enterpriseSingleSignOn": { + "message": "Kurumsal tek oturum açma (SSO)" + }, + "cancel": { + "message": "İptal" + }, + "close": { + "message": "Kapat" + }, + "submit": { + "message": "Gönder" + }, + "emailAddress": { + "message": "E-posta adresi" + }, + "masterPass": { + "message": "Ana parola" + }, + "masterPassDesc": { + "message": "Ana parola, kasanıza ulaşmak için kullanacağınız paroladır. Ana parolanızı unutmamanız çok önemlidir. Unutursanız parolalarınızı asla kurtaramazsınız." + }, + "masterPassHintDesc": { + "message": "Ana parolanızı unutursanız bu ipucuna bakınca size ana parolanızı hatırlatacak bir şey yazabilirsiniz." + }, + "reTypeMasterPass": { + "message": "Ana parolayı tekrar yazın" + }, + "masterPassHint": { + "message": "Ana Parola İpucu (isteğe bağlı)" + }, + "tab": { + "message": "Sekme" + }, + "myVault": { + "message": "Kasam" + }, + "tools": { + "message": "Araçlar" + }, + "settings": { + "message": "Ayarlar" + }, + "currentTab": { + "message": "Geçerli sekme" + }, + "copyPassword": { + "message": "Parolayı kopyala" + }, + "copyNote": { + "message": "Notu kopyala" + }, + "copyUri": { + "message": "URI'yi kopyala" + }, + "copyUsername": { + "message": "Kullanıcı adını kopyala" + }, + "copyNumber": { + "message": "Numarayı kopyala" + }, + "copySecurityCode": { + "message": "Güvenlik kodunu kopyala" + }, + "autoFill": { + "message": "Otomatik doldur" + }, + "generatePasswordCopied": { + "message": "Parola oluştur (ve kopyala)" + }, + "copyElementIdentifier": { + "message": "Özel alan adını kopyala" + }, + "noMatchingLogins": { + "message": "Eşleşen hesap yok." + }, + "unlockVaultMenu": { + "message": "Kasanızın kilidini açın" + }, + "loginToVaultMenu": { + "message": "Kasanıza giriş yapın" + }, + "autoFillInfo": { + "message": "Mevcut sekme için otomatik doldurulacak giriş bilgisi bulunmuyor." + }, + "addLogin": { + "message": "Hesap ekle" + }, + "addItem": { + "message": "Kayıt ekle" + }, + "passwordHint": { + "message": "Parola ipucu" + }, + "enterEmailToGetHint": { + "message": "Ana parola ipucunu almak için hesabınızın e-posta adresini girin." + }, + "getMasterPasswordHint": { + "message": "Ana parola ipucunu al" + }, + "continue": { + "message": "Devam" + }, + "sendVerificationCode": { + "message": "E-posta adresime doğrulama kodu gönder" + }, + "sendCode": { + "message": "Kod gönder" + }, + "codeSent": { + "message": "Kod gönderildi" + }, + "verificationCode": { + "message": "Doğrulama kodu" + }, + "confirmIdentity": { + "message": "Devam etmek için kimliğinizi doğrulayın." + }, + "account": { + "message": "Hesap" + }, + "changeMasterPassword": { + "message": "Ana parolayı değiştir" + }, + "fingerprintPhrase": { + "message": "Parmak izi ifadesi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Hesabınızın parmak izi ifadesi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "İki aşamalı giriş" + }, + "logOut": { + "message": "Çıkış yap" + }, + "about": { + "message": "Hakkında" + }, + "version": { + "message": "Sürüm" + }, + "save": { + "message": "Kaydet" + }, + "move": { + "message": "Taşı" + }, + "addFolder": { + "message": "Klasör ekle" + }, + "name": { + "message": "Ad" + }, + "editFolder": { + "message": "Klasörü düzenle" + }, + "deleteFolder": { + "message": "Klasörü sil" + }, + "folders": { + "message": "Klasörler" + }, + "noFolders": { + "message": "Listelenecek klasör yok." + }, + "helpFeedback": { + "message": "Yardım ve geribildirim" + }, + "sync": { + "message": "Eşitle" + }, + "syncVaultNow": { + "message": "Kasayı şimdi eşitle" + }, + "lastSync": { + "message": "Son eşitleme:" + }, + "passGen": { + "message": "Parola Oluşturucu" + }, + "generator": { + "message": "Oluşturucu", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Hesaplarınız için otomatik olarak güçlü, özgün parolalar oluşturun." + }, + "bitWebVault": { + "message": "Bitwarden web kasası" + }, + "importItems": { + "message": "Hesapları içe aktar" + }, + "select": { + "message": "Seç" + }, + "generatePassword": { + "message": "Parola oluştur" + }, + "regeneratePassword": { + "message": "Yeni parola oluştur" + }, + "options": { + "message": "Seçenekler" + }, + "length": { + "message": "Uzunluk" + }, + "uppercase": { + "message": "Büyük harf (A-Z)" + }, + "lowercase": { + "message": "Küçük harf (a-z)" + }, + "numbers": { + "message": "Rakamlar (0-9)" + }, + "specialCharacters": { + "message": "Özel karakterler (!@#$%^&*)" + }, + "numWords": { + "message": "Kelime sayısı" + }, + "wordSeparator": { + "message": "Kelime ayracı" + }, + "capitalize": { + "message": "Baş harfleri büyük yap", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Rakam ekle" + }, + "minNumbers": { + "message": "En az rakam" + }, + "minSpecial": { + "message": "En az özel karakter" + }, + "avoidAmbChar": { + "message": "Okurken karışabilecek karakterleri kullanma" + }, + "searchVault": { + "message": "Kasada ara" + }, + "edit": { + "message": "Düzenle" + }, + "view": { + "message": "Görüntüle" + }, + "noItemsInList": { + "message": "Listelenecek kayıt yok." + }, + "itemInformation": { + "message": "Hesap Bilgileri" + }, + "username": { + "message": "Kullanıcı adı" + }, + "password": { + "message": "Parola" + }, + "passphrase": { + "message": "Uzun söz" + }, + "favorite": { + "message": "Favori" + }, + "notes": { + "message": "Notlar" + }, + "note": { + "message": "Not" + }, + "editItem": { + "message": "Kaydı düzenle" + }, + "folder": { + "message": "Klasör" + }, + "deleteItem": { + "message": "Kaydı sil" + }, + "viewItem": { + "message": "Kaydı göster" + }, + "launch": { + "message": "Aç" + }, + "website": { + "message": "Web sitesi" + }, + "toggleVisibility": { + "message": "Görünürlüğünü aç/kapat" + }, + "manage": { + "message": "Yönet" + }, + "other": { + "message": "Diğer" + }, + "rateExtension": { + "message": "Uzantıyı değerlendirin" + }, + "rateExtensionDesc": { + "message": "İyi bir yorum yazarak bizi destekleyebilirsiniz." + }, + "browserNotSupportClipboard": { + "message": "Web tarayıcınız panoya kopyalamayı desteklemiyor. Parolayı elle kopyalayın." + }, + "verifyIdentity": { + "message": "Kimlik Doğrulama" + }, + "yourVaultIsLocked": { + "message": "Kasanız kilitli. Devam etmek için kimliğinizi doğrulayın." + }, + "unlock": { + "message": "Kilidi aç" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ üzerinde $EMAIL$ adresiyle oturum açtınız.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Geçersiz ana parola" + }, + "vaultTimeout": { + "message": "Kasa zaman aşımı" + }, + "lockNow": { + "message": "Şimdi kilitle" + }, + "immediately": { + "message": "Hemen" + }, + "tenSeconds": { + "message": "10 saniye" + }, + "twentySeconds": { + "message": "20 saniye" + }, + "thirtySeconds": { + "message": "30 saniye" + }, + "oneMinute": { + "message": "1 dakika" + }, + "twoMinutes": { + "message": "2 dakika" + }, + "fiveMinutes": { + "message": "5 dakika" + }, + "fifteenMinutes": { + "message": "15 dakika" + }, + "thirtyMinutes": { + "message": "30 dakika" + }, + "oneHour": { + "message": "1 saat" + }, + "fourHours": { + "message": "4 saat" + }, + "onLocked": { + "message": "Sistem kilitlenince" + }, + "onRestart": { + "message": "Tarayıcı yeniden başlatılınca" + }, + "never": { + "message": "Asla" + }, + "security": { + "message": "Güvenlik" + }, + "errorOccurred": { + "message": "Bir hata oluştu" + }, + "emailRequired": { + "message": "E-posta adresi gereklidir." + }, + "invalidEmail": { + "message": "Geçersiz e-posta adresi." + }, + "masterPassRequired": { + "message": "Ana parola gereklidir." + }, + "masterPassLength": { + "message": "Ana parola en az 8 karakter uzunluğunda olmalıdır." + }, + "masterPassDoesntMatch": { + "message": "Ana parola onayı eşleşmiyor." + }, + "newAccountCreated": { + "message": "Yeni hesabınız oluşturuldu! Şimdi giriş yapabilirsiniz." + }, + "masterPassSent": { + "message": "Size ana parolanızın ipucunu içeren bir e-posta gönderdik." + }, + "verificationCodeRequired": { + "message": "Doğrulama kodu gereklidir." + }, + "invalidVerificationCode": { + "message": "Geçersiz doğrulama kodu" + }, + "valueCopied": { + "message": "$VALUE$ kopyalandı", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Seçilen hesap bu sayfada otomatik olarak doldurulamadı. Lütfen bilgileri elle kopyalayıp yapıştırın." + }, + "loggedOut": { + "message": "Çıkış yapıldı" + }, + "loginExpired": { + "message": "Oturumunuz zaman aşımına uğradı." + }, + "logOutConfirmation": { + "message": "Çıkış yapmak istediğinize emin misiniz?" + }, + "yes": { + "message": "Evet" + }, + "no": { + "message": "Hayır" + }, + "unexpectedError": { + "message": "Beklenmedik bir hata oluştu." + }, + "nameRequired": { + "message": "Ad gereklidir." + }, + "addedFolder": { + "message": "Klasör eklendi" + }, + "changeMasterPass": { + "message": "Ana parolayı değiştir" + }, + "changeMasterPasswordConfirmation": { + "message": "Ana parolanızı bitwarden.com web kasası üzerinden değiştirebilirsiniz. Siteye gitmek ister misiniz?" + }, + "twoStepLoginConfirmation": { + "message": "İki aşamalı giriş, hesabınıza girererken işlemi bir güvenlik anahtarı, şifrematik uygulaması, SMS, telefon araması veya e-posta gibi ek bir yöntemle doğrulamanızı isteyerek hesabınızın güvenliğini artırır. İki aşamalı giriş özelliğini bitwarden.com web kasası üzerinden etkinleştirebilirsiniz. Şimdi siteye gitmek ister misiniz?" + }, + "editedFolder": { + "message": "Klasör düzenlendi" + }, + "deleteFolderConfirmation": { + "message": "Bu klasörü silmek istediğinizden emin misiniz?" + }, + "deletedFolder": { + "message": "Klasör silindi" + }, + "gettingStartedTutorial": { + "message": "Başlangıç Rehberi" + }, + "gettingStartedTutorialVideo": { + "message": "Tarayıcı uzantımızdan en iyi şekilde yararlanmayı öğrenmek için başlangıç eğitimimizi izleyebilirsiniz." + }, + "syncingComplete": { + "message": "Eşitleme tamamlandı" + }, + "syncingFailed": { + "message": "Eşitleme başarısız" + }, + "passwordCopied": { + "message": "Parola kopyalandı" + }, + "uri": { + "message": "URl" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Yeni URI" + }, + "addedItem": { + "message": "Kayıt eklendi" + }, + "editedItem": { + "message": "Kayıt düzenlendi" + }, + "deleteItemConfirmation": { + "message": "Çöp kutusuna göndermek istediğinizden emin misiniz?" + }, + "deletedItem": { + "message": "Kayıt çöp kutusuna gönderildi" + }, + "overwritePassword": { + "message": "Parolanın üzerine yaz" + }, + "overwritePasswordConfirmation": { + "message": "Mevcut parolanın üzerine kaydetmek istediğinize emin misiniz?" + }, + "overwriteUsername": { + "message": "Kullanıcı adının üzerine yaz" + }, + "overwriteUsernameConfirmation": { + "message": "Kullanıcı adının üzerine kaydetmek istediğinizden emin misiniz?" + }, + "searchFolder": { + "message": "Klasörde ara" + }, + "searchCollection": { + "message": "Koleksiyonda ara" + }, + "searchType": { + "message": "Arama türü" + }, + "noneFolder": { + "message": "Klasör yok", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "\"Hesap ekle\" bildirimini kapat" + }, + "addLoginNotificationDesc": { + "message": "\"Hesap ekle\" bildirimi, ilk kez kullandığınız hesap bilgilerini kasanıza kaydetmek isteyip istemediğinizi otomatik olarak sorar." + }, + "dontShowCardsCurrentTab": { + "message": "Sekme sayfasında kartları gösterme" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Kasanızdaki banka/kredi kartları, otomatik doldurmayı kolaylaştırmak için \"geçerli sekme\" sayfasında listelenir." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Sekme sayfasında kimlikleri gösterme" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Kasanızdaki kimlik kayıtları, otomatik doldurmayı kolaylaştırmak için \"geçerli sekme\" sayfasında listelenir." + }, + "clearClipboard": { + "message": "Panoyu temizle", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Kopyalanan değerleri otomatik olarak panodan sil.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Bitwarden bu parolayı sizin için hatırlasın mı?" + }, + "notificationAddSave": { + "message": "Kaydet" + }, + "disableChangedPasswordNotification": { + "message": "\"Parola değiştirildi\" bildirimini kapat" + }, + "disableChangedPasswordNotificationDesc": { + "message": "\"Parola değiştirildi\" bildirimi, bir web sitesindeki parolanızı değiştirdiğiniz algılanınca otomatik olarak kasanızda kayıtlı parolayı güncellemenizi sağlar." + }, + "notificationChangeDesc": { + "message": "Bu parolayı Bitwarden'da güncellemek ister misiniz?" + }, + "notificationChangeSave": { + "message": "Güncelle" + }, + "disableContextMenuItem": { + "message": "Sağ tıklama menüsünü kapat" + }, + "disableContextMenuItemDesc": { + "message": "Sağ tıklama menüsü, parola oluşturma aracına ve açık sekmeye ait hesaplara hızlı erişim sağlar." + }, + "defaultUriMatchDetection": { + "message": "Varsayılan URI eşleşme tespiti", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Otomatik doldurma gibi eylemler gerçekleştirilirken hesaplar için URI eşleşme tespitinin nasıl yapılacağını seçin." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Uygulamanın renk temasını değiştir." + }, + "dark": { + "message": "Koyu", + "description": "Dark color" + }, + "light": { + "message": "Açık", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized koyu", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Kasayı dışa aktar" + }, + "fileFormat": { + "message": "Dosya biçimi" + }, + "warning": { + "message": "UYARI", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Kasayı Dışa Aktarmayı Onayla" + }, + "exportWarningDesc": { + "message": "Dışa aktarılan dosyadaki verileriniz şifrelenmemiş olacak. Bu dosyayı güvensiz yöntemlerle (örn. e-posta) göndermemeli ve saklamamalısınız. İşiniz bittikten sonra dosyayı hemen silin." + }, + "encExportKeyWarningDesc": { + "message": "Dışa aktardığınız bu dosyadaki verileriniz, hesabınızın şifreleme anahtarıyla şifrelenir. Hesabınızın şifreleme anahtarını değiştirirseniz bu dosyanın şifresi çözülemez hale gelir, dolayısıyla dosyayı yeniden dışa aktarmanız gerekir." + }, + "encExportAccountWarningDesc": { + "message": "Her Bitwarden kullanıcı hesabının hesap şifreleme anahtarları farklıdır. Yani şifrelenmiş bir dışa aktarmayı farklı bir hesapta içe aktaramazsınız." + }, + "exportMasterPassword": { + "message": "Kasadaki verilerinizi dışa aktarmak için ana parolanızı girin." + }, + "shared": { + "message": "Paylaşılan" + }, + "learnOrg": { + "message": "Kuruluşlar hakkında bilgi al" + }, + "learnOrgConfirmation": { + "message": "Bitwarden'ın kuruluş özelliğini kullanarak kasanızdaki kayıtları başkalarıyla paylaşabilirsiniz. Daha fazla bilgi için bitwarden.com sitesini ziyaret etmek ister misiniz?" + }, + "moveToOrganization": { + "message": "Kuruluşa taşı" + }, + "share": { + "message": "Paylaş" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ $ORGNAME$ kuruluşuna taşındı", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Bu kaydı taşımak istediğiniz kuruluşu seçin. Taşıdığınız kaydın sahipliği seçtiğiniz kuruluşa aktarılacak. Artık bu kaydın doğrudan sahibi olmayacaksınız." + }, + "learnMore": { + "message": "Daha fazla bilgi al" + }, + "authenticatorKeyTotp": { + "message": "Kimlik doğrulama anahtarı (TOTP)" + }, + "verificationCodeTotp": { + "message": "Doğrulama kodu (TOTP)" + }, + "copyVerificationCode": { + "message": "Doğrulama kodunu kopyala" + }, + "attachments": { + "message": "Ekler" + }, + "deleteAttachment": { + "message": "Eki sil" + }, + "deleteAttachmentConfirmation": { + "message": "Bu eki silmek istediğinize emin misiniz?" + }, + "deletedAttachment": { + "message": "Ek silindi" + }, + "newAttachment": { + "message": "Yeni dosya ekle" + }, + "noAttachments": { + "message": "Ek yok." + }, + "attachmentSaved": { + "message": "Dosya kaydedildi." + }, + "file": { + "message": "Dosya" + }, + "selectFile": { + "message": "Bir dosya seçin." + }, + "maxFileSize": { + "message": "Maksimum dosya boyutu 500 MB'dir." + }, + "featureUnavailable": { + "message": "Özellik kullanılamıyor" + }, + "updateKey": { + "message": "Şifreleme anahtarınızı güncellemeden bu özelliği kullanamazsınız." + }, + "premiumMembership": { + "message": "Premium üyelik" + }, + "premiumManage": { + "message": "Üyeliğimi yönet" + }, + "premiumManageAlert": { + "message": "Üyeliğinizi bitwarden.com web kasası üzerinden yönetebilirsiniz. Şimdi siteye gitmek ister misiniz?" + }, + "premiumRefresh": { + "message": "Üyeliğimi yenile" + }, + "premiumNotCurrentMember": { + "message": "Şu anda premium üye değilsiniz." + }, + "premiumSignUpAndGet": { + "message": "Premium üye olarak sahip olacağınız avantajlar:" + }, + "ppremiumSignUpStorage": { + "message": "Dosya ekleri için 1 GB şifrelenmiş depolama." + }, + "ppremiumSignUpTwoStep": { + "message": "YubiKey, FIDO U2F ve Duo gibi iki aşamalı giriş seçenekleri." + }, + "ppremiumSignUpReports": { + "message": "Kasanızı güvende tutmak için parola hijyeni, hesap sağlığı ve veri ihlali raporları." + }, + "ppremiumSignUpTotp": { + "message": "Kasanızdaki hesaplar için TOTP doğrulama kodu (2FA) oluşturucu." + }, + "ppremiumSignUpSupport": { + "message": "Öncelikli müşteri desteği." + }, + "ppremiumSignUpFuture": { + "message": "Ve ileride duyuracağımız tüm premium özellikler. Daha fazlası yakında!" + }, + "premiumPurchase": { + "message": "Premium satın al" + }, + "premiumPurchaseAlert": { + "message": "Premium üyeliği bitwarden.com web kasası üzerinden satın alabilirsiniz. Şimdi siteye gitmek ister misiniz?" + }, + "premiumCurrentMember": { + "message": "Premium üyesiniz!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden'ı desteklediğiniz için teşekkür ederiz." + }, + "premiumPrice": { + "message": "Bunların hepsi sadece yılda $PRICE$!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Yenileme tamamlandı" + }, + "disableAutoTotpCopy": { + "message": "Otomatik TOTP kopyalamayı kapat" + }, + "disableAutoTotpCopyDesc": { + "message": "Hesabınıza bağlı bir kimlik doğrulama anahtarı varsa giriş bilgilerini otomatik olarak doldurduğunuzda TOTP doğrulama kodu da otomatik olarak panonuza kopyalanır." + }, + "disableAutoBiometricsPrompt": { + "message": "Açılışta biyometri doğrulaması isteme" + }, + "premiumRequired": { + "message": "Premium gerekli" + }, + "premiumRequiredDesc": { + "message": "Bu özelliği kullanmak için premium üyelik gereklidir." + }, + "enterVerificationCodeApp": { + "message": "Kimlik doğrulama uygulamanızdaki 6 haneli doğrulama kodunu girin." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ adresine e-postayla gönderdiğimiz 6 haneli doğrulama kodunu girin.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Doğrulama e-postası $EMAIL$ adresine gönderildi.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Beni hatırla" + }, + "sendVerificationCodeEmailAgain": { + "message": "Doğrulama kodunu yeniden gönder" + }, + "useAnotherTwoStepMethod": { + "message": "Başka bir iki aşamalı giriş yöntemini kullan" + }, + "insertYubiKey": { + "message": "YubiKey'i bilgisayarınızın USB portuna takın, ardından düğmesine dokunun." + }, + "insertU2f": { + "message": "Güvenlik anahtarınızı bilgisayarınızın USB portuna takın. Düğmesi varsa dokunun." + }, + "webAuthnNewTab": { + "message": "WebAuthn iki aşamalı doğrulamayı başlatmak için aşağıdaki düğmeye tıklayın ve açılan sekmedeki yönergeleri takip edin." + }, + "webAuthnNewTabOpen": { + "message": "Yeni sekme aç" + }, + "webAuthnAuthenticate": { + "message": "WebAutn ile doğrula" + }, + "loginUnavailable": { + "message": "Giriş yapılamıyor" + }, + "noTwoStepProviders": { + "message": "Bu hesapta iki aşamalı giriş özelliği etkin ama yapılandırdığınız iki aşamalı giriş sağlayıcılarının hiçbiri bu tarayıcıyı desteklemiyor." + }, + "noTwoStepProviders2": { + "message": "Lütfen desteklenen bir web tarayıcısı (örn. Chrome) kullanın ve/veya web tarayıcılarında daha iyi desteklenen sağlayıcılar (örn. kimlik doğrulama uygulaması) ekleyin." + }, + "twoStepOptions": { + "message": "İki aşamalı giriş seçenekleri" + }, + "recoveryCodeDesc": { + "message": "İki aşamalı doğrulama sağlayıcılarınıza ulaşamıyor musunuz? Kurtarma kodunuzu kullanarak hesabınızdaki tüm iki aşamalı giriş sağlayıcılarını devre dışı bırakabilirsiniz." + }, + "recoveryCodeTitle": { + "message": "Kurtarma kodu" + }, + "authenticatorAppTitle": { + "message": "Kimlik doğrulama uygulaması" + }, + "authenticatorAppDesc": { + "message": "Zamana dayalı doğrulama kodları oluşturmak için kimlik doğrulama uygulaması (örn. Authy veya Google Authenticator) kullanın.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP güvenlik anahtarı" + }, + "yubiKeyDesc": { + "message": "Hesabınıza erişmek için bir YubiKey kullanın. YubiKey 4, 4 Nano, 4C ve NEO cihazlarıyla çalışır." + }, + "duoDesc": { + "message": "Duo Security ile doğrulama için Duo Mobile uygulaması, SMS, telefon araması veya U2F güvenlik anahtarını kullanın.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Kuruluşunuzun Duo Security doğrulaması için Duo Mobile uygulaması, SMS, telefon araması veya U2F güvenlik anahtarını kullanın.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Hesabınıza erişmek için WebAuthn uyumlu bir güvenlik anahtarı kullanın." + }, + "emailTitle": { + "message": "E-posta" + }, + "emailDesc": { + "message": "Doğrulama kodları e-posta adresinize gönderilecek." + }, + "selfHostedEnvironment": { + "message": "Şirket içinde barındırılan ortam" + }, + "selfHostedEnvironmentFooter": { + "message": "Kurum içinde barındırılan Bitwarden kurulumunuzun taban URL'sini belirtin." + }, + "customEnvironment": { + "message": "Özel ortam" + }, + "customEnvironmentFooter": { + "message": "İleri düzey kullanıcılar için. Her hizmetin taban URL'sini bağımsız olarak belirleyebilirsiniz." + }, + "baseUrl": { + "message": "Sunucu URL'si" + }, + "apiUrl": { + "message": "API sunucu URL'si" + }, + "webVaultUrl": { + "message": "Web kasası sunucu URL'si" + }, + "identityUrl": { + "message": "Kimlik sunucusu URL'si" + }, + "notificationsUrl": { + "message": "Bildirim sunucusu URL'si" + }, + "iconsUrl": { + "message": "Simge sunucusu URL'si" + }, + "environmentSaved": { + "message": "Ortam URL'leri kaydedildi." + }, + "enableAutoFillOnPageLoad": { + "message": "Sayfa yüklendiğinde otomatik doldur" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Sayfa yüklendiğinde giriş formu tespit edilirse otomatik olarak formu doldur." + }, + "experimentalFeature": { + "message": "Bu şu anda deneysel bir özelliktir. Kullanımı sizin sorumluluğunuzdadır." + }, + "defaultAutoFillOnPageLoad": { + "message": "Hesaplar için varsayılan otomatik doldurma ayarı" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "\"Sayfa yüklendiğinde otomatik doldur\"u açtıktan sonra her hesap için bu özelliği ayrı ayrı açıp kapatabilirsiniz. Bu ayar, özellikle ayarlama yapmadığınız hesaplarda kullanılacak varsayılan ayardır." + }, + "itemAutoFillOnPageLoad": { + "message": "Sayfa yüklendiğinde otomatik doldur (seçeneklerde etkinleştirilmişse)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Varsayılan ayarı kullan" + }, + "autoFillOnPageLoadYes": { + "message": "Sayfa yüklendiğinde otomatik doldur" + }, + "autoFillOnPageLoadNo": { + "message": "Sayfa yüklendiğinde otomatik doldurma" + }, + "commandOpenPopup": { + "message": "Kasayı açılır pencerede aç" + }, + "commandOpenSidebar": { + "message": "Kasayı kenar çubuğunda aç" + }, + "commandAutofillDesc": { + "message": "Geçerli site için son kullanılan hesabı otomatik doldur" + }, + "commandGeneratePasswordDesc": { + "message": "Rastgele yeni bir parola oluştur ve panoya kopyala" + }, + "commandLockVaultDesc": { + "message": "Kasayı kilitle" + }, + "privateModeWarning": { + "message": "Gizli mod desteği deneyseldir ve bazı özellikler kısıtlıdır." + }, + "customFields": { + "message": "Özel alanlar" + }, + "copyValue": { + "message": "Değeri kopyala" + }, + "value": { + "message": "Değer" + }, + "newCustomField": { + "message": "Yeni özel alan" + }, + "dragToSort": { + "message": "Sıralamak için sürükleyin" + }, + "cfTypeText": { + "message": "Metin" + }, + "cfTypeHidden": { + "message": "Gizli" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Bağlantılı", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Bağlı değer", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Doğrulama kodunuzu alacağınız e-postayı kontrol etmek için bu pencerenin dışında bir yere tıklarsanız bu pencere kapanacaktır. Bu pencerenin kapanmaması için yeni bir pencerede açmak ister misiniz?" + }, + "popupU2fCloseMessage": { + "message": "Bu tarayıcı bu açılır pencerede U2F isteklerini işleyemiyor. U2F kullanarak giriş yapmak için bu açılır pencereyi yeni bir pencerede açmak ister misiniz?" + }, + "disableFavicon": { + "message": "Site simgelerini devre dışı bırak" + }, + "disableFaviconDesc": { + "message": "Web sitesi simgeleri, kasanızdaki her kaydın yanında o siteyi tanımanıza yardımcı olan bir resim sunar." + }, + "disableBadgeCounter": { + "message": "Düğmedeki sayacı devre dışı bırak" + }, + "disableBadgeCounterDesc": { + "message": "Düğmedeki sayaç, görüntülenen sayfaya ait kaç hesabınız olduğunu gösterir." + }, + "cardholderName": { + "message": "Kart sahibinin adı" + }, + "number": { + "message": "Numara" + }, + "brand": { + "message": "Marka" + }, + "expirationMonth": { + "message": "Son kullanma ayı" + }, + "expirationYear": { + "message": "Son kullanma yılı" + }, + "expiration": { + "message": "Son kullanma tarihi" + }, + "january": { + "message": "Ocak" + }, + "february": { + "message": "Şubat" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "Nisan" + }, + "may": { + "message": "May" + }, + "june": { + "message": "Haziran" + }, + "july": { + "message": "Temmuz" + }, + "august": { + "message": "Ağustos" + }, + "september": { + "message": "Eylül" + }, + "october": { + "message": "Ekim" + }, + "november": { + "message": "Kasım" + }, + "december": { + "message": "Aralık" + }, + "securityCode": { + "message": "Güvenlik kodu" + }, + "ex": { + "message": "örn." + }, + "title": { + "message": "Unvan" + }, + "mr": { + "message": "Bay" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "Ad" + }, + "middleName": { + "message": "İkinci ad" + }, + "lastName": { + "message": "Soyad" + }, + "fullName": { + "message": "Adı soyadı" + }, + "identityName": { + "message": "Kimlik adı" + }, + "company": { + "message": "Şirket" + }, + "ssn": { + "message": "Sosyal güvenlik numarası" + }, + "passportNumber": { + "message": "Pasaport numarası" + }, + "licenseNumber": { + "message": "Ehliyet numarası" + }, + "email": { + "message": "E-posta" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adres" + }, + "address1": { + "message": "Adres 1" + }, + "address2": { + "message": "Adres 2" + }, + "address3": { + "message": "Adres 3" + }, + "cityTown": { + "message": "İlçe" + }, + "stateProvince": { + "message": "İl / eyalet" + }, + "zipPostalCode": { + "message": "Posta kodu" + }, + "country": { + "message": "Ülke" + }, + "type": { + "message": "Tür" + }, + "typeLogin": { + "message": "Hesap" + }, + "typeLogins": { + "message": "Hesaplar" + }, + "typeSecureNote": { + "message": "Güvenli not" + }, + "typeCard": { + "message": "Kart" + }, + "typeIdentity": { + "message": "Kimlik" + }, + "passwordHistory": { + "message": "Parola geçmişi" + }, + "back": { + "message": "Geri" + }, + "collections": { + "message": "Koleksiyonlar" + }, + "favorites": { + "message": "Favoriler" + }, + "popOutNewWindow": { + "message": "Yeni pencerede aç" + }, + "refresh": { + "message": "Yenile" + }, + "cards": { + "message": "Kartlar" + }, + "identities": { + "message": "Kimlikler" + }, + "logins": { + "message": "Hesaplar" + }, + "secureNotes": { + "message": "Güvenli notlar" + }, + "clear": { + "message": "Temizle", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Parolanız ele geçirilip geçirilmediğini kontrol edin." + }, + "passwordExposed": { + "message": "Bu parola, veri ihlallerinde $VALUE$ kere açığa çıkmış. Değiştirmenizi tavsiye ederiz.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Bilinen veri ihlallerinde bu parola bulunamadı. Güvenle kullanabilirsiniz." + }, + "baseDomain": { + "message": "Ana alan adı", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Alan adı", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Sunucu", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tam" + }, + "startsWith": { + "message": "URI başlangıcı" + }, + "regEx": { + "message": "Düzenli ifade", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Eşleşme tespiti", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Varsayılan eşleşme tespiti", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Seçenekleri aç/kapat" + }, + "toggleCurrentUris": { + "message": "Geçerli URI'leri aç/kapat", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Geçerli URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Kuruluş", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Türler" + }, + "allItems": { + "message": "Tüm kayıtlar" + }, + "noPasswordsInList": { + "message": "Listelenecek parola yok." + }, + "remove": { + "message": "Kaldır" + }, + "default": { + "message": "Varsayılan" + }, + "dateUpdated": { + "message": "Güncelleme", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parola güncelleme", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "\"Asla\" seçeneğini kullanmak istediğinizden emin misiniz? Kilit seçeneğinizi \"Asla\" olarak ayarlarsanız kasanızın şifreleme anahtarı cihazınızda saklanacaktır. Bu seçeneği kullanırsanız cihazınızı çok iyi korumalısınız." + }, + "noOrganizationsList": { + "message": "Herhangi bir kuruluşa dahil değilsiniz. Kuruluşlar, kayıtlarınızı diğer kullanıcılarla güvenli bir şekilde paylaşmanıza olanak verir." + }, + "noCollectionsInList": { + "message": "Listelenecek koleksiyon yok." + }, + "ownership": { + "message": "Sahip" + }, + "whoOwnsThisItem": { + "message": "Bu öğenin sahibi kim?" + }, + "strong": { + "message": "Güçlü", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "İyi", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Zayıf", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Zayıf ana parola" + }, + "weakMasterPasswordDesc": { + "message": "Seçtiğiniz ana parola zayıf. Bitwarden hesabınızı korumak için daha güçlü bir ana parola seçmenizi öneririz. Bu ana parolayı kullanmak istediğinizden emin misiniz?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Kilidi PIN koduyla aç" + }, + "setYourPinCode": { + "message": "Bitwarden'ı açarken kullanacağınız PIN kodunu belirleyin. Uygulamadan tamamen çıkış yaparsanız PIN ayarlarınız sıfırlanacaktır." + }, + "pinRequired": { + "message": "PIN kodu gerekli." + }, + "invalidPin": { + "message": "PIN kodu geçersiz." + }, + "unlockWithBiometrics": { + "message": "Kilidi biyometri ile aç" + }, + "awaitDesktop": { + "message": "Masaüstünden onay bekleniyor" + }, + "awaitDesktopDesc": { + "message": "Tarayıcıda biyometriyi etkinleştirmek için lütfen Bitwarden masaüstü uygulamasında biyometri kullanımını onaylayın." + }, + "lockWithMasterPassOnRestart": { + "message": "Tarayıcı yeniden başlatıldığında ana parola ile kilitle" + }, + "selectOneCollection": { + "message": "En az bir koleksiyon seçmelisiniz." + }, + "cloneItem": { + "message": "Kaydı klonla" + }, + "clone": { + "message": "Klonla" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Bir ya da daha fazla kuruluş ilkesi, oluşturucu ayarlarınızı etkiliyor." + }, + "vaultTimeoutAction": { + "message": "Kasa zaman aşımı eylemi" + }, + "lock": { + "message": "Kilitle", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Çöp kutusu", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Çöp kutusunda ara" + }, + "permanentlyDeleteItem": { + "message": "Kaydı kalıcı olarak sil" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Bu kaydı kalıcı olarak silmek istediğinizden emin misiniz?" + }, + "permanentlyDeletedItem": { + "message": "Kayıt kalıcı olarak silindi" + }, + "restoreItem": { + "message": "Kaydı geri yükle" + }, + "restoreItemConfirmation": { + "message": "Bu kaydı geri yüklemek istediğinizden emin misiniz?" + }, + "restoredItem": { + "message": "Kayıt geri yüklendi" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Çıkış yaptığınızda kasanıza erişiminiz tamamen sonlanacak ve zaman aşımının ardından çevrimiçi kimlik doğrulaması yapmanız gerekecek. Bu ayarı kullanmak istediğinizden emin misiniz?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Zaman Aşımı Eylem Onayı" + }, + "autoFillAndSave": { + "message": "Otomatik doldur ve kaydet" + }, + "autoFillSuccessAndSavedUri": { + "message": "Kayıt otomatik dolduruldu ve URI kaydedildi" + }, + "autoFillSuccess": { + "message": "Kayıt otomatik dolduruldu" + }, + "setMasterPassword": { + "message": "Ana parolayı belirle" + }, + "masterPasswordPolicyInEffect": { + "message": "Bir veya daha fazla kuruluş ilkesi gereğince ana parolanız aşağıdaki gereksinimleri karşılamalıdır:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum karmaşıklık puanı: $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum uzunluk: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Bir veya daha fazla büyük harf içermeli" + }, + "policyInEffectLowercase": { + "message": "Bir veya daha fazla küçük harf içermeli" + }, + "policyInEffectNumbers": { + "message": "Bir veya daha fazla rakam içermeli" + }, + "policyInEffectSpecial": { + "message": "Şu özel karakterlerden birini veya daha fazlasını içermeli: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Yeni ana parolanız ilke gereksinimlerini karşılamıyor." + }, + "acceptPolicies": { + "message": "Bu kutuyu işaretleyerek aşağıdakileri kabul etmiş olursunuz:" + }, + "acceptPoliciesError": { + "message": "Hizmet Koşulları ve Gizlilik Politikası kabul edilmemiş." + }, + "termsOfService": { + "message": "Hizmet Koşulları" + }, + "privacyPolicy": { + "message": "Gizlilik Politikası" + }, + "hintEqualsPassword": { + "message": "Parola ipucunuz parolanızla aynı olamaz." + }, + "ok": { + "message": "Tamam" + }, + "desktopSyncVerificationTitle": { + "message": "Masaüstü eşitleme doğrulaması" + }, + "desktopIntegrationVerificationText": { + "message": "Lütfen masaüstü uygulamasında bu parmak izinin göründüğünü onaylayın: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Tarayıcı entegrasyonu etkinleştirilmedi" + }, + "desktopIntegrationDisabledDesc": { + "message": "Bitwarden masaüstü uygulamasında tarayıcı entegrasyonu etkin değil. Lütfen masaüstü uygulamasının ayarlarından tarayıcı entegrasyonunu açın." + }, + "startDesktopTitle": { + "message": "Bitwarden masaüstü uygulamasını başlat" + }, + "startDesktopDesc": { + "message": "Bu işlevin kullanılabilmesi için Bitwarden masaüstü uygulamasının başlatılması gerekir." + }, + "errorEnableBiometricTitle": { + "message": "Biyometri etkinleştirilemedi" + }, + "errorEnableBiometricDesc": { + "message": "İşlem masaüstü uygulaması tarafından iptal edildi" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Masaüstü uygulaması güvenli iletişim kanalını geçersiz kıldı. Lütfen bu işlemi tekrar deneyin" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Masaüstü ile iletişim kesildi" + }, + "nativeMessagingWrongUserDesc": { + "message": "Masaüstü uygulamasında farklı bir hesaba giriş yapılmış. Lütfen her iki uygulamada da aynı hesaba giriş yapın." + }, + "nativeMessagingWrongUserTitle": { + "message": "Hesap uyuşmazlığı" + }, + "biometricsNotEnabledTitle": { + "message": "Biyometri etkin değil" + }, + "biometricsNotEnabledDesc": { + "message": "Tarayıcıda biyometriyi kullanmak için önce ayarlardan masaüstü biyometrisini etkinleştirilmeniz gerekir." + }, + "biometricsNotSupportedTitle": { + "message": "Biyometri desteklenmiyor" + }, + "biometricsNotSupportedDesc": { + "message": "Tarayıcı biyometrisi bu cihazda desteklenmiyor." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "İzin verilmedi" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Bitwarden masaüstü uygulamasıyla iletişim kurma iznimiz olmadan tarayıcı uzantısında biyometriyi kullanamayız. Lütfen tekrar deneyin." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "İzin isteme hatası" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Bu işlemi kenar çubuğundan yapamazsınız. Lütfen açılır pencereden yapmayı deneyin." + }, + "personalOwnershipSubmitError": { + "message": "Bir kuruluş ilkesi nedeniyle kişisel kasanıza hesap kaydetmeniz kısıtlanmış. Sahip seçeneğini bir kuruluş olarak değiştirin ve mevcut koleksiyonlar arasından seçim yapın." + }, + "personalOwnershipPolicyInEffect": { + "message": "Bir kuruluş ilkesi sahiplik seçeneklerinizi etkiliyor." + }, + "excludedDomains": { + "message": "Hariç tutulan alan adları" + }, + "excludedDomainsDesc": { + "message": "Bitwarden bu alan adlarında hesaplarınızı kaydetmeyi sormayacaktır. Değişikliklerin etkili olması için sayfayı yenilemelisiniz." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ geçerli bir alan adı değil", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Send'lerde ara", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Send ekle", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Metin" + }, + "sendTypeFile": { + "message": "Dosya" + }, + "allSends": { + "message": "Tüm Send'ler", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Maksimum erişim sayısına ulaşıldı", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Süresi dolmuş" + }, + "pendingDeletion": { + "message": "Silinmesi bekleniyor" + }, + "passwordProtected": { + "message": "Parola korumalı" + }, + "copySendLink": { + "message": "Send bağlantısını kopyala", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Parolayı kaldır" + }, + "delete": { + "message": "Sil" + }, + "removedPassword": { + "message": "Parola kaldırıldı" + }, + "deletedSend": { + "message": "Send silindi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send bağlantısı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Devre dışı" + }, + "removePasswordConfirmation": { + "message": "Parolayı kaldırmak istediğinizden emin misiniz?" + }, + "deleteSend": { + "message": "Send'i sil", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Bu Send'i silmek istediğinizden emin misiniz?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send'i düzenle", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Bu ne tür bir Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Bu Send'i açıklayan anlaşılır bir ad", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Göndermek istediğiniz dosya." + }, + "deletionDate": { + "message": "Silinme tarihi" + }, + "deletionDateDesc": { + "message": "Bu Send belirtilen tarih ve saatte kalıcı olacak silinecek.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Son kullanma tarihi" + }, + "expirationDateDesc": { + "message": "Bunu ayarlarsanız belirtilen tarih ve saatten sonra bu Send'e erişilemeyecektir.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 gün" + }, + "days": { + "message": "$DAYS$ gün", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Özel" + }, + "maximumAccessCount": { + "message": "Maksimum erişim sayısı" + }, + "maximumAccessCountDesc": { + "message": "Bunu ayarlarsanız maksimum erişim sayısına ulaşıldıktan sonra bu Send'e erişilemeyecektir.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Kullanıcıların bu Send'e erişmek için parola girmelerini isteyebilirsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Bu Send ile ilgili özel notlar.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Kimsenin erişememesi için bu Send'i devre dışı bırak.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Kaydettikten sonra bu Send'in linkini panoya kopyala.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Göndermek istediğiniz metin." + }, + "sendHideText": { + "message": "Bu Send'in metnini varsayılan olarak gizle.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Mevcut erişim sayısı" + }, + "createSend": { + "message": "Yeni Send oluştur", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Yeni parola" + }, + "sendDisabled": { + "message": "Send devre dışı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Bir kuruluş ilkesi nedeniyle yalnızca mevcut Send'leri silebilirsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send oluşturuldu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send düzenlendi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Dosya seçmek için eklentiyi kenar çubuğunda açın (mümkünse) veya bu banner'a tıklayarak yeni bir pencerede açın." + }, + "sendFirefoxFileWarning": { + "message": "Firefox ile dosya seçmek için eklentiyi kenar çubuğunda açın veya bu banner'a tıklayarak yeni bir pencerede açın." + }, + "sendSafariFileWarning": { + "message": "Safari ile dosya seçmek için bu banner'a tıklayarak eklentiyi yeni bir pencerede açın." + }, + "sendFileCalloutHeader": { + "message": "Başlamadan önce" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Takvim tarzı tarih seçiyi kullanmak için", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "buraya tıklayarak", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "yeni bir pencere açın.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Belirtilen son kullanma tarihi geçersiz." + }, + "deletionDateIsInvalid": { + "message": "Belirtilen silinme tarihi geçersiz." + }, + "expirationDateAndTimeRequired": { + "message": "Son kullanma tarihi ve saati gereklidir." + }, + "deletionDateAndTimeRequired": { + "message": "Silinme tarihi ve saati gereklidir." + }, + "dateParsingError": { + "message": "Silinme ve son kullanma tarihleriniz kaydedilirken bir hata oluştu." + }, + "hideEmail": { + "message": "E-posta adresimi alıcılardan gizle." + }, + "sendOptionsPolicyInEffect": { + "message": "Bir veya daha fazla kuruluş ilkesi Send seçeneklerinizi etkiliyor." + }, + "passwordPrompt": { + "message": "Ana parolayı yeniden iste" + }, + "passwordConfirmation": { + "message": "Ana parola onayı" + }, + "passwordConfirmationDesc": { + "message": "Bu işlem korumalıdır. İşleme devam etmek için lütfen ana parolanızı yeniden girin." + }, + "emailVerificationRequired": { + "message": "E-posta doğrulaması gerekiyor" + }, + "emailVerificationRequiredDesc": { + "message": "Bu özelliği kullanmak için e-postanızı doğrulamanız gerekir. E-postanızı web kasasında doğrulayabilirsiniz." + }, + "updatedMasterPassword": { + "message": "Ana parola güncellendi" + }, + "updateMasterPassword": { + "message": "Ana parolayı güncelle" + }, + "updateMasterPasswordWarning": { + "message": "Ana parolanız kuruluşunuzdaki bir yönetici tarafından yakın zamanda değiştirildi. Kasanıza erişmek için parolanızı güncellemelisiniz. Devam ettiğinizde oturumunuz kapanacak ve yeniden oturum açmanız gerekecektir. Diğer cihazlardaki aktif oturumlar bir saate kadar aktif kalabilir." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Otomatik Eklenme" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Bu kuruluşun sizi otomatik olarak parola sıfırlamaya ekleyen bir ilkesi bulunmakta. Bu ilkeye eklenmek, kuruluş yöneticilerinin ana parolanızı değiştirebilmesini sağlar." + }, + "selectFolder": { + "message": "Klasör seç..." + }, + "ssoCompleteRegistration": { + "message": "SSO ile girişinizi tamamlamak için lütfen kasanıza erişirken kullanacağınız ana parolayı belirleyin." + }, + "hours": { + "message": "Saat" + }, + "minutes": { + "message": "Dakika" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Kuruluş ilkeleriniz kasa zaman aşımınızı etkiliyor. İzin verilen maksimum kasa zaman aşımı $HOURS$ saat $MINUTES$ dakikadır", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Kasa zaman aşımınız, kuruluşunuz tarafından belirlenen kısıtlamaları aşıyor." + }, + "vaultExportDisabled": { + "message": "Kasayı dışa aktarma devre dışı" + }, + "personalVaultExportPolicyInEffect": { + "message": "Bir veya daha fazla kuruluş ilkesi, kişisel kasanızı dışa aktarmanızı engelliyor." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Geçerli bir form elemanı bulunamadı. HTML'i denetlemeyi deneyebilirsiniz." + }, + "copyCustomFieldNameNotUnique": { + "message": "Benzersiz tanımlayıcı bulunamadı." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ kendi barındırdığı bir anahtar sunucusuyla SSO kullanıyor. Bu kuruluşun üyelerinin artık ana parola kullanması gerekmiyor.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Kuruluştan ayrıl" + }, + "removeMasterPassword": { + "message": "Ana parolayı kaldır" + }, + "removedMasterPassword": { + "message": "Ana parola kaldırıldı." + }, + "leaveOrganizationConfirmation": { + "message": "Bu kuruluştan ayrılmak istediğinizden emin misiniz?" + }, + "leftOrganization": { + "message": "Kuruluştan ayrıldınız." + }, + "toggleCharacterCount": { + "message": "Karakter sayacını aç/kapat" + }, + "sessionTimeout": { + "message": "Oturumunuzun süresi doldu. Lütfen geri dönüp yeniden giriş yapın." + }, + "exportingPersonalVaultTitle": { + "message": "Kişisel Kasayı Dışa Aktarma" + }, + "exportingPersonalVaultDescription": { + "message": "Yalnızca $EMAIL$ ile ilişkili kişisel kasa öğeleri dışa aktarılacaktır. Kuruluş kasası öğeleri dahil edilmeyecektir.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Hata" + }, + "regenerateUsername": { + "message": "Kullanıcı adını yeniden oluştur" + }, + "generateUsername": { + "message": "Kullanıcı adı oluştur" + }, + "usernameType": { + "message": "Kullanıcı adı türü" + }, + "plusAddressedEmail": { + "message": "Artı adresli e-posta", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "E-posta sağlayıcınızın alt adres özelliklerini kullanın." + }, + "catchallEmail": { + "message": "Catch-all e-posta" + }, + "catchallEmailDesc": { + "message": "Alan adınızın tüm iletileri yakalamaya ayarlanmış adresini kullanın." + }, + "random": { + "message": "Rastgele" + }, + "randomWord": { + "message": "Rastgele kelime" + }, + "websiteName": { + "message": "Web sitesi adı" + }, + "whatWouldYouLikeToGenerate": { + "message": "Ne oluşturmak istersiniz?" + }, + "passwordType": { + "message": "Parola türü" + }, + "service": { + "message": "Servis" + } +} diff --git a/apps/browser/src/_locales/uk/messages.json b/apps/browser/src/_locales/uk/messages.json new file mode 100644 index 0000000000..b0d8ecd981 --- /dev/null +++ b/apps/browser/src/_locales/uk/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden - це захищений і безкоштовний менеджер паролів для всіх ваших пристроїв.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Для доступу до сховища увійдіть в обліковий запис, або створіть новий." + }, + "createAccount": { + "message": "Створити обліковий запис" + }, + "login": { + "message": "Увійти" + }, + "enterpriseSingleSignOn": { + "message": "Єдиний корпоративний вхід (SSO)" + }, + "cancel": { + "message": "Скасувати" + }, + "close": { + "message": "Закрити" + }, + "submit": { + "message": "Відправити" + }, + "emailAddress": { + "message": "Адреса е-пошти" + }, + "masterPass": { + "message": "Головний пароль" + }, + "masterPassDesc": { + "message": "Головний пароль використовується для доступу до вашого сховища. Дуже важливо, щоб ви запам'ятали його. Якщо ви забудете головний пароль, його неможливо буде відновити." + }, + "masterPassHintDesc": { + "message": "Якщо ви забудете головний пароль, підказка може допомогти вам згадати його." + }, + "reTypeMasterPass": { + "message": "Введіть головний пароль ще раз" + }, + "masterPassHint": { + "message": "Підказка для головного пароля (необов'язково)" + }, + "tab": { + "message": "Вкладка" + }, + "myVault": { + "message": "Моє сховище" + }, + "tools": { + "message": "Інструменти" + }, + "settings": { + "message": "Налаштування" + }, + "currentTab": { + "message": "Поточна вкладка" + }, + "copyPassword": { + "message": "Копіювати пароль" + }, + "copyNote": { + "message": "Копіювати нотатку" + }, + "copyUri": { + "message": "Копіювати URI" + }, + "copyUsername": { + "message": "Копіювати ім'я користувача" + }, + "copyNumber": { + "message": "Копіювати номер" + }, + "copySecurityCode": { + "message": "Копіювати код безпеки" + }, + "autoFill": { + "message": "Автозаповнення" + }, + "generatePasswordCopied": { + "message": "Генерувати пароль (з копіюванням)" + }, + "copyElementIdentifier": { + "message": "Копіювати назву власного поля" + }, + "noMatchingLogins": { + "message": "Немає відповідних записів." + }, + "unlockVaultMenu": { + "message": "Розблокуйте сховище" + }, + "loginToVaultMenu": { + "message": "Увійдіть до сховища" + }, + "autoFillInfo": { + "message": "Для поточної вкладки браузера немає записів автозаповнення." + }, + "addLogin": { + "message": "Додати запис" + }, + "addItem": { + "message": "Додати запис" + }, + "passwordHint": { + "message": "Підказка для пароля" + }, + "enterEmailToGetHint": { + "message": "Введіть свою адресу е-пошти, щоб отримати підказку для головного пароля." + }, + "getMasterPasswordHint": { + "message": "Отримати підказку для головного пароля" + }, + "continue": { + "message": "Продовжити" + }, + "sendVerificationCode": { + "message": "Надіслати код підтвердження е-поштою" + }, + "sendCode": { + "message": "Надіслати код" + }, + "codeSent": { + "message": "Код надіслано" + }, + "verificationCode": { + "message": "Код підтвердження" + }, + "confirmIdentity": { + "message": "Підтвердьте свої облікові дані для продовження." + }, + "account": { + "message": "Обліковий запис" + }, + "changeMasterPassword": { + "message": "Змінити головний пароль" + }, + "fingerprintPhrase": { + "message": "Фраза відбитку", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Фраза відбитку вашого облікового запису", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Двоетапна перевірка" + }, + "logOut": { + "message": "Вийти" + }, + "about": { + "message": "Про розширення" + }, + "version": { + "message": "Версія" + }, + "save": { + "message": "Зберегти" + }, + "move": { + "message": "Перемістити" + }, + "addFolder": { + "message": "Додати теку" + }, + "name": { + "message": "Назва" + }, + "editFolder": { + "message": "Редагувати теку" + }, + "deleteFolder": { + "message": "Видалити теку" + }, + "folders": { + "message": "Теки" + }, + "noFolders": { + "message": "Немає тек." + }, + "helpFeedback": { + "message": "Допомога і зворотній зв'язок" + }, + "sync": { + "message": "Синхронізація" + }, + "syncVaultNow": { + "message": "Синхронізувати зараз" + }, + "lastSync": { + "message": "Остання синхронізація:" + }, + "passGen": { + "message": "Генератор паролів" + }, + "generator": { + "message": "Генератор", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Автоматичне генерування стійких, унікальних паролів." + }, + "bitWebVault": { + "message": "Веб сховище Bitwarden" + }, + "importItems": { + "message": "Імпорт записів" + }, + "select": { + "message": "Обрати" + }, + "generatePassword": { + "message": "Генерувати пароль" + }, + "regeneratePassword": { + "message": "Генерувати новий" + }, + "options": { + "message": "Додатково" + }, + "length": { + "message": "Довжина" + }, + "uppercase": { + "message": "Верхній регістр (A-Z)" + }, + "lowercase": { + "message": "Нижній регістр (a-z)" + }, + "numbers": { + "message": "Числа (0-9)" + }, + "specialCharacters": { + "message": "Спеціальні символи (!@#$%^&*)" + }, + "numWords": { + "message": "Кількість слів" + }, + "wordSeparator": { + "message": "Розділювач слів" + }, + "capitalize": { + "message": "Великі літери", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Включити число" + }, + "minNumbers": { + "message": "Мінімум цифр" + }, + "minSpecial": { + "message": "Мінімум спеціальних символів" + }, + "avoidAmbChar": { + "message": "Уникати неоднозначних символів" + }, + "searchVault": { + "message": "Пошук" + }, + "edit": { + "message": "Змінити" + }, + "view": { + "message": "Перегляд" + }, + "noItemsInList": { + "message": "Немає записів." + }, + "itemInformation": { + "message": "Інформація про запис" + }, + "username": { + "message": "Ім'я користувача" + }, + "password": { + "message": "Пароль" + }, + "passphrase": { + "message": "Парольна фраза" + }, + "favorite": { + "message": "Обране" + }, + "notes": { + "message": "Нотатки" + }, + "note": { + "message": "Нотатка" + }, + "editItem": { + "message": "Зміна запису" + }, + "folder": { + "message": "Тека" + }, + "deleteItem": { + "message": "Видалити запис" + }, + "viewItem": { + "message": "Перегляд запису" + }, + "launch": { + "message": "Перейти" + }, + "website": { + "message": "Вебсайт" + }, + "toggleVisibility": { + "message": "Змінити видимість" + }, + "manage": { + "message": "Керування" + }, + "other": { + "message": "Інше" + }, + "rateExtension": { + "message": "Оцінити розширення" + }, + "rateExtensionDesc": { + "message": "Будь ласка, подумайте про те, щоб допомогти нам хорошим відгуком!" + }, + "browserNotSupportClipboard": { + "message": "Ваш браузер не підтримує копіювання даних в буфер обміну. Скопіюйте вручну." + }, + "verifyIdentity": { + "message": "Виконати перевірку" + }, + "yourVaultIsLocked": { + "message": "Ваше сховище заблоковане. Для продовження виконайте перевірку." + }, + "unlock": { + "message": "Розблокувати" + }, + "loggedInAsOn": { + "message": "Ви увійшли як $EMAIL$ на $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Неправильний головний пароль" + }, + "vaultTimeout": { + "message": "Час очікування сховища" + }, + "lockNow": { + "message": "Заблокувати зараз" + }, + "immediately": { + "message": "Негайно" + }, + "tenSeconds": { + "message": "10 секунд" + }, + "twentySeconds": { + "message": "20 секунд" + }, + "thirtySeconds": { + "message": "30 секунд" + }, + "oneMinute": { + "message": "1 хвилина" + }, + "twoMinutes": { + "message": "2 хвилини" + }, + "fiveMinutes": { + "message": "5 хвилин" + }, + "fifteenMinutes": { + "message": "15 хвилин" + }, + "thirtyMinutes": { + "message": "30 хвилин" + }, + "oneHour": { + "message": "1 година" + }, + "fourHours": { + "message": "4 години" + }, + "onLocked": { + "message": "При блокуванні системи" + }, + "onRestart": { + "message": "При перезапуску браузера" + }, + "never": { + "message": "Ніколи" + }, + "security": { + "message": "Безпека" + }, + "errorOccurred": { + "message": "Сталася помилка" + }, + "emailRequired": { + "message": "Необхідно вказати адресу е-пошти." + }, + "invalidEmail": { + "message": "Неправильна адреса е-пошти." + }, + "masterPassRequired": { + "message": "Потрібен головний пароль." + }, + "masterPassLength": { + "message": "Довжина головного пароля повинна бути не менше 8 символів." + }, + "masterPassDoesntMatch": { + "message": "Підтвердження головного пароля не збігається." + }, + "newAccountCreated": { + "message": "Ваш обліковий запис створений! Тепер ви можете увійти." + }, + "masterPassSent": { + "message": "Ми надіслали вам лист з підказкою для головного пароля." + }, + "verificationCodeRequired": { + "message": "Потрібний код підтвердження." + }, + "invalidVerificationCode": { + "message": "Недійсний код підтвердження" + }, + "valueCopied": { + "message": "$VALUE$ скопійовано", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Не вдається заповнити пароль на цій сторінці. Скопіюйте і вставте ім'я користувача та/або пароль." + }, + "loggedOut": { + "message": "Ви вийшли" + }, + "loginExpired": { + "message": "Тривалість вашого сеансу завершилась." + }, + "logOutConfirmation": { + "message": "Ви дійсно хочете вийти?" + }, + "yes": { + "message": "Так" + }, + "no": { + "message": "Ні" + }, + "unexpectedError": { + "message": "Сталася неочікувана помилка." + }, + "nameRequired": { + "message": "Потрібна назва." + }, + "addedFolder": { + "message": "Додано теку" + }, + "changeMasterPass": { + "message": "Змінити головний пароль" + }, + "changeMasterPasswordConfirmation": { + "message": "Ви можете змінити головний пароль в сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "twoStepLoginConfirmation": { + "message": "Двоетапна перевірка робить ваш обліковий запис більш захищеним, вимагаючи підтвердження входу з використанням іншого пристрою, наприклад, за допомогою коду безпеки, програми авторизації, SMS, телефонного виклику, або е-пошти. Ви можете увімкнути двоетапну перевірку в сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "editedFolder": { + "message": "Тека змінена" + }, + "deleteFolderConfirmation": { + "message": "Ви дійсно хочете видалити цю теку?" + }, + "deletedFolder": { + "message": "Теку видалено" + }, + "gettingStartedTutorial": { + "message": "Знайомство" + }, + "gettingStartedTutorialVideo": { + "message": "Перегляньте знайомство, щоб дізнатися про можливості розширення для браузера." + }, + "syncingComplete": { + "message": "Синхронізацію завершено" + }, + "syncingFailed": { + "message": "Не вдалося синхронізувати" + }, + "passwordCopied": { + "message": "Пароль скопійовано" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Новий URI" + }, + "addedItem": { + "message": "Запис додано" + }, + "editedItem": { + "message": "Запис змінено" + }, + "deleteItemConfirmation": { + "message": "Ви дійсно хочете перенести до смітника?" + }, + "deletedItem": { + "message": "Запис перенесено до смітника" + }, + "overwritePassword": { + "message": "Перезаписати пароль" + }, + "overwritePasswordConfirmation": { + "message": "Ви дійсно хочете перезаписати поточний пароль?" + }, + "overwriteUsername": { + "message": "Перезаписати ім'я користувача" + }, + "overwriteUsernameConfirmation": { + "message": "Ви дійсно бажаєте перезаписати поточне ім'я користувача?" + }, + "searchFolder": { + "message": "Пошук в теці" + }, + "searchCollection": { + "message": "Пошук в збірках" + }, + "searchType": { + "message": "Пошук за типом" + }, + "noneFolder": { + "message": "Без теки", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Вимкнути сповіщення про новий запис" + }, + "addLoginNotificationDesc": { + "message": "Сповіщення про додавання пароля автоматично пропонує зберегти нові паролі у вашому сховищі під час першого входу." + }, + "dontShowCardsCurrentTab": { + "message": "Не показувати картки на вкладці" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Картки з вашого сховища показано на сторінці поточної вкладки для швидкого доступу." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Не показувати посвідчення на вкладці" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Посвідчення з вашого сховища показано на сторінці поточної вкладки для швидкого доступу." + }, + "clearClipboard": { + "message": "Очистити буфер обміну", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Автоматично очищати скопійовані значення з буфера обміну.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Чи повинен Bitwarden зберегти цей пароль?" + }, + "notificationAddSave": { + "message": "Зберегти" + }, + "disableChangedPasswordNotification": { + "message": "Вимкнути сповіщення зміненого пароля" + }, + "disableChangedPasswordNotificationDesc": { + "message": "Сповіщення зміненого пароля автоматично запитує вас про оновлення пароля у сховищі, коли виявлено його зміну на вебсайті." + }, + "notificationChangeDesc": { + "message": "Ви хочете оновити цей пароль в Bitwarden?" + }, + "notificationChangeSave": { + "message": "Оновити" + }, + "disableContextMenuItem": { + "message": "Вимкнути в контекстному меню" + }, + "disableContextMenuItemDesc": { + "message": "Можливості контекстного меню забезпечують швидкий доступ до генерування пароля й входу для вебсайту поточної вкладки." + }, + "defaultUriMatchDetection": { + "message": "Типове виявлення збігів URI", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Оберіть типовий спосіб виявлення збігів URI для виконання автозаповнення під час входу." + }, + "theme": { + "message": "Тема" + }, + "themeDesc": { + "message": "Змінити колірну тему додатка." + }, + "dark": { + "message": "Темна", + "description": "Dark color" + }, + "light": { + "message": "Світла", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized темна", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Експорт сховища" + }, + "fileFormat": { + "message": "Формат файлу" + }, + "warning": { + "message": "ПОПЕРЕДЖЕННЯ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Підтвердити експорт сховища" + }, + "exportWarningDesc": { + "message": "Експортовані дані вашого сховища знаходяться в незашифрованому вигляді. Вам не слід зберігати чи надсилати їх через незахищені канали (наприклад, е-поштою). Після використання негайно видаліть їх." + }, + "encExportKeyWarningDesc": { + "message": "Цей експорт шифрує ваші дані за допомогою ключа шифрування облікового запису. Якщо ви коли-небудь оновите ключ шифрування облікового запису, ви повинні виконати експорт знову, оскільки не зможете розшифрувати цей файл експорту." + }, + "encExportAccountWarningDesc": { + "message": "Ключі шифрування унікальні для кожного облікового запису користувача Bitwarden, тому ви не можете імпортувати зашифрований експорт до іншого облікового запису." + }, + "exportMasterPassword": { + "message": "Введіть головний пароль, щоб експортувати дані сховища." + }, + "shared": { + "message": "Спільні" + }, + "learnOrg": { + "message": "Докладніше про організації" + }, + "learnOrgConfirmation": { + "message": "Bitwarden дозволяє вам надавати доступ до записів свого сховища іншим за допомогою облікового запису організації. Бажаєте перейти на веб-сайт bitwarden.com, щоб дізнатися більше?" + }, + "moveToOrganization": { + "message": "Перемістити до організації" + }, + "share": { + "message": "Поділитися" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ переміщено до $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Виберіть організацію, до якої ви бажаєте перемістити цей запис. При переміщенні до організації власність запису передається тій організації. Ви більше не будете єдиним власником цього запису після переміщення." + }, + "learnMore": { + "message": "Докладніше" + }, + "authenticatorKeyTotp": { + "message": "Ключ авторизації (TOTP)" + }, + "verificationCodeTotp": { + "message": "Код підтвердження (TOTP)" + }, + "copyVerificationCode": { + "message": "Копіювати код підтвердження" + }, + "attachments": { + "message": "Вкладення" + }, + "deleteAttachment": { + "message": "Видалити вкладення" + }, + "deleteAttachmentConfirmation": { + "message": "Ви дійсно хочете видалити це вкладення?" + }, + "deletedAttachment": { + "message": "Вкладення видалено" + }, + "newAttachment": { + "message": "Додати нове вкладення" + }, + "noAttachments": { + "message": "Немає вкладень." + }, + "attachmentSaved": { + "message": "Вкладення збережено." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Оберіть файл." + }, + "maxFileSize": { + "message": "Максимальний розмір файлу 500 Мб." + }, + "featureUnavailable": { + "message": "Функція недоступна" + }, + "updateKey": { + "message": "Ви не можете використовувати цю функцію доки не оновите свій ключ шифрування." + }, + "premiumMembership": { + "message": "Преміум статус" + }, + "premiumManage": { + "message": "Керувати статусом" + }, + "premiumManageAlert": { + "message": "Ви можете керувати своїм статусом у сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "premiumRefresh": { + "message": "Оновити статус" + }, + "premiumNotCurrentMember": { + "message": "Зараз у вас немає преміум-статусу." + }, + "premiumSignUpAndGet": { + "message": "Підпишіться на преміум-статус і отримайте:" + }, + "ppremiumSignUpStorage": { + "message": "1 ГБ зашифрованого сховища для файлів." + }, + "ppremiumSignUpTwoStep": { + "message": "Додаткові можливості двоетапної перевірки, наприклад, YubiKey, FIDO U2F та Duo." + }, + "ppremiumSignUpReports": { + "message": "Гігієна паролів, здоров'я облікового запису, а також звіти про вразливості даних, щоб зберігати ваше сховище в безпеці." + }, + "ppremiumSignUpTotp": { + "message": "Генератор коду авторизації TOTP (2FA) для входу в сховище." + }, + "ppremiumSignUpSupport": { + "message": "Пріоритетну технічну підтримку." + }, + "ppremiumSignUpFuture": { + "message": "Всі майбутні функції преміум статусу. Їх буде більше!" + }, + "premiumPurchase": { + "message": "Придбати преміум" + }, + "premiumPurchaseAlert": { + "message": "Ви можете придбати преміум статус у сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "premiumCurrentMember": { + "message": "У вас преміум статус!" + }, + "premiumCurrentMemberThanks": { + "message": "Дякуємо за підтримку Bitwarden." + }, + "premiumPrice": { + "message": "Всього лише $PRICE$ / за рік!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Оновлення завершено" + }, + "disableAutoTotpCopy": { + "message": "Вимкнути авто-копіювання TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Якщо ваш запис має вкладений ключ авторизації, код підтвердження TOTP автоматично копіюється до буфера обміну щоразу при автозаповненні." + }, + "disableAutoBiometricsPrompt": { + "message": "Не запитувати біометрію при запуску" + }, + "premiumRequired": { + "message": "Необхідний преміум статус" + }, + "premiumRequiredDesc": { + "message": "Для використання цієї функції необхідний преміум статус." + }, + "enterVerificationCodeApp": { + "message": "Введіть 6-значний код підтвердження з програми авторизації." + }, + "enterVerificationCodeEmail": { + "message": "Введіть 6-значний код підтвердження, надісланий на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Код підтвердження надіслано на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запам'ятати мене" + }, + "sendVerificationCodeEmailAgain": { + "message": "Надіслати код підтвердження ще раз" + }, + "useAnotherTwoStepMethod": { + "message": "Інший спосіб двоетапної перевірки" + }, + "insertYubiKey": { + "message": "Вставте свій YubiKey в USB порт комп'ютера, потім торкніться цієї кнопки." + }, + "insertU2f": { + "message": "Вставте свій ключ безпеки в USB порт комп'ютера. Якщо в нього є кнопка, натисніть її." + }, + "webAuthnNewTab": { + "message": "Щоб почати перевірку WebAuthn 2FA, натисніть кнопку внизу для відкриття нової вкладки і дотримуйтесь зазначених на ній настанов." + }, + "webAuthnNewTabOpen": { + "message": "Відкрити нову вкладку" + }, + "webAuthnAuthenticate": { + "message": "Авторизація WebAuthn" + }, + "loginUnavailable": { + "message": "Вхід недоступний" + }, + "noTwoStepProviders": { + "message": "Для цього облікового запису увімкнено двоетапну перевірку. Однак, жоден з налаштованих провайдерів двоетапної перевірки не підтримується цим браузером." + }, + "noTwoStepProviders2": { + "message": "Будь ласка, скористайтеся підтримуваним браузером (наприклад, Chrome) та/або іншими провайдерами, що краще підтримуються браузерами (наприклад, програма авторизації)." + }, + "twoStepOptions": { + "message": "Налаштування двоетапної перевірки" + }, + "recoveryCodeDesc": { + "message": "Втратили доступ до всіх провайдерів двоетапної перевірки? Скористайтеся кодом відновлення, щоб вимкнути двоетапну перевірку для свого облікового запису." + }, + "recoveryCodeTitle": { + "message": "Код відновлення" + }, + "authenticatorAppTitle": { + "message": "Програма авторизації" + }, + "authenticatorAppDesc": { + "message": "Використовуйте програму авторизації (наприклад, Authy або Google Authenticator), щоб генерувати тимчасові коди підтвердження.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Ключ безпеки YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Використовуйте YubiKey для доступу до сховища. Працює з YubiKey 4, 4 Nano, 4C та пристроями NEO." + }, + "duoDesc": { + "message": "Авторизуйтесь за допомогою Duo Security з використанням мобільного додатку Duo Mobile, SMS, телефонного виклику, або ключа безпеки U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Авторизуйтесь за допомогою Duo Security для вашої організації з використанням мобільного додатку Duo Mobile, SMS, телефонного виклику, або ключа безпеки U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Використовуйте будь-який ключ безпеки WebAuthn для доступу до сховища." + }, + "emailTitle": { + "message": "Е-пошта" + }, + "emailDesc": { + "message": "Коди підтвердження будуть надсилатися на вашу пошту." + }, + "selfHostedEnvironment": { + "message": "Середовище власного хостингу" + }, + "selfHostedEnvironmentFooter": { + "message": "Вкажіть основну URL-адресу Bitwarden на вашому сервері." + }, + "customEnvironment": { + "message": "Власне середовище" + }, + "customEnvironmentFooter": { + "message": "Для досвідчених користувачів. Ви можете вказати основну URL-адресу окремо для кожної служби." + }, + "baseUrl": { + "message": "URL-адреса сервера" + }, + "apiUrl": { + "message": "URL-адреса API" + }, + "webVaultUrl": { + "message": "URL-адреса сервера веб сховища" + }, + "identityUrl": { + "message": "URL-адреса сервера ідентифікації" + }, + "notificationsUrl": { + "message": "URL сервера сповіщень" + }, + "iconsUrl": { + "message": "URL-адреса сервера піктограм" + }, + "environmentSaved": { + "message": "URL-адреси середовища збережено." + }, + "enableAutoFillOnPageLoad": { + "message": "Автозаповнення на сторінці" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "При виявленні форми входу виконувати автоматичне її заповнення під час завантаження сторінки." + }, + "experimentalFeature": { + "message": "Це експериментальна функція. При її використанні ви берете ризик на себе." + }, + "defaultAutoFillOnPageLoad": { + "message": "Типове налаштування автозаповнення для записів входу" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "Після увімкнення автозаповнення на сторінці ви можете увімкнути чи вимкнути цю функцію для окремих записів входу. Це налаштування є типовим для записів входу, які не мають окремого налаштування." + }, + "itemAutoFillOnPageLoad": { + "message": "Автозаповнення на сторінці (якщо не увімкнено в налаштуваннях)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Типове налаштування" + }, + "autoFillOnPageLoadYes": { + "message": "Автозаповнення на сторінці" + }, + "autoFillOnPageLoadNo": { + "message": "Не заповнювати автоматично" + }, + "commandOpenPopup": { + "message": "Відкрити сховище у виринаючому вікні" + }, + "commandOpenSidebar": { + "message": "Відкрити сховище у бічній панелі" + }, + "commandAutofillDesc": { + "message": "Автозаповнення останнього використаного запису для цього вебсайту" + }, + "commandGeneratePasswordDesc": { + "message": "Генерувати і копіювати новий випадковий пароль в буфер обміну" + }, + "commandLockVaultDesc": { + "message": "Заблокувати сховище" + }, + "privateModeWarning": { + "message": "Приватний режим - це експериментальна функція і деякі можливості обмежені." + }, + "customFields": { + "message": "Власні поля" + }, + "copyValue": { + "message": "Копіювати значення" + }, + "value": { + "message": "Значення" + }, + "newCustomField": { + "message": "Нове власне поле" + }, + "dragToSort": { + "message": "Перетягніть, щоб відсортувати" + }, + "cfTypeText": { + "message": "Текст" + }, + "cfTypeHidden": { + "message": "Приховано" + }, + "cfTypeBoolean": { + "message": "Логічне значення" + }, + "cfTypeLinked": { + "message": "Пов'язано", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Пов'язане значення", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Натискання поза межами спливаючого вікна для перевірки коду підтвердження в пошті спричинить його закриття. Хочете відкрити його в новому вікні, щоб воно не закрилося?" + }, + "popupU2fCloseMessage": { + "message": "Цей браузер не може обробити U2F запити в цьому виринаючому вікні. Хочете відкрити його у новому вікні, щоб ви змогли увійти з використанням U2F?" + }, + "disableFavicon": { + "message": "Вимкнути піктограми вебсайтів" + }, + "disableFaviconDesc": { + "message": "Впізнавані піктограми вебсайтів додаються біля кожного запису вашого сховища." + }, + "disableBadgeCounter": { + "message": "Вимкнути лічильник значка" + }, + "disableBadgeCounterDesc": { + "message": "Лічильник значка показує кількість записів у сховищі для поточної сторінки." + }, + "cardholderName": { + "message": "Ім'я власника картки" + }, + "number": { + "message": "Номер" + }, + "brand": { + "message": "Тип картки" + }, + "expirationMonth": { + "message": "Місяць завершення" + }, + "expirationYear": { + "message": "Рік завершення" + }, + "expiration": { + "message": "Термін дії" + }, + "january": { + "message": "Січень" + }, + "february": { + "message": "Лютий" + }, + "march": { + "message": "Березень" + }, + "april": { + "message": "Квітень" + }, + "may": { + "message": "Травень" + }, + "june": { + "message": "Червень" + }, + "july": { + "message": "Липень" + }, + "august": { + "message": "Серпень" + }, + "september": { + "message": "Вересень" + }, + "october": { + "message": "Жовтень" + }, + "november": { + "message": "Листопад" + }, + "december": { + "message": "Грудень" + }, + "securityCode": { + "message": "Код безпеки" + }, + "ex": { + "message": "зразок" + }, + "title": { + "message": "Звернення" + }, + "mr": { + "message": "Містер" + }, + "mrs": { + "message": "Місіс" + }, + "ms": { + "message": "Міс" + }, + "dr": { + "message": "Доктор" + }, + "firstName": { + "message": "Ім’я" + }, + "middleName": { + "message": "По батькові" + }, + "lastName": { + "message": "Прізвище" + }, + "fullName": { + "message": "Повне ім'я" + }, + "identityName": { + "message": "Назва" + }, + "company": { + "message": "Компанія" + }, + "ssn": { + "message": "Номер соціального страхування" + }, + "passportNumber": { + "message": "Номер паспорта" + }, + "licenseNumber": { + "message": "Номер ліцензії" + }, + "email": { + "message": "Е-пошта" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адреса" + }, + "address1": { + "message": "Адреса 1" + }, + "address2": { + "message": "Адреса 2" + }, + "address3": { + "message": "Адреса 3" + }, + "cityTown": { + "message": "Місто / Селище" + }, + "stateProvince": { + "message": "Штат / Область" + }, + "zipPostalCode": { + "message": "Поштовий індекс" + }, + "country": { + "message": "Країна" + }, + "type": { + "message": "Тип" + }, + "typeLogin": { + "message": "Вхід" + }, + "typeLogins": { + "message": "Записи входу" + }, + "typeSecureNote": { + "message": "Захищена нотатка" + }, + "typeCard": { + "message": "Картка" + }, + "typeIdentity": { + "message": "Особисті дані" + }, + "passwordHistory": { + "message": "Історія паролів" + }, + "back": { + "message": "Назад" + }, + "collections": { + "message": "Збірки" + }, + "favorites": { + "message": "Обране" + }, + "popOutNewWindow": { + "message": "Відкрити в новому вікні" + }, + "refresh": { + "message": "Оновити" + }, + "cards": { + "message": "Картки" + }, + "identities": { + "message": "Особисті дані" + }, + "logins": { + "message": "Записи входу" + }, + "secureNotes": { + "message": "Захищені нотатки" + }, + "clear": { + "message": "Стерти", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Перевірити чи пароль було викрито." + }, + "passwordExposed": { + "message": "Цей пароль було викрито $VALUE$ разів з витоком даних. Вам слід його змінити.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Цей пароль не було знайдено у жодних відомих витоках даних. Його можна безпечно використовувати." + }, + "baseDomain": { + "message": "Основний домен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Ім'я домену", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Вузол", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Точно" + }, + "startsWith": { + "message": "Починається з" + }, + "regEx": { + "message": "Звичайний вираз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Виявлення збігів", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Типове виявлення збігів", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Перемкнути налаштування" + }, + "toggleCurrentUris": { + "message": "Перемкнути поточні URL-адреси", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "Поточна URL-адреса", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Організація", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Типи" + }, + "allItems": { + "message": "Всі елементи" + }, + "noPasswordsInList": { + "message": "Немає паролів." + }, + "remove": { + "message": "Вилучити" + }, + "default": { + "message": "Типово" + }, + "dateUpdated": { + "message": "Оновлено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Пароль оновлено", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Ви впевнені, що ніколи не хочете блокувати? Встановивши цю опцію, ключ шифрування вашого сховища зберігатиметься на вашому пристрої. Використовуючи цю опцію, вам слід бути певними в тому, що ваш пристрій має належний захист." + }, + "noOrganizationsList": { + "message": "Ви не входите до жодної організації. Організації дозволяють безпечно обмінюватися елементами з іншими користувачами." + }, + "noCollectionsInList": { + "message": "Немає збірок." + }, + "ownership": { + "message": "Власник" + }, + "whoOwnsThisItem": { + "message": "Хто є власником цього елемента?" + }, + "strong": { + "message": "Надійний", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Хороший", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабкий", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слабкий головний пароль" + }, + "weakMasterPasswordDesc": { + "message": "Обраний вами головний пароль є слабким. Для належного захисту свого облікового запису Bitwarden, вам слід використовувати надійний головний пароль (або парольну фразу). Ви впевнені, що хочете використати цей пароль?" + }, + "pin": { + "message": "PIN-код", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Розблокування з PIN-кодом" + }, + "setYourPinCode": { + "message": "Встановіть PIN-код для розблокування Bitwarden. Налаштування PIN-коду будуть скинуті, якщо ви коли-небудь повністю вийдете з програми." + }, + "pinRequired": { + "message": "Необхідний PIN-код." + }, + "invalidPin": { + "message": "Неправильний PIN-код." + }, + "unlockWithBiometrics": { + "message": "Розблокувати з біометрією" + }, + "awaitDesktop": { + "message": "Очікується підтвердження з комп'ютера" + }, + "awaitDesktopDesc": { + "message": "Для увімкнення біометрії в браузері, будь ласка, підтвердьте це у програмі Bitwarden на комп'ютері." + }, + "lockWithMasterPassOnRestart": { + "message": "Блокувати головним паролем при перезапуску браузера" + }, + "selectOneCollection": { + "message": "Ви повинні обрати принаймні одну збірку." + }, + "cloneItem": { + "message": "Клонувати запис" + }, + "clone": { + "message": "Клонувати" + }, + "passwordGeneratorPolicyInEffect": { + "message": "На параметри генератора впливають одна чи декілька політик організації." + }, + "vaultTimeoutAction": { + "message": "Дія після часу очікування сховища" + }, + "lock": { + "message": "Блокувати", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Смітник", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Пошук у смітнику" + }, + "permanentlyDeleteItem": { + "message": "Остаточно видалити запис" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Ви дійсно хочете остаточно видалити цей запис?" + }, + "permanentlyDeletedItem": { + "message": "Запис остаточно видалено" + }, + "restoreItem": { + "message": "Відновити запис" + }, + "restoreItemConfirmation": { + "message": "Ви дійсно хочете відновити цей запис?" + }, + "restoredItem": { + "message": "Запис відновлено" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Вихід скасує всі права доступу до вашого сховища і вимагатиме авторизації після завершення часу очікування. Ви дійсно хочете використати цей параметр?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Підтвердження дії часу очікування" + }, + "autoFillAndSave": { + "message": "Заповнити і зберегти" + }, + "autoFillSuccessAndSavedUri": { + "message": "Запис заповнено і збережено" + }, + "autoFillSuccess": { + "message": "Запис заповнено" + }, + "setMasterPassword": { + "message": "Встановити головний пароль" + }, + "masterPasswordPolicyInEffect": { + "message": "Одна або декілька політик організації вимагають дотримання таких вимог для головного пароля:" + }, + "policyInEffectMinComplexity": { + "message": "Мінімальний рівень складності $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Мінімальна довжина $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Наявність одного чи більше символів верхнього регістру" + }, + "policyInEffectLowercase": { + "message": "Наявність одного чи більше символів нижнього регістру" + }, + "policyInEffectNumbers": { + "message": "Наявність однієї чи більше цифр" + }, + "policyInEffectSpecial": { + "message": "Наявність одного чи більше таких спеціальних символів: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваш новий головний пароль не задовольняє вимоги політики." + }, + "acceptPolicies": { + "message": "Позначивши цей прапорець, ви погоджуєтеся з:" + }, + "acceptPoliciesError": { + "message": "Умови користування та політика приватності не погоджені." + }, + "termsOfService": { + "message": "Умови користування" + }, + "privacyPolicy": { + "message": "Політика приватності" + }, + "hintEqualsPassword": { + "message": "Підказка для пароля не може бути такою самою, як ваш пароль." + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Перевірка синхронізації на комп'ютері" + }, + "desktopIntegrationVerificationText": { + "message": "Перевірте, чи програма на комп'ютері показує відбиток: " + }, + "desktopIntegrationDisabledTitle": { + "message": "Інтеграція з браузером не увімкнена" + }, + "desktopIntegrationDisabledDesc": { + "message": "Інтеграція з браузером не увімкнена в програмі Bitwarden на комп'ютері. Увімкніть її в налаштуваннях програми на комп'ютері." + }, + "startDesktopTitle": { + "message": "Запустіть програму Bitwarden на комп'ютері" + }, + "startDesktopDesc": { + "message": "Для можливості розблокування з біометрією необхідно запустити програму Bitwarden на комп'ютері." + }, + "errorEnableBiometricTitle": { + "message": "Не вдається увімкнути біометрію" + }, + "errorEnableBiometricDesc": { + "message": "Дію було скасовано програмою на комп'ютері" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Програма на комп'ютері не схвалила безпечний канал зв'язку. Будь ласка, спробуйте знову" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "З'єднання з комп'ютером перервано" + }, + "nativeMessagingWrongUserDesc": { + "message": "Програма на комп'ютері використовує інший обліковий запис. Переконайтеся, що програма й розширення використовують однаковий обліковий запис." + }, + "nativeMessagingWrongUserTitle": { + "message": "Невідповідність облікових записів" + }, + "biometricsNotEnabledTitle": { + "message": "Біометрію не увімкнено" + }, + "biometricsNotEnabledDesc": { + "message": "Для активації біометрії в браузері необхідно спершу увімкнути біометрію в програмі на комп'ютері." + }, + "biometricsNotSupportedTitle": { + "message": "Біометрія не підтримується" + }, + "biometricsNotSupportedDesc": { + "message": "Біометрія в браузері не підтримується на цьому пристрої." + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Дозвіл не надано" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Без дозволу з'єднання з програмою Bitwarden на комп'ютері неможливо використовувати біометрію в розширенні браузера. Спробуйте знову." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Помилка запиту дозволу" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "Цю дію неможливо виконати в бічній панелі. Спробуйте знову в спливному чи окремому вікні." + }, + "personalOwnershipSubmitError": { + "message": "У зв'язку з корпоративною політикою, вам не дозволено зберігати записи до особистого сховища. Змініть налаштування власності на організацію та виберіть серед доступних збірок." + }, + "personalOwnershipPolicyInEffect": { + "message": "Політика організації впливає на ваші параметри власності." + }, + "excludedDomains": { + "message": "Виключені домени" + }, + "excludedDomainsDesc": { + "message": "Bitwarden не запитуватиме про збереження даних входу для цих доменів. Ви повинні оновити сторінку для застосування змін." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ не є дійсним доменом", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Пошук відправлень", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Додати відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Текст" + }, + "sendTypeFile": { + "message": "Файл" + }, + "allSends": { + "message": "Усі відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Досягнуто максимальну кількість доступів", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Термін дії завершився" + }, + "pendingDeletion": { + "message": "Очікується видалення" + }, + "passwordProtected": { + "message": "Захищено паролем" + }, + "copySendLink": { + "message": "Копіювати посилання відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Вилучити пароль" + }, + "delete": { + "message": "Видалити" + }, + "removedPassword": { + "message": "Пароль вилучено" + }, + "deletedSend": { + "message": "Відправлення видалено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Посилання на відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Вимкнено" + }, + "removePasswordConfirmation": { + "message": "Ви дійсно хочете вилучити пароль?" + }, + "deleteSend": { + "message": "Видалити відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Ви дійсно хочете видалити це відправлення?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Змінити відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Який це тип відправлення?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Опис цього відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Файл, який ви хочете відправити." + }, + "deletionDate": { + "message": "Дата видалення" + }, + "deletionDateDesc": { + "message": "Відправлення буде остаточно видалено у вказаний час.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Дата завершення" + }, + "expirationDateDesc": { + "message": "Якщо встановлено, термін дії цього відправлення завершиться у вказаний час.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 день" + }, + "days": { + "message": "$DAYS$ днів", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Спеціальний" + }, + "maximumAccessCount": { + "message": "Максимальна кількість доступів" + }, + "maximumAccessCountDesc": { + "message": "Якщо встановлено, користувачі більше не зможуть отримати доступ до цього відправлення після досягнення максимальної кількості доступів.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "За бажанням вимагати пароль в користувачів для доступу до цього відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Особисті нотатки про це відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Деактивувати це відправлення для скасування доступу до нього.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Копіювати посилання цього відправлення перед збереженням.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст, який ви хочете відправити." + }, + "sendHideText": { + "message": "Приховувати текст цього відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Поточна кількість доступів" + }, + "createSend": { + "message": "Створити нове відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Новий пароль" + }, + "sendDisabled": { + "message": "Відправлення вимкнено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "У зв'язку з політикою компанії, ви можете лише видалити наявне відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Відправлення створено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Відправлення змінено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "Щоб вибрати файл, відкрийте розширення в бічній панелі (якщо можливо) або в новому вікні, натиснувши цей банер." + }, + "sendFirefoxFileWarning": { + "message": "Щоб вибрати файл з використанням Firefox, відкрийте розширення в бічній панелі або в новому вікні, натиснувши цей банер." + }, + "sendSafariFileWarning": { + "message": "Щоб вибрати файл з використанням Safari, відкрийте розширення в новому вікні, натиснувши на цей банер." + }, + "sendFileCalloutHeader": { + "message": "Перед початком" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "Щоб використовувати календарний стиль вибору дати", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "натисніть тут", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "щоб відкріпити ваше вікно.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "Вказано недійсний термін дії." + }, + "deletionDateIsInvalid": { + "message": "Вказано недійсну дату видалення." + }, + "expirationDateAndTimeRequired": { + "message": "Необхідно вказати час і дату терміну дії." + }, + "deletionDateAndTimeRequired": { + "message": "Необхідно вказати час і дату видалення." + }, + "dateParsingError": { + "message": "При збереженні дат видалення і терміну дії виникла помилка." + }, + "hideEmail": { + "message": "Приховувати мою адресу електронної пошти від отримувачів." + }, + "sendOptionsPolicyInEffect": { + "message": "На параметри відправлень впливають одна чи декілька політик організації." + }, + "passwordPrompt": { + "message": "Повторний запит головного пароля" + }, + "passwordConfirmation": { + "message": "Підтвердження головного пароля" + }, + "passwordConfirmationDesc": { + "message": "Ця дія захищена. Щоб продовжити, повторно введіть головний пароль." + }, + "emailVerificationRequired": { + "message": "Необхідно підтвердити е-пошту" + }, + "emailVerificationRequiredDesc": { + "message": "Для використання цієї функції необхідно підтвердити електронну пошту. Ви можете виконати підтвердження у веб сховищі." + }, + "updatedMasterPassword": { + "message": "Головний пароль оновлено" + }, + "updateMasterPassword": { + "message": "Оновити головний пароль" + }, + "updateMasterPasswordWarning": { + "message": "Ваш головний пароль нещодавно був змінений адміністратором організації. Щоб отримати доступ до сховища, ви повинні оновити його зараз. Продовживши, ви вийдете з поточного сеансу, після чого необхідно буде повторно виконати вхід. Сеанси на інших пристроях можуть залишатися активними протягом однієї години." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Автоматичне розгортання" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ця організація має корпоративну політику, яка автоматично розгортає вас на скидання пароля. Розгортання дозволятиме адміністраторам організації змінювати ваш головний пароль." + }, + "selectFolder": { + "message": "Обрати теку..." + }, + "ssoCompleteRegistration": { + "message": "Щоб завершити налаштування входу з SSO, встановіть головний пароль для доступу і захисту сховища." + }, + "hours": { + "message": "Годин" + }, + "minutes": { + "message": "Хвилин" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Політики вашої організації впливають на час очікування сховища. Максимальний дозволений час очікування сховища $HOURS$ годин, $MINUTES$ хвилин", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Час очікування сховища перевищує обмеження, встановлені вашою організацією." + }, + "vaultExportDisabled": { + "message": "Експорт сховища вимкнено" + }, + "personalVaultExportPolicyInEffect": { + "message": "Одна чи декілька організаційних політик не дозволяють вам експортувати особисте сховище." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Не вдається ідентифікувати дійсний елемент форми. Спробуйте натомість інспектувати HTML." + }, + "copyCustomFieldNameNotUnique": { + "message": "Не знайдено унікальний ідентифікатор." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ використовує SSO з власним сервером ключів. Головний пароль для учасників цієї організації більше не вимагається.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Покинути організацію" + }, + "removeMasterPassword": { + "message": "Вилучити головний пароль" + }, + "removedMasterPassword": { + "message": "Головний пароль вилучено." + }, + "leaveOrganizationConfirmation": { + "message": "Ви справді хочете покинути цю організацію?" + }, + "leftOrganization": { + "message": "Ви покинули організацію." + }, + "toggleCharacterCount": { + "message": "Перемкнути лічильник символів" + }, + "sessionTimeout": { + "message": "Час вашого сеансу завершився. Поверніться назад і спробуйте увійти знову." + }, + "exportingPersonalVaultTitle": { + "message": "Експортування особистого сховища" + }, + "exportingPersonalVaultDescription": { + "message": "Будуть експортовані лише записи особистого сховища, пов'язані з $EMAIL$. Записи сховища організації не буде включено.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Помилка" + }, + "regenerateUsername": { + "message": "Повторно генерувати ім'я користувача" + }, + "generateUsername": { + "message": "Генерувати ім'я користувача" + }, + "usernameType": { + "message": "Тип імені користувача" + }, + "plusAddressedEmail": { + "message": "Плюс адреса електронної пошти", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Використовуйте розширені можливості адрес вашого постачальника електронної пошти." + }, + "catchallEmail": { + "message": "Адреса е-пошти Catch-all" + }, + "catchallEmailDesc": { + "message": "Використовуйте свою скриньку вхідних Catch-All власного домену." + }, + "random": { + "message": "Випадково" + }, + "randomWord": { + "message": "Випадкове слово" + }, + "websiteName": { + "message": "Назва вебсайту" + }, + "whatWouldYouLikeToGenerate": { + "message": "Що ви бажаєте згенерувати?" + }, + "passwordType": { + "message": "Тип пароля" + }, + "service": { + "message": "Послуга" + } +} diff --git a/apps/browser/src/_locales/vi/messages.json b/apps/browser/src/_locales/vi/messages.json new file mode 100644 index 0000000000..0ee9af993c --- /dev/null +++ b/apps/browser/src/_locales/vi/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Một trình quản lý mật khẩu an toàn và miễn phí cho mọi thiết bị của bạn.", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "Đăng nhập hoặc tạo tài khoản mới để truy cập kho mật khẩu của bạn." + }, + "createAccount": { + "message": "Tạo Tài Khoản" + }, + "login": { + "message": "Đăng Nhập" + }, + "enterpriseSingleSignOn": { + "message": "Đăng nhập theo tài khoản tổ chức" + }, + "cancel": { + "message": "Hủy bỏ" + }, + "close": { + "message": "Đóng" + }, + "submit": { + "message": "Gửi" + }, + "emailAddress": { + "message": "Địa chỉ Email" + }, + "masterPass": { + "message": "Mật khẩu chính" + }, + "masterPassDesc": { + "message": "Mật khẩu chủ là mật khẩu bạn sử dụng để truy cập kho mật khẩu của bạn. Nó rất quan trọng nên bạn không được quên mật khẩu chủ của mình. Không thể khôi phục lại mật khẩu chủ nếu bạn quên nó." + }, + "masterPassHintDesc": { + "message": "Một gợi ý mật khẩu có thể giúp bạn nhớ lại mật khẩu chủ của bạn nếu bạn quên nó." + }, + "reTypeMasterPass": { + "message": "Nhập lại mật khẩu chính" + }, + "masterPassHint": { + "message": "Gợi ý mật khẩu chính (tùy chọn)" + }, + "tab": { + "message": "Thẻ" + }, + "myVault": { + "message": "Hầm của tôi" + }, + "tools": { + "message": "Công cụ" + }, + "settings": { + "message": "Cài đặt" + }, + "currentTab": { + "message": "Thẻ hiện tại" + }, + "copyPassword": { + "message": "Sao chép Mật khẩu" + }, + "copyNote": { + "message": "Sao chép Ghi chú" + }, + "copyUri": { + "message": "Sao chép URL" + }, + "copyUsername": { + "message": "Sao chép tên đăng nhập" + }, + "copyNumber": { + "message": "Sao chép Số" + }, + "copySecurityCode": { + "message": "Sao chép Mã bảo mật" + }, + "autoFill": { + "message": "Tự động điền" + }, + "generatePasswordCopied": { + "message": "Tạo mật khẩu (đã sao chép)" + }, + "copyElementIdentifier": { + "message": "Sao chép Tên trường Tùy chỉnh" + }, + "noMatchingLogins": { + "message": "Không có thông tin đăng nhập phù hợp." + }, + "unlockVaultMenu": { + "message": "Mở khóa bảo mật" + }, + "loginToVaultMenu": { + "message": "Đăng nhập tài khoản bảo mật" + }, + "autoFillInfo": { + "message": "Không có thông tin đăng nhập nào sẵn có để tự động điền vào tab hiện tại." + }, + "addLogin": { + "message": "Thêm một Đăng nhập" + }, + "addItem": { + "message": "Thêm Mục" + }, + "passwordHint": { + "message": "Gợi ý mật khẩu" + }, + "enterEmailToGetHint": { + "message": "Nhập địa chỉ email tài khoản của bạn để nhận gợi ý mật khẩu chủ." + }, + "getMasterPasswordHint": { + "message": "Nhận gợi ý mật khẩu chủ" + }, + "continue": { + "message": "Tiếp tục" + }, + "sendVerificationCode": { + "message": "Gửi mã xác minh tới email của bạn" + }, + "sendCode": { + "message": "Gửi mã" + }, + "codeSent": { + "message": "Đã gửi mã" + }, + "verificationCode": { + "message": "Mã xác nhận" + }, + "confirmIdentity": { + "message": "Xác nhận nhận dạng của bạn để tiếp tục" + }, + "account": { + "message": "Tài khoản" + }, + "changeMasterPassword": { + "message": "Thay đổi mật khẩu chính" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Cụm từ mật khẩu của tài khoản của bạn", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "Xác thực hai lớp" + }, + "logOut": { + "message": "Đăng xuất" + }, + "about": { + "message": "Thông tin" + }, + "version": { + "message": "Phiên bản" + }, + "save": { + "message": "Lưu" + }, + "move": { + "message": "Chuyển" + }, + "addFolder": { + "message": "Thêm thư mục" + }, + "name": { + "message": "Tên mục" + }, + "editFolder": { + "message": "Chỉnh sửa thư mục" + }, + "deleteFolder": { + "message": "Xóa thư mục" + }, + "folders": { + "message": "Thư mục" + }, + "noFolders": { + "message": "Không có thư mục để liệt kê." + }, + "helpFeedback": { + "message": "Trợ giúp & Phản hồi" + }, + "sync": { + "message": "Đồng bộ" + }, + "syncVaultNow": { + "message": "Đồng bộ Kho mật khẩu ngay" + }, + "lastSync": { + "message": "Lần đồng bộ gần nhất:" + }, + "passGen": { + "message": "Tạo mật khẩu" + }, + "generator": { + "message": "Tạo mật khẩu", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "Tự động tạo mật khẩu mạnh mẽ, duy nhất cho đăng nhập của bạn." + }, + "bitWebVault": { + "message": "Hầm bitwarden trên Web" + }, + "importItems": { + "message": "Nhập mục" + }, + "select": { + "message": "Chọn" + }, + "generatePassword": { + "message": "Tạo mật khẩu" + }, + "regeneratePassword": { + "message": "Tạo lại mật khẩu" + }, + "options": { + "message": "Tùy chọn" + }, + "length": { + "message": "Độ dài" + }, + "uppercase": { + "message": "Chữ in hoa (A-Z)" + }, + "lowercase": { + "message": "Chữ in thường (a-z)" + }, + "numbers": { + "message": "Chữ số (0-9)" + }, + "specialCharacters": { + "message": "Ký tự đặc biệt (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Viết hoa", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Bao gồm cả số" + }, + "minNumbers": { + "message": "Số kí tự tối thiểu" + }, + "minSpecial": { + "message": "Số kí tự đặc biệt tối thiểu" + }, + "avoidAmbChar": { + "message": "Tránh các ký tự không rõ ràng" + }, + "searchVault": { + "message": "Tìm kiếm trong kho" + }, + "edit": { + "message": "Sửa" + }, + "view": { + "message": "Xem" + }, + "noItemsInList": { + "message": "Không có mục nào để liệt kê." + }, + "itemInformation": { + "message": "Mục thông tin" + }, + "username": { + "message": "Tên người dùng" + }, + "password": { + "message": "Mật khẩu" + }, + "passphrase": { + "message": "Cụm từ mật khẩu" + }, + "favorite": { + "message": "Yêu thích" + }, + "notes": { + "message": "Ghi chú" + }, + "note": { + "message": "Ghi chú" + }, + "editItem": { + "message": "Chỉnh sửa mục" + }, + "folder": { + "message": "Thư mục" + }, + "deleteItem": { + "message": "Xóa mục" + }, + "viewItem": { + "message": "Xem mục" + }, + "launch": { + "message": "Khởi chạy" + }, + "website": { + "message": "Trang web" + }, + "toggleVisibility": { + "message": "Bật/tắt khả năng hiển thị" + }, + "manage": { + "message": "Quản lý" + }, + "other": { + "message": "Khác" + }, + "rateExtension": { + "message": "Đánh giá tiện ích mở rộng" + }, + "rateExtensionDesc": { + "message": "Xin hãy nhìn nhận và đánh giá tốt cho chúng tôi!" + }, + "browserNotSupportClipboard": { + "message": "Trình duyệt web của bạn không hỗ trợ dễ dàng sao chép bộ nhớ tạm. Bạn có thể sao chép nó theo cách thủ công để thay thế." + }, + "verifyIdentity": { + "message": "Mã xác minh" + }, + "yourVaultIsLocked": { + "message": "Kho của bạn đã bị khóa. Xác minh mật khẩu chính của bạn để mở." + }, + "unlock": { + "message": "Mở khóa" + }, + "loggedInAsOn": { + "message": "Đã đăng nhập là $EMAIL$ trên $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Mật khẩu chủ không hợp lệ" + }, + "vaultTimeout": { + "message": "Thời Gian Chờ Của Kho" + }, + "lockNow": { + "message": "Khóa ngay" + }, + "immediately": { + "message": "Tức thì" + }, + "tenSeconds": { + "message": "10 giây" + }, + "twentySeconds": { + "message": "20 giây" + }, + "thirtySeconds": { + "message": "30 giây" + }, + "oneMinute": { + "message": "1 phút" + }, + "twoMinutes": { + "message": "2 phút" + }, + "fiveMinutes": { + "message": "5 phút" + }, + "fifteenMinutes": { + "message": "15 phút" + }, + "thirtyMinutes": { + "message": "30 phút" + }, + "oneHour": { + "message": "1 giờ" + }, + "fourHours": { + "message": "4 giờ" + }, + "onLocked": { + "message": "Mỗi khi khóa" + }, + "onRestart": { + "message": "Mỗi khi khởi động lại trình duyệt" + }, + "never": { + "message": "Không bao giờ" + }, + "security": { + "message": "Bảo mật" + }, + "errorOccurred": { + "message": "Đã xảy ra lỗi chưa xác định" + }, + "emailRequired": { + "message": "Địa chỉ email là bắt buộc." + }, + "invalidEmail": { + "message": "Địa chỉ email không hợp lệ." + }, + "masterPassRequired": { + "message": "Mật khẩu chủ là bắt buộc." + }, + "masterPassLength": { + "message": "Mật khẩu chủ phải có ít nhất 8 kí tự." + }, + "masterPassDoesntMatch": { + "message": "Xác nhận mật khẩu chủ không khớp." + }, + "newAccountCreated": { + "message": "Tài khoản của bạn đã được tạo. Bạn có thể đăng nhập bây giờ." + }, + "masterPassSent": { + "message": "Chúng tôi đã gửi cho bạn email có chứa gợi ý mật khẩu chủ của bạn." + }, + "verificationCodeRequired": { + "message": "Yêu cầu mã xác nhận." + }, + "invalidVerificationCode": { + "message": "Mã xác minh không đúng" + }, + "valueCopied": { + "message": "$VALUE$ đã sao chép", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "Tự động điền thông tin đăng nhập trong hoạt động trên trang này. Bạn có thể thực hiện thủ công bằng cách sao chép/dán thông tin đăng nhập." + }, + "loggedOut": { + "message": "Đăng xuất" + }, + "loginExpired": { + "message": "Phiên đăng nhập của bạn đã hết hạn." + }, + "logOutConfirmation": { + "message": "Bạn có chắc chắn muốn đăng xuất không?" + }, + "yes": { + "message": "Có" + }, + "no": { + "message": "Không" + }, + "unexpectedError": { + "message": "Một lỗi bất ngờ đã xảy ra." + }, + "nameRequired": { + "message": "Tên là bắt buộc." + }, + "addedFolder": { + "message": "Thêm thư mục" + }, + "changeMasterPass": { + "message": "Thay đổi mật khẩu chính" + }, + "changeMasterPasswordConfirmation": { + "message": "Bạn có thể thay đổi mật khẩu chủ trong trang web Bitwarden. Bạn có muốn truy cập bitwarden.com bây giờ?" + }, + "twoStepLoginConfirmation": { + "message": "Xác thực hai lớp giúp cho tài khoản của bạn an toàn hơn bằng cách yêu cầu bạn xác minh thông tin đăng nhập của bạn bằng một thiết bị khác như khóa bảo mật, ứng dụng xác thực, SMS, cuộc gọi điện thoại hoặc email. Bạn có thể bật xác thực hai lớp trong trang web Bitwarden. Bạn có muốn ghé thăm bitwarden.com bây giờ?" + }, + "editedFolder": { + "message": "Chỉnh sửa Thư mục" + }, + "deleteFolderConfirmation": { + "message": "Bạn có chắc chắn muốn xóa thư mục này không?" + }, + "deletedFolder": { + "message": "Đã xóa thư mục" + }, + "gettingStartedTutorial": { + "message": "Hướng dẫn Bắt đầu" + }, + "gettingStartedTutorialVideo": { + "message": "Xem hướng dẫn bắt đầu của chúng tôi để tìm hiểu cách tận dụng tối đa tiện ích mở rộng của trình duyệt." + }, + "syncingComplete": { + "message": "Đồng bộ hoàn tất" + }, + "syncingFailed": { + "message": "Đồng bộ thất bại" + }, + "passwordCopied": { + "message": "Đã sao chép mật khẩu" + }, + "uri": { + "message": "Đường dẫn" + }, + "uriPosition": { + "message": "URL $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "URL Mới" + }, + "addedItem": { + "message": "Đã thêm mục" + }, + "editedItem": { + "message": "Mục được chỉnh sửa" + }, + "deleteItemConfirmation": { + "message": "Bạn có chắc bạn muốn xóa mục này?" + }, + "deletedItem": { + "message": "Đã xóa mục" + }, + "overwritePassword": { + "message": "Ghi đè lên mật khẩu" + }, + "overwritePasswordConfirmation": { + "message": "Bạn có chắc chắn muốn ghi đè mật khẩu hiện tại không?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "searchFolder": { + "message": "Tìm kiếm thư mục" + }, + "searchCollection": { + "message": "Tìm kiếm bộ sưu tập" + }, + "searchType": { + "message": "Tìm mục" + }, + "noneFolder": { + "message": "Không có thư mục", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "Vô hiệu thông báo Thêm đăng nhập" + }, + "addLoginNotificationDesc": { + "message": "'Thông báo Thêm đăng nhập' sẽ tự động nhắc bạn lưu các đăng nhập mới vào hầm an toàn của bạn bất cứ khi nào bạn đăng nhập trang web lần đầu tiên." + }, + "dontShowCardsCurrentTab": { + "message": "Don't Show Cards on Tab Page" + }, + "dontShowCardsCurrentTabDesc": { + "message": "Card items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "dontShowIdentitiesCurrentTab": { + "message": "Don't Show Identities on Tab Page" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "Identity items from your vault are listed on the 'Current Tab' page for easy auto-fill access." + }, + "clearClipboard": { + "message": "Dọn dẹp khay nhớ tạm", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Tự động dọn dẹp giá trị được sao chép khỏi khay nhớ tạm của bạn.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "Bạn có cần Bitwarden nhớ giúp bạn mật khẩu này không?" + }, + "notificationAddSave": { + "message": "Vâng, Lưu Ngay" + }, + "disableChangedPasswordNotification": { + "message": "Disable Changed Password Notification" + }, + "disableChangedPasswordNotificationDesc": { + "message": "The \"Changed Password Notification\" automatically prompts you to update a login's password in your vault whenever it detects that you have changed it on a website." + }, + "notificationChangeDesc": { + "message": "Bạn có muốn cập nhật mật khẩu này trên Bitwarden không?" + }, + "notificationChangeSave": { + "message": "Yes, Update Now" + }, + "disableContextMenuItem": { + "message": "Tắt tuỳ chọn trong Menu Ngữ Cảnh" + }, + "disableContextMenuItemDesc": { + "message": "Tùy chọn menu ngữ cảnh giúp bạn truy cập nhanh thông tin đăng nhập và tạo mật khẩu cho trang web trong tab mà bạn đang mở." + }, + "defaultUriMatchDetection": { + "message": "Phương thức kiểm tra URI mặc định", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "Chọn phương thức mặc định để kiểm tra so sánh URI cho các đăng nhập khi xử lí các hành động như là tự động điền." + }, + "theme": { + "message": "Giao diện" + }, + "themeDesc": { + "message": "Thay đổi màu sắc ứng dụng." + }, + "dark": { + "message": "Tối", + "description": "Dark color" + }, + "light": { + "message": "Sáng", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "Xuất Kho" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "CẢNH BÁO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Xác nhận xuất mật khẩu" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Nhập mật khẩu chủ để xuất kho dữ liệu của bạn." + }, + "shared": { + "message": "Đã chia sẻ" + }, + "learnOrg": { + "message": "Xem tổ chức của bạn" + }, + "learnOrgConfirmation": { + "message": "Bitwarden allows you to share your vault items with others by using an organization. Would you like to visit the bitwarden.com website to learn more?" + }, + "moveToOrganization": { + "message": "Chuyển tới Tổ chức" + }, + "share": { + "message": "Chia sẻ" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ chuyển tới $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "learnMore": { + "message": "Tìm hiểu thêm" + }, + "authenticatorKeyTotp": { + "message": "Khóa xác thực (TOTP)" + }, + "verificationCodeTotp": { + "message": "Mã xác thực (TOTP)" + }, + "copyVerificationCode": { + "message": "Sao chép Mã xác thực" + }, + "attachments": { + "message": "Tệp đính kèm" + }, + "deleteAttachment": { + "message": "Xóa tệp đính kèm" + }, + "deleteAttachmentConfirmation": { + "message": "Bạn có muốn xóa tệp đính kèm này không?" + }, + "deletedAttachment": { + "message": "Đã xoá tệp đính kèm" + }, + "newAttachment": { + "message": "Thêm tệp đính kèm mới" + }, + "noAttachments": { + "message": "Không có tệp đính kèm." + }, + "attachmentSaved": { + "message": "Tệp đính kèm đã được lưu." + }, + "file": { + "message": "Tập tin" + }, + "selectFile": { + "message": "Chọn 1 tập tin." + }, + "maxFileSize": { + "message": "Kích thước tối đa của tệp tin là 500MB." + }, + "featureUnavailable": { + "message": "Tính năng không có sẵn" + }, + "updateKey": { + "message": "Bạn không thể sử dụng tính năng này cho đến khi bạn cập nhật khoá mã hóa." + }, + "premiumMembership": { + "message": "Thành viên Cao Cấp" + }, + "premiumManage": { + "message": "Quản lý Thành viên" + }, + "premiumManageAlert": { + "message": "Bạn có thể quản lý các thành viên trong trang web Bitwarden. Bạn có muốn truy cập bitwarden.com bây giờ?" + }, + "premiumRefresh": { + "message": "Làm mới thành viên" + }, + "premiumNotCurrentMember": { + "message": "Bạn hiện không phải là một thành viên cao cấp." + }, + "premiumSignUpAndGet": { + "message": "Đăng ký làm thành viên cao cấp và nhận được:" + }, + "ppremiumSignUpStorage": { + "message": "1GB bộ nhớ lưu trữ tập tin được mã hóa." + }, + "ppremiumSignUpTwoStep": { + "message": "Các tùy chọn xác thực hai lớp bổ sung như YubiKey, FIDO U2F và Duo." + }, + "ppremiumSignUpReports": { + "message": "Thanh lọc mật khẩu, kiểm tra an toàn tài khoản và các báo cáo rò rĩ dữ liệu là để giữ cho kho của bạn an toàn." + }, + "ppremiumSignUpTotp": { + "message": "Mã xác nhận TOTP (2FA) để đăng nhập vào kho mật khẩu của bạn." + }, + "ppremiumSignUpSupport": { + "message": "Hỗ trợ khách hàng ưu tiên." + }, + "ppremiumSignUpFuture": { + "message": "Tất cả các tính năng cao cấp trong tương lai. Nó sẽ sớm xuất hiện!" + }, + "premiumPurchase": { + "message": "Mua bản Cao Cấp" + }, + "premiumPurchaseAlert": { + "message": "Bạn có thể nâng cấp làm thành viên cao cấp trong trang web Bitwarden. Bạn có muốn truy cập bitwarden.com bây giờ?" + }, + "premiumCurrentMember": { + "message": "Bạn là một thành viên cao cấp!" + }, + "premiumCurrentMemberThanks": { + "message": "Cảm ơn bạn đã hỗ trợ Bitwarden." + }, + "premiumPrice": { + "message": "Tất cả chỉ với $PRICE$ /năm!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Làm mới hoàn tất" + }, + "disableAutoTotpCopy": { + "message": "Vô hiệu hoá tự động sao chép TOTP" + }, + "disableAutoTotpCopyDesc": { + "message": "Nếu đăng nhập của bạn có một khóa xác thực gắn liền với nó, mã xác nhận TOTP sẽ được tự động sao chép vào bộ nhớ tạm của bạn bất cứ khi nào bạn tự động điền thông tin đăng nhập." + }, + "disableAutoBiometricsPrompt": { + "message": "Không nhắc bảo mật sinh trắc học khi khởi chạy" + }, + "premiumRequired": { + "message": "Cần có tài khoản cao cấp" + }, + "premiumRequiredDesc": { + "message": "Cần là thành viên cao cấp để sử dụng tính năng này." + }, + "enterVerificationCodeApp": { + "message": "Nhập mã xác nhận 6 chữ số từ ứng dụng xác thực của bạn." + }, + "enterVerificationCodeEmail": { + "message": "Nhập mã xác nhận 6 chữ số đã được gửi tới $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Email xác minh được gửi tới $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Ghi nhớ đăng nhập" + }, + "sendVerificationCodeEmailAgain": { + "message": "Gửi lại email chứa mã xác nhận" + }, + "useAnotherTwoStepMethod": { + "message": "Sử dụng phương pháp xác thực hai lớp khác" + }, + "insertYubiKey": { + "message": "Lắp YubiKey vào cổng USB máy tính của bạn, sau đó chạm vào nút trên nó." + }, + "insertU2f": { + "message": "Lắp khóa bảo mật vào cổng USB của máy tính. Nếu nó có một nút, nhấn vào nó." + }, + "webAuthnNewTab": { + "message": "To start the WebAuthn 2FA verification. Click the button below to open a new tab and follow the instructions provided in the new tab." + }, + "webAuthnNewTabOpen": { + "message": "Mở thẻ mới" + }, + "webAuthnAuthenticate": { + "message": "Xác thực WebAuthn" + }, + "loginUnavailable": { + "message": "Đăng nhập không sẵn có" + }, + "noTwoStepProviders": { + "message": "Tài khoản này đã kích hoạt xác thực hai lớp, tuy nhiên, trình duyệt này không hỗ trợ cấu hình dịch vụ xác thực hai lớp đang sử dụng." + }, + "noTwoStepProviders2": { + "message": "Vui lòng sử dụng trình duyệt web được hỗ trợ (chẳng hạn như Chrome) và/hoặc thêm dịch vụ bổ sung được hỗ trợ tốt hơn trên các trình duyệt web (chẳng hạn như một ứng dụng xác thực)." + }, + "twoStepOptions": { + "message": "Tùy chọn xác thực hai lớp" + }, + "recoveryCodeDesc": { + "message": "Bạn mất quyền truy cập vào tất cả các dịch vụ xác thực 2 lớp? Sử dụng mã phục hồi của bạn để vô hiệu hóa tất cả các dịch vụ xác thực hai lớp trong tài khoản của bạn." + }, + "recoveryCodeTitle": { + "message": "Mã phục hồi" + }, + "authenticatorAppTitle": { + "message": "Ứng dụng Authenticator" + }, + "authenticatorAppDesc": { + "message": "Sử dụng một ứng dụng xác thực (chẳng hạn như Authy hoặc Google Authenticator) để tạo các mã xác nhận theo thời gian thực.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Khóa bảo mật YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Sử dụng YubiKey để truy cập tài khoản của bạn. Làm việc với thiết bị YubiKey 4, 4 Nano, 4C và NEO." + }, + "duoDesc": { + "message": "Xác minh với Duo Security sử dụng ứng dụng Duo Mobile, SMS, cuộc gọi điện thoại, hoặc khoá bảo mật U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Xác minh với Duo Security cho tổ chức của bạn sử dụng ứng dụng Duo Mobile, SMS, cuộc gọi điện thoại, hoặc khoá bảo mật U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Mã xác thực sẽ được gửi qua email cho bạn." + }, + "selfHostedEnvironment": { + "message": "Môi trường độc lập" + }, + "selfHostedEnvironmentFooter": { + "message": "Chỉ định liên kết cơ bản của cài đặt bitwarden tại chỗ của bạn." + }, + "customEnvironment": { + "message": "Môi trường tùy chỉnh" + }, + "customEnvironmentFooter": { + "message": "Đối với người dùng nâng cao. Bạn có thể chỉ định liên kết cơ bản của mỗi dịch vụ một cách độc lập." + }, + "baseUrl": { + "message": "Địa chỉ máy chủ" + }, + "apiUrl": { + "message": "Địa chỉ API máy chủ" + }, + "webVaultUrl": { + "message": "Địa chỉ máy chủ kho web" + }, + "identityUrl": { + "message": "Địa chỉ nhận dạng máy chủ" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Biểu tượng địa chỉ máy chủ" + }, + "environmentSaved": { + "message": "Địa chỉ môi trường đã được lưu." + }, + "enableAutoFillOnPageLoad": { + "message": "Bật Tự động điền vào Tải trang" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "Nếu có một biểu mẫu đăng nhập được phát hiện, thực hiện tự động điền khi trang web tải xong." + }, + "experimentalFeature": { + "message": "Đây là một tính năng thử nghiệm. Sử dụng nó có thể gây ra rủi ro cho bạn." + }, + "defaultAutoFillOnPageLoad": { + "message": "Default autofill setting for login items" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "After enabling Auto-fill on Page Load, you can enable or disable the feature for individual login items. This is the default setting for login items that are not separately configured." + }, + "itemAutoFillOnPageLoad": { + "message": "Tự động điền khi tải trang (nếu được kích hoạt trong Tùy chọn)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "Sử dụng thiết lập mặc định" + }, + "autoFillOnPageLoadYes": { + "message": "Tự động điền khi tải trang" + }, + "autoFillOnPageLoadNo": { + "message": "Không tự động điền khi tải trang" + }, + "commandOpenPopup": { + "message": "Mở popup kho" + }, + "commandOpenSidebar": { + "message": "Mở kho ở thanh bên" + }, + "commandAutofillDesc": { + "message": "Tự động điền thông tin đăng nhập người dùng cho trang web hiện tại." + }, + "commandGeneratePasswordDesc": { + "message": "Tạo và sao chép một mật khẩu ngẫu nhiên mới vào bộ nhớ tạm." + }, + "commandLockVaultDesc": { + "message": "Khóa bảo mật" + }, + "privateModeWarning": { + "message": "Hỗ trợ cho chế độ riêng tư đang được thử nghiệm và hạn chế một số tính năng." + }, + "customFields": { + "message": "Trường tùy chỉnh" + }, + "copyValue": { + "message": "Sao chép giá trị" + }, + "value": { + "message": "Giá trị" + }, + "newCustomField": { + "message": "Trường tùy chỉnh mới" + }, + "dragToSort": { + "message": "Kéo để sắp xếp" + }, + "cfTypeText": { + "message": "Văn bản" + }, + "cfTypeHidden": { + "message": "Ẩn" + }, + "cfTypeBoolean": { + "message": "Đúng/Sai" + }, + "cfTypeLinked": { + "message": "Đã liên kết", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "Giá trị liên kết", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "Nhấp bên ngoài popup để xem mã xác thực trong email của bạn sẽ làm cho popup này đóng lại. Bạn có muốn mở popup này trong một cửa sổ mới để nó không bị đóng?" + }, + "popupU2fCloseMessage": { + "message": "Trình duyệt này không thể xử lý các yêu cầu U2F trong cửa sổ popup này. Bạn có muốn mở popup này trong cửa sổ mới để bạn có thể đăng nhập thông qua U2F?" + }, + "disableFavicon": { + "message": "Vô hiệu hoá biểu tượng trang web" + }, + "disableFaviconDesc": { + "message": "Biểu tượng trang web cung cấp các biểu tượng nhận dạng trang web bên cạnh mỗi mục đăng nhập trong kho mật khẩu của bạn." + }, + "disableBadgeCounter": { + "message": "Hủy bộ đếm số" + }, + "disableBadgeCounterDesc": { + "message": "Bộ đếm số chỉ ra bao nhiêu tài khoản đăng nhập bạn có với trang hiện tại." + }, + "cardholderName": { + "message": "Tên chủ thẻ" + }, + "number": { + "message": "Số" + }, + "brand": { + "message": "Thương hiệu" + }, + "expirationMonth": { + "message": "Tháng Hết Hạn" + }, + "expirationYear": { + "message": "Năm hết hạn" + }, + "expiration": { + "message": "Hết hạn" + }, + "january": { + "message": "Tháng 1" + }, + "february": { + "message": "Tháng 2" + }, + "march": { + "message": "Tháng 3" + }, + "april": { + "message": "Tháng 4" + }, + "may": { + "message": "Tháng 5" + }, + "june": { + "message": "Tháng 6" + }, + "july": { + "message": "Tháng 7" + }, + "august": { + "message": "Tháng 8" + }, + "september": { + "message": "Tháng 9" + }, + "october": { + "message": "Tháng 10" + }, + "november": { + "message": "Tháng 11" + }, + "december": { + "message": "Tháng 12" + }, + "securityCode": { + "message": "Mã bảo mật" + }, + "ex": { + "message": "Ví dụ:" + }, + "title": { + "message": "Tiêu đề" + }, + "mr": { + "message": "Ông" + }, + "mrs": { + "message": "Bà" + }, + "ms": { + "message": "Chị" + }, + "dr": { + "message": "Bác sĩ" + }, + "firstName": { + "message": "Tên" + }, + "middleName": { + "message": "Tên đệm" + }, + "lastName": { + "message": "Họ" + }, + "fullName": { + "message": "Họ và tên" + }, + "identityName": { + "message": "Tên nhận dạng" + }, + "company": { + "message": "Công ty" + }, + "ssn": { + "message": "Số bảo hiểm xã hội" + }, + "passportNumber": { + "message": "Số hộ chiếu" + }, + "licenseNumber": { + "message": "Số giấy phép" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Số điện thoại" + }, + "address": { + "message": "Địa chỉ" + }, + "address1": { + "message": "Địa chỉ 1" + }, + "address2": { + "message": "Địa chỉ 2" + }, + "address3": { + "message": "Địa chỉ 3" + }, + "cityTown": { + "message": "Quận/Huyện/Thị trấn" + }, + "stateProvince": { + "message": "Tỉnh/Thành Phố" + }, + "zipPostalCode": { + "message": "Mã bưu chính" + }, + "country": { + "message": "Quốc Gia" + }, + "type": { + "message": "Loại" + }, + "typeLogin": { + "message": "Đăng nhập" + }, + "typeLogins": { + "message": "Đăng nhập" + }, + "typeSecureNote": { + "message": "Lưu ý an toàn" + }, + "typeCard": { + "message": "Thẻ" + }, + "typeIdentity": { + "message": "Danh tính" + }, + "passwordHistory": { + "message": "Lịch sử Mật khẩu" + }, + "back": { + "message": "Quay lại" + }, + "collections": { + "message": "Các Bộ Sưu Tập" + }, + "favorites": { + "message": "Yêu thích" + }, + "popOutNewWindow": { + "message": "Mở trong cửa sổ mới" + }, + "refresh": { + "message": "Làm mới" + }, + "cards": { + "message": "Thẻ" + }, + "identities": { + "message": "Danh tính" + }, + "logins": { + "message": "Đăng nhập" + }, + "secureNotes": { + "message": "Ghi chú bảo mật" + }, + "clear": { + "message": "Xoá", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "Kiểm tra xem mật khẩu có bị lộ không." + }, + "passwordExposed": { + "message": "Mật khẩu này đã bị lộ $VALUE$ trong các dữ liệu vi phạm. Bạn nên thay đổi nó.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Mật khẩu này không được tìm thấy trong bất kỳ dữ liệu vi phạm nào được biết đến. Nó an toàn để sử dụng." + }, + "baseDomain": { + "message": "Tên miền cơ sở", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Máy chủ", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Chính xác" + }, + "startsWith": { + "message": "Bắt đầu với" + }, + "regEx": { + "message": "Biểu thức chính quy", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Độ phù hợp", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Độ phù hợp mặc định", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Bật/tắt tùy chọn" + }, + "toggleCurrentUris": { + "message": "Bật/tắt URI hiện tại", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "URI hiện tại", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "Tổ chức", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "Các loại" + }, + "allItems": { + "message": "Tất cả các mục" + }, + "noPasswordsInList": { + "message": "Không có mật khẩu để liệt kê." + }, + "remove": { + "message": "Xoá" + }, + "default": { + "message": "Mặc định" + }, + "dateUpdated": { + "message": "Ngày cập nhật", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "Bạn có chắc bạn muốn sử dụng tùy chọn \"Không bao giờ\"? Đặt các tùy chọn khóa về \"Không bao giờ\" sẽ lưu key mã hóa kho của ngay trên thiết bị của bạn. Nếu bạn sử dụng tùy chọn này, bạn nên chắc chắn là thiết bị bạn đang được bảo vệ." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "Không có bộ sưu tập nào để liệt kê." + }, + "ownership": { + "message": "Quyền sở hữu" + }, + "whoOwnsThisItem": { + "message": "Ai sở hữu mục này?" + }, + "strong": { + "message": "Mạnh", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Tốt", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Yếu", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Mật khẩu chính đơn giản" + }, + "weakMasterPasswordDesc": { + "message": "Mật khẩu chính bạn vừa chọn có vẻ yếu. Bạn nên chọn mật khẩu chính (hoặc cụm từ mật khẩu) mạnh để bảo vệ đúng cách tài khoản Bitwarden của bạn. Bạn có thực sự muốn dùng mật khẩu chính này?" + }, + "pin": { + "message": "Mã PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Mở khóa với mã PIN" + }, + "setYourPinCode": { + "message": "Đặt mã PIN của bạn để mở khóa Bitwarden. Cài đặt mã PIN của bạn sẽ bị xóa nếu bạn hoàn toàn đăng xuất khỏi ứng dụng." + }, + "pinRequired": { + "message": "Mã PIN là bắt buộc." + }, + "invalidPin": { + "message": "Mã PIN không hợp lệ." + }, + "unlockWithBiometrics": { + "message": "Mở khóa bằng sinh trắc học" + }, + "awaitDesktop": { + "message": "Đợi xác nhận từ máy tính" + }, + "awaitDesktopDesc": { + "message": "Vui lòng xác nhận sử dụng sinh trắc học với ứng dụng Bitwarden trên máy tính." + }, + "lockWithMasterPassOnRestart": { + "message": "Khóa với mật khẩu chính khi trình duyệt khởi động lại" + }, + "selectOneCollection": { + "message": "Bạn phải chọn ít nhất một bộ sưu tập." + }, + "cloneItem": { + "message": "Tại bản sao của mục" + }, + "clone": { + "message": "Tạo bản sao" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Có một hoặc vài chính sách của tổ chức đang làm ảnh hưởng đến cài đặt tạo mật khẩu của bạn." + }, + "vaultTimeoutAction": { + "message": "Hành Động Khi Hết Thời Gian Chờ" + }, + "lock": { + "message": "Khóa", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Thùng rác", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Tìm kiếm thùng rác" + }, + "permanentlyDeleteItem": { + "message": "Xoá vĩnh viễn mục" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Bạn có chắc chắn muốn xóa vĩnh viễn mục này không?" + }, + "permanentlyDeletedItem": { + "message": "Đã xóa vĩnh viễn mục" + }, + "restoreItem": { + "message": "Khôi phục mục" + }, + "restoreItemConfirmation": { + "message": "Bạn có chắc chắn muốn khôi phục mục này không?" + }, + "restoredItem": { + "message": "Mục đã được khôi phục" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Đăng xuất sẽ xóa tất các truy cập vào kho của bạn và yêu cầu xác thực trực tuyến sau khi khoảng thời gian chờ hết. Bạn có chắc bạn muốn dùng cài đặt này?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Xác nhận hành động khi hết thời gian chờ" + }, + "autoFillAndSave": { + "message": "Tự động điền và Lưu" + }, + "autoFillSuccessAndSavedUri": { + "message": "Tự động điền và Lưu URI" + }, + "autoFillSuccess": { + "message": "Tự động điền" + }, + "setMasterPassword": { + "message": "Đặt mật khẩu chính" + }, + "masterPasswordPolicyInEffect": { + "message": "Tổ chức của bạn yêu cầu mật khẩu chính của bạn phải đáp ứng các yêu cầu sau:" + }, + "policyInEffectMinComplexity": { + "message": "Điểm số phức tạp là", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Độ dài tối thiểu là $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Chứa chữ cái in hoa" + }, + "policyInEffectLowercase": { + "message": "Chứa một hoặc nhiều kí tự viết thường" + }, + "policyInEffectNumbers": { + "message": "Chứa một hoặc nhiều chữ số" + }, + "policyInEffectSpecial": { + "message": "Chứa ký tự đặc biệt $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Mật khẩu chính bạn chọn không đáp ứng yêu cầu." + }, + "acceptPolicies": { + "message": "Bạn đồng ý với những điều sau khi nhấn chọn ô này:" + }, + "acceptPoliciesError": { + "message": "Điều khoản sử dụng và Chính sách quyền riêng tư chưa được đồng ý." + }, + "termsOfService": { + "message": "Điều khoản sử dụng" + }, + "privacyPolicy": { + "message": "Chính sách quyền riêng tư" + }, + "hintEqualsPassword": { + "message": "Lời nhắc mật khẩu không được giống mật khẩu của bạn" + }, + "ok": { + "message": "Ok" + }, + "desktopSyncVerificationTitle": { + "message": "Xác minh đồng bộ máy tính" + }, + "desktopIntegrationVerificationText": { + "message": "Vui lòng xác minh rằng ứng dụng trên máy tính thấy vân tay này:" + }, + "desktopIntegrationDisabledTitle": { + "message": "Tích hợp trình duyệt chưa được kích hoạt" + }, + "desktopIntegrationDisabledDesc": { + "message": "Browser integration is not enabled in the Bitwarden Desktop application. Please enable it in the settings within the desktop application." + }, + "startDesktopTitle": { + "message": "Mở ứng dụng Bitwarden trên máy tính" + }, + "startDesktopDesc": { + "message": "The Bitwarden Desktop application needs to be started before unlock with biometrics can be used." + }, + "errorEnableBiometricTitle": { + "message": "Không thể bật nhận dạng sinh trắc học" + }, + "errorEnableBiometricDesc": { + "message": "Action was canceled by the desktop application" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "Desktop application invalidated the secure communication channel. Please retry this operation" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "Desktop communication interrupted" + }, + "nativeMessagingWrongUserDesc": { + "message": "The desktop application is logged into a different account. Please ensure both applications are logged into the same account." + }, + "nativeMessagingWrongUserTitle": { + "message": "Tài khoản không đúng" + }, + "biometricsNotEnabledTitle": { + "message": "Nhận dạng sinh trắc học chưa được bật" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometric to be enabled in the settings first." + }, + "biometricsNotSupportedTitle": { + "message": "Nhận dạng sinh trắc học không được hỗ trợ" + }, + "biometricsNotSupportedDesc": { + "message": "Nhận dạng sinh trắc học trên trình duyệt không được hỗ trợ trên thiết bị này" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "Quyền chưa được cấp" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "Without permission to communicate with the Bitwarden Desktop Application we cannot provide biometrics in the browser extension. Please try again." + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "Lỗi yêu cầu quyền" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "This action cannot be done in the sidebar, please retry the action in the popup or popout." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "excludedDomains": { + "message": "Excluded Domains" + }, + "excludedDomainsDesc": { + "message": "Bitwarden will not ask to save login details for these domains. You must refresh the page for changes to take effect." + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ is not a valid domain", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "Tìm kiếm Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "Thêm Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "Văn bản" + }, + "sendTypeFile": { + "message": "Tập tin" + }, + "allSends": { + "message": "Toàn bộ Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "Max access count reached", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "Đã hết hạn" + }, + "pendingDeletion": { + "message": "Đang chờ xóa" + }, + "passwordProtected": { + "message": "Mật khẩu đã được bảo vệ" + }, + "copySendLink": { + "message": "Sao chép liên kết Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "Đã xóa mật khẩu" + }, + "delete": { + "message": "Xóa" + }, + "removedPassword": { + "message": "Xóa mật khẩu" + }, + "deletedSend": { + "message": "Đã xóa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Gửi liên kết", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "Đã tắt" + }, + "removePasswordConfirmation": { + "message": "Bạn có chắc chắn muốn xóa mật khẩu này?" + }, + "deleteSend": { + "message": "Xóa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "Bạn có chắc chắn muốn xóa Send này?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Chỉnh sửa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "Đây là loại Send gì?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "Một tên gợi nhớ để mô tả về Send này.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "Tập tin bạn muốn gửi." + }, + "deletionDate": { + "message": "Ngày xóa" + }, + "deletionDateDesc": { + "message": "Send sẽ được xóa vĩnh viễn vào ngày và giờ được chỉ định.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Ngày hết hạn" + }, + "expirationDateDesc": { + "message": "Nếu được thiết lập, truy cập vào Send này sẽ hết hạn vào ngày và giờ được chỉ định.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 ngày" + }, + "days": { + "message": "#DAYS# ngày", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "Tùy chỉnh" + }, + "maximumAccessCount": { + "message": "Số lượng truy cập tối đa" + }, + "maximumAccessCountDesc": { + "message": "Nếu được thiết lập, khi đã đạt tới số lượng truy cập tối đa, người dùng sẽ không thể truy cập Send này nữa.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "Copy this Send's link to clipboard upon save.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Văn bản bạn muốn gửi." + }, + "sendHideText": { + "message": "Hide this Send's text by default.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "createSend": { + "message": "Create New Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Mật khẩu mới" + }, + "sendDisabled": { + "message": "Đã tắt gửi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Do chính sách doanh nghiệp, bạn chỉ có thể xóa những Send hiện có.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Đã tạo Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Đã chỉnh sửa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "In order to choose a file, open the extension in the sidebar (if possible) or pop out to a new window by clicking this banner." + }, + "sendFirefoxFileWarning": { + "message": "In order to choose a file using Firefox, open the extension in the sidebar or pop out to a new window by clicking this banner." + }, + "sendSafariFileWarning": { + "message": "In order to choose a file using Safari, pop out to a new window by clicking this banner." + }, + "sendFileCalloutHeader": { + "message": "Trước khi bạn bắt đầu" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "To use a calendar style date picker", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "nhấn vào đây", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "to pop out your window.", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "The expiration date provided is not valid." + }, + "deletionDateIsInvalid": { + "message": "The deletion date provided is not valid." + }, + "expirationDateAndTimeRequired": { + "message": "An expiration date and time are required." + }, + "deletionDateAndTimeRequired": { + "message": "A deletion date and time are required." + }, + "dateParsingError": { + "message": "There was an error saving your deletion and expiration dates." + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "passwordPrompt": { + "message": "Nhắc lại mật khẩu chính" + }, + "passwordConfirmation": { + "message": "Xác nhận mật khẩu chính" + }, + "passwordConfirmationDesc": { + "message": "Hành động này được bảo vệ. Để tiếp tục, vui lòng nhập lại mật khẩu chính của bạn." + }, + "emailVerificationRequired": { + "message": "Yêu cầu xác nhận danh tính qua email" + }, + "emailVerificationRequiredDesc": { + "message": "Bạn phải xác nhận email để sử dụng tính năng này. Bạn có thể xác minh email trên web." + }, + "updatedMasterPassword": { + "message": "Mật khẩu chính đã cập nhật" + }, + "updateMasterPassword": { + "message": "Cập nhật mật khẩu chính" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Chọn thư mục" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Giờ" + }, + "minutes": { + "message": "Phút" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Xuất mật khẩu đăng tắt" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Rời tổ chức" + }, + "removeMasterPassword": { + "message": "Xóa mật khẩu chính" + }, + "removedMasterPassword": { + "message": "Đã xóa mật khẩu chính" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "toggleCharacterCount": { + "message": "Toggle character count" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "Error" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/browser/src/_locales/zh_CN/messages.json b/apps/browser/src/_locales/zh_CN/messages.json new file mode 100644 index 0000000000..4155b19928 --- /dev/null +++ b/apps/browser/src/_locales/zh_CN/messages.json @@ -0,0 +1,1817 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - 免费密码管理器", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden 是一个安全且免费的跨平台密码管理器。", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "登录或新建一个帐号来访问你的密码库。" + }, + "createAccount": { + "message": "新建帐号" + }, + "login": { + "message": "登录" + }, + "enterpriseSingleSignOn": { + "message": "企业单点登录(SSO)" + }, + "cancel": { + "message": "取消" + }, + "close": { + "message": "关闭" + }, + "submit": { + "message": "提交" + }, + "emailAddress": { + "message": "电子邮件地址" + }, + "masterPass": { + "message": "主密码" + }, + "masterPassDesc": { + "message": "主密码是您访问密码库的唯一密码。它非常重要,请您不要忘记。一旦忘记,无任何办法恢复此密码。" + }, + "masterPassHintDesc": { + "message": "主密码提示可以在你忘记密码时帮你回忆起来。" + }, + "reTypeMasterPass": { + "message": "重新输入主密码" + }, + "masterPassHint": { + "message": "主密码提示 (可选)" + }, + "tab": { + "message": "标签页" + }, + "myVault": { + "message": "密码库" + }, + "tools": { + "message": "工具" + }, + "settings": { + "message": "设置" + }, + "currentTab": { + "message": "当前标签" + }, + "copyPassword": { + "message": "复制密码" + }, + "copyNote": { + "message": "复制备注" + }, + "copyUri": { + "message": "复制 URI" + }, + "copyUsername": { + "message": "复制用户名" + }, + "copyNumber": { + "message": "复制号码" + }, + "copySecurityCode": { + "message": "复制安全码" + }, + "autoFill": { + "message": "自动填充" + }, + "generatePasswordCopied": { + "message": "生成密码 (并复制)" + }, + "copyElementIdentifier": { + "message": "Copy Custom Field Name" + }, + "noMatchingLogins": { + "message": "无匹配的登录信息。" + }, + "vaultLocked": { + "message": "密码库已锁定" + }, + "vaultLoggedOut": { + "message": "密码库已注销" + }, + "autoFillInfo": { + "message": "没有可以自动填充当前浏览器标签页的登录项目。" + }, + "addLogin": { + "message": "添加登录信息" + }, + "addItem": { + "message": "添加项目" + }, + "passwordHint": { + "message": "密码提示" + }, + "enterEmailToGetHint": { + "message": "请输入您帐号的 Email 地址来接收主密码提示。" + }, + "getMasterPasswordHint": { + "message": "获取主密码提示" + }, + "continue": { + "message": "继续" + }, + "verificationCode": { + "message": "验证码" + }, + "account": { + "message": "账户" + }, + "changeMasterPassword": { + "message": "修改主密码" + }, + "fingerprintPhrase": { + "message": "指纹短语", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "您的账户的指纹短语", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "两步登录" + }, + "logOut": { + "message": "注销" + }, + "about": { + "message": "关于" + }, + "version": { + "message": "版本" + }, + "save": { + "message": "保存" + }, + "move": { + "message": "移动" + }, + "addFolder": { + "message": "添加文件夹" + }, + "name": { + "message": "名称" + }, + "editFolder": { + "message": "编辑文件夹" + }, + "deleteFolder": { + "message": "删除文件夹" + }, + "folders": { + "message": "文件夹" + }, + "noFolders": { + "message": "没有可列出的文件夹。" + }, + "helpFeedback": { + "message": "帮助和反馈" + }, + "sync": { + "message": "同步" + }, + "syncVaultNow": { + "message": "立即同步密码库" + }, + "lastSync": { + "message": "上次同步:" + }, + "passGen": { + "message": "密码生成器" + }, + "generator": { + "message": "生成器", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "自动生成安全可靠唯一的登录密码。" + }, + "bitWebVault": { + "message": "Bitwarden 网页版密码库" + }, + "importItems": { + "message": "导入项目" + }, + "select": { + "message": "选择" + }, + "generatePassword": { + "message": "生成密码" + }, + "regeneratePassword": { + "message": "重新生成密码" + }, + "options": { + "message": "选项" + }, + "length": { + "message": "长度" + }, + "numWords": { + "message": "单词数" + }, + "wordSeparator": { + "message": "单词分隔符" + }, + "capitalize": { + "message": "大写", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "包含数字" + }, + "minNumbers": { + "message": "数字最少个数" + }, + "minSpecial": { + "message": "符号最少个数" + }, + "avoidAmbChar": { + "message": "避免易混淆的字符" + }, + "searchVault": { + "message": "搜索密码库" + }, + "edit": { + "message": "编辑" + }, + "view": { + "message": "查看" + }, + "noItemsInList": { + "message": "没有可列出的项目。" + }, + "itemInformation": { + "message": "项目信息" + }, + "username": { + "message": "用户名" + }, + "password": { + "message": "密码" + }, + "passphrase": { + "message": "密码短语" + }, + "favorite": { + "message": "收藏" + }, + "notes": { + "message": "备注" + }, + "note": { + "message": "备注" + }, + "editItem": { + "message": "编辑项目" + }, + "folder": { + "message": "文件夹" + }, + "deleteItem": { + "message": "删除项目" + }, + "viewItem": { + "message": "查看项目" + }, + "launch": { + "message": "启动" + }, + "website": { + "message": "网站" + }, + "toggleVisibility": { + "message": "切换可见性" + }, + "manage": { + "message": "管理" + }, + "other": { + "message": "其他" + }, + "rateExtension": { + "message": "为本扩展打分" + }, + "rateExtensionDesc": { + "message": "请给我们好评!" + }, + "browserNotSupportClipboard": { + "message": "您的浏览器不支持剪贴板简单复制,请手动复制。" + }, + "verifyMasterPassword": { + "message": "验证主密码" + }, + "yourVaultIsLocked": { + "message": "您的密码库已锁定,验证您的主密码以继续。" + }, + "unlock": { + "message": "解锁" + }, + "loggedInAsOn": { + "message": "以 $EMAIL$ 在 $HOSTNAME$ 上登录。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "无效的主密码" + }, + "vaultTimeout": { + "message": "密码库超时" + }, + "lockNow": { + "message": "立即锁定" + }, + "immediately": { + "message": "立即" + }, + "tenSeconds": { + "message": "10 秒" + }, + "twentySeconds": { + "message": "20 秒" + }, + "thirtySeconds": { + "message": "30 秒" + }, + "oneMinute": { + "message": "1 分钟" + }, + "twoMinutes": { + "message": "2 分钟" + }, + "fiveMinutes": { + "message": "5 分钟" + }, + "fifteenMinutes": { + "message": "15 分钟" + }, + "thirtyMinutes": { + "message": "30 分钟" + }, + "oneHour": { + "message": "1 小时" + }, + "fourHours": { + "message": "4 小时" + }, + "onLocked": { + "message": "系统锁定时" + }, + "onRestart": { + "message": "重启浏览器时" + }, + "never": { + "message": "从不" + }, + "security": { + "message": "安全" + }, + "errorOccurred": { + "message": "发生了一个错误" + }, + "emailRequired": { + "message": "必须填写电子邮件地址。" + }, + "invalidEmail": { + "message": "无效的电子邮件地址。" + }, + "masterPassRequired": { + "message": "必须填写主密码。" + }, + "masterPassLength": { + "message": "主密码至少需要 8 个字符。" + }, + "masterPassDoesntMatch": { + "message": "两次填写的主密码不一致。" + }, + "newAccountCreated": { + "message": "已经为您建立了账户,您可以登录了。" + }, + "masterPassSent": { + "message": "我们已经为您发送了包含主密码提示的邮件。" + }, + "verificationCodeRequired": { + "message": "必须填写验证码。" + }, + "valueCopied": { + "message": "$VALUE$ 已复制", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "无法在此页面上自动填充所选项目。请改为手工复制并粘贴。" + }, + "loggedOut": { + "message": "已注销" + }, + "loginExpired": { + "message": "您的登录会话已过期。" + }, + "logOutConfirmation": { + "message": "您确定要注销吗?" + }, + "yes": { + "message": "是" + }, + "no": { + "message": "否" + }, + "unexpectedError": { + "message": "发生意外错误。" + }, + "nameRequired": { + "message": "必须填写名称。" + }, + "addedFolder": { + "message": "文件夹已添加" + }, + "changeMasterPass": { + "message": "修改主密码" + }, + "changeMasterPasswordConfirmation": { + "message": "您可以在 bitwarden.com 网页版密码库修改主密码。您现在要访问这个网站吗?" + }, + "twoStepLoginConfirmation": { + "message": "两步登录要求您从其他设备(例如安全钥匙、验证器应用、短信、电话或者电子邮件)来验证你的登录,这能使您的账户更加安全。两步登录可以在 bitwarden.com 网页版密码库启用。您现在要访问这个网站吗?" + }, + "editedFolder": { + "message": "文件夹已编辑" + }, + "deleteFolderConfirmation": { + "message": "您确定要删除此文件夹吗?" + }, + "deletedFolder": { + "message": "文件夹已删除" + }, + "gettingStartedTutorial": { + "message": "入门教程" + }, + "gettingStartedTutorialVideo": { + "message": "观看我们的入门教程,了解如何充分利用浏览器扩展。" + }, + "syncingComplete": { + "message": "同步完成" + }, + "syncingFailed": { + "message": "同步失败" + }, + "passwordCopied": { + "message": "密码已复制" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "新增 URI" + }, + "addedItem": { + "message": "项目已添加" + }, + "editedItem": { + "message": "项目已编辑" + }, + "deleteItemConfirmation": { + "message": "您确定要删除此项目吗?" + }, + "deletedItem": { + "message": "发送项目到回收站" + }, + "overwritePassword": { + "message": "覆盖密码" + }, + "overwritePasswordConfirmation": { + "message": "您确定要覆盖当前密码吗?" + }, + "searchFolder": { + "message": "搜索文件夹" + }, + "searchCollection": { + "message": "搜索集合" + }, + "searchType": { + "message": "搜索类型" + }, + "noneFolder": { + "message": "默认文件夹", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "禁用添加登录项的提醒" + }, + "addLoginNotificationDesc": { + "message": "当您第一次登录时,\"添加登录提醒\" 会自动提醒您在密码库里保存新的登录信息。" + }, + "dontShowCardsCurrentTab": { + "message": "标签页上不显示支付卡" + }, + "dontShowCardsCurrentTabDesc": { + "message": "密码库中的支付卡项目会在 “当前标签” 页面列出,以便于自动填充。" + }, + "dontShowIdentitiesCurrentTab": { + "message": "标签页上不显示身份" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "密码库中的身份项目会在 “当前标签” 页面列出,以便于自动填充。" + }, + "clearClipboard": { + "message": "清除剪贴板", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "自动清除复制到剪贴板的值。", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "希望 Bitwarden 为您保存这个密码吗?" + }, + "notificationAddSave": { + "message": "是,现在保存" + }, + "notificationNeverSave": { + "message": "永久忽略此网站" + }, + "disableChangedPasswordNotification": { + "message": "禁用密码变更通知" + }, + "disableChangedPasswordNotificationDesc": { + "message": "检测到您已变更网站上的密码时,“密码变更通知” 自动提醒您更新密码库中相应项的密码。" + }, + "notificationChangeDesc": { + "message": "是否要在 Bitwarden 中更新此密码?" + }, + "notificationChangeSave": { + "message": "是,立即更新" + }, + "disableContextMenuItem": { + "message": "关闭上下文菜单选项" + }, + "disableContextMenuItemDesc": { + "message": "上下文菜单选项可以让您快速访问密码生成器,也可以登陆当前标签的网站。" + }, + "defaultUriMatchDetection": { + "message": "默认的 URI 匹配检测方式", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "选择在执行诸如自动填充之类的操作时对登录进行 URI 匹配检测的默认方式。" + }, + "theme": { + "message": "主题" + }, + "themeDesc": { + "message": "更改本应用程序的颜色主题。" + }, + "dark": { + "message": "暗", + "description": "Dark color" + }, + "light": { + "message": "亮", + "description": "Light color" + }, + "solarizedDark": { + "message": "过曝暗", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "导出密码库" + }, + "fileFormat": { + "message": "文件格式" + }, + "warning": { + "message": "警告", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "确认密码库导出" + }, + "exportWarningDesc": { + "message": "导出的密码库数据包含未加密格式。您不应该通过不安全的渠道(例如电子邮件)来存储或发送导出的文件。用完后请立即将其删除。" + }, + "encExportKeyWarningDesc": { + "message": "此导出将使用您账户的加密密钥来加密您的数据。 如果您曾经轮换过账户的加密密钥,您应将其重新导出,否则您将无法解密导出的文件。" + }, + "encExportAccountWarningDesc": { + "message": "账户加密密钥对每个 Bitwarden 用户账户都是唯一的,所以您不能将加密的导出导入到另一个账户。" + }, + "exportMasterPassword": { + "message": "输入主密码来导出你的密码库。" + }, + "shared": { + "message": "已共享" + }, + "learnOrg": { + "message": "了解组织" + }, + "learnOrgConfirmation": { + "message": "Bitwarden 允许您使用组织与他人共享您的密码库项目。要访问 bitwarden.com 网站以了解更多内容吗?" + }, + "moveToOrganization": { + "message": "移动到组织" + }, + "share": { + "message": "共享" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ 已移动到 $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "选择一个您想将此项目移至的组织。移动到组织会将该项目的所有权转让给该组织。移动后,您将不再是此项目的直接所有者。" + }, + "learnMore": { + "message": "进一步了解" + }, + "authenticatorKeyTotp": { + "message": "验证器密钥 (TOTP)" + }, + "verificationCodeTotp": { + "message": "验证码 (TOTP)" + }, + "copyVerificationCode": { + "message": "复制验证码" + }, + "attachments": { + "message": "附件" + }, + "deleteAttachment": { + "message": "删除附件" + }, + "deleteAttachmentConfirmation": { + "message": "您确定要删除此附件吗?" + }, + "deletedAttachment": { + "message": "附件已删除" + }, + "newAttachment": { + "message": "添加新附件" + }, + "noAttachments": { + "message": "没有附件。" + }, + "attachmentSaved": { + "message": "附件已保存。" + }, + "file": { + "message": "文件" + }, + "selectFile": { + "message": "选择一个文件。" + }, + "maxFileSize": { + "message": "文件最大为 500 MB。" + }, + "featureUnavailable": { + "message": "功能不可用" + }, + "updateKey": { + "message": "在您更新加密密钥前,您不能使用此功能。" + }, + "premiumMembership": { + "message": "高级会员" + }, + "premiumManage": { + "message": "管理会员资格" + }, + "premiumManageAlert": { + "message": "您可以在 bitwarden.com 网页版密码库管理您的会员资格。现在要访问吗?" + }, + "premiumRefresh": { + "message": "刷新会员资格" + }, + "premiumNotCurrentMember": { + "message": "您目前不是高级会员。" + }, + "premiumSignUpAndGet": { + "message": "注册高级会员将获得:" + }, + "ppremiumSignUpStorage": { + "message": "1 GB 文件附件加密存储。" + }, + "ppremiumSignUpTwoStep": { + "message": "额外的两步登录选项,如 YubiKey、FIDO U2F 和 Duo。" + }, + "ppremiumSignUpReports": { + "message": "密码健康、账户体检以及数据泄露报告,保障您的密码库安全。" + }, + "ppremiumSignUpTotp": { + "message": "用于登录您的密码库的 TOTP 验证码(两步验证)生成器。" + }, + "ppremiumSignUpSupport": { + "message": "优先客户支持。" + }, + "ppremiumSignUpFuture": { + "message": "未来会增加更多高级功能。敬请期待!" + }, + "premiumPurchase": { + "message": "购买高级版" + }, + "premiumPurchaseAlert": { + "message": "您可以在 bitwarden.com 网页版密码库购买高级会员。现在要访问吗?" + }, + "premiumCurrentMember": { + "message": "您是高级会员!" + }, + "premiumCurrentMemberThanks": { + "message": "感谢您支持 Bitwarden。" + }, + "premiumPrice": { + "message": "每年只需 $PRICE$ !", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "刷新完成" + }, + "disableAutoTotpCopy": { + "message": "禁用自动 TOTP 复制" + }, + "disableAutoTotpCopyDesc": { + "message": "如果您的登录信息包含一个验证器密钥,当自动填充该登录项目时,TOTP 验证码将会自动复制到剪贴板。" + }, + "disableAutoBiometricsPrompt": { + "message": "Do not prompt for biometrics on launch" + }, + "premiumRequired": { + "message": "需要高级会员" + }, + "premiumRequiredDesc": { + "message": "使用此功能需要高级会员资格。" + }, + "enterVerificationCodeApp": { + "message": "请输入您的身份验证器应用中的 6 位验证码。" + }, + "enterVerificationCodeEmail": { + "message": "请输入通过电子邮件发送给 $EMAIL$ 的 6 位验证码。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "验证邮件已发送到 $EMAIL$。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "记住我" + }, + "sendVerificationCodeEmailAgain": { + "message": "再次发送验证码电子邮件" + }, + "useAnotherTwoStepMethod": { + "message": "使用其他两步登录方式" + }, + "insertYubiKey": { + "message": "将您的 YubiKey 插入计算机的 USB 端口,然后按下按钮。" + }, + "insertU2f": { + "message": "将您的安全钥匙插入计算机的 USB 端口。如果它有一个按钮,按下它。" + }, + "webAuthnNewTab": { + "message": "要开始 WebAuthn 2FA 验证,请点击下面的按钮打开一个新标签页,并按照新标签页中提供的说明操作。" + }, + "webAuthnNewTabOpen": { + "message": "打开新标签页" + }, + "webAuthnAuthenticate": { + "message": "验证 WebAuthn" + }, + "loginUnavailable": { + "message": "登录不可用" + }, + "noTwoStepProviders": { + "message": "此账户已启用两步登录,但此浏览器不支持任何已配置的两步登录提供程序。" + }, + "noTwoStepProviders2": { + "message": "请使用支持的网页浏览器(例如 Chrome)和/或添加其他支持更广泛的提供程序(例如验证器应用)。" + }, + "twoStepOptions": { + "message": "两步登录选项" + }, + "recoveryCodeDesc": { + "message": "失去访问您所有的双重身份验证设备?请使用您的恢复代码来禁用您账户中所有的两步登录提供程序。" + }, + "recoveryCodeTitle": { + "message": "恢复代码" + }, + "authenticatorAppTitle": { + "message": "验证器应用" + }, + "authenticatorAppDesc": { + "message": "使用身份验证器应用(例如 Authy 或 Google Authenticator)来生成基于时间的验证码。", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP 安全钥匙" + }, + "yubiKeyDesc": { + "message": "使用 YubiKey 来访问您的账户。支持 YubiKey 4、4 Nano、4C 以及 NEO 设备。" + }, + "duoDesc": { + "message": "使用 Duo Security 的 Duo 移动应用、短信、电话或 U2F 安全钥匙来进行验证。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "为您的组织使用 Duo Security 的 Duo 移动应用、短信、电话或 U2F 安全钥匙来进行验证。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "使用任何启用了 WebAuthn 的安全钥匙访问您的帐户。" + }, + "emailTitle": { + "message": "电子邮件" + }, + "emailDesc": { + "message": "验证码将会发送到您的电子邮箱。" + }, + "selfHostedEnvironment": { + "message": "自托管环境" + }, + "selfHostedEnvironmentFooter": { + "message": "指定您本地托管的 Bitwarden 安装的基础 URL。" + }, + "customEnvironment": { + "message": "自定义环境" + }, + "customEnvironmentFooter": { + "message": "适用于高级用户。你可以分别指定各个服务的基础 URL。" + }, + "baseUrl": { + "message": "服务器 URL" + }, + "apiUrl": { + "message": "API 服务器 URL" + }, + "webVaultUrl": { + "message": "网页密码库服务器 URL" + }, + "identityUrl": { + "message": "身份服务器 URL" + }, + "notificationsUrl": { + "message": "通知服务器 URL" + }, + "iconsUrl": { + "message": "图标服务器 URL" + }, + "environmentSaved": { + "message": "各环境 URL 已保存。" + }, + "enableAutoFillOnPageLoad": { + "message": "启用页面加载时的自动填充" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "如果网页加载时检测到登录表单,自动进行自动填充。" + }, + "experimentalFeature": { + "message": "目前这是一项实验功能。使用需自担风险。" + }, + "defaultAutoFillOnPageLoad": { + "message": "登录项目的默认自动填充设置" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "启用页面加载时自动填充后,您可以为单个登录项目启用或禁用此功能。这是未单独配置的登录项目的默认设置。" + }, + "itemAutoFillOnPageLoad": { + "message": "页面加载时自动填充(如果选项中已启用)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "使用默认设置" + }, + "autoFillOnPageLoadYes": { + "message": "页面加载时自动填充" + }, + "autoFillOnPageLoadNo": { + "message": "页面加载时不自动填充" + }, + "commandOpenPopup": { + "message": "在弹出框中打开密码库" + }, + "commandOpenSidebar": { + "message": "在侧边栏中打开密码库" + }, + "commandAutofillDesc": { + "message": "为当前网站自动填充最后使用的登录信息" + }, + "commandGeneratePasswordDesc": { + "message": "生成一个新的随机密码并将其复制到剪贴板中。" + }, + "commandLockVaultDesc": { + "message": "锁定密码库" + }, + "privateModeMessage": { + "message": "非常不幸,此窗口在这个浏览器的隐私模式中不可用。" + }, + "customFields": { + "message": "自定义字段" + }, + "copyValue": { + "message": "复制值" + }, + "value": { + "message": "值" + }, + "newCustomField": { + "message": "新建自定义字段" + }, + "dragToSort": { + "message": "拖动排序" + }, + "cfTypeText": { + "message": "文本" + }, + "cfTypeHidden": { + "message": "隐藏的" + }, + "cfTypeBoolean": { + "message": "布尔值" + }, + "popup2faCloseMessage": { + "message": "如果您点击弹窗外的任何区域,将导致弹窗关闭。您想在新窗口中打开此弹窗,以便它不会关闭吗?" + }, + "popupU2fCloseMessage": { + "message": "此浏览器无法处理此弹出窗口中的 U2F 请求。您想要在新窗口中打开此弹出窗口吗?" + }, + "disableFavicon": { + "message": "禁用网站图标" + }, + "disableFaviconDesc": { + "message": "在您密码库的每个登录项目旁边显示一个可识别的图标。" + }, + "disableBadgeCounter": { + "message": "禁用角标计数器" + }, + "disableBadgeCounterDesc": { + "message": "角标计数器表示您的密码库中可用于当前页面的登录的数量。" + }, + "cardholderName": { + "message": "持卡人姓名" + }, + "number": { + "message": "号码" + }, + "brand": { + "message": "品牌" + }, + "expirationMonth": { + "message": "到期月份" + }, + "expirationYear": { + "message": "到期年份" + }, + "expiration": { + "message": "到期" + }, + "january": { + "message": "一月" + }, + "february": { + "message": "二月" + }, + "march": { + "message": "三月" + }, + "april": { + "message": "四月" + }, + "may": { + "message": "五月" + }, + "june": { + "message": "六月" + }, + "july": { + "message": "七月" + }, + "august": { + "message": "八月" + }, + "september": { + "message": "九月" + }, + "october": { + "message": "十月" + }, + "november": { + "message": "十一月" + }, + "december": { + "message": "十二月" + }, + "securityCode": { + "message": "安全码" + }, + "ex": { + "message": "例如" + }, + "title": { + "message": "称呼" + }, + "mr": { + "message": "先生" + }, + "mrs": { + "message": "夫人" + }, + "ms": { + "message": "女士" + }, + "dr": { + "message": "博士" + }, + "firstName": { + "message": "名" + }, + "middleName": { + "message": "中间名" + }, + "lastName": { + "message": "姓" + }, + "identityName": { + "message": "身份名称" + }, + "company": { + "message": "公司" + }, + "ssn": { + "message": "社会安全号码" + }, + "passportNumber": { + "message": "护照号码" + }, + "licenseNumber": { + "message": "许可证编号" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "电话" + }, + "address": { + "message": "地址" + }, + "address1": { + "message": "地址 1" + }, + "address2": { + "message": "地址 2" + }, + "address3": { + "message": "地址 3" + }, + "cityTown": { + "message": "市 / 镇" + }, + "stateProvince": { + "message": "州 / 省" + }, + "zipPostalCode": { + "message": "邮编 / 邮政代码" + }, + "country": { + "message": "国家" + }, + "type": { + "message": "类型" + }, + "typeLogin": { + "message": "登录" + }, + "typeLogins": { + "message": "登录项目" + }, + "typeSecureNote": { + "message": "安全笔记" + }, + "typeCard": { + "message": "支付卡" + }, + "typeIdentity": { + "message": "身份" + }, + "passwordHistory": { + "message": "密码历史记录" + }, + "back": { + "message": "后退" + }, + "collections": { + "message": "集合" + }, + "favorites": { + "message": "收藏" + }, + "popOutNewWindow": { + "message": "弹出到新窗口" + }, + "refresh": { + "message": "刷新" + }, + "cards": { + "message": "支付卡" + }, + "identities": { + "message": "身份" + }, + "logins": { + "message": "登录" + }, + "secureNotes": { + "message": "安全笔记" + }, + "clear": { + "message": "清除", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "检查密码是否已经被公开。" + }, + "passwordExposed": { + "message": "此密码在泄露数据中已被公开 $VALUE$ 次。请立即修改。", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "没有在已知的数据泄露中发现此密码,它暂时比较安全。" + }, + "baseDomain": { + "message": "基础域" + }, + "host": { + "message": "主机", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "精确" + }, + "startsWith": { + "message": "开始于" + }, + "regEx": { + "message": "正则表达式", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "匹配检测", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "默认匹配检测", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "切换选项" + }, + "toggleCurrentUris": { + "message": "切换当前网址", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "当前 URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "组织", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "类型" + }, + "allItems": { + "message": "所有项目" + }, + "noPasswordsInList": { + "message": "没有可列出的密码。" + }, + "remove": { + "message": "移除" + }, + "default": { + "message": "默认" + }, + "dateUpdated": { + "message": "更新于", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "密码更新于", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "您确定要使用“从不”选项吗?将锁定选项设置为“从不”会将密码库的加密密钥存储在您的设备上。如果使用此选项,您必须确保您的设备安全。" + }, + "noOrganizationsList": { + "message": "您没有加入任何组织。组织允许您与其他用户安全地共享项目。" + }, + "noCollectionsInList": { + "message": "没有可列出的集合。" + }, + "ownership": { + "message": "所有权" + }, + "whoOwnsThisItem": { + "message": "谁拥有这个项目?" + }, + "strong": { + "message": "强", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "良好", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "弱", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "脆弱的主密码" + }, + "weakMasterPasswordDesc": { + "message": "您选择的主密码较弱。您应该使用强密码(或密码短语)来正确保护您的 Bitwarden 账户。仍要使用此主密码吗?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "使用 PIN 解锁" + }, + "setYourPinCode": { + "message": "设定您用来解锁 Bitwarden 的 PIN 码。您的 PIN 设置将在您完全注销本应用程序时被重置。" + }, + "pinRequired": { + "message": "需要 PIN 码。" + }, + "invalidPin": { + "message": "无效 PIN 码。" + }, + "verifyPin": { + "message": "验证 PIN 码" + }, + "yourVaultIsLockedPinCode": { + "message": "您的密码库已锁定。请验证您的 PIN 码以继续。" + }, + "unlockWithBiometrics": { + "message": "使用生物识别解锁" + }, + "awaitDesktop": { + "message": "等待来自桌面应用程序的确认" + }, + "awaitDesktopDesc": { + "message": "请确认在 Bitwarden 桌面应用程序中使用了生物识别以启用浏览器的生物识别。" + }, + "lockWithMasterPassOnRestart": { + "message": "浏览器重启后使用主密码锁定" + }, + "selectOneCollection": { + "message": "您必须至少选择一个集合。" + }, + "cloneItem": { + "message": "复制项目" + }, + "clone": { + "message": "克隆" + }, + "passwordGeneratorPolicyInEffect": { + "message": "一个或多个组织策略正在影响您的生成器设置。" + }, + "vaultTimeoutAction": { + "message": "密码库超时动作" + }, + "lock": { + "message": "锁定", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "回收站", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "搜索回收站" + }, + "permanentlyDeleteItem": { + "message": "永久删除项目" + }, + "permanentlyDeleteItemConfirmation": { + "message": "您确定要永久删除此项目吗?" + }, + "permanentlyDeletedItem": { + "message": "已永久删除项目" + }, + "restoreItem": { + "message": "恢复项目" + }, + "restoreItemConfirmation": { + "message": "您确定要恢复此项目吗?" + }, + "restoredItem": { + "message": "项目已恢复" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "超时后注销将解除对密码库的所有访问权限,并需要进行在线认证。确定使用此设置吗?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "超时动作确认" + }, + "autoFillAndSave": { + "message": "自动填充并保存" + }, + "autoFillSuccessAndSavedUri": { + "message": "项目已自动填充且 URI 已保存" + }, + "autoFillSuccess": { + "message": "项目已自动填充" + }, + "setMasterPassword": { + "message": "设置主密码" + }, + "masterPasswordPolicyInEffect": { + "message": "一个或多个组织策略要求您的主密码满足下列要求:" + }, + "policyInEffectMinComplexity": { + "message": "最小复杂度为 $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "最小长度为 $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "至少包含一个大写字符" + }, + "policyInEffectLowercase": { + "message": "至少包含一个小写字符" + }, + "policyInEffectNumbers": { + "message": "至少包含一个数字" + }, + "policyInEffectSpecial": { + "message": "至少包含一个下列的特殊字符:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "您的新主密码不符合策略要求。" + }, + "acceptPolicies": { + "message": "选中此框表示您同意:" + }, + "acceptPoliciesError": { + "message": "尚未同意服务条款和隐私政策。" + }, + "termsOfService": { + "message": "服务条款" + }, + "privacyPolicy": { + "message": "隐私政策" + }, + "hintEqualsPassword": { + "message": "您的密码提示不能与您的密码相同。" + }, + "ok": { + "message": "确定" + }, + "desktopSyncVerificationTitle": { + "message": "桌面同步验证" + }, + "desktopIntegrationVerificationText": { + "message": "请验证桌面应用程序显示的指纹为: " + }, + "desktopIntegrationDisabledTitle": { + "message": "浏览器整合未启用" + }, + "desktopIntegrationDisabledDesc": { + "message": "浏览器整合在 Bitwarden 桌面应用程序中未启用。请在桌面应用程序的设置中启用它。" + }, + "startDesktopTitle": { + "message": "启动 Bitwarden 桌面应用程序" + }, + "startDesktopDesc": { + "message": "Bitwarden 桌面应用程序需要已启动才能使用此功能。" + }, + "errorEnableBiometricTitle": { + "message": "无法启用生物识别" + }, + "errorEnableBiometricDesc": { + "message": "操作被桌面应用程序取消" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "桌面应用程序废止了安全通信通道。请重试此操作" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "桌面通信已中断" + }, + "nativeMessagingWrongUserDesc": { + "message": "桌面应用程序登录到了不同的帐户。请确保两个应用程序都登录到同一个帐户。" + }, + "nativeMessagingWrongUserTitle": { + "message": "账户不匹配" + }, + "biometricsNotEnabledTitle": { + "message": "生物识别未启用" + }, + "biometricsNotEnabledDesc": { + "message": "需要首先在桌面应用程序的设置中启用生物识别才能使用浏览器的生物识别。" + }, + "biometricsNotSupportedTitle": { + "message": "不支持生物识别" + }, + "biometricsNotSupportedDesc": { + "message": "此设备不支持浏览器生物识别。" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "未提供权限" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "没有与 Bitwarden 桌面应用程序通信的权限,我们无法在浏览器扩展中提供生物识别。请再试一次。" + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "权限请求错误" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "此操作不能在侧边栏中完成,请在弹出窗口或弹出对话框中重试。" + }, + "personalOwnershipSubmitError": { + "message": "由于某个企业策略,您被限制为保存项目到您的个人密码库。将所有权选项更改为组织,并从可用的集合中选择。" + }, + "personalOwnershipPolicyInEffect": { + "message": "一个组织策略正影响您的所有权选项。" + }, + "excludedDomains": { + "message": "排除的域名" + }, + "excludedDomainsDesc": { + "message": "Bitwarden 将不会询问是否为这些域名保存登录信息。需要刷新页面才能生效。" + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ 不是一个有效的域名", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "搜索 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "添加 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "文本" + }, + "sendTypeFile": { + "message": "文件" + }, + "allSends": { + "message": "所有 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "已达最大访问次数" + }, + "expired": { + "message": "已过期" + }, + "pendingDeletion": { + "message": "等待删除" + }, + "passwordProtected": { + "message": "密码保护" + }, + "copySendLink": { + "message": "复制 Send 链接", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "移除密码" + }, + "delete": { + "message": "删除" + }, + "removedPassword": { + "message": "密码已移除" + }, + "deletedSend": { + "message": "Send 已删除", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send 链接", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "已禁用" + }, + "removePasswordConfirmation": { + "message": "确定要移除此密码吗?" + }, + "deleteSend": { + "message": "删除 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "确定要删除此 Send 吗?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "编辑 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "这是什么类型的 Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "用于描述此 Send 的友好名称。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "您想要发送的文件。" + }, + "deletionDate": { + "message": "删除日期" + }, + "deletionDateDesc": { + "message": "此 Send 将在指定的日期和时间后被永久删除。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "到期日期" + }, + "expirationDateDesc": { + "message": "如果设置,此 Send 将在指定的日期和时间后过期。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 天" + }, + "days": { + "message": "$DAYS$ 天", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "自定义" + }, + "maximumAccessCount": { + "message": "最大访问次数" + }, + "maximumAccessCountDesc": { + "message": "如果设置,达到最大访问次数后用户将无法访问此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "可选,用户需要提供密码才能访问此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "关于此 Send 的私密备注。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "禁用此 Send 以阻止任何人访问它。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "保存时复制此 Send 的链接到剪贴板。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "您想要发送的文本。" + }, + "sendHideText": { + "message": "默认隐藏此 Send 的文本。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "当前访问次数" + }, + "createSend": { + "message": "创建新 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "新密码" + }, + "sendDisabled": { + "message": "Send 已禁用", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "由于企业策略,您只能删除现有的 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send 已创建", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send 已编辑", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "要选择文件,请在侧边栏中打开扩展(如果可以),或者点击此横幅来弹出一个新窗口。" + }, + "sendFirefoxFileWarning": { + "message": "要在 Firefox 中选择文件,请在侧边栏中打开本扩展,或者点击此横幅来弹出一个新窗口。" + }, + "sendSafariFileWarning": { + "message": "要在 Safari 中选择文件,请点击此横幅来弹出一个新窗口。" + }, + "sendFileCalloutHeader": { + "message": "在开始之前" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "要使用日历样式的日期选择器", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "点击这里", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "来弹出窗口。", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "所提供的到期日期无效。" + }, + "deletionDateIsInvalid": { + "message": "所提供的删除日期无效。" + }, + "expirationDateAndTimeRequired": { + "message": "需要到期日期和时间。" + }, + "deletionDateAndTimeRequired": { + "message": "需要删除日期和时间。" + }, + "dateParsingError": { + "message": "保存您的删除和到期日期时出错。" + }, + "hideEmail": { + "message": "对收件人隐藏我的电子邮件地址。" + }, + "sendOptionsPolicyInEffect": { + "message": "一个或多个组织策略正在影响您的 Send 选项。" + }, + "passwordPrompt": { + "message": "重新询问主密码" + }, + "passwordConfirmation": { + "message": "确认主密码" + }, + "passwordConfirmationDesc": { + "message": "此操作受到保护。若要继续,请重新输入您的主密码以验证您的身份。" + }, + "emailVerificationRequired": { + "message": "需要验证电子邮件地址" + }, + "emailVerificationRequiredDesc": { + "message": "您必须验证电子邮件才能使用此功能。您可以在网页密码库中验证您的电子邮件。" + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "selectFolder": { + "message": "Select folder..." + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "copyCustomFieldNameInvalidElement": { + "message": "Unable to identify a valid form element. Try inspecting the HTML instead." + }, + "copyCustomFieldNameNotUnique": { + "message": "No unique identifier found." + } +} diff --git a/apps/browser/src/_locales/zh_TW/messages.json b/apps/browser/src/_locales/zh_TW/messages.json new file mode 100644 index 0000000000..58f30ba0f3 --- /dev/null +++ b/apps/browser/src/_locales/zh_TW/messages.json @@ -0,0 +1,1943 @@ +{ + "appName": { + "message": "Bitwarden" + }, + "extName": { + "message": "Bitwarden - 免費密碼管理工具", + "description": "Extension name, MUST be less than 40 characters (Safari restriction)" + }, + "extDesc": { + "message": "Bitwarden 是一款安全、免費、跨平台的密碼管理工具。", + "description": "Extension description" + }, + "loginOrCreateNewAccount": { + "message": "登入或建立帳戶以存取您的安全密碼庫。" + }, + "createAccount": { + "message": "建立帳戶" + }, + "login": { + "message": "登入" + }, + "enterpriseSingleSignOn": { + "message": "企業單一登入" + }, + "cancel": { + "message": "取消" + }, + "close": { + "message": "關閉" + }, + "submit": { + "message": "送出" + }, + "emailAddress": { + "message": "電子郵件地址" + }, + "masterPass": { + "message": "主密碼" + }, + "masterPassDesc": { + "message": "主密碼是用於存取密碼庫的密碼。它非常重要,請您不要忘記它。若您忘記了主密碼,沒有任何方法能將其復原。" + }, + "masterPassHintDesc": { + "message": "主密碼提示可以在您忘記主密碼時幫助您回憶主密碼。" + }, + "reTypeMasterPass": { + "message": "重新輸入主密碼" + }, + "masterPassHint": { + "message": "主密碼提示(選用)" + }, + "tab": { + "message": "分頁" + }, + "myVault": { + "message": "密碼庫" + }, + "tools": { + "message": "工具" + }, + "settings": { + "message": "設定" + }, + "currentTab": { + "message": "目前分頁" + }, + "copyPassword": { + "message": "複製密碼" + }, + "copyNote": { + "message": "複製備註" + }, + "copyUri": { + "message": "複製 URI" + }, + "copyUsername": { + "message": "複製使用者名稱" + }, + "copyNumber": { + "message": "複製號碼" + }, + "copySecurityCode": { + "message": "複製安全代碼" + }, + "autoFill": { + "message": "自動填入" + }, + "generatePasswordCopied": { + "message": "產生及複製密碼" + }, + "copyElementIdentifier": { + "message": "複製自訂欄位名稱" + }, + "noMatchingLogins": { + "message": "無符合的登入資料。" + }, + "unlockVaultMenu": { + "message": "解鎖您的密碼庫" + }, + "loginToVaultMenu": { + "message": "登入您的密碼庫" + }, + "autoFillInfo": { + "message": "沒有可以自動填入目前瀏覽器分頁的登入資料。" + }, + "addLogin": { + "message": "新增登入資料" + }, + "addItem": { + "message": "新增項目" + }, + "passwordHint": { + "message": "密碼提示" + }, + "enterEmailToGetHint": { + "message": "請輸入您的帳户電子郵件地址以接收主密碼提示。" + }, + "getMasterPasswordHint": { + "message": "取得主密碼提示" + }, + "continue": { + "message": "繼續" + }, + "sendVerificationCode": { + "message": "傳送驗證碼至您的電子郵件信箱" + }, + "sendCode": { + "message": "傳送驗證碼" + }, + "codeSent": { + "message": "驗證碼已傳送" + }, + "verificationCode": { + "message": "驗證碼" + }, + "confirmIdentity": { + "message": "請先確認身分後再繼續。" + }, + "account": { + "message": "帳戶" + }, + "changeMasterPassword": { + "message": "變更主密碼" + }, + "fingerprintPhrase": { + "message": "指紋短語", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "您帳戶的指紋短語", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "twoStepLogin": { + "message": "兩步驟登入" + }, + "logOut": { + "message": "登出" + }, + "about": { + "message": "關於" + }, + "version": { + "message": "版本" + }, + "save": { + "message": "儲存" + }, + "move": { + "message": "移動" + }, + "addFolder": { + "message": "新增資料夾" + }, + "name": { + "message": "名稱" + }, + "editFolder": { + "message": "編輯資料夾" + }, + "deleteFolder": { + "message": "刪除資料夾" + }, + "folders": { + "message": "資料夾" + }, + "noFolders": { + "message": "沒有可列出的資料夾。" + }, + "helpFeedback": { + "message": "協助與意見反應" + }, + "sync": { + "message": "同步" + }, + "syncVaultNow": { + "message": "立即同步密碼庫" + }, + "lastSync": { + "message": "上次同步於:" + }, + "passGen": { + "message": "密碼產生器" + }, + "generator": { + "message": "產生器", + "description": "Short for 'Password Generator'." + }, + "passGenInfo": { + "message": "自動產生安全、唯一的登入密碼。" + }, + "bitWebVault": { + "message": "Bitwarden 網頁版密碼庫" + }, + "importItems": { + "message": "匯入項目" + }, + "select": { + "message": "選擇" + }, + "generatePassword": { + "message": "產生密碼" + }, + "regeneratePassword": { + "message": "重新產生密碼" + }, + "options": { + "message": "選項" + }, + "length": { + "message": "長度" + }, + "uppercase": { + "message": "大寫 (A-Z)" + }, + "lowercase": { + "message": "小寫 (a-z)" + }, + "numbers": { + "message": "數字 (0-9)" + }, + "specialCharacters": { + "message": "特殊字元 (!@#$%^&*)" + }, + "numWords": { + "message": "字數" + }, + "wordSeparator": { + "message": "文字分隔字元" + }, + "capitalize": { + "message": "大寫", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "包含數字" + }, + "minNumbers": { + "message": "最少數字位數" + }, + "minSpecial": { + "message": "最少符號位數" + }, + "avoidAmbChar": { + "message": "避免易混淆的字元" + }, + "searchVault": { + "message": "搜尋密碼庫" + }, + "edit": { + "message": "編輯" + }, + "view": { + "message": "檢視" + }, + "noItemsInList": { + "message": "沒有可列出的項目。" + }, + "itemInformation": { + "message": "項目資訊" + }, + "username": { + "message": "使用者名稱" + }, + "password": { + "message": "密碼" + }, + "passphrase": { + "message": "密碼短語" + }, + "favorite": { + "message": "我的最愛" + }, + "notes": { + "message": "備註" + }, + "note": { + "message": "備註" + }, + "editItem": { + "message": "編輯項目" + }, + "folder": { + "message": "資料夾" + }, + "deleteItem": { + "message": "刪除項目" + }, + "viewItem": { + "message": "檢視項目" + }, + "launch": { + "message": "啟動" + }, + "website": { + "message": "網站" + }, + "toggleVisibility": { + "message": "切換可見度" + }, + "manage": { + "message": "管理" + }, + "other": { + "message": "其他" + }, + "rateExtension": { + "message": "為本套件評分" + }, + "rateExtensionDesc": { + "message": "請給予我們好評!" + }, + "browserNotSupportClipboard": { + "message": "您的瀏覽器不支援剪貼簿簡單複製,請手動複製。" + }, + "verifyIdentity": { + "message": "驗證身份" + }, + "yourVaultIsLocked": { + "message": "您的密碼庫已鎖定。請驗證身分以繼續。" + }, + "unlock": { + "message": "解鎖" + }, + "loggedInAsOn": { + "message": "已在 $HOSTNAME$ 以 $EMAIL$ 身份登入。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "無效的主密碼" + }, + "vaultTimeout": { + "message": "密碼庫逾時時間" + }, + "lockNow": { + "message": "立即鎖定" + }, + "immediately": { + "message": "立即" + }, + "tenSeconds": { + "message": "10 秒鐘" + }, + "twentySeconds": { + "message": "20 秒鐘" + }, + "thirtySeconds": { + "message": "30 秒鐘" + }, + "oneMinute": { + "message": "1 分鐘" + }, + "twoMinutes": { + "message": "2 分鐘" + }, + "fiveMinutes": { + "message": "5 分鐘" + }, + "fifteenMinutes": { + "message": "15 分鐘" + }, + "thirtyMinutes": { + "message": "30 分鐘" + }, + "oneHour": { + "message": "1 小時" + }, + "fourHours": { + "message": "4 小時" + }, + "onLocked": { + "message": "系統鎖定時" + }, + "onRestart": { + "message": "重新啟動瀏覽器時" + }, + "never": { + "message": "永不" + }, + "security": { + "message": "安全" + }, + "errorOccurred": { + "message": "發生錯誤" + }, + "emailRequired": { + "message": "必須填入電子郵件地址 。" + }, + "invalidEmail": { + "message": "無效的電子郵件地址。" + }, + "masterPassRequired": { + "message": "必須填入主密碼。" + }, + "masterPassLength": { + "message": "主密碼需要至少 8 個字元。" + }, + "masterPassDoesntMatch": { + "message": "兩次填入的主密碼不相符。" + }, + "newAccountCreated": { + "message": "帳戶已建立!現在可以登入了。" + }, + "masterPassSent": { + "message": "已寄出包含您主密碼提示的電子郵件。" + }, + "verificationCodeRequired": { + "message": "必須填入驗證碼。" + }, + "invalidVerificationCode": { + "message": "無效的驗證碼" + }, + "valueCopied": { + "message": "$VALUE$ 已複製", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "autofillError": { + "message": "無法在此頁面自動填入所選項目。請手動複製貼上。" + }, + "loggedOut": { + "message": "已登出" + }, + "loginExpired": { + "message": "您的登入階段已過期。" + }, + "logOutConfirmation": { + "message": "您確定要登出嗎?" + }, + "yes": { + "message": "是" + }, + "no": { + "message": "否" + }, + "unexpectedError": { + "message": "發生了未預期的錯誤。" + }, + "nameRequired": { + "message": "必須填入名稱。" + }, + "addedFolder": { + "message": "已新增資料夾" + }, + "changeMasterPass": { + "message": "變更主密碼" + }, + "changeMasterPasswordConfirmation": { + "message": "您可以在 Bitwarden 網頁版密碼庫變更主密碼。要現在前往嗎?" + }, + "twoStepLoginConfirmation": { + "message": "兩步驟登入需要您從其他裝置(例如安全金鑰、驗證器程式、SMS、手機或電子郵件)來驗證您的登入,這使您的帳戶更加安全。兩步驟登入可以在 Bitwarden 網頁版密碼庫啟用。要現在前往嗎?" + }, + "editedFolder": { + "message": "已編輯資料夾" + }, + "deleteFolderConfirmation": { + "message": "您確定要刪除此資料夾嗎?" + }, + "deletedFolder": { + "message": "已刪除資料夾" + }, + "gettingStartedTutorial": { + "message": "新手教學" + }, + "gettingStartedTutorialVideo": { + "message": "觀看我們的新手教學,了解如何充分利用瀏覽器擴充套件。" + }, + "syncingComplete": { + "message": "同步完成" + }, + "syncingFailed": { + "message": "同步失敗" + }, + "passwordCopied": { + "message": "已複製密碼" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "新增 URI" + }, + "addedItem": { + "message": "已新增項目" + }, + "editedItem": { + "message": "已編輯項目" + }, + "deleteItemConfirmation": { + "message": "確定要刪除此項目嗎?" + }, + "deletedItem": { + "message": "將項目移至垃圾桶" + }, + "overwritePassword": { + "message": "覆寫密碼" + }, + "overwritePasswordConfirmation": { + "message": "您確定要覆寫目前的密碼嗎?" + }, + "overwriteUsername": { + "message": "覆寫使用者名稱" + }, + "overwriteUsernameConfirmation": { + "message": "您確定要覆寫目前的使用者名稱嗎?" + }, + "searchFolder": { + "message": "搜尋資料夾" + }, + "searchCollection": { + "message": "搜尋集合" + }, + "searchType": { + "message": "搜尋類型" + }, + "noneFolder": { + "message": "(未分類)", + "description": "This is the folder for uncategorized items" + }, + "disableAddLoginNotification": { + "message": "停用新增登入資料提示" + }, + "addLoginNotificationDesc": { + "message": "當您首次登入時,「新增登入資料提示」會自動提醒您在密碼庫中新增登入資料。" + }, + "dontShowCardsCurrentTab": { + "message": "不要在分頁頁面顯示支付卡" + }, + "dontShowCardsCurrentTabDesc": { + "message": "將密碼庫中的支付卡項目列在「目前分頁」頁面上,以便於自動填入。" + }, + "dontShowIdentitiesCurrentTab": { + "message": "不要在分頁頁面顯示身分" + }, + "dontShowIdentitiesCurrentTabDesc": { + "message": "將密碼庫中的身分項目列在「目前分頁」頁面上,以便於自動填入。" + }, + "clearClipboard": { + "message": "清除剪貼簿", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "自動清除剪貼簿中複製的值。", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "notificationAddDesc": { + "message": "希望 Bitwarden 幫您儲存這個密碼嗎?" + }, + "notificationAddSave": { + "message": "儲存" + }, + "disableChangedPasswordNotification": { + "message": "停用密碼變更通知" + }, + "disableChangedPasswordNotificationDesc": { + "message": "偵測到您變更網站上的密碼時,「密碼變更通知」將會自動提醒您更新密碼庫的密碼。" + }, + "notificationChangeDesc": { + "message": "是否要在 Bitwarden 中更新此密碼?" + }, + "notificationChangeSave": { + "message": "更新" + }, + "disableContextMenuItem": { + "message": "停用右鍵選單選項" + }, + "disableContextMenuItemDesc": { + "message": "右鍵選單選項幫您快速使用密碼產生器,以及快速登入目前分頁中的網站。" + }, + "defaultUriMatchDetection": { + "message": "預設的 URI 一致性偵測", + "description": "Default URI match detection for auto-fill." + }, + "defaultUriMatchDetectionDesc": { + "message": "選擇在執行自動填入等動作時對登入資料進行 URI 一致性偵測的預設方式。" + }, + "theme": { + "message": "主題" + }, + "themeDesc": { + "message": "變更應用程式的主題色彩。" + }, + "dark": { + "message": "深色", + "description": "Dark color" + }, + "light": { + "message": "淺色", + "description": "Light color" + }, + "solarizedDark": { + "message": "Solarized Dark", + "description": "'Solarized' is a noun and the name of a color scheme. It should not be translated." + }, + "exportVault": { + "message": "匯出密碼庫" + }, + "fileFormat": { + "message": "檔案格式" + }, + "warning": { + "message": "警告", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "確認匯出密碼庫" + }, + "exportWarningDesc": { + "message": "此次匯出的密碼庫資料為未加密格式。您不應將它存放或經由不安全的方式(例如電子郵件)傳送。用完後請立即將它刪除。" + }, + "encExportKeyWarningDesc": { + "message": "將使用您帳戶的加密金鑰來加密匯出的資料,若您更新了帳戶的加密金鑰,請重新匯出,否則將無法解密匯出的檔案。" + }, + "encExportAccountWarningDesc": { + "message": "每個 Bitwarden 使用者帳戶的帳戶加密金鑰都不相同,因此無法將已加密匯出的檔案匯入至不同帳戶中。" + }, + "exportMasterPassword": { + "message": "輸入您的主密碼以匯出密碼庫資料。" + }, + "shared": { + "message": "已共用" + }, + "learnOrg": { + "message": "瞭解組織" + }, + "learnOrgConfirmation": { + "message": "Bitwarden 允許您使用組織與他人分享您的密碼庫項目。您想造訪 bitwarden.com 網站以深入了解內容嗎?" + }, + "moveToOrganization": { + "message": "移動至組織 " + }, + "share": { + "message": "共用" + }, + "movedItemToOrg": { + "message": "已將 $ITEMNAME$ 移動至 $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "選擇您希望將這個項目移動至哪個組織。項目的擁有權將會轉移至該組織。轉移之後,您將不再是此項目的直接擁有者。" + }, + "learnMore": { + "message": "深入了解" + }, + "authenticatorKeyTotp": { + "message": "驗證器金鑰 (TOTP)" + }, + "verificationCodeTotp": { + "message": "驗證碼 (TOTP)" + }, + "copyVerificationCode": { + "message": "複製驗證碼" + }, + "attachments": { + "message": "附件" + }, + "deleteAttachment": { + "message": "刪除附件" + }, + "deleteAttachmentConfirmation": { + "message": "確定要刪除此附件嗎?" + }, + "deletedAttachment": { + "message": "附件已刪除" + }, + "newAttachment": { + "message": "新增附件" + }, + "noAttachments": { + "message": "沒有附件。" + }, + "attachmentSaved": { + "message": "附件已儲存。" + }, + "file": { + "message": "檔案" + }, + "selectFile": { + "message": "選擇檔案。" + }, + "maxFileSize": { + "message": "檔案最大為 500MB。" + }, + "featureUnavailable": { + "message": "功能無法使用" + }, + "updateKey": { + "message": "更新加密金鑰前不能使用此功能。" + }, + "premiumMembership": { + "message": "進階會員" + }, + "premiumManage": { + "message": "管理會員資格" + }, + "premiumManageAlert": { + "message": "您可以在 Bitwarden 網頁版管理您的會員資格。要現在前往嗎?" + }, + "premiumRefresh": { + "message": "更新會員資格狀態" + }, + "premiumNotCurrentMember": { + "message": "您尚未成為進階會員。" + }, + "premiumSignUpAndGet": { + "message": "註冊成為進階會員將獲得:" + }, + "ppremiumSignUpStorage": { + "message": "用於檔案附件的 1 GB 加密儲存空間。" + }, + "ppremiumSignUpTwoStep": { + "message": "YubiKey、FIDO U2F 和 Duo 等額外的兩步驟登入選項。" + }, + "ppremiumSignUpReports": { + "message": "密碼健康度檢查、提供帳戶體檢以及資料外洩報告,以保障您的密碼庫安全。" + }, + "ppremiumSignUpTotp": { + "message": "用於登入您的密碼庫的 TOTP 驗證碼 (2FA) 產生器。" + }, + "ppremiumSignUpSupport": { + "message": "優先客戶支援。" + }, + "ppremiumSignUpFuture": { + "message": "未來會新增更多進階功能,敬請期待!" + }, + "premiumPurchase": { + "message": "升級為進階會員" + }, + "premiumPurchaseAlert": { + "message": "您可以在 Bitwarden 網頁版密碼庫購買進階會員資格。要現在前往嗎?" + }, + "premiumCurrentMember": { + "message": "您目前為進階會員!" + }, + "premiumCurrentMemberThanks": { + "message": "感謝您支持 Bitwarden 。" + }, + "premiumPrice": { + "message": "每年只需 $PRICE$!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "狀態更新完成" + }, + "disableAutoTotpCopy": { + "message": "停用自動 TOTP 複製" + }, + "disableAutoTotpCopyDesc": { + "message": "若您的登入資料已包含驗證器金鑰,TOTP 驗證碼會在您自動填入時自動複製至您的剪貼簿。" + }, + "disableAutoBiometricsPrompt": { + "message": "不要在啟動時提示生物特徵辨識驗證" + }, + "premiumRequired": { + "message": "需要進階會員資格" + }, + "premiumRequiredDesc": { + "message": "進階會員才可使用此功能。" + }, + "enterVerificationCodeApp": { + "message": "輸入驗證器應用程式提供的 6 位數驗證碼。" + }, + "enterVerificationCodeEmail": { + "message": "輸入已傳送至 $EMAIL$ 的 6 位數驗證碼。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "已傳送驗證電子郵件至 $EMAIL$。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "記住我" + }, + "sendVerificationCodeEmailAgain": { + "message": "再次傳送​​包含驗證碼的電子郵件" + }, + "useAnotherTwoStepMethod": { + "message": "使用另一種兩步驟登入方法" + }, + "insertYubiKey": { + "message": "將您的 YubiKey 插入電腦的 USB 連接埠,然後按一下它的按鈕。" + }, + "insertU2f": { + "message": "將您的安全金鑰插入電腦的 USB 連接埠,然後按一下它的按鈕(如有的話)。" + }, + "webAuthnNewTab": { + "message": "要開始 WebAuthn 2FA 驗證,請點選下面的按鈕開啟一個新分頁,並依照新分頁中提供的說明操作。" + }, + "webAuthnNewTabOpen": { + "message": "開啟新分頁" + }, + "webAuthnAuthenticate": { + "message": "驗證 WebAuthn" + }, + "loginUnavailable": { + "message": "無法登入" + }, + "noTwoStepProviders": { + "message": "此帳戶已啟用兩步驟登入,但是本瀏覽器不支援已設定的兩步驟登入方式。" + }, + "noTwoStepProviders2": { + "message": "請使用已支援的瀏覽器(例如 Chrome ),及/或新增可以更好地跨瀏覽器的兩步驟登入方法(例如驗證器應用程式)。" + }, + "twoStepOptions": { + "message": "兩步驟登入選項" + }, + "recoveryCodeDesc": { + "message": "無法使用任何雙因素提供程式嗎?請使用您的復原碼以停用您帳戶的所有雙因素提供程式。" + }, + "recoveryCodeTitle": { + "message": "復原碼" + }, + "authenticatorAppTitle": { + "message": "驗證器應用程式" + }, + "authenticatorAppDesc": { + "message": "使用驗證器應用程式 (如 Authy 或 Google Authenticator) 產生基於時間的驗證碼。", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP 安全金鑰" + }, + "yubiKeyDesc": { + "message": "使用 YubiKey 存取您的帳戶。支援 YubiKey 4、4 Nano、4C、以及 NEO 裝置。" + }, + "duoDesc": { + "message": "使用 Duo Security 的 Duo Mobile 程式、SMS 、撥打電話或 U2F 安全金鑰進行驗證。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "為您的組織使用 Duo Security 的 Duo Mobile 程式、SMS、撥打電話或 U2F 安全金鑰進行驗證。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "使用任何具有 WebAuthn 功能的安全金鑰來存取您的帳戶。" + }, + "emailTitle": { + "message": "電子郵件" + }, + "emailDesc": { + "message": "使用電子郵件傳送驗證碼給您。" + }, + "selfHostedEnvironment": { + "message": "自我裝載環境" + }, + "selfHostedEnvironmentFooter": { + "message": "指定您內部部署的 Bitwarden 安裝之基礎 URL。" + }, + "customEnvironment": { + "message": "自訂環境" + }, + "customEnvironmentFooter": { + "message": "適用於進階使用者。您可以單獨指定各個服務的基礎 URL。" + }, + "baseUrl": { + "message": "伺服器 URL" + }, + "apiUrl": { + "message": "API 伺服器 URL" + }, + "webVaultUrl": { + "message": "網頁版密碼庫伺服器 URL" + }, + "identityUrl": { + "message": "身分伺服器 URL" + }, + "notificationsUrl": { + "message": "通知伺服器 URL" + }, + "iconsUrl": { + "message": "圖示伺服器 URL" + }, + "environmentSaved": { + "message": "已儲存環境 URL。" + }, + "enableAutoFillOnPageLoad": { + "message": "啟用頁面載入時的自動填入功能" + }, + "enableAutoFillOnPageLoadDesc": { + "message": "如果網頁載入時偵測到登入表單,則自動執行表單填入。" + }, + "experimentalFeature": { + "message": "這目前是一項實驗性功能。要使用需自行承擔風險。" + }, + "defaultAutoFillOnPageLoad": { + "message": "登入項目的預設自動填入設定" + }, + "defaultAutoFillOnPageLoadDesc": { + "message": "啟用頁面載入時自動填入後,您可以為單個登入項目啟用或停用此功能。這是未單獨設定的登入項目的預設設定。" + }, + "itemAutoFillOnPageLoad": { + "message": "頁面載入時自動填入 (如果選項中已啟用)" + }, + "autoFillOnPageLoadUseDefault": { + "message": "使用預設設定" + }, + "autoFillOnPageLoadYes": { + "message": "頁面載入時自動填入" + }, + "autoFillOnPageLoadNo": { + "message": "不要在頁面載入時自動填入" + }, + "commandOpenPopup": { + "message": "在彈出式視窗中開啟密碼庫" + }, + "commandOpenSidebar": { + "message": "在側邊欄中開啟密碼庫" + }, + "commandAutofillDesc": { + "message": "自動將上次使用的登入資料填入目前網站" + }, + "commandGeneratePasswordDesc": { + "message": "產生一組新的隨機密碼並將它複製到剪貼簿中。" + }, + "commandLockVaultDesc": { + "message": "鎖定密碼庫" + }, + "privateModeWarning": { + "message": "私密模式的支援是實驗性功能,部分功能無法完全發揮作用。" + }, + "customFields": { + "message": "自訂欄位" + }, + "copyValue": { + "message": "複製值" + }, + "value": { + "message": "值" + }, + "newCustomField": { + "message": "新增自訂欄位" + }, + "dragToSort": { + "message": "透過拖曳來排序" + }, + "cfTypeText": { + "message": "文字型" + }, + "cfTypeHidden": { + "message": "隱藏型" + }, + "cfTypeBoolean": { + "message": "布林值" + }, + "cfTypeLinked": { + "message": "連結型", + "description": "This describes a field that is 'linked' (tied) to another field." + }, + "linkedValue": { + "message": "連結的值", + "description": "This describes a value that is 'linked' (tied) to another value." + }, + "popup2faCloseMessage": { + "message": "如果您點選彈出式視窗外的任意區域,將導致彈出式視窗關閉。您想在新視窗中開啟此彈出式視窗,以讓它不關閉嗎?" + }, + "popupU2fCloseMessage": { + "message": "此瀏覽器不能在彈出式視窗中處理 U2F 要求。是否在新視窗開啟此對話方塊,以便您能夠使用 U2F 登入?" + }, + "disableFavicon": { + "message": "停用網站圖示顯示功能" + }, + "disableFaviconDesc": { + "message": "在您密碼庫的每個登入資料旁顯示一個可辨識的圖示。" + }, + "disableBadgeCounter": { + "message": "停用圖示計數器" + }, + "disableBadgeCounterDesc": { + "message": "圖示計數器可顯示您密碼庫中可用於目前頁面的登入資料數量。" + }, + "cardholderName": { + "message": "持卡人姓名" + }, + "number": { + "message": "號碼" + }, + "brand": { + "message": "發卡組織" + }, + "expirationMonth": { + "message": "逾期月份" + }, + "expirationYear": { + "message": "逾期年份" + }, + "expiration": { + "message": "逾期" + }, + "january": { + "message": "一月" + }, + "february": { + "message": "二月" + }, + "march": { + "message": "三月" + }, + "april": { + "message": "四月" + }, + "may": { + "message": "五月" + }, + "june": { + "message": "六月" + }, + "july": { + "message": "七月" + }, + "august": { + "message": "八月" + }, + "september": { + "message": "九月" + }, + "october": { + "message": "十月" + }, + "november": { + "message": "十一月" + }, + "december": { + "message": "十二月" + }, + "securityCode": { + "message": "安全代碼" + }, + "ex": { + "message": "例如" + }, + "title": { + "message": "稱呼" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "firstName": { + "message": "名" + }, + "middleName": { + "message": "中間名" + }, + "lastName": { + "message": "姓" + }, + "fullName": { + "message": "全名" + }, + "identityName": { + "message": "身分名稱" + }, + "company": { + "message": "公司" + }, + "ssn": { + "message": "社會安全號碼" + }, + "passportNumber": { + "message": "護照號碼" + }, + "licenseNumber": { + "message": "許可證號碼" + }, + "email": { + "message": "電子郵件" + }, + "phone": { + "message": "電話號碼" + }, + "address": { + "message": "地址" + }, + "address1": { + "message": "地址 1" + }, + "address2": { + "message": "地址 2" + }, + "address3": { + "message": "地址 3" + }, + "cityTown": { + "message": "市/鎮" + }, + "stateProvince": { + "message": "州/省" + }, + "zipPostalCode": { + "message": "郵遞區號" + }, + "country": { + "message": "國家" + }, + "type": { + "message": "類型" + }, + "typeLogin": { + "message": "登入" + }, + "typeLogins": { + "message": "登入資料" + }, + "typeSecureNote": { + "message": "安全筆記" + }, + "typeCard": { + "message": "支付卡" + }, + "typeIdentity": { + "message": "身分" + }, + "passwordHistory": { + "message": "密碼歷史記錄" + }, + "back": { + "message": "返回" + }, + "collections": { + "message": "集合" + }, + "favorites": { + "message": "我的最愛" + }, + "popOutNewWindow": { + "message": "彈出至新視窗" + }, + "refresh": { + "message": "重新整理" + }, + "cards": { + "message": "支付卡" + }, + "identities": { + "message": "身分" + }, + "logins": { + "message": "登入資料" + }, + "secureNotes": { + "message": "安全筆記" + }, + "clear": { + "message": "清除", + "description": "To clear something out. example: To clear browser history." + }, + "checkPassword": { + "message": "檢查密碼是否已外洩。" + }, + "passwordExposed": { + "message": "此密碼已外洩了 $VALUE$ 次,應立即變更密碼。", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "任何已知的外洩密碼資料庫中都沒有此密碼,它目前是安全的。" + }, + "baseDomain": { + "message": "基底網域", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "網域名稱", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "主機", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "完全相符" + }, + "startsWith": { + "message": "開始於" + }, + "regEx": { + "message": "規則運算式", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "一致性偵測", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "預設一致性偵測", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "切換選項" + }, + "toggleCurrentUris": { + "message": "切換目前 URI", + "description": "Toggle the display of the URIs of the currently open tabs in the browser." + }, + "currentUri": { + "message": "目前 URI", + "description": "The URI of one of the current open tabs in the browser." + }, + "organization": { + "message": "組織", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "types": { + "message": "類型" + }, + "allItems": { + "message": "所有項目" + }, + "noPasswordsInList": { + "message": "沒有可列出的密碼。" + }, + "remove": { + "message": "移除" + }, + "default": { + "message": "預設" + }, + "dateUpdated": { + "message": "更新於", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "密碼更新於", + "description": "ex. Date this password was updated" + }, + "neverLockWarning": { + "message": "您確定要使用「永不」選項嗎?將鎖定選項設定為「永不」會將密碼庫的加密金鑰儲存在您的裝置上。如果使用此選項,應確保您的裝置是安全的。" + }, + "noOrganizationsList": { + "message": "您沒有加入任何組織。組織允許您與其他使用者安全地共用項目。" + }, + "noCollectionsInList": { + "message": "沒有可顯示的集合。" + }, + "ownership": { + "message": "擁有權" + }, + "whoOwnsThisItem": { + "message": "誰擁有這個項目?" + }, + "strong": { + "message": "強", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "良好", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "弱", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "主密碼強度太弱" + }, + "weakMasterPasswordDesc": { + "message": "您設定的主密碼很脆弱。您應該使用高強度的密碼(或密碼短語)來正確保護您的 bitwarden 帳戶。仍要使用這組主密碼嗎?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "使用 PIN 碼解鎖" + }, + "setYourPinCode": { + "message": "設定您用來解鎖 Bitwarden 的 PIN 碼。您的 PIN 設定將在您完全登出本應用程式時被重設。" + }, + "pinRequired": { + "message": "需要 PIN 碼。" + }, + "invalidPin": { + "message": "無效的 PIN 碼。" + }, + "unlockWithBiometrics": { + "message": "使用生物特徵辨識解鎖" + }, + "awaitDesktop": { + "message": "等待來自桌面應用程式的確認" + }, + "awaitDesktopDesc": { + "message": "請確認在 Bitwarden 桌面應用程式中使用了生物特徵辨識,以啟用瀏覽器的生物特徵辨識。" + }, + "lockWithMasterPassOnRestart": { + "message": "瀏覽器重啟後使用主密碼鎖定" + }, + "selectOneCollection": { + "message": "您必須至少選擇一個集合。" + }, + "cloneItem": { + "message": "複製項目" + }, + "clone": { + "message": "複製" + }, + "passwordGeneratorPolicyInEffect": { + "message": "一個或多個組織原則正影響密碼產生器設定。" + }, + "vaultTimeoutAction": { + "message": "密碼庫逾時動作" + }, + "lock": { + "message": "鎖定", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "垃圾桶", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "搜尋垃圾桶" + }, + "permanentlyDeleteItem": { + "message": "永久刪除項目" + }, + "permanentlyDeleteItemConfirmation": { + "message": "您確定要永久刪除此項目嗎?" + }, + "permanentlyDeletedItem": { + "message": "已永久刪除項目" + }, + "restoreItem": { + "message": "還原項目" + }, + "restoreItemConfirmation": { + "message": "您確定要還原此項目嗎?" + }, + "restoredItem": { + "message": "項目已還原" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "選擇登出將會在密碼庫逾時後移除對密碼庫的所有存取權限,若要重新驗證則需連線網路。確定要使用此設定嗎?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "逾時動作確認" + }, + "autoFillAndSave": { + "message": "自動填入並儲存" + }, + "autoFillSuccessAndSavedUri": { + "message": "項目已自動填入並且 URL 已儲存" + }, + "autoFillSuccess": { + "message": "項目已自動填入" + }, + "setMasterPassword": { + "message": "設定主密碼" + }, + "masterPasswordPolicyInEffect": { + "message": "一個或多個組織原則要求您的主密碼須符合下列條件:" + }, + "policyInEffectMinComplexity": { + "message": "最小複雜度為 $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "最小長度為 $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "至少包含一個大寫字元" + }, + "policyInEffectLowercase": { + "message": "至少包含一個小寫字元" + }, + "policyInEffectNumbers": { + "message": "至少包含一個數字" + }, + "policyInEffectSpecial": { + "message": "至少包含一個下列特殊字元:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "您新的主密碼不符合原則要求。" + }, + "acceptPolicies": { + "message": "若選取此方塊,代表您同意下列項目:" + }, + "acceptPoliciesError": { + "message": "尚未接受服務條款與隱私權政策。" + }, + "termsOfService": { + "message": "服務條款" + }, + "privacyPolicy": { + "message": "隱私權政策" + }, + "hintEqualsPassword": { + "message": "密碼提示不能與您的密碼相同。" + }, + "ok": { + "message": "確定" + }, + "desktopSyncVerificationTitle": { + "message": "桌面同步驗證" + }, + "desktopIntegrationVerificationText": { + "message": "請驗證桌面應用程式顯示的指紋為: " + }, + "desktopIntegrationDisabledTitle": { + "message": "瀏覽器整合未啟用" + }, + "desktopIntegrationDisabledDesc": { + "message": "瀏覽器整合在桌面應用程式中未啟用,請在桌面應用程式的設定中啟用它。" + }, + "startDesktopTitle": { + "message": "啟動 Bitwarden 桌面應用程式" + }, + "startDesktopDesc": { + "message": "Bitwarden 桌面應用程式需要在啟動狀態才能使用生物特徵辨識解鎖功能。" + }, + "errorEnableBiometricTitle": { + "message": "無法啟用生物特徵辨識" + }, + "errorEnableBiometricDesc": { + "message": "動作被桌面應用程式取消" + }, + "nativeMessagingInvalidEncryptionDesc": { + "message": "桌面應用程式廢止了安全通訊通道。請重試此操作" + }, + "nativeMessagingInvalidEncryptionTitle": { + "message": "桌面通訊已中斷" + }, + "nativeMessagingWrongUserDesc": { + "message": "桌面應用程式登入了不同的帳戶。請確保兩個應用程式登入的是同一個帳戶。" + }, + "nativeMessagingWrongUserTitle": { + "message": "帳戶不相符" + }, + "biometricsNotEnabledTitle": { + "message": "生物特徵辨識未啟用" + }, + "biometricsNotEnabledDesc": { + "message": "需先在桌面應用程式設定中啟用生物特徵辨識,才能使用瀏覽器的生物特徵辨識功能。" + }, + "biometricsNotSupportedTitle": { + "message": "不支援生物特徵辨識" + }, + "biometricsNotSupportedDesc": { + "message": "此裝置不支援瀏覽器生物特徵辨識。" + }, + "nativeMessaginPermissionErrorTitle": { + "message": "未提供權限" + }, + "nativeMessaginPermissionErrorDesc": { + "message": "沒有與 Bitwarden 桌面應用程式通訊的權限,我們無法在瀏覽器擴充套件中提供生物特徵辨識功能。請再試一次。" + }, + "nativeMessaginPermissionSidebarTitle": { + "message": "權限要求錯誤" + }, + "nativeMessaginPermissionSidebarDesc": { + "message": "此動作無法在側邊欄中完成,請在彈出式視窗中再試一次。" + }, + "personalOwnershipSubmitError": { + "message": "由於某個企業原則,您被限制為儲存項目到您的個人密碼庫。將擁有權變更為組織,並從可用的集合中選擇。" + }, + "personalOwnershipPolicyInEffect": { + "message": "組織原則正在影響您的擁有權選項。" + }, + "excludedDomains": { + "message": "排除的網域" + }, + "excludedDomainsDesc": { + "message": "Bitwarden 不會要求儲存這些網域的詳細登入資訊。必須重新整理頁面才能使變更生效。" + }, + "excludedDomainsInvalidDomain": { + "message": "$DOMAIN$ 不是一個有效的網域", + "placeholders": { + "domain": { + "content": "$1", + "example": "googlecom" + } + } + }, + "send": { + "message": "Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "searchSends": { + "message": "搜尋 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "addSend": { + "message": "新增 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeText": { + "message": "文字" + }, + "sendTypeFile": { + "message": "檔案" + }, + "allSends": { + "message": "所有 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCountReached": { + "message": "已達最大存取次數", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "expired": { + "message": "已逾期" + }, + "pendingDeletion": { + "message": "等待刪除" + }, + "passwordProtected": { + "message": "密碼保護" + }, + "copySendLink": { + "message": "複製 Send 連結", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "removePassword": { + "message": "移除密碼" + }, + "delete": { + "message": "刪除" + }, + "removedPassword": { + "message": "已移除密碼" + }, + "deletedSend": { + "message": "已刪除 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send 連結", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "disabled": { + "message": "已停用" + }, + "removePasswordConfirmation": { + "message": "您確定要移除此密碼嗎?" + }, + "deleteSend": { + "message": "刪除 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deleteSendConfirmation": { + "message": "您確定要刪除此 Send 嗎?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "編輯 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeHeader": { + "message": "這是什麽類型的 Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNameDesc": { + "message": "用於描述此 Send 的易記名稱。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendFileDesc": { + "message": "您想要傳送的檔案。" + }, + "deletionDate": { + "message": "刪除日期" + }, + "deletionDateDesc": { + "message": "此 Send 將在指定的日期和時間後被永久刪除。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "逾期日期" + }, + "expirationDateDesc": { + "message": "如果設定此選項,對此 Send 的存取將在指定的日期和時間後逾期。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "oneDay": { + "message": "1 天" + }, + "days": { + "message": "$DAYS$ 天", + "placeholders": { + "days": { + "content": "$1", + "example": "2" + } + } + }, + "custom": { + "message": "自訂" + }, + "maximumAccessCount": { + "message": "最大存取次數" + }, + "maximumAccessCountDesc": { + "message": "如果設定此選項,當達到最大存取次數時,使用者將無法再次存取此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "選用功能。使用者需提供密碼才能存取此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "關於此 Send 的私人備註。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisableDesc": { + "message": "停用此 Send 以阻止任何人存取。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendShareDesc": { + "message": "儲存時複製此 Send 的連結至剪貼簿。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "您想要傳送的文字。" + }, + "sendHideText": { + "message": "預設隱藏此 Send 的文字。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "目前存取次數" + }, + "createSend": { + "message": "建立新 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "新密碼" + }, + "sendDisabled": { + "message": "已停用 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "由於企業原則限制,您只能刪除現有的 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "已建立 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "已編輯 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinuxChromiumFileWarning": { + "message": "要選擇檔案,請在側邊欄中開啟擴充套件(若可以),或點選此橫幅彈出至新視窗。" + }, + "sendFirefoxFileWarning": { + "message": "要使用 Firefox 來選擇檔案,請在側邊欄中開啟擴充套件,或點選此橫幅彈出至新視窗。" + }, + "sendSafariFileWarning": { + "message": "要使用 Safari 來選擇檔案,請點選此橫幅彈出至新視窗。" + }, + "sendFileCalloutHeader": { + "message": "在開始之前" + }, + "sendFirefoxCustomDatePopoutMessage1": { + "message": "使用行事曆樣式的日期選擇器", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read '**To use a calendar style date picker ** click here to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage2": { + "message": "點選此處", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker **click here** to pop out your window.'" + }, + "sendFirefoxCustomDatePopoutMessage3": { + "message": "要彈出至視窗。", + "description": "This will be used as part of a larger sentence, broken up to include links. The full sentence will read 'To use a calendar style date picker click here **to pop out your window.**'" + }, + "expirationDateIsInvalid": { + "message": "指定的逾期日期無效。" + }, + "deletionDateIsInvalid": { + "message": "指定的刪除日期無效。" + }, + "expirationDateAndTimeRequired": { + "message": "要求指定逾期日期和時間。" + }, + "deletionDateAndTimeRequired": { + "message": "要求指定刪除日期和時間。" + }, + "dateParsingError": { + "message": "儲存刪除日期和逾期日期時發生錯誤。" + }, + "hideEmail": { + "message": "對收件人隱藏我的電子郵件地址。" + }, + "sendOptionsPolicyInEffect": { + "message": "一個或多個組織原則正影響您的 Send 選項。" + }, + "passwordPrompt": { + "message": "重新詢問主密碼" + }, + "passwordConfirmation": { + "message": "確認主密碼" + }, + "passwordConfirmationDesc": { + "message": "此動作受到保護。若要繼續,請重新輸入您的主密碼以驗證您的身份。" + }, + "emailVerificationRequired": { + "message": "需要驗證電子郵件" + }, + "emailVerificationRequiredDesc": { + "message": "您必須驗證您的電子郵件才能使用此功能。您可以在網頁密碼庫裡驗證您的電子郵件。" + }, + "updatedMasterPassword": { + "message": "已更新主密碼" + }, + "updateMasterPassword": { + "message": "更新主密碼" + }, + "updateMasterPasswordWarning": { + "message": "您的主密碼最近被您的組織管理者變更過。若要存取密碼庫,您必須立即更新主密碼。繼續操作會登出目前的登入階段,並要求您重新登入。其他裝置上的活動登入階段最多會保持一個小時。" + }, + "resetPasswordPolicyAutoEnroll": { + "message": "自動註冊" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "此組織有一個可以為您自動註冊密碼重設的企業原則。註冊後將允許組織管理員變更您的主密碼。" + }, + "selectFolder": { + "message": "選擇資料夾⋯" + }, + "ssoCompleteRegistration": { + "message": "要完成 SSO 登入設定,請設定一組主密碼以存取和保護您的密碼庫。" + }, + "hours": { + "message": "小時" + }, + "minutes": { + "message": "分鐘" + }, + "vaultTimeoutPolicyInEffect": { + "message": "您的組織原則正在影響您的密碼庫逾時時間。密碼庫逾時時間最多可以設定到 $HOURS$ 小時 $MINUTES$ 分鐘。", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutToLarge": { + "message": "您的密碼庫逾時時間超過組織限制。" + }, + "vaultExportDisabled": { + "message": "密碼庫匯出已停用" + }, + "personalVaultExportPolicyInEffect": { + "message": "一個或多個組織原則禁止您匯出個人密碼庫。" + }, + "copyCustomFieldNameInvalidElement": { + "message": "未能找出有效的表單元件。請試試看改用 HTML 檢查功能。" + }, + "copyCustomFieldNameNotUnique": { + "message": "找不到唯一識別碼。" + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ 使用自我裝載金鑰伺服器 SSO。此組織的成員登入時將不再需要主密碼。", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "離開組織" + }, + "removeMasterPassword": { + "message": "移除主密碼" + }, + "removedMasterPassword": { + "message": "已移除主密碼。" + }, + "leaveOrganizationConfirmation": { + "message": "您確定要離開這個組織嗎?" + }, + "leftOrganization": { + "message": "您已離開此組織。" + }, + "toggleCharacterCount": { + "message": "切換字元計數" + }, + "sessionTimeout": { + "message": "您的登入階段已逾時,請返回並嘗試重新登入。" + }, + "exportingPersonalVaultTitle": { + "message": "匯出個人密碼庫" + }, + "exportingPersonalVaultDescription": { + "message": "只會匯出與 $EMAIL$ 關聯的個人密碼庫。組織密碼庫的項目不包含在內。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "error": { + "message": "錯誤" + }, + "regenerateUsername": { + "message": "重新產生使用者名稱" + }, + "generateUsername": { + "message": "產生使用者名稱" + }, + "usernameType": { + "message": "使用者名稱類型" + }, + "plusAddressedEmail": { + "message": "加號地址電子郵件", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "使用您電子郵件提供者的子地址功能。" + }, + "catchallEmail": { + "message": "Catch-all 電子郵件" + }, + "catchallEmailDesc": { + "message": "使用您網域設定的 Catch-all 收件匣。" + }, + "random": { + "message": "隨機" + }, + "randomWord": { + "message": "隨機單字" + }, + "websiteName": { + "message": "網站名稱" + }, + "whatWouldYouLikeToGenerate": { + "message": "您想要產生什麼?" + }, + "passwordType": { + "message": "密碼類型" + }, + "service": { + "message": "服務" + } +} diff --git a/apps/browser/src/background.html b/apps/browser/src/background.html new file mode 100644 index 0000000000..0cd95f3f02 --- /dev/null +++ b/apps/browser/src/background.html @@ -0,0 +1,6 @@ + + + + + + diff --git a/apps/browser/src/background.ts b/apps/browser/src/background.ts new file mode 100644 index 0000000000..939a481bd5 --- /dev/null +++ b/apps/browser/src/background.ts @@ -0,0 +1,6 @@ +import MainBackground from "./background/main.background"; + +const bitwardenMain = ((window as any).bitwardenMain = new MainBackground()); +bitwardenMain.bootstrap().then(() => { + // Finished bootstrapping +}); diff --git a/apps/browser/src/background/commands.background.ts b/apps/browser/src/background/commands.background.ts new file mode 100644 index 0000000000..97b367e1d4 --- /dev/null +++ b/apps/browser/src/background/commands.background.ts @@ -0,0 +1,115 @@ +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; + +import { BrowserApi } from "../browser/browserApi"; + +import MainBackground from "./main.background"; +import LockedVaultPendingNotificationsItem from "./models/lockedVaultPendingNotificationsItem"; + +export default class CommandsBackground { + private isSafari: boolean; + private isVivaldi: boolean; + + constructor( + private main: MainBackground, + private passwordGenerationService: PasswordGenerationService, + private platformUtilsService: PlatformUtilsService, + private vaultTimeoutService: VaultTimeoutService, + private authService: AuthService + ) { + this.isSafari = this.platformUtilsService.isSafari(); + this.isVivaldi = this.platformUtilsService.isVivaldi(); + } + + async init() { + BrowserApi.messageListener( + "commands.background", + async (msg: any, sender: chrome.runtime.MessageSender, sendResponse: any) => { + if (msg.command === "unlockCompleted" && msg.data.target === "commands.background") { + await this.processCommand( + msg.data.commandToRetry.msg.command, + msg.data.commandToRetry.sender + ); + } + + if (this.isVivaldi && msg.command === "keyboardShortcutTriggered" && msg.shortcut) { + await this.processCommand(msg.shortcut, sender); + } + } + ); + + if (!this.isVivaldi && chrome && chrome.commands) { + chrome.commands.onCommand.addListener(async (command: string) => { + await this.processCommand(command); + }); + } + } + + private async processCommand(command: string, sender?: chrome.runtime.MessageSender) { + switch (command) { + case "generate_password": + await this.generatePasswordToClipboard(); + break; + case "autofill_login": + await this.autoFillLogin(sender ? sender.tab : null); + break; + case "open_popup": + await this.openPopup(); + break; + case "lock_vault": + await this.vaultTimeoutService.lock(true); + break; + default: + break; + } + } + + private async generatePasswordToClipboard() { + const options = (await this.passwordGenerationService.getOptions())[0]; + const password = await this.passwordGenerationService.generatePassword(options); + this.platformUtilsService.copyToClipboard(password, { window: window }); + this.passwordGenerationService.addHistory(password); + } + + private async autoFillLogin(tab?: chrome.tabs.Tab) { + if (!tab) { + tab = await BrowserApi.getTabFromCurrentWindowId(); + } + + if (tab == null) { + return; + } + + if ((await this.authService.getAuthStatus()) < AuthenticationStatus.Unlocked) { + const retryMessage: LockedVaultPendingNotificationsItem = { + commandToRetry: { + msg: { command: "autofill_login" }, + sender: { tab: tab }, + }, + target: "commands.background", + }; + await BrowserApi.tabSendMessageData( + tab, + "addToLockedVaultPendingNotifications", + retryMessage + ); + + BrowserApi.tabSendMessageData(tab, "promptForLogin"); + return; + } + + await this.main.collectPageDetailsForContentScript(tab, "autofill_cmd"); + } + + private async openPopup() { + // Chrome APIs cannot open popup + if (!this.isSafari) { + return; + } + + this.main.openPopup(); + } +} diff --git a/apps/browser/src/background/contextMenus.background.ts b/apps/browser/src/background/contextMenus.background.ts new file mode 100644 index 0000000000..29bc5254d1 --- /dev/null +++ b/apps/browser/src/background/contextMenus.background.ts @@ -0,0 +1,142 @@ +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { EventType } from "jslib-common/enums/eventType"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +import { BrowserApi } from "../browser/browserApi"; + +import MainBackground from "./main.background"; +import LockedVaultPendingNotificationsItem from "./models/lockedVaultPendingNotificationsItem"; + +export default class ContextMenusBackground { + private readonly noopCommandSuffix = "noop"; + private contextMenus: any; + + constructor( + private main: MainBackground, + private cipherService: CipherService, + private passwordGenerationService: PasswordGenerationService, + private platformUtilsService: PlatformUtilsService, + private authService: AuthService, + private eventService: EventService, + private totpService: TotpService + ) { + this.contextMenus = chrome.contextMenus; + } + + async init() { + if (!this.contextMenus) { + return; + } + + this.contextMenus.onClicked.addListener( + async (info: chrome.contextMenus.OnClickData, tab: chrome.tabs.Tab) => { + if (info.menuItemId === "generate-password") { + await this.generatePasswordToClipboard(); + } else if (info.menuItemId === "copy-identifier") { + await this.getClickedElement(tab, info.frameId); + } else if ( + info.parentMenuItemId === "autofill" || + info.parentMenuItemId === "copy-username" || + info.parentMenuItemId === "copy-password" || + info.parentMenuItemId === "copy-totp" + ) { + await this.cipherAction(tab, info); + } + } + ); + + BrowserApi.messageListener( + "contextmenus.background", + async (msg: any, sender: chrome.runtime.MessageSender, sendResponse: any) => { + if (msg.command === "unlockCompleted" && msg.data.target === "contextmenus.background") { + await this.cipherAction( + msg.data.commandToRetry.sender.tab, + msg.data.commandToRetry.msg.data + ); + } + } + ); + } + + private async generatePasswordToClipboard() { + const options = (await this.passwordGenerationService.getOptions())[0]; + const password = await this.passwordGenerationService.generatePassword(options); + this.platformUtilsService.copyToClipboard(password, { window: window }); + this.passwordGenerationService.addHistory(password); + } + + private async getClickedElement(tab: chrome.tabs.Tab, frameId: number) { + if (tab == null) { + return; + } + + BrowserApi.tabSendMessage(tab, { command: "getClickedElement" }, { frameId: frameId }); + } + + private async cipherAction(tab: chrome.tabs.Tab, info: chrome.contextMenus.OnClickData) { + const id = info.menuItemId.split("_")[1]; + + if ((await this.authService.getAuthStatus()) < AuthenticationStatus.Unlocked) { + const retryMessage: LockedVaultPendingNotificationsItem = { + commandToRetry: { + msg: { command: this.noopCommandSuffix, data: info }, + sender: { tab: tab }, + }, + target: "contextmenus.background", + }; + await BrowserApi.tabSendMessageData( + tab, + "addToLockedVaultPendingNotifications", + retryMessage + ); + + BrowserApi.tabSendMessageData(tab, "promptForLogin"); + return; + } + + let cipher: CipherView; + if (id === this.noopCommandSuffix) { + const ciphers = await this.cipherService.getAllDecryptedForUrl(tab.url); + cipher = ciphers.find((c) => c.reprompt === CipherRepromptType.None); + } else { + const ciphers = await this.cipherService.getAllDecrypted(); + cipher = ciphers.find((c) => c.id === id); + } + + if (cipher == null) { + return; + } + + if (info.parentMenuItemId === "autofill") { + await this.startAutofillPage(tab, cipher); + } else if (info.parentMenuItemId === "copy-username") { + this.platformUtilsService.copyToClipboard(cipher.login.username, { window: window }); + } else if (info.parentMenuItemId === "copy-password") { + this.platformUtilsService.copyToClipboard(cipher.login.password, { window: window }); + this.eventService.collect(EventType.Cipher_ClientCopiedPassword, cipher.id); + } else if (info.parentMenuItemId === "copy-totp") { + const totpValue = await this.totpService.getCode(cipher.login.totp); + this.platformUtilsService.copyToClipboard(totpValue, { window: window }); + } + } + + private async startAutofillPage(tab: chrome.tabs.Tab, cipher: CipherView) { + this.main.loginToAutoFill = cipher; + if (tab == null) { + return; + } + + BrowserApi.tabSendMessage(tab, { + command: "collectPageDetails", + tab: tab, + sender: "contextMenu", + }); + } +} diff --git a/apps/browser/src/background/idle.background.ts b/apps/browser/src/background/idle.background.ts new file mode 100644 index 0000000000..fb51968ad4 --- /dev/null +++ b/apps/browser/src/background/idle.background.ts @@ -0,0 +1,72 @@ +import { NotificationsService } from "jslib-common/abstractions/notifications.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; + +import { StateService } from "../services/abstractions/state.service"; + +const IdleInterval = 60 * 5; // 5 minutes + +export default class IdleBackground { + private idle: any; + private idleTimer: number = null; + private idleState = "active"; + + constructor( + private vaultTimeoutService: VaultTimeoutService, + private stateService: StateService, + private notificationsService: NotificationsService + ) { + this.idle = chrome.idle || (browser != null ? browser.idle : null); + } + + async init() { + if (!this.idle) { + return; + } + + const idleHandler = (newState: string) => { + if (newState === "active") { + this.notificationsService.reconnectFromActivity(); + } else { + this.notificationsService.disconnectFromInactivity(); + } + }; + if (this.idle.onStateChanged && this.idle.setDetectionInterval) { + this.idle.setDetectionInterval(IdleInterval); + this.idle.onStateChanged.addListener(idleHandler); + } else { + this.pollIdle(idleHandler); + } + + if (this.idle.onStateChanged) { + this.idle.onStateChanged.addListener(async (newState: string) => { + if (newState === "locked") { + // If the screen is locked or the screensaver activates + const timeout = await this.stateService.getVaultTimeout(); + if (timeout === -2) { + // On System Lock vault timeout option + const action = await this.stateService.getVaultTimeoutAction(); + if (action === "logOut") { + await this.vaultTimeoutService.logOut(); + } else { + await this.vaultTimeoutService.lock(true); + } + } + } + }); + } + } + + private pollIdle(handler: (newState: string) => void) { + if (this.idleTimer != null) { + window.clearTimeout(this.idleTimer); + this.idleTimer = null; + } + this.idle.queryState(IdleInterval, (state: string) => { + if (state !== this.idleState) { + this.idleState = state; + handler(state); + } + this.idleTimer = window.setTimeout(() => this.pollIdle(handler), 5000); + }); + } +} diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts new file mode 100644 index 0000000000..b94b93f2a9 --- /dev/null +++ b/apps/browser/src/background/main.background.ts @@ -0,0 +1,1037 @@ +import { ApiService as ApiServiceAbstraction } from "jslib-common/abstractions/api.service"; +import { AppIdService as AppIdServiceAbstraction } from "jslib-common/abstractions/appId.service"; +import { AuditService as AuditServiceAbstraction } from "jslib-common/abstractions/audit.service"; +import { AuthService as AuthServiceAbstraction } from "jslib-common/abstractions/auth.service"; +import { CipherService as CipherServiceAbstraction } from "jslib-common/abstractions/cipher.service"; +import { CollectionService as CollectionServiceAbstraction } from "jslib-common/abstractions/collection.service"; +import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service"; +import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service"; +import { ExportService as ExportServiceAbstraction } from "jslib-common/abstractions/export.service"; +import { FileUploadService as FileUploadServiceAbstraction } from "jslib-common/abstractions/fileUpload.service"; +import { FolderService as FolderServiceAbstraction } from "jslib-common/abstractions/folder.service"; +import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService as KeyConnectorServiceAbstraction } from "jslib-common/abstractions/keyConnector.service"; +import { LogService as LogServiceAbstraction } from "jslib-common/abstractions/log.service"; +import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service"; +import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service"; +import { OrganizationService as OrganizationServiceAbstraction } from "jslib-common/abstractions/organization.service"; +import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService as PolicyServiceAbstraction } from "jslib-common/abstractions/policy.service"; +import { ProviderService as ProviderServiceAbstraction } from "jslib-common/abstractions/provider.service"; +import { SearchService as SearchServiceAbstraction } from "jslib-common/abstractions/search.service"; +import { SendService as SendServiceAbstraction } from "jslib-common/abstractions/send.service"; +import { SettingsService as SettingsServiceAbstraction } from "jslib-common/abstractions/settings.service"; +import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; +import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service"; +import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service"; +import { TokenService as TokenServiceAbstraction } from "jslib-common/abstractions/token.service"; +import { TotpService as TotpServiceAbstraction } from "jslib-common/abstractions/totp.service"; +import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; +import { UserVerificationService as UserVerificationServiceAbstraction } from "jslib-common/abstractions/userVerification.service"; +import { UsernameGenerationService as UsernameGenerationServiceAbstraction } from "jslib-common/abstractions/usernameGeneration.service"; +import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { ApiService } from "jslib-common/services/api.service"; +import { AppIdService } from "jslib-common/services/appId.service"; +import { AuditService } from "jslib-common/services/audit.service"; +import { AuthService } from "jslib-common/services/auth.service"; +import { CipherService } from "jslib-common/services/cipher.service"; +import { CollectionService } from "jslib-common/services/collection.service"; +import { ConsoleLogService } from "jslib-common/services/consoleLog.service"; +import { ContainerService } from "jslib-common/services/container.service"; +import { EnvironmentService } from "jslib-common/services/environment.service"; +import { EventService } from "jslib-common/services/event.service"; +import { ExportService } from "jslib-common/services/export.service"; +import { FileUploadService } from "jslib-common/services/fileUpload.service"; +import { FolderService } from "jslib-common/services/folder.service"; +import { KeyConnectorService } from "jslib-common/services/keyConnector.service"; +import { NotificationsService } from "jslib-common/services/notifications.service"; +import { OrganizationService } from "jslib-common/services/organization.service"; +import { PasswordGenerationService } from "jslib-common/services/passwordGeneration.service"; +import { PolicyService } from "jslib-common/services/policy.service"; +import { ProviderService } from "jslib-common/services/provider.service"; +import { SearchService } from "jslib-common/services/search.service"; +import { SendService } from "jslib-common/services/send.service"; +import { SettingsService } from "jslib-common/services/settings.service"; +import { StateMigrationService } from "jslib-common/services/stateMigration.service"; +import { SyncService } from "jslib-common/services/sync.service"; +import { SystemService } from "jslib-common/services/system.service"; +import { TokenService } from "jslib-common/services/token.service"; +import { TotpService } from "jslib-common/services/totp.service"; +import { TwoFactorService } from "jslib-common/services/twoFactor.service"; +import { UserVerificationService } from "jslib-common/services/userVerification.service"; +import { UsernameGenerationService } from "jslib-common/services/usernameGeneration.service"; +import { WebCryptoFunctionService } from "jslib-common/services/webCryptoFunction.service"; + +import { BrowserApi } from "../browser/browserApi"; +import { SafariApp } from "../browser/safariApp"; +import { Account } from "../models/account"; +import { PopupUtilsService } from "../popup/services/popup-utils.service"; +import { AutofillService as AutofillServiceAbstraction } from "../services/abstractions/autofill.service"; +import { StateService as StateServiceAbstraction } from "../services/abstractions/state.service"; +import AutofillService from "../services/autofill.service"; +import { BrowserCryptoService } from "../services/browserCrypto.service"; +import BrowserMessagingService from "../services/browserMessaging.service"; +import BrowserMessagingPrivateModeBackgroundService from "../services/browserMessagingPrivateModeBackground.service"; +import BrowserPlatformUtilsService from "../services/browserPlatformUtils.service"; +import BrowserStorageService from "../services/browserStorage.service"; +import I18nService from "../services/i18n.service"; +import { StateService } from "../services/state.service"; +import { VaultFilterService } from "../services/vaultFilter.service"; +import VaultTimeoutService from "../services/vaultTimeout.service"; + +import CommandsBackground from "./commands.background"; +import ContextMenusBackground from "./contextMenus.background"; +import IdleBackground from "./idle.background"; +import IconDetails from "./models/iconDetails"; +import { NativeMessagingBackground } from "./nativeMessaging.background"; +import NotificationBackground from "./notification.background"; +import RuntimeBackground from "./runtime.background"; +import TabsBackground from "./tabs.background"; +import WebRequestBackground from "./webRequest.background"; + +export default class MainBackground { + messagingService: MessagingServiceAbstraction; + storageService: StorageServiceAbstraction; + secureStorageService: StorageServiceAbstraction; + i18nService: I18nServiceAbstraction; + platformUtilsService: PlatformUtilsServiceAbstraction; + logService: LogServiceAbstraction; + cryptoService: CryptoServiceAbstraction; + cryptoFunctionService: CryptoFunctionServiceAbstraction; + tokenService: TokenServiceAbstraction; + appIdService: AppIdServiceAbstraction; + apiService: ApiServiceAbstraction; + environmentService: EnvironmentServiceAbstraction; + settingsService: SettingsServiceAbstraction; + cipherService: CipherServiceAbstraction; + folderService: FolderServiceAbstraction; + collectionService: CollectionServiceAbstraction; + vaultTimeoutService: VaultTimeoutServiceAbstraction; + syncService: SyncServiceAbstraction; + passwordGenerationService: PasswordGenerationServiceAbstraction; + totpService: TotpServiceAbstraction; + autofillService: AutofillServiceAbstraction; + containerService: ContainerService; + auditService: AuditServiceAbstraction; + authService: AuthServiceAbstraction; + exportService: ExportServiceAbstraction; + searchService: SearchServiceAbstraction; + notificationsService: NotificationsServiceAbstraction; + stateService: StateServiceAbstraction; + stateMigrationService: StateMigrationService; + systemService: SystemServiceAbstraction; + eventService: EventServiceAbstraction; + policyService: PolicyServiceAbstraction; + popupUtilsService: PopupUtilsService; + sendService: SendServiceAbstraction; + fileUploadService: FileUploadServiceAbstraction; + organizationService: OrganizationServiceAbstraction; + providerService: ProviderServiceAbstraction; + keyConnectorService: KeyConnectorServiceAbstraction; + userVerificationService: UserVerificationServiceAbstraction; + twoFactorService: TwoFactorServiceAbstraction; + vaultFilterService: VaultFilterService; + usernameGenerationService: UsernameGenerationServiceAbstraction; + + onUpdatedRan: boolean; + onReplacedRan: boolean; + loginToAutoFill: CipherView = null; + + private commandsBackground: CommandsBackground; + private contextMenusBackground: ContextMenusBackground; + private idleBackground: IdleBackground; + private notificationBackground: NotificationBackground; + private runtimeBackground: RuntimeBackground; + private tabsBackground: TabsBackground; + private webRequestBackground: WebRequestBackground; + + private sidebarAction: any; + private buildingContextMenu: boolean; + private menuOptionsLoaded: any[] = []; + private syncTimeout: any; + private isSafari: boolean; + private nativeMessagingBackground: NativeMessagingBackground; + + constructor(public isPrivateMode: boolean = false) { + // Services + const lockedCallback = async (userId?: string) => { + if (this.notificationsService != null) { + this.notificationsService.updateConnection(false); + } + await this.setIcon(); + await this.refreshBadgeAndMenu(true); + if (this.systemService != null) { + await this.systemService.clearPendingClipboard(); + await this.reloadProcess(); + } + }; + + const logoutCallback = async (expired: boolean, userId?: string) => + await this.logout(expired, userId); + + this.messagingService = isPrivateMode + ? new BrowserMessagingPrivateModeBackgroundService() + : new BrowserMessagingService(); + this.storageService = new BrowserStorageService(); + this.secureStorageService = new BrowserStorageService(); + this.logService = new ConsoleLogService(false); + this.stateMigrationService = new StateMigrationService( + this.storageService, + this.secureStorageService, + new StateFactory(GlobalState, Account) + ); + this.stateService = new StateService( + this.storageService, + this.secureStorageService, + this.logService, + this.stateMigrationService, + new StateFactory(GlobalState, Account) + ); + this.platformUtilsService = new BrowserPlatformUtilsService( + this.messagingService, + this.stateService, + (clipboardValue, clearMs) => { + if (this.systemService != null) { + this.systemService.clearClipboard(clipboardValue, clearMs); + } + }, + async () => { + if (this.nativeMessagingBackground != null) { + const promise = this.nativeMessagingBackground.getResponse(); + + try { + await this.nativeMessagingBackground.send({ command: "biometricUnlock" }); + } catch (e) { + return Promise.reject(e); + } + + return promise.then((result) => result.response === "unlocked"); + } + } + ); + this.i18nService = new I18nService(BrowserApi.getUILanguage(window)); + this.cryptoFunctionService = new WebCryptoFunctionService(window); + this.cryptoService = new BrowserCryptoService( + this.cryptoFunctionService, + this.platformUtilsService, + this.logService, + this.stateService + ); + this.tokenService = new TokenService(this.stateService); + this.appIdService = new AppIdService(this.storageService); + this.environmentService = new EnvironmentService(this.stateService); + this.apiService = new ApiService( + this.tokenService, + this.platformUtilsService, + this.environmentService, + this.appIdService, + (expired: boolean) => this.logout(expired) + ); + this.settingsService = new SettingsService(this.stateService); + this.fileUploadService = new FileUploadService(this.logService, this.apiService); + this.cipherService = new CipherService( + this.cryptoService, + this.settingsService, + this.apiService, + this.fileUploadService, + this.i18nService, + () => this.searchService, + this.logService, + this.stateService + ); + this.folderService = new FolderService( + this.cryptoService, + this.apiService, + this.i18nService, + this.cipherService, + this.stateService + ); + this.collectionService = new CollectionService( + this.cryptoService, + this.i18nService, + this.stateService + ); + this.searchService = new SearchService(this.cipherService, this.logService, this.i18nService); + this.sendService = new SendService( + this.cryptoService, + this.apiService, + this.fileUploadService, + this.i18nService, + this.cryptoFunctionService, + this.stateService + ); + this.organizationService = new OrganizationService(this.stateService); + this.policyService = new PolicyService( + this.stateService, + this.organizationService, + this.apiService + ); + this.keyConnectorService = new KeyConnectorService( + this.stateService, + this.cryptoService, + this.apiService, + this.tokenService, + this.logService, + this.organizationService, + this.cryptoFunctionService, + logoutCallback + ); + this.vaultFilterService = new VaultFilterService( + this.stateService, + this.organizationService, + this.folderService, + this.cipherService, + this.collectionService, + this.policyService + ); + + this.twoFactorService = new TwoFactorService(this.i18nService, this.platformUtilsService); + + // eslint-disable-next-line + const that = this; + const backgroundMessagingService = new (class extends MessagingServiceAbstraction { + // AuthService should send the messages to the background not popup. + send = (subscriber: string, arg: any = {}) => { + const message = Object.assign({}, { command: subscriber }, arg); + that.runtimeBackground.processMessage(message, that, null); + }; + })(); + this.authService = new AuthService( + this.cryptoService, + this.apiService, + this.tokenService, + this.appIdService, + this.platformUtilsService, + backgroundMessagingService, + this.logService, + this.keyConnectorService, + this.environmentService, + this.stateService, + this.twoFactorService, + this.i18nService + ); + + this.vaultTimeoutService = new VaultTimeoutService( + this.cipherService, + this.folderService, + this.collectionService, + this.cryptoService, + this.platformUtilsService, + this.messagingService, + this.searchService, + this.tokenService, + this.policyService, + this.keyConnectorService, + this.stateService, + this.authService, + lockedCallback, + logoutCallback + ); + this.providerService = new ProviderService(this.stateService); + this.syncService = new SyncService( + this.apiService, + this.settingsService, + this.folderService, + this.cipherService, + this.cryptoService, + this.collectionService, + this.messagingService, + this.policyService, + this.sendService, + this.logService, + this.keyConnectorService, + this.stateService, + this.organizationService, + this.providerService, + logoutCallback + ); + this.eventService = new EventService( + this.apiService, + this.cipherService, + this.stateService, + this.logService, + this.organizationService + ); + this.passwordGenerationService = new PasswordGenerationService( + this.cryptoService, + this.policyService, + this.stateService + ); + this.totpService = new TotpService( + this.cryptoFunctionService, + this.logService, + this.stateService + ); + this.autofillService = new AutofillService( + this.cipherService, + this.stateService, + this.totpService, + this.eventService, + this.logService + ); + this.containerService = new ContainerService(this.cryptoService); + this.auditService = new AuditService(this.cryptoFunctionService, this.apiService); + this.exportService = new ExportService( + this.folderService, + this.cipherService, + this.apiService, + this.cryptoService, + this.cryptoFunctionService + ); + this.notificationsService = new NotificationsService( + this.syncService, + this.appIdService, + this.apiService, + this.environmentService, + logoutCallback, + this.logService, + this.stateService, + this.authService + ); + this.popupUtilsService = new PopupUtilsService(isPrivateMode); + + this.userVerificationService = new UserVerificationService( + this.cryptoService, + this.i18nService, + this.apiService + ); + + const systemUtilsServiceReloadCallback = () => { + const forceWindowReload = + this.platformUtilsService.isSafari() || + this.platformUtilsService.isFirefox() || + this.platformUtilsService.isOpera(); + BrowserApi.reloadExtension(forceWindowReload ? window : null); + return Promise.resolve(); + }; + + this.systemService = new SystemService( + this.messagingService, + this.platformUtilsService, + systemUtilsServiceReloadCallback, + this.stateService + ); + + // Other fields + this.isSafari = this.platformUtilsService.isSafari(); + this.sidebarAction = this.isSafari + ? null + : typeof opr !== "undefined" && opr.sidebarAction + ? opr.sidebarAction + : (window as any).chrome.sidebarAction; + + // Background + this.runtimeBackground = new RuntimeBackground( + this, + this.autofillService, + this.platformUtilsService as BrowserPlatformUtilsService, + this.i18nService, + this.notificationsService, + this.systemService, + this.environmentService, + this.messagingService, + this.logService + ); + this.nativeMessagingBackground = new NativeMessagingBackground( + this.cryptoService, + this.cryptoFunctionService, + this.runtimeBackground, + this.i18nService, + this.messagingService, + this.appIdService, + this.platformUtilsService, + this.stateService, + this.logService, + this.authService + ); + this.commandsBackground = new CommandsBackground( + this, + this.passwordGenerationService, + this.platformUtilsService, + this.vaultTimeoutService, + this.authService + ); + this.notificationBackground = new NotificationBackground( + this.autofillService, + this.cipherService, + this.authService, + this.policyService, + this.folderService, + this.stateService + ); + + this.tabsBackground = new TabsBackground(this, this.notificationBackground); + this.contextMenusBackground = new ContextMenusBackground( + this, + this.cipherService, + this.passwordGenerationService, + this.platformUtilsService, + this.authService, + this.eventService, + this.totpService + ); + this.idleBackground = new IdleBackground( + this.vaultTimeoutService, + this.stateService, + this.notificationsService + ); + this.webRequestBackground = new WebRequestBackground( + this.platformUtilsService, + this.cipherService, + this.authService + ); + + this.usernameGenerationService = new UsernameGenerationService( + this.cryptoService, + this.stateService, + this.apiService + ); + } + + async bootstrap() { + this.containerService.attachToWindow(window); + + await this.stateService.init(); + + await (this.vaultTimeoutService as VaultTimeoutService).init(true); + await (this.i18nService as I18nService).init(); + await (this.eventService as EventService).init(true); + await this.runtimeBackground.init(); + await this.notificationBackground.init(); + await this.commandsBackground.init(); + + this.twoFactorService.init(); + + await this.tabsBackground.init(); + await this.contextMenusBackground.init(); + await this.idleBackground.init(); + await this.webRequestBackground.init(); + + if (this.platformUtilsService.isFirefox() && !this.isPrivateMode) { + // Set Private Mode windows to the default icon - they do not share state with the background page + const privateWindows = await BrowserApi.getPrivateModeWindows(); + privateWindows.forEach(async (win) => { + await this.actionSetIcon(chrome.browserAction, "", win.id); + await this.actionSetIcon(this.sidebarAction, "", win.id); + }); + + BrowserApi.onWindowCreated(async (win) => { + if (win.incognito) { + await this.actionSetIcon(chrome.browserAction, "", win.id); + await this.actionSetIcon(this.sidebarAction, "", win.id); + } + }); + } + + return new Promise((resolve) => { + setTimeout(async () => { + await this.environmentService.setUrlsFromStorage(); + await this.setIcon(); + this.fullSync(true); + setTimeout(() => this.notificationsService.init(), 2500); + resolve(); + }, 500); + }); + } + + async setIcon() { + if ((!chrome.browserAction && !this.sidebarAction) || this.isPrivateMode) { + return; + } + + const authStatus = await this.authService.getAuthStatus(); + + let suffix = ""; + if (authStatus === AuthenticationStatus.LoggedOut) { + suffix = "_gray"; + } else if (authStatus === AuthenticationStatus.Locked) { + suffix = "_locked"; + } + + await this.actionSetIcon(chrome.browserAction, suffix); + await this.actionSetIcon(this.sidebarAction, suffix); + } + + async refreshBadgeAndMenu(forLocked = false) { + if (!chrome.windows || !chrome.contextMenus) { + return; + } + + const menuDisabled = await this.stateService.getDisableContextMenuItem(); + if (!menuDisabled) { + await this.buildContextMenu(); + } else { + await this.contextMenusRemoveAll(); + } + + if (forLocked) { + await this.loadMenuAndUpdateBadgeForNoAccessState(!menuDisabled); + this.onUpdatedRan = this.onReplacedRan = false; + return; + } + + const tab = await BrowserApi.getTabFromCurrentWindow(); + if (tab) { + await this.contextMenuReady(tab, !menuDisabled); + } + } + + async logout(expired: boolean, userId?: string) { + await this.eventService.uploadEvents(userId); + + await Promise.all([ + this.eventService.clearEvents(userId), + this.syncService.setLastSync(new Date(0), userId), + this.cryptoService.clearKeys(userId), + this.settingsService.clear(userId), + this.cipherService.clear(userId), + this.folderService.clear(userId), + this.collectionService.clear(userId), + this.policyService.clear(userId), + this.passwordGenerationService.clear(userId), + this.vaultTimeoutService.clear(userId), + this.keyConnectorService.clear(), + this.vaultFilterService.clear(), + ]); + + await this.stateService.clean({ userId: userId }); + + if (userId == null || userId === (await this.stateService.getUserId())) { + this.searchService.clearIndex(); + this.messagingService.send("doneLoggingOut", { expired: expired, userId: userId }); + } + + await this.setIcon(); + await this.refreshBadgeAndMenu(true); + await this.reseedStorage(); + this.notificationsService.updateConnection(false); + await this.systemService.clearPendingClipboard(); + await this.reloadProcess(); + } + + async collectPageDetailsForContentScript(tab: any, sender: string, frameId: number = null) { + if (tab == null || !tab.id) { + return; + } + + const options: any = {}; + if (frameId != null) { + options.frameId = frameId; + } + + BrowserApi.tabSendMessage( + tab, + { + command: "collectPageDetails", + tab: tab, + sender: sender, + }, + options + ); + } + + async openPopup() { + // Chrome APIs cannot open popup + + // TODO: Do we need to open this popup? + if (!this.isSafari) { + return; + } + await SafariApp.sendMessageToApp("showPopover", null, true); + } + + async reseedStorage() { + if ( + !this.platformUtilsService.isChrome() && + !this.platformUtilsService.isVivaldi() && + !this.platformUtilsService.isOpera() + ) { + return; + } + + const currentVaultTimeout = await this.stateService.getVaultTimeout(); + if (currentVaultTimeout == null) { + return; + } + + const getStorage = (): Promise => + new Promise((resolve) => { + chrome.storage.local.get(null, (o: any) => resolve(o)); + }); + + const clearStorage = (): Promise => + new Promise((resolve) => { + chrome.storage.local.clear(() => resolve()); + }); + + const storage = await getStorage(); + await clearStorage(); + + for (const key in storage) { + // eslint-disable-next-line + if (!storage.hasOwnProperty(key)) { + continue; + } + await this.storageService.save(key, storage[key]); + } + } + + private async buildContextMenu() { + if (!chrome.contextMenus || this.buildingContextMenu) { + return; + } + + this.buildingContextMenu = true; + await this.contextMenusRemoveAll(); + + await this.contextMenusCreate({ + type: "normal", + id: "root", + contexts: ["all"], + title: "Bitwarden", + }); + + await this.contextMenusCreate({ + type: "normal", + id: "autofill", + parentId: "root", + contexts: ["all"], + title: this.i18nService.t("autoFill"), + }); + + await this.contextMenusCreate({ + type: "normal", + id: "copy-username", + parentId: "root", + contexts: ["all"], + title: this.i18nService.t("copyUsername"), + }); + + await this.contextMenusCreate({ + type: "normal", + id: "copy-password", + parentId: "root", + contexts: ["all"], + title: this.i18nService.t("copyPassword"), + }); + + if (await this.stateService.getCanAccessPremium()) { + await this.contextMenusCreate({ + type: "normal", + id: "copy-totp", + parentId: "root", + contexts: ["all"], + title: this.i18nService.t("copyVerificationCode"), + }); + } + + await this.contextMenusCreate({ + type: "separator", + parentId: "root", + }); + + await this.contextMenusCreate({ + type: "normal", + id: "generate-password", + parentId: "root", + contexts: ["all"], + title: this.i18nService.t("generatePasswordCopied"), + }); + + await this.contextMenusCreate({ + type: "normal", + id: "copy-identifier", + parentId: "root", + contexts: ["all"], + title: this.i18nService.t("copyElementIdentifier"), + }); + + this.buildingContextMenu = false; + } + + private async contextMenuReady(tab: any, contextMenuEnabled: boolean) { + await this.loadMenuAndUpdateBadge(tab.url, tab.id, contextMenuEnabled); + this.onUpdatedRan = this.onReplacedRan = false; + } + + private async loadMenuAndUpdateBadge(url: string, tabId: number, contextMenuEnabled: boolean) { + if (!url || (!chrome.browserAction && !this.sidebarAction)) { + return; + } + + this.actionSetBadgeBackgroundColor(chrome.browserAction); + this.actionSetBadgeBackgroundColor(this.sidebarAction); + + this.menuOptionsLoaded = []; + const authStatus = await this.authService.getAuthStatus(); + if (authStatus === AuthenticationStatus.Unlocked) { + try { + const ciphers = await this.cipherService.getAllDecryptedForUrl(url); + ciphers.sort((a, b) => this.cipherService.sortCiphersByLastUsedThenName(a, b)); + + if (contextMenuEnabled) { + ciphers.forEach((cipher) => { + this.loadLoginContextMenuOptions(cipher); + }); + } + + const disableBadgeCounter = await this.stateService.getDisableBadgeCounter(); + let theText = ""; + + if (!disableBadgeCounter) { + if (ciphers.length > 0 && ciphers.length <= 9) { + theText = ciphers.length.toString(); + } else if (ciphers.length > 0) { + theText = "9+"; + } + } + + if (contextMenuEnabled && ciphers.length === 0) { + await this.loadNoLoginsContextMenuOptions(this.i18nService.t("noMatchingLogins")); + } + + this.sidebarActionSetBadgeText(theText, tabId); + this.browserActionSetBadgeText(theText, tabId); + + return; + } catch (e) { + this.logService.error(e); + } + } + + await this.loadMenuAndUpdateBadgeForNoAccessState(contextMenuEnabled); + } + + private async loadMenuAndUpdateBadgeForNoAccessState(contextMenuEnabled: boolean) { + if (contextMenuEnabled) { + const authed = await this.stateService.getIsAuthenticated(); + await this.loadNoLoginsContextMenuOptions( + this.i18nService.t(authed ? "unlockVaultMenu" : "loginToVaultMenu") + ); + } + + const tabs = await BrowserApi.getActiveTabs(); + if (tabs != null) { + tabs.forEach((tab) => { + if (tab.id != null) { + this.browserActionSetBadgeText("", tab.id); + this.sidebarActionSetBadgeText("", tab.id); + } + }); + } + } + + private async loadLoginContextMenuOptions(cipher: any) { + if ( + cipher == null || + cipher.type !== CipherType.Login || + cipher.reprompt !== CipherRepromptType.None + ) { + return; + } + + let title = cipher.name; + if (cipher.login.username && cipher.login.username !== "") { + title += " (" + cipher.login.username + ")"; + } + await this.loadContextMenuOptions(title, cipher.id, cipher); + } + + private async loadNoLoginsContextMenuOptions(noLoginsMessage: string) { + await this.loadContextMenuOptions(noLoginsMessage, "noop", null); + } + + private async loadContextMenuOptions(title: string, idSuffix: string, cipher: any) { + if ( + !chrome.contextMenus || + this.menuOptionsLoaded.indexOf(idSuffix) > -1 || + (cipher != null && cipher.type !== CipherType.Login) + ) { + return; + } + + this.menuOptionsLoaded.push(idSuffix); + + if (cipher == null || (cipher.login.password && cipher.login.password !== "")) { + await this.contextMenusCreate({ + type: "normal", + id: "autofill_" + idSuffix, + parentId: "autofill", + contexts: ["all"], + title: this.sanitizeContextMenuTitle(title), + }); + } + + if (cipher == null || (cipher.login.username && cipher.login.username !== "")) { + await this.contextMenusCreate({ + type: "normal", + id: "copy-username_" + idSuffix, + parentId: "copy-username", + contexts: ["all"], + title: this.sanitizeContextMenuTitle(title), + }); + } + + if ( + cipher == null || + (cipher.login.password && cipher.login.password !== "" && cipher.viewPassword) + ) { + await this.contextMenusCreate({ + type: "normal", + id: "copy-password_" + idSuffix, + parentId: "copy-password", + contexts: ["all"], + title: this.sanitizeContextMenuTitle(title), + }); + } + + const canAccessPremium = await this.stateService.getCanAccessPremium(); + if (canAccessPremium && (cipher == null || (cipher.login.totp && cipher.login.totp !== ""))) { + await this.contextMenusCreate({ + type: "normal", + id: "copy-totp_" + idSuffix, + parentId: "copy-totp", + contexts: ["all"], + title: this.sanitizeContextMenuTitle(title), + }); + } + } + + private sanitizeContextMenuTitle(title: string): string { + return title.replace(/&/g, "&&"); + } + + private async fullSync(override = false) { + const syncInternal = 6 * 60 * 60 * 1000; // 6 hours + const lastSync = await this.syncService.getLastSync(); + + let lastSyncAgo = syncInternal + 1; + if (lastSync != null) { + lastSyncAgo = new Date().getTime() - lastSync.getTime(); + } + + if (override || lastSyncAgo >= syncInternal) { + await this.syncService.fullSync(override); + this.scheduleNextSync(); + } else { + this.scheduleNextSync(); + } + } + + private scheduleNextSync() { + if (this.syncTimeout) { + clearTimeout(this.syncTimeout); + } + + this.syncTimeout = setTimeout(async () => await this.fullSync(), 5 * 60 * 1000); // check every 5 minutes + } + + // Browser API Helpers + + private contextMenusRemoveAll() { + return new Promise((resolve) => { + chrome.contextMenus.removeAll(() => { + resolve(); + if (chrome.runtime.lastError) { + return; + } + }); + }); + } + + private contextMenusCreate(options: any) { + return new Promise((resolve) => { + chrome.contextMenus.create(options, () => { + resolve(); + if (chrome.runtime.lastError) { + return; + } + }); + }); + } + + private async actionSetIcon(theAction: any, suffix: string, windowId?: number): Promise { + if (!theAction || !theAction.setIcon) { + return; + } + + const options: IconDetails = { + path: { + 19: "images/icon19" + suffix + ".png", + 38: "images/icon38" + suffix + ".png", + }, + }; + + if (this.platformUtilsService.isFirefox()) { + options.windowId = windowId; + await theAction.setIcon(options); + } else if (this.platformUtilsService.isSafari()) { + // Workaround since Safari 14.0.3 returns a pending promise + // which doesn't resolve within a reasonable time. + theAction.setIcon(options); + } else { + return new Promise((resolve) => { + theAction.setIcon(options, () => resolve()); + }); + } + } + + private actionSetBadgeBackgroundColor(action: any) { + if (action && action.setBadgeBackgroundColor) { + action.setBadgeBackgroundColor({ color: "#294e5f" }); + } + } + + private browserActionSetBadgeText(text: string, tabId: number) { + if (chrome.browserAction && chrome.browserAction.setBadgeText) { + chrome.browserAction.setBadgeText({ + text: text, + tabId: tabId, + }); + } + } + + private sidebarActionSetBadgeText(text: string, tabId: number) { + if (!this.sidebarAction) { + return; + } + + if (this.sidebarAction.setBadgeText) { + this.sidebarAction.setBadgeText({ + text: text, + tabId: tabId, + }); + } else if (this.sidebarAction.setTitle) { + let title = "Bitwarden"; + if (text && text !== "") { + title += " [" + text + "]"; + } + + this.sidebarAction.setTitle({ + title: title, + tabId: tabId, + }); + } + } + + private async reloadProcess(): Promise { + const accounts = this.stateService.accounts.getValue(); + if (accounts != null) { + for (const userId of Object.keys(accounts)) { + if ((await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Unlocked) { + return; + } + } + } + await this.systemService.startProcessReload(); + } +} diff --git a/apps/browser/src/background/models/addChangePasswordQueueMessage.ts b/apps/browser/src/background/models/addChangePasswordQueueMessage.ts new file mode 100644 index 0000000000..51a745643d --- /dev/null +++ b/apps/browser/src/background/models/addChangePasswordQueueMessage.ts @@ -0,0 +1,6 @@ +import NotificationQueueMessage from "./notificationQueueMessage"; + +export default class AddChangePasswordQueueMessage extends NotificationQueueMessage { + cipherId: string; + newPassword: string; +} diff --git a/apps/browser/src/background/models/addLoginQueueMessage.ts b/apps/browser/src/background/models/addLoginQueueMessage.ts new file mode 100644 index 0000000000..ba13071262 --- /dev/null +++ b/apps/browser/src/background/models/addLoginQueueMessage.ts @@ -0,0 +1,7 @@ +import NotificationQueueMessage from "./notificationQueueMessage"; + +export default class AddLoginQueueMessage extends NotificationQueueMessage { + username: string; + password: string; + uri: string; +} diff --git a/apps/browser/src/background/models/addLoginRuntimeMessage.ts b/apps/browser/src/background/models/addLoginRuntimeMessage.ts new file mode 100644 index 0000000000..e234edeb67 --- /dev/null +++ b/apps/browser/src/background/models/addLoginRuntimeMessage.ts @@ -0,0 +1,5 @@ +export default class AddLoginRuntimeMessage { + username: string; + password: string; + url: string; +} diff --git a/apps/browser/src/background/models/changePasswordRuntimeMessage.ts b/apps/browser/src/background/models/changePasswordRuntimeMessage.ts new file mode 100644 index 0000000000..072848226e --- /dev/null +++ b/apps/browser/src/background/models/changePasswordRuntimeMessage.ts @@ -0,0 +1,5 @@ +export default class ChangePasswordRuntimeMessage { + currentPassword: string; + newPassword: string; + url: string; +} diff --git a/apps/browser/src/background/models/iconDetails.ts b/apps/browser/src/background/models/iconDetails.ts new file mode 100644 index 0000000000..3d60a735fc --- /dev/null +++ b/apps/browser/src/background/models/iconDetails.ts @@ -0,0 +1,8 @@ +export default interface IconDetails { + path: { + 19: string; + 38: string; + }; + // Chrome does not support windowId, only Firefox + windowId?: number; +} diff --git a/apps/browser/src/background/models/lockedVaultPendingNotificationsItem.ts b/apps/browser/src/background/models/lockedVaultPendingNotificationsItem.ts new file mode 100644 index 0000000000..ec697b1699 --- /dev/null +++ b/apps/browser/src/background/models/lockedVaultPendingNotificationsItem.ts @@ -0,0 +1,7 @@ +export default class LockedVaultPendingNotificationsItem { + commandToRetry: { + msg: any; + sender: chrome.runtime.MessageSender; + }; + target: string; +} diff --git a/apps/browser/src/background/models/notificationQueueMessage.ts b/apps/browser/src/background/models/notificationQueueMessage.ts new file mode 100644 index 0000000000..f0984133ae --- /dev/null +++ b/apps/browser/src/background/models/notificationQueueMessage.ts @@ -0,0 +1,9 @@ +import { NotificationQueueMessageType } from "./notificationQueueMessageType"; + +export default class NotificationQueueMessage { + type: NotificationQueueMessageType; + domain: string; + tabId: number; + expires: Date; + wasVaultLocked: boolean; +} diff --git a/apps/browser/src/background/models/notificationQueueMessageType.ts b/apps/browser/src/background/models/notificationQueueMessageType.ts new file mode 100644 index 0000000000..f5e4115c4f --- /dev/null +++ b/apps/browser/src/background/models/notificationQueueMessageType.ts @@ -0,0 +1,4 @@ +export enum NotificationQueueMessageType { + AddLogin = 0, + ChangePassword = 1, +} diff --git a/apps/browser/src/background/nativeMessaging.background.ts b/apps/browser/src/background/nativeMessaging.background.ts new file mode 100644 index 0000000000..e48345be11 --- /dev/null +++ b/apps/browser/src/background/nativeMessaging.background.ts @@ -0,0 +1,379 @@ +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { Utils } from "jslib-common/misc/utils"; +import { EncString } from "jslib-common/models/domain/encString"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; + +import { BrowserApi } from "../browser/browserApi"; + +import RuntimeBackground from "./runtime.background"; + +const MessageValidTimeout = 10 * 1000; +const EncryptionAlgorithm = "sha1"; + +type Message = { + command: string; + + // Filled in by this service + userId?: string; + timestamp?: number; + + // Used for sharing secret + publicKey?: string; +}; + +type OuterMessage = { + message: Message | EncString; + appId: string; +}; + +type ReceiveMessage = { + timestamp: number; + command: string; + response?: any; + + // Unlock key + keyB64?: string; +}; + +type ReceiveMessageOuter = { + command: string; + appId: string; + + // Should only have one of these. + message?: EncString; + sharedSecret?: string; +}; + +export class NativeMessagingBackground { + private connected = false; + private connecting: boolean; + private port: browser.runtime.Port | chrome.runtime.Port; + + private resolver: any = null; + private privateKey: ArrayBuffer = null; + private publicKey: ArrayBuffer = null; + private secureSetupResolve: any = null; + private sharedSecret: SymmetricCryptoKey; + private appId: string; + private validatingFingerprint: boolean; + + constructor( + private cryptoService: CryptoService, + private cryptoFunctionService: CryptoFunctionService, + private runtimeBackground: RuntimeBackground, + private i18nService: I18nService, + private messagingService: MessagingService, + private appIdService: AppIdService, + private platformUtilsService: PlatformUtilsService, + private stateService: StateService, + private logService: LogService, + private authService: AuthService + ) { + this.stateService.setBiometricFingerprintValidated(false); + + if (chrome?.permissions?.onAdded) { + // Reload extension to activate nativeMessaging + chrome.permissions.onAdded.addListener((permissions) => { + BrowserApi.reloadExtension(null); + }); + } + } + + async connect() { + this.appId = await this.appIdService.getAppId(); + this.stateService.setBiometricFingerprintValidated(false); + + return new Promise((resolve, reject) => { + this.port = BrowserApi.connectNative("com.8bit.bitwarden"); + + this.connecting = true; + + const connectedCallback = () => { + this.connected = true; + this.connecting = false; + resolve(); + }; + + // Safari has a bundled native component which is always available, no need to + // check if the desktop app is running. + if (this.platformUtilsService.isSafari()) { + connectedCallback(); + } + + this.port.onMessage.addListener(async (message: ReceiveMessageOuter) => { + switch (message.command) { + case "connected": + connectedCallback(); + break; + case "disconnected": + if (this.connecting) { + reject("startDesktop"); + } + this.connected = false; + this.port.disconnect(); + break; + case "setupEncryption": { + // Ignore since it belongs to another device + if (message.appId !== this.appId) { + return; + } + + const encrypted = Utils.fromB64ToArray(message.sharedSecret); + const decrypted = await this.cryptoFunctionService.rsaDecrypt( + encrypted.buffer, + this.privateKey, + EncryptionAlgorithm + ); + + if (this.validatingFingerprint) { + this.validatingFingerprint = false; + this.stateService.setBiometricFingerprintValidated(true); + } + this.sharedSecret = new SymmetricCryptoKey(decrypted); + this.secureSetupResolve(); + break; + } + case "invalidateEncryption": + // Ignore since it belongs to another device + if (message.appId !== this.appId) { + return; + } + + this.sharedSecret = null; + this.privateKey = null; + this.connected = false; + + this.messagingService.send("showDialog", { + text: this.i18nService.t("nativeMessagingInvalidEncryptionDesc"), + title: this.i18nService.t("nativeMessagingInvalidEncryptionTitle"), + confirmText: this.i18nService.t("ok"), + type: "error", + }); + break; + case "verifyFingerprint": { + if (this.sharedSecret == null) { + this.validatingFingerprint = true; + this.showFingerprintDialog(); + } + break; + } + case "wrongUserId": + this.showWrongUserDialog(); + break; + default: + // Ignore since it belongs to another device + if (!this.platformUtilsService.isSafari() && message.appId !== this.appId) { + return; + } + + this.onMessage(message.message); + } + }); + + this.port.onDisconnect.addListener((p: any) => { + let error; + if (BrowserApi.isWebExtensionsApi) { + error = p.error.message; + } else { + error = chrome.runtime.lastError.message; + } + + this.sharedSecret = null; + this.privateKey = null; + this.connected = false; + + const reason = error != null ? "desktopIntegrationDisabled" : null; + reject(reason); + }); + }); + } + + showWrongUserDialog() { + this.messagingService.send("showDialog", { + text: this.i18nService.t("nativeMessagingWrongUserDesc"), + title: this.i18nService.t("nativeMessagingWrongUserTitle"), + confirmText: this.i18nService.t("ok"), + type: "error", + }); + } + + async send(message: Message) { + if (!this.connected) { + await this.connect(); + } + + message.userId = await this.stateService.getUserId(); + message.timestamp = Date.now(); + + if (this.platformUtilsService.isSafari()) { + this.postMessage(message as any); + } else { + this.postMessage({ appId: this.appId, message: await this.encryptMessage(message) }); + } + } + + async encryptMessage(message: Message) { + if (this.sharedSecret == null) { + await this.secureCommunication(); + } + + return await this.cryptoService.encrypt(JSON.stringify(message), this.sharedSecret); + } + + getResponse(): Promise { + return new Promise((resolve, reject) => { + this.resolver = resolve; + }); + } + + private postMessage(message: OuterMessage) { + // Wrap in try-catch to when the port disconnected without triggering `onDisconnect`. + try { + this.port.postMessage(message); + } catch (e) { + this.logService.error("NativeMessaging port disconnected, disconnecting."); + + this.sharedSecret = null; + this.privateKey = null; + this.connected = false; + + this.messagingService.send("showDialog", { + text: this.i18nService.t("nativeMessagingInvalidEncryptionDesc"), + title: this.i18nService.t("nativeMessagingInvalidEncryptionTitle"), + confirmText: this.i18nService.t("ok"), + type: "error", + }); + } + } + + private async onMessage(rawMessage: ReceiveMessage | EncString) { + let message = rawMessage as ReceiveMessage; + if (!this.platformUtilsService.isSafari()) { + message = JSON.parse( + await this.cryptoService.decryptToUtf8(rawMessage as EncString, this.sharedSecret) + ); + } + + if (Math.abs(message.timestamp - Date.now()) > MessageValidTimeout) { + this.logService.error("NativeMessage is to old, ignoring."); + return; + } + + switch (message.command) { + case "biometricUnlock": { + await this.stateService.setBiometricAwaitingAcceptance(null); + + if (message.response === "not enabled") { + this.messagingService.send("showDialog", { + text: this.i18nService.t("biometricsNotEnabledDesc"), + title: this.i18nService.t("biometricsNotEnabledTitle"), + confirmText: this.i18nService.t("ok"), + type: "error", + }); + break; + } else if (message.response === "not supported") { + this.messagingService.send("showDialog", { + text: this.i18nService.t("biometricsNotSupportedDesc"), + title: this.i18nService.t("biometricsNotSupportedTitle"), + confirmText: this.i18nService.t("ok"), + type: "error", + }); + break; + } + + const enabled = await this.stateService.getBiometricUnlock(); + if (enabled === null || enabled === false) { + if (message.response === "unlocked") { + await this.stateService.setBiometricUnlock(true); + } + break; + } + + // Ignore unlock if already unlocked + if ((await this.authService.getAuthStatus()) === AuthenticationStatus.Unlocked) { + break; + } + + if (message.response === "unlocked") { + await this.cryptoService.setKey( + new SymmetricCryptoKey(Utils.fromB64ToArray(message.keyB64).buffer) + ); + + // Verify key is correct by attempting to decrypt a secret + try { + await this.cryptoService.getFingerprint(await this.stateService.getUserId()); + } catch (e) { + this.logService.error("Unable to verify key: " + e); + await this.cryptoService.clearKey(); + this.showWrongUserDialog(); + + // Exit early + if (this.resolver) { + this.resolver(message); + } + return; + } + + await this.stateService.setBiometricLocked(false); + this.runtimeBackground.processMessage({ command: "unlocked" }, null, null); + } + break; + } + default: + this.logService.error("NativeMessage, got unknown command: " + message.command); + break; + } + + if (this.resolver) { + this.resolver(message); + } + } + + private async secureCommunication() { + const [publicKey, privateKey] = await this.cryptoFunctionService.rsaGenerateKeyPair(2048); + this.publicKey = publicKey; + this.privateKey = privateKey; + + this.sendUnencrypted({ + command: "setupEncryption", + publicKey: Utils.fromBufferToB64(publicKey), + userId: await this.stateService.getUserId(), + }); + + return new Promise((resolve, reject) => (this.secureSetupResolve = resolve)); + } + + private async sendUnencrypted(message: Message) { + if (!this.connected) { + await this.connect(); + } + + message.timestamp = Date.now(); + + this.postMessage({ appId: this.appId, message: message }); + } + + private async showFingerprintDialog() { + const fingerprint = ( + await this.cryptoService.getFingerprint(await this.stateService.getUserId(), this.publicKey) + ).join(" "); + + this.messagingService.send("showDialog", { + html: `${this.i18nService.t( + "desktopIntegrationVerificationText" + )}

${fingerprint}`, + title: this.i18nService.t("desktopSyncVerificationTitle"), + confirmText: this.i18nService.t("ok"), + type: "warning", + }); + } +} diff --git a/apps/browser/src/background/notification.background.ts b/apps/browser/src/background/notification.background.ts new file mode 100644 index 0000000000..366eddc61a --- /dev/null +++ b/apps/browser/src/background/notification.background.ts @@ -0,0 +1,449 @@ +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { PolicyType } from "jslib-common/enums/policyType"; +import { Utils } from "jslib-common/misc/utils"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; +import { LoginView } from "jslib-common/models/view/loginView"; + +import { BrowserApi } from "../browser/browserApi"; +import { AutofillService } from "../services/abstractions/autofill.service"; +import { StateService } from "../services/abstractions/state.service"; + +import AddChangePasswordQueueMessage from "./models/addChangePasswordQueueMessage"; +import AddLoginQueueMessage from "./models/addLoginQueueMessage"; +import AddLoginRuntimeMessage from "./models/addLoginRuntimeMessage"; +import ChangePasswordRuntimeMessage from "./models/changePasswordRuntimeMessage"; +import LockedVaultPendingNotificationsItem from "./models/lockedVaultPendingNotificationsItem"; +import { NotificationQueueMessageType } from "./models/notificationQueueMessageType"; + +export default class NotificationBackground { + private notificationQueue: (AddLoginQueueMessage | AddChangePasswordQueueMessage)[] = []; + + constructor( + private autofillService: AutofillService, + private cipherService: CipherService, + private authService: AuthService, + private policyService: PolicyService, + private folderService: FolderService, + private stateService: StateService + ) {} + + async init() { + if (chrome.runtime == null) { + return; + } + + BrowserApi.messageListener( + "notification.background", + async (msg: any, sender: chrome.runtime.MessageSender) => { + await this.processMessage(msg, sender); + } + ); + + this.cleanupNotificationQueue(); + } + + async processMessage(msg: any, sender: chrome.runtime.MessageSender) { + switch (msg.command) { + case "unlockCompleted": + if (msg.data.target !== "notification.background") { + return; + } + await this.processMessage(msg.data.commandToRetry.msg, msg.data.commandToRetry.sender); + break; + case "bgGetDataForTab": + await this.getDataForTab(sender.tab, msg.responseCommand); + break; + case "bgCloseNotificationBar": + await BrowserApi.tabSendMessageData(sender.tab, "closeNotificationBar"); + break; + case "bgAdjustNotificationBar": + await BrowserApi.tabSendMessageData(sender.tab, "adjustNotificationBar", msg.data); + break; + case "bgAddLogin": + await this.addLogin(msg.login, sender.tab); + break; + case "bgChangedPassword": + await this.changedPassword(msg.data, sender.tab); + break; + case "bgAddClose": + case "bgChangeClose": + this.removeTabFromNotificationQueue(sender.tab); + break; + case "bgAddSave": + case "bgChangeSave": + if ((await this.authService.getAuthStatus()) < AuthenticationStatus.Unlocked) { + const retryMessage: LockedVaultPendingNotificationsItem = { + commandToRetry: { + msg: msg, + sender: sender, + }, + target: "notification.background", + }; + await BrowserApi.tabSendMessageData( + sender.tab, + "addToLockedVaultPendingNotifications", + retryMessage + ); + await BrowserApi.tabSendMessageData(sender.tab, "promptForLogin"); + return; + } + await this.saveOrUpdateCredentials(sender.tab, msg.folder); + break; + case "bgNeverSave": + await this.saveNever(sender.tab); + break; + case "collectPageDetailsResponse": + switch (msg.sender) { + case "notificationBar": { + const forms = this.autofillService.getFormsWithPasswordFields(msg.details); + await BrowserApi.tabSendMessageData(msg.tab, "notificationBarPageDetails", { + details: msg.details, + forms: forms, + }); + break; + } + default: + break; + } + break; + default: + break; + } + } + + async checkNotificationQueue(tab: chrome.tabs.Tab = null): Promise { + if (this.notificationQueue.length === 0) { + return; + } + + if (tab != null) { + this.doNotificationQueueCheck(tab); + return; + } + + const currentTab = await BrowserApi.getTabFromCurrentWindow(); + if (currentTab != null) { + this.doNotificationQueueCheck(currentTab); + } + } + + private cleanupNotificationQueue() { + for (let i = this.notificationQueue.length - 1; i >= 0; i--) { + if (this.notificationQueue[i].expires < new Date()) { + this.notificationQueue.splice(i, 1); + } + } + setTimeout(() => this.cleanupNotificationQueue(), 2 * 60 * 1000); // check every 2 minutes + } + + private doNotificationQueueCheck(tab: chrome.tabs.Tab): void { + if (tab == null) { + return; + } + + const tabDomain = Utils.getDomain(tab.url); + if (tabDomain == null) { + return; + } + + for (let i = 0; i < this.notificationQueue.length; i++) { + if ( + this.notificationQueue[i].tabId !== tab.id || + this.notificationQueue[i].domain !== tabDomain + ) { + continue; + } + + if (this.notificationQueue[i].type === NotificationQueueMessageType.AddLogin) { + BrowserApi.tabSendMessageData(tab, "openNotificationBar", { + type: "add", + typeData: { + isVaultLocked: this.notificationQueue[i].wasVaultLocked, + }, + }); + } else if (this.notificationQueue[i].type === NotificationQueueMessageType.ChangePassword) { + BrowserApi.tabSendMessageData(tab, "openNotificationBar", { + type: "change", + typeData: { + isVaultLocked: this.notificationQueue[i].wasVaultLocked, + }, + }); + } + break; + } + } + + private removeTabFromNotificationQueue(tab: chrome.tabs.Tab) { + for (let i = this.notificationQueue.length - 1; i >= 0; i--) { + if (this.notificationQueue[i].tabId === tab.id) { + this.notificationQueue.splice(i, 1); + } + } + } + + private async addLogin(loginInfo: AddLoginRuntimeMessage, tab: chrome.tabs.Tab) { + const authStatus = await this.authService.getAuthStatus(); + if (authStatus === AuthenticationStatus.LoggedOut) { + return; + } + + const loginDomain = Utils.getDomain(loginInfo.url); + if (loginDomain == null) { + return; + } + + let normalizedUsername = loginInfo.username; + if (normalizedUsername != null) { + normalizedUsername = normalizedUsername.toLowerCase(); + } + + const disabledAddLogin = await this.stateService.getDisableAddLoginNotification(); + if (authStatus === AuthenticationStatus.Locked) { + if (disabledAddLogin) { + return; + } + + if (!(await this.allowPersonalOwnership())) { + return; + } + + this.pushAddLoginToQueue(loginDomain, loginInfo, tab, true); + return; + } + + const ciphers = await this.cipherService.getAllDecryptedForUrl(loginInfo.url); + const usernameMatches = ciphers.filter( + (c) => c.login.username != null && c.login.username.toLowerCase() === normalizedUsername + ); + if (usernameMatches.length === 0) { + if (disabledAddLogin) { + return; + } + + if (!(await this.allowPersonalOwnership())) { + return; + } + + this.pushAddLoginToQueue(loginDomain, loginInfo, tab); + } else if ( + usernameMatches.length === 1 && + usernameMatches[0].login.password !== loginInfo.password + ) { + const disabledChangePassword = + await this.stateService.getDisableChangedPasswordNotification(); + if (disabledChangePassword) { + return; + } + this.pushChangePasswordToQueue(usernameMatches[0].id, loginDomain, loginInfo.password, tab); + } + } + + private async pushAddLoginToQueue( + loginDomain: string, + loginInfo: AddLoginRuntimeMessage, + tab: chrome.tabs.Tab, + isVaultLocked = false + ) { + // remove any old messages for this tab + this.removeTabFromNotificationQueue(tab); + const message: AddLoginQueueMessage = { + type: NotificationQueueMessageType.AddLogin, + username: loginInfo.username, + password: loginInfo.password, + domain: loginDomain, + uri: loginInfo.url, + tabId: tab.id, + expires: new Date(new Date().getTime() + 5 * 60000), // 5 minutes + wasVaultLocked: isVaultLocked, + }; + this.notificationQueue.push(message); + await this.checkNotificationQueue(tab); + } + + private async changedPassword(changeData: ChangePasswordRuntimeMessage, tab: chrome.tabs.Tab) { + const loginDomain = Utils.getDomain(changeData.url); + if (loginDomain == null) { + return; + } + + if ((await this.authService.getAuthStatus()) < AuthenticationStatus.Unlocked) { + this.pushChangePasswordToQueue(null, loginDomain, changeData.newPassword, tab, true); + return; + } + + let id: string = null; + const ciphers = await this.cipherService.getAllDecryptedForUrl(changeData.url); + if (changeData.currentPassword != null) { + const passwordMatches = ciphers.filter( + (c) => c.login.password === changeData.currentPassword + ); + if (passwordMatches.length === 1) { + id = passwordMatches[0].id; + } + } else if (ciphers.length === 1) { + id = ciphers[0].id; + } + if (id != null) { + this.pushChangePasswordToQueue(id, loginDomain, changeData.newPassword, tab); + } + } + + private async pushChangePasswordToQueue( + cipherId: string, + loginDomain: string, + newPassword: string, + tab: chrome.tabs.Tab, + isVaultLocked = false + ) { + // remove any old messages for this tab + this.removeTabFromNotificationQueue(tab); + const message: AddChangePasswordQueueMessage = { + type: NotificationQueueMessageType.ChangePassword, + cipherId: cipherId, + newPassword: newPassword, + domain: loginDomain, + tabId: tab.id, + expires: new Date(new Date().getTime() + 5 * 60000), // 5 minutes + wasVaultLocked: isVaultLocked, + }; + this.notificationQueue.push(message); + await this.checkNotificationQueue(tab); + } + + private async saveOrUpdateCredentials(tab: chrome.tabs.Tab, folderId?: string) { + for (let i = this.notificationQueue.length - 1; i >= 0; i--) { + const queueMessage = this.notificationQueue[i]; + if ( + queueMessage.tabId !== tab.id || + (queueMessage.type !== NotificationQueueMessageType.AddLogin && + queueMessage.type !== NotificationQueueMessageType.ChangePassword) + ) { + continue; + } + + const tabDomain = Utils.getDomain(tab.url); + if (tabDomain != null && tabDomain !== queueMessage.domain) { + continue; + } + + this.notificationQueue.splice(i, 1); + BrowserApi.tabSendMessageData(tab, "closeNotificationBar"); + + if (queueMessage.type === NotificationQueueMessageType.ChangePassword) { + const changePasswordMessage = queueMessage as AddChangePasswordQueueMessage; + const cipher = await this.getDecryptedCipherById(changePasswordMessage.cipherId); + if (cipher == null) { + return; + } + await this.updateCipher(cipher, changePasswordMessage.newPassword); + return; + } + + if (queueMessage.type === NotificationQueueMessageType.AddLogin) { + if (!queueMessage.wasVaultLocked) { + await this.createNewCipher(queueMessage as AddLoginQueueMessage, folderId); + BrowserApi.tabSendMessageData(tab, "addedCipher"); + return; + } + + // If the vault was locked, check if a cipher needs updating instead of creating a new one + const addLoginMessage = queueMessage as AddLoginQueueMessage; + const ciphers = await this.cipherService.getAllDecryptedForUrl(addLoginMessage.uri); + const usernameMatches = ciphers.filter( + (c) => + c.login.username != null && c.login.username.toLowerCase() === addLoginMessage.username + ); + + if (usernameMatches.length >= 1) { + await this.updateCipher(usernameMatches[0], addLoginMessage.password); + return; + } + + await this.createNewCipher(addLoginMessage, folderId); + BrowserApi.tabSendMessageData(tab, "addedCipher"); + } + } + } + + private async createNewCipher(queueMessage: AddLoginQueueMessage, folderId: string) { + const loginModel = new LoginView(); + const loginUri = new LoginUriView(); + loginUri.uri = queueMessage.uri; + loginModel.uris = [loginUri]; + loginModel.username = queueMessage.username; + loginModel.password = queueMessage.password; + const model = new CipherView(); + model.name = Utils.getHostname(queueMessage.uri) || queueMessage.domain; + model.name = model.name.replace(/^www\./, ""); + model.type = CipherType.Login; + model.login = loginModel; + + if (!Utils.isNullOrWhitespace(folderId)) { + const folders = await this.folderService.getAllDecrypted(); + if (folders.some((x) => x.id === folderId)) { + model.folderId = folderId; + } + } + + const cipher = await this.cipherService.encrypt(model); + await this.cipherService.saveWithServer(cipher); + } + + private async getDecryptedCipherById(cipherId: string) { + const cipher = await this.cipherService.get(cipherId); + if (cipher != null && cipher.type === CipherType.Login) { + return await cipher.decrypt(); + } + return null; + } + + private async updateCipher(cipher: CipherView, newPassword: string) { + if (cipher != null && cipher.type === CipherType.Login) { + cipher.login.password = newPassword; + const newCipher = await this.cipherService.encrypt(cipher); + await this.cipherService.saveWithServer(newCipher); + } + } + + private async saveNever(tab: chrome.tabs.Tab) { + for (let i = this.notificationQueue.length - 1; i >= 0; i--) { + const queueMessage = this.notificationQueue[i]; + if ( + queueMessage.tabId !== tab.id || + queueMessage.type !== NotificationQueueMessageType.AddLogin + ) { + continue; + } + + const tabDomain = Utils.getDomain(tab.url); + if (tabDomain != null && tabDomain !== queueMessage.domain) { + continue; + } + + this.notificationQueue.splice(i, 1); + BrowserApi.tabSendMessageData(tab, "closeNotificationBar"); + + const hostname = Utils.getHostname(tab.url); + await this.cipherService.saveNeverDomain(hostname); + } + } + + private async getDataForTab(tab: chrome.tabs.Tab, responseCommand: string) { + const responseData: any = {}; + if (responseCommand === "notificationBarGetFoldersList") { + responseData.folders = await this.folderService.getAllDecrypted(); + } + + await BrowserApi.tabSendMessageData(tab, responseCommand, responseData); + } + + private async allowPersonalOwnership(): Promise { + return !(await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership)); + } +} diff --git a/apps/browser/src/background/runtime.background.ts b/apps/browser/src/background/runtime.background.ts new file mode 100644 index 0000000000..9c5ce75fac --- /dev/null +++ b/apps/browser/src/background/runtime.background.ts @@ -0,0 +1,235 @@ +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { NotificationsService } from "jslib-common/abstractions/notifications.service"; +import { SystemService } from "jslib-common/abstractions/system.service"; +import { Utils } from "jslib-common/misc/utils"; + +import { BrowserApi } from "../browser/browserApi"; +import { AutofillService } from "../services/abstractions/autofill.service"; +import BrowserPlatformUtilsService from "../services/browserPlatformUtils.service"; + +import MainBackground from "./main.background"; +import LockedVaultPendingNotificationsItem from "./models/lockedVaultPendingNotificationsItem"; + +export default class RuntimeBackground { + private autofillTimeout: any; + private pageDetailsToAutoFill: any[] = []; + private onInstalledReason: string = null; + private lockedVaultPendingNotifications: LockedVaultPendingNotificationsItem[] = []; + + constructor( + private main: MainBackground, + private autofillService: AutofillService, + private platformUtilsService: BrowserPlatformUtilsService, + private i18nService: I18nService, + private notificationsService: NotificationsService, + private systemService: SystemService, + private environmentService: EnvironmentService, + private messagingService: MessagingService, + private logService: LogService + ) { + // onInstalled listener must be wired up before anything else, so we do it in the ctor + chrome.runtime.onInstalled.addListener((details: any) => { + this.onInstalledReason = details.reason; + }); + } + + async init() { + if (!chrome.runtime) { + return; + } + + await this.checkOnInstalled(); + const backgroundMessageListener = async ( + msg: any, + sender: chrome.runtime.MessageSender, + sendResponse: any + ) => { + await this.processMessage(msg, sender, sendResponse); + }; + + BrowserApi.messageListener("runtime.background", backgroundMessageListener); + if (this.main.isPrivateMode) { + (window as any).bitwardenBackgroundMessageListener = backgroundMessageListener; + } + } + + async processMessage(msg: any, sender: any, sendResponse: any) { + switch (msg.command) { + case "loggedIn": + case "unlocked": { + let item: LockedVaultPendingNotificationsItem; + + if (this.lockedVaultPendingNotifications?.length > 0) { + await BrowserApi.closeLoginTab(); + + item = this.lockedVaultPendingNotifications.pop(); + if (item.commandToRetry.sender?.tab?.id) { + await BrowserApi.focusSpecifiedTab(item.commandToRetry.sender.tab.id); + } + } + + await this.main.setIcon(); + await this.main.refreshBadgeAndMenu(false); + this.notificationsService.updateConnection(msg.command === "unlocked"); + this.systemService.cancelProcessReload(); + + if (item) { + await BrowserApi.tabSendMessageData( + item.commandToRetry.sender.tab, + "unlockCompleted", + item + ); + } + break; + } + case "addToLockedVaultPendingNotifications": + this.lockedVaultPendingNotifications.push(msg.data); + break; + case "logout": + await this.main.logout(msg.expired, msg.userId); + break; + case "syncCompleted": + if (msg.successfully) { + setTimeout(async () => await this.main.refreshBadgeAndMenu(), 2000); + } + break; + case "openPopup": + await this.main.openPopup(); + break; + case "promptForLogin": + await BrowserApi.createNewTab("popup/index.html?uilocation=popout", true, true); + break; + case "showDialogResolve": + this.platformUtilsService.resolveDialogPromise(msg.dialogId, msg.confirmed); + break; + case "bgCollectPageDetails": + await this.main.collectPageDetailsForContentScript(sender.tab, msg.sender, sender.frameId); + break; + case "bgUpdateContextMenu": + case "editedCipher": + case "addedCipher": + case "deletedCipher": + await this.main.refreshBadgeAndMenu(); + break; + case "bgReseedStorage": + await this.main.reseedStorage(); + break; + case "collectPageDetailsResponse": + switch (msg.sender) { + case "autofiller": + case "autofill_cmd": { + const totpCode = await this.autofillService.doAutoFillActiveTab( + [ + { + frameId: sender.frameId, + tab: msg.tab, + details: msg.details, + }, + ], + msg.sender === "autofill_cmd" + ); + if (totpCode != null) { + this.platformUtilsService.copyToClipboard(totpCode, { window: window }); + } + break; + } + case "contextMenu": + clearTimeout(this.autofillTimeout); + this.pageDetailsToAutoFill.push({ + frameId: sender.frameId, + tab: msg.tab, + details: msg.details, + }); + this.autofillTimeout = setTimeout(async () => await this.autofillPage(), 300); + break; + default: + break; + } + break; + case "authResult": { + const vaultUrl = this.environmentService.getWebVaultUrl(); + + if (msg.referrer == null || Utils.getHostname(vaultUrl) !== msg.referrer) { + return; + } + + try { + BrowserApi.createNewTab( + "popup/index.html?uilocation=popout#/sso?code=" + + encodeURIComponent(msg.code) + + "&state=" + + encodeURIComponent(msg.state) + ); + } catch { + this.logService.error("Unable to open sso popout tab"); + } + break; + } + case "webAuthnResult": { + const vaultUrl = this.environmentService.getWebVaultUrl(); + + if (msg.referrer == null || Utils.getHostname(vaultUrl) !== msg.referrer) { + return; + } + + const params = + `webAuthnResponse=${encodeURIComponent(msg.data)};` + + `remember=${encodeURIComponent(msg.remember)}`; + BrowserApi.createNewTab( + `popup/index.html?uilocation=popout#/2fa;${params}`, + undefined, + false + ); + break; + } + case "reloadPopup": + this.messagingService.send("reloadPopup"); + break; + case "emailVerificationRequired": + this.messagingService.send("showDialog", { + dialogId: "emailVerificationRequired", + title: this.i18nService.t("emailVerificationRequired"), + text: this.i18nService.t("emailVerificationRequiredDesc"), + confirmText: this.i18nService.t("ok"), + type: "info", + }); + break; + case "getClickedElementResponse": + this.platformUtilsService.copyToClipboard(msg.identifier, { window: window }); + break; + default: + break; + } + } + + private async autofillPage() { + const totpCode = await this.autofillService.doAutoFill({ + cipher: this.main.loginToAutoFill, + pageDetails: this.pageDetailsToAutoFill, + fillNewPassword: true, + }); + + if (totpCode != null) { + this.platformUtilsService.copyToClipboard(totpCode, { window: window }); + } + + // reset + this.main.loginToAutoFill = null; + this.pageDetailsToAutoFill = []; + } + + private async checkOnInstalled() { + setTimeout(async () => { + if (this.onInstalledReason != null) { + if (this.onInstalledReason === "install") { + BrowserApi.createNewTab("https://bitwarden.com/browser-start/"); + } + + this.onInstalledReason = null; + } + }, 100); + } +} diff --git a/apps/browser/src/background/tabs.background.ts b/apps/browser/src/background/tabs.background.ts new file mode 100644 index 0000000000..ba56d99692 --- /dev/null +++ b/apps/browser/src/background/tabs.background.ts @@ -0,0 +1,63 @@ +import MainBackground from "./main.background"; +import NotificationBackground from "./notification.background"; + +export default class TabsBackground { + constructor( + private main: MainBackground, + private notificationBackground: NotificationBackground + ) {} + + private focusedWindowId: number; + + async init() { + if (!chrome.tabs || !chrome.windows) { + return; + } + + chrome.windows.onFocusChanged.addListener(async (windowId: number) => { + if (windowId === null || windowId < 0) { + return; + } + + this.focusedWindowId = windowId; + this.main.messagingService.send("windowChanged"); + }); + + chrome.tabs.onActivated.addListener(async (activeInfo: chrome.tabs.TabActiveInfo) => { + await this.main.refreshBadgeAndMenu(); + this.main.messagingService.send("tabChanged"); + }); + + chrome.tabs.onReplaced.addListener(async (addedTabId: number, removedTabId: number) => { + if (this.main.onReplacedRan) { + return; + } + this.main.onReplacedRan = true; + + await this.notificationBackground.checkNotificationQueue(); + await this.main.refreshBadgeAndMenu(); + this.main.messagingService.send("tabChanged"); + }); + + chrome.tabs.onUpdated.addListener( + async (tabId: number, changeInfo: chrome.tabs.TabChangeInfo, tab: chrome.tabs.Tab) => { + if (this.focusedWindowId > 0 && tab.windowId != this.focusedWindowId) { + return; + } + + if (!tab.active) { + return; + } + + if (this.main.onUpdatedRan) { + return; + } + this.main.onUpdatedRan = true; + + await this.notificationBackground.checkNotificationQueue(tab); + await this.main.refreshBadgeAndMenu(); + this.main.messagingService.send("tabChanged"); + } + ); + } +} diff --git a/apps/browser/src/background/webRequest.background.ts b/apps/browser/src/background/webRequest.background.ts new file mode 100644 index 0000000000..ad78ae7085 --- /dev/null +++ b/apps/browser/src/background/webRequest.background.ts @@ -0,0 +1,96 @@ +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { UriMatchType } from "jslib-common/enums/uriMatchType"; + +export default class WebRequestBackground { + private pendingAuthRequests: any[] = []; + private webRequest: any; + private isFirefox: boolean; + + constructor( + platformUtilsService: PlatformUtilsService, + private cipherService: CipherService, + private authService: AuthService + ) { + this.webRequest = (window as any).chrome.webRequest; + this.isFirefox = platformUtilsService.isFirefox(); + } + + async init() { + if (!this.webRequest || !this.webRequest.onAuthRequired) { + return; + } + + this.webRequest.onAuthRequired.addListener( + async (details: any, callback: any) => { + if (!details.url || this.pendingAuthRequests.indexOf(details.requestId) !== -1) { + if (callback) { + callback(); + } + return; + } + + this.pendingAuthRequests.push(details.requestId); + + if (this.isFirefox) { + // eslint-disable-next-line + return new Promise(async (resolve, reject) => { + await this.resolveAuthCredentials(details.url, resolve, reject); + }); + } else { + await this.resolveAuthCredentials(details.url, callback, callback); + } + }, + { urls: ["http://*/*", "https://*/*"] }, + [this.isFirefox ? "blocking" : "asyncBlocking"] + ); + + this.webRequest.onCompleted.addListener((details: any) => this.completeAuthRequest(details), { + urls: ["http://*/*"], + }); + this.webRequest.onErrorOccurred.addListener( + (details: any) => this.completeAuthRequest(details), + { + urls: ["http://*/*"], + } + ); + } + + // eslint-disable-next-line + private async resolveAuthCredentials(domain: string, success: Function, error: Function) { + if ((await this.authService.getAuthStatus()) < AuthenticationStatus.Unlocked) { + error(); + return; + } + + try { + const ciphers = await this.cipherService.getAllDecryptedForUrl( + domain, + null, + UriMatchType.Host + ); + if (ciphers == null || ciphers.length !== 1) { + error(); + return; + } + + success({ + authCredentials: { + username: ciphers[0].login.username, + password: ciphers[0].login.password, + }, + }); + } catch { + error(); + } + } + + private completeAuthRequest(details: any) { + const i = this.pendingAuthRequests.indexOf(details.requestId); + if (i > -1) { + this.pendingAuthRequests.splice(i, 1); + } + } +} diff --git a/apps/browser/src/browser/browserApi.ts b/apps/browser/src/browser/browserApi.ts new file mode 100644 index 0000000000..bc421fad4b --- /dev/null +++ b/apps/browser/src/browser/browserApi.ts @@ -0,0 +1,236 @@ +import { Utils } from "jslib-common/misc/utils"; + +import { SafariApp } from "./safariApp"; + +export class BrowserApi { + static isWebExtensionsApi: boolean = typeof browser !== "undefined"; + static isSafariApi: boolean = + navigator.userAgent.indexOf(" Safari/") !== -1 && + navigator.userAgent.indexOf(" Chrome/") === -1 && + navigator.userAgent.indexOf(" Chromium/") === -1; + static isChromeApi: boolean = !BrowserApi.isSafariApi && typeof chrome !== "undefined"; + static isFirefoxOnAndroid: boolean = + navigator.userAgent.indexOf("Firefox/") !== -1 && navigator.userAgent.indexOf("Android") !== -1; + + static async getTabFromCurrentWindowId(): Promise | null { + return await BrowserApi.tabsQueryFirst({ + active: true, + windowId: chrome.windows.WINDOW_ID_CURRENT, + }); + } + + static async getTabFromCurrentWindow(): Promise | null { + return await BrowserApi.tabsQueryFirst({ + active: true, + currentWindow: true, + }); + } + + static async getActiveTabs(): Promise { + return await BrowserApi.tabsQuery({ + active: true, + }); + } + + static async tabsQuery(options: chrome.tabs.QueryInfo): Promise { + return new Promise((resolve) => { + chrome.tabs.query(options, (tabs: any[]) => { + resolve(tabs); + }); + }); + } + + static async tabsQueryFirst(options: chrome.tabs.QueryInfo): Promise | null { + const tabs = await BrowserApi.tabsQuery(options); + if (tabs.length > 0) { + return tabs[0]; + } + + return null; + } + + static tabSendMessageData( + tab: chrome.tabs.Tab, + command: string, + data: any = null + ): Promise { + const obj: any = { + command: command, + }; + + if (data != null) { + obj.data = data; + } + + return BrowserApi.tabSendMessage(tab, obj); + } + + static async tabSendMessage( + tab: chrome.tabs.Tab, + obj: any, + options: chrome.tabs.MessageSendOptions = null + ): Promise { + if (!tab || !tab.id) { + return; + } + + return new Promise((resolve) => { + chrome.tabs.sendMessage(tab.id, obj, options, () => { + if (chrome.runtime.lastError) { + // Some error happened + } + resolve(); + }); + }); + } + + static async getPrivateModeWindows(): Promise { + return (await browser.windows.getAll()).filter((win) => win.incognito); + } + + static async onWindowCreated(callback: (win: chrome.windows.Window) => any) { + return chrome.windows.onCreated.addListener(callback); + } + + static getBackgroundPage(): any { + return chrome.extension.getBackgroundPage(); + } + + static getApplicationVersion(): string { + return chrome.runtime.getManifest().version; + } + + static async isPopupOpen(): Promise { + return Promise.resolve(chrome.extension.getViews({ type: "popup" }).length > 0); + } + + static createNewTab(url: string, extensionPage = false, active = true) { + chrome.tabs.create({ url: url, active: active }); + } + + static messageListener( + name: string, + callback: (message: any, sender: chrome.runtime.MessageSender, response: any) => void + ) { + chrome.runtime.onMessage.addListener( + (msg: any, sender: chrome.runtime.MessageSender, response: any) => { + callback(msg, sender, response); + } + ); + } + + static async closeLoginTab() { + const tabs = await BrowserApi.tabsQuery({ + active: true, + title: "Bitwarden", + windowType: "normal", + currentWindow: true, + }); + + if (tabs.length === 0) { + return; + } + + const tabToClose = tabs[tabs.length - 1].id; + chrome.tabs.remove(tabToClose); + } + + static async focusSpecifiedTab(tabId: number) { + chrome.tabs.update(tabId, { active: true, highlighted: true }); + } + + static closePopup(win: Window) { + if (BrowserApi.isWebExtensionsApi && BrowserApi.isFirefoxOnAndroid) { + // Reactivating the active tab dismisses the popup tab. The promise final + // condition is only called if the popup wasn't already dismissed (future proofing). + // ref: https://bugzilla.mozilla.org/show_bug.cgi?id=1433604 + browser.tabs.update({ active: true }).finally(win.close); + } else { + win.close(); + } + } + + static downloadFile(win: Window, blobData: any, blobOptions: any, fileName: string) { + if (BrowserApi.isSafariApi) { + const type = blobOptions != null ? blobOptions.type : null; + let data: string = null; + if (type === "text/plain" && typeof blobData === "string") { + data = blobData; + } else { + data = Utils.fromBufferToB64(blobData); + } + SafariApp.sendMessageToApp( + "downloadFile", + JSON.stringify({ + blobData: data, + blobOptions: blobOptions, + fileName: fileName, + }), + true + ); + } else { + const blob = new Blob([blobData], blobOptions); + if (navigator.msSaveOrOpenBlob) { + navigator.msSaveBlob(blob, fileName); + } else { + const a = win.document.createElement("a"); + a.href = URL.createObjectURL(blob); + a.download = fileName; + win.document.body.appendChild(a); + a.click(); + win.document.body.removeChild(a); + } + } + } + + static gaFilter() { + return process.env.ENV !== "production"; + } + + static getUILanguage(win: Window) { + return chrome.i18n.getUILanguage(); + } + + static reloadExtension(win: Window) { + if (win != null) { + return win.location.reload(true); + } else { + return chrome.runtime.reload(); + } + } + + static reloadOpenWindows() { + const views = chrome.extension.getViews() as Window[]; + views + .filter((w) => w.location.href != null) + .forEach((w) => { + w.location.reload(); + }); + } + + static connectNative(application: string): browser.runtime.Port | chrome.runtime.Port { + if (BrowserApi.isWebExtensionsApi) { + return browser.runtime.connectNative(application); + } else if (BrowserApi.isChromeApi) { + return chrome.runtime.connectNative(application); + } + } + + static requestPermission(permission: any) { + if (BrowserApi.isWebExtensionsApi) { + return browser.permissions.request(permission); + } + return new Promise((resolve, reject) => { + chrome.permissions.request(permission, resolve); + }); + } + + static getPlatformInfo(): Promise { + if (BrowserApi.isWebExtensionsApi) { + return browser.runtime.getPlatformInfo(); + } + return new Promise((resolve) => { + chrome.runtime.getPlatformInfo(resolve); + }); + } +} diff --git a/apps/browser/src/browser/safariApp.ts b/apps/browser/src/browser/safariApp.ts new file mode 100644 index 0000000000..7a86295df6 --- /dev/null +++ b/apps/browser/src/browser/safariApp.ts @@ -0,0 +1,26 @@ +import { BrowserApi } from "./browserApi"; + +export class SafariApp { + static sendMessageToApp(command: string, data: any = null, resolveNow = false): Promise { + if (!BrowserApi.isSafariApi) { + return Promise.resolve(null); + } + return new Promise((resolve) => { + const now = new Date(); + const messageId = + now.getTime().toString() + "_" + Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); + (browser as any).runtime.sendNativeMessage( + "com.bitwarden.desktop", + { + id: messageId, + command: command, + data: data, + responseData: null, + }, + (response: any) => { + resolve(response); + } + ); + }); + } +} diff --git a/apps/browser/src/content/autofill.css b/apps/browser/src/content/autofill.css new file mode 100644 index 0000000000..e495cbf5c4 --- /dev/null +++ b/apps/browser/src/content/autofill.css @@ -0,0 +1,36 @@ +@-webkit-keyframes bitwardenfill { + 0% { + -webkit-transform: scale(1, 1); + } + + 50% { + -webkit-transform: scale(1.2, 1.2); + } + + 100% { + -webkit-transform: scale(1, 1); + } +} + +@-moz-keyframes bitwardenfill { + 0% { + transform: scale(1, 1); + } + + 50% { + transform: scale(1.2, 1.2); + } + + 100% { + transform: scale(1, 1); + } +} + +span[data-bwautofill].com-bitwarden-browser-animated-fill { + display: inline-block; +} + +.com-bitwarden-browser-animated-fill { + animation: bitwardenfill 200ms ease-in-out 0ms 1; + -webkit-animation: bitwardenfill 200ms ease-in-out 0ms 1; +} diff --git a/apps/browser/src/content/autofill.js b/apps/browser/src/content/autofill.js new file mode 100644 index 0000000000..7b285d4cf4 --- /dev/null +++ b/apps/browser/src/content/autofill.js @@ -0,0 +1,1042 @@ +!(function () { + /* + 1Password Extension + + Lovingly handcrafted by Dave Teare, Michael Fey, Rad Azzouz, and Roustem Karimov. + Copyright (c) 2014 AgileBits. All rights reserved. + + ================================================================================ + + Copyright (c) 2014 AgileBits Inc. + + 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. + */ + + /* + MODIFICATIONS FROM ORIGINAL + + 1. Populate isFirefox + 2. Remove isChrome and isSafari since they are not used. + 3. Unminify and format to meet Mozilla review requirements. + 4. Remove unnecessary input types from getFormElements query selector and limit number of elements returned. + 5. Remove fakeTested prop. + 6. Rename com.agilebits.* stuff to com.bitwarden.* + 7. Remove "some useful globals" on window + 8. Add ability to autofill span[data-bwautofill] elements + */ + + function collect(document, undefined) { + // START MODIFICATION + var isFirefox = navigator.userAgent.indexOf('Firefox') !== -1 || navigator.userAgent.indexOf('Gecko/') !== -1; + // END MODIFICATION + + document.elementsByOPID = {}; + document.addEventListener('input', function (inputevent) { + inputevent.a !== false && + inputevent.target.tagName.toLowerCase() === 'input' && + (inputevent.target.dataset['com.bitwarden.browser.userEdited'] = 'yes'); + }, true); + + function getPageDetails(theDoc, oneShotId) { + // start helpers + + // get the value of a dom element's attribute + function getElementAttrValue(el, attrName) { + var attrVal = el[attrName]; + if ('string' == typeof attrVal) { + return attrVal; + } + attrVal = el.getAttribute(attrName); + return 'string' == typeof attrVal ? attrVal : null; + } + + // has the element been fake tested? + function checkIfFakeTested(field, el) { + if (-1 === ['text', 'password'].indexOf(el.type.toLowerCase()) || + !(passwordRegEx.test(field.value) || + passwordRegEx.test(field.htmlID) || passwordRegEx.test(field.htmlName) || + passwordRegEx.test(field.placeholder) || passwordRegEx.test(field['label-tag']) || + passwordRegEx.test(field['label-data']) || passwordRegEx.test(field['label-aria']))) { + return false; + } + + if (!field.visible) { + return true; + } + + if ('password' == el.type.toLowerCase()) { + return false; + } + + var elType = el.type; + focusElement(el, true); + return elType !== el.type; + } + + // get the value of a dom element + function getElementValue(el) { + switch (toLowerString(el.type)) { + case 'checkbox': + return el.checked ? '✓' : ''; + + case 'hidden': + el = el.value; + if (!el || 'number' != typeof el.length) { + return ''; + } + 254 < el.length && (el = el.substr(0, 254) + '...SNIPPED'); + return el; + + default: + // START MODIFICATION + if (!el.type && el.tagName.toLowerCase() === 'span') { + return el.innerText; + } + // END MODIFICATION + return el.value; + } + } + + // get all the options for a "select" element + function getSelectElementOptions(el) { + if (!el.options) { + return null; + } + + var options = Array.prototype.slice.call(el.options).map(function (option) { + var optionText = option.text ? + toLowerString(option.text).replace(/\\s/gm, '').replace(/[~`!@$%^&*()\\-_+=:;'\"\\[\\]|\\\\,<.>\\?]/gm, '') : + null; + + return [optionText ? optionText : null, option.value]; + }) + + return { + options: options + }; + } + + // get the top label + function getLabelTop(el) { + var parent; + for (el = el.parentElement || el.parentNode; el && 'td' != toLowerString(el.tagName);) { + el = el.parentElement || el.parentNode; + } + + if (!el || void 0 === el) { + return null; + } + + parent = el.parentElement || el.parentNode; + if ('tr' != parent.tagName.toLowerCase()) { + return null; + } + + parent = parent.previousElementSibling; + if (!parent || 'tr' != (parent.tagName + '').toLowerCase() || + parent.cells && el.cellIndex >= parent.cells.length) { + return null; + } + + el = parent.cells[el.cellIndex]; + var elText = el.textContent || el.innerText; + return elText = cleanText(elText); + } + + // get all the tags for a given label + function getLabelTag(el) { + var docLabel, + theLabels = []; + + if (el.labels && el.labels.length && 0 < el.labels.length) { + theLabels = Array.prototype.slice.call(el.labels); + } else { + if (el.id) { + theLabels = theLabels.concat(Array.prototype.slice.call( + queryDoc(theDoc, 'label[for=' + JSON.stringify(el.id) + ']'))); + } + + if (el.name) { + docLabel = queryDoc(theDoc, 'label[for=' + JSON.stringify(el.name) + ']'); + + for (var labelIndex = 0; labelIndex < docLabel.length; labelIndex++) { + if (-1 === theLabels.indexOf(docLabel[labelIndex])) { + theLabels.push(docLabel[labelIndex]) + } + } + } + + for (var theEl = el; theEl && theEl != theDoc; theEl = theEl.parentNode) { + if ('label' === toLowerString(theEl.tagName) && -1 === theLabels.indexOf(theEl)) { + theLabels.push(theEl); + } + } + } + + if (0 === theLabels.length) { + theEl = el.parentNode; + if ('dd' === theEl.tagName.toLowerCase() && null !== theEl.previousElementSibling + && 'dt' === theEl.previousElementSibling.tagName.toLowerCase()) { + theLabels.push(theEl.previousElementSibling); + } + } + + if (0 > theLabels.length) { + return null; + } + + return theLabels.map(function (l) { + return (l.textContent || l.innerText) + .replace(/^\\s+/, '').replace(/\\s+$/, '').replace('\\n', '').replace(/\\s{2,}/, ' '); + }).join(''); + } + + // add property and value to the object if there is a value + function addProp(obj, prop, val, d) { + if (0 !== d && d === val || null === val || void 0 === val) { + return; + } + + obj[prop] = val; + } + + // lowercase helper + function toLowerString(s) { + return 'string' === typeof s ? s.toLowerCase() : ('' + s).toLowerCase(); + } + + // query the document helper + function queryDoc(doc, query) { + var els = []; + try { + els = doc.querySelectorAll(query); + } catch (e) { } + return els; + } + + // end helpers + + var theView = theDoc.defaultView ? theDoc.defaultView : window, + passwordRegEx = RegExp('((\\\\b|_|-)pin(\\\\b|_|-)|password|passwort|kennwort|(\\\\b|_|-)passe(\\\\b|_|-)|contraseña|senha|密码|adgangskode|hasło|wachtwoord)', 'i'); + + // get all the docs + var theForms = Array.prototype.slice.call(queryDoc(theDoc, 'form')).map(function (formEl, elIndex) { + var op = {}, + formOpId = '__form__' + elIndex; + + formEl.opid = formOpId; + op.opid = formOpId; + addProp(op, 'htmlName', getElementAttrValue(formEl, 'name')); + addProp(op, 'htmlID', getElementAttrValue(formEl, 'id')); + formOpId = getElementAttrValue(formEl, 'action'); + formOpId = new URL(formOpId, window.location.href); + addProp(op, 'htmlAction', formOpId ? formOpId.href : null); + addProp(op, 'htmlMethod', getElementAttrValue(formEl, 'method')); + + return op; + }); + + // get all the form fields + var theFields = Array.prototype.slice.call(getFormElements(theDoc, 50)).map(function (el, elIndex) { + var field = {}, + opId = '__' + elIndex, + elMaxLen = -1 == el.maxLength ? 999 : el.maxLength; + + if (!elMaxLen || 'number' === typeof elMaxLen && isNaN(elMaxLen)) { + elMaxLen = 999; + } + + theDoc.elementsByOPID[opId] = el; + el.opid = opId; + field.opid = opId; + field.elementNumber = elIndex; + addProp(field, 'maxLength', Math.min(elMaxLen, 999), 999); + field.visible = isElementVisible(el); + field.viewable = isElementViewable(el); + addProp(field, 'htmlID', getElementAttrValue(el, 'id')); + addProp(field, 'htmlName', getElementAttrValue(el, 'name')); + addProp(field, 'htmlClass', getElementAttrValue(el, 'class')); + addProp(field, 'tabindex', getElementAttrValue(el, 'tabindex')); + addProp(field, 'title', getElementAttrValue(el, 'title')); + + // START MODIFICATION + addProp(field, 'userEdited', !!el.dataset['com.browser.browser.userEdited']); + + var elTagName = el.tagName.toLowerCase(); + addProp(field, 'tagName', elTagName); + + if (elTagName === 'span') { + return field; + } + // END MODIFICATION + + if ('hidden' != toLowerString(el.type)) { + addProp(field, 'label-tag', getLabelTag(el)); + addProp(field, 'label-data', getElementAttrValue(el, 'data-label')); + addProp(field, 'label-aria', getElementAttrValue(el, 'aria-label')); + addProp(field, 'label-top', getLabelTop(el)); + var labelArr = []; + for (var sib = el; sib && sib.nextSibling;) { + sib = sib.nextSibling; + if (isKnownTag(sib)) { + break; + } + checkNodeType(labelArr, sib); + } + addProp(field, 'label-right', labelArr.join('')); + labelArr = []; + shiftForLeftLabel(el, labelArr); + labelArr = labelArr.reverse().join(''); + addProp(field, 'label-left', labelArr); + addProp(field, 'placeholder', getElementAttrValue(el, 'placeholder')); + } + + addProp(field, 'rel', getElementAttrValue(el, 'rel')); + addProp(field, 'type', toLowerString(getElementAttrValue(el, 'type'))); + addProp(field, 'value', getElementValue(el)); + addProp(field, 'checked', el.checked, false); + addProp(field, 'autoCompleteType', el.getAttribute('x-autocompletetype') || el.getAttribute('autocompletetype') || el.getAttribute('autocomplete'), 'off'); + addProp(field, 'disabled', el.disabled); + addProp(field, 'readonly', el.b || el.readOnly); + addProp(field, 'selectInfo', getSelectElementOptions(el)); + addProp(field, 'aria-hidden', 'true' == el.getAttribute('aria-hidden'), false); + addProp(field, 'aria-disabled', 'true' == el.getAttribute('aria-disabled'), false); + addProp(field, 'aria-haspopup', 'true' == el.getAttribute('aria-haspopup'), false); + addProp(field, 'data-unmasked', el.dataset.unmasked); + addProp(field, 'data-stripe', getElementAttrValue(el, 'data-stripe')); + addProp(field, 'onepasswordFieldType', el.dataset.onepasswordFieldType || el.type); + addProp(field, 'onepasswordDesignation', el.dataset.onepasswordDesignation); + addProp(field, 'onepasswordSignInUrl', el.dataset.onepasswordSignInUrl); + addProp(field, 'onepasswordSectionTitle', el.dataset.onepasswordSectionTitle); + addProp(field, 'onepasswordSectionFieldKind', el.dataset.onepasswordSectionFieldKind); + addProp(field, 'onepasswordSectionFieldTitle', el.dataset.onepasswordSectionFieldTitle); + addProp(field, 'onepasswordSectionFieldValue', el.dataset.onepasswordSectionFieldValue); + + if (el.form) { + field.form = getElementAttrValue(el.form, 'opid'); + } + + // START MODIFICATION + //addProp(field, 'fakeTested', checkIfFakeTested(field, el), false); + // END MODIFICATION + + return field; + }); + + // test form fields + theFields.filter(function (f) { + return f.fakeTested; + }).forEach(function (f) { + var el = theDoc.elementsByOPID[f.opid]; + el.getBoundingClientRect(); + + var originalValue = el.value; + // click it + !el || el && 'function' !== typeof el.click || el.click(); + focusElement(el, false); + + el.dispatchEvent(doEventOnElement(el, 'keydown')); + el.dispatchEvent(doEventOnElement(el, 'keypress')); + el.dispatchEvent(doEventOnElement(el, 'keyup')); + + el.value !== originalValue && (el.value = originalValue); + + el.click && el.click(); + f.postFakeTestVisible = isElementVisible(el); + f.postFakeTestViewable = isElementViewable(el); + f.postFakeTestType = el.type; + + var elValue = el.value; + + var event1 = el.ownerDocument.createEvent('HTMLEvents'), + event2 = el.ownerDocument.createEvent('HTMLEvents'); + el.dispatchEvent(doEventOnElement(el, 'keydown')); + el.dispatchEvent(doEventOnElement(el, 'keypress')); + el.dispatchEvent(doEventOnElement(el, 'keyup')); + event2.initEvent('input', true, true); + el.dispatchEvent(event2); + event1.initEvent('change', true, true); + el.dispatchEvent(event1); + + el.blur(); + el.value !== elValue && (el.value = elValue); + }); + + // build out the page details object. this is the final result + var pageDetails = { + documentUUID: oneShotId, + title: theDoc.title, + url: theView.location.href, + documentUrl: theDoc.location.href, + tabUrl: theView.location.href, + forms: function (forms) { + var formObj = {}; + forms.forEach(function (f) { + formObj[f.opid] = f; + }); + return formObj; + }(theForms), + fields: theFields, + collectedTimestamp: new Date().getTime() + }; + + // get proper page title. maybe they are using the special meta tag? + var theTitle = document.querySelector('[data-onepassword-title]') + if (theTitle && theTitle.dataset[DISPLAY_TITLE_ATTRIBUE]) { + pageDetails.displayTitle = theTitle.dataset.onepasswordTitle; + } + + return pageDetails; + } + + document.elementForOPID = getElementForOPID; + + function doEventOnElement(kedol, fonor) { + var quebo; + isFirefox ? (quebo = document.createEvent('KeyboardEvent'), quebo.initKeyEvent(fonor, true, false, null, false, false, false, false, 0, 0)) : (quebo = kedol.ownerDocument.createEvent('Events'), + quebo.initEvent(fonor, true, false), quebo.charCode = 0, quebo.keyCode = 0, quebo.which = 0, + quebo.srcElement = kedol, quebo.target = kedol); + return quebo; + } + + // clean up the text + function cleanText(s) { + var sVal = null; + s && (sVal = s.replace(/^\\s+|\\s+$|\\r?\\n.*$/gm, ''), sVal = 0 < sVal.length ? sVal : null); + return sVal; + } + + // check the node type and adjust the array accordingly + function checkNodeType(arr, el) { + var theText = ''; + 3 === el.nodeType ? theText = el.nodeValue : 1 === el.nodeType && (theText = el.textContent || el.innerText); + (theText = cleanText(theText)) && arr.push(theText); + } + + function isKnownTag(el) { + if (el && void 0 !== el) { + var tags = 'select option input form textarea button table iframe body head script'.split(' '); + + if (el) { + var elTag = el ? (el.tagName || '').toLowerCase() : ''; + return tags.constructor == Array ? 0 <= tags.indexOf(elTag) : elTag === tags; + } + else { + return false; + } + } + else { + return true; + } + } + + function shiftForLeftLabel(el, arr, steps) { + var sib; + for (steps || (steps = 0); el && el.previousSibling;) { + el = el.previousSibling; + if (isKnownTag(el)) { + return; + } + + checkNodeType(arr, el); + } + if (el && 0 === arr.length) { + for (sib = null; !sib;) { + el = el.parentElement || el.parentNode; + if (!el) { + return; + } + for (sib = el.previousSibling; sib && !isKnownTag(sib) && sib.lastChild;) { + sib = sib.lastChild; + } + } + + // base case and recurse + isKnownTag(sib) || (checkNodeType(arr, sib), 0 === arr.length && shiftForLeftLabel(sib, arr, steps + 1)); + } + } + + // is a dom element visible on screen? + function isElementVisible(el) { + var theEl = el; + el = (el = el.ownerDocument) ? el.defaultView : {}; + + // walk the dom tree + for (var elStyle; theEl && theEl !== document;) { + elStyle = el.getComputedStyle ? el.getComputedStyle(theEl, null) : theEl.style; + if (!elStyle) { + return true; + } + + if ('none' === elStyle.display || 'hidden' == elStyle.visibility) { + return false; + } + + // walk up + theEl = theEl.parentNode; + } + + return theEl === document; + } + + // is a dom element "viewable" on screen? + function isElementViewable(el) { + var theDoc = el.ownerDocument.documentElement, + rect = el.getBoundingClientRect(), + docScrollWidth = theDoc.scrollWidth, + docScrollHeight = theDoc.scrollHeight, + leftOffset = rect.left - theDoc.clientLeft, + topOffset = rect.top - theDoc.clientTop, + theRect; + + if (!isElementVisible(el) || !el.offsetParent || 10 > el.clientWidth || 10 > el.clientHeight) { + return false; + } + + var rects = el.getClientRects(); + if (0 === rects.length) { + return false; + } + + for (var i = 0; i < rects.length; i++) { + if (theRect = rects[i], theRect.left > docScrollWidth || 0 > theRect.right) { + return false; + } + } + + if (0 > leftOffset || leftOffset > docScrollWidth || 0 > topOffset || topOffset > docScrollHeight) { + return false; + } + + // walk the tree + for (var pointEl = el.ownerDocument.elementFromPoint(leftOffset + (rect.right > window.innerWidth ? (window.innerWidth - leftOffset) / 2 : rect.width / 2), topOffset + (rect.bottom > window.innerHeight ? (window.innerHeight - topOffset) / 2 : rect.height / 2)); pointEl && pointEl !== el && pointEl !== document;) { + if (pointEl.tagName && 'string' === typeof pointEl.tagName && 'label' === pointEl.tagName.toLowerCase() + && el.labels && 0 < el.labels.length) { + return 0 <= Array.prototype.slice.call(el.labels).indexOf(pointEl); + } + + // walk up + pointEl = pointEl.parentNode; + } + + return pointEl === el; + } + + function getElementForOPID(opId) { + var theEl; + if (void 0 === opId || null === opId) { + return null; + } + + try { + var formEls = Array.prototype.slice.call(getFormElements(document)); + var filteredFormEls = formEls.filter(function (el) { + return el.opid == opId; + }); + + if (0 < filteredFormEls.length) { + theEl = filteredFormEls[0], 1 < filteredFormEls.length && console.warn('More than one element found with opid ' + opId); + } else { + var theIndex = parseInt(opId.split('__')[1], 10); + isNaN(theIndex) || (theEl = formEls[theIndex]); + } + } catch (e) { + console.error('An unexpected error occurred: ' + e); + } finally { + return theEl; + } + } + + // get all the form elements that we care about + function getFormElements(theDoc, limit) { + // START MODIFICATION + var els = []; + try { + var elsList = theDoc.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="reset"])' + + ':not([type="button"]):not([type="image"]):not([type="file"]):not([data-bwignore]), select, ' + + 'span[data-bwautofill]'); + els = Array.prototype.slice.call(elsList); + } catch (e) { } + + if (!limit || els.length <= limit) { + return els; + } + + // non-checkboxes/radios have higher priority + var returnEls = []; + var unimportantEls = []; + for (var i = 0; i < els.length; i++) { + if (returnEls.length >= limit) { + break; + } + + var el = els[i]; + var type = el.type ? el.type.toLowerCase() : el.type; + if (type === 'checkbox' || type === 'radio') { + unimportantEls.push(el); + } + else { + returnEls.push(el); + } + } + + var unimportantElsToAdd = limit - returnEls.length; + if (unimportantElsToAdd > 0) { + returnEls = returnEls.concat(unimportantEls.slice(0, unimportantElsToAdd)); + } + + return returnEls; + // END MODIFICATION + } + + // focus the element and optionally restore its original value + function focusElement(el, setVal) { + if (setVal) { + var initialValue = el.value; + el.focus(); + + if (el.value !== initialValue) { + el.value = initialValue; + } + } else { + el.focus(); + } + } + + return JSON.stringify(getPageDetails(document, 'oneshotUUID')); + } + + function fill(document, fillScript, undefined) { + var isFirefox = navigator.userAgent.indexOf('Firefox') !== -1 || navigator.userAgent.indexOf('Gecko/') !== -1; + + var markTheFilling = true, + animateTheFilling = true; + + // Check if URL is not secure when the original saved one was + function urlNotSecure(savedURL) { + var passwordInputs = null; + if (!savedURL) { + return false; + } + + return 0 === savedURL.indexOf('https://') && 'http:' === document.location.protocol && (passwordInputs = document.querySelectorAll('input[type=password]'), + 0 < passwordInputs.length && (confirmResult = confirm('Warning: This is an unsecured HTTP page, and any information you submit can potentially be seen and changed by others. This Login was originally saved on a secure (HTTPS) page.\\n\\nDo you still wish to fill this login?'), + 0 == confirmResult)) ? true : false; + } + + function doFill(fillScript) { + var fillScriptOps, + theOpIds = [], + fillScriptProperties = fillScript.properties, + operationDelayMs = 1, + doOperation, + operationsToDo = []; + + fillScriptProperties && + fillScriptProperties.delay_between_operations && + (operationDelayMs = fillScriptProperties.delay_between_operations); + + if (urlNotSecure(fillScript.savedURL)) { + return; + } + + doOperation = function (ops, theOperation) { + var op = ops[0]; + if (void 0 === op) { + theOperation(); + } else { + // should we delay? + if ('delay' === op.operation || 'delay' === op[0]) { + operationDelayMs = op.parameters ? op.parameters[0] : op[1]; + } else { + if (op = normalizeOp(op)) { + for (var opIndex = 0; opIndex < op.length; opIndex++) { + -1 === operationsToDo.indexOf(op[opIndex]) && operationsToDo.push(op[opIndex]); + } + } + theOpIds = theOpIds.concat(operationsToDo.map(function (operationToDo) { + return operationToDo && operationToDo.hasOwnProperty('opid') ? operationToDo.opid : null; + })); + } + setTimeout(function () { + doOperation(ops.slice(1), theOperation); + }, operationDelayMs); + } + }; + + if (fillScriptOps = fillScript.options) { + fillScriptOps.hasOwnProperty('animate') && (animateTheFilling = fillScriptOps.animate), + fillScriptOps.hasOwnProperty('markFilling') && (markTheFilling = fillScriptOps.markFilling); + } + + // don't mark a password filling + fillScript.itemType && 'fillPassword' === fillScript.itemType && (markTheFilling = false); + + if (!fillScript.hasOwnProperty('script')) { + return; + } + + // custom fill script + + fillScriptOps = fillScript.script; + doOperation(fillScriptOps, function () { + // Done now + // Do we have anything to autosubmit? + if (fillScript.hasOwnProperty('autosubmit') && 'function' == typeof autosubmit) { + fillScript.itemType && 'fillLogin' !== fillScript.itemType || (0 < operationsToDo.length ? setTimeout(function () { + autosubmit(fillScript.autosubmit, fillScriptProperties.allow_clicky_autosubmit, operationsToDo); + }, AUTOSUBMIT_DELAY) : DEBUG_AUTOSUBMIT && console.log('[AUTOSUBMIT] Not attempting to submit since no fields were filled: ', operationsToDo)) + } + + // handle protectedGlobalPage + if ('object' == typeof protectedGlobalPage) { + protectedGlobalPage.b('fillItemResults', { + documentUUID: documentUUID, + fillContextIdentifier: fillScript.fillContextIdentifier, + usedOpids: theOpIds + }, function () { + fillingItemType = null; + }) + } + }); + } + + // fill for reference + var thisFill = { + fill_by_opid: doFillByOpId, + fill_by_query: doFillByQuery, + click_on_opid: doClickByOpId, + click_on_query: doClickByQuery, + touch_all_fields: touchAllFields, + simple_set_value_by_query: doSimpleSetByQuery, + focus_by_opid: doFocusByOpId, + delay: null + }; + + // normalize the op versus the reference + function normalizeOp(op) { + var thisOperation; + if (op.hasOwnProperty('operation') && op.hasOwnProperty('parameters')) { + thisOperation = op.operation, op = op.parameters; + } else { + if ('[object Array]' === Object.prototype.toString.call(op)) { + thisOperation = op[0], + op = op.splice(1); + } else { + return null; + } + } + return thisFill.hasOwnProperty(thisOperation) ? thisFill[thisOperation].apply(this, op) : null; + } + + // do a fill by opid operation + function doFillByOpId(opId, op) { + var el = getElementByOpId(opId); + return el ? (fillTheElement(el, op), [el]) : null; + } + + // do a fill by query operation + function doFillByQuery(query, op) { + var elements = selectAllFromDoc(query); + return Array.prototype.map.call(Array.prototype.slice.call(elements), function (el) { + fillTheElement(el, op); + return el; + }, this); + } + + // do a simple set value by query + function doSimpleSetByQuery(query, valueToSet) { + var elements = selectAllFromDoc(query), + arr = []; + Array.prototype.forEach.call(Array.prototype.slice.call(elements), function (el) { + el.disabled || el.a || el.readOnly || void 0 === el.value || (el.value = valueToSet, arr.push(el)); + }); + return arr; + } + + // focus by opid + function doFocusByOpId(opId) { + var el = getElementByOpId(opId) + if (el) { + 'function' === typeof el.click && el.click(), + 'function' === typeof el.focus && doFocusElement(el, true); + } + + return null; + } + + // do a click by opid operation + function doClickByOpId(opId) { + var el = getElementByOpId(opId); + return el ? clickElement(el) ? [el] : null : null; + } + + // do a click by query operation + function doClickByQuery(query) { + query = selectAllFromDoc(query); + return Array.prototype.map.call(Array.prototype.slice.call(query), function (el) { + clickElement(el); + 'function' === typeof el.click && el.click(); + 'function' === typeof el.focus && doFocusElement(el, true); + return [el]; + }, this); + } + + var checkRadioTrueOps = { + 'true': true, + y: true, + 1: true, + yes: true, + '✓': true + }, + styleTimeout = 200; + + // fill an element + function fillTheElement(el, op) { + var shouldCheck; + if (el && null !== op && void 0 !== op && !(el.disabled || el.a || el.readOnly)) { + switch (markTheFilling && el.form && !el.form.opfilled && (el.form.opfilled = true), + el.type ? el.type.toLowerCase() : null) { + case 'checkbox': + shouldCheck = op && 1 <= op.length && checkRadioTrueOps.hasOwnProperty(op.toLowerCase()) && true === checkRadioTrueOps[op.toLowerCase()]; + el.checked === shouldCheck || doAllFillOperations(el, function (theEl) { + theEl.checked = shouldCheck; + }); + break; + case 'radio': + true === checkRadioTrueOps[op.toLowerCase()] && el.click(); + break; + default: + el.value == op || doAllFillOperations(el, function (theEl) { + // START MODIFICATION + if (!theEl.type && theEl.tagName.toLowerCase() === 'span') { + theEl.innerText = op; + return; + } + // END MODIFICATION + theEl.value = op; + }); + } + } + } + + // do all the full operations needed + function doAllFillOperations(el, afterValSetFunc) { + setValueForElement(el); + afterValSetFunc(el); + setValueForElementByEvent(el); + + // START MODIFICATION + if (canSeeElementToStyle(el)) { + el.classList.add('com-bitwarden-browser-animated-fill'); + setTimeout(function () { + if (el) { + el.classList.remove('com-bitwarden-browser-animated-fill'); + } + }, styleTimeout); + } + // END MODIFICATION + } + + document.elementForOPID = getElementByOpId; + + // normalize the event based on API support + function normalizeEvent(el, eventName) { + var ev; + if ('KeyboardEvent' in window) { + ev = new window.KeyboardEvent(eventName, { + bubbles: true, + cancelable: false, + }); + } + else { + ev = el.ownerDocument.createEvent('Events'); + ev.initEvent(eventName, true, false); + ev.charCode = 0; + ev.keyCode = 0; + ev.which = 0; + ev.srcElement = el; + ev.target = el; + } + + return ev; + } + + // set value of the given element + function setValueForElement(el) { + var valueToSet = el.value; + clickElement(el); + doFocusElement(el, false); + el.dispatchEvent(normalizeEvent(el, 'keydown')); + el.dispatchEvent(normalizeEvent(el, 'keypress')); + el.dispatchEvent(normalizeEvent(el, 'keyup')); + el.value !== valueToSet && (el.value = valueToSet); + } + + // set value of the given element by using events + function setValueForElementByEvent(el) { + var valueToSet = el.value, + ev1 = el.ownerDocument.createEvent('HTMLEvents'), + ev2 = el.ownerDocument.createEvent('HTMLEvents'); + + el.dispatchEvent(normalizeEvent(el, 'keydown')); + el.dispatchEvent(normalizeEvent(el, 'keypress')); + el.dispatchEvent(normalizeEvent(el, 'keyup')); + ev2.initEvent('input', true, true); + el.dispatchEvent(ev2); + ev1.initEvent('change', true, true); + el.dispatchEvent(ev1); + el.blur(); + el.value !== valueToSet && (el.value = valueToSet); + } + + // click on an element + function clickElement(el) { + if (!el || el && 'function' !== typeof el.click) { + return false; + } + el.click(); + return true; + } + + // get all fields we care about + function getAllFields() { + var r = RegExp('((\\\\b|_|-)pin(\\\\b|_|-)|password|passwort|kennwort|passe|contraseña|senha|密码|adgangskode|hasło|wachtwoord)', 'i'); + return Array.prototype.slice.call(selectAllFromDoc("input[type='text']")).filter(function (el) { + return el.value && r.test(el.value); + }, this); + } + + // touch all the fields + function touchAllFields() { + getAllFields().forEach(function (el) { + setValueForElement(el); + el.click && el.click(); + setValueForElementByEvent(el); + }); + } + + // can we see the element to apply some styling? + function canSeeElementToStyle(el) { + var currentEl; + if (currentEl = animateTheFilling) { + a: { + currentEl = el; + for (var owner = el.ownerDocument, owner = owner ? owner.defaultView : {}, theStyle; currentEl && currentEl !== document;) { + theStyle = owner.getComputedStyle ? owner.getComputedStyle(currentEl, null) : currentEl.style; + if (!theStyle) { + currentEl = true; + break a; + } + if ('none' === theStyle.display || 'hidden' == theStyle.visibility) { + currentEl = false; + break a; + } + currentEl = currentEl.parentNode; + } + currentEl = currentEl === document; + } + } + // START MODIFICATION + if (el && !el.type && el.tagName.toLowerCase() === 'span') { + return true; + } + // END MODIFICATION + return currentEl ? -1 !== 'email text password number tel url'.split(' ').indexOf(el.type || '') : false; + } + + // find the element for this operation + function getElementByOpId(theOpId) { + var theElement; + if (void 0 === theOpId || null === theOpId) { + return null; + } + try { + // START MODIFICATION + var elements = Array.prototype.slice.call(selectAllFromDoc('input, select, button, ' + + 'span[data-bwautofill]')); + // END MODIFICATION + var filteredElements = elements.filter(function (o) { + return o.opid == theOpId; + }); + if (0 < filteredElements.length) { + theElement = filteredElements[0], + 1 < filteredElements.length && console.warn('More than one element found with opid ' + theOpId); + } else { + var elIndex = parseInt(theOpId.split('__')[1], 10); + isNaN(elIndex) || (theElement = elements[elIndex]); + } + } catch (e) { + console.error('An unexpected error occurred: ' + e); + } finally { + return theElement; + } + } + + // helper for doc.querySelectorAll + function selectAllFromDoc(theSelector) { + var d = document, elements = []; + try { + elements = d.querySelectorAll(theSelector); + } catch (e) { } + return elements; + } + + // focus an element and optionally re-set its value after focusing + function doFocusElement(el, setValue) { + if (setValue) { + var existingValue = el.value; + el.focus(); + el.value !== existingValue && (el.value = existingValue); + } else { + el.focus(); + } + } + + doFill(fillScript); + + return JSON.stringify({ + success: true + }); + } + + /* + End 1Password Extension + */ + + chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { + if (msg.command === 'collectPageDetails') { + var pageDetails = collect(document); + var pageDetailsObj = JSON.parse(pageDetails); + chrome.runtime.sendMessage({ + command: 'collectPageDetailsResponse', + tab: msg.tab, + details: pageDetailsObj, + sender: msg.sender + }); + sendResponse(); + return true; + } + else if (msg.command === 'fillForm') { + fill(document, msg.fillScript); + sendResponse(); + return true; + } + }); +})(); diff --git a/apps/browser/src/content/autofiller.ts b/apps/browser/src/content/autofiller.ts new file mode 100644 index 0000000000..7fe9e5514a --- /dev/null +++ b/apps/browser/src/content/autofiller.ts @@ -0,0 +1,52 @@ +document.addEventListener("DOMContentLoaded", (event) => { + let pageHref: string = null; + let filledThisHref = false; + let delayFillTimeout: number; + + const activeUserIdKey = "activeUserId"; + let activeUserId: string; + + chrome.storage.local.get(activeUserIdKey, (obj: any) => { + if (obj == null || obj[activeUserIdKey] == null) { + return; + } + activeUserId = obj[activeUserIdKey]; + }); + + chrome.storage.local.get(activeUserId, (obj: any) => { + if (obj?.[activeUserId]?.settings?.enableAutoFillOnPageLoad === true) { + setInterval(() => doFillIfNeeded(), 500); + } + }); + chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { + if (msg.command === "fillForm" && pageHref === msg.url) { + filledThisHref = true; + } + }); + + function doFillIfNeeded(force = false) { + if (force || pageHref !== window.location.href) { + if (!force) { + // Some websites are slow and rendering all page content. Try to fill again later + // if we haven't already. + filledThisHref = false; + if (delayFillTimeout != null) { + window.clearTimeout(delayFillTimeout); + } + delayFillTimeout = window.setTimeout(() => { + if (!filledThisHref) { + doFillIfNeeded(true); + } + }, 1500); + } + + pageHref = window.location.href; + const msg: any = { + command: "bgCollectPageDetails", + sender: "autofiller", + }; + + chrome.runtime.sendMessage(msg); + } + } +}); diff --git a/apps/browser/src/content/contextMenuHandler.ts b/apps/browser/src/content/contextMenuHandler.ts new file mode 100644 index 0000000000..b6d0159df0 --- /dev/null +++ b/apps/browser/src/content/contextMenuHandler.ts @@ -0,0 +1,66 @@ +const inputTags = ["input", "textarea", "select"]; +const labelTags = ["label", "span"]; +const attributes = ["id", "name", "label-aria", "placeholder"]; +const invalidElement = chrome.i18n.getMessage("copyCustomFieldNameInvalidElement"); +const noUniqueIdentifier = chrome.i18n.getMessage("copyCustomFieldNameNotUnique"); + +let clickedEl: HTMLElement = null; + +// Find the best attribute to be used as the Name for an element in a custom field. +function getClickedElementIdentifier() { + if (clickedEl == null) { + return invalidElement; + } + + const clickedTag = clickedEl.nodeName.toLowerCase(); + let inputEl = null; + + // Try to identify the input element (which may not be the clicked element) + if (labelTags.includes(clickedTag)) { + let inputId = null; + if (clickedTag === "label") { + inputId = clickedEl.getAttribute("for"); + } else { + inputId = clickedEl.closest("label")?.getAttribute("for"); + } + + inputEl = document.getElementById(inputId); + } else { + inputEl = clickedEl; + } + + if (inputEl == null || !inputTags.includes(inputEl.nodeName.toLowerCase())) { + return invalidElement; + } + + for (const attr of attributes) { + const attributeValue = inputEl.getAttribute(attr); + const selector = "[" + attr + '="' + attributeValue + '"]'; + if (!isNullOrEmpty(attributeValue) && document.querySelectorAll(selector)?.length === 1) { + return attributeValue; + } + } + return noUniqueIdentifier; +} + +function isNullOrEmpty(s: string) { + return s == null || s === ""; +} + +// We only have access to the element that's been clicked when the context menu is first opened. +// Remember it for use later. +document.addEventListener("contextmenu", (event) => { + clickedEl = event.target as HTMLElement; +}); + +// Runs when the 'Copy Custom Field Name' context menu item is actually clicked. +chrome.runtime.onMessage.addListener((event) => { + if (event.command === "getClickedElement") { + const identifier = getClickedElementIdentifier(); + chrome.runtime.sendMessage({ + command: "getClickedElementResponse", + sender: "contextMenuHandler", + identifier: identifier, + }); + } +}); diff --git a/apps/browser/src/content/message_handler.ts b/apps/browser/src/content/message_handler.ts new file mode 100644 index 0000000000..2e90038673 --- /dev/null +++ b/apps/browser/src/content/message_handler.ts @@ -0,0 +1,38 @@ +window.addEventListener( + "message", + (event) => { + if (event.source !== window) return; + + if (event.data.command && event.data.command === "authResult") { + chrome.runtime.sendMessage({ + command: event.data.command, + code: event.data.code, + state: event.data.state, + referrer: event.source.location.hostname, + }); + } + + if (event.data.command && event.data.command === "webAuthnResult") { + chrome.runtime.sendMessage({ + command: event.data.command, + data: event.data.data, + remember: event.data.remember, + referrer: event.source.location.hostname, + }); + } + }, + false +); + +const forwardCommands = [ + "promptForLogin", + "addToLockedVaultPendingNotifications", + "unlockCompleted", + "addedCipher", +]; + +chrome.runtime.onMessage.addListener((event) => { + if (forwardCommands.includes(event.command)) { + chrome.runtime.sendMessage(event); + } +}); diff --git a/apps/browser/src/content/notificationBar.ts b/apps/browser/src/content/notificationBar.ts new file mode 100644 index 0000000000..dcb9ce0453 --- /dev/null +++ b/apps/browser/src/content/notificationBar.ts @@ -0,0 +1,603 @@ +import AddLoginRuntimeMessage from "src/background/models/addLoginRuntimeMessage"; +import ChangePasswordRuntimeMessage from "src/background/models/changePasswordRuntimeMessage"; + +document.addEventListener("DOMContentLoaded", (event) => { + if (window.location.hostname.endsWith("vault.bitwarden.com")) { + return; + } + + const pageDetails: any[] = []; + const formData: any[] = []; + let barType: string = null; + let pageHref: string = null; + let observer: MutationObserver = null; + const observeIgnoredElements = new Set([ + "a", + "i", + "b", + "strong", + "span", + "code", + "br", + "img", + "small", + "em", + "hr", + ]); + let domObservationCollectTimeout: number = null; + let collectIfNeededTimeout: number = null; + let observeDomTimeout: number = null; + const inIframe = isInIframe(); + const cancelButtonNames = new Set(["cancel", "close", "back"]); + const logInButtonNames = new Set([ + "log in", + "sign in", + "login", + "go", + "submit", + "continue", + "next", + ]); + const changePasswordButtonNames = new Set([ + "save password", + "update password", + "change password", + "change", + ]); + const changePasswordButtonContainsNames = new Set(["pass", "change", "contras", "senha"]); + let disabledAddLoginNotification = false; + let disabledChangedPasswordNotification = false; + + const activeUserIdKey = "activeUserId"; + let activeUserId: string; + chrome.storage.local.get(activeUserIdKey, (obj: any) => { + if (obj == null || obj[activeUserIdKey] == null) { + return; + } + activeUserId = obj[activeUserIdKey]; + }); + + chrome.storage.local.get(activeUserId, (obj: any) => { + if (obj?.[activeUserId] == null) { + return; + } + + const domains = obj[activeUserId].settings.neverDomains; + // eslint-disable-next-line + if (domains != null && domains.hasOwnProperty(window.location.hostname)) { + return; + } + + disabledAddLoginNotification = obj[activeUserId].settings.disableAddLoginNotification; + disabledChangedPasswordNotification = + obj[activeUserId].settings.disableChangedPasswordNotification; + + if (!disabledAddLoginNotification || !disabledChangedPasswordNotification) { + collectIfNeededWithTimeout(); + } + }); + + chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { + processMessages(msg, sendResponse); + }); + + function processMessages(msg: any, sendResponse: (response?: any) => void) { + if (msg.command === "openNotificationBar") { + if (inIframe) { + return; + } + closeExistingAndOpenBar(msg.data.type, msg.data.typeData); + sendResponse(); + return true; + } else if (msg.command === "closeNotificationBar") { + if (inIframe) { + return; + } + closeBar(true); + sendResponse(); + return true; + } else if (msg.command === "adjustNotificationBar") { + if (inIframe) { + return; + } + adjustBar(msg.data); + sendResponse(); + return true; + } else if (msg.command === "notificationBarPageDetails") { + pageDetails.push(msg.data.details); + watchForms(msg.data.forms); + sendResponse(); + return true; + } + } + + function isInIframe() { + try { + return window.self !== window.top; + } catch { + return true; + } + } + + function observeDom() { + const bodies = document.querySelectorAll("body"); + if (bodies && bodies.length > 0) { + observer = new MutationObserver((mutations) => { + if (mutations == null || mutations.length === 0 || pageHref !== window.location.href) { + return; + } + + let doCollect = false; + for (let i = 0; i < mutations.length; i++) { + const mutation = mutations[i]; + if (mutation.addedNodes == null || mutation.addedNodes.length === 0) { + continue; + } + + for (let j = 0; j < mutation.addedNodes.length; j++) { + const addedNode: any = mutation.addedNodes[j]; + if (addedNode == null) { + continue; + } + + const tagName = addedNode.tagName != null ? addedNode.tagName.toLowerCase() : null; + if ( + tagName != null && + tagName === "form" && + (addedNode.dataset == null || !addedNode.dataset.bitwardenWatching) + ) { + doCollect = true; + break; + } + + if ( + (tagName != null && observeIgnoredElements.has(tagName)) || + addedNode.querySelectorAll == null + ) { + continue; + } + + const forms = addedNode.querySelectorAll("form:not([data-bitwarden-watching])"); + if (forms != null && forms.length > 0) { + doCollect = true; + break; + } + } + + if (doCollect) { + break; + } + } + + if (doCollect) { + if (domObservationCollectTimeout != null) { + window.clearTimeout(domObservationCollectTimeout); + } + + domObservationCollectTimeout = window.setTimeout(collect, 1000); + } + }); + + observer.observe(bodies[0], { childList: true, subtree: true }); + } + } + + function collectIfNeededWithTimeout() { + if (collectIfNeededTimeout != null) { + window.clearTimeout(collectIfNeededTimeout); + } + collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000); + } + + function collectIfNeeded() { + if (pageHref !== window.location.href) { + pageHref = window.location.href; + if (observer) { + observer.disconnect(); + observer = null; + } + + collect(); + + if (observeDomTimeout != null) { + window.clearTimeout(observeDomTimeout); + } + observeDomTimeout = window.setTimeout(observeDom, 1000); + } + + if (collectIfNeededTimeout != null) { + window.clearTimeout(collectIfNeededTimeout); + } + collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000); + } + + function collect() { + sendPlatformMessage({ + command: "bgCollectPageDetails", + sender: "notificationBar", + }); + } + + function watchForms(forms: any[]) { + if (forms == null || forms.length === 0) { + return; + } + + forms.forEach((f: any) => { + const formId: string = f.form != null ? f.form.htmlID : null; + let formEl: HTMLFormElement = null; + if (formId != null && formId !== "") { + formEl = document.getElementById(formId) as HTMLFormElement; + } + + if (formEl == null) { + const index = parseInt(f.form.opid.split("__")[2], null); + formEl = document.getElementsByTagName("form")[index]; + } + + if (formEl != null && formEl.dataset.bitwardenWatching !== "1") { + const formDataObj: any = { + data: f, + formEl: formEl, + usernameEl: null, + passwordEl: null, + passwordEls: null, + }; + locateFields(formDataObj); + formData.push(formDataObj); + listen(formEl); + formEl.dataset.bitwardenWatching = "1"; + } + }); + } + + function listen(form: HTMLFormElement) { + form.removeEventListener("submit", formSubmitted, false); + form.addEventListener("submit", formSubmitted, false); + const submitButton = getSubmitButton(form, logInButtonNames); + if (submitButton != null) { + submitButton.removeEventListener("click", formSubmitted, false); + submitButton.addEventListener("click", formSubmitted, false); + } + } + + function locateFields(formDataObj: any) { + const inputs = Array.from(document.getElementsByTagName("input")); + formDataObj.usernameEl = locateField(formDataObj.formEl, formDataObj.data.username, inputs); + if (formDataObj.usernameEl != null && formDataObj.data.password != null) { + formDataObj.passwordEl = locatePassword( + formDataObj.formEl, + formDataObj.data.password, + inputs, + true + ); + } else if (formDataObj.data.passwords != null) { + formDataObj.passwordEls = []; + formDataObj.data.passwords.forEach((pData: any) => { + const el = locatePassword(formDataObj.formEl, pData, inputs, false); + if (el != null) { + formDataObj.passwordEls.push(el); + } + }); + if (formDataObj.passwordEls.length === 0) { + formDataObj.passwordEls = null; + } + } + } + + function locatePassword( + form: HTMLFormElement, + passwordData: any, + inputs: HTMLInputElement[], + doLastFallback: boolean + ) { + let el = locateField(form, passwordData, inputs); + if (el != null && el.type !== "password") { + el = null; + } + if (doLastFallback && el == null) { + el = form.querySelector('input[type="password"]'); + } + return el; + } + + function locateField(form: HTMLFormElement, fieldData: any, inputs: HTMLInputElement[]) { + if (fieldData == null) { + return; + } + let el: HTMLInputElement = null; + if (fieldData.htmlID != null && fieldData.htmlID !== "") { + try { + el = form.querySelector("#" + fieldData.htmlID); + } catch { + // Ignore error, we perform fallbacks below. + } + } + if (el == null && fieldData.htmlName != null && fieldData.htmlName !== "") { + el = form.querySelector('input[name="' + fieldData.htmlName + '"]'); + } + if (el == null && fieldData.elementNumber != null) { + el = inputs[fieldData.elementNumber]; + } + return el; + } + + function formSubmitted(e: Event) { + let form: HTMLFormElement = null; + if (e.type === "click") { + form = (e.target as HTMLElement).closest("form"); + if (form == null) { + const parentModal = (e.target as HTMLElement).closest("div.modal"); + if (parentModal != null) { + const modalForms = parentModal.querySelectorAll("form"); + if (modalForms.length === 1) { + form = modalForms[0]; + } + } + } + } else { + form = e.target as HTMLFormElement; + } + + if (form == null || form.dataset.bitwardenProcessed === "1") { + return; + } + + for (let i = 0; i < formData.length; i++) { + if (formData[i].formEl !== form) { + continue; + } + const disabledBoth = disabledChangedPasswordNotification && disabledAddLoginNotification; + if (!disabledBoth && formData[i].usernameEl != null && formData[i].passwordEl != null) { + const login: AddLoginRuntimeMessage = { + username: formData[i].usernameEl.value, + password: formData[i].passwordEl.value, + url: document.URL, + }; + + if ( + login.username != null && + login.username !== "" && + login.password != null && + login.password !== "" + ) { + processedForm(form); + sendPlatformMessage({ + command: "bgAddLogin", + login: login, + }); + break; + } + } + if (!disabledChangedPasswordNotification && formData[i].passwordEls != null) { + const passwords: string[] = formData[i].passwordEls + .filter((el: HTMLInputElement) => el.value != null && el.value !== "") + .map((el: HTMLInputElement) => el.value); + + let curPass: string = null; + let newPass: string = null; + let newPassOnly = false; + if (formData[i].passwordEls.length === 3 && passwords.length === 3) { + newPass = passwords[1]; + if (passwords[0] !== newPass && newPass === passwords[2]) { + curPass = passwords[0]; + } else if (newPass !== passwords[2] && passwords[0] === newPass) { + curPass = passwords[2]; + } + } else if (formData[i].passwordEls.length === 2 && passwords.length === 2) { + if (passwords[0] === passwords[1]) { + newPassOnly = true; + newPass = passwords[0]; + curPass = null; + } else { + const buttonText = getButtonText(getSubmitButton(form, changePasswordButtonNames)); + const matches = Array.from(changePasswordButtonContainsNames).filter( + (n) => buttonText.indexOf(n) > -1 + ); + if (matches.length > 0) { + curPass = passwords[0]; + newPass = passwords[1]; + } + } + } + + if ((newPass != null && curPass != null) || (newPassOnly && newPass != null)) { + processedForm(form); + + const changePasswordRuntimeMessage: ChangePasswordRuntimeMessage = { + newPassword: newPass, + currentPassword: curPass, + url: document.URL, + }; + sendPlatformMessage({ + command: "bgChangedPassword", + data: changePasswordRuntimeMessage, + }); + break; + } + } + } + } + + function getSubmitButton(wrappingEl: HTMLElement, buttonNames: Set) { + if (wrappingEl == null) { + return null; + } + + const wrappingElIsForm = wrappingEl.tagName.toLowerCase() === "form"; + + let submitButton = wrappingEl.querySelector( + 'input[type="submit"], input[type="image"], ' + 'button[type="submit"]' + ) as HTMLElement; + if (submitButton == null && wrappingElIsForm) { + submitButton = wrappingEl.querySelector("button:not([type])"); + if (submitButton != null) { + const buttonText = getButtonText(submitButton); + if (buttonText != null && cancelButtonNames.has(buttonText.trim().toLowerCase())) { + submitButton = null; + } + } + } + if (submitButton == null) { + const possibleSubmitButtons = Array.from( + wrappingEl.querySelectorAll( + 'a, span, button[type="button"], ' + 'input[type="button"], button:not([type])' + ) + ) as HTMLElement[]; + let typelessButton: HTMLElement = null; + possibleSubmitButtons.forEach((button) => { + if (submitButton != null || button == null || button.tagName == null) { + return; + } + const buttonText = getButtonText(button); + if (buttonText != null) { + if ( + typelessButton != null && + button.tagName.toLowerCase() === "button" && + button.getAttribute("type") == null && + !cancelButtonNames.has(buttonText.trim().toLowerCase()) + ) { + typelessButton = button; + } else if (buttonNames.has(buttonText.trim().toLowerCase())) { + submitButton = button; + } + } + }); + if (submitButton == null && typelessButton != null) { + submitButton = typelessButton; + } + } + if (submitButton == null && wrappingElIsForm) { + // Maybe it's in a modal? + const parentModal = wrappingEl.closest("div.modal") as HTMLElement; + if (parentModal != null) { + const modalForms = parentModal.querySelectorAll("form"); + if (modalForms.length === 1) { + submitButton = getSubmitButton(parentModal, buttonNames); + } + } + } + return submitButton; + } + + function getButtonText(button: HTMLElement) { + let buttonText: string = null; + if (button.tagName.toLowerCase() === "input") { + buttonText = (button as HTMLInputElement).value; + } else { + buttonText = button.innerText; + } + return buttonText; + } + + function processedForm(form: HTMLFormElement) { + form.dataset.bitwardenProcessed = "1"; + window.setTimeout(() => { + form.dataset.bitwardenProcessed = "0"; + }, 500); + } + + function closeExistingAndOpenBar(type: string, typeData: any) { + let barPage = "notification/bar.html"; + switch (type) { + case "add": + barPage = barPage + "?add=1&isVaultLocked=" + typeData.isVaultLocked; + break; + case "change": + barPage = barPage + "?change=1&isVaultLocked=" + typeData.isVaultLocked; + break; + default: + break; + } + + const frame = document.getElementById("bit-notification-bar-iframe") as HTMLIFrameElement; + if (frame != null && frame.src.indexOf(barPage) >= 0) { + return; + } + + closeBar(false); + openBar(type, barPage); + } + + function openBar(type: string, barPage: string) { + barType = type; + + if (document.body == null) { + return; + } + + const barPageUrl: string = chrome.extension.getURL(barPage); + + const iframe = document.createElement("iframe"); + iframe.style.cssText = "height: 42px; width: 100%; border: 0; min-height: initial;"; + iframe.id = "bit-notification-bar-iframe"; + iframe.src = barPageUrl; + + const frameDiv = document.createElement("div"); + frameDiv.setAttribute("aria-live", "polite"); + frameDiv.id = "bit-notification-bar"; + frameDiv.style.cssText = + "height: 42px; width: 100%; top: 0; left: 0; padding: 0; position: fixed; " + + "z-index: 2147483647; visibility: visible;"; + frameDiv.appendChild(iframe); + document.body.appendChild(frameDiv); + + (iframe.contentWindow.location as any) = barPageUrl; + + const spacer = document.createElement("div"); + spacer.id = "bit-notification-bar-spacer"; + spacer.style.cssText = "height: 42px;"; + document.body.insertBefore(spacer, document.body.firstChild); + } + + function closeBar(explicitClose: boolean) { + const barEl = document.getElementById("bit-notification-bar"); + if (barEl != null) { + barEl.parentElement.removeChild(barEl); + } + + const spacerEl = document.getElementById("bit-notification-bar-spacer"); + if (spacerEl) { + spacerEl.parentElement.removeChild(spacerEl); + } + + if (!explicitClose) { + return; + } + + switch (barType) { + case "add": + sendPlatformMessage({ + command: "bgAddClose", + }); + break; + case "change": + sendPlatformMessage({ + command: "bgChangeClose", + }); + break; + default: + break; + } + } + + function adjustBar(data: any) { + if (data != null && data.height !== 42) { + const newHeight = data.height + "px"; + doHeightAdjustment("bit-notification-bar-iframe", newHeight); + doHeightAdjustment("bit-notification-bar", newHeight); + doHeightAdjustment("bit-notification-bar-spacer", newHeight); + } + } + + function doHeightAdjustment(elId: string, heightStyle: string) { + const el = document.getElementById(elId); + if (el != null) { + el.style.height = heightStyle; + } + } + + function sendPlatformMessage(msg: any) { + chrome.runtime.sendMessage(msg); + } +}); diff --git a/apps/browser/src/content/shortcuts.ts b/apps/browser/src/content/shortcuts.ts new file mode 100644 index 0000000000..4832644082 --- /dev/null +++ b/apps/browser/src/content/shortcuts.ts @@ -0,0 +1,52 @@ +import * as Mousetrap from "mousetrap"; + +document.addEventListener("DOMContentLoaded", (event) => { + const isSafari = + typeof safari !== "undefined" && + navigator.userAgent.indexOf(" Safari/") !== -1 && + navigator.userAgent.indexOf("Chrome") === -1; + const isVivaldi = !isSafari && navigator.userAgent.indexOf(" Vivaldi/") !== -1; + + if (!isSafari && !isVivaldi) { + return; + } + + if (isSafari && (window as any).__bitwardenFrameId == null) { + (window as any).__bitwardenFrameId = Math.floor(Math.random() * Math.floor(99999999)); + } + + Mousetrap.prototype.stopCallback = () => { + return false; + }; + + let autofillCommand = ["mod+shift+l"]; + if (isSafari) { + autofillCommand = ["mod+\\", "mod+8", "mod+shift+p"]; + } + Mousetrap.bind(autofillCommand, () => { + sendMessage("autofill_login"); + }); + + if (isSafari) { + Mousetrap.bind("mod+shift+y", () => { + sendMessage("open_popup"); + }); + + Mousetrap.bind("mod+shift+s", () => { + sendMessage("lock_vault"); + }); + } else { + Mousetrap.bind("mod+shift+9", () => { + sendMessage("generate_password"); + }); + } + + function sendMessage(shortcut: string) { + const msg: any = { + command: "keyboardShortcutTriggered", + shortcut: shortcut, + }; + + chrome.runtime.sendMessage(msg); + } +}); diff --git a/apps/browser/src/globals.d.ts b/apps/browser/src/globals.d.ts new file mode 100644 index 0000000000..7307f696ae --- /dev/null +++ b/apps/browser/src/globals.d.ts @@ -0,0 +1,4 @@ +declare function escape(s: string): string; +declare function unescape(s: string): string; +declare let opr: any; +declare let safari: any; diff --git a/apps/browser/src/images/close.png b/apps/browser/src/images/close.png new file mode 100644 index 0000000000..ccbb3b1d5c Binary files /dev/null and b/apps/browser/src/images/close.png differ diff --git a/apps/browser/src/images/icon128.png b/apps/browser/src/images/icon128.png new file mode 100644 index 0000000000..914b3e3899 Binary files /dev/null and b/apps/browser/src/images/icon128.png differ diff --git a/apps/browser/src/images/icon128_gray.png b/apps/browser/src/images/icon128_gray.png new file mode 100644 index 0000000000..4b8fb42683 Binary files /dev/null and b/apps/browser/src/images/icon128_gray.png differ diff --git a/apps/browser/src/images/icon16.png b/apps/browser/src/images/icon16.png new file mode 100644 index 0000000000..3acbfd1435 Binary files /dev/null and b/apps/browser/src/images/icon16.png differ diff --git a/apps/browser/src/images/icon16_gray.png b/apps/browser/src/images/icon16_gray.png new file mode 100644 index 0000000000..ad9da3296f Binary files /dev/null and b/apps/browser/src/images/icon16_gray.png differ diff --git a/apps/browser/src/images/icon18_safari.png b/apps/browser/src/images/icon18_safari.png new file mode 100644 index 0000000000..aaca663c9e Binary files /dev/null and b/apps/browser/src/images/icon18_safari.png differ diff --git a/apps/browser/src/images/icon18_safari@2x.png b/apps/browser/src/images/icon18_safari@2x.png new file mode 100644 index 0000000000..ea812a0859 Binary files /dev/null and b/apps/browser/src/images/icon18_safari@2x.png differ diff --git a/apps/browser/src/images/icon18_safari_locked.png b/apps/browser/src/images/icon18_safari_locked.png new file mode 100644 index 0000000000..164ada8dc6 Binary files /dev/null and b/apps/browser/src/images/icon18_safari_locked.png differ diff --git a/apps/browser/src/images/icon18_safari_locked@2x.png b/apps/browser/src/images/icon18_safari_locked@2x.png new file mode 100644 index 0000000000..afa0173455 Binary files /dev/null and b/apps/browser/src/images/icon18_safari_locked@2x.png differ diff --git a/apps/browser/src/images/icon19.png b/apps/browser/src/images/icon19.png new file mode 100644 index 0000000000..5bf18c7a2a Binary files /dev/null and b/apps/browser/src/images/icon19.png differ diff --git a/apps/browser/src/images/icon19_gray.png b/apps/browser/src/images/icon19_gray.png new file mode 100644 index 0000000000..a6df4d7d5a Binary files /dev/null and b/apps/browser/src/images/icon19_gray.png differ diff --git a/apps/browser/src/images/icon19_locked.png b/apps/browser/src/images/icon19_locked.png new file mode 100644 index 0000000000..4838e6e00c Binary files /dev/null and b/apps/browser/src/images/icon19_locked.png differ diff --git a/apps/browser/src/images/icon32.png b/apps/browser/src/images/icon32.png new file mode 100644 index 0000000000..35008195d9 Binary files /dev/null and b/apps/browser/src/images/icon32.png differ diff --git a/apps/browser/src/images/icon32_gray.png b/apps/browser/src/images/icon32_gray.png new file mode 100644 index 0000000000..6e0c4323b9 Binary files /dev/null and b/apps/browser/src/images/icon32_gray.png differ diff --git a/apps/browser/src/images/icon38.png b/apps/browser/src/images/icon38.png new file mode 100644 index 0000000000..a9a8d3eda9 Binary files /dev/null and b/apps/browser/src/images/icon38.png differ diff --git a/apps/browser/src/images/icon38_gray.png b/apps/browser/src/images/icon38_gray.png new file mode 100644 index 0000000000..c506e6d3d2 Binary files /dev/null and b/apps/browser/src/images/icon38_gray.png differ diff --git a/apps/browser/src/images/icon38_locked.png b/apps/browser/src/images/icon38_locked.png new file mode 100644 index 0000000000..f771defa35 Binary files /dev/null and b/apps/browser/src/images/icon38_locked.png differ diff --git a/apps/browser/src/images/icon48.png b/apps/browser/src/images/icon48.png new file mode 100644 index 0000000000..0de0da04fb Binary files /dev/null and b/apps/browser/src/images/icon48.png differ diff --git a/apps/browser/src/images/icon48_gray.png b/apps/browser/src/images/icon48_gray.png new file mode 100644 index 0000000000..5f694d8c98 Binary files /dev/null and b/apps/browser/src/images/icon48_gray.png differ diff --git a/apps/browser/src/images/icon96.png b/apps/browser/src/images/icon96.png new file mode 100644 index 0000000000..af71804325 Binary files /dev/null and b/apps/browser/src/images/icon96.png differ diff --git a/apps/browser/src/images/icon96_gray.png b/apps/browser/src/images/icon96_gray.png new file mode 100644 index 0000000000..a1b7886752 Binary files /dev/null and b/apps/browser/src/images/icon96_gray.png differ diff --git a/apps/browser/src/manifest.json b/apps/browser/src/manifest.json new file mode 100644 index 0000000000..b9dfaa1077 --- /dev/null +++ b/apps/browser/src/manifest.json @@ -0,0 +1,123 @@ +{ + "manifest_version": 2, + "name": "__MSG_extName__", + "short_name": "__MSG_appName__", + "version": "2022.5.0", + "description": "__MSG_extDesc__", + "default_locale": "en", + "author": "Bitwarden Inc.", + "homepage_url": "https://bitwarden.com", + "icons": { + "16": "images/icon16.png", + "32": "images/icon32.png", + "48": "images/icon48.png", + "96": "images/icon96.png", + "128": "images/icon128.png" + }, + "content_scripts": [ + { + "all_frames": true, + "js": [ + "content/autofill.js", + "content/autofiller.js", + "content/notificationBar.js", + "content/contextMenuHandler.js" + ], + "matches": ["http://*/*", "https://*/*", "file:///*"], + "run_at": "document_start" + }, + { + "all_frames": false, + "js": ["content/shortcuts.js"], + "matches": ["http://*/*", "https://*/*", "file:///*"], + "run_at": "document_start" + }, + { + "all_frames": false, + "js": ["content/message_handler.js"], + "matches": ["http://*/*", "https://*/*", "file:///*"], + "run_at": "document_start" + }, + { + "all_frames": true, + "css": ["content/autofill.css"], + "matches": ["http://*/*", "https://*/*", "file:///*"], + "run_at": "document_end" + } + ], + "background": { + "page": "background.html", + "persistent": true + }, + "browser_action": { + "default_icon": { + "19": "images/icon19.png", + "38": "images/icon38.png" + }, + "default_title": "Bitwarden", + "default_popup": "popup/index.html" + }, + "permissions": [ + "tabs", + "contextMenus", + "storage", + "unlimitedStorage", + "clipboardRead", + "clipboardWrite", + "idle", + "http://*/*", + "https://*/*", + "webRequest", + "webRequestBlocking" + ], + "optional_permissions": ["nativeMessaging"], + "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'", + "commands": { + "_execute_browser_action": { + "suggested_key": { + "default": "Ctrl+Shift+Y", + "linux": "Ctrl+Shift+U" + }, + "description": "__MSG_commandOpenPopup__" + }, + "_execute_sidebar_action": { + "suggested_key": { + "default": "Alt+Shift+Y", + "linux": "Alt+Shift+U" + }, + "description": "__MSG_commandOpenSidebar__" + }, + "autofill_login": { + "suggested_key": { + "default": "Ctrl+Shift+L" + }, + "description": "__MSG_commandAutofillDesc__" + }, + "generate_password": { + "suggested_key": { + "default": "Ctrl+Shift+9" + }, + "description": "__MSG_commandGeneratePasswordDesc__" + }, + "lock_vault": { + "description": "__MSG_commandLockVaultDesc__" + } + }, + "web_accessible_resources": [ + "notification/bar.html", + "images/icon38.png", + "images/icon38_locked.png", + "images/close.png" + ], + "applications": { + "gecko": { + "id": "{446900e4-71c2-419f-a6a7-df9c091e268b}", + "strict_min_version": "42.0" + } + }, + "sidebar_action": { + "default_title": "Bitwarden", + "default_panel": "popup/index.html?uilocation=sidebar", + "default_icon": "images/icon19.png" + } +} diff --git a/apps/browser/src/models/account.ts b/apps/browser/src/models/account.ts new file mode 100644 index 0000000000..e06f260efb --- /dev/null +++ b/apps/browser/src/models/account.ts @@ -0,0 +1,32 @@ +import { + Account as BaseAccount, + AccountSettings as BaseAccountSettings, +} from "jslib-common/models/domain/account"; + +import { BrowserComponentState } from "./browserComponentState"; +import { BrowserGroupingsComponentState } from "./browserGroupingsComponentState"; +import { BrowserSendComponentState } from "./browserSendComponentState"; + +export class AccountSettings extends BaseAccountSettings { + vaultTimeout = -1; // On Restart +} + +export class Account extends BaseAccount { + settings?: AccountSettings = new AccountSettings(); + groupings?: BrowserGroupingsComponentState; + send?: BrowserSendComponentState; + ciphers?: BrowserComponentState; + sendType?: BrowserComponentState; + + constructor(init: Partial) { + super(init); + Object.assign(this.settings, { + ...new AccountSettings(), + ...this.settings, + }); + this.groupings = init?.groupings ?? new BrowserGroupingsComponentState(); + this.send = init?.send ?? new BrowserSendComponentState(); + this.ciphers = init?.ciphers ?? new BrowserComponentState(); + this.sendType = init?.sendType ?? new BrowserComponentState(); + } +} diff --git a/apps/browser/src/models/autofillField.ts b/apps/browser/src/models/autofillField.ts new file mode 100644 index 0000000000..fa08602a32 --- /dev/null +++ b/apps/browser/src/models/autofillField.ts @@ -0,0 +1,25 @@ +export default class AutofillField { + opid: string; + elementNumber: number; + visible: boolean; + viewable: boolean; + htmlID: string; + htmlName: string; + htmlClass: string; + "label-left": string; + "label-right": string; + "label-top": string; + "label-tag": string; + "label-aria": string; + placeholder: string; + type: string; + value: string; + disabled: boolean; + readonly: boolean; + onePasswordFieldType: string; + form: string; + autoCompleteType: string; + selectInfo: any; + maxLength: number; + tagName: string; +} diff --git a/apps/browser/src/models/autofillForm.ts b/apps/browser/src/models/autofillForm.ts new file mode 100644 index 0000000000..625d886f21 --- /dev/null +++ b/apps/browser/src/models/autofillForm.ts @@ -0,0 +1,7 @@ +export default class AutofillForm { + opid: string; + htmlName: string; + htmlID: string; + htmlAction: string; + htmlMethod: string; +} diff --git a/apps/browser/src/models/autofillPageDetails.ts b/apps/browser/src/models/autofillPageDetails.ts new file mode 100644 index 0000000000..1c91386930 --- /dev/null +++ b/apps/browser/src/models/autofillPageDetails.ts @@ -0,0 +1,13 @@ +import AutofillField from "./autofillField"; +import AutofillForm from "./autofillForm"; + +export default class AutofillPageDetails { + documentUUID: string; + title: string; + url: string; + documentUrl: string; + tabUrl: string; + forms: { [id: string]: AutofillForm }; + fields: AutofillField[]; + collectedTimestamp: number; +} diff --git a/apps/browser/src/models/autofillScript.ts b/apps/browser/src/models/autofillScript.ts new file mode 100644 index 0000000000..509c1da87b --- /dev/null +++ b/apps/browser/src/models/autofillScript.ts @@ -0,0 +1,12 @@ +export default class AutofillScript { + script: string[][] = []; + documentUUID: any = {}; + properties: any = {}; + options: any = {}; + metadata: any = {}; + autosubmit: any = null; + + constructor(documentUUID: string) { + this.documentUUID = documentUUID; + } +} diff --git a/apps/browser/src/models/biometricErrors.ts b/apps/browser/src/models/biometricErrors.ts new file mode 100644 index 0000000000..822a5c16f4 --- /dev/null +++ b/apps/browser/src/models/biometricErrors.ts @@ -0,0 +1,17 @@ +type BiometricError = { + title: string; + description: string; +}; + +export type BiometricErrorTypes = "startDesktop" | "desktopIntegrationDisabled"; + +export const BiometricErrors: Record = { + startDesktop: { + title: "startDesktopTitle", + description: "startDesktopDesc", + }, + desktopIntegrationDisabled: { + title: "desktopIntegrationDisabledTitle", + description: "desktopIntegrationDisabledDesc", + }, +}; diff --git a/apps/browser/src/models/browserComponentState.ts b/apps/browser/src/models/browserComponentState.ts new file mode 100644 index 0000000000..d968726c41 --- /dev/null +++ b/apps/browser/src/models/browserComponentState.ts @@ -0,0 +1,4 @@ +export class BrowserComponentState { + scrollY: number; + searchText: string; +} diff --git a/apps/browser/src/models/browserGroupingsComponentState.ts b/apps/browser/src/models/browserGroupingsComponentState.ts new file mode 100644 index 0000000000..8c539b4144 --- /dev/null +++ b/apps/browser/src/models/browserGroupingsComponentState.ts @@ -0,0 +1,18 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; + +import { BrowserComponentState } from "./browserComponentState"; + +export class BrowserGroupingsComponentState extends BrowserComponentState { + favoriteCiphers: CipherView[]; + noFolderCiphers: CipherView[]; + ciphers: CipherView[]; + collectionCounts: Map; + folderCounts: Map; + typeCounts: Map; + folders: FolderView[]; + collections: CollectionView[]; + deletedCount: number; +} diff --git a/apps/browser/src/models/browserSendComponentState.ts b/apps/browser/src/models/browserSendComponentState.ts new file mode 100644 index 0000000000..108d4363c3 --- /dev/null +++ b/apps/browser/src/models/browserSendComponentState.ts @@ -0,0 +1,9 @@ +import { SendType } from "jslib-common/enums/sendType"; +import { SendView } from "jslib-common/models/view/sendView"; + +import { BrowserComponentState } from "./browserComponentState"; + +export class BrowserSendComponentState extends BrowserComponentState { + sends: SendView[]; + typeCounts: Map; +} diff --git a/apps/browser/src/notification/bar.html b/apps/browser/src/notification/bar.html new file mode 100644 index 0000000000..101b555df0 --- /dev/null +++ b/apps/browser/src/notification/bar.html @@ -0,0 +1,39 @@ + + + + Bitwarden + + + + +
+ +
+
+ +
+
+ + + diff --git a/apps/browser/src/notification/bar.js b/apps/browser/src/notification/bar.js new file mode 100644 index 0000000000..1c1021ad5f --- /dev/null +++ b/apps/browser/src/notification/bar.js @@ -0,0 +1,161 @@ +// eslint-disable-next-line +require("./bar.scss"); + +document.addEventListener("DOMContentLoaded", () => { + let i18n = {}; + let lang = window.navigator.language; + + i18n.appName = chrome.i18n.getMessage("appName"); + i18n.close = chrome.i18n.getMessage("close"); + i18n.never = chrome.i18n.getMessage("never"); + i18n.folder = chrome.i18n.getMessage("folder"); + i18n.notificationAddSave = chrome.i18n.getMessage("notificationAddSave"); + i18n.notificationAddDesc = chrome.i18n.getMessage("notificationAddDesc"); + i18n.notificationChangeSave = chrome.i18n.getMessage("notificationChangeSave"); + i18n.notificationChangeDesc = chrome.i18n.getMessage("notificationChangeDesc"); + lang = chrome.i18n.getUILanguage(); // eslint-disable-line + + // delay 50ms so that we get proper body dimensions + setTimeout(load, 50); + + function load() { + const isVaultLocked = getQueryVariable("isVaultLocked") == "true"; + document.getElementById("logo").src = isVaultLocked + ? chrome.runtime.getURL("images/icon38_locked.png") + : chrome.runtime.getURL("images/icon38.png"); + + document.getElementById("logo-link").title = i18n.appName; + + var neverButton = document.querySelector("#template-add .never-save"); + neverButton.textContent = i18n.never; + + var selectFolder = document.querySelector("#template-add .select-folder"); + selectFolder.setAttribute("aria-label", i18n.folder); + selectFolder.setAttribute("isVaultLocked", isVaultLocked.toString()); + + var addButton = document.querySelector("#template-add .add-save"); + addButton.textContent = i18n.notificationAddSave; + + var changeButton = document.querySelector("#template-change .change-save"); + changeButton.textContent = i18n.notificationChangeSave; + + var closeIcon = document.getElementById("close"); + closeIcon.src = chrome.runtime.getURL("images/close.png"); + closeIcon.alt = i18n.close; + + var closeButton = document.getElementById("close-button"); + closeButton.title = i18n.close; + closeButton.setAttribute("aria-label", i18n.close); + + document.querySelector("#template-add .add-text").textContent = i18n.notificationAddDesc; + document.querySelector("#template-change .change-text").textContent = + i18n.notificationChangeDesc; + + if (getQueryVariable("add")) { + setContent(document.getElementById("template-add")); + + var addButton = document.querySelector("#template-add-clone .add-save"), // eslint-disable-line + neverButton = document.querySelector("#template-add-clone .never-save"); // eslint-disable-line + + addButton.addEventListener("click", (e) => { + e.preventDefault(); + + const folderId = document.querySelector("#template-add-clone .select-folder").value; + + const bgAddSaveMessage = { + command: "bgAddSave", + folder: folderId, + }; + sendPlatformMessage(bgAddSaveMessage); + }); + + neverButton.addEventListener("click", (e) => { + e.preventDefault(); + sendPlatformMessage({ + command: "bgNeverSave", + }); + }); + + if (!isVaultLocked) { + const responseFoldersCommand = "notificationBarGetFoldersList"; + chrome.runtime.onMessage.addListener((msg) => { + if (msg.command === responseFoldersCommand && msg.data) { + fillSelectorWithFolders(msg.data.folders); + } + }); + sendPlatformMessage({ + command: "bgGetDataForTab", + responseCommand: responseFoldersCommand, + }); + } + } else if (getQueryVariable("change")) { + setContent(document.getElementById("template-change")); + var changeButton = document.querySelector("#template-change-clone .change-save"); // eslint-disable-line + changeButton.addEventListener("click", (e) => { + e.preventDefault(); + + const bgChangeSaveMessage = { + command: "bgChangeSave", + }; + sendPlatformMessage(bgChangeSaveMessage); + }); + } + + closeButton.addEventListener("click", (e) => { + e.preventDefault(); + sendPlatformMessage({ + command: "bgCloseNotificationBar", + }); + }); + + window.addEventListener("resize", adjustHeight); + adjustHeight(); + } + + function getQueryVariable(variable) { + var query = window.location.search.substring(1); + var vars = query.split("&"); + + for (var i = 0; i < vars.length; i++) { + var pair = vars[i].split("="); + if (pair[0] === variable) { + return pair[1]; + } + } + + return null; + } + + function setContent(element) { + const content = document.getElementById("content"); + while (content.firstChild) { + content.removeChild(content.firstChild); + } + + var newElement = element.cloneNode(true); + newElement.id = newElement.id + "-clone"; + content.appendChild(newElement); + } + + function sendPlatformMessage(msg) { + chrome.runtime.sendMessage(msg); + } + + function fillSelectorWithFolders(folders) { + const select = document.querySelector("#template-add-clone .select-folder"); + select.appendChild(new Option(chrome.i18n.getMessage("selectFolder"), null, true)); + folders.forEach((folder) => { + //Select "No Folder" (id=null) folder by default + select.appendChild(new Option(folder.name, folder.id || "", false)); + }); + } + + function adjustHeight() { + sendPlatformMessage({ + command: "bgAdjustNotificationBar", + data: { + height: document.querySelector("body").scrollHeight, + }, + }); + } +}); diff --git a/apps/browser/src/notification/bar.scss b/apps/browser/src/notification/bar.scss new file mode 100644 index 0000000000..8303cb5151 --- /dev/null +++ b/apps/browser/src/notification/bar.scss @@ -0,0 +1,94 @@ +body { + background-color: #ffffff; + padding: 0; + margin: 0; + height: 100%; + font-size: 14px; + line-height: 16px; + color: #333333; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +.outer-wrapper { + padding: 0 10px; + border-bottom: 2px solid #175ddc; + display: grid; + grid-template-columns: 24px auto 55px; + grid-column-gap: 10px; + box-sizing: border-box; + min-height: 42px; +} + +.inner-wrapper { + display: grid; + grid-template-columns: auto max-content; +} + +.outer-wrapper > *, +.inner-wrapper > * { + align-self: center; +} + +img { + border: 0; + margin: 0; + padding: 0; +} + +#logo { + width: 24px; + height: 24px; + display: block; +} + +#close { + width: 15px; + height: 15px; + display: block; + padding: 5px 0; + margin-right: 10px; +} + +button:not(.link), +button:not(.neutral) { + background-color: #175ddc; + padding: 5px 15px; + border-radius: 3px; + color: #ffffff; + border: 0; + + &:hover { + cursor: pointer; + background-color: #1751bd; + } +} + +button.link, +button.neutral { + background: none; + padding: 5px 15px; + color: #175ddc; + border: 0; + + &:hover { + cursor: pointer; + background: none; + text-decoration: underline; + } +} + +.select-folder[isVaultLocked="true"] { + display: none; +} + +@media screen and (max-width: 768px) { + .select-folder { + display: none; + } +} + +@media (print) { + body { + display: none; + } +} diff --git a/apps/browser/src/popup/accounts/environment.component.html b/apps/browser/src/popup/accounts/environment.component.html new file mode 100644 index 0000000000..626c5b7b3e --- /dev/null +++ b/apps/browser/src/popup/accounts/environment.component.html @@ -0,0 +1,104 @@ +
+
+ +

+ {{ "appName" | i18n }} +

+
+ +
+
+
+
+

+ {{ "selfHostedEnvironment" | i18n }} +

+
+
+ + +
+
+ +
+
+

+ {{ "customEnvironment" | i18n }} +

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
diff --git a/apps/browser/src/popup/accounts/environment.component.ts b/apps/browser/src/popup/accounts/environment.component.ts new file mode 100644 index 0000000000..615c8e6470 --- /dev/null +++ b/apps/browser/src/popup/accounts/environment.component.ts @@ -0,0 +1,28 @@ +import { Component } from "@angular/core"; +import { Router } from "@angular/router"; + +import { EnvironmentComponent as BaseEnvironmentComponent } from "jslib-angular/components/environment.component"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-environment", + templateUrl: "environment.component.html", +}) +export class EnvironmentComponent extends BaseEnvironmentComponent { + constructor( + platformUtilsService: PlatformUtilsService, + environmentService: EnvironmentService, + i18nService: I18nService, + private router: Router + ) { + super(platformUtilsService, environmentService, i18nService); + this.showCustom = true; + } + + saved() { + super.saved(); + this.router.navigate([""]); + } +} diff --git a/apps/browser/src/popup/accounts/hint.component.html b/apps/browser/src/popup/accounts/hint.component.html new file mode 100644 index 0000000000..b4fbfdc05a --- /dev/null +++ b/apps/browser/src/popup/accounts/hint.component.html @@ -0,0 +1,38 @@ +
+
+ +

+ {{ "passwordHint" | i18n }} +

+
+ +
+
+
+
+
+
+ + +
+
+ +
+
+
diff --git a/apps/browser/src/popup/accounts/hint.component.ts b/apps/browser/src/popup/accounts/hint.component.ts new file mode 100644 index 0000000000..5bed1b5858 --- /dev/null +++ b/apps/browser/src/popup/accounts/hint.component.ts @@ -0,0 +1,24 @@ +import { Component } from "@angular/core"; +import { Router } from "@angular/router"; + +import { HintComponent as BaseHintComponent } from "jslib-angular/components/hint.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-hint", + templateUrl: "hint.component.html", +}) +export class HintComponent extends BaseHintComponent { + constructor( + router: Router, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + apiService: ApiService, + logService: LogService + ) { + super(router, i18nService, apiService, platformUtilsService, logService); + } +} diff --git a/apps/browser/src/popup/accounts/home.component.html b/apps/browser/src/popup/accounts/home.component.html new file mode 100644 index 0000000000..2fb6907dcc --- /dev/null +++ b/apps/browser/src/popup/accounts/home.component.html @@ -0,0 +1,16 @@ +
+
+
+

{{ "loginOrCreateNewAccount" | i18n }}

+ {{ "login" | i18n }} + + {{ "createAccount" | i18n }} +
+
+ +  {{ "settings" | i18n }} + diff --git a/apps/browser/src/popup/accounts/home.component.ts b/apps/browser/src/popup/accounts/home.component.ts new file mode 100644 index 0000000000..ca74774024 --- /dev/null +++ b/apps/browser/src/popup/accounts/home.component.ts @@ -0,0 +1,63 @@ +import { Component } from "@angular/core"; + +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; + +@Component({ + selector: "app-home", + templateUrl: "home.component.html", +}) +export class HomeComponent { + constructor( + protected platformUtilsService: PlatformUtilsService, + private passwordGenerationService: PasswordGenerationService, + private stateService: StateService, + private cryptoFunctionService: CryptoFunctionService, + private environmentService: EnvironmentService + ) {} + + async launchSsoBrowser() { + // Generate necessary sso params + const passwordOptions: any = { + type: "password", + length: 64, + uppercase: true, + lowercase: true, + numbers: true, + special: false, + }; + + const state = + (await this.passwordGenerationService.generatePassword(passwordOptions)) + + ":clientId=browser"; + const codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions); + const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, "sha256"); + const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); + + await this.stateService.setSsoCodeVerifier(codeVerifier); + await this.stateService.setSsoState(state); + + let url = this.environmentService.getWebVaultUrl(); + if (url == null) { + url = "https://vault.bitwarden.com"; + } + + const redirectUri = url + "/sso-connector.html"; + + // Launch browser + this.platformUtilsService.launchUri( + url + + "/#/sso?clientId=browser" + + "&redirectUri=" + + encodeURIComponent(redirectUri) + + "&state=" + + state + + "&codeChallenge=" + + codeChallenge + ); + } +} diff --git a/apps/browser/src/popup/accounts/lock.component.html b/apps/browser/src/popup/accounts/lock.component.html new file mode 100644 index 0000000000..04e6eb1e10 --- /dev/null +++ b/apps/browser/src/popup/accounts/lock.component.html @@ -0,0 +1,85 @@ +
+
+
+

+ {{ "verifyIdentity" | i18n }} +

+
+ +
+
+
+
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+ +
+

+ +

+ + {{ biometricError }} +

+ {{ "awaitDesktop" | i18n }} +

+
+
diff --git a/apps/browser/src/popup/accounts/lock.component.ts b/apps/browser/src/popup/accounts/lock.component.ts new file mode 100644 index 0000000000..e1bee7fc78 --- /dev/null +++ b/apps/browser/src/popup/accounts/lock.component.ts @@ -0,0 +1,105 @@ +import { Component, NgZone } from "@angular/core"; +import { Router } from "@angular/router"; + +import { LockComponent as BaseLockComponent } from "jslib-angular/components/lock.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; + +import { BiometricErrors, BiometricErrorTypes } from "../../models/biometricErrors"; + +@Component({ + selector: "app-lock", + templateUrl: "lock.component.html", +}) +export class LockComponent extends BaseLockComponent { + private isInitialLockScreen: boolean; + + biometricError: string; + pendingBiometric = false; + + constructor( + router: Router, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + messagingService: MessagingService, + cryptoService: CryptoService, + vaultTimeoutService: VaultTimeoutService, + environmentService: EnvironmentService, + stateService: StateService, + apiService: ApiService, + logService: LogService, + keyConnectorService: KeyConnectorService, + ngZone: NgZone, + private authService: AuthService + ) { + super( + router, + i18nService, + platformUtilsService, + messagingService, + cryptoService, + vaultTimeoutService, + environmentService, + stateService, + apiService, + logService, + keyConnectorService, + ngZone + ); + this.successRoute = "/tabs/current"; + this.isInitialLockScreen = (window as any).previousPopupUrl == null; + } + + async ngOnInit() { + await super.ngOnInit(); + const disableAutoBiometricsPrompt = + (await this.stateService.getDisableAutoBiometricsPrompt()) ?? true; + + window.setTimeout(async () => { + document.getElementById(this.pinLock ? "pin" : "masterPassword").focus(); + if ( + this.biometricLock && + !disableAutoBiometricsPrompt && + this.isInitialLockScreen && + (await this.authService.getAuthStatus()) === AuthenticationStatus.Locked + ) { + await this.unlockBiometric(); + } + }, 100); + } + + async unlockBiometric(): Promise { + if (!this.biometricLock) { + return; + } + + this.pendingBiometric = true; + this.biometricError = null; + + let success; + try { + success = await super.unlockBiometric(); + } catch (e) { + const error = BiometricErrors[e as BiometricErrorTypes]; + + if (error == null) { + this.logService.error("Unknown error: " + e); + } + + this.biometricError = this.i18nService.t(error.description); + } + this.pendingBiometric = false; + + return success; + } +} diff --git a/apps/browser/src/popup/accounts/login.component.html b/apps/browser/src/popup/accounts/login.component.html new file mode 100644 index 0000000000..d82d214fb2 --- /dev/null +++ b/apps/browser/src/popup/accounts/login.component.html @@ -0,0 +1,72 @@ +
+
+ +

+ {{ "appName" | i18n }} +

+
+ +
+
+
+
+
+
+ + +
+
+
+ + +
+
+ +
+
+
+ +
+
+
+

+ {{ "getMasterPasswordHint" | i18n }} +

+ +
+
diff --git a/apps/browser/src/popup/accounts/login.component.ts b/apps/browser/src/popup/accounts/login.component.ts new file mode 100644 index 0000000000..cb0567c8d9 --- /dev/null +++ b/apps/browser/src/popup/accounts/login.component.ts @@ -0,0 +1,56 @@ +import { Component, NgZone } from "@angular/core"; +import { Router } from "@angular/router"; + +import { LoginComponent as BaseLoginComponent } from "jslib-angular/components/login.component"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +@Component({ + selector: "app-login", + templateUrl: "login.component.html", +}) +export class LoginComponent extends BaseLoginComponent { + protected alwaysRememberEmail = true; + + constructor( + authService: AuthService, + router: Router, + protected platformUtilsService: PlatformUtilsService, + protected i18nService: I18nService, + protected stateService: StateService, + protected environmentService: EnvironmentService, + protected passwordGenerationService: PasswordGenerationService, + protected cryptoFunctionService: CryptoFunctionService, + syncService: SyncService, + logService: LogService, + ngZone: NgZone + ) { + super( + authService, + router, + platformUtilsService, + i18nService, + stateService, + environmentService, + passwordGenerationService, + cryptoFunctionService, + logService, + ngZone + ); + super.onSuccessfulLogin = async () => { + await syncService.fullSync(true); + }; + super.successRoute = "/tabs/vault"; + } + + settings() { + this.router.navigate(["environment"]); + } +} diff --git a/apps/browser/src/popup/accounts/register.component.html b/apps/browser/src/popup/accounts/register.component.html new file mode 100644 index 0000000000..fc9c4e7990 --- /dev/null +++ b/apps/browser/src/popup/accounts/register.component.html @@ -0,0 +1,160 @@ +
+
+ +

+ {{ "createAccount" | i18n }} +

+
+ +
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+ + +
+
+ +
+
+
+ + +
+
+ +
+
+
+
+
+ + +
+
+
+
+
diff --git a/apps/browser/src/popup/accounts/register.component.ts b/apps/browser/src/popup/accounts/register.component.ts new file mode 100644 index 0000000000..98412cd0c9 --- /dev/null +++ b/apps/browser/src/popup/accounts/register.component.ts @@ -0,0 +1,45 @@ +import { Component } from "@angular/core"; +import { Router } from "@angular/router"; + +import { RegisterComponent as BaseRegisterComponent } from "jslib-angular/components/register.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Component({ + selector: "app-register", + templateUrl: "register.component.html", +}) +export class RegisterComponent extends BaseRegisterComponent { + constructor( + authService: AuthService, + router: Router, + i18nService: I18nService, + cryptoService: CryptoService, + apiService: ApiService, + stateService: StateService, + platformUtilsService: PlatformUtilsService, + passwordGenerationService: PasswordGenerationService, + environmentService: EnvironmentService, + logService: LogService + ) { + super( + authService, + router, + i18nService, + cryptoService, + apiService, + stateService, + platformUtilsService, + passwordGenerationService, + environmentService, + logService + ); + } +} diff --git a/apps/browser/src/popup/accounts/remove-password.component.html b/apps/browser/src/popup/accounts/remove-password.component.html new file mode 100644 index 0000000000..793bcff3e0 --- /dev/null +++ b/apps/browser/src/popup/accounts/remove-password.component.html @@ -0,0 +1,49 @@ +
+
+
+ {{ "removeMasterPassword" | i18n }} +
+
+
+ +
+
+
+
+

{{ "convertOrganizationEncryptionDesc" | i18n: organization.name }}

+
+
+ +
+
+ +
+
+
+
diff --git a/apps/browser/src/popup/accounts/remove-password.component.ts b/apps/browser/src/popup/accounts/remove-password.component.ts new file mode 100644 index 0000000000..cdb75058ab --- /dev/null +++ b/apps/browser/src/popup/accounts/remove-password.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +import { RemovePasswordComponent as BaseRemovePasswordComponent } from "jslib-angular/components/remove-password.component"; + +@Component({ + selector: "app-remove-password", + templateUrl: "remove-password.component.html", +}) +export class RemovePasswordComponent extends BaseRemovePasswordComponent {} diff --git a/apps/browser/src/popup/accounts/set-password.component.html b/apps/browser/src/popup/accounts/set-password.component.html new file mode 100644 index 0000000000..b8e89b7693 --- /dev/null +++ b/apps/browser/src/popup/accounts/set-password.component.html @@ -0,0 +1,148 @@ +
+
+ +

+ {{ "setMasterPassword" | i18n }} +

+
+ +
+
+
+
+ +
+
+
+ {{ "ssoCompleteRegistration" | i18n }} + + {{ "resetPasswordAutoEnrollInviteWarning" | i18n }} + + + +
+
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+
+ + +
+
+ +
+
+
+
diff --git a/apps/browser/src/popup/accounts/set-password.component.ts b/apps/browser/src/popup/accounts/set-password.component.ts new file mode 100644 index 0000000000..668f98bb1b --- /dev/null +++ b/apps/browser/src/popup/accounts/set-password.component.ts @@ -0,0 +1,77 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { SetPasswordComponent as BaseSetPasswordComponent } from "jslib-angular/components/set-password.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +@Component({ + selector: "app-set-password", + templateUrl: "set-password.component.html", +}) +export class SetPasswordComponent extends BaseSetPasswordComponent { + constructor( + apiService: ApiService, + i18nService: I18nService, + cryptoService: CryptoService, + messagingService: MessagingService, + stateService: StateService, + passwordGenerationService: PasswordGenerationService, + platformUtilsService: PlatformUtilsService, + policyService: PolicyService, + router: Router, + syncService: SyncService, + route: ActivatedRoute + ) { + super( + i18nService, + cryptoService, + messagingService, + passwordGenerationService, + platformUtilsService, + policyService, + router, + apiService, + syncService, + route, + stateService + ); + } + + get masterPasswordScoreWidth() { + return this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20; + } + + get masterPasswordScoreColor() { + switch (this.masterPasswordScore) { + case 4: + return "success"; + case 3: + return "primary"; + case 2: + return "warning"; + default: + return "danger"; + } + } + + get masterPasswordScoreText() { + switch (this.masterPasswordScore) { + case 4: + return this.i18nService.t("strong"); + case 3: + return this.i18nService.t("good"); + case 2: + return this.i18nService.t("weak"); + default: + return this.masterPasswordScore != null ? this.i18nService.t("weak") : null; + } + } +} diff --git a/.gitmodules b/apps/browser/src/popup/accounts/sso.component.html similarity index 100% rename from .gitmodules rename to apps/browser/src/popup/accounts/sso.component.html diff --git a/apps/browser/src/popup/accounts/sso.component.ts b/apps/browser/src/popup/accounts/sso.component.ts new file mode 100644 index 0000000000..29af3db6ae --- /dev/null +++ b/apps/browser/src/popup/accounts/sso.component.ts @@ -0,0 +1,71 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { SsoComponent as BaseSsoComponent } from "jslib-angular/components/sso.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; + +import { BrowserApi } from "../../browser/browserApi"; + +@Component({ + selector: "app-sso", + templateUrl: "sso.component.html", +}) +export class SsoComponent extends BaseSsoComponent { + constructor( + authService: AuthService, + router: Router, + i18nService: I18nService, + route: ActivatedRoute, + stateService: StateService, + platformUtilsService: PlatformUtilsService, + apiService: ApiService, + cryptoFunctionService: CryptoFunctionService, + passwordGenerationService: PasswordGenerationService, + syncService: SyncService, + environmentService: EnvironmentService, + logService: LogService, + private vaultTimeoutService: VaultTimeoutService + ) { + super( + authService, + router, + i18nService, + route, + stateService, + platformUtilsService, + apiService, + cryptoFunctionService, + environmentService, + passwordGenerationService, + logService + ); + + const url = this.environmentService.getWebVaultUrl(); + + this.redirectUri = url + "/sso-connector.html"; + this.clientId = "browser"; + + super.onSuccessfulLogin = async () => { + await syncService.fullSync(true); + + // If the vault is unlocked then this will clear keys from memory, which we don't want to do + if ((await this.authService.getAuthStatus()) !== AuthenticationStatus.Unlocked) { + BrowserApi.reloadOpenWindows(); + } + + const thisWindow = window.open("", "_self"); + thisWindow.close(); + }; + } +} diff --git a/apps/browser/src/popup/accounts/two-factor-options.component.html b/apps/browser/src/popup/accounts/two-factor-options.component.html new file mode 100644 index 0000000000..e70d6a373c --- /dev/null +++ b/apps/browser/src/popup/accounts/two-factor-options.component.html @@ -0,0 +1,29 @@ +
+ +

+ {{ "twoStepOptions" | i18n }} +

+
+
+
+
+
+ + +
+
+
diff --git a/apps/browser/src/popup/accounts/two-factor-options.component.ts b/apps/browser/src/popup/accounts/two-factor-options.component.ts new file mode 100644 index 0000000000..e08e6e7b90 --- /dev/null +++ b/apps/browser/src/popup/accounts/two-factor-options.component.ts @@ -0,0 +1,28 @@ +import { Component } from "@angular/core"; +import { Router } from "@angular/router"; + +import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "jslib-angular/components/two-factor-options.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; + +@Component({ + selector: "app-two-factor-options", + templateUrl: "two-factor-options.component.html", +}) +export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent { + constructor( + twoFactorService: TwoFactorService, + router: Router, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService + ) { + super(twoFactorService, router, i18nService, platformUtilsService, window); + } + + choose(p: any) { + super.choose(p); + this.twoFactorService.setSelectedProvider(p.type); + this.router.navigate(["2fa"]); + } +} diff --git a/apps/browser/src/popup/accounts/two-factor.component.html b/apps/browser/src/popup/accounts/two-factor.component.html new file mode 100644 index 0000000000..84ad0cc8bb --- /dev/null +++ b/apps/browser/src/popup/accounts/two-factor.component.html @@ -0,0 +1,144 @@ +
+
+ +

+ {{ title }} +

+
+ +
+
+
+ +
+ + {{ "enterVerificationCodeApp" | i18n }} + + + {{ "enterVerificationCodeEmail" | i18n: twoFactorEmail }} + +
+
+
+
+ + +
+
+ + +
+
+
+
+ +
+

{{ "insertYubiKey" | i18n }}

+ +
+
+
+
+ + +
+
+ + +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+ +
+

{{ "webAuthnNewTab" | i18n }}

+ +
+
+ +
+
+
+
+ + +
+
+
+
+
+ +
+
+

{{ "noTwoStepProviders" | i18n }}

+

{{ "noTwoStepProviders2" | i18n }}

+
+
+

+ +

+

+ +

+
+
+
diff --git a/apps/browser/src/popup/accounts/two-factor.component.ts b/apps/browser/src/popup/accounts/two-factor.component.ts new file mode 100644 index 0000000000..d7e2d3771b --- /dev/null +++ b/apps/browser/src/popup/accounts/two-factor.component.ts @@ -0,0 +1,140 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType"; + +import { BrowserApi } from "../../browser/browserApi"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const BroadcasterSubscriptionId = "TwoFactorComponent"; + +@Component({ + selector: "app-two-factor", + templateUrl: "two-factor.component.html", +}) +export class TwoFactorComponent extends BaseTwoFactorComponent { + showNewWindowMessage = false; + + constructor( + authService: AuthService, + router: Router, + i18nService: I18nService, + apiService: ApiService, + platformUtilsService: PlatformUtilsService, + private syncService: SyncService, + environmentService: EnvironmentService, + private broadcasterService: BroadcasterService, + private popupUtilsService: PopupUtilsService, + stateService: StateService, + route: ActivatedRoute, + private messagingService: MessagingService, + logService: LogService, + twoFactorService: TwoFactorService, + appIdService: AppIdService + ) { + super( + authService, + router, + i18nService, + apiService, + platformUtilsService, + window, + environmentService, + stateService, + route, + logService, + twoFactorService, + appIdService + ); + super.onSuccessfulLogin = () => { + return syncService.fullSync(true); + }; + super.successRoute = "/tabs/vault"; + this.webAuthnNewTab = + this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari(); + } + + async ngOnInit() { + if (this.route.snapshot.paramMap.has("webAuthnResponse")) { + // WebAuthn fallback response + this.selectedProviderType = TwoFactorProviderType.WebAuthn; + this.token = this.route.snapshot.paramMap.get("webAuthnResponse"); + super.onSuccessfulLogin = async () => { + this.syncService.fullSync(true); + this.messagingService.send("reloadPopup"); + window.close(); + }; + this.remember = this.route.snapshot.paramMap.get("remember") === "true"; + await this.doSubmit(); + return; + } + + await super.ngOnInit(); + if (this.selectedProviderType == null) { + return; + } + + // WebAuthn prompt appears inside the popup on linux, and requires a larger popup width + // than usual to avoid cutting off the dialog. + if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && (await this.isLinux())) { + document.body.classList.add("linux-webauthn"); + } + + if ( + this.selectedProviderType === TwoFactorProviderType.Email && + this.popupUtilsService.inPopup(window) + ) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("popup2faCloseMessage"), + null, + this.i18nService.t("yes"), + this.i18nService.t("no") + ); + if (confirmed) { + this.popupUtilsService.popOut(window); + } + } + + this.route.queryParams.pipe(first()).subscribe(async (qParams) => { + if (qParams.sso === "true") { + super.onSuccessfulLogin = () => { + BrowserApi.reloadOpenWindows(); + const thisWindow = window.open("", "_self"); + thisWindow.close(); + return this.syncService.fullSync(true); + }; + } + }); + } + + async ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + + if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && (await this.isLinux())) { + document.body.classList.remove("linux-webauthn"); + } + super.ngOnDestroy(); + } + + anotherMethod() { + this.router.navigate(["2fa-options"]); + } + + async isLinux() { + return (await BrowserApi.getPlatformInfo()).os === "linux"; + } +} diff --git a/apps/browser/src/popup/accounts/update-temp-password.component.html b/apps/browser/src/popup/accounts/update-temp-password.component.html new file mode 100644 index 0000000000..f1836132f7 --- /dev/null +++ b/apps/browser/src/popup/accounts/update-temp-password.component.html @@ -0,0 +1,130 @@ +
+
+ +

+ {{ "updateMasterPassword" | i18n }} +

+
+ +
+
+
+ + {{ "updateMasterPasswordWarning" | i18n }} + + + +
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+ + +
+
+ +
+
+
diff --git a/apps/browser/src/popup/accounts/update-temp-password.component.ts b/apps/browser/src/popup/accounts/update-temp-password.component.ts new file mode 100644 index 0000000000..7ffbad1927 --- /dev/null +++ b/apps/browser/src/popup/accounts/update-temp-password.component.ts @@ -0,0 +1,81 @@ +import { Component } from "@angular/core"; + +import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from "jslib-angular/components/update-temp-password.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +interface MasterPasswordScore { + Color: string; + Text: string; + Width: number; +} + +@Component({ + selector: "app-update-temp-password", + templateUrl: "update-temp-password.component.html", +}) +export class UpdateTempPasswordComponent extends BaseUpdateTempPasswordComponent { + get masterPasswordScoreStyle(): MasterPasswordScore { + const scoreWidth = this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20; + switch (this.masterPasswordScore) { + case 4: + return { + Color: "bg-success", + Text: "strong", + Width: scoreWidth, + }; + case 3: + return { + Color: "bg-primary", + Text: "good", + Width: scoreWidth, + }; + case 2: + return { + Color: "bg-warning", + Text: "weak", + Width: scoreWidth, + }; + default: + return { + Color: "bg-danger", + Text: "weak", + Width: scoreWidth, + }; + } + } + + constructor( + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + passwordGenerationService: PasswordGenerationService, + policyService: PolicyService, + cryptoService: CryptoService, + stateService: StateService, + messagingService: MessagingService, + apiService: ApiService, + syncService: SyncService, + logService: LogService + ) { + super( + i18nService, + platformUtilsService, + passwordGenerationService, + policyService, + cryptoService, + messagingService, + apiService, + stateService, + syncService, + logService + ); + } +} diff --git a/apps/browser/src/popup/app-routing.animations.ts b/apps/browser/src/popup/app-routing.animations.ts new file mode 100644 index 0000000000..a37c128c80 --- /dev/null +++ b/apps/browser/src/popup/app-routing.animations.ts @@ -0,0 +1,205 @@ +import { animate, group, query, style, transition, trigger } from "@angular/animations"; + +const queryShown = query( + ":enter, :leave", + [style({ position: "fixed", width: "100%", height: "100%" })], + { + optional: true, + } +); + +// ref: https://github.com/angular/angular/issues/15477 +const queryChildRoute = query("router-outlet ~ *", [style({}), animate(1, style({}))], { + optional: true, +}); + +const speed = "0.4s"; + +export function queryTranslate( + direction: string, + axis: string, + from: number, + to: number, + zIndex = 1000 +) { + return query( + ":" + direction, + [ + style({ + transform: "translate" + axis + "(" + from + "%)", + zIndex: zIndex, + boxShadow: "0 3px 2px -2px gray", + }), + animate(speed + " ease-in-out", style({ transform: "translate" + axis + "(" + to + "%)" })), + ], + { optional: true } + ); +} + +export function queryTranslateX(direction: string, from: number, to: number, zIndex = 1000) { + return queryTranslate(direction, "X", from, to, zIndex); +} + +export function queryTranslateY(direction: string, from: number, to: number, zIndex = 1000) { + return queryTranslate(direction, "Y", from, to, zIndex); +} + +const inSlideLeft = [ + queryShown, + group([queryTranslateX("enter", 100, 0), queryTranslateX("leave", 0, -100), queryChildRoute]), +]; + +const outSlideRight = [ + queryShown, + group([queryTranslateX("enter", -100, 0), queryTranslateX("leave", 0, 100)]), +]; + +const inSlideUp = [ + queryShown, + group([queryTranslateY("enter", 100, 0, 1010), queryTranslateY("leave", 0, 0), queryChildRoute]), +]; + +const outSlideDown = [ + queryShown, + group([queryTranslateY("enter", 0, 0), queryTranslateY("leave", 0, 100, 1010)]), +]; + +const inSlideDown = [ + queryShown, + group([queryTranslateY("enter", -100, 0, 1010), queryTranslateY("leave", 0, 0), queryChildRoute]), +]; + +// eslint-disable-next-line +const outSlideUp = [ + queryShown, + group([queryTranslateY("enter", 0, 0), queryTranslateY("leave", 0, -100, 1010)]), +]; + +export function tabsToCiphers(fromState: string, toState: string) { + if (fromState == null || toState === null || toState.indexOf("ciphers_") === -1) { + return false; + } + return ( + (fromState.indexOf("ciphers_") === 0 && fromState.indexOf("ciphers_direction=b") === -1) || + fromState === "tabs" + ); +} + +export function ciphersToTabs(fromState: string, toState: string) { + if (fromState == null || toState === null || fromState.indexOf("ciphers_") === -1) { + return false; + } + return toState.indexOf("ciphers_direction=b") === 0 || toState === "tabs"; +} + +export function ciphersToView(fromState: string, toState: string) { + if (fromState == null || toState === null) { + return false; + } + return ( + fromState.indexOf("ciphers_") === 0 && + (toState === "view-cipher" || toState === "add-cipher" || toState === "clone-cipher") + ); +} + +export function viewToCiphers(fromState: string, toState: string) { + if (fromState == null || toState === null) { + return false; + } + return ( + (fromState === "view-cipher" || fromState === "add-cipher" || fromState === "clone-cipher") && + toState.indexOf("ciphers_") === 0 + ); +} + +export const routerTransition = trigger("routerTransition", [ + transition("void => home", inSlideLeft), + transition("void => tabs", inSlideLeft), + + transition("home => environment, home => login, home => register", inSlideUp), + + transition("login => home", outSlideDown), + transition("login => hint", inSlideUp), + transition("login => tabs, login => 2fa", inSlideLeft), + + transition("hint => login, register => home, environment => home", outSlideDown), + + transition("2fa => login", outSlideRight), + transition("2fa => 2fa-options", inSlideUp), + transition("2fa-options => 2fa", outSlideDown), + transition("2fa => tabs", inSlideLeft), + + transition(tabsToCiphers, inSlideLeft), + transition(ciphersToTabs, outSlideRight), + + transition(ciphersToView, inSlideUp), + transition(viewToCiphers, outSlideDown), + + transition("tabs => view-cipher", inSlideUp), + transition("view-cipher => tabs", outSlideDown), + + transition("view-cipher => edit-cipher, view-cipher => cipher-password-history", inSlideUp), + transition( + "edit-cipher => view-cipher, cipher-password-history => view-cipher, edit-cipher => tabs", + outSlideDown + ), + + transition("view-cipher => clone-cipher", inSlideUp), + transition("clone-cipher => view-cipher, clone-cipher => tabs", outSlideDown), + + transition("view-cipher => share-cipher", inSlideUp), + transition("share-cipher => view-cipher", outSlideDown), + + transition("tabs => add-cipher", inSlideUp), + transition("add-cipher => tabs", outSlideDown), + + transition("generator => generator-history, tabs => generator-history", inSlideLeft), + transition("generator-history => generator, generator-history => tabs", outSlideRight), + + transition( + "add-cipher => generator, edit-cipher => generator, clone-cipher => generator", + inSlideUp + ), + transition( + "generator => add-cipher, generator => edit-cipher, generator => clone-cipher", + outSlideDown + ), + + transition("edit-cipher => attachments, edit-cipher => collections", inSlideLeft), + transition("attachments => edit-cipher, collections => edit-cipher", outSlideRight), + + transition("clone-cipher => attachments, clone-cipher => collections", inSlideLeft), + transition("attachments => clone-cipher, collections => clone-cipher", outSlideRight), + + transition("tabs => export", inSlideLeft), + transition("export => tabs", outSlideRight), + + transition("tabs => folders", inSlideLeft), + transition("folders => tabs", outSlideRight), + + transition("folders => edit-folder, folders => add-folder", inSlideUp), + transition("edit-folder => folders, add-folder => folders", outSlideDown), + + transition("tabs => sync", inSlideLeft), + transition("sync => tabs", outSlideRight), + + transition("tabs => excluded-domains", inSlideLeft), + transition("excluded-domains => tabs", outSlideRight), + + transition("tabs => options", inSlideLeft), + transition("options => tabs", outSlideRight), + + transition("tabs => premium", inSlideLeft), + transition("premium => tabs", outSlideRight), + + transition("tabs => lock", inSlideDown), + + transition("tabs => send-type", inSlideLeft), + transition("send-type => tabs", outSlideRight), + + transition("tabs => add-send, send-type => add-send", inSlideUp), + transition("add-send => tabs, add-send => send-type", outSlideDown), + + transition("tabs => edit-send, send-type => edit-send", inSlideUp), + transition("edit-send => tabs, edit-send => send-type", outSlideDown), +]); diff --git a/apps/browser/src/popup/app-routing.module.ts b/apps/browser/src/popup/app-routing.module.ts new file mode 100644 index 0000000000..b9d741615a --- /dev/null +++ b/apps/browser/src/popup/app-routing.module.ts @@ -0,0 +1,341 @@ +import { Injectable, NgModule } from "@angular/core"; +import { ActivatedRouteSnapshot, RouteReuseStrategy, RouterModule, Routes } from "@angular/router"; + +import { AuthGuard } from "jslib-angular/guards/auth.guard"; +import { LockGuard } from "jslib-angular/guards/lock.guard"; +import { UnauthGuard } from "jslib-angular/guards/unauth.guard"; + +import { EnvironmentComponent } from "./accounts/environment.component"; +import { HintComponent } from "./accounts/hint.component"; +import { HomeComponent } from "./accounts/home.component"; +import { LockComponent } from "./accounts/lock.component"; +import { LoginComponent } from "./accounts/login.component"; +import { RegisterComponent } from "./accounts/register.component"; +import { RemovePasswordComponent } from "./accounts/remove-password.component"; +import { SetPasswordComponent } from "./accounts/set-password.component"; +import { SsoComponent } from "./accounts/sso.component"; +import { TwoFactorOptionsComponent } from "./accounts/two-factor-options.component"; +import { TwoFactorComponent } from "./accounts/two-factor.component"; +import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.component"; +import { GeneratorComponent } from "./generator/generator.component"; +import { PasswordGeneratorHistoryComponent } from "./generator/password-generator-history.component"; +import { SendAddEditComponent } from "./send/send-add-edit.component"; +import { SendGroupingsComponent } from "./send/send-groupings.component"; +import { SendTypeComponent } from "./send/send-type.component"; +import { DebounceNavigationService } from "./services/debounceNavigationService"; +import { ExcludedDomainsComponent } from "./settings/excluded-domains.component"; +import { ExportComponent } from "./settings/export.component"; +import { FolderAddEditComponent } from "./settings/folder-add-edit.component"; +import { FoldersComponent } from "./settings/folders.component"; +import { OptionsComponent } from "./settings/options.component"; +import { PremiumComponent } from "./settings/premium.component"; +import { SettingsComponent } from "./settings/settings.component"; +import { SyncComponent } from "./settings/sync.component"; +import { TabsComponent } from "./tabs.component"; +import { AddEditComponent } from "./vault/add-edit.component"; +import { AttachmentsComponent } from "./vault/attachments.component"; +import { CiphersComponent } from "./vault/ciphers.component"; +import { CollectionsComponent } from "./vault/collections.component"; +import { CurrentTabComponent } from "./vault/current-tab.component"; +import { PasswordHistoryComponent } from "./vault/password-history.component"; +import { ShareComponent } from "./vault/share.component"; +import { VaultFilterComponent } from "./vault/vault-filter.component"; +import { ViewComponent } from "./vault/view.component"; + +const routes: Routes = [ + { + path: "", + redirectTo: "home", + pathMatch: "full", + }, + { + path: "vault", + redirectTo: "/tabs/vault", + pathMatch: "full", + }, + { + path: "home", + component: HomeComponent, + canActivate: [UnauthGuard], + data: { state: "home" }, + }, + { + path: "login", + component: LoginComponent, + canActivate: [UnauthGuard], + data: { state: "login" }, + }, + { + path: "lock", + component: LockComponent, + canActivate: [LockGuard], + data: { state: "lock" }, + }, + { + path: "2fa", + component: TwoFactorComponent, + canActivate: [UnauthGuard], + data: { state: "2fa" }, + }, + { + path: "2fa-options", + component: TwoFactorOptionsComponent, + canActivate: [UnauthGuard], + data: { state: "2fa-options" }, + }, + { + path: "sso", + component: SsoComponent, + canActivate: [UnauthGuard], + data: { state: "sso" }, + }, + { + path: "set-password", + component: SetPasswordComponent, + data: { state: "set-password" }, + }, + { + path: "remove-password", + component: RemovePasswordComponent, + canActivate: [AuthGuard], + data: { state: "remove-password" }, + }, + { + path: "register", + component: RegisterComponent, + canActivate: [UnauthGuard], + data: { state: "register" }, + }, + { + path: "hint", + component: HintComponent, + canActivate: [UnauthGuard], + data: { state: "hint" }, + }, + { + path: "environment", + component: EnvironmentComponent, + canActivate: [UnauthGuard], + data: { state: "environment" }, + }, + { + path: "ciphers", + component: CiphersComponent, + canActivate: [AuthGuard], + data: { state: "ciphers" }, + }, + { + path: "view-cipher", + component: ViewComponent, + canActivate: [AuthGuard], + data: { state: "view-cipher" }, + }, + { + path: "cipher-password-history", + component: PasswordHistoryComponent, + canActivate: [AuthGuard], + data: { state: "cipher-password-history" }, + }, + { + path: "add-cipher", + component: AddEditComponent, + canActivate: [AuthGuard, DebounceNavigationService], + data: { state: "add-cipher" }, + runGuardsAndResolvers: "always", + }, + { + path: "edit-cipher", + component: AddEditComponent, + canActivate: [AuthGuard, DebounceNavigationService], + data: { state: "edit-cipher" }, + runGuardsAndResolvers: "always", + }, + { + path: "share-cipher", + component: ShareComponent, + canActivate: [AuthGuard], + data: { state: "share-cipher" }, + }, + { + path: "collections", + component: CollectionsComponent, + canActivate: [AuthGuard], + data: { state: "collections" }, + }, + { + path: "attachments", + component: AttachmentsComponent, + canActivate: [AuthGuard], + data: { state: "attachments" }, + }, + { + path: "generator", + component: GeneratorComponent, + canActivate: [AuthGuard], + data: { state: "generator" }, + }, + { + path: "generator-history", + component: PasswordGeneratorHistoryComponent, + canActivate: [AuthGuard], + data: { state: "generator-history" }, + }, + { + path: "export", + component: ExportComponent, + canActivate: [AuthGuard], + data: { state: "export" }, + }, + { + path: "folders", + component: FoldersComponent, + canActivate: [AuthGuard], + data: { state: "folders" }, + }, + { + path: "add-folder", + component: FolderAddEditComponent, + canActivate: [AuthGuard], + data: { state: "add-folder" }, + }, + { + path: "edit-folder", + component: FolderAddEditComponent, + canActivate: [AuthGuard], + data: { state: "edit-folder" }, + }, + { + path: "sync", + component: SyncComponent, + canActivate: [AuthGuard], + data: { state: "sync" }, + }, + { + path: "excluded-domains", + component: ExcludedDomainsComponent, + canActivate: [AuthGuard], + data: { state: "excluded-domains" }, + }, + { + path: "premium", + component: PremiumComponent, + canActivate: [AuthGuard], + data: { state: "premium" }, + }, + { + path: "options", + component: OptionsComponent, + canActivate: [AuthGuard], + data: { state: "options" }, + }, + { + path: "clone-cipher", + component: AddEditComponent, + canActivate: [AuthGuard], + data: { state: "clone-cipher" }, + }, + { + path: "send-type", + component: SendTypeComponent, + canActivate: [AuthGuard], + data: { state: "send-type" }, + }, + { + path: "add-send", + component: SendAddEditComponent, + canActivate: [AuthGuard], + data: { state: "add-send" }, + }, + { + path: "edit-send", + component: SendAddEditComponent, + canActivate: [AuthGuard], + data: { state: "edit-send" }, + }, + { + path: "update-temp-password", + component: UpdateTempPasswordComponent, + canActivate: [AuthGuard], + data: { state: "update-temp-password" }, + }, + { + path: "tabs", + component: TabsComponent, + data: { state: "tabs" }, + children: [ + { + path: "", + redirectTo: "/tabs/vault", + pathMatch: "full", + }, + { + path: "current", + component: CurrentTabComponent, + canActivate: [AuthGuard], + data: { state: "tabs_current" }, + runGuardsAndResolvers: "always", + }, + { + path: "vault", + component: VaultFilterComponent, + canActivate: [AuthGuard], + data: { state: "tabs_vault" }, + }, + { + path: "generator", + component: GeneratorComponent, + canActivate: [AuthGuard], + data: { state: "tabs_generator" }, + }, + { + path: "settings", + component: SettingsComponent, + canActivate: [AuthGuard], + data: { state: "tabs_settings" }, + }, + { + path: "send", + component: SendGroupingsComponent, + canActivate: [AuthGuard], + data: { state: "tabs_send" }, + }, + ], + }, +]; + +@Injectable() +export class NoRouteReuseStrategy implements RouteReuseStrategy { + shouldDetach(route: ActivatedRouteSnapshot) { + return false; + } + + // eslint-disable-next-line + store(route: ActivatedRouteSnapshot, handle: {}) { + /* Nothing */ + } + + shouldAttach(route: ActivatedRouteSnapshot) { + return false; + } + + retrieve(route: ActivatedRouteSnapshot): any { + return null; + } + + shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot) { + return false; + } +} + +@NgModule({ + imports: [ + RouterModule.forRoot(routes, { + useHash: true, + onSameUrlNavigation: "reload", + /*enableTracing: true,*/ + }), + ], + exports: [RouterModule], + providers: [{ provide: RouteReuseStrategy, useClass: NoRouteReuseStrategy }], +}) +export class AppRoutingModule {} diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts new file mode 100644 index 0000000000..62872f35b7 --- /dev/null +++ b/apps/browser/src/popup/app.component.ts @@ -0,0 +1,267 @@ +import { ChangeDetectorRef, Component, NgZone, OnInit, SecurityContext } from "@angular/core"; +import { DomSanitizer } from "@angular/platform-browser"; +import { NavigationEnd, Router, RouterOutlet } from "@angular/router"; +import { IndividualConfig, ToastrService } from "ngx-toastr"; +import Swal, { SweetAlertIcon } from "sweetalert2"; + +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +import { BrowserApi } from "../browser/browserApi"; +import { StateService } from "../services/abstractions/state.service"; + +import { routerTransition } from "./app-routing.animations"; + +@Component({ + selector: "app-root", + styles: [], + animations: [routerTransition], + template: `
+ +
`, +}) +export class AppComponent implements OnInit { + private lastActivity: number = null; + private activeUserId: string; + + constructor( + private toastrService: ToastrService, + private broadcasterService: BroadcasterService, + private authService: AuthService, + private i18nService: I18nService, + private router: Router, + private stateService: StateService, + private messagingService: MessagingService, + private changeDetectorRef: ChangeDetectorRef, + private ngZone: NgZone, + private sanitizer: DomSanitizer, + private platformUtilsService: PlatformUtilsService + ) {} + + async ngOnInit() { + // Component states must not persist between closing and reopening the popup, otherwise they become dead objects + // Clear them aggressively to make sure this doesn't occur + await this.clearComponentStates(); + + this.stateService.activeAccount.subscribe((userId) => { + this.activeUserId = userId; + }); + + this.ngZone.runOutsideAngular(() => { + window.onmousedown = () => this.recordActivity(); + window.ontouchstart = () => this.recordActivity(); + window.onclick = () => this.recordActivity(); + window.onscroll = () => this.recordActivity(); + window.onkeypress = () => this.recordActivity(); + }); + + (window as any).bitwardenPopupMainMessageListener = async ( + msg: any, + sender: any, + sendResponse: any + ) => { + if (msg.command === "doneLoggingOut") { + this.ngZone.run(async () => { + this.authService.logOut(async () => { + if (msg.expired) { + this.showToast({ + type: "warning", + title: this.i18nService.t("loggedOut"), + text: this.i18nService.t("loginExpired"), + }); + } + + if (this.stateService.activeAccount.getValue() == null) { + this.router.navigate(["home"]); + } + }); + this.changeDetectorRef.detectChanges(); + }); + } else if (msg.command === "authBlocked") { + this.ngZone.run(() => { + this.router.navigate(["home"]); + }); + } else if (msg.command === "locked") { + if (msg.userId == null || msg.userId === (await this.stateService.getUserId())) { + this.ngZone.run(() => { + this.router.navigate(["lock"]); + }); + } + } else if (msg.command === "showDialog") { + await this.showDialog(msg); + } else if (msg.command === "showToast") { + this.ngZone.run(() => { + this.showToast(msg); + }); + } else if (msg.command === "reloadProcess") { + const windowReload = + this.platformUtilsService.isSafari() || + this.platformUtilsService.isFirefox() || + this.platformUtilsService.isOpera(); + if (windowReload) { + // Wait to make sure background has reloaded first. + window.setTimeout(() => BrowserApi.reloadExtension(window), 2000); + } + } else if (msg.command === "reloadPopup") { + this.ngZone.run(() => { + this.router.navigate(["/"]); + }); + } else if (msg.command === "convertAccountToKeyConnector") { + this.ngZone.run(async () => { + this.router.navigate(["/remove-password"]); + }); + } else { + msg.webExtSender = sender; + this.broadcasterService.send(msg); + } + }; + + BrowserApi.messageListener("app.component", (window as any).bitwardenPopupMainMessageListener); + + this.router.events.subscribe(async (event) => { + if (event instanceof NavigationEnd) { + const url = event.urlAfterRedirects || event.url || ""; + if ( + url.startsWith("/tabs/") && + (window as any).previousPopupUrl != null && + (window as any).previousPopupUrl.startsWith("/tabs/") + ) { + await this.clearComponentStates(); + } + if (url.startsWith("/tabs/")) { + await this.stateService.setAddEditCipherInfo(null); + } + (window as any).previousPopupUrl = url; + + // Clear route direction after animation (400ms) + if ((window as any).routeDirection != null) { + window.setTimeout(() => { + (window as any).routeDirection = null; + }, 400); + } + } + }); + } + + getState(outlet: RouterOutlet) { + if (outlet.activatedRouteData.state === "ciphers") { + const routeDirection = + (window as any).routeDirection != null ? (window as any).routeDirection : ""; + return ( + "ciphers_direction=" + + routeDirection + + "_" + + (outlet.activatedRoute.queryParams as any).value.folderId + + "_" + + (outlet.activatedRoute.queryParams as any).value.collectionId + ); + } else { + return outlet.activatedRouteData.state; + } + } + + private async recordActivity() { + if (this.activeUserId == null) { + return; + } + + const now = new Date().getTime(); + if (this.lastActivity != null && now - this.lastActivity < 250) { + return; + } + + this.lastActivity = now; + await this.stateService.setLastActive(now, { userId: this.activeUserId }); + } + + private showToast(msg: any) { + let message = ""; + + const options: Partial = {}; + + if (typeof msg.text === "string") { + message = msg.text; + } else if (msg.text.length === 1) { + message = msg.text[0]; + } else { + msg.text.forEach( + (t: string) => + (message += "

" + this.sanitizer.sanitize(SecurityContext.HTML, t) + "

") + ); + options.enableHtml = true; + } + if (msg.options != null) { + if (msg.options.trustedHtml === true) { + options.enableHtml = true; + } + if (msg.options.timeout != null && msg.options.timeout > 0) { + options.timeOut = msg.options.timeout; + } + } + + this.toastrService.show(message, msg.title, options, "toast-" + msg.type); + } + + private async showDialog(msg: any) { + let iconClasses: string = null; + const type = msg.type; + if (type != null) { + // If you add custom types to this part, the type to SweetAlertIcon cast below needs to be changed. + switch (type) { + case "success": + iconClasses = "bwi-check text-success"; + break; + case "warning": + iconClasses = "bwi-exclamation-triangle text-warning"; + break; + case "error": + iconClasses = "bwi-error text-danger"; + break; + case "info": + iconClasses = "bwi-info-circle text-info"; + break; + default: + break; + } + } + + const cancelText = msg.cancelText; + const confirmText = msg.confirmText; + const confirmed = await Swal.fire({ + heightAuto: false, + buttonsStyling: false, + icon: type as SweetAlertIcon, // required to be any of the SweetAlertIcons to output the iconHtml. + iconHtml: + iconClasses != null ? `` : undefined, + text: msg.text, + html: msg.html, + titleText: msg.title, + showCancelButton: cancelText != null, + cancelButtonText: cancelText, + showConfirmButton: true, + confirmButtonText: confirmText == null ? this.i18nService.t("ok") : confirmText, + timer: 300000, + }); + + this.messagingService.send("showDialogResolve", { + dialogId: msg.dialogId, + confirmed: confirmed.value, + }); + } + + private async clearComponentStates() { + if (!(await this.stateService.getIsAuthenticated())) { + return; + } + + await Promise.all([ + this.stateService.setBrowserGroupingComponentState(null), + this.stateService.setBrowserCipherComponentState(null), + this.stateService.setBrowserSendComponentState(null), + this.stateService.setBrowserSendTypeComponentState(null), + ]); + } +} diff --git a/apps/browser/src/popup/app.module.ts b/apps/browser/src/popup/app.module.ts new file mode 100644 index 0000000000..8fc728ffcf --- /dev/null +++ b/apps/browser/src/popup/app.module.ts @@ -0,0 +1,244 @@ +import { A11yModule } from "@angular/cdk/a11y"; +import { DragDropModule } from "@angular/cdk/drag-drop"; +import { OverlayModule } from "@angular/cdk/overlay"; +import { ScrollingModule } from "@angular/cdk/scrolling"; +import { CurrencyPipe, DatePipe, registerLocaleData } from "@angular/common"; +import localeAz from "@angular/common/locales/az"; +import localeBe from "@angular/common/locales/be"; +import localeBg from "@angular/common/locales/bg"; +import localeBn from "@angular/common/locales/bn"; +import localeBs from "@angular/common/locales/bs"; +import localeCa from "@angular/common/locales/ca"; +import localeCs from "@angular/common/locales/cs"; +import localeDa from "@angular/common/locales/da"; +import localeDe from "@angular/common/locales/de"; +import localeEl from "@angular/common/locales/el"; +import localeEnGb from "@angular/common/locales/en-GB"; +import localeEnIn from "@angular/common/locales/en-IN"; +import localeEs from "@angular/common/locales/es"; +import localeEt from "@angular/common/locales/et"; +import localeFa from "@angular/common/locales/fa"; +import localeFi from "@angular/common/locales/fi"; +import localeFil from "@angular/common/locales/fil"; +import localeFr from "@angular/common/locales/fr"; +import localeHe from "@angular/common/locales/he"; +import localeHi from "@angular/common/locales/hi"; +import localeHr from "@angular/common/locales/hr"; +import localeHu from "@angular/common/locales/hu"; +import localeId from "@angular/common/locales/id"; +import localeIt from "@angular/common/locales/it"; +import localeJa from "@angular/common/locales/ja"; +import localeKa from "@angular/common/locales/ka"; +import localeKm from "@angular/common/locales/km"; +import localeKn from "@angular/common/locales/kn"; +import localeKo from "@angular/common/locales/ko"; +import localeLt from "@angular/common/locales/lt"; +import localeLv from "@angular/common/locales/lv"; +import localeMl from "@angular/common/locales/ml"; +import localeNb from "@angular/common/locales/nb"; +import localeNl from "@angular/common/locales/nl"; +import localeNn from "@angular/common/locales/nn"; +import localePl from "@angular/common/locales/pl"; +import localePtBr from "@angular/common/locales/pt"; +import localePtPt from "@angular/common/locales/pt-PT"; +import localeRo from "@angular/common/locales/ro"; +import localeRu from "@angular/common/locales/ru"; +import localeSi from "@angular/common/locales/si"; +import localeSk from "@angular/common/locales/sk"; +import localeSl from "@angular/common/locales/sl"; +import localeSr from "@angular/common/locales/sr"; +import localeSv from "@angular/common/locales/sv"; +import localeTh from "@angular/common/locales/th"; +import localeTr from "@angular/common/locales/tr"; +import localeUk from "@angular/common/locales/uk"; +import localeVi from "@angular/common/locales/vi"; +import localeZhCn from "@angular/common/locales/zh-Hans"; +import localeZhTw from "@angular/common/locales/zh-Hant"; +import { NgModule } from "@angular/core"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { BrowserModule } from "@angular/platform-browser"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; + +import { BitwardenToastModule } from "jslib-angular/components/toastr.component"; +import { JslibModule } from "jslib-angular/jslib.module"; + +import { EnvironmentComponent } from "./accounts/environment.component"; +import { HintComponent } from "./accounts/hint.component"; +import { HomeComponent } from "./accounts/home.component"; +import { LockComponent } from "./accounts/lock.component"; +import { LoginComponent } from "./accounts/login.component"; +import { RegisterComponent } from "./accounts/register.component"; +import { RemovePasswordComponent } from "./accounts/remove-password.component"; +import { SetPasswordComponent } from "./accounts/set-password.component"; +import { SsoComponent } from "./accounts/sso.component"; +import { TwoFactorOptionsComponent } from "./accounts/two-factor-options.component"; +import { TwoFactorComponent } from "./accounts/two-factor.component"; +import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.component"; +import { AppRoutingModule } from "./app-routing.module"; +import { AppComponent } from "./app.component"; +import { ActionButtonsComponent } from "./components/action-buttons.component"; +import { CipherRowComponent } from "./components/cipher-row.component"; +import { PasswordRepromptComponent } from "./components/password-reprompt.component"; +import { PopOutComponent } from "./components/pop-out.component"; +import { PrivateModeWarningComponent } from "./components/private-mode-warning.component"; +import { SendListComponent } from "./components/send-list.component"; +import { SetPinComponent } from "./components/set-pin.component"; +import { UserVerificationComponent } from "./components/user-verification.component"; +import { GeneratorComponent } from "./generator/generator.component"; +import { PasswordGeneratorHistoryComponent } from "./generator/password-generator-history.component"; +import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component"; +import { SendAddEditComponent } from "./send/send-add-edit.component"; +import { SendGroupingsComponent } from "./send/send-groupings.component"; +import { SendTypeComponent } from "./send/send-type.component"; +import { ServicesModule } from "./services/services.module"; +import { ExcludedDomainsComponent } from "./settings/excluded-domains.component"; +import { ExportComponent } from "./settings/export.component"; +import { FolderAddEditComponent } from "./settings/folder-add-edit.component"; +import { FoldersComponent } from "./settings/folders.component"; +import { OptionsComponent } from "./settings/options.component"; +import { PremiumComponent } from "./settings/premium.component"; +import { SettingsComponent } from "./settings/settings.component"; +import { SyncComponent } from "./settings/sync.component"; +import { VaultTimeoutInputComponent } from "./settings/vault-timeout-input.component"; +import { TabsComponent } from "./tabs.component"; +import { AddEditCustomFieldsComponent } from "./vault/add-edit-custom-fields.component"; +import { AddEditComponent } from "./vault/add-edit.component"; +import { AttachmentsComponent } from "./vault/attachments.component"; +import { CiphersComponent } from "./vault/ciphers.component"; +import { CollectionsComponent } from "./vault/collections.component"; +import { CurrentTabComponent } from "./vault/current-tab.component"; +import { PasswordHistoryComponent } from "./vault/password-history.component"; +import { ShareComponent } from "./vault/share.component"; +import { VaultFilterComponent } from "./vault/vault-filter.component"; +import { VaultSelectComponent } from "./vault/vault-select.component"; +import { ViewCustomFieldsComponent } from "./vault/view-custom-fields.component"; +import { ViewComponent } from "./vault/view.component"; + +registerLocaleData(localeAz, "az"); +registerLocaleData(localeBe, "be"); +registerLocaleData(localeBg, "bg"); +registerLocaleData(localeBn, "bn"); +registerLocaleData(localeBs, "bs"); +registerLocaleData(localeCa, "ca"); +registerLocaleData(localeCs, "cs"); +registerLocaleData(localeDa, "da"); +registerLocaleData(localeDe, "de"); +registerLocaleData(localeEl, "el"); +registerLocaleData(localeEnGb, "en-GB"); +registerLocaleData(localeEnIn, "en-IN"); +registerLocaleData(localeEs, "es"); +registerLocaleData(localeEt, "et"); +registerLocaleData(localeFa, "fa"); +registerLocaleData(localeFi, "fi"); +registerLocaleData(localeFil, "fil"); +registerLocaleData(localeFr, "fr"); +registerLocaleData(localeHe, "he"); +registerLocaleData(localeHi, "hi"); +registerLocaleData(localeHr, "hr"); +registerLocaleData(localeHu, "hu"); +registerLocaleData(localeId, "id"); +registerLocaleData(localeIt, "it"); +registerLocaleData(localeJa, "ja"); +registerLocaleData(localeKa, "ka"); +registerLocaleData(localeKm, "km"); +registerLocaleData(localeKn, "kn"); +registerLocaleData(localeKo, "ko"); +registerLocaleData(localeLt, "lt"); +registerLocaleData(localeLv, "lv"); +registerLocaleData(localeMl, "ml"); +registerLocaleData(localeNb, "nb"); +registerLocaleData(localeNl, "nl"); +registerLocaleData(localeNn, "nn"); +registerLocaleData(localePl, "pl"); +registerLocaleData(localePtBr, "pt-BR"); +registerLocaleData(localePtPt, "pt-PT"); +registerLocaleData(localeRo, "ro"); +registerLocaleData(localeRu, "ru"); +registerLocaleData(localeSi, "si"); +registerLocaleData(localeSk, "sk"); +registerLocaleData(localeSl, "sl"); +registerLocaleData(localeSr, "sr"); +registerLocaleData(localeSv, "sv"); +registerLocaleData(localeTh, "th"); +registerLocaleData(localeTr, "tr"); +registerLocaleData(localeUk, "uk"); +registerLocaleData(localeVi, "vi"); +registerLocaleData(localeZhCn, "zh-CN"); +registerLocaleData(localeZhTw, "zh-TW"); + +@NgModule({ + imports: [ + A11yModule, + AppRoutingModule, + BitwardenToastModule.forRoot({ + maxOpened: 2, + autoDismiss: true, + closeButton: true, + positionClass: "toast-bottom-full-width", + }), + BrowserAnimationsModule, + BrowserModule, + DragDropModule, + FormsModule, + JslibModule, + OverlayModule, + ReactiveFormsModule, + ScrollingModule, + ServicesModule, + ], + declarations: [ + ActionButtonsComponent, + AddEditComponent, + AddEditCustomFieldsComponent, + AppComponent, + AttachmentsComponent, + CipherRowComponent, + CiphersComponent, + CollectionsComponent, + CurrentTabComponent, + EnvironmentComponent, + ExcludedDomainsComponent, + ExportComponent, + FolderAddEditComponent, + FoldersComponent, + VaultFilterComponent, + HintComponent, + HomeComponent, + LockComponent, + LoginComponent, + OptionsComponent, + GeneratorComponent, + PasswordGeneratorHistoryComponent, + PasswordHistoryComponent, + PasswordRepromptComponent, + PopOutComponent, + PremiumComponent, + PrivateModeWarningComponent, + RegisterComponent, + SendAddEditComponent, + SendEffluxDatesComponent, + SendGroupingsComponent, + SendListComponent, + SendTypeComponent, + SetPasswordComponent, + SetPinComponent, + SettingsComponent, + ShareComponent, + SsoComponent, + SyncComponent, + TabsComponent, + TwoFactorComponent, + TwoFactorOptionsComponent, + UpdateTempPasswordComponent, + UserVerificationComponent, + VaultTimeoutInputComponent, + ViewComponent, + ViewCustomFieldsComponent, + RemovePasswordComponent, + VaultSelectComponent, + ], + entryComponents: [], + providers: [CurrencyPipe, DatePipe], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/apps/browser/src/popup/components/action-buttons.component.html b/apps/browser/src/popup/components/action-buttons.component.html new file mode 100644 index 0000000000..f63c1f1ac3 --- /dev/null +++ b/apps/browser/src/popup/components/action-buttons.component.html @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + diff --git a/apps/browser/src/popup/components/action-buttons.component.ts b/apps/browser/src/popup/components/action-buttons.component.ts new file mode 100644 index 0000000000..8568e0b4ff --- /dev/null +++ b/apps/browser/src/popup/components/action-buttons.component.ts @@ -0,0 +1,86 @@ +import { Component, EventEmitter, Input, Output } from "@angular/core"; + +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { EventType } from "jslib-common/enums/eventType"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +@Component({ + selector: "app-action-buttons", + templateUrl: "action-buttons.component.html", +}) +export class ActionButtonsComponent { + @Output() onView = new EventEmitter(); + @Output() launchEvent = new EventEmitter(); + @Input() cipher: CipherView; + @Input() showView = false; + + cipherType = CipherType; + userHasPremiumAccess = false; + + constructor( + private i18nService: I18nService, + private platformUtilsService: PlatformUtilsService, + private eventService: EventService, + private totpService: TotpService, + private stateService: StateService, + private passwordRepromptService: PasswordRepromptService + ) {} + + async ngOnInit() { + this.userHasPremiumAccess = await this.stateService.getCanAccessPremium(); + } + + launchCipher() { + this.launchEvent.emit(this.cipher); + } + + async copy(cipher: CipherView, value: string, typeI18nKey: string, aType: string) { + if ( + this.cipher.reprompt !== CipherRepromptType.None && + this.passwordRepromptService.protectedFields().includes(aType) && + !(await this.passwordRepromptService.showPasswordPrompt()) + ) { + return; + } + + if (value == null || (aType === "TOTP" && !this.displayTotpCopyButton(cipher))) { + return; + } else if (aType === "TOTP") { + value = await this.totpService.getCode(value); + } + + if (!cipher.viewPassword) { + return; + } + + this.platformUtilsService.copyToClipboard(value, { window: window }); + this.platformUtilsService.showToast( + "info", + null, + this.i18nService.t("valueCopied", this.i18nService.t(typeI18nKey)) + ); + + if (typeI18nKey === "password" || typeI18nKey === "verificationCodeTotp") { + this.eventService.collect(EventType.Cipher_ClientToggledHiddenFieldVisible, cipher.id); + } else if (typeI18nKey === "securityCode") { + this.eventService.collect(EventType.Cipher_ClientCopiedCardCode, cipher.id); + } + } + + displayTotpCopyButton(cipher: CipherView) { + return ( + (cipher?.login?.hasTotp ?? false) && (cipher.organizationUseTotp || this.userHasPremiumAccess) + ); + } + + view() { + this.onView.emit(this.cipher); + } +} diff --git a/apps/browser/src/popup/components/cipher-row.component.html b/apps/browser/src/popup/components/cipher-row.component.html new file mode 100644 index 0000000000..fc78fd9ccf --- /dev/null +++ b/apps/browser/src/popup/components/cipher-row.component.html @@ -0,0 +1,47 @@ +
+ + + +
diff --git a/apps/browser/src/popup/components/cipher-row.component.ts b/apps/browser/src/popup/components/cipher-row.component.ts new file mode 100644 index 0000000000..fa2b66c1b1 --- /dev/null +++ b/apps/browser/src/popup/components/cipher-row.component.ts @@ -0,0 +1,29 @@ +import { Component, EventEmitter, Input, Output } from "@angular/core"; + +import { CipherView } from "jslib-common/models/view/cipherView"; + +@Component({ + selector: "app-cipher-row", + templateUrl: "cipher-row.component.html", +}) +export class CipherRowComponent { + @Output() onSelected = new EventEmitter(); + @Output() launchEvent = new EventEmitter(); + @Output() onView = new EventEmitter(); + @Input() cipher: CipherView; + @Input() last: boolean; + @Input() showView = false; + @Input() title: string; + + selectCipher(c: CipherView) { + this.onSelected.emit(c); + } + + launchCipher(c: CipherView) { + this.launchEvent.emit(c); + } + + viewCipher(c: CipherView) { + this.onView.emit(c); + } +} diff --git a/apps/browser/src/popup/components/password-reprompt.component.html b/apps/browser/src/popup/components/password-reprompt.component.html new file mode 100644 index 0000000000..e57ad7d178 --- /dev/null +++ b/apps/browser/src/popup/components/password-reprompt.component.html @@ -0,0 +1,55 @@ + diff --git a/apps/browser/src/popup/components/password-reprompt.component.ts b/apps/browser/src/popup/components/password-reprompt.component.ts new file mode 100644 index 0000000000..442a0ab5ee --- /dev/null +++ b/apps/browser/src/popup/components/password-reprompt.component.ts @@ -0,0 +1,8 @@ +import { Component } from "@angular/core"; + +import { PasswordRepromptComponent as BasePasswordRepromptComponent } from "jslib-angular/components/password-reprompt.component"; + +@Component({ + templateUrl: "password-reprompt.component.html", +}) +export class PasswordRepromptComponent extends BasePasswordRepromptComponent {} diff --git a/apps/browser/src/popup/components/pop-out.component.html b/apps/browser/src/popup/components/pop-out.component.html new file mode 100644 index 0000000000..73bf76941d --- /dev/null +++ b/apps/browser/src/popup/components/pop-out.component.html @@ -0,0 +1,5 @@ + + + diff --git a/apps/browser/src/popup/components/pop-out.component.ts b/apps/browser/src/popup/components/pop-out.component.ts new file mode 100644 index 0000000000..94a4b3a8de --- /dev/null +++ b/apps/browser/src/popup/components/pop-out.component.ts @@ -0,0 +1,33 @@ +import { Component, Input, OnInit } from "@angular/core"; + +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +import { PopupUtilsService } from "../services/popup-utils.service"; + +@Component({ + selector: "app-pop-out", + templateUrl: "pop-out.component.html", +}) +export class PopOutComponent implements OnInit { + @Input() show = true; + + constructor( + private platformUtilsService: PlatformUtilsService, + private popupUtilsService: PopupUtilsService + ) {} + + ngOnInit() { + if (this.show) { + if ( + (this.popupUtilsService.inSidebar(window) && this.platformUtilsService.isFirefox()) || + this.popupUtilsService.inPopout(window) + ) { + this.show = false; + } + } + } + + expand() { + this.popupUtilsService.popOut(window); + } +} diff --git a/apps/browser/src/popup/components/private-mode-warning.component.html b/apps/browser/src/popup/components/private-mode-warning.component.html new file mode 100644 index 0000000000..848b69c92d --- /dev/null +++ b/apps/browser/src/popup/components/private-mode-warning.component.html @@ -0,0 +1,6 @@ + + {{ "privateModeWarning" | i18n }} + {{ + "learnMore" | i18n + }} + diff --git a/apps/browser/src/popup/components/private-mode-warning.component.ts b/apps/browser/src/popup/components/private-mode-warning.component.ts new file mode 100644 index 0000000000..4d5587d65f --- /dev/null +++ b/apps/browser/src/popup/components/private-mode-warning.component.ts @@ -0,0 +1,17 @@ +import { Component, OnInit } from "@angular/core"; + +import { PopupUtilsService } from "../services/popup-utils.service"; + +@Component({ + selector: "app-private-mode-warning", + templateUrl: "private-mode-warning.component.html", +}) +export class PrivateModeWarningComponent implements OnInit { + showWarning = false; + + constructor(private popupUtilsService: PopupUtilsService) {} + + ngOnInit() { + this.showWarning = this.popupUtilsService.inPrivateMode(); + } +} diff --git a/apps/browser/src/popup/components/send-list.component.html b/apps/browser/src/popup/components/send-list.component.html new file mode 100644 index 0000000000..05c8e3e375 --- /dev/null +++ b/apps/browser/src/popup/components/send-list.component.html @@ -0,0 +1,98 @@ +
+ +
+ + + +
+
diff --git a/apps/browser/src/popup/components/send-list.component.ts b/apps/browser/src/popup/components/send-list.component.ts new file mode 100644 index 0000000000..60e61edc4b --- /dev/null +++ b/apps/browser/src/popup/components/send-list.component.ts @@ -0,0 +1,36 @@ +import { Component, EventEmitter, Input, Output } from "@angular/core"; + +import { SendType } from "jslib-common/enums/sendType"; +import { SendView } from "jslib-common/models/view/sendView"; + +@Component({ + selector: "app-send-list", + templateUrl: "send-list.component.html", +}) +export class SendListComponent { + @Input() sends: SendView[]; + @Input() title: string; + @Input() disabledByPolicy = false; + @Output() onSelected = new EventEmitter(); + @Output() onCopySendLink = new EventEmitter(); + @Output() onRemovePassword = new EventEmitter(); + @Output() onDeleteSend = new EventEmitter(); + + sendType = SendType; + + selectSend(s: SendView) { + this.onSelected.emit(s); + } + + copySendLink(s: SendView) { + this.onCopySendLink.emit(s); + } + + removePassword(s: SendView) { + this.onRemovePassword.emit(s); + } + + delete(s: SendView) { + this.onDeleteSend.emit(s); + } +} diff --git a/apps/browser/src/popup/components/set-pin.component.html b/apps/browser/src/popup/components/set-pin.component.html new file mode 100644 index 0000000000..095b80fb8c --- /dev/null +++ b/apps/browser/src/popup/components/set-pin.component.html @@ -0,0 +1,65 @@ + diff --git a/apps/browser/src/popup/components/set-pin.component.ts b/apps/browser/src/popup/components/set-pin.component.ts new file mode 100644 index 0000000000..4497f7e774 --- /dev/null +++ b/apps/browser/src/popup/components/set-pin.component.ts @@ -0,0 +1,8 @@ +import { Component } from "@angular/core"; + +import { SetPinComponent as BaseSetPinComponent } from "jslib-angular/components/set-pin.component"; + +@Component({ + templateUrl: "set-pin.component.html", +}) +export class SetPinComponent extends BaseSetPinComponent {} diff --git a/apps/browser/src/popup/components/user-verification.component.html b/apps/browser/src/popup/components/user-verification.component.html new file mode 100644 index 0000000000..2fd78bb907 --- /dev/null +++ b/apps/browser/src/popup/components/user-verification.component.html @@ -0,0 +1,46 @@ + +
+ + +
+
+ +
+ + + + + {{ "codeSent" | i18n }} + +
+ +
+ + +
+
diff --git a/apps/browser/src/popup/components/user-verification.component.ts b/apps/browser/src/popup/components/user-verification.component.ts new file mode 100644 index 0000000000..dc12c94a78 --- /dev/null +++ b/apps/browser/src/popup/components/user-verification.component.ts @@ -0,0 +1,23 @@ +import { animate, style, transition, trigger } from "@angular/animations"; +import { Component } from "@angular/core"; +import { NG_VALUE_ACCESSOR } from "@angular/forms"; + +import { UserVerificationComponent as BaseComponent } from "jslib-angular/components/user-verification.component"; + +@Component({ + selector: "app-user-verification", + templateUrl: "user-verification.component.html", + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: UserVerificationComponent, + }, + ], + animations: [ + trigger("sent", [ + transition(":enter", [style({ opacity: 0 }), animate("100ms", style({ opacity: 1 }))]), + ]), + ], +}) +export class UserVerificationComponent extends BaseComponent {} diff --git a/apps/browser/src/popup/generator/generator.component.html b/apps/browser/src/popup/generator/generator.component.html new file mode 100644 index 0000000000..e3a4c51e58 --- /dev/null +++ b/apps/browser/src/popup/generator/generator.component.html @@ -0,0 +1,507 @@ +
+
+ + +
+

+ {{ "generator" | i18n }} +

+
+ +
+
+
+ + {{ "passwordGeneratorPolicyInEffect" | i18n }} + +
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ +
+ + +
+
+
+
+ +
+

+ {{ "options" | i18n }} +

+
+
+ +
+ + +
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+ + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ +
+ +
+

+ {{ "options" | i18n }} +

+
+
+ +
+ + +
+
+
+
+
+
+
+ +
+ + +
+
+ +
+ + +
+
+ +
+ + +
+
+ + +
+
+ +
+ + +
+
+
+
+
+
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+
+
+
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+
+
+
+
+ + +
+
+ + +
+
+
+
+
diff --git a/apps/browser/src/popup/generator/generator.component.ts b/apps/browser/src/popup/generator/generator.component.ts new file mode 100644 index 0000000000..4e9f710c5b --- /dev/null +++ b/apps/browser/src/popup/generator/generator.component.ts @@ -0,0 +1,71 @@ +import { Location } from "@angular/common"; +import { Component } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; + +import { GeneratorComponent as BaseGeneratorComponent } from "jslib-angular/components/generator.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { UsernameGenerationService } from "jslib-common/abstractions/usernameGeneration.service"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +@Component({ + selector: "app-generator", + templateUrl: "generator.component.html", +}) +export class GeneratorComponent extends BaseGeneratorComponent { + private addEditCipherInfo: any; + private cipherState: CipherView; + + constructor( + passwordGenerationService: PasswordGenerationService, + usernameGenerationService: UsernameGenerationService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + stateService: StateService, + route: ActivatedRoute, + logService: LogService, + private location: Location + ) { + super( + passwordGenerationService, + usernameGenerationService, + platformUtilsService, + stateService, + i18nService, + logService, + route, + window + ); + } + + async ngOnInit() { + this.addEditCipherInfo = await this.stateService.getAddEditCipherInfo(); + if (this.addEditCipherInfo != null) { + this.cipherState = this.addEditCipherInfo.cipher; + } + this.comingFromAddEdit = this.cipherState != null; + if (this.cipherState?.login?.hasUris) { + this.usernameWebsite = this.cipherState.login.uris[0].hostname; + } + await super.ngOnInit(); + } + + select() { + super.select(); + if (this.type === "password") { + this.cipherState.login.password = this.password; + } else if (this.type === "username") { + this.cipherState.login.username = this.username; + } + this.addEditCipherInfo.cipher = this.cipherState; + this.stateService.setAddEditCipherInfo(this.addEditCipherInfo); + this.close(); + } + + close() { + this.location.back(); + } +} diff --git a/apps/browser/src/popup/generator/password-generator-history.component.html b/apps/browser/src/popup/generator/password-generator-history.component.html new file mode 100644 index 0000000000..62e5abd28e --- /dev/null +++ b/apps/browser/src/popup/generator/password-generator-history.component.html @@ -0,0 +1,48 @@ +
+
+ +
+

+ {{ "passwordHistory" | i18n }} +

+
+ +
+
+
+
+
+
+
+
+
+ {{ h.date | date: "medium" }} +
+
+
+ +
+
+
+
+
+

{{ "noPasswordsInList" | i18n }}

+
+
diff --git a/apps/browser/src/popup/generator/password-generator-history.component.ts b/apps/browser/src/popup/generator/password-generator-history.component.ts new file mode 100644 index 0000000000..2de2996bc5 --- /dev/null +++ b/apps/browser/src/popup/generator/password-generator-history.component.ts @@ -0,0 +1,26 @@ +import { Location } from "@angular/common"; +import { Component } from "@angular/core"; + +import { PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryComponent } from "jslib-angular/components/password-generator-history.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-password-generator-history", + templateUrl: "password-generator-history.component.html", +}) +export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHistoryComponent { + constructor( + passwordGenerationService: PasswordGenerationService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + private location: Location + ) { + super(passwordGenerationService, platformUtilsService, i18nService, window); + } + + close() { + this.location.back(); + } +} diff --git a/apps/browser/src/popup/images/bwi-globe.png b/apps/browser/src/popup/images/bwi-globe.png new file mode 100644 index 0000000000..cceeaefbcf Binary files /dev/null and b/apps/browser/src/popup/images/bwi-globe.png differ diff --git a/apps/browser/src/popup/images/loading.svg b/apps/browser/src/popup/images/loading.svg new file mode 100644 index 0000000000..7076310516 --- /dev/null +++ b/apps/browser/src/popup/images/loading.svg @@ -0,0 +1,6 @@ + + + Loading... + + diff --git a/apps/browser/src/popup/images/logo-dark@2x.png b/apps/browser/src/popup/images/logo-dark@2x.png new file mode 100644 index 0000000000..3fc3c6d7a5 Binary files /dev/null and b/apps/browser/src/popup/images/logo-dark@2x.png differ diff --git a/apps/browser/src/popup/images/logo-white@2x.png b/apps/browser/src/popup/images/logo-white@2x.png new file mode 100644 index 0000000000..519cbc75e1 Binary files /dev/null and b/apps/browser/src/popup/images/logo-white@2x.png differ diff --git a/apps/browser/src/popup/images/search-desktop-dark.svg b/apps/browser/src/popup/images/search-desktop-dark.svg new file mode 100644 index 0000000000..029d464afa --- /dev/null +++ b/apps/browser/src/popup/images/search-desktop-dark.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/browser/src/popup/images/search-desktop-light.svg b/apps/browser/src/popup/images/search-desktop-light.svg new file mode 100644 index 0000000000..273bcff401 --- /dev/null +++ b/apps/browser/src/popup/images/search-desktop-light.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/browser/src/popup/images/search-desktop-solarized.svg b/apps/browser/src/popup/images/search-desktop-solarized.svg new file mode 100644 index 0000000000..3676a6bccd --- /dev/null +++ b/apps/browser/src/popup/images/search-desktop-solarized.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/browser/src/popup/images/u2fkey.jpg b/apps/browser/src/popup/images/u2fkey.jpg new file mode 100644 index 0000000000..8013df0e56 Binary files /dev/null and b/apps/browser/src/popup/images/u2fkey.jpg differ diff --git a/apps/browser/src/popup/images/yubikey.jpg b/apps/browser/src/popup/images/yubikey.jpg new file mode 100644 index 0000000000..9ddf755dec Binary files /dev/null and b/apps/browser/src/popup/images/yubikey.jpg differ diff --git a/apps/browser/src/popup/index.html b/apps/browser/src/popup/index.html new file mode 100644 index 0000000000..17f50e0a0e --- /dev/null +++ b/apps/browser/src/popup/index.html @@ -0,0 +1,14 @@ + + + + + + Bitwarden + + + + +
+
+ + diff --git a/apps/browser/src/popup/main.ts b/apps/browser/src/popup/main.ts new file mode 100644 index 0000000000..b550cba86f --- /dev/null +++ b/apps/browser/src/popup/main.ts @@ -0,0 +1,16 @@ +import { enableProdMode } from "@angular/core"; +import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; + +require("./scss/popup.scss"); + +import { AppModule } from "./app.module"; + +if (process.env.ENV === "production") { + enableProdMode(); +} + +function init() { + platformBrowserDynamic().bootstrapModule(AppModule, { preserveWhitespaces: true }); +} + +init(); diff --git a/apps/browser/src/popup/polyfills.ts b/apps/browser/src/popup/polyfills.ts new file mode 100644 index 0000000000..8d5d8a0e3b --- /dev/null +++ b/apps/browser/src/popup/polyfills.ts @@ -0,0 +1,4 @@ +import "core-js/stable"; +import "date-input-polyfill"; +import "web-animations-js"; +import "zone.js/dist/zone"; diff --git a/apps/browser/src/popup/scss/base.scss b/apps/browser/src/popup/scss/base.scss new file mode 100644 index 0000000000..8465a1ba33 --- /dev/null +++ b/apps/browser/src/popup/scss/base.scss @@ -0,0 +1,535 @@ +@import "variables.scss"; + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + font-family: $font-family-sans-serif; + font-size: $font-size-base; + line-height: $line-height-base; + -webkit-font-smoothing: antialiased; +} + +body { + width: 375px !important; + height: 600px !important; + overflow: hidden; + color: $text-color; + background-color: $background-color; + + @include themify($themes) { + color: themed("textColor"); + background-color: themed("backgroundColor"); + } + + &.body-sm { + width: 375px !important; + height: 500px !important; + } + + &.body-xs { + width: 375px !important; + height: 300px !important; + } + + &.body-full { + width: 100% !important; + height: 100% !important; + } +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: $font-family-sans-serif; + font-size: $font-size-base; + font-weight: normal; +} + +p { + margin-bottom: 10px; +} + +ul, +ol { + margin-bottom: 10px; +} + +img { + border: none; +} + +a { + text-decoration: none; + + @include themify($themes) { + color: themed("primaryColor"); + } + + &:hover, + &:focus { + @include themify($themes) { + color: darken(themed("primaryColor"), 6%); + } + } +} + +input, +select, +textarea { + @include themify($themes) { + color: themed("textColor"); + background-color: themed("inputBackgroundColor"); + } +} + +input, +select, +textarea, +button { + font-size: $font-size-base; + font-family: $font-family-sans-serif; +} + +button { + white-space: nowrap; + cursor: pointer; +} + +textarea { + resize: vertical; +} + +app-root > div { + height: 100%; +} + +main::-webkit-scrollbar, +cdk-virtual-scroll-viewport::-webkit-scrollbar, +.vault-select::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +main::-webkit-scrollbar-track, +.vault-select::-webkit-scrollbar-track { + background-color: transparent; +} + +cdk-virtual-scroll-viewport::-webkit-scrollbar-track { + @include themify($themes) { + background-color: themed("backgroundColor"); + } +} + +main::-webkit-scrollbar-thumb, +cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb, +.vault-select::-webkit-scrollbar-thumb { + border-radius: 10px; + margin-right: 1px; + + @include themify($themes) { + background-color: themed("scrollbarColor"); + } + + &:hover { + @include themify($themes) { + background-color: themed("scrollbarHoverColor"); + } + } +} + +header { + min-height: 44px; + max-height: 44px; + display: flex; + border-bottom: 1px solid #000000; + + @include themify($themes) { + color: themed("headerColor"); + background-color: themed("headerBackgroundColor"); + border-bottom-color: themed("headerBorderColor"); + } + + .left, + .right { + flex: 1; + display: flex; + min-width: -webkit-min-content; /* Workaround to Chrome bug */ + .header-icon { + margin-right: 5px; + } + } + + .right { + justify-content: flex-end; + } + + .center { + display: flex; + align-items: center; + text-align: center; + min-width: 0; + } + + app-pop-out > button, + div > button, + div > a { + border: none; + padding: 0 10px; + text-decoration: none; + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + + @include themify($themes) { + color: themed("headerColor"); + background-color: themed("headerBackgroundColor"); + } + + &:hover, + &:focus { + @include themify($themes) { + background-color: themed("headerBackgroundHoverColor"); + color: themed("headerColor"); + } + } + + &[disabled] { + opacity: 0.65; + cursor: default !important; + } + + i + span { + margin-left: 5px; + } + } + + app-pop-out { + display: flex; + padding-right: 0.5em; + } + + .title { + font-weight: bold; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .search { + padding: 7px 10px; + width: 100%; + text-align: left; + position: relative; + display: flex; + + .bwi { + position: absolute; + top: 15px; + left: 20px; + + @include themify($themes) { + color: themed("headerInputPlaceholderColor"); + } + } + + input { + width: 100%; + margin: 0; + border: none; + padding: 5px 10px 5px 30px; + border-radius: $border-radius; + + @include themify($themes) { + background-color: themed("headerInputBackgroundColor"); + color: themed("headerInputColor"); + } + + &:focus { + border-radius: $border-radius; + outline: none; + + @include themify($themes) { + background-color: themed("headerInputBackgroundFocusColor"); + } + } + + &::-webkit-input-placeholder { + @include themify($themes) { + color: themed("headerInputPlaceholderColor"); + } + } + } + } + + .left + .search, + .left + .sr-only + .search { + padding-left: 0; + + .bwi { + left: 10px; + } + } + + .search + .right { + margin-left: -10px; + } +} + +.content { + padding: 15px; +} + +.tabs { + width: 100%; + height: 55px; + border-top: 1px solid #000000; + position: absolute; + bottom: 0; + left: 0; + right: 0; + overflow: hidden; + + @include themify($themes) { + background-color: themed("tabBackgroundColor"); + border-top-color: themed("borderColor"); + } + + ul { + display: flex; + list-style: none; + padding: 0; + margin: 0; + + li { + flex: 1; + display: inline-block; + padding: 0; + margin: 0; + + a, + button { + text-align: center; + display: block; + padding: 7px 0; + text-decoration: none; + font-size: 12px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + + @include themify($themes) { + color: themed("mutedColor"); + } + + &:hover, + &:focus { + @include themify($themes) { + background-color: themed("tabBackgroundHoverColor"); + } + } + + i { + display: block; + margin-bottom: 2px; + text-align: center; + } + } + + &.active { + a, + button { + @include themify($themes) { + color: themed("primaryColor"); + } + } + } + } + } +} + +app-root { + position: absolute; + width: 100%; + height: 100%; + z-index: 980; + @include themify($themes) { + background-color: themed("backgroundColor"); + } +} + +@media only screen and (min-width: 601px) { + app-login header { + padding: 0 calc((100% - 500px) / 2); + } + + app-login main { + padding: 0 calc((100% - 500px) / 2); + } + + app-two-factor header { + padding: 0 calc((100% - 500px) / 2); + } + + app-two-factor main { + padding: 0 calc((100% - 500px) / 2); + } + + app-lock header { + padding: 0 calc((100% - 500px) / 2); + } + + app-lock main { + padding: 0 calc((100% - 500px) / 2); + } +} + +main { + position: absolute; + top: 44px; + bottom: 0; + left: 0; + right: 0; + overflow-y: auto; + overflow-x: hidden; + + @include themify($themes) { + background-color: themed("backgroundColor"); + } + + &.no-header { + top: 0; + } + + &.flex { + display: flex; + flex-flow: column; + height: calc(100% - 44px); + + &.tab-page { + height: calc(100% - 99px); + } + } +} + +.tab-page { + main { + bottom: 55px; + } +} + +.center-content, +.no-items, +.full-loading-spinner { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + flex-direction: column; + flex-grow: 1; +} + +.no-items, +.full-loading-spinner { + text-align: center; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + + .no-items-image { + @include themify($themes) { + content: url("../images/search-desktop" + themed("svgSuffix")); + } + } + + .bwi { + margin-bottom: 10px; + + @include themify($themes) { + color: themed("disabledIconColor"); + } + } +} + +// cdk-virtual-scroll +.cdk-virtual-scroll-viewport { + width: 100%; + height: 100%; + overflow-y: auto; + overflow-x: hidden; +} + +.cdk-virtual-scroll-content-wrapper { + width: 100%; +} + +.org-filter-content { + padding-bottom: 5px; + padding-left: 7px; + .org-filter { + @include themify($themes) { + background-color: themed("backgroundColor"); + } + border: 1px solid; + padding: 7px; + border-radius: $border-radius; + } +} +.vault-select { + overflow-y: auto; + display: flex; + flex-direction: column; + + @include themify($themes) { + background-color: themed("boxBackgroundColor"); + } + margin-right: 5px; + margin-top: 1px; + width: 160px; + @include themify($themes) { + border: 1px solid themed("borderColor"); + } + border-radius: $border-radius; + button { + border: none; + background: transparent; + width: 100%; + padding: 5px 10px; + text-align: start; + @include themify($themes) { + color: themed("textColor"); + } + + a { + @include themify($themes) { + color: themed("textColor"); + } + } + + &:hover { + @include themify($themes) { + background-color: themed("boxBackgroundHoverColor"); + } + } + } + .border { + @include themify($themes) { + background: themed("borderColor"); + } + left: 10px; + width: calc(100% - 20px); + height: 1px; + position: relative; + } +} diff --git a/apps/browser/src/popup/scss/box.scss b/apps/browser/src/popup/scss/box.scss new file mode 100644 index 0000000000..9629ddae6f --- /dev/null +++ b/apps/browser/src/popup/scss/box.scss @@ -0,0 +1,694 @@ +@import "variables.scss"; + +.box { + position: relative; + width: 100%; + margin: 10px 0; + + &.first { + margin-top: 0; + } + + .box-header { + margin: 0 10px 5px 10px; + text-transform: uppercase; + display: flex; + + @include themify($themes) { + color: themed("headingColor"); + } + } + + .box-header-expandable { + padding: 0 10px; + margin-bottom: 5px; + text-transform: uppercase; + display: flex; + width: 100%; + box-sizing: border-box; + align-items: center; + + @include themify($themes) { + color: themed("headingColor"); + } + + &:hover, + &:focus, + &.active { + @include themify($themes) { + background-color: themed("boxBackgroundHoverColor"); + } + } + + .icon { + display: flex; + align-items: center; + margin-left: 5px; + + @include themify($themes) { + color: themed("headingColor"); + } + } + } + + .box-content { + border-top: 1px solid #000000; + border-bottom: 1px solid #000000; + + @include themify($themes) { + background-color: themed("boxBackgroundColor"); + border-color: themed("borderColor"); + } + + &.box-content-padded { + padding: 10px 15px; + } + + &.condensed .box-content-row, + .box-content-row.condensed { + padding-top: 5px; + padding-bottom: 5px; + } + + &.no-hover .box-content-row, + .box-content-row.no-hover { + &:hover, + &:focus { + background-color: initial !important; + } + } + } + + .box-footer { + margin: 5px 10px; + font-size: $font-size-small; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + &.list { + .box-content { + .box-content-row { + padding: 3px 10px; + text-decoration: none; + + @include themify($themes) { + color: themed("textColor"); + } + + &.padded { + padding-top: 10px; + padding-bottom: 10px; + } + + &:hover, + &:focus, + &.active { + @include themify($themes) { + background-color: themed("listItemBackgroundHoverColor"); + } + } + + &:focus { + border-left: 5px solid #000000; + padding-left: 5px; + + @include themify($themes) { + border-left-color: themed("mutedColor"); + } + } + + .action-buttons { + .row-btn { + padding-left: 5px; + padding-right: 5px; + } + } + + .text:not(.no-ellipsis), + .detail { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .row-main { + display: flex; + min-width: 0; + align-items: normal; + + .row-main-content { + min-width: 0; + } + } + } + + &.single-line { + .box-content-row { + display: flex; + padding-top: 10px; + padding-bottom: 10px; + } + } + } + } + + &.only-list { + margin-bottom: 0; + + .box-content { + border-bottom: none; + } + } + + &.full-list { + margin: 0; + + .box-content { + border: none; + } + } +} + +.stacked-boxes { + display: flex; + flex-direction: column; +} + +.box-section-divider { + border-top: 1px solid #000000; + padding-top: 10px; + + @include themify($themes) { + border-color: themed("borderColor"); + } +} + +.box-content-row { + display: block; + padding: 10px 15px; + position: relative; + z-index: 1; + + &:before { + content: ""; + position: absolute; + right: 0; + bottom: 0; + height: 1px; + width: calc(100% - 10px); + border-bottom: 1px solid #000000; + + @include themify($themes) { + border-bottom-color: themed("boxBorderColor"); + } + } + + &:last-child { + &:before { + border: none; + height: 0; + } + } + + &.override-last:last-child:before { + border-bottom: 1px solid #000000; + @include themify($themes) { + border-bottom-color: themed("boxBorderColor"); + } + } + + &.last:last-child:before { + border-bottom: 1px solid #000000; + @include themify($themes) { + border-bottom-color: themed("boxBorderColor"); + } + } + + &:after { + content: ""; + display: table; + clear: both; + } + + &:hover, + &:focus, + &.active { + @include themify($themes) { + background-color: themed("boxBackgroundHoverColor"); + } + } + + &.pre { + white-space: pre; + overflow-x: auto; + } + + &.pre-wrap { + white-space: pre-wrap; + overflow-x: auto; + } + + .row-label, + label { + font-size: $font-size-small; + display: block; + width: 100%; + margin-bottom: 5px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + .sub-label { + margin-left: 10px; + } + } + + .flex-label { + font-size: $font-size-small; + display: flex; + flex-grow: 1; + margin-bottom: 5px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + > a { + flex-grow: 0; + } + } + + .text, + .detail { + display: block; + text-align: left; + + @include themify($themes) { + color: themed("textColor"); + } + } + + .detail { + font-size: $font-size-small; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + .img-right { + float: right; + margin-left: 10px; + } + + .row-main { + flex-grow: 1; + min-width: 0; + } + + &.box-content-row-flex, + .box-content-row-flex, + &.box-content-row-checkbox, + &.box-content-row-input, + &.box-content-row-slider, + &.box-content-row-multi { + display: flex; + align-items: center; + word-break: break-all; + + &.box-content-row-word-break { + word-break: normal; + } + } + + &.box-content-row-multi { + width: 100%; + + input:not([type="checkbox"]) { + width: 100%; + } + + input + label.sr-only + select { + margin-top: 5px; + } + + > a, + > button { + padding: 8px 8px 8px 4px; + margin: 0; + + @include themify($themes) { + color: themed("dangerColor"); + } + } + } + + &.box-content-row-multi, + &.box-content-row-newmulti { + padding-left: 10px; + } + + &.box-content-row-newmulti { + @include themify($themes) { + color: themed("primaryColor"); + } + } + + &.box-content-row-checkbox, + &.box-content-row-input, + &.box-content-row-slider { + label, + .row-label { + font-size: $font-size-base; + display: block; + width: initial; + margin-bottom: 0; + + @include themify($themes) { + color: themed("textColor"); + } + } + + > span { + @include themify($themes) { + color: themed("mutedColor"); + } + } + + > input { + margin: 0 0 0 auto; + padding: 0; + } + + > * { + margin-right: 15px; + + &:last-child { + margin-right: 0; + } + } + } + + &.box-content-row-checkbox-left { + justify-content: flex-start; + + > input { + margin: 0 15px 0 0; + } + } + + &.box-content-row-input { + label { + white-space: nowrap; + } + + input { + text-align: right; + + &[type="number"] { + max-width: 50px; + } + } + } + + &.box-content-row-slider { + input[type="range"] { + height: 10px; + } + + input[type="number"] { + width: 45px; + } + + label { + white-space: nowrap; + } + } + + input:not([type="checkbox"]):not([type="radio"]), + textarea { + border: none; + width: 100%; + background-color: transparent !important; + + &::-webkit-input-placeholder { + @include themify($themes) { + color: themed("inputPlaceholderColor"); + } + } + + &:focus { + outline: none; + } + } + + select { + width: 100%; + border: 1px solid #000000; + border-radius: $border-radius; + + @include themify($themes) { + border-color: themed("inputBorderColor"); + } + } + + .action-buttons { + display: flex; + margin-left: 5px; + + &.action-buttons-fixed { + align-self: start; + margin-top: 2px; + } + + .row-btn { + cursor: pointer; + padding: 10px 8px; + background: none; + border: none; + + @include themify($themes) { + color: themed("boxRowButtonColor"); + } + + &:hover, + &:focus { + @include themify($themes) { + color: themed("boxRowButtonHoverColor"); + } + } + + &.disabled, + &[disabled] { + @include themify($themes) { + color: themed("disabledIconColor"); + opacity: themed("disabledBoxOpacity"); + } + + &:hover { + @include themify($themes) { + color: themed("disabledIconColor"); + opacity: themed("disabledBoxOpacity"); + } + } + cursor: default !important; + } + } + + &.no-pad .row-btn { + padding-top: 0; + padding-bottom: 0; + } + } + + &:not(.box-draggable-row) { + .action-buttons .row-btn:last-child { + margin-right: -3px; + } + } + + &.box-draggable-row { + &.box-content-row-checkbox { + input[type="checkbox"] + .drag-handle { + margin-left: 10px; + } + } + } + + .drag-handle { + cursor: move; + padding: 10px 2px 10px 8px; + user-select: none; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + &.cdk-drag-preview { + position: relative; + display: flex; + align-items: center; + opacity: 0.8; + + @include themify($themes) { + background-color: themed("boxBackgroundColor"); + } + } + + select.field-type { + margin: 5px 0 0 25px; + width: calc(100% - 25px); + } + + .row-sub-icon, + .row-sub-label + i.bwi { + @include themify($themes) { + color: themed("disabledIconColor"); + } + } + + .row-sub-label { + margin: 0 15px; + white-space: nowrap; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + .icon { + display: flex; + justify-content: center; + align-items: center; + min-width: 34px; + margin-left: -5px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + &.icon-small { + min-width: 25px; + } + + img { + border-radius: $border-radius; + max-height: 20px; + max-width: 20px; + } + } + + &.totp { + .totp-code { + font-family: $font-family-monospace; + font-size: 1.1em; + } + + .totp-countdown { + margin: 3px 3px 0 0; + display: block; + user-select: none; + + .totp-sec { + font-size: 0.85em; + position: absolute; + line-height: 32px; + width: 32px; + text-align: center; + } + + svg { + width: 32px; + height: 32px; + transform: rotate(-90deg); + } + + .totp-circle { + fill: none; + + @include themify($themes) { + stroke: themed("totpStrokeColor"); + } + + &.inner { + stroke-width: 3; + stroke-dasharray: 78.6; + stroke-dashoffset: 0; + } + + &.outer { + stroke-width: 2; + stroke-dasharray: 88; + stroke-dashoffset: 0; + } + } + } + + &.low { + .totp-sec, + .totp-code { + @include themify($themes) { + color: themed("dangerColor"); + } + } + + .totp-circle { + @include themify($themes) { + stroke: themed("dangerColor"); + } + } + } + } + + .progress { + display: flex; + height: 5px; + overflow: hidden; + margin: 5px -15px -10px; + + .progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + white-space: nowrap; + background-color: $brand-primary; + } + } + + .radio-group { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 5px; + + input { + flex-grow: 0; + } + + label { + margin: 0 0 0 5px; + flex-grow: 1; + font-size: $font-size-base; + display: block; + width: 100%; + + @include themify($themes) { + color: themed("textColor"); + } + } + + &.align-start { + align-items: start; + margin-top: 10px; + + label { + margin-top: -4px; + } + } + } +} diff --git a/apps/browser/src/popup/scss/buttons.scss b/apps/browser/src/popup/scss/buttons.scss new file mode 100644 index 0000000000..f4eea2a1cc --- /dev/null +++ b/apps/browser/src/popup/scss/buttons.scss @@ -0,0 +1,101 @@ +@import "variables.scss"; + +.btn { + border-radius: $border-radius; + padding: 7px 15px; + border: 1px solid #000000; + font-size: $font-size-base; + white-space: nowrap; + text-align: center; + cursor: pointer; + + @include themify($themes) { + background-color: themed("buttonBackgroundColor"); + border-color: themed("buttonBorderColor"); + color: themed("buttonColor"); + } + + &.primary { + @include themify($themes) { + color: themed("buttonPrimaryColor"); + } + } + + &.danger { + @include themify($themes) { + color: themed("buttonDangerColor"); + } + } + + &:hover:not([disabled]) { + cursor: pointer; + + @include themify($themes) { + background-color: darken(themed("buttonBackgroundColor"), 1.5%); + border-color: darken(themed("buttonBorderColor"), 17%); + color: darken(themed("buttonColor"), 10%); + } + + &.primary { + @include themify($themes) { + color: darken(themed("buttonPrimaryColor"), 6%); + } + } + + &.danger { + @include themify($themes) { + color: darken(themed("buttonDangerColor"), 6%); + } + } + } + + &:focus:not([disabled]) { + cursor: pointer; + outline: 0; + + @include themify($themes) { + background-color: darken(themed("buttonBackgroundColor"), 6%); + border-color: darken(themed("buttonBorderColor"), 25%); + } + } + + &[disabled] { + opacity: 0.65; + cursor: default !important; + } + + &.block { + display: block; + width: 100%; + } + + &.link, + &.neutral { + border: none !important; + background: none !important; + + &:focus { + text-decoration: underline; + } + } +} + +.action-buttons { + .btn { + &:focus { + outline: auto; + } + } +} + +button.box-content-row { + display: block; + width: 100%; + text-align: left; +} + +button { + border: none; + background: transparent; + color: inherit; +} diff --git a/apps/browser/src/popup/scss/environment.scss b/apps/browser/src/popup/scss/environment.scss new file mode 100644 index 0000000000..17e7c23d2e --- /dev/null +++ b/apps/browser/src/popup/scss/environment.scss @@ -0,0 +1,39 @@ +@import "variables.scss"; + +html.browser_safari { + body { + height: 360px !important; + + &.body-xs { + height: 300px !important; + } + + &.body-full { + height: 100% !important; + } + } + + header { + .search .bwi { + left: 20px; + } + + .left + .search .bwi { + left: 10px; + } + } + + app-root { + border-width: 1px; + border-style: solid; + border-color: #000000; + } + + &.theme_light app-root { + border-color: #777777; + } + + &.theme_nord app-root { + border-color: #2e3440; + } +} diff --git a/apps/browser/src/popup/scss/grid.scss b/apps/browser/src/popup/scss/grid.scss new file mode 100644 index 0000000000..8cdb29bb52 --- /dev/null +++ b/apps/browser/src/popup/scss/grid.scss @@ -0,0 +1,11 @@ +.row { + display: flex; + margin: 0 -15px; + width: 100%; +} + +.col { + flex-basis: 0; + flex-grow: 1; + padding: 0 15px; +} diff --git a/apps/browser/src/popup/scss/misc.scss b/apps/browser/src/popup/scss/misc.scss new file mode 100644 index 0000000000..8752ad7088 --- /dev/null +++ b/apps/browser/src/popup/scss/misc.scss @@ -0,0 +1,403 @@ +@import "variables.scss"; + +small, +.small { + font-size: $font-size-small; +} + +.bg-primary { + @include themify($themes) { + background-color: themed("primaryColor") !important; + } +} + +.bg-success { + @include themify($themes) { + background-color: themed("successColor") !important; + } +} + +.bg-danger { + @include themify($themes) { + background-color: themed("dangerColor") !important; + } +} + +.bg-info { + @include themify($themes) { + background-color: themed("infoColor") !important; + } +} + +.bg-warning { + @include themify($themes) { + background-color: themed("warningColor") !important; + } +} + +.text-primary { + @include themify($themes) { + color: themed("primaryColor") !important; + } +} + +.text-success { + @include themify($themes) { + color: themed("successColor") !important; + } +} + +.text-muted { + @include themify($themes) { + color: themed("mutedColor") !important; + } +} + +.text-default { + @include themify($themes) { + color: themed("textColor") !important; + } +} + +.text-danger { + @include themify($themes) { + color: themed("dangerColor") !important; + } +} + +.text-info { + @include themify($themes) { + color: themed("infoColor") !important; + } +} + +.text-warning { + @include themify($themes) { + color: themed("warningColor") !important; + } +} + +.text-center { + text-align: center; +} + +.font-weight-semibold { + font-weight: 600; +} + +p.lead { + font-size: $font-size-large; + margin-bottom: 20px; + font-weight: normal; +} + +.flex-right { + margin-left: auto; +} + +.flex-bottom { + margin-top: auto; +} + +.no-margin { + margin: 0 !important; +} + +.no-vmargin { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +.no-vpad { + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.display-block { + display: block !important; +} + +.monospaced { + font-family: $font-family-monospace; +} + +.show-whitespace { + white-space: pre-wrap; +} + +.img-responsive { + display: block; + max-width: 100%; + height: auto; +} + +.img-rounded { + border-radius: 6px; +} + +.sr-only { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + border: 0 !important; +} + +.password-wrapper { + overflow-wrap: break-word; + white-space: pre-wrap; + min-width: 0; +} + +.password-number { + @include themify($themes) { + color: themed("passwordNumberColor"); + } +} + +.password-special { + @include themify($themes) { + color: themed("passwordSpecialColor"); + } +} + +.password-character { + display: inline-flex; + flex-direction: column; + align-items: center; + width: 30px; + height: 36px; + font-weight: 600; + + &:nth-child(odd) { + @include themify($themes) { + background-color: themed("backgroundColor"); + } + } +} + +.password-count { + white-space: nowrap; + font-size: 8px; + + @include themify($themes) { + color: themed("mutedColor") !important; + } +} + +#duo-frame { + background: url("../images/loading.svg") 0 0 no-repeat; + width: 100%; + height: 470px; + margin-bottom: -10px; + + iframe { + width: 100%; + height: 100%; + border: none; + } +} + +#web-authn-frame { + background: url("../images/loading.svg") 0 0 no-repeat; + width: 100%; + height: 310px; + margin-bottom: -10px; + + iframe { + width: 100%; + height: 100%; + border: none; + } +} + +#hcaptcha_iframe { + width: 100%; + border: none; + transition: height 0.25s linear; +} + +body.linux-webauthn { + width: 485px !important; + #web-authn-frame { + iframe { + width: 375px; + margin: 0 55px; + } + } +} + +app-root > #loading { + display: flex; + text-align: center; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + color: $text-muted; + + @include themify($themes) { + color: themed("mutedColor"); + } +} + +app-vault-icon, +.app-vault-icon { + display: flex; +} + +.logo-image { + margin: 0 auto; + width: 142px; + height: 21px; + background-size: 142px 21px; + background-repeat: no-repeat; + @include themify($themes) { + background-image: url("../images/logo-" + themed("logoSuffix") + "@2x.png"); + } + @media (min-width: 219px) { + width: 189px; + height: 28px; + background-size: 189px 28px; + } + @media (min-width: 314px) { + width: 284px; + height: 43px; + background-size: 284px 43px; + } +} + +[hidden] { + display: none !important; +} + +.draggable { + cursor: move; +} + +.callout { + padding: 10px; + margin: 10px; + border: 1px solid #000000; + border-left-width: 5px; + border-radius: 3px; + @include themify($themes) { + border-color: themed("calloutBorderColor"); + background-color: themed("calloutBackgroundColor"); + } + + .callout-heading { + margin-top: 0; + } + + h3.callout-heading { + font-weight: bold; + text-transform: uppercase; + } + + &.callout-primary { + @include themify($themes) { + border-left-color: themed("primaryColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("primaryColor"); + } + } + } + + &.callout-info { + @include themify($themes) { + border-left-color: themed("infoColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("infoColor"); + } + } + } + + &.callout-danger { + @include themify($themes) { + border-left-color: themed("dangerColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("dangerColor"); + } + } + } + + &.callout-success { + @include themify($themes) { + border-left-color: themed("successColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("successColor"); + } + } + } + + &.callout-warning { + @include themify($themes) { + border-left-color: themed("warningColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("warningColor"); + } + } + } + + &.clickable { + &:hover, + &:focus, + &.active { + @include themify($themes) { + background-color: themed("boxBackgroundHoverColor"); + } + } + } + + .enforced-policy-options ul { + padding-left: 30px; + margin: 0; + } +} + +input[type="password"]::-ms-reveal { + display: none; +} + +.flex { + display: flex; + + &.flex-grow { + > * { + flex: 1; + } + } +} + +// Workaround for slow performance on external monitors on Chrome + MacOS +// See: https://bugs.chromium.org/p/chromium/issues/detail?id=971701#c64 +@keyframes redraw { + 0% { + opacity: 0.99; + } + 100% { + opacity: 1; + } +} +html.force_redraw { + animation: redraw 1s linear infinite; +} diff --git a/apps/browser/src/popup/scss/modal.scss b/apps/browser/src/popup/scss/modal.scss new file mode 100644 index 0000000000..1d86b1e880 --- /dev/null +++ b/apps/browser/src/popup/scss/modal.scss @@ -0,0 +1,356 @@ +@import "variables.scss"; + +$white: white; +$black: black; +$line-height-base: 14px; +$border-radius-lg: $border-radius; + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss + +$grid-breakpoints: ( + xs: 0, + sm: 576px, + md: 768px, + lg: 992px, + xl: 1200px, +) !default; + +$zindex-modal-backdrop: 1040 !default; +$zindex-modal: 1050 !default; + +// Padding applied to the modal body +$modal-inner-padding: 10px !default; + +$modal-dialog-margin: 0.5rem !default; +$modal-dialog-margin-y-sm-up: 1.75rem !default; + +$modal-title-line-height: $line-height-base !default; + +//$modal-content-bg: $background-color-alt !default; +$modal-content-border-color: rgba($black, 0.2) !default; +$modal-content-border-width: 1px !default; +$modal-content-box-shadow-xs: none; +$modal-content-box-shadow-sm-up: none; + +$modal-backdrop-bg: $black !default; +$modal-backdrop-opacity: 0.5 !default; +$modal-header-border-color: $border-color-dark !default; +$modal-footer-border-color: $modal-header-border-color !default; +$modal-header-border-width: $modal-content-border-width !default; +$modal-footer-border-width: $modal-header-border-width !default; +$modal-header-padding: 12px !default; + +$modal-lg: 800px !default; +$modal-md: 500px !default; +$modal-sm: 300px !default; + +$modal-transition: transform 0.3s ease-out !default; + +$close-font-size: $font-size-base * 1.5 !default; +$close-font-weight: bold !default; +$close-color: $black !default; +$close-text-shadow: 0 1px 0 $white !default; + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_breakpoints.scss + +@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) { + $min: breakpoint-min($name, $breakpoints); + + @if $min { + @media (min-width: $min) { + @content; + } + } @else { + @content; + } +} + +@function breakpoint-min($name, $breakpoints: $grid-breakpoints) { + $min: map-get($breakpoints, $name); + @return if($min != 0, $min, null); +} + +// Custom Added CSS animations + +@keyframes modalshow { + 0% { + opacity: 0; + transform: translate(0, -25%); + } + + 100% { + opacity: 1; + transform: translate(0, 0); + } +} + +@keyframes backdropshow { + 0% { + opacity: 0; + } + + 100% { + opacity: $modal-backdrop-opacity; + } +} + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_modal.scss + +// .modal-open - body class for killing the scroll +// .modal - container to scroll within +// .modal-dialog - positioning shell for the actual modal +// .modal-content - actual modal w/ bg and corners and stuff + +// Kill the scroll on the body +.modal-open { + overflow: hidden; +} + +// Container that the modal scrolls within +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: $zindex-modal; + //display: none; + overflow: hidden; + // Prevent Chrome on Windows from adding a focus outline. For details, see + // https://github.com/twbs/bootstrap/pull/10951. + outline: 0; + // We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a + // gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342 + // See also https://github.com/twbs/bootstrap/issues/17695 + .modal-open & { + overflow-x: hidden; + overflow-y: auto; + } +} + +// Shell div to position the modal with bottom padding +.modal-dialog { + position: relative; + width: auto; + margin: $modal-dialog-margin; + // allow clicks to pass through for custom click handling to close modal + pointer-events: none; + // When fading in the modal, animate it to slide down + .modal.fade & { + //@include transition($modal-transition); + //transform: translate(0, -25%); + animation: modalshow 0.3s ease-in; + } + //.modal.show & { + // transform: translate(0, 0); + //} + transform: translate(0, 0); +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - (#{$modal-dialog-margin} * 2)); +} + +// Actual modal +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog` + // counteract the pointer-events: none; in the .modal-dialog + pointer-events: auto; + //background-color: $modal-content-bg; + background-clip: padding-box; + border: $modal-content-border-width solid $modal-content-border-color; + //@include border-radius($border-radius-lg); + //@include box-shadow($modal-content-box-shadow-xs); + border-radius: $border-radius-lg; + box-shadow: $modal-content-box-shadow-xs; + // Remove focus outline from opened modal + outline: 0; + + @include themify($themes) { + background-color: themed("backgroundColorAlt"); + } +} + +// Modal background +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: $zindex-modal-backdrop; + background-color: $modal-backdrop-bg; + // Fade for backdrop + &.fade { + //opacity: 0; + animation: backdropshow 0.1s ease-in; + } + //&.show { + // opacity: $modal-backdrop-opacity; + //} + opacity: $modal-backdrop-opacity; +} + +// Modal header +// Top section of the modal w/ title and dismiss +.modal-header { + display: flex; + align-items: flex-start; // so the close btn always stays on the upper right corner + justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends + padding: $modal-header-padding $modal-inner-padding; + border-bottom: $modal-header-border-width solid $modal-header-border-color; + //@include border-top-radius($border-radius-lg); + + @include themify($themes) { + border-bottom-color: themed("borderColor"); + } + + .close { + padding: $modal-header-padding $modal-inner-padding; + // auto on the left force icon to the right even when there is no .modal-title + margin: (-$modal-header-padding) (-$modal-inner-padding) (-$modal-header-padding) auto; + } + + h5 { + font-size: $font-size-base; + font-weight: bold; + display: flex; + align-items: center; + + .bwi { + margin-right: 5px; + } + } +} + +// Title text within header +.modal-title { + margin-bottom: 0; + line-height: $modal-title-line-height; +} + +// Modal body +// Where all modal content resides (sibling of .modal-header and .modal-footer) +.modal-body { + position: relative; + // Enable `flex-grow: 1` so that the body take up as much space as possible + // when should there be a fixed height on `.modal-dialog`. + flex: 1 1 auto; + padding: $modal-inner-padding; +} + +// Footer (for actions) +.modal-footer { + display: flex; + align-items: center; // vertically center + //justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items + padding: $modal-inner-padding; + border-top: $modal-footer-border-width solid $modal-footer-border-color; + + @include themify($themes) { + border-top-color: themed("borderColor"); + } + + // Easily place margin between footer elements + button { + margin-right: 10px; + + &:last-child { + margin-right: 0; + } + } + + .right { + margin-left: auto; + display: flex; + } +} + +// Measure scrollbar width for padding body during modal show/hide +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +// Scale up the modal +@include media-breakpoint-up(sm) { + // Automatically set modal's width for larger viewports + .modal-dialog { + max-width: $modal-md; + margin: $modal-dialog-margin-y-sm-up auto; + } + + .modal-dialog-centered { + min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2)); + } + + .modal-content { + //@include box-shadow($modal-content-box-shadow-sm-up); + box-shadow: $modal-content-box-shadow-sm-up; + } + + .modal-sm { + max-width: $modal-sm; + } +} + +@include media-breakpoint-up(lg) { + .modal-lg { + max-width: $modal-lg; + } +} + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_close.scss + +.close { + float: right; + font-size: $close-font-size; + font-weight: $close-font-weight; + line-height: 1; + color: $close-color; + text-shadow: $close-text-shadow; + opacity: 0.5; + + &:hover, + &:focus { + color: $close-color; + text-decoration: none; + opacity: 0.75; + } + // Opinionated: add "hand" cursor to non-disabled .close elements + &:not(:disabled):not(.disabled) { + cursor: pointer; + } +} + +// Additional properties for button version +// iOS requires the button element instead of an anchor tag. +// If you want the anchor version, it requires `href="#"`. +// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile + +// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type +button.close { + padding: 0; + background-color: transparent; + border: 0; + -webkit-appearance: none; +} +// stylelint-enable + +// box + +.modal-content .box { + margin-top: 20px; + + &:first-child { + margin-top: 0; + } +} diff --git a/apps/browser/src/popup/scss/pages.scss b/apps/browser/src/popup/scss/pages.scss new file mode 100644 index 0000000000..74a2605b75 --- /dev/null +++ b/apps/browser/src/popup/scss/pages.scss @@ -0,0 +1,117 @@ +@import "variables.scss"; + +app-sync { + main { + .btn { + margin-bottom: 10px; + } + } +} + +app-generator .generated-block { + font-size: $font-size-large; + font-family: $font-family-monospace; + margin: 20px; + display: flex; + + .generated-wrapper { + text-align: left; + width: 100%; + min-width: 0; + white-space: pre-wrap; + word-break: break-all; + } + + .action-buttons { + display: flex; + align-self: center; + + button { + padding: 5px; + margin: -5px -5px 5px 5px; + } + } +} + +app-home { + position: fixed; + height: 100%; + width: 100%; + + .center-content { + margin-top: -50px; + height: calc(100% + 50px); + } + + img { + width: 284px; + margin: 0 auto; + } + + p.lead { + margin: 30px 0; + } + + .btn + .btn { + margin-top: 10px; + } + + a.settings-icon { + position: absolute; + top: 10px; + left: 10px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + &:not(:hover):not(:focus) { + span { + clip: rect(0 0 0 0); + clip-path: inset(50%); + height: 1px; + overflow: hidden; + position: absolute; + white-space: nowrap; + width: 1px; + } + } + + &:hover, + &:focus { + text-decoration: none; + + @include themify($themes) { + color: themed("primaryColor"); + } + } + } +} + +app-private-mode-warning { + display: block; + padding-top: 1rem; +} + +body.body-sm, +body.body-xs { + app-home { + .center-content { + margin-top: 0; + height: 100%; + } + + p.lead { + margin: 15px 0; + } + } +} + +body.body-full { + app-home { + .center-content { + margin-top: -80px; + height: calc(100% + 80px); + } + } +} diff --git a/apps/browser/src/popup/scss/plugins.scss b/apps/browser/src/popup/scss/plugins.scss new file mode 100644 index 0000000000..44a181c0dc --- /dev/null +++ b/apps/browser/src/popup/scss/plugins.scss @@ -0,0 +1,218 @@ +@import "~ngx-toastr/toastr"; +@import "~#sweetalert2"; + +@import "variables.scss"; +@import "buttons.scss"; + +// Toaster + +.toast-container { + .toast-close-button { + @include themify($themes) { + color: themed("toastTextColor"); + } + font-size: 18px; + margin-right: 4px; + } + + .ngx-toastr { + @include themify($themes) { + color: themed("toastTextColor"); + } + align-items: center; + background-image: none !important; + border-radius: $border-radius; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.35); + display: flex; + padding: 15px; + + .toast-close-button { + position: absolute; + right: 5px; + top: 0; + } + + &:hover { + box-shadow: 0 0 10px rgba(0, 0, 0, 0.6); + } + + .icon i::before { + float: left; + font-style: normal; + font-family: $icomoon-font-family; + font-size: 25px; + line-height: 20px; + padding-right: 15px; + } + + .toast-message { + p { + margin-bottom: 0.5rem; + + &:last-child { + margin-bottom: 0; + } + } + } + + &.toast-danger, + &.toast-error { + @include themify($themes) { + background-color: themed("dangerColor"); + } + + .icon i::before { + content: map_get($icons, "error"); + } + } + + &.toast-warning { + @include themify($themes) { + background-color: themed("warningColor"); + } + + .icon i::before { + content: map_get($icons, "exclamation-triangle"); + } + } + + &.toast-info { + @include themify($themes) { + background-color: themed("infoColor"); + } + + .icon i:before { + content: map_get($icons, "info-circle"); + } + } + + &.toast-success { + @include themify($themes) { + background-color: themed("successColor"); + } + + .icon i:before { + content: map_get($icons, "check"); + } + } + } +} + +// SweetAlert + +.swal2-popup { + padding: 15px; + border-radius: $border-radius; + width: 34em; + + @include themify($themes) { + background-color: themed("backgroundColorAlt"); + color: themed("textColor"); + } + + .swal2-icon { + margin: 0 auto; + width: auto; + height: auto; + border: none; + } + + .swal2-content { + margin: 0; + font-size: $font-size-base; + @include themify($themes) { + color: themed("textColor"); + } + + label.checkbox { + margin-top: 10px; + display: flex; + text-align: left; + align-items: top; + + input { + margin: 3px 5px 0 1px; + } + } + + .swal2-input, + .swal2-textarea { + border: 1px solid #000000; + border-radius: $border-radius; + margin-bottom: 0; + box-shadow: none; + // Inherit theme font-size + font-size: inherit; + + // Sweetalert 1 did not have box-shadow + &:focus { + box-shadow: none; + } + @include themify($themes) { + border-color: themed("inputBorderColor"); + color: themed("textColor"); + background-color: themed("inputBackgroundColor"); + } + &::-webkit-input-placeholder { + @include themify($themes) { + color: themed("inputPlaceholderColor"); + } + } + } + } + + i.swal-custom-icon { + display: block; + margin: 0 auto; + font-size: 35px; + } + + .swal2-title { + padding: 10px 0 15px; + margin: 0; + font-size: $font-size-large; + + @include themify($themes) { + color: themed("textColor"); + } + } + + .swal2-text { + text-align: left; // sweetalert1 behaviour + font-size: $font-size-base; + + @include themify($themes) { + color: themed("textColor"); + } + } + + > .swal2-text:first-child { + margin-top: 20px; + } + + .swal2-actions { + margin: 20px auto 0; + justify-content: flex-start; + flex-direction: row-reverse; + + button { + margin-left: 10px; + @extend .btn; + + &.swal2-confirm { + @extend .btn, .primary; + font-weight: bold; + } + } + } + + .swal2-validation-message { + margin-top: 20px; + } +} + +date-input-polyfill { + &[data-open="true"] { + z-index: 10000 !important; + } +} diff --git a/apps/browser/src/popup/scss/popup.scss b/apps/browser/src/popup/scss/popup.scss new file mode 100644 index 0000000000..8a7b648545 --- /dev/null +++ b/apps/browser/src/popup/scss/popup.scss @@ -0,0 +1,17 @@ +$icomoon-font-path: "../../../../../libs/angular/src/scss/bwicons/fonts/"; +$card-icons-base: "../../../../../libs/angular/src/images/cards/"; + +@import "../../../../../libs/angular/src/scss/webfonts.css"; +@import "../../../../../libs/angular/src/scss/bwicons/styles/style.scss"; +@import "variables.scss"; +@import "../../../../../libs/angular/src/scss/icons.scss"; +@import "base.scss"; +@import "grid.scss"; +@import "box.scss"; +@import "buttons.scss"; +@import "misc.scss"; +@import "modal.scss"; +@import "plugins.scss"; +@import "environment.scss"; +@import "pages.scss"; +@import "~@angular/cdk/overlay-prebuilt.css"; diff --git a/apps/browser/src/popup/scss/variables.scss b/apps/browser/src/popup/scss/variables.scss new file mode 100644 index 0000000000..049954bc33 --- /dev/null +++ b/apps/browser/src/popup/scss/variables.scss @@ -0,0 +1,287 @@ +@import "~nord/src/sass/nord.scss"; + +$dark-icon-themes: "theme_dark", "theme_solarizedDark", "theme_nord"; + +$font-family-sans-serif: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; +$font-size-base: 14px; +$font-size-large: 18px; +$font-size-small: 12px; +$text-color: #000000; +$border-color: #f0f0f0; +$border-color-dark: #ddd; +$list-item-hover: #fbfbfb; +$list-icon-color: #767679; +$disabled-box-opacity: 1; +$border-radius: 3px; +$line-height-base: 1.42857143; + +$gray: #555; +$gray-light: #777; +$text-muted: $gray-light; + +$brand-primary: #175ddc; +$brand-danger: #dd4b39; +$brand-success: #00a65a; +$brand-info: #555555; +$brand-warning: #bf7e16; +$brand-primary-accent: #1252a3; + +$background-color: #f0f0f0; + +$box-background-color: white; +$box-background-hover-color: $list-item-hover; +$box-border-color: $border-color; + +$button-border-color: darken($border-color-dark, 12%); +$button-background-color: white; +$button-color: lighten($text-color, 40%); +$button-color-primary: darken($brand-primary, 8%); +$button-color-danger: darken($brand-danger, 10%); + +$solarizedDarkBase03: #002b36; +$solarizedDarkBase02: #073642; +$solarizedDarkBase01: #586e75; +$solarizedDarkBase00: #657b83; +$solarizedDarkBase0: #839496; +$solarizedDarkBase1: #93a1a1; +$solarizedDarkBase2: #eee8d5; +$solarizedDarkBase3: #fdf6e3; +$solarizedDarkYellow: #b58900; +$solarizedDarkOrange: #cb4b16; +$solarizedDarkRed: #dc322f; +$solarizedDarkMagenta: #d33682; +$solarizedDarkViolet: #6c71c4; +$solarizedDarkBlue: #268bd2; +$solarizedDarkCyan: #2aa198; +$solarizedDarkGreen: #859900; + +$themes: ( + light: ( + textColor: $text-color, + borderColor: $border-color-dark, + backgroundColor: $background-color, + backgroundColorAlt: #ffffff, + scrollbarColor: rgba(100, 100, 100, 0.2), + scrollbarHoverColor: rgba(100, 100, 100, 0.4), + boxBackgroundColor: $box-background-color, + boxBackgroundHoverColor: $box-background-hover-color, + boxBorderColor: $box-border-color, + tabBackgroundColor: #ffffff, + tabBackgroundHoverColor: $list-item-hover, + headerColor: #ffffff, + headerBackgroundColor: $brand-primary, + headerBackgroundHoverColor: rgba(255, 255, 255, 0.1), + headerBorderColor: $brand-primary, + headerInputBackgroundColor: darken($brand-primary, 8%), + headerInputBackgroundFocusColor: darken($brand-primary, 10%), + headerInputColor: #ffffff, + headerInputPlaceholderColor: lighten($brand-primary, 35%), + listItemBackgroundHoverColor: $list-item-hover, + disabledIconColor: $list-icon-color, + disabledBoxOpacity: $disabled-box-opacity, + headingColor: $gray-light, + labelColor: $gray-light, + mutedColor: $text-muted, + totpStrokeColor: $brand-primary, + boxRowButtonColor: $brand-primary, + boxRowButtonHoverColor: darken($brand-primary, 10%), + inputBorderColor: darken($border-color-dark, 7%), + inputBackgroundColor: #ffffff, + inputPlaceholderColor: lighten($gray-light, 35%), + buttonBackgroundColor: $button-background-color, + buttonBorderColor: $button-border-color, + buttonColor: $button-color, + buttonPrimaryColor: $button-color-primary, + buttonDangerColor: $button-color-danger, + primaryColor: $brand-primary, + primaryAccentColor: $brand-primary-accent, + dangerColor: $brand-danger, + successColor: $brand-success, + infoColor: $brand-info, + warningColor: $brand-warning, + logoSuffix: "dark", + passwordNumberColor: #007fde, + passwordSpecialColor: #c40800, + calloutBorderColor: $border-color-dark, + calloutBackgroundColor: $box-background-color, + toastTextColor: #ffffff, + svgSuffix: "-light.svg", + ), + dark: ( + textColor: #ffffff, + borderColor: #161c26, + backgroundColor: #161c26, + backgroundColorAlt: #2f343d, + scrollbarColor: #6e788a, + scrollbarHoverColor: #8d94a5, + boxBackgroundColor: #2f343d, + boxBackgroundHoverColor: #3c424e, + boxBorderColor: #4c525f, + tabBackgroundColor: #2f343d, + tabBackgroundHoverColor: #3c424e, + headerColor: #ffffff, + headerBackgroundColor: #2f343d, + headerBackgroundHoverColor: #3c424e, + headerBorderColor: #161c26, + headerInputBackgroundColor: #3c424e, + headerInputBackgroundFocusColor: #4c525f, + headerInputColor: #ffffff, + headerInputPlaceholderColor: #bac0ce, + listItemBackgroundHoverColor: #3c424e, + disabledIconColor: #bac0ce, + disabledBoxOpacity: 0.5, + headingColor: #bac0ce, + labelColor: #bac0ce, + mutedColor: #bac0ce, + totpStrokeColor: #4c525f, + boxRowButtonColor: #bac0ce, + boxRowButtonHoverColor: #ffffff, + inputBorderColor: #4c525f, + inputBackgroundColor: #2f343d, + inputPlaceholderColor: #bac0ce, + buttonBackgroundColor: #3c424e, + buttonBorderColor: #4c525f, + buttonColor: #bac0ce, + buttonPrimaryColor: #6f9df1, + buttonDangerColor: #ff8d85, + primaryColor: #6f9df1, + primaryAccentColor: #6f9df1, + dangerColor: #ff8d85, + successColor: #52e07c, + infoColor: #a4b0c6, + warningColor: #ffeb66, + logoSuffix: "white", + passwordNumberColor: #6f9df1, + passwordSpecialColor: #ff8d85, + calloutBorderColor: #4c525f, + calloutBackgroundColor: #3c424e, + toastTextColor: #1f242e, + svgSuffix: "-dark.svg", + ), + nord: ( + textColor: $nord5, + borderColor: $nord0, + backgroundColor: $nord1, + backgroundColorAlt: $nord2, + scrollbarColor: $nord4, + scrollbarHoverColor: $nord6, + boxBackgroundColor: $nord2, + boxBackgroundHoverColor: $nord3, + boxBorderColor: $nord1, + tabBackgroundColor: $nord1, + tabBackgroundHoverColor: $nord2, + headerColor: $nord5, + headerBackgroundColor: $nord1, + headerBackgroundHoverColor: $nord2, + headerBorderColor: $nord0, + headerInputBackgroundColor: $nord6, + headerInputBackgroundFocusColor: $nord5, + headerInputColor: $nord2, + headerInputPlaceholderColor: $nord3, + listItemBackgroundHoverColor: $nord3, + disabledIconColor: $nord4, + disabledBoxOpacity: 0.5, + headingColor: $nord4, + labelColor: $nord4, + mutedColor: $nord4, + totpStrokeColor: $nord4, + boxRowButtonColor: $nord4, + boxRowButtonHoverColor: $nord6, + inputBorderColor: $nord0, + inputBackgroundColor: $nord2, + inputPlaceholderColor: lighten($nord3, 20%), + buttonBackgroundColor: $nord3, + buttonBorderColor: $nord0, + buttonColor: $nord5, + buttonPrimaryColor: $nord8, + buttonDangerColor: $nord11, + primaryColor: $nord9, + primaryAccentColor: $nord8, + dangerColor: $nord11, + successColor: $nord14, + infoColor: $nord9, + warningColor: $nord12, + logoSuffix: "white", + passwordNumberColor: $nord8, + passwordSpecialColor: $nord12, + calloutBorderColor: $nord0, + calloutBackgroundColor: $nord2, + toastTextColor: #ffffff, + svgSuffix: "-dark.svg", + ), + solarizedDark: ( + textColor: $solarizedDarkBase2, + borderColor: $solarizedDarkBase03, + backgroundColor: $solarizedDarkBase03, + backgroundColorAlt: $solarizedDarkBase02, + scrollbarColor: $solarizedDarkBase0, + scrollbarHoverColor: $solarizedDarkBase2, + boxBackgroundColor: $solarizedDarkBase03, + boxBackgroundHoverColor: $solarizedDarkBase02, + boxBorderColor: $solarizedDarkBase02, + tabBackgroundColor: $solarizedDarkBase02, + tabBackgroundHoverColor: $solarizedDarkBase01, + headerColor: $solarizedDarkBase1, + headerBackgroundColor: $solarizedDarkBase02, + headerBackgroundHoverColor: $solarizedDarkBase01, + headerBorderColor: $solarizedDarkBase03, + headerInputBackgroundColor: $solarizedDarkBase2, + headerInputBackgroundFocusColor: $solarizedDarkBase1, + headerInputColor: $solarizedDarkBase01, + headerInputPlaceholderColor: $solarizedDarkBase00, + listItemBackgroundHoverColor: $solarizedDarkBase02, + disabledIconColor: $solarizedDarkBase0, + disabledBoxOpacity: 0.5, + headingColor: $solarizedDarkBase0, + labelColor: $solarizedDarkBase0, + mutedColor: $solarizedDarkBase0, + totpStrokeColor: $solarizedDarkBase0, + boxRowButtonColor: $solarizedDarkBase0, + boxRowButtonHoverColor: $solarizedDarkBase2, + inputBorderColor: $solarizedDarkBase03, + inputBackgroundColor: $solarizedDarkBase01, + inputPlaceholderColor: lighten($solarizedDarkBase00, 20%), + buttonBackgroundColor: $solarizedDarkBase00, + buttonBorderColor: $solarizedDarkBase03, + buttonColor: $solarizedDarkBase1, + buttonPrimaryColor: $solarizedDarkCyan, + buttonDangerColor: $solarizedDarkRed, + primaryColor: $solarizedDarkGreen, + primaryAccentColor: $solarizedDarkCyan, + dangerColor: $solarizedDarkRed, + successColor: $solarizedDarkGreen, + infoColor: $solarizedDarkGreen, + warningColor: $solarizedDarkYellow, + logoSuffix: "white", + passwordNumberColor: $solarizedDarkCyan, + passwordSpecialColor: $solarizedDarkYellow, + calloutBorderColor: $solarizedDarkBase03, + calloutBackgroundColor: $solarizedDarkBase01, + toastTextColor: #ffffff, + svgSuffix: "-solarized.svg", + ), +); + +@mixin themify($themes: $themes) { + @each $theme, $map in $themes { + html.theme_#{$theme} & { + $theme-map: () !global; + @each $key, $submap in $map { + $value: map-get(map-get($themes, $theme), "#{$key}"); + $theme-map: map-merge( + $theme-map, + ( + $key: $value, + ) + ) !global; + } + @content; + $theme-map: null !global; + } + } +} + +@function themed($key) { + @return map-get($theme-map, $key); +} diff --git a/apps/browser/src/popup/send/efflux-dates.component.html b/apps/browser/src/popup/send/efflux-dates.component.html new file mode 100644 index 0000000000..81fcf8f838 --- /dev/null +++ b/apps/browser/src/popup/send/efflux-dates.component.html @@ -0,0 +1,209 @@ + +
+
+ +
+ + +
+
+ +
+
+
+ + +
+
+ +
+
+
+ +
+ + +
+
+ +
+
+
+
+ + +
+ +
+
+ +
+ + + +
+ + +
+
+ +
+ + +
+
+ + + +
+
+ + + +
+ + +
+
+ +
+ + +
+
+ + + +
+
+
diff --git a/apps/browser/src/popup/send/efflux-dates.component.ts b/apps/browser/src/popup/send/efflux-dates.component.ts new file mode 100644 index 0000000000..2683720bf0 --- /dev/null +++ b/apps/browser/src/popup/send/efflux-dates.component.ts @@ -0,0 +1,25 @@ +import { DatePipe } from "@angular/common"; +import { Component, EventEmitter, Input, Output } from "@angular/core"; +import { ControlContainer, NgForm } from "@angular/forms"; + +import { EffluxDatesComponent as BaseEffluxDatesComponent } from "jslib-angular/components/send/efflux-dates.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-send-efflux-dates", + templateUrl: "efflux-dates.component.html", + viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], +}) +export class EffluxDatesComponent extends BaseEffluxDatesComponent { + @Input() readonly inPopout: boolean; + @Output() popOutWindow = new EventEmitter(); + + constructor( + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected datePipe: DatePipe + ) { + super(i18nService, platformUtilsService, datePipe); + } +} diff --git a/apps/browser/src/popup/send/send-add-edit.component.html b/apps/browser/src/popup/send/send-add-edit.component.html new file mode 100644 index 0000000000..3fea4094d6 --- /dev/null +++ b/apps/browser/src/popup/send/send-add-edit.component.html @@ -0,0 +1,319 @@ +
+
+
+ +
+

+ {{ title }} +

+
+ +
+
+
+ + + {{ "sendDisabledWarning" | i18n }} + + + {{ "sendOptionsPolicyInEffect" | i18n }} + + + +
{{ "sendLinuxChromiumFileWarning" | i18n }}
+
{{ "sendFirefoxFileWarning" | i18n }}
+
{{ "sendSafariFileWarning" | i18n }}
+
+ +
+
+
+ + +
+
+ +
+ +
+
+
+ +
+ + +
+
+
+
+ +
+
+
+ +
{{ send.file.fileName }} ({{ send.file.sizeName }})
+
+
+ + +
+
+ +
+ +
+
+
+ + +
+
+ +
+
+ + +
+
+
+ +
+

+ {{ "share" | i18n }} +

+
+ +
+ + +
+
+
+ +
+

+ +

+
+
+ + + +
+
+
+ + +
+
+ +
+ +
+
+
+ + +
+
+
+ +
+
+
+
+ + + +
+
+ +
+
+
+ +
+ +
+
+
+ + +
+
+ +
+ +
+
+
+ + +
+
+
+ +
+
+
+ + +
+
+
+
+ +
+
+ +
+
+
+
diff --git a/apps/browser/src/popup/send/send-add-edit.component.ts b/apps/browser/src/popup/send/send-add-edit.component.ts new file mode 100644 index 0000000000..0087b0ba53 --- /dev/null +++ b/apps/browser/src/popup/send/send-add-edit.component.ts @@ -0,0 +1,145 @@ +import { DatePipe, Location } from "@angular/common"; +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { AddEditComponent as BaseAddEditComponent } from "jslib-angular/components/send/add-edit.component"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SendService } from "jslib-common/abstractions/send.service"; + +import { StateService } from "../../services/abstractions/state.service"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +@Component({ + selector: "app-send-add-edit", + templateUrl: "send-add-edit.component.html", +}) +export class SendAddEditComponent extends BaseAddEditComponent { + // Options header + showOptions = false; + // File visibility + isFirefox = false; + inPopout = false; + inSidebar = false; + isLinux = false; + isUnsupportedMac = false; + + constructor( + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + stateService: StateService, + messagingService: MessagingService, + policyService: PolicyService, + environmentService: EnvironmentService, + datePipe: DatePipe, + sendService: SendService, + private route: ActivatedRoute, + private router: Router, + private location: Location, + private popupUtilsService: PopupUtilsService, + logService: LogService + ) { + super( + i18nService, + platformUtilsService, + environmentService, + datePipe, + sendService, + messagingService, + policyService, + logService, + stateService + ); + } + + get showFileSelector(): boolean { + return !(this.editMode || this.showFilePopoutMessage); + } + + get showFilePopoutMessage(): boolean { + return ( + !this.editMode && + (this.showFirefoxFileWarning || this.showSafariFileWarning || this.showChromiumFileWarning) + ); + } + + get showFirefoxFileWarning(): boolean { + return this.isFirefox && !(this.inSidebar || this.inPopout); + } + + get showSafariFileWarning(): boolean { + return this.isSafari && !this.inPopout; + } + + // Only show this for Chromium based browsers in Linux and Mac > Big Sur + get showChromiumFileWarning(): boolean { + return ( + (this.isLinux || this.isUnsupportedMac) && + !this.isFirefox && + !(this.inSidebar || this.inPopout) + ); + } + + popOutWindow() { + this.popupUtilsService.popOut(window); + } + + async ngOnInit() { + // File visilibity + this.isFirefox = this.platformUtilsService.isFirefox(); + this.inPopout = this.popupUtilsService.inPopout(window); + this.inSidebar = this.popupUtilsService.inSidebar(window); + this.isLinux = window?.navigator?.userAgent.indexOf("Linux") !== -1; + this.isUnsupportedMac = + this.platformUtilsService.isChrome() && window?.navigator?.appVersion.includes("Mac OS X 11"); + + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (params.sendId) { + this.sendId = params.sendId; + } + if (params.type) { + const type = parseInt(params.type, null); + this.type = type; + } + await this.load(); + }); + + window.setTimeout(() => { + if (!this.editMode) { + document.getElementById("name").focus(); + } + }, 200); + } + + async submit(): Promise { + if (await super.submit()) { + this.cancel(); + return true; + } + + return false; + } + + async delete(): Promise { + if (await super.delete()) { + this.cancel(); + return true; + } + + return false; + } + + cancel() { + // If true, the window was pop'd out on the add-send page. location.back will not work + if ((window as any).previousPopupUrl.startsWith("/add-send")) { + this.router.navigate(["tabs/send"]); + } else { + this.location.back(); + } + } +} diff --git a/apps/browser/src/popup/send/send-groupings.component.html b/apps/browser/src/popup/send/send-groupings.component.html new file mode 100644 index 0000000000..72c79e7cb7 --- /dev/null +++ b/apps/browser/src/popup/send/send-groupings.component.html @@ -0,0 +1,122 @@ +
+
+ +
+

{{ "send" | i18n }}

+ +
+ +
+
+
+ + {{ "sendDisabledWarning" | i18n }} + +
+ + + +

{{ "noItemsInList" | i18n }}

+ +
+
+ +
+

+ {{ "types" | i18n }} +

+
+ + +
+
+
+

+ {{ "allSends" | i18n }} +
{{ sends.length }}
+

+
+ +
+
+
+ +
+

{{ "noItemsInList" | i18n }}

+
+
+
+ + +
+
+
+
diff --git a/apps/browser/src/popup/send/send-groupings.component.ts b/apps/browser/src/popup/send/send-groupings.component.ts new file mode 100644 index 0000000000..8aebbfcd59 --- /dev/null +++ b/apps/browser/src/popup/send/send-groupings.component.ts @@ -0,0 +1,192 @@ +import { ChangeDetectorRef, Component, NgZone } from "@angular/core"; +import { Router } from "@angular/router"; + +import { SendComponent as BaseSendComponent } from "jslib-angular/components/send/send.component"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { SendType } from "jslib-common/enums/sendType"; +import { SendView } from "jslib-common/models/view/sendView"; + +import { BrowserSendComponentState } from "../../models/browserSendComponentState"; +import { StateService } from "../../services/abstractions/state.service"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const ComponentId = "SendComponent"; + +@Component({ + selector: "app-send-groupings", + templateUrl: "send-groupings.component.html", +}) +export class SendGroupingsComponent extends BaseSendComponent { + // Header + showLeftHeader = true; + // Send Type Calculations + typeCounts = new Map(); + // State Handling + state: BrowserSendComponentState; + private loadedTimeout: number; + + constructor( + sendService: SendService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + environmentService: EnvironmentService, + ngZone: NgZone, + policyService: PolicyService, + searchService: SearchService, + private popupUtils: PopupUtilsService, + private stateService: StateService, + private router: Router, + private syncService: SyncService, + private changeDetectorRef: ChangeDetectorRef, + private broadcasterService: BroadcasterService, + logService: LogService + ) { + super( + sendService, + i18nService, + platformUtilsService, + environmentService, + ngZone, + searchService, + policyService, + logService + ); + super.onSuccessfulLoad = async () => { + this.calculateTypeCounts(); + this.selectAll(); + }; + } + + async ngOnInit() { + // Determine Header details + this.showLeftHeader = !( + this.popupUtils.inSidebar(window) && this.platformUtilsService.isFirefox() + ); + // Clear state of Send Type Component + await this.stateService.setBrowserSendTypeComponentState(null); + // Let super class finish + await super.ngOnInit(); + // Handle State Restore if necessary + const restoredScopeState = await this.restoreState(); + if (this.state?.searchText != null) { + this.searchText = this.state.searchText; + } + + if (!this.syncService.syncInProgress) { + this.load(); + } else { + this.loadedTimeout = window.setTimeout(() => { + if (!this.loaded) { + this.load(); + } + }, 5000); + } + + if (!this.syncService.syncInProgress || restoredScopeState) { + window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state?.scrollY), 0); + } + + // Load all sends if sync completed in background + this.broadcasterService.subscribe(ComponentId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + window.setTimeout(() => { + this.load(); + }, 500); + break; + default: + break; + } + + this.changeDetectorRef.detectChanges(); + }); + }); + } + + ngOnDestroy() { + // Remove timeout + if (this.loadedTimeout != null) { + window.clearTimeout(this.loadedTimeout); + } + // Save state + this.saveState(); + // Unsubscribe + this.broadcasterService.unsubscribe(ComponentId); + } + + async selectType(type: SendType) { + this.router.navigate(["/send-type"], { queryParams: { type: type } }); + } + + async selectSend(s: SendView) { + this.router.navigate(["/edit-send"], { queryParams: { sendId: s.id } }); + } + + async addSend() { + if (this.disableSend) { + return; + } + this.router.navigate(["/add-send"]); + } + + async removePassword(s: SendView): Promise { + if (this.disableSend) { + return; + } + super.removePassword(s); + } + + showSearching() { + return ( + this.hasSearched || (!this.searchPending && this.searchService.isSearchable(this.searchText)) + ); + } + + private calculateTypeCounts() { + // Create type counts + const typeCounts = new Map(); + this.sends.forEach((s) => { + if (typeCounts.has(s.type)) { + typeCounts.set(s.type, typeCounts.get(s.type) + 1); + } else { + typeCounts.set(s.type, 1); + } + }); + this.typeCounts = typeCounts; + } + + private async saveState() { + this.state = { + scrollY: this.popupUtils.getContentScrollY(window), + searchText: this.searchText, + sends: this.sends, + typeCounts: this.typeCounts, + }; + await this.stateService.setBrowserSendComponentState(this.state); + } + + private async restoreState(): Promise { + this.state = await this.stateService.getBrowserSendComponentState(); + if (this.state == null) { + return false; + } + + if (this.state.sends != null) { + this.sends = this.state.sends; + } + if (this.state.typeCounts != null) { + this.typeCounts = this.state.typeCounts; + } + + return true; + } +} diff --git a/apps/browser/src/popup/send/send-type.component.html b/apps/browser/src/popup/send/send-type.component.html new file mode 100644 index 0000000000..1e14dc151b --- /dev/null +++ b/apps/browser/src/popup/send/send-type.component.html @@ -0,0 +1,69 @@ +
+
+ +
+

{{ "send" | i18n }}

+ +
+ +
+
+
+ + {{ "sendDisabledWarning" | i18n }} + +
+ + +

{{ "noItemsInList" | i18n }}

+ +
+
+
+

+ {{ groupingTitle }} + {{ filteredSends.length }} +

+
+ + +
+
+
diff --git a/apps/browser/src/popup/send/send-type.component.ts b/apps/browser/src/popup/send/send-type.component.ts new file mode 100644 index 0000000000..8b4d5039af --- /dev/null +++ b/apps/browser/src/popup/send/send-type.component.ts @@ -0,0 +1,164 @@ +import { Location } from "@angular/common"; +import { ChangeDetectorRef, Component, NgZone } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { SendComponent as BaseSendComponent } from "jslib-angular/components/send/send.component"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { SendType } from "jslib-common/enums/sendType"; +import { SendView } from "jslib-common/models/view/sendView"; + +import { BrowserComponentState } from "../../models/browserComponentState"; +import { StateService } from "../../services/abstractions/state.service"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const ComponentId = "SendTypeComponent"; + +@Component({ + selector: "app-send-type", + templateUrl: "send-type.component.html", +}) +export class SendTypeComponent extends BaseSendComponent { + groupingTitle: string; + // State Handling + state: BrowserComponentState; + private refreshTimeout: number; + private applySavedState = true; + + constructor( + sendService: SendService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + environmentService: EnvironmentService, + ngZone: NgZone, + policyService: PolicyService, + searchService: SearchService, + private popupUtils: PopupUtilsService, + private stateService: StateService, + private route: ActivatedRoute, + private location: Location, + private changeDetectorRef: ChangeDetectorRef, + private broadcasterService: BroadcasterService, + private router: Router, + logService: LogService + ) { + super( + sendService, + i18nService, + platformUtilsService, + environmentService, + ngZone, + searchService, + policyService, + logService + ); + super.onSuccessfulLoad = async () => { + this.selectType(this.type); + }; + this.applySavedState = + (window as any).previousPopupUrl != null && + !(window as any).previousPopupUrl.startsWith("/send-type"); + } + + async ngOnInit() { + // Let super class finish + await super.ngOnInit(); + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (this.applySavedState) { + this.state = await this.stateService.getBrowserSendTypeComponentState(); + if (this.state?.searchText != null) { + this.searchText = this.state.searchText; + } + } + + if (params.type != null) { + this.type = parseInt(params.type, null); + switch (this.type) { + case SendType.Text: + this.groupingTitle = this.i18nService.t("sendTypeText"); + break; + case SendType.File: + this.groupingTitle = this.i18nService.t("sendTypeFile"); + break; + default: + break; + } + await this.load((s) => s.type === this.type); + } + + // Restore state and remove reference + if (this.applySavedState && this.state != null) { + window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state?.scrollY), 0); + } + this.stateService.setBrowserSendTypeComponentState(null); + }); + + // Refresh Send list if sync completed in background + this.broadcasterService.subscribe(ComponentId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + if (message.successfully) { + this.refreshTimeout = window.setTimeout(() => { + this.refresh(); + }, 500); + } + break; + default: + break; + } + + this.changeDetectorRef.detectChanges(); + }); + }); + } + + ngOnDestroy() { + // Remove timeout + if (this.refreshTimeout != null) { + window.clearTimeout(this.refreshTimeout); + } + // Save state + this.saveState(); + // Unsubscribe + this.broadcasterService.unsubscribe(ComponentId); + } + + async selectSend(s: SendView) { + this.router.navigate(["/edit-send"], { queryParams: { sendId: s.id } }); + } + + async addSend() { + if (this.disableSend) { + return; + } + this.router.navigate(["/add-send"], { queryParams: { type: this.type } }); + } + + async removePassword(s: SendView): Promise { + if (this.disableSend) { + return; + } + super.removePassword(s); + } + + back() { + (window as any).routeDirection = "b"; + this.location.back(); + } + + private async saveState() { + this.state = { + scrollY: this.popupUtils.getContentScrollY(window), + searchText: this.searchText, + }; + await this.stateService.setBrowserSendTypeComponentState(this.state); + } +} diff --git a/apps/browser/src/popup/services/debounceNavigationService.ts b/apps/browser/src/popup/services/debounceNavigationService.ts new file mode 100644 index 0000000000..bf1e2e83ca --- /dev/null +++ b/apps/browser/src/popup/services/debounceNavigationService.ts @@ -0,0 +1,49 @@ +import { Injectable, OnDestroy } from "@angular/core"; +import { CanActivate, NavigationEnd, NavigationStart, Router } from "@angular/router"; +import { Subscription } from "rxjs"; +import { filter, pairwise } from "rxjs/operators"; + +@Injectable() +export class DebounceNavigationService implements CanActivate, OnDestroy { + navigationStartSub: Subscription; + navigationSuccessSub: Subscription; + + private lastNavigation: NavigationStart; + private thisNavigation: NavigationStart; + private lastNavigationSuccessId: number; + + constructor(private router: Router) { + this.navigationStartSub = this.router.events + .pipe( + filter((event) => event instanceof NavigationStart), + pairwise() + ) + .subscribe( + (events: [NavigationStart, NavigationStart]) => + ([this.lastNavigation, this.thisNavigation] = events) + ); + + this.navigationSuccessSub = this.router.events + .pipe(filter((event) => event instanceof NavigationEnd)) + .subscribe((event: NavigationEnd) => (this.lastNavigationSuccessId = event.id)); + } + + async canActivate() { + return !( + this.thisNavigation?.navigationTrigger === "hashchange" && + this.lastNavigation.navigationTrigger === "popstate" && + this.lastNavigationSuccessId === this.lastNavigation.id && + this.lastNavigation.url === this.thisNavigation?.url + ); + } + + ngOnDestroy() { + if (this.navigationStartSub != null) { + this.navigationStartSub.unsubscribe(); + } + + if (this.navigationSuccessSub != null) { + this.navigationSuccessSub.unsubscribe(); + } + } +} diff --git a/apps/browser/src/popup/services/init.service.ts b/apps/browser/src/popup/services/init.service.ts new file mode 100644 index 0000000000..e128e9c090 --- /dev/null +++ b/apps/browser/src/popup/services/init.service.ts @@ -0,0 +1,62 @@ +import { Injectable } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService as LogServiceAbstraction } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { ThemeType } from "jslib-common/enums/themeType"; + +import { StateService as StateServiceAbstraction } from "../../services/abstractions/state.service"; + +import { PopupUtilsService } from "./popup-utils.service"; + +@Injectable() +export class InitService { + constructor( + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService, + private popupUtilsService: PopupUtilsService, + private stateService: StateServiceAbstraction, + private logService: LogServiceAbstraction + ) {} + + init() { + return async () => { + await this.stateService.init(); + + if (!this.popupUtilsService.inPopup(window)) { + window.document.body.classList.add("body-full"); + } else if (window.screen.availHeight < 600) { + window.document.body.classList.add("body-xs"); + } else if (window.screen.availHeight <= 800) { + window.document.body.classList.add("body-sm"); + } + + const htmlEl = window.document.documentElement; + const theme = await this.platformUtilsService.getEffectiveTheme(); + htmlEl.classList.add("theme_" + theme); + this.platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => { + const bwTheme = await this.stateService.getTheme(); + if (bwTheme == null || bwTheme === ThemeType.System) { + htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark); + htmlEl.classList.add("theme_" + sysTheme); + } + }); + htmlEl.classList.add("locale_" + this.i18nService.translationLocale); + + // Workaround for slow performance on external monitors on Chrome + MacOS + // See: https://bugs.chromium.org/p/chromium/issues/detail?id=971701#c64 + if ( + this.platformUtilsService.isChrome() && + navigator.platform.indexOf("Mac") > -1 && + this.popupUtilsService.inPopup(window) && + (window.screenLeft < 0 || + window.screenTop < 0 || + window.screenLeft > window.screen.width || + window.screenTop > window.screen.height) + ) { + htmlEl.classList.add("force_redraw"); + this.logService.info("Force redraw is on"); + } + }; + } +} diff --git a/apps/browser/src/popup/services/lock-guard.service.ts b/apps/browser/src/popup/services/lock-guard.service.ts new file mode 100644 index 0000000000..ad62951568 --- /dev/null +++ b/apps/browser/src/popup/services/lock-guard.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from "@angular/core"; + +import { LockGuard as BaseLockGuardService } from "jslib-angular/guards/lock.guard"; + +@Injectable() +export class LockGuardService extends BaseLockGuardService { + protected homepage = "tabs/current"; +} diff --git a/apps/browser/src/popup/services/password-reprompt.service.ts b/apps/browser/src/popup/services/password-reprompt.service.ts new file mode 100644 index 0000000000..33b26bfeb8 --- /dev/null +++ b/apps/browser/src/popup/services/password-reprompt.service.ts @@ -0,0 +1,10 @@ +import { Injectable } from "@angular/core"; + +import { PasswordRepromptService as BasePasswordRepromptService } from "jslib-angular/services/passwordReprompt.service"; + +import { PasswordRepromptComponent } from "../components/password-reprompt.component"; + +@Injectable() +export class PasswordRepromptService extends BasePasswordRepromptService { + component = PasswordRepromptComponent; +} diff --git a/apps/browser/src/popup/services/popup-search.service.ts b/apps/browser/src/popup/services/popup-search.service.ts new file mode 100644 index 0000000000..a6745baf0b --- /dev/null +++ b/apps/browser/src/popup/services/popup-search.service.ts @@ -0,0 +1,27 @@ +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { ConsoleLogService } from "jslib-common/services/consoleLog.service"; +import { SearchService } from "jslib-common/services/search.service"; + +export class PopupSearchService extends SearchService { + constructor( + private mainSearchService: SearchService, + cipherService: CipherService, + consoleLogService: ConsoleLogService, + i18nService: I18nService + ) { + super(cipherService, consoleLogService, i18nService); + } + + clearIndex() { + throw new Error("Not available."); + } + + indexCiphers(): Promise { + throw new Error("Not available."); + } + + getIndexForSearch() { + return this.mainSearchService.getIndexForSearch(); + } +} diff --git a/apps/browser/src/popup/services/popup-utils.service.ts b/apps/browser/src/popup/services/popup-utils.service.ts new file mode 100644 index 0000000000..3b2556b99d --- /dev/null +++ b/apps/browser/src/popup/services/popup-utils.service.ts @@ -0,0 +1,83 @@ +import { Injectable } from "@angular/core"; + +import { BrowserApi } from "../../browser/browserApi"; + +@Injectable() +export class PopupUtilsService { + constructor(private privateMode: boolean = false) {} + + inSidebar(win: Window): boolean { + return win.location.search !== "" && win.location.search.indexOf("uilocation=sidebar") > -1; + } + + inTab(win: Window): boolean { + return win.location.search !== "" && win.location.search.indexOf("uilocation=tab") > -1; + } + + inPopout(win: Window): boolean { + return win.location.search !== "" && win.location.search.indexOf("uilocation=popout") > -1; + } + + inPopup(win: Window): boolean { + return ( + win.location.search === "" || + win.location.search.indexOf("uilocation=") === -1 || + win.location.search.indexOf("uilocation=popup") > -1 + ); + } + + inPrivateMode(): boolean { + return this.privateMode; + } + + getContentScrollY(win: Window, scrollingContainer = "content"): number { + const content = win.document.getElementsByTagName(scrollingContainer)[0]; + return content.scrollTop; + } + + setContentScrollY(win: Window, scrollY: number, scrollingContainer = "content"): void { + if (scrollY != null) { + const content = win.document.getElementsByTagName(scrollingContainer)[0]; + content.scrollTop = scrollY; + } + } + + popOut(win: Window, href: string = null): void { + if (href === null) { + href = win.location.href; + } + + if (typeof chrome !== "undefined" && chrome.windows && chrome.windows.create) { + if (href.indexOf("?uilocation=") > -1) { + href = href + .replace("uilocation=popup", "uilocation=popout") + .replace("uilocation=tab", "uilocation=popout") + .replace("uilocation=sidebar", "uilocation=popout"); + } else { + const hrefParts = href.split("#"); + href = + hrefParts[0] + "?uilocation=popout" + (hrefParts.length > 0 ? "#" + hrefParts[1] : ""); + } + + const bodyRect = document.querySelector("body").getBoundingClientRect(); + chrome.windows.create({ + url: href, + type: "popup", + width: Math.round(bodyRect.width ? bodyRect.width + 60 : 375), + height: Math.round(bodyRect.height || 600), + }); + + if (this.inPopup(win)) { + BrowserApi.closePopup(win); + } + } else if (typeof chrome !== "undefined" && chrome.tabs && chrome.tabs.create) { + href = href + .replace("uilocation=popup", "uilocation=tab") + .replace("uilocation=popout", "uilocation=tab") + .replace("uilocation=sidebar", "uilocation=tab"); + chrome.tabs.create({ + url: href, + }); + } + } +} diff --git a/apps/browser/src/popup/services/services.module.ts b/apps/browser/src/popup/services/services.module.ts new file mode 100644 index 0000000000..bb38a01e12 --- /dev/null +++ b/apps/browser/src/popup/services/services.module.ts @@ -0,0 +1,269 @@ +import { APP_INITIALIZER, LOCALE_ID, NgModule } from "@angular/core"; + +import { LockGuard as BaseLockGuardService } from "jslib-angular/guards/lock.guard"; +import { UnauthGuard as BaseUnauthGuardService } from "jslib-angular/guards/unauth.guard"; +import { JslibServicesModule, SECURE_STORAGE } from "jslib-angular/services/jslib-services.module"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { AuthService as AuthServiceAbstraction } from "jslib-common/abstractions/auth.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { ExportService } from "jslib-common/abstractions/export.service"; +import { FileUploadService } from "jslib-common/abstractions/fileUpload.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { LogService as LogServiceAbstraction } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { NotificationsService } from "jslib-common/abstractions/notifications.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { ProviderService } from "jslib-common/abstractions/provider.service"; +import { SearchService as SearchServiceAbstraction } from "jslib-common/abstractions/search.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { SettingsService } from "jslib-common/abstractions/settings.service"; +import { StateService as BaseStateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { UserVerificationService } from "jslib-common/abstractions/userVerification.service"; +import { UsernameGenerationService } from "jslib-common/abstractions/usernameGeneration.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { AuthService } from "jslib-common/services/auth.service"; +import { ConsoleLogService } from "jslib-common/services/consoleLog.service"; +import { SearchService } from "jslib-common/services/search.service"; + +import MainBackground from "../../background/main.background"; +import { BrowserApi } from "../../browser/browserApi"; +import { AutofillService } from "../../services/abstractions/autofill.service"; +import { StateService as StateServiceAbstraction } from "../../services/abstractions/state.service"; +import BrowserMessagingService from "../../services/browserMessaging.service"; +import BrowserMessagingPrivateModePopupService from "../../services/browserMessagingPrivateModePopup.service"; +import { VaultFilterService } from "../../services/vaultFilter.service"; + +import { DebounceNavigationService } from "./debounceNavigationService"; +import { InitService } from "./init.service"; +import { LockGuardService } from "./lock-guard.service"; +import { PasswordRepromptService } from "./password-reprompt.service"; +import { PopupSearchService } from "./popup-search.service"; +import { PopupUtilsService } from "./popup-utils.service"; +import { UnauthGuardService } from "./unauth-guard.service"; + +const isPrivateMode = BrowserApi.getBackgroundPage() == null; +const mainBackground: MainBackground = isPrivateMode + ? createLocalBgService() + : BrowserApi.getBackgroundPage().bitwardenMain; + +function createLocalBgService() { + const localBgService = new MainBackground(true); + localBgService.bootstrap(); + return localBgService; +} + +function getBgService(service: keyof MainBackground) { + return (): T => { + return mainBackground ? (mainBackground[service] as any as T) : null; + }; +} + +@NgModule({ + imports: [JslibServicesModule], + declarations: [], + providers: [ + InitService, + DebounceNavigationService, + { + provide: LOCALE_ID, + useFactory: () => getBgService("i18nService")().translationLocale, + deps: [], + }, + { + provide: APP_INITIALIZER, + useFactory: (initService: InitService) => initService.init(), + deps: [InitService], + multi: true, + }, + { provide: BaseLockGuardService, useClass: LockGuardService }, + { provide: BaseUnauthGuardService, useClass: UnauthGuardService }, + { provide: PopupUtilsService, useFactory: () => new PopupUtilsService(isPrivateMode) }, + { + provide: MessagingService, + useFactory: () => { + return isPrivateMode + ? new BrowserMessagingPrivateModePopupService() + : new BrowserMessagingService(); + }, + }, + { + provide: TwoFactorService, + useFactory: getBgService("twoFactorService"), + deps: [], + }, + { + provide: AuthServiceAbstraction, + useFactory: getBgService("authService"), + deps: [], + }, + { + provide: SearchServiceAbstraction, + useFactory: ( + cipherService: CipherService, + logService: ConsoleLogService, + i18nService: I18nService + ) => { + return new PopupSearchService( + getBgService("searchService")(), + cipherService, + logService, + i18nService + ); + }, + deps: [CipherService, LogServiceAbstraction, I18nService], + }, + { provide: AuditService, useFactory: getBgService("auditService"), deps: [] }, + { + provide: FileUploadService, + useFactory: getBgService("fileUploadService"), + deps: [], + }, + { provide: CipherService, useFactory: getBgService("cipherService"), deps: [] }, + { + provide: CryptoFunctionService, + useFactory: getBgService("cryptoFunctionService"), + deps: [], + }, + { provide: FolderService, useFactory: getBgService("folderService"), deps: [] }, + { + provide: CollectionService, + useFactory: getBgService("collectionService"), + deps: [], + }, + { + provide: LogServiceAbstraction, + useFactory: getBgService("logService"), + deps: [], + }, + { + provide: EnvironmentService, + useFactory: getBgService("environmentService"), + deps: [], + }, + { provide: TotpService, useFactory: getBgService("totpService"), deps: [] }, + { provide: TokenService, useFactory: getBgService("tokenService"), deps: [] }, + { provide: I18nService, useFactory: getBgService("i18nService"), deps: [] }, + { provide: CryptoService, useFactory: getBgService("cryptoService"), deps: [] }, + { provide: EventService, useFactory: getBgService("eventService"), deps: [] }, + { provide: PolicyService, useFactory: getBgService("policyService"), deps: [] }, + { + provide: PlatformUtilsService, + useFactory: getBgService("platformUtilsService"), + deps: [], + }, + { + provide: PasswordGenerationService, + useFactory: getBgService("passwordGenerationService"), + deps: [], + }, + { provide: ApiService, useFactory: getBgService("apiService"), deps: [] }, + { provide: SyncService, useFactory: getBgService("syncService"), deps: [] }, + { + provide: SettingsService, + useFactory: getBgService("settingsService"), + deps: [], + }, + { + provide: StorageServiceAbstraction, + useFactory: getBgService("storageService"), + deps: [], + }, + { provide: AppIdService, useFactory: getBgService("appIdService"), deps: [] }, + { + provide: AutofillService, + useFactory: getBgService("autofillService"), + deps: [], + }, + { provide: ExportService, useFactory: getBgService("exportService"), deps: [] }, + { provide: SendService, useFactory: getBgService("sendService"), deps: [] }, + { + provide: KeyConnectorService, + useFactory: getBgService("keyConnectorService"), + deps: [], + }, + { + provide: UserVerificationService, + useFactory: getBgService("userVerificationService"), + deps: [], + }, + { + provide: VaultTimeoutService, + useFactory: getBgService("vaultTimeoutService"), + deps: [], + }, + { + provide: NotificationsService, + useFactory: getBgService("notificationsService"), + deps: [], + }, + { + provide: LogServiceAbstraction, + useFactory: getBgService("logService"), + deps: [], + }, + { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, + { + provide: OrganizationService, + useFactory: getBgService("organizationService"), + deps: [], + }, + { + provide: VaultFilterService, + useFactory: () => { + return new VaultFilterService( + getBgService("stateService")(), + getBgService("organizationService")(), + getBgService("folderService")(), + getBgService("cipherService")(), + getBgService("collectionService")(), + getBgService("policyService")() + ); + }, + deps: [], + }, + { + provide: ProviderService, + useFactory: getBgService("providerService"), + deps: [], + }, + { + provide: SECURE_STORAGE, + useFactory: getBgService("secureStorageService"), + deps: [], + }, + { + provide: StateServiceAbstraction, + useFactory: getBgService("stateService"), + deps: [], + }, + { + provide: UsernameGenerationService, + useFactory: getBgService("usernameGenerationService"), + deps: [], + }, + { + provide: BaseStateServiceAbstraction, + useExisting: StateServiceAbstraction, + deps: [], + }, + ], +}) +export class ServicesModule {} diff --git a/apps/browser/src/popup/services/unauth-guard.service.ts b/apps/browser/src/popup/services/unauth-guard.service.ts new file mode 100644 index 0000000000..71a497e03c --- /dev/null +++ b/apps/browser/src/popup/services/unauth-guard.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from "@angular/core"; + +import { UnauthGuard as BaseUnauthGuardService } from "jslib-angular/guards/unauth.guard"; + +@Injectable() +export class UnauthGuardService extends BaseUnauthGuardService { + protected homepage = "tabs/current"; +} diff --git a/apps/browser/src/popup/settings/excluded-domains.component.html b/apps/browser/src/popup/settings/excluded-domains.component.html new file mode 100644 index 0000000000..2d44de3d92 --- /dev/null +++ b/apps/browser/src/popup/settings/excluded-domains.component.html @@ -0,0 +1,88 @@ +
+
+ +

+ {{ "excludedDomains" | i18n }} +

+
+ +
+
+
+
+
+ +
+ +
+ + + + +
+
+ +
+
+
+ +
+ +
+
+
diff --git a/apps/browser/src/popup/settings/excluded-domains.component.ts b/apps/browser/src/popup/settings/excluded-domains.component.ts new file mode 100644 index 0000000000..b6a47932c9 --- /dev/null +++ b/apps/browser/src/popup/settings/excluded-domains.component.ts @@ -0,0 +1,115 @@ +import { Component, NgZone, OnDestroy, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; + +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; + +import { BrowserApi } from "../../browser/browserApi"; + +interface ExcludedDomain { + uri: string; + showCurrentUris: boolean; +} + +const BroadcasterSubscriptionId = "excludedDomains"; + +@Component({ + selector: "app-excluded-domains", + templateUrl: "excluded-domains.component.html", +}) +export class ExcludedDomainsComponent implements OnInit, OnDestroy { + excludedDomains: ExcludedDomain[] = []; + currentUris: string[]; + loadCurrentUrisTimeout: number; + + constructor( + private stateService: StateService, + private i18nService: I18nService, + private router: Router, + private broadcasterService: BroadcasterService, + private ngZone: NgZone, + private platformUtilsService: PlatformUtilsService + ) {} + + async ngOnInit() { + const savedDomains = await this.stateService.getNeverDomains(); + if (savedDomains) { + for (const uri of Object.keys(savedDomains)) { + this.excludedDomains.push({ uri: uri, showCurrentUris: false }); + } + } + + await this.loadCurrentUris(); + + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "tabChanged": + case "windowChanged": + if (this.loadCurrentUrisTimeout != null) { + window.clearTimeout(this.loadCurrentUrisTimeout); + } + this.loadCurrentUrisTimeout = window.setTimeout( + async () => await this.loadCurrentUris(), + 500 + ); + break; + default: + break; + } + }); + }); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async addUri() { + this.excludedDomains.push({ uri: "", showCurrentUris: false }); + } + + async removeUri(i: number) { + this.excludedDomains.splice(i, 1); + } + + async submit() { + const savedDomains: { [name: string]: null } = {}; + for (const domain of this.excludedDomains) { + if (domain.uri && domain.uri !== "") { + const validDomain = Utils.getHostname(domain.uri); + if (!validDomain) { + this.platformUtilsService.showToast( + "error", + null, + this.i18nService.t("excludedDomainsInvalidDomain", domain.uri) + ); + return; + } + savedDomains[validDomain] = null; + } + } + await this.stateService.setNeverDomains(savedDomains); + this.router.navigate(["/tabs/settings"]); + } + + trackByFunction(index: number, item: any) { + return index; + } + + toggleUriInput(domain: ExcludedDomain) { + domain.showCurrentUris = !domain.showCurrentUris; + } + + async loadCurrentUris() { + const tabs = await BrowserApi.tabsQuery({ windowType: "normal" }); + if (tabs) { + const uriSet = new Set(tabs.map((tab) => Utils.getHostname(tab.url))); + uriSet.delete(null); + this.currentUris = Array.from(uriSet); + } + } +} diff --git a/apps/browser/src/popup/settings/export.component.html b/apps/browser/src/popup/settings/export.component.html new file mode 100644 index 0000000000..ee74c4f7d9 --- /dev/null +++ b/apps/browser/src/popup/settings/export.component.html @@ -0,0 +1,40 @@ +
+
+ +

+ {{ "exportVault" | i18n }} +

+
+ +
+
+
+ + {{ "personalVaultExportPolicyInEffect" | i18n }} + + + +
+
+
+ + +
+ + +
+ +
+
+
diff --git a/apps/browser/src/popup/settings/export.component.ts b/apps/browser/src/popup/settings/export.component.ts new file mode 100644 index 0000000000..104f298e14 --- /dev/null +++ b/apps/browser/src/popup/settings/export.component.ts @@ -0,0 +1,50 @@ +import { Component } from "@angular/core"; +import { FormBuilder } from "@angular/forms"; +import { Router } from "@angular/router"; + +import { ExportComponent as BaseExportComponent } from "jslib-angular/components/export.component"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { ExportService } from "jslib-common/abstractions/export.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { UserVerificationService } from "jslib-common/abstractions/userVerification.service"; + +@Component({ + selector: "app-export", + templateUrl: "export.component.html", +}) +export class ExportComponent extends BaseExportComponent { + constructor( + cryptoService: CryptoService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + exportService: ExportService, + eventService: EventService, + policyService: PolicyService, + private router: Router, + logService: LogService, + userVerificationService: UserVerificationService, + formBuilder: FormBuilder + ) { + super( + cryptoService, + i18nService, + platformUtilsService, + exportService, + eventService, + policyService, + window, + logService, + userVerificationService, + formBuilder + ); + } + + protected saved() { + super.saved(); + this.router.navigate(["/tabs/settings"]); + } +} diff --git a/apps/browser/src/popup/settings/folder-add-edit.component.html b/apps/browser/src/popup/settings/folder-add-edit.component.html new file mode 100644 index 0000000000..3999f6fb88 --- /dev/null +++ b/apps/browser/src/popup/settings/folder-add-edit.component.html @@ -0,0 +1,53 @@ +
+
+ +

+ {{ title }} +

+
+ +
+
+
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
diff --git a/apps/browser/src/popup/settings/folder-add-edit.component.ts b/apps/browser/src/popup/settings/folder-add-edit.component.ts new file mode 100644 index 0000000000..d00eefcb79 --- /dev/null +++ b/apps/browser/src/popup/settings/folder-add-edit.component.ts @@ -0,0 +1,52 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { FolderAddEditComponent as BaseFolderAddEditComponent } from "jslib-angular/components/folder-add-edit.component"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-folder-add-edit", + templateUrl: "folder-add-edit.component.html", +}) +export class FolderAddEditComponent extends BaseFolderAddEditComponent { + constructor( + folderService: FolderService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + private router: Router, + private route: ActivatedRoute, + logService: LogService + ) { + super(folderService, i18nService, platformUtilsService, logService); + } + + async ngOnInit() { + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (params.folderId) { + this.folderId = params.folderId; + } + await this.init(); + }); + } + + async submit(): Promise { + if (await super.submit()) { + this.router.navigate(["/folders"]); + return true; + } + + return false; + } + + async delete(): Promise { + const confirmed = await super.delete(); + if (confirmed) { + this.router.navigate(["/folders"]); + } + return confirmed; + } +} diff --git a/apps/browser/src/popup/settings/folders.component.html b/apps/browser/src/popup/settings/folders.component.html new file mode 100644 index 0000000000..47b6f78a1d --- /dev/null +++ b/apps/browser/src/popup/settings/folders.component.html @@ -0,0 +1,39 @@ +
+ +

+ {{ "folders" | i18n }} +

+
+ +
+
+
+
+
+ +
+
+
+

{{ "noFolders" | i18n }}

+
+
diff --git a/apps/browser/src/popup/settings/folders.component.ts b/apps/browser/src/popup/settings/folders.component.ts new file mode 100644 index 0000000000..dd8e7566a5 --- /dev/null +++ b/apps/browser/src/popup/settings/folders.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; + +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { FolderView } from "jslib-common/models/view/folderView"; + +@Component({ + selector: "app-folders", + templateUrl: "folders.component.html", +}) +export class FoldersComponent implements OnInit { + folders: FolderView[]; + + constructor(private folderService: FolderService, private router: Router) {} + + async ngOnInit() { + this.folders = await this.folderService.getAllDecrypted(); + // Remove "No Folder" + if (this.folders.length > 0) { + this.folders = this.folders.slice(0, this.folders.length - 1); + } + } + + folderSelected(folder: FolderView) { + this.router.navigate(["/edit-folder"], { queryParams: { folderId: folder.id } }); + } + + addFolder() { + this.router.navigate(["/add-folder"]); + } +} diff --git a/apps/browser/src/popup/settings/options.component.html b/apps/browser/src/popup/settings/options.component.html new file mode 100644 index 0000000000..4281c97e52 --- /dev/null +++ b/apps/browser/src/popup/settings/options.component.html @@ -0,0 +1,258 @@ +
+ +

+ {{ "options" | i18n }} +

+
+
+
+
+

+ +

+
+ +
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+

+ +

+
+ +
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
+

+ +

+
+ +
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ +
+
+
diff --git a/apps/browser/src/popup/settings/options.component.ts b/apps/browser/src/popup/settings/options.component.ts new file mode 100644 index 0000000000..8c3ea8cdc4 --- /dev/null +++ b/apps/browser/src/popup/settings/options.component.ts @@ -0,0 +1,159 @@ +import { Component, OnInit } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { ThemeType } from "jslib-common/enums/themeType"; +import { UriMatchType } from "jslib-common/enums/uriMatchType"; + +@Component({ + selector: "app-options", + templateUrl: "options.component.html", +}) +export class OptionsComponent implements OnInit { + disableFavicon = false; + disableBadgeCounter = false; + enableAutoFillOnPageLoad = false; + autoFillOnPageLoadDefault = false; + autoFillOnPageLoadOptions: any[]; + disableAutoTotpCopy = false; + disableContextMenuItem = false; + disableAddLoginNotification = false; + disableChangedPasswordNotification = false; + dontShowCards = false; + dontShowIdentities = false; + showClearClipboard = true; + theme: ThemeType; + themeOptions: any[]; + defaultUriMatch = UriMatchType.Domain; + uriMatchOptions: any[]; + clearClipboard: number; + clearClipboardOptions: any[]; + showGeneral = true; + showAutofill = true; + showDisplay = true; + + constructor( + private messagingService: MessagingService, + private stateService: StateService, + private totpService: TotpService, + i18nService: I18nService + ) { + this.themeOptions = [ + { name: i18nService.t("default"), value: ThemeType.System }, + { name: i18nService.t("light"), value: ThemeType.Light }, + { name: i18nService.t("dark"), value: ThemeType.Dark }, + { name: "Nord", value: ThemeType.Nord }, + { name: i18nService.t("solarizedDark"), value: ThemeType.SolarizedDark }, + ]; + this.uriMatchOptions = [ + { name: i18nService.t("baseDomain"), value: UriMatchType.Domain }, + { name: i18nService.t("host"), value: UriMatchType.Host }, + { name: i18nService.t("startsWith"), value: UriMatchType.StartsWith }, + { name: i18nService.t("regEx"), value: UriMatchType.RegularExpression }, + { name: i18nService.t("exact"), value: UriMatchType.Exact }, + { name: i18nService.t("never"), value: UriMatchType.Never }, + ]; + this.clearClipboardOptions = [ + { name: i18nService.t("never"), value: null }, + { name: i18nService.t("tenSeconds"), value: 10 }, + { name: i18nService.t("twentySeconds"), value: 20 }, + { name: i18nService.t("thirtySeconds"), value: 30 }, + { name: i18nService.t("oneMinute"), value: 60 }, + { name: i18nService.t("twoMinutes"), value: 120 }, + { name: i18nService.t("fiveMinutes"), value: 300 }, + ]; + this.autoFillOnPageLoadOptions = [ + { name: i18nService.t("autoFillOnPageLoadYes"), value: true }, + { name: i18nService.t("autoFillOnPageLoadNo"), value: false }, + ]; + } + + async ngOnInit() { + this.enableAutoFillOnPageLoad = await this.stateService.getEnableAutoFillOnPageLoad(); + + this.autoFillOnPageLoadDefault = + (await this.stateService.getAutoFillOnPageLoadDefault()) ?? true; + + this.disableAddLoginNotification = await this.stateService.getDisableAddLoginNotification(); + + this.disableChangedPasswordNotification = + await this.stateService.getDisableChangedPasswordNotification(); + + this.disableContextMenuItem = await this.stateService.getDisableContextMenuItem(); + + this.dontShowCards = await this.stateService.getDontShowCardsCurrentTab(); + this.dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab(); + + this.disableAutoTotpCopy = !(await this.totpService.isAutoCopyEnabled()); + + this.disableFavicon = await this.stateService.getDisableFavicon(); + + this.disableBadgeCounter = await this.stateService.getDisableBadgeCounter(); + + this.theme = await this.stateService.getTheme(); + + const defaultUriMatch = await this.stateService.getDefaultUriMatch(); + this.defaultUriMatch = defaultUriMatch == null ? UriMatchType.Domain : defaultUriMatch; + + this.clearClipboard = await this.stateService.getClearClipboard(); + } + + async updateAddLoginNotification() { + await this.stateService.setDisableAddLoginNotification(this.disableAddLoginNotification); + } + + async updateChangedPasswordNotification() { + await this.stateService.setDisableChangedPasswordNotification( + this.disableChangedPasswordNotification + ); + } + + async updateDisableContextMenuItem() { + await this.stateService.setDisableContextMenuItem(this.disableContextMenuItem); + this.messagingService.send("bgUpdateContextMenu"); + } + + async updateAutoTotpCopy() { + await this.stateService.setDisableAutoTotpCopy(this.disableAutoTotpCopy); + } + + async updateAutoFillOnPageLoad() { + await this.stateService.setEnableAutoFillOnPageLoad(this.enableAutoFillOnPageLoad); + } + + async updateAutoFillOnPageLoadDefault() { + await this.stateService.setAutoFillOnPageLoadDefault(this.autoFillOnPageLoadDefault); + } + + async updateDisableFavicon() { + await this.stateService.setDisableFavicon(this.disableFavicon); + } + + async updateDisableBadgeCounter() { + await this.stateService.setDisableBadgeCounter(this.disableBadgeCounter); + this.messagingService.send("bgUpdateContextMenu"); + } + + async updateShowCards() { + await this.stateService.setDontShowCardsCurrentTab(this.dontShowCards); + } + + async updateShowIdentities() { + await this.stateService.setDontShowIdentitiesCurrentTab(this.dontShowIdentities); + } + + async saveTheme() { + await this.stateService.setTheme(this.theme); + window.setTimeout(() => window.location.reload(), 200); + } + + async saveDefaultUriMatch() { + await this.stateService.setDefaultUriMatch(this.defaultUriMatch); + } + + async saveClearClipboard() { + await this.stateService.setClearClipboard(this.clearClipboard); + } +} diff --git a/apps/browser/src/popup/settings/premium.component.html b/apps/browser/src/popup/settings/premium.component.html new file mode 100644 index 0000000000..a12fd370d2 --- /dev/null +++ b/apps/browser/src/popup/settings/premium.component.html @@ -0,0 +1,73 @@ +
+ +

+ {{ "premiumMembership" | i18n }} +

+
+
+
+
+ +

{{ "premiumNotCurrentMember" | i18n }}

+

{{ "premiumSignUpAndGet" | i18n }}

+
    +
  • + + {{ "ppremiumSignUpStorage" | i18n }} +
  • +
  • + + {{ "ppremiumSignUpTwoStep" | i18n }} +
  • +
  • + + {{ "ppremiumSignUpReports" | i18n }} +
  • +
  • + + {{ "ppremiumSignUpTotp" | i18n }} +
  • +
  • + + {{ "ppremiumSignUpSupport" | i18n }} +
  • +
  • + + {{ "ppremiumSignUpFuture" | i18n }} +
  • +
+

{{ priceString }}

+ + +
+ +

{{ "premiumCurrentMember" | i18n }}

+

{{ "premiumCurrentMemberThanks" | i18n }}

+ +
+
+
diff --git a/apps/browser/src/popup/settings/premium.component.ts b/apps/browser/src/popup/settings/premium.component.ts new file mode 100644 index 0000000000..040d872130 --- /dev/null +++ b/apps/browser/src/popup/settings/premium.component.ts @@ -0,0 +1,35 @@ +import { CurrencyPipe } from "@angular/common"; +import { Component } from "@angular/core"; + +import { PremiumComponent as BasePremiumComponent } from "jslib-angular/components/premium.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Component({ + selector: "app-premium", + templateUrl: "premium.component.html", +}) +export class PremiumComponent extends BasePremiumComponent { + priceString: string; + + constructor( + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + apiService: ApiService, + stateService: StateService, + logService: LogService, + private currencyPipe: CurrencyPipe + ) { + super(i18nService, platformUtilsService, apiService, logService, stateService); + + // Support old price string. Can be removed in future once all translations are properly updated. + const thePrice = this.currencyPipe.transform(this.price, "$"); + this.priceString = i18nService.t("premiumPrice", thePrice); + if (this.priceString.indexOf("%price%") > -1) { + this.priceString = this.priceString.replace("%price%", thePrice); + } + } +} diff --git a/apps/browser/src/popup/settings/settings.component.html b/apps/browser/src/popup/settings/settings.component.html new file mode 100644 index 0000000000..3f441835c5 --- /dev/null +++ b/apps/browser/src/popup/settings/settings.component.html @@ -0,0 +1,226 @@ +
+
+ +
+

+ {{ "settings" | i18n }} +

+
+
+
+ +
+

{{ "security" | i18n }}

+
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+
+
+

{{ "account" | i18n }}

+
+ +
+
+ +
+ {{ "premiumMembership" | i18n }} +
+ +
+ + + +
+
+
+

{{ "tools" | i18n }}

+
+ + + +
+
+
+

{{ "other" | i18n }}

+
+ +
{{ "options" | i18n }}
+ +
+ + + + +
+ +
+
diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts new file mode 100644 index 0000000000..a616b39a41 --- /dev/null +++ b/apps/browser/src/popup/settings/settings.component.ts @@ -0,0 +1,420 @@ +import { Component, ElementRef, OnInit, ViewChild } from "@angular/core"; +import { FormControl } from "@angular/forms"; +import { Router } from "@angular/router"; +import Swal from "sweetalert2"; + +import { ModalService } from "jslib-angular/services/modal.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { DeviceType } from "jslib-common/enums/deviceType"; + +import { BrowserApi } from "../../browser/browserApi"; +import { BiometricErrors, BiometricErrorTypes } from "../../models/biometricErrors"; +import { SetPinComponent } from "../components/set-pin.component"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const RateUrls = { + [DeviceType.ChromeExtension]: + "https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews", + [DeviceType.FirefoxExtension]: + "https://addons.mozilla.org/en-US/firefox/addon/bitwarden-password-manager/#reviews", + [DeviceType.OperaExtension]: + "https://addons.opera.com/en/extensions/details/bitwarden-free-password-manager/#feedback-container", + [DeviceType.EdgeExtension]: + "https://microsoftedge.microsoft.com/addons/detail/jbkfoedolllekgbhcbcoahefnbanhhlh", + [DeviceType.VivaldiExtension]: + "https://chrome.google.com/webstore/detail/bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb/reviews", + [DeviceType.SafariExtension]: "https://apps.apple.com/app/bitwarden/id1352778147", +}; + +@Component({ + selector: "app-settings", + templateUrl: "settings.component.html", +}) +export class SettingsComponent implements OnInit { + @ViewChild("vaultTimeoutActionSelect", { read: ElementRef, static: true }) + vaultTimeoutActionSelectRef: ElementRef; + vaultTimeouts: any[]; + vaultTimeoutActions: any[]; + vaultTimeoutAction: string; + pin: boolean = null; + supportsBiometric: boolean; + biometric = false; + disableAutoBiometricsPrompt = true; + previousVaultTimeout: number = null; + showChangeMasterPass = true; + + vaultTimeout: FormControl = new FormControl(null); + + constructor( + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService, + private vaultTimeoutService: VaultTimeoutService, + public messagingService: MessagingService, + private router: Router, + private environmentService: EnvironmentService, + private cryptoService: CryptoService, + private stateService: StateService, + private popupUtilsService: PopupUtilsService, + private modalService: ModalService, + private keyConnectorService: KeyConnectorService + ) {} + + async ngOnInit() { + const showOnLocked = + !this.platformUtilsService.isFirefox() && !this.platformUtilsService.isSafari(); + + this.vaultTimeouts = [ + { name: this.i18nService.t("immediately"), value: 0 }, + { name: this.i18nService.t("oneMinute"), value: 1 }, + { name: this.i18nService.t("fiveMinutes"), value: 5 }, + { name: this.i18nService.t("fifteenMinutes"), value: 15 }, + { name: this.i18nService.t("thirtyMinutes"), value: 30 }, + { name: this.i18nService.t("oneHour"), value: 60 }, + { name: this.i18nService.t("fourHours"), value: 240 }, + // { name: i18nService.t('onIdle'), value: -4 }, + // { name: i18nService.t('onSleep'), value: -3 }, + ]; + + if (showOnLocked) { + this.vaultTimeouts.push({ name: this.i18nService.t("onLocked"), value: -2 }); + } + + this.vaultTimeouts.push({ name: this.i18nService.t("onRestart"), value: -1 }); + this.vaultTimeouts.push({ name: this.i18nService.t("never"), value: null }); + + this.vaultTimeoutActions = [ + { name: this.i18nService.t("lock"), value: "lock" }, + { name: this.i18nService.t("logOut"), value: "logOut" }, + ]; + + let timeout = await this.vaultTimeoutService.getVaultTimeout(); + if (timeout != null) { + if (timeout === -2 && !showOnLocked) { + timeout = -1; + } + this.vaultTimeout.setValue(timeout); + } + this.previousVaultTimeout = this.vaultTimeout.value; + this.vaultTimeout.valueChanges.subscribe(async (value) => { + await this.saveVaultTimeout(value); + }); + + const action = await this.stateService.getVaultTimeoutAction(); + this.vaultTimeoutAction = action == null ? "lock" : action; + + const pinSet = await this.vaultTimeoutService.isPinLockSet(); + this.pin = pinSet[0] || pinSet[1]; + + this.supportsBiometric = await this.platformUtilsService.supportsBiometric(); + this.biometric = await this.vaultTimeoutService.isBiometricLockSet(); + this.disableAutoBiometricsPrompt = + (await this.stateService.getDisableAutoBiometricsPrompt()) ?? true; + this.showChangeMasterPass = !(await this.keyConnectorService.getUsesKeyConnector()); + } + + async saveVaultTimeout(newValue: number) { + if (newValue == null) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("neverLockWarning"), + null, + this.i18nService.t("yes"), + this.i18nService.t("cancel"), + "warning" + ); + if (!confirmed) { + this.vaultTimeout.setValue(this.previousVaultTimeout); + return; + } + } + + if (!this.vaultTimeout.valid) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("vaultTimeoutToLarge")); + return; + } + + this.previousVaultTimeout = this.vaultTimeout.value; + + await this.vaultTimeoutService.setVaultTimeoutOptions( + this.vaultTimeout.value, + this.vaultTimeoutAction + ); + if (this.previousVaultTimeout == null) { + this.messagingService.send("bgReseedStorage"); + } + } + + async saveVaultTimeoutAction(newValue: string) { + if (newValue === "logOut") { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("vaultTimeoutLogOutConfirmation"), + this.i18nService.t("vaultTimeoutLogOutConfirmationTitle"), + this.i18nService.t("yes"), + this.i18nService.t("cancel"), + "warning" + ); + if (!confirmed) { + this.vaultTimeoutActions.forEach((option: any, i) => { + if (option.value === this.vaultTimeoutAction) { + this.vaultTimeoutActionSelectRef.nativeElement.value = + i + ": " + this.vaultTimeoutAction; + } + }); + return; + } + } + + if (!this.vaultTimeout.valid) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("vaultTimeoutToLarge")); + return; + } + + this.vaultTimeoutAction = newValue; + await this.vaultTimeoutService.setVaultTimeoutOptions( + this.vaultTimeout.value, + this.vaultTimeoutAction + ); + } + + async updatePin() { + if (this.pin) { + const ref = this.modalService.open(SetPinComponent, { allowMultipleModals: true }); + + if (ref == null) { + this.pin = false; + return; + } + + this.pin = await ref.onClosedPromise(); + } else { + await this.cryptoService.clearPinProtectedKey(); + await this.vaultTimeoutService.clear(); + } + } + + async updateBiometric() { + if (this.biometric && this.supportsBiometric) { + let granted; + try { + granted = await BrowserApi.requestPermission({ permissions: ["nativeMessaging"] }); + } catch (e) { + // eslint-disable-next-line + console.error(e); + + if (this.platformUtilsService.isFirefox() && this.popupUtilsService.inSidebar(window)) { + await this.platformUtilsService.showDialog( + this.i18nService.t("nativeMessaginPermissionSidebarDesc"), + this.i18nService.t("nativeMessaginPermissionSidebarTitle"), + this.i18nService.t("ok"), + null + ); + this.biometric = false; + return; + } + } + + if (!granted) { + await this.platformUtilsService.showDialog( + this.i18nService.t("nativeMessaginPermissionErrorDesc"), + this.i18nService.t("nativeMessaginPermissionErrorTitle"), + this.i18nService.t("ok"), + null + ); + this.biometric = false; + return; + } + + const submitted = Swal.fire({ + heightAuto: false, + buttonsStyling: false, + titleText: this.i18nService.t("awaitDesktop"), + text: this.i18nService.t("awaitDesktopDesc"), + icon: "info", + iconHtml: '', + showCancelButton: true, + cancelButtonText: this.i18nService.t("cancel"), + showConfirmButton: false, + allowOutsideClick: false, + }); + + await this.stateService.setBiometricAwaitingAcceptance(true); + await this.cryptoService.toggleKey(); + + await Promise.race([ + submitted.then(async (result) => { + if (result.dismiss === Swal.DismissReason.cancel) { + this.biometric = false; + await this.stateService.setBiometricAwaitingAcceptance(null); + } + }), + this.platformUtilsService + .authenticateBiometric() + .then((result) => { + this.biometric = result; + + Swal.close(); + if (this.biometric === false) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorEnableBiometricTitle"), + this.i18nService.t("errorEnableBiometricDesc") + ); + } + }) + .catch((e) => { + // Handle connection errors + this.biometric = false; + + const error = BiometricErrors[e as BiometricErrorTypes]; + + this.platformUtilsService.showDialog( + this.i18nService.t(error.description), + this.i18nService.t(error.title), + this.i18nService.t("ok"), + null, + "error" + ); + }), + ]); + } else { + await this.stateService.setBiometricUnlock(null); + await this.stateService.setBiometricLocked(false); + } + } + + async updateAutoBiometricsPrompt() { + await this.stateService.setDisableAutoBiometricsPrompt(this.disableAutoBiometricsPrompt); + } + + async lock() { + await this.vaultTimeoutService.lock(true); + } + + async logOut() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("logOutConfirmation"), + this.i18nService.t("logOut"), + this.i18nService.t("yes"), + this.i18nService.t("cancel") + ); + if (confirmed) { + this.messagingService.send("logout"); + } + } + + async changePassword() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("changeMasterPasswordConfirmation"), + this.i18nService.t("changeMasterPassword"), + this.i18nService.t("yes"), + this.i18nService.t("cancel") + ); + if (confirmed) { + BrowserApi.createNewTab( + "https://bitwarden.com/help/master-password/#change-your-master-password" + ); + } + } + + async twoStep() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("twoStepLoginConfirmation"), + this.i18nService.t("twoStepLogin"), + this.i18nService.t("yes"), + this.i18nService.t("cancel") + ); + if (confirmed) { + BrowserApi.createNewTab("https://bitwarden.com/help/setup-two-step-login/"); + } + } + + async share() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("learnOrgConfirmation"), + this.i18nService.t("learnOrg"), + this.i18nService.t("yes"), + this.i18nService.t("cancel") + ); + if (confirmed) { + BrowserApi.createNewTab("https://bitwarden.com/help/about-organizations/"); + } + } + + async webVault() { + const url = this.environmentService.getWebVaultUrl(); + BrowserApi.createNewTab(url); + } + + import() { + BrowserApi.createNewTab("https://bitwarden.com/help/import-data/"); + } + + export() { + this.router.navigate(["/export"]); + } + + help() { + BrowserApi.createNewTab("https://bitwarden.com/help/"); + } + + about() { + const year = new Date().getFullYear(); + const versionText = document.createTextNode( + this.i18nService.t("version") + ": " + BrowserApi.getApplicationVersion() + ); + const div = document.createElement("div"); + div.innerHTML = + `

+

Bitwarden
© Bitwarden Inc. 2015-` + + year + + `

`; + div.appendChild(versionText); + + Swal.fire({ + heightAuto: false, + buttonsStyling: false, + html: div, + showConfirmButton: false, + showCancelButton: true, + cancelButtonText: this.i18nService.t("close"), + }); + } + + async fingerprint() { + const fingerprint = await this.cryptoService.getFingerprint( + await this.stateService.getUserId() + ); + const p = document.createElement("p"); + p.innerText = this.i18nService.t("yourAccountsFingerprint") + ":"; + const p2 = document.createElement("p"); + p2.innerText = fingerprint.join("-"); + const div = document.createElement("div"); + div.appendChild(p); + div.appendChild(p2); + + const result = await Swal.fire({ + heightAuto: false, + buttonsStyling: false, + html: div, + showCancelButton: true, + cancelButtonText: this.i18nService.t("close"), + showConfirmButton: true, + confirmButtonText: this.i18nService.t("learnMore"), + }); + + if (result.value) { + this.platformUtilsService.launchUri("https://bitwarden.com/help/fingerprint-phrase/"); + } + } + + rate() { + const deviceType = this.platformUtilsService.getDevice(); + BrowserApi.createNewTab((RateUrls as any)[deviceType]); + } +} diff --git a/apps/browser/src/popup/settings/sync.component.html b/apps/browser/src/popup/settings/sync.component.html new file mode 100644 index 0000000000..74f1c0ea87 --- /dev/null +++ b/apps/browser/src/popup/settings/sync.component.html @@ -0,0 +1,28 @@ +
+ +

+ {{ "sync" | i18n }} +

+
+
+
+
+ +

{{ "lastSync" | i18n }} {{ lastSync }}

+
+
diff --git a/apps/browser/src/popup/settings/sync.component.ts b/apps/browser/src/popup/settings/sync.component.ts new file mode 100644 index 0000000000..c0f9ae7959 --- /dev/null +++ b/apps/browser/src/popup/settings/sync.component.ts @@ -0,0 +1,44 @@ +import { Component, OnInit } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +@Component({ + selector: "app-sync", + templateUrl: "sync.component.html", +}) +export class SyncComponent implements OnInit { + lastSync = "--"; + syncPromise: Promise; + + constructor( + private syncService: SyncService, + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService + ) {} + + async ngOnInit() { + await this.setLastSync(); + } + + async sync() { + this.syncPromise = this.syncService.fullSync(true); + const success = await this.syncPromise; + if (success) { + await this.setLastSync(); + this.platformUtilsService.showToast("success", null, this.i18nService.t("syncingComplete")); + } else { + this.platformUtilsService.showToast("error", null, this.i18nService.t("syncingFailed")); + } + } + + async setLastSync() { + const last = await this.syncService.getLastSync(); + if (last != null) { + this.lastSync = last.toLocaleDateString() + " " + last.toLocaleTimeString(); + } else { + this.lastSync = this.i18nService.t("never"); + } + } +} diff --git a/apps/browser/src/popup/settings/vault-timeout-input.component.html b/apps/browser/src/popup/settings/vault-timeout-input.component.html new file mode 100644 index 0000000000..68b5665073 --- /dev/null +++ b/apps/browser/src/popup/settings/vault-timeout-input.component.html @@ -0,0 +1,48 @@ + + {{ "vaultTimeoutPolicyInEffect" | i18n: vaultTimeoutPolicyHours:vaultTimeoutPolicyMinutes }} + + +
+
+ + +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
diff --git a/apps/browser/src/popup/settings/vault-timeout-input.component.ts b/apps/browser/src/popup/settings/vault-timeout-input.component.ts new file mode 100644 index 0000000000..8eb308b4c0 --- /dev/null +++ b/apps/browser/src/popup/settings/vault-timeout-input.component.ts @@ -0,0 +1,22 @@ +import { Component } from "@angular/core"; +import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from "@angular/forms"; + +import { VaultTimeoutInputComponent as VaultTimeoutInputComponentBase } from "jslib-angular/components/settings/vault-timeout-input.component"; + +@Component({ + selector: "app-vault-timeout-input", + templateUrl: "vault-timeout-input.component.html", + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: VaultTimeoutInputComponent, + }, + { + provide: NG_VALIDATORS, + multi: true, + useExisting: VaultTimeoutInputComponent, + }, + ], +}) +export class VaultTimeoutInputComponent extends VaultTimeoutInputComponentBase {} diff --git a/apps/browser/src/popup/tabs.component.html b/apps/browser/src/popup/tabs.component.html new file mode 100644 index 0000000000..f64837cc73 --- /dev/null +++ b/apps/browser/src/popup/tabs.component.html @@ -0,0 +1,52 @@ +
+ + +
diff --git a/apps/browser/src/popup/tabs.component.ts b/apps/browser/src/popup/tabs.component.ts new file mode 100644 index 0000000000..856529a0a3 --- /dev/null +++ b/apps/browser/src/popup/tabs.component.ts @@ -0,0 +1,17 @@ +import { Component, OnInit } from "@angular/core"; + +import { PopupUtilsService } from "./services/popup-utils.service"; + +@Component({ + selector: "app-tabs", + templateUrl: "tabs.component.html", +}) +export class TabsComponent implements OnInit { + showCurrentTab = true; + + constructor(private popupUtilsService: PopupUtilsService) {} + + ngOnInit() { + this.showCurrentTab = !this.popupUtilsService.inPopout(window); + } +} diff --git a/apps/browser/src/popup/vault/add-edit-custom-fields.component.html b/apps/browser/src/popup/vault/add-edit-custom-fields.component.html new file mode 100644 index 0000000000..92b8bfe453 --- /dev/null +++ b/apps/browser/src/popup/vault/add-edit-custom-fields.component.html @@ -0,0 +1,121 @@ +
+

+ {{ "customFields" | i18n }} +

+
+ +
+
+ + + +
+ + + + + + + +
+ + +
+ +
+
+ +
+
+
+ +
+ + + +
+
+
diff --git a/apps/browser/src/popup/vault/add-edit-custom-fields.component.ts b/apps/browser/src/popup/vault/add-edit-custom-fields.component.ts new file mode 100644 index 0000000000..5ce773e014 --- /dev/null +++ b/apps/browser/src/popup/vault/add-edit-custom-fields.component.ts @@ -0,0 +1,15 @@ +import { Component } from "@angular/core"; + +import { AddEditCustomFieldsComponent as BaseAddEditCustomFieldsComponent } from "jslib-angular/components/add-edit-custom-fields.component"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +@Component({ + selector: "app-vault-add-edit-custom-fields", + templateUrl: "add-edit-custom-fields.component.html", +}) +export class AddEditCustomFieldsComponent extends BaseAddEditCustomFieldsComponent { + constructor(i18nService: I18nService, eventService: EventService) { + super(i18nService, eventService); + } +} diff --git a/apps/browser/src/popup/vault/add-edit.component.html b/apps/browser/src/popup/vault/add-edit.component.html new file mode 100644 index 0000000000..9876da114c --- /dev/null +++ b/apps/browser/src/popup/vault/add-edit.component.html @@ -0,0 +1,660 @@ +
+
+
+ +
+

+ {{ title }} +

+
+ +
+
+
+ + {{ "personalOwnershipPolicyInEffect" | i18n }} + +
+

+ {{ "itemInformation" | i18n }} +

+
+
+ + +
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ + + +
+
+
+ + +
+
+ +
+
+ + +
+
+
+ + +
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ +
+
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ +
+ +
+ + + + + + +
+
+ + +
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+ + +
+
+
+

+ +

+
+
+ +
+
+
+ + +
+

+ {{ "ownership" | i18n }} +

+
+
+ + +
+
+
+
+

+ {{ "collections" | i18n }} +

+
+
+ {{ "noCollectionsInList" | i18n }} +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+
diff --git a/apps/browser/src/popup/vault/add-edit.component.ts b/apps/browser/src/popup/vault/add-edit.component.ts new file mode 100644 index 0000000000..d286b96875 --- /dev/null +++ b/apps/browser/src/popup/vault/add-edit.component.ts @@ -0,0 +1,236 @@ +import { Location } from "@angular/common"; +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { AddEditComponent as BaseAddEditComponent } from "jslib-angular/components/add-edit.component"; +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; + +import { BrowserApi } from "../../browser/browserApi"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +@Component({ + selector: "app-vault-add-edit", + templateUrl: "add-edit.component.html", +}) +export class AddEditComponent extends BaseAddEditComponent { + currentUris: string[]; + showAttachments = true; + openAttachmentsInPopup: boolean; + showAutoFillOnPageLoadOptions: boolean; + + constructor( + cipherService: CipherService, + folderService: FolderService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + auditService: AuditService, + stateService: StateService, + collectionService: CollectionService, + messagingService: MessagingService, + private route: ActivatedRoute, + private router: Router, + private location: Location, + eventService: EventService, + policyService: PolicyService, + private popupUtilsService: PopupUtilsService, + organizationService: OrganizationService, + passwordRepromptService: PasswordRepromptService, + logService: LogService + ) { + super( + cipherService, + folderService, + i18nService, + platformUtilsService, + auditService, + stateService, + collectionService, + messagingService, + eventService, + policyService, + logService, + passwordRepromptService, + organizationService + ); + } + + async ngOnInit() { + await super.ngOnInit(); + + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (params.cipherId) { + this.cipherId = params.cipherId; + } + if (params.folderId) { + this.folderId = params.folderId; + } + if (params.collectionId) { + const collection = this.writeableCollections.find((c) => c.id === params.collectionId); + if (collection != null) { + this.collectionIds = [collection.id]; + this.organizationId = collection.organizationId; + } + } + if (params.type) { + const type = parseInt(params.type, null); + this.type = type; + } + this.editMode = !params.cipherId; + + if (params.cloneMode != null) { + this.cloneMode = params.cloneMode === "true"; + } + if (params.selectedVault) { + this.organizationId = params.selectedVault; + } + await this.load(); + + if (!this.editMode || this.cloneMode) { + if ( + !this.popupUtilsService.inPopout(window) && + params.name && + (this.cipher.name == null || this.cipher.name === "") + ) { + this.cipher.name = params.name; + } + if ( + !this.popupUtilsService.inPopout(window) && + params.uri && + (this.cipher.login.uris[0].uri == null || this.cipher.login.uris[0].uri === "") + ) { + this.cipher.login.uris[0].uri = params.uri; + } + } + + this.openAttachmentsInPopup = this.popupUtilsService.inPopup(window); + }); + + if (!this.editMode) { + const tabs = await BrowserApi.tabsQuery({ windowType: "normal" }); + this.currentUris = + tabs == null + ? null + : tabs.filter((tab) => tab.url != null && tab.url !== "").map((tab) => tab.url); + } + + window.setTimeout(() => { + if (!this.editMode) { + if (this.cipher.name != null && this.cipher.name !== "") { + document.getElementById("loginUsername").focus(); + } else { + document.getElementById("name").focus(); + } + } + }, 200); + } + + async load() { + await super.load(); + this.showAutoFillOnPageLoadOptions = + this.cipher.type === CipherType.Login && + (await this.stateService.getEnableAutoFillOnPageLoad()); + } + + async submit(): Promise { + if (await super.submit()) { + if (this.cloneMode) { + this.router.navigate(["/tabs/vault"]); + } else { + this.location.back(); + } + return true; + } + + return false; + } + + attachments() { + super.attachments(); + + if (this.openAttachmentsInPopup) { + const destinationUrl = this.router + .createUrlTree(["/attachments"], { queryParams: { cipherId: this.cipher.id } }) + .toString(); + const currentBaseUrl = window.location.href.replace(this.router.url, ""); + this.popupUtilsService.popOut(window, currentBaseUrl + destinationUrl); + } else { + this.router.navigate(["/attachments"], { queryParams: { cipherId: this.cipher.id } }); + } + } + + editCollections() { + super.editCollections(); + if (this.cipher.organizationId != null) { + this.router.navigate(["/collections"], { queryParams: { cipherId: this.cipher.id } }); + } + } + + cancel() { + super.cancel(); + this.location.back(); + } + + async generateUsername(): Promise { + const confirmed = await super.generateUsername(); + if (confirmed) { + await this.saveCipherState(); + this.router.navigate(["generator"], { queryParams: { type: "username" } }); + } + return confirmed; + } + + async generatePassword(): Promise { + const confirmed = await super.generatePassword(); + if (confirmed) { + await this.saveCipherState(); + this.router.navigate(["generator"], { queryParams: { type: "password" } }); + } + return confirmed; + } + + async delete(): Promise { + const confirmed = await super.delete(); + if (confirmed) { + this.router.navigate(["/tabs/vault"]); + } + return confirmed; + } + + toggleUriInput(uri: LoginUriView) { + const u = uri as any; + u.showCurrentUris = !u.showCurrentUris; + } + + allowOwnershipOptions(): boolean { + return ( + (!this.editMode || this.cloneMode) && + this.ownershipOptions && + (this.ownershipOptions.length > 1 || !this.allowPersonal) + ); + } + + private saveCipherState() { + return this.stateService.setAddEditCipherInfo({ + cipher: this.cipher, + collectionIds: + this.collections == null + ? [] + : this.collections.filter((c) => (c as any).checked).map((c) => c.id), + }); + } +} diff --git a/apps/browser/src/popup/vault/attachments.component.html b/apps/browser/src/popup/vault/attachments.component.html new file mode 100644 index 0000000000..4b687dc10b --- /dev/null +++ b/apps/browser/src/popup/vault/attachments.component.html @@ -0,0 +1,73 @@ +
+
+
+ + +
+

+ {{ "attachments" | i18n }} +

+
+ +
+
+
+
+
+
+
+ {{ a.fileName }} +
+ {{ a.sizeName }} +
+ +
+
+
+
+
+

+ {{ "newAttachment" | i18n }} +

+
+
+ + +
+
+ +
+
+
diff --git a/apps/browser/src/popup/vault/attachments.component.ts b/apps/browser/src/popup/vault/attachments.component.ts new file mode 100644 index 0000000000..bec18333c3 --- /dev/null +++ b/apps/browser/src/popup/vault/attachments.component.ts @@ -0,0 +1,61 @@ +import { Location } from "@angular/common"; +import { Component } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { AttachmentsComponent as BaseAttachmentsComponent } from "jslib-angular/components/attachments.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Component({ + selector: "app-vault-attachments", + templateUrl: "attachments.component.html", +}) +export class AttachmentsComponent extends BaseAttachmentsComponent { + openedAttachmentsInPopup: boolean; + + constructor( + cipherService: CipherService, + i18nService: I18nService, + cryptoService: CryptoService, + platformUtilsService: PlatformUtilsService, + apiService: ApiService, + private location: Location, + private route: ActivatedRoute, + stateService: StateService, + logService: LogService + ) { + super( + cipherService, + i18nService, + cryptoService, + platformUtilsService, + apiService, + window, + logService, + stateService + ); + } + + async ngOnInit() { + this.route.queryParams.pipe(first()).subscribe(async (params) => { + this.cipherId = params.cipherId; + await this.init(); + }); + + this.openedAttachmentsInPopup = history.length === 1; + } + + back() { + this.location.back(); + } + + close() { + window.close(); + } +} diff --git a/apps/browser/src/popup/vault/ciphers.component.html b/apps/browser/src/popup/vault/ciphers.component.html new file mode 100644 index 0000000000..d6b8756866 --- /dev/null +++ b/apps/browser/src/popup/vault/ciphers.component.html @@ -0,0 +1,124 @@ +
+
+ +
+

{{ "myVault" | i18n }}

+ +
+ +
+
+
+ + +
+

+ {{ "folders" | i18n }} +

+
+ +
+
+
+

+ {{ "collections" | i18n }} +

+
+ +
+
+
+ +
+ +
+ + +

{{ "noItemsInList" | i18n }}

+ +
+
+
+ +
+

+ {{ groupingTitle }} + {{ isSearching() ? ciphers.length : ciphers.length }} +

+
+ +
+
+
+
+
diff --git a/apps/browser/src/popup/vault/ciphers.component.ts b/apps/browser/src/popup/vault/ciphers.component.ts new file mode 100644 index 0000000000..fd58a8e713 --- /dev/null +++ b/apps/browser/src/popup/vault/ciphers.component.ts @@ -0,0 +1,296 @@ +import { Location } from "@angular/common"; +import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { CiphersComponent as BaseCiphersComponent } from "jslib-angular/components/ciphers.component"; +import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { TreeNode } from "jslib-common/models/domain/treeNode"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; + +import { BrowserComponentState } from "src/models/browserComponentState"; + +import { BrowserApi } from "../../browser/browserApi"; +import { StateService } from "../../services/abstractions/state.service"; +import { VaultFilterService } from "../../services/vaultFilter.service"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const ComponentId = "CiphersComponent"; + +@Component({ + selector: "app-vault-ciphers", + templateUrl: "ciphers.component.html", +}) +export class CiphersComponent extends BaseCiphersComponent implements OnInit, OnDestroy { + groupingTitle: string; + state: BrowserComponentState; + folderId: string = null; + collectionId: string = null; + type: CipherType = null; + nestedFolders: TreeNode[]; + nestedCollections: TreeNode[]; + searchTypeSearch = false; + showOrganizations = false; + vaultFilter: VaultFilter; + deleted = true; + noneFolder = false; + showVaultFilter = false; + + private selectedTimeout: number; + private preventSelected = false; + private applySavedState = true; + private scrollingContainer = "cdk-virtual-scroll-viewport"; + + constructor( + searchService: SearchService, + private organizationService: OrganizationService, + private route: ActivatedRoute, + private router: Router, + private location: Location, + private ngZone: NgZone, + private broadcasterService: BroadcasterService, + private changeDetectorRef: ChangeDetectorRef, + private stateService: StateService, + private popupUtils: PopupUtilsService, + private i18nService: I18nService, + private folderService: FolderService, + private collectionService: CollectionService, + private platformUtilsService: PlatformUtilsService, + private cipherService: CipherService, + private vaultFilterService: VaultFilterService + ) { + super(searchService); + this.applySavedState = + (window as any).previousPopupUrl != null && + !(window as any).previousPopupUrl.startsWith("/ciphers"); + } + + async ngOnInit() { + this.searchTypeSearch = !this.platformUtilsService.isSafari(); + this.showOrganizations = await this.organizationService.hasOrganizations(); + this.vaultFilter = this.vaultFilterService.getVaultFilter(); + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (this.applySavedState) { + this.state = await this.stateService.getBrowserCipherComponentState(); + if (this.state?.searchText) { + this.searchText = this.state.searchText; + } + } + + if (params.deleted) { + this.showVaultFilter = true; + this.groupingTitle = this.i18nService.t("trash"); + this.searchPlaceholder = this.i18nService.t("searchTrash"); + await this.load(this.buildFilter(), true); + } else if (params.type) { + this.showVaultFilter = true; + this.searchPlaceholder = this.i18nService.t("searchType"); + this.type = parseInt(params.type, null); + switch (this.type) { + case CipherType.Login: + this.groupingTitle = this.i18nService.t("logins"); + break; + case CipherType.Card: + this.groupingTitle = this.i18nService.t("cards"); + break; + case CipherType.Identity: + this.groupingTitle = this.i18nService.t("identities"); + break; + case CipherType.SecureNote: + this.groupingTitle = this.i18nService.t("secureNotes"); + break; + default: + break; + } + await this.load(this.buildFilter()); + } else if (params.folderId) { + this.showVaultFilter = true; + this.folderId = params.folderId === "none" ? null : params.folderId; + this.searchPlaceholder = this.i18nService.t("searchFolder"); + if (this.folderId != null) { + this.showOrganizations = false; + const folderNode = await this.folderService.getNested(this.folderId); + if (folderNode != null && folderNode.node != null) { + this.groupingTitle = folderNode.node.name; + this.nestedFolders = + folderNode.children != null && folderNode.children.length > 0 + ? folderNode.children + : null; + } + } else { + this.noneFolder = true; + this.groupingTitle = this.i18nService.t("noneFolder"); + } + await this.load(this.buildFilter()); + } else if (params.collectionId) { + this.showVaultFilter = false; + this.collectionId = params.collectionId; + this.searchPlaceholder = this.i18nService.t("searchCollection"); + const collectionNode = await this.collectionService.getNested(this.collectionId); + if (collectionNode != null && collectionNode.node != null) { + this.groupingTitle = collectionNode.node.name; + this.nestedCollections = + collectionNode.children != null && collectionNode.children.length > 0 + ? collectionNode.children + : null; + } + await this.load( + (c) => c.collectionIds != null && c.collectionIds.indexOf(this.collectionId) > -1 + ); + } else { + this.showVaultFilter = true; + this.groupingTitle = this.i18nService.t("allItems"); + await this.load(this.buildFilter()); + } + + if (this.applySavedState && this.state != null) { + window.setTimeout( + () => + this.popupUtils.setContentScrollY(window, this.state.scrollY, this.scrollingContainer), + 0 + ); + } + await this.stateService.setBrowserCipherComponentState(null); + }); + + this.broadcasterService.subscribe(ComponentId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + if (message.successfully) { + window.setTimeout(() => { + this.refresh(); + }, 500); + } + break; + default: + break; + } + + this.changeDetectorRef.detectChanges(); + }); + }); + } + + ngOnDestroy() { + this.saveState(); + this.broadcasterService.unsubscribe(ComponentId); + } + + selectCipher(cipher: CipherView) { + this.selectedTimeout = window.setTimeout(() => { + if (!this.preventSelected) { + super.selectCipher(cipher); + this.router.navigate(["/view-cipher"], { queryParams: { cipherId: cipher.id } }); + } + this.preventSelected = false; + }, 200); + } + + selectFolder(folder: FolderView) { + if (folder.id != null) { + this.router.navigate(["/ciphers"], { queryParams: { folderId: folder.id } }); + } + } + + selectCollection(collection: CollectionView) { + this.router.navigate(["/ciphers"], { queryParams: { collectionId: collection.id } }); + } + + async launchCipher(cipher: CipherView) { + if (cipher.type !== CipherType.Login || !cipher.login.canLaunch) { + return; + } + + if (this.selectedTimeout != null) { + window.clearTimeout(this.selectedTimeout); + } + this.preventSelected = true; + await this.cipherService.updateLastLaunchedDate(cipher.id); + BrowserApi.createNewTab(cipher.login.launchUri); + if (this.popupUtils.inPopup(window)) { + BrowserApi.closePopup(window); + } + } + + addCipher() { + if (this.deleted) { + return false; + } + super.addCipher(); + this.router.navigate(["/add-cipher"], { + queryParams: { + folderId: this.folderId, + type: this.type, + collectionId: this.collectionId, + selectedVault: this.vaultFilter.selectedOrganizationId, + }, + }); + } + + back() { + (window as any).routeDirection = "b"; + this.location.back(); + } + + showGroupings() { + return ( + !this.isSearching() && + ((this.nestedFolders && this.nestedFolders.length) || + (this.nestedCollections && this.nestedCollections.length)) + ); + } + + async changeVaultSelection() { + this.vaultFilter = this.vaultFilterService.getVaultFilter(); + await this.load(this.buildFilter(), this.deleted); + } + + private buildFilter(): (cipher: CipherView) => boolean { + return (cipher) => { + let cipherPassesFilter = true; + if (this.deleted && cipherPassesFilter) { + cipherPassesFilter = cipher.isDeleted; + } + if (this.type != null && cipherPassesFilter) { + cipherPassesFilter = cipher.type === this.type; + } + if (this.folderId != null && this.folderId != "none" && cipherPassesFilter) { + cipherPassesFilter = cipher.folderId === this.folderId; + } + if (this.noneFolder) { + cipherPassesFilter = cipher.folderId == null; + } + if (this.collectionId != null && cipherPassesFilter) { + cipherPassesFilter = + cipher.collectionIds != null && cipher.collectionIds.indexOf(this.collectionId) > -1; + } + if (this.vaultFilter.selectedOrganizationId != null && cipherPassesFilter) { + cipherPassesFilter = cipher.organizationId === this.vaultFilter.selectedOrganizationId; + } + if (this.vaultFilter.myVaultOnly && cipherPassesFilter) { + cipherPassesFilter = cipher.organizationId === null; + } + return cipherPassesFilter; + }; + } + + private async saveState() { + this.state = { + scrollY: this.popupUtils.getContentScrollY(window, this.scrollingContainer), + searchText: this.searchText, + }; + await this.stateService.setBrowserCipherComponentState(this.state); + } +} diff --git a/apps/browser/src/popup/vault/collections.component.html b/apps/browser/src/popup/vault/collections.component.html new file mode 100644 index 0000000000..35d7b08261 --- /dev/null +++ b/apps/browser/src/popup/vault/collections.component.html @@ -0,0 +1,43 @@ +
+
+
+ +
+

+ {{ "collections" | i18n }} +

+
+ +
+
+
+
+
+
+ {{ "noCollectionsInList" | i18n }} +
+
+
+
+ + +
+
+
+
+
diff --git a/apps/browser/src/popup/vault/collections.component.ts b/apps/browser/src/popup/vault/collections.component.ts new file mode 100644 index 0000000000..ea01e3f061 --- /dev/null +++ b/apps/browser/src/popup/vault/collections.component.ts @@ -0,0 +1,43 @@ +import { Location } from "@angular/common"; +import { Component } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { CollectionsComponent as BaseCollectionsComponent } from "jslib-angular/components/collections.component"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-vault-collections", + templateUrl: "collections.component.html", +}) +export class CollectionsComponent extends BaseCollectionsComponent { + constructor( + collectionService: CollectionService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + cipherService: CipherService, + private route: ActivatedRoute, + private location: Location, + logService: LogService + ) { + super(collectionService, platformUtilsService, i18nService, cipherService, logService); + } + + async ngOnInit() { + this.onSavedCollections.subscribe(() => { + this.back(); + }); + this.route.queryParams.pipe(first()).subscribe(async (params) => { + this.cipherId = params.cipherId; + await this.load(); + }); + } + + back() { + this.location.back(); + } +} diff --git a/apps/browser/src/popup/vault/current-tab.component.html b/apps/browser/src/popup/vault/current-tab.component.html new file mode 100644 index 0000000000..f4cfd9f4bc --- /dev/null +++ b/apps/browser/src/popup/vault/current-tab.component.html @@ -0,0 +1,95 @@ +
+

{{ "currentTab" | i18n }}

+
+ + +
+ +
+ +
+
+
+
+ +
+ + +
+

+ {{ "typeLogins" | i18n }} + {{ loginCiphers.length }} +

+
+ + +
+

{{ "autoFillInfo" | i18n }}

+ +
+
+
+
+

+ {{ "cards" | i18n }} + {{ cardCiphers.length }} +

+
+ +
+
+
+

+ {{ "identities" | i18n }} + {{ identityCiphers.length }} +

+
+ +
+
+
+
diff --git a/apps/browser/src/popup/vault/current-tab.component.ts b/apps/browser/src/popup/vault/current-tab.component.ts new file mode 100644 index 0000000000..726a291689 --- /dev/null +++ b/apps/browser/src/popup/vault/current-tab.component.ts @@ -0,0 +1,259 @@ +import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; + +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { Utils } from "jslib-common/misc/utils"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +import { BrowserApi } from "../../browser/browserApi"; +import { AutofillService } from "../../services/abstractions/autofill.service"; +import { VaultFilterService } from "../../services/vaultFilter.service"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const BroadcasterSubscriptionId = "CurrentTabComponent"; + +@Component({ + selector: "app-current-tab", + templateUrl: "current-tab.component.html", +}) +export class CurrentTabComponent implements OnInit, OnDestroy { + pageDetails: any[] = []; + cardCiphers: CipherView[]; + identityCiphers: CipherView[]; + loginCiphers: CipherView[]; + url: string; + hostname: string; + searchText: string; + inSidebar = false; + searchTypeSearch = false; + loaded = false; + showOrganizations = false; + + private totpCode: string; + private totpTimeout: number; + private loadedTimeout: number; + private searchTimeout: number; + + constructor( + private platformUtilsService: PlatformUtilsService, + private cipherService: CipherService, + private popupUtilsService: PopupUtilsService, + private autofillService: AutofillService, + private i18nService: I18nService, + private router: Router, + private ngZone: NgZone, + private broadcasterService: BroadcasterService, + private changeDetectorRef: ChangeDetectorRef, + private syncService: SyncService, + private searchService: SearchService, + private stateService: StateService, + private passwordRepromptService: PasswordRepromptService, + private organizationService: OrganizationService, + private vaultFilterService: VaultFilterService + ) {} + + async ngOnInit() { + this.searchTypeSearch = !this.platformUtilsService.isSafari(); + this.inSidebar = this.popupUtilsService.inSidebar(window); + + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + if (this.loaded) { + window.setTimeout(() => { + this.load(); + }, 500); + } + break; + case "collectPageDetailsResponse": + if (message.sender === BroadcasterSubscriptionId) { + this.pageDetails.push({ + frameId: message.webExtSender.frameId, + tab: message.tab, + details: message.details, + }); + } + break; + default: + break; + } + + this.changeDetectorRef.detectChanges(); + }); + }); + + if (!this.syncService.syncInProgress) { + await this.load(); + } else { + this.loadedTimeout = window.setTimeout(async () => { + if (!this.loaded) { + await this.load(); + } + }, 5000); + } + + window.setTimeout(() => { + document.getElementById("search").focus(); + }, 100); + } + + ngOnDestroy() { + window.clearTimeout(this.loadedTimeout); + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async refresh() { + await this.load(); + } + + addCipher() { + this.router.navigate(["/add-cipher"], { + queryParams: { + name: this.hostname, + uri: this.url, + selectedVault: this.vaultFilterService.getVaultFilter().selectedOrganizationId, + }, + }); + } + + viewCipher(cipher: CipherView) { + this.router.navigate(["/view-cipher"], { queryParams: { cipherId: cipher.id } }); + } + + async fillCipher(cipher: CipherView) { + if ( + cipher.reprompt !== CipherRepromptType.None && + !(await this.passwordRepromptService.showPasswordPrompt()) + ) { + return; + } + + this.totpCode = null; + if (this.totpTimeout != null) { + window.clearTimeout(this.totpTimeout); + } + + if (this.pageDetails == null || this.pageDetails.length === 0) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("autofillError")); + return; + } + + try { + this.totpCode = await this.autofillService.doAutoFill({ + cipher: cipher, + pageDetails: this.pageDetails, + doc: window.document, + fillNewPassword: true, + }); + if (this.totpCode != null) { + this.platformUtilsService.copyToClipboard(this.totpCode, { window: window }); + } + if (this.popupUtilsService.inPopup(window)) { + if (this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari()) { + BrowserApi.closePopup(window); + } else { + // Slight delay to fix bug in Chromium browsers where popup closes without copying totp to clipboard + setTimeout(() => BrowserApi.closePopup(window), 50); + } + } + } catch { + this.ngZone.run(() => { + this.platformUtilsService.showToast("error", null, this.i18nService.t("autofillError")); + this.changeDetectorRef.detectChanges(); + }); + } + } + + searchVault() { + if (this.searchTimeout != null) { + clearTimeout(this.searchTimeout); + } + if (!this.searchService.isSearchable(this.searchText)) { + return; + } + this.searchTimeout = window.setTimeout(async () => { + this.router.navigate(["/tabs/vault"], { queryParams: { searchText: this.searchText } }); + }, 200); + } + + closeOnEsc(e: KeyboardEvent) { + // If input not empty, use browser default behavior of clearing input instead + if (e.key === "Escape" && (this.searchText == null || this.searchText === "")) { + BrowserApi.closePopup(window); + } + } + + private async load() { + this.loaded = false; + const tab = await BrowserApi.getTabFromCurrentWindow(); + if (tab != null) { + this.url = tab.url; + } else { + this.loginCiphers = []; + this.loaded = true; + return; + } + + this.hostname = Utils.getHostname(this.url); + this.pageDetails = []; + BrowserApi.tabSendMessage(tab, { + command: "collectPageDetails", + tab: tab, + sender: BroadcasterSubscriptionId, + }); + + const otherTypes: CipherType[] = []; + const dontShowCards = await this.stateService.getDontShowCardsCurrentTab(); + const dontShowIdentities = await this.stateService.getDontShowIdentitiesCurrentTab(); + this.showOrganizations = await this.organizationService.hasOrganizations(); + if (!dontShowCards) { + otherTypes.push(CipherType.Card); + } + if (!dontShowIdentities) { + otherTypes.push(CipherType.Identity); + } + + const ciphers = await this.cipherService.getAllDecryptedForUrl( + this.url, + otherTypes.length > 0 ? otherTypes : null + ); + + this.loginCiphers = []; + this.cardCiphers = []; + this.identityCiphers = []; + + ciphers.forEach((c) => { + if (!this.vaultFilterService.filterCipherForSelectedVault(c)) { + switch (c.type) { + case CipherType.Login: + this.loginCiphers.push(c); + break; + case CipherType.Card: + this.cardCiphers.push(c); + break; + case CipherType.Identity: + this.identityCiphers.push(c); + break; + default: + break; + } + } + }); + + this.loginCiphers = this.loginCiphers.sort((a, b) => + this.cipherService.sortCiphersByLastUsedThenName(a, b) + ); + this.loaded = true; + } +} diff --git a/apps/browser/src/popup/vault/password-history.component.html b/apps/browser/src/popup/vault/password-history.component.html new file mode 100644 index 0000000000..009b7089ba --- /dev/null +++ b/apps/browser/src/popup/vault/password-history.component.html @@ -0,0 +1,39 @@ +
+
+ +
+

+ {{ "passwordHistory" | i18n }} +

+
+
+
+
+
+
+
+
+ + {{ h.password }} + + {{ h.lastUsedDate | date: "medium" }} +
+
+
+ +
+
+
+
+
+

{{ "noPasswordsInList" | i18n }}

+
+
diff --git a/apps/browser/src/popup/vault/password-history.component.ts b/apps/browser/src/popup/vault/password-history.component.ts new file mode 100644 index 0000000000..96e3a6c2d1 --- /dev/null +++ b/apps/browser/src/popup/vault/password-history.component.ts @@ -0,0 +1,40 @@ +import { Location } from "@angular/common"; +import { Component } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { PasswordHistoryComponent as BasePasswordHistoryComponent } from "jslib-angular/components/password-history.component"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-password-history", + templateUrl: "password-history.component.html", +}) +export class PasswordHistoryComponent extends BasePasswordHistoryComponent { + constructor( + cipherService: CipherService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + private location: Location, + private route: ActivatedRoute + ) { + super(cipherService, platformUtilsService, i18nService, window); + } + + async ngOnInit() { + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (params.cipherId) { + this.cipherId = params.cipherId; + } else { + this.close(); + } + await this.init(); + }); + } + + close() { + this.location.back(); + } +} diff --git a/apps/browser/src/popup/vault/share.component.html b/apps/browser/src/popup/vault/share.component.html new file mode 100644 index 0000000000..7e6d6e38af --- /dev/null +++ b/apps/browser/src/popup/vault/share.component.html @@ -0,0 +1,71 @@ +
+
+
+ +
+

+ {{ "moveToOrganization" | i18n }} +

+
+ +
+
+
+
+
+
+ {{ "noOrganizationsList" | i18n }} +
+
+
+
+ + +
+
+ +
+
+

+ {{ "collections" | i18n }} +

+
+
+ {{ "noCollectionsInList" | i18n }} +
+
+
+
+ + +
+
+
+
+
diff --git a/apps/browser/src/popup/vault/share.component.ts b/apps/browser/src/popup/vault/share.component.ts new file mode 100644 index 0000000000..edd53225be --- /dev/null +++ b/apps/browser/src/popup/vault/share.component.ts @@ -0,0 +1,62 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { ShareComponent as BaseShareComponent } from "jslib-angular/components/share.component"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-vault-share", + templateUrl: "share.component.html", +}) +export class ShareComponent extends BaseShareComponent { + constructor( + collectionService: CollectionService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + logService: LogService, + cipherService: CipherService, + private route: ActivatedRoute, + private router: Router, + organizationService: OrganizationService + ) { + super( + collectionService, + platformUtilsService, + i18nService, + cipherService, + logService, + organizationService + ); + } + + async ngOnInit() { + this.onSharedCipher.subscribe(() => { + this.router.navigate(["view-cipher", { cipherId: this.cipherId }]); + }); + this.route.queryParams.pipe(first()).subscribe(async (params) => { + this.cipherId = params.cipherId; + await this.load(); + }); + } + + async submit(): Promise { + const success = await super.submit(); + if (success) { + this.cancel(); + } + return success; + } + + cancel() { + this.router.navigate(["/view-cipher"], { + replaceUrl: true, + queryParams: { cipherId: this.cipher.id }, + }); + } +} diff --git a/apps/browser/src/popup/vault/vault-filter.component.html b/apps/browser/src/popup/vault/vault-filter.component.html new file mode 100644 index 0000000000..4c2ce65f42 --- /dev/null +++ b/apps/browser/src/popup/vault/vault-filter.component.html @@ -0,0 +1,231 @@ +
+
+ +
+

{{ "myVault" | i18n }}

+ +
+ +
+
+
+ +
+ + + +

{{ "noItemsInList" | i18n }}

+ +
+
+ +
+

+ {{ "favorites" | i18n }} + {{ favoriteCiphers.length }} +

+
+ + +
+
+
+

+ {{ "types" | i18n }} + 4 +

+
+ + + + +
+
+
+

+ {{ "folders" | i18n }} + {{ folderCount }} +

+
+ +
+
+
+

+ {{ "collections" | i18n }} + {{ nestedCollections.length }} +

+
+ +
+
+
+

+ {{ "noneFolder" | i18n }} +
{{ noFolderCiphers.length }}
+

+
+ + +
+
+
+

+ {{ "trash" | i18n }} + {{ deletedCount }} +

+
+ +
+
+
+ +
+

{{ "noItemsInList" | i18n }}

+
+ +
+
+ + +
+
+
+
+
diff --git a/apps/browser/src/popup/vault/vault-filter.component.ts b/apps/browser/src/popup/vault/vault-filter.component.ts new file mode 100644 index 0000000000..9c663d8a91 --- /dev/null +++ b/apps/browser/src/popup/vault/vault-filter.component.ts @@ -0,0 +1,425 @@ +import { Location } from "@angular/common"; +import { ChangeDetectorRef, Component, NgZone, OnDestroy, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { TreeNode } from "jslib-common/models/domain/treeNode"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; + +import { BrowserGroupingsComponentState } from "src/models/browserGroupingsComponentState"; + +import { BrowserApi } from "../../browser/browserApi"; +import { StateService } from "../../services/abstractions/state.service"; +import { VaultFilterService } from "../../services/vaultFilter.service"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const ComponentId = "VaultComponent"; + +@Component({ + selector: "app-vault-filter", + templateUrl: "vault-filter.component.html", +}) +export class VaultFilterComponent implements OnInit, OnDestroy { + get showNoFolderCiphers(): boolean { + return ( + this.noFolderCiphers != null && + this.noFolderCiphers.length < this.noFolderListSize && + this.collections.length === 0 + ); + } + + get folderCount(): number { + return this.nestedFolders.length - (this.showNoFolderCiphers ? 0 : 1); + } + folders: FolderView[]; + nestedFolders: TreeNode[]; + collections: CollectionView[]; + nestedCollections: TreeNode[]; + loaded = false; + cipherType = CipherType; + ciphers: CipherView[]; + favoriteCiphers: CipherView[]; + noFolderCiphers: CipherView[]; + folderCounts = new Map(); + collectionCounts = new Map(); + typeCounts = new Map(); + searchText: string; + state: BrowserGroupingsComponentState; + showLeftHeader = true; + searchPending = false; + searchTypeSearch = false; + deletedCount = 0; + vaultFilter: VaultFilter; + selectedOrganization: string = null; + showCollections = true; + + private loadedTimeout: number; + private selectedTimeout: number; + private preventSelected = false; + private noFolderListSize = 100; + private searchTimeout: any = null; + private hasSearched = false; + private hasLoadedAllCiphers = false; + private allCiphers: CipherView[] = null; + + constructor( + private cipherService: CipherService, + private router: Router, + private ngZone: NgZone, + private broadcasterService: BroadcasterService, + private changeDetectorRef: ChangeDetectorRef, + private route: ActivatedRoute, + private popupUtils: PopupUtilsService, + private syncService: SyncService, + private platformUtilsService: PlatformUtilsService, + private searchService: SearchService, + private location: Location, + private browserStateService: StateService, + private vaultFilterService: VaultFilterService + ) { + this.noFolderListSize = 100; + } + + async ngOnInit() { + this.searchTypeSearch = !this.platformUtilsService.isSafari(); + this.showLeftHeader = !( + this.popupUtils.inSidebar(window) && this.platformUtilsService.isFirefox() + ); + await this.browserStateService.setBrowserCipherComponentState(null); + + this.broadcasterService.subscribe(ComponentId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + window.setTimeout(() => { + this.load(); + }, 500); + break; + default: + break; + } + + this.changeDetectorRef.detectChanges(); + }); + }); + + const restoredScopeState = await this.restoreState(); + this.route.queryParams.pipe(first()).subscribe(async (params) => { + this.state = await this.browserStateService.getBrowserGroupingComponentState(); + if (this.state?.searchText) { + this.searchText = this.state.searchText; + } else if (params.searchText) { + this.searchText = params.searchText; + this.location.replaceState("vault"); + } + + if (!this.syncService.syncInProgress) { + this.load(); + } else { + this.loadedTimeout = window.setTimeout(() => { + if (!this.loaded) { + this.load(); + } + }, 5000); + } + + if (!this.syncService.syncInProgress || restoredScopeState) { + window.setTimeout(() => this.popupUtils.setContentScrollY(window, this.state?.scrollY), 0); + } + }); + } + + ngOnDestroy() { + if (this.loadedTimeout != null) { + window.clearTimeout(this.loadedTimeout); + } + if (this.selectedTimeout != null) { + window.clearTimeout(this.selectedTimeout); + } + this.saveState(); + this.broadcasterService.unsubscribe(ComponentId); + } + + async load() { + this.vaultFilter = this.vaultFilterService.getVaultFilter(); + + this.updateSelectedOrg(); + await this.loadCollectionsAndFolders(); + await this.loadCiphers(); + + if (this.showNoFolderCiphers && this.nestedFolders.length > 0) { + // Remove "No Folder" from folder listing + this.nestedFolders = this.nestedFolders.slice(0, this.nestedFolders.length - 1); + } + + this.loaded = true; + } + + async loadCiphers() { + this.allCiphers = await this.cipherService.getAllDecrypted(); + if (!this.hasLoadedAllCiphers) { + this.hasLoadedAllCiphers = !this.searchService.isSearchable(this.searchText); + } + await this.search(null); + this.getCounts(); + } + + async loadCollections() { + const allCollections = await this.vaultFilterService.buildCollections( + this.selectedOrganization + ); + this.collections = allCollections.fullList; + this.nestedCollections = allCollections.nestedList; + } + + async loadFolders() { + const allFolders = await this.vaultFilterService.buildFolders(this.selectedOrganization); + this.folders = allFolders.fullList; + this.nestedFolders = await allFolders.nestedList; + } + + async search(timeout: number = null) { + this.searchPending = false; + if (this.searchTimeout != null) { + clearTimeout(this.searchTimeout); + } + const filterDeleted = (c: CipherView) => !c.isDeleted; + if (timeout == null) { + this.hasSearched = this.searchService.isSearchable(this.searchText); + this.ciphers = await this.searchService.searchCiphers( + this.searchText, + filterDeleted, + this.allCiphers + ); + this.ciphers = this.ciphers.filter( + (c) => !this.vaultFilterService.filterCipherForSelectedVault(c) + ); + return; + } + this.searchPending = true; + this.searchTimeout = setTimeout(async () => { + this.hasSearched = this.searchService.isSearchable(this.searchText); + if (!this.hasLoadedAllCiphers && !this.hasSearched) { + await this.loadCiphers(); + } else { + this.ciphers = await this.searchService.searchCiphers( + this.searchText, + filterDeleted, + this.allCiphers + ); + } + this.ciphers = this.ciphers.filter( + (c) => !this.vaultFilterService.filterCipherForSelectedVault(c) + ); + this.searchPending = false; + }, timeout); + } + + async selectType(type: CipherType) { + this.router.navigate(["/ciphers"], { queryParams: { type: type } }); + } + + async selectFolder(folder: FolderView) { + this.router.navigate(["/ciphers"], { queryParams: { folderId: folder.id || "none" } }); + } + + async selectCollection(collection: CollectionView) { + this.router.navigate(["/ciphers"], { queryParams: { collectionId: collection.id } }); + } + + async selectTrash() { + this.router.navigate(["/ciphers"], { queryParams: { deleted: true } }); + } + + async selectCipher(cipher: CipherView) { + this.selectedTimeout = window.setTimeout(() => { + if (!this.preventSelected) { + this.router.navigate(["/view-cipher"], { queryParams: { cipherId: cipher.id } }); + } + this.preventSelected = false; + }, 200); + } + + async launchCipher(cipher: CipherView) { + if (cipher.type !== CipherType.Login || !cipher.login.canLaunch) { + return; + } + + if (this.selectedTimeout != null) { + window.clearTimeout(this.selectedTimeout); + } + this.preventSelected = true; + await this.cipherService.updateLastLaunchedDate(cipher.id); + BrowserApi.createNewTab(cipher.login.launchUri); + if (this.popupUtils.inPopup(window)) { + BrowserApi.closePopup(window); + } + } + + async addCipher() { + this.router.navigate(["/add-cipher"], { + queryParams: { selectedVault: this.vaultFilter.selectedOrganizationId }, + }); + } + + async vaultFilterChanged() { + if (this.showSearching) { + await this.search(); + } + this.updateSelectedOrg(); + await this.loadCollectionsAndFolders(); + this.getCounts(); + } + + updateSelectedOrg() { + this.vaultFilter = this.vaultFilterService.getVaultFilter(); + if (this.vaultFilter.selectedOrganizationId != null) { + this.selectedOrganization = this.vaultFilter.selectedOrganizationId; + } else { + this.selectedOrganization = null; + } + } + + getCounts() { + let favoriteCiphers: CipherView[] = null; + let noFolderCiphers: CipherView[] = null; + const folderCounts = new Map(); + const collectionCounts = new Map(); + const typeCounts = new Map(); + + this.deletedCount = this.allCiphers.filter( + (c) => c.isDeleted && !this.vaultFilterService.filterCipherForSelectedVault(c) + ).length; + + this.ciphers?.forEach((c) => { + if (!this.vaultFilterService.filterCipherForSelectedVault(c)) { + if (c.isDeleted) { + return; + } + if (c.favorite) { + if (favoriteCiphers == null) { + favoriteCiphers = []; + } + favoriteCiphers.push(c); + } + + if (c.folderId == null) { + if (noFolderCiphers == null) { + noFolderCiphers = []; + } + noFolderCiphers.push(c); + } + + if (typeCounts.has(c.type)) { + typeCounts.set(c.type, typeCounts.get(c.type) + 1); + } else { + typeCounts.set(c.type, 1); + } + + if (folderCounts.has(c.folderId)) { + folderCounts.set(c.folderId, folderCounts.get(c.folderId) + 1); + } else { + folderCounts.set(c.folderId, 1); + } + + if (c.collectionIds != null) { + c.collectionIds.forEach((colId) => { + if (collectionCounts.has(colId)) { + collectionCounts.set(colId, collectionCounts.get(colId) + 1); + } else { + collectionCounts.set(colId, 1); + } + }); + } + } + }); + + this.favoriteCiphers = favoriteCiphers; + this.noFolderCiphers = noFolderCiphers; + this.typeCounts = typeCounts; + this.folderCounts = folderCounts; + this.collectionCounts = collectionCounts; + } + + showSearching() { + return ( + this.hasSearched || (!this.searchPending && this.searchService.isSearchable(this.searchText)) + ); + } + + closeOnEsc(e: KeyboardEvent) { + // If input not empty, use browser default behavior of clearing input instead + if (e.key === "Escape" && (this.searchText == null || this.searchText === "")) { + BrowserApi.closePopup(window); + } + } + + private async loadCollectionsAndFolders() { + this.showCollections = !this.vaultFilter.myVaultOnly; + await this.loadFolders(); + await this.loadCollections(); + } + + private async saveState() { + this.state = { + scrollY: this.popupUtils.getContentScrollY(window), + searchText: this.searchText, + favoriteCiphers: this.favoriteCiphers, + noFolderCiphers: this.noFolderCiphers, + ciphers: this.ciphers, + collectionCounts: this.collectionCounts, + folderCounts: this.folderCounts, + typeCounts: this.typeCounts, + folders: this.folders, + collections: this.collections, + deletedCount: this.deletedCount, + }; + await this.browserStateService.setBrowserGroupingComponentState(this.state); + } + + private async restoreState(): Promise { + this.state = await this.browserStateService.getBrowserGroupingComponentState(); + if (this.state == null) { + return false; + } + + if (this.state.favoriteCiphers != null) { + this.favoriteCiphers = this.state.favoriteCiphers; + } + if (this.state.noFolderCiphers != null) { + this.noFolderCiphers = this.state.noFolderCiphers; + } + if (this.state.ciphers != null) { + this.ciphers = this.state.ciphers; + } + if (this.state.collectionCounts != null) { + this.collectionCounts = this.state.collectionCounts; + } + if (this.state.folderCounts != null) { + this.folderCounts = this.state.folderCounts; + } + if (this.state.typeCounts != null) { + this.typeCounts = this.state.typeCounts; + } + if (this.state.folders != null) { + this.folders = this.state.folders; + } + if (this.state.collections != null) { + this.collections = this.state.collections; + } + if (this.state.deletedCount != null) { + this.deletedCount = this.state.deletedCount; + } + + return true; + } +} diff --git a/apps/browser/src/popup/vault/vault-select.component.html b/apps/browser/src/popup/vault/vault-select.component.html new file mode 100644 index 0000000000..813fbccf14 --- /dev/null +++ b/apps/browser/src/popup/vault/vault-select.component.html @@ -0,0 +1,65 @@ +
+ + + + +
diff --git a/apps/browser/src/popup/vault/vault-select.component.ts b/apps/browser/src/popup/vault/vault-select.component.ts new file mode 100644 index 0000000000..fb5178cfd4 --- /dev/null +++ b/apps/browser/src/popup/vault/vault-select.component.ts @@ -0,0 +1,191 @@ +import { animate, state, style, transition, trigger } from "@angular/animations"; +import { ConnectedPosition, Overlay, OverlayRef } from "@angular/cdk/overlay"; +import { TemplatePortal } from "@angular/cdk/portal"; +import { + Component, + ElementRef, + EventEmitter, + NgZone, + OnInit, + Output, + TemplateRef, + ViewChild, + ViewContainerRef, +} from "@angular/core"; +import { merge } from "rxjs"; + +import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { Organization } from "jslib-common/models/domain/organization"; + +import { VaultFilterService } from "../../services/vaultFilter.service"; + +@Component({ + selector: "app-vault-select", + templateUrl: "vault-select.component.html", + animations: [ + trigger("transformPanel", [ + state( + "void", + style({ + opacity: 0, + }) + ), + transition( + "void => open", + animate( + "100ms linear", + style({ + opacity: 1, + }) + ) + ), + transition("* => void", animate("100ms linear", style({ opacity: 0 }))), + ]), + ], +}) +export class VaultSelectComponent implements OnInit { + @Output() onVaultSelectionChanged = new EventEmitter(); + + @ViewChild("toggleVaults", { read: ElementRef }) + buttonRef: ElementRef; + @ViewChild("vaultSelectorTemplate", { read: TemplateRef }) templateRef: TemplateRef; + + isOpen = false; + loaded = false; + organizations: Organization[]; + vaultFilter: VaultFilter = new VaultFilter(); + vaultFilterDisplay = ""; + enforcePersonalOwnwership = false; + overlayPostition: ConnectedPosition[] = [ + { + originX: "start", + originY: "bottom", + overlayX: "start", + overlayY: "top", + }, + ]; + + private overlayRef: OverlayRef; + + get show() { + return ( + (this.organizations.length > 0 && !this.enforcePersonalOwnwership) || + (this.organizations.length > 1 && this.enforcePersonalOwnwership) + ); + } + + constructor( + private vaultFilterService: VaultFilterService, + private i18nService: I18nService, + private ngZone: NgZone, + private broadcasterService: BroadcasterService, + private overlay: Overlay, + private viewContainerRef: ViewContainerRef + ) {} + + async ngOnInit() { + await this.load(); + this.broadcasterService.subscribe(this.constructor.name, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + await this.load(); + break; + default: + break; + } + }); + }); + } + + async load() { + this.vaultFilter = this.vaultFilterService.getVaultFilter(); + this.organizations = (await this.vaultFilterService.buildOrganizations()).sort((a, b) => + a.name.localeCompare(b.name) + ); + this.enforcePersonalOwnwership = + await this.vaultFilterService.checkForPersonalOwnershipPolicy(); + + if (this.show) { + if (this.enforcePersonalOwnwership && !this.vaultFilter.myVaultOnly) { + this.vaultFilterService.setVaultFilter(this.organizations[0].id); + this.vaultFilter.selectedOrganizationId = this.organizations[0].id; + this.vaultFilterDisplay = this.organizations.find( + (o) => o.id === this.vaultFilter.selectedOrganizationId + ).name; + } else if (this.vaultFilter.myVaultOnly) { + this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.myVault); + } else if (this.vaultFilter.selectedOrganizationId != null) { + this.vaultFilterDisplay = this.organizations.find( + (o) => o.id === this.vaultFilter.selectedOrganizationId + ).name; + } else { + this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.allVaults); + } + } + this.loaded = true; + } + + openOverlay() { + const viewPortHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); + const positionStrategyBuilder = this.overlay.position(); + + const positionStrategy = positionStrategyBuilder + .flexibleConnectedTo(this.buttonRef.nativeElement) + .withFlexibleDimensions(true) + .withPush(true) + .withViewportMargin(10) + .withGrowAfterOpen(true) + .withPositions(this.overlayPostition); + + this.overlayRef = this.overlay.create({ + hasBackdrop: false, + positionStrategy, + maxHeight: viewPortHeight - 160, + backdropClass: "cdk-overlay-transparent-backdrop", + scrollStrategy: this.overlay.scrollStrategies.close(), + }); + + const templatePortal = new TemplatePortal(this.templateRef, this.viewContainerRef); + this.overlayRef.attach(templatePortal); + this.isOpen = true; + + // Handle closing + merge( + this.overlayRef.outsidePointerEvents(), + this.overlayRef.backdropClick(), + this.overlayRef.detachments() + ).subscribe(() => { + this.close(); + }); + } + + close() { + if (this.overlayRef) { + this.overlayRef.dispose(); + this.overlayRef = undefined; + } + this.isOpen = false; + } + + selectOrganization(organization: Organization) { + this.vaultFilterDisplay = organization.name; + this.vaultFilterService.setVaultFilter(organization.id); + this.onVaultSelectionChanged.emit(); + this.close(); + } + selectAllVaults() { + this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.allVaults); + this.vaultFilterService.setVaultFilter(this.vaultFilterService.allVaults); + this.onVaultSelectionChanged.emit(); + this.close(); + } + selectMyVault() { + this.vaultFilterDisplay = this.i18nService.t(this.vaultFilterService.myVault); + this.vaultFilterService.setVaultFilter(this.vaultFilterService.myVault); + this.onVaultSelectionChanged.emit(); + this.close(); + } +} diff --git a/apps/browser/src/popup/vault/view-custom-fields.component.html b/apps/browser/src/popup/vault/view-custom-fields.component.html new file mode 100644 index 0000000000..ebedd30776 --- /dev/null +++ b/apps/browser/src/popup/vault/view-custom-fields.component.html @@ -0,0 +1,91 @@ + +

+ {{ "customFields" | i18n }} +

+
+
+
+ {{ field.name }} +
+ {{ field.value || " " }} +
+
+ {{ field.maskedValue }} + + +
+
+ + + {{ field.value }} +
+
+
+ + {{ "linkedValue" | i18n }} +
+ {{ cipher.linkedFieldI18nKey(field.linkedId) | i18n }} +
+
+
+ + + +
+
+
+
diff --git a/apps/browser/src/popup/vault/view-custom-fields.component.ts b/apps/browser/src/popup/vault/view-custom-fields.component.ts new file mode 100644 index 0000000000..30046a3110 --- /dev/null +++ b/apps/browser/src/popup/vault/view-custom-fields.component.ts @@ -0,0 +1,14 @@ +import { Component } from "@angular/core"; + +import { ViewCustomFieldsComponent as BaseViewCustomFieldsComponent } from "jslib-angular/components/view-custom-fields.component"; +import { EventService } from "jslib-common/abstractions/event.service"; + +@Component({ + selector: "app-vault-view-custom-fields", + templateUrl: "view-custom-fields.component.html", +}) +export class ViewCustomFieldsComponent extends BaseViewCustomFieldsComponent { + constructor(eventService: EventService) { + super(eventService); + } +} diff --git a/apps/browser/src/popup/vault/view.component.html b/apps/browser/src/popup/vault/view.component.html new file mode 100644 index 0000000000..fa69a3c34a --- /dev/null +++ b/apps/browser/src/popup/vault/view.component.html @@ -0,0 +1,528 @@ +
+
+ +
+

+ {{ "viewItem" | i18n }} +

+
+ +
+
+
+
+

+ {{ "itemInformation" | i18n }} +

+
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+
+ {{ "password" | i18n }} +
+ {{ cipher.login.maskedPassword }} +
+
+
+
+
+ + + + +
+
+
+
+ {{ "verificationCodeTotp" | i18n }} + {{ totpCodeFormatted }} +
+ + {{ totpSec }} + + + + + + + +
+ +
+
+
+ +
+
+ {{ "cardholderName" | i18n }} + {{ cipher.card.cardholderName }} +
+
+
+ {{ "number" | i18n }} + {{ + cipher.card.maskedNumber | creditCardNumber: cipher.card.brand + }} + {{ + cipher.card.number | creditCardNumber: cipher.card.brand + }} +
+
+ + +
+
+
+ {{ "brand" | i18n }} + {{ cipher.card.brand }} +
+
+ {{ "expiration" | i18n }} + {{ cipher.card.expiration }} +
+
+
+ {{ "securityCode" | i18n }} + {{ cipher.card.maskedCode }} + {{ cipher.card.code }} +
+
+ + +
+
+
+ +
+
+ {{ "identityName" | i18n }} + {{ cipher.identity.fullName }} +
+
+ {{ "username" | i18n }} + {{ cipher.identity.username }} +
+
+ {{ "company" | i18n }} + {{ cipher.identity.company }} +
+
+ {{ "ssn" | i18n }} + {{ cipher.identity.ssn }} +
+
+ {{ "passportNumber" | i18n }} + {{ cipher.identity.passportNumber }} +
+
+ {{ "licenseNumber" | i18n }} + {{ cipher.identity.licenseNumber }} +
+
+ {{ "email" | i18n }} + {{ cipher.identity.email }} +
+
+ {{ "phone" | i18n }} + {{ cipher.identity.phone }} +
+
+ {{ "address" | i18n }} +
{{ cipher.identity.address1 }}
+
{{ cipher.identity.address2 }}
+
{{ cipher.identity.address3 }}
+
{{ cipher.identity.fullAddressPart2 }}
+
{{ cipher.identity.country }}
+
+
+
+
+
+
+
+
+ + + + + +
+
+ + +
+
+
+
+
+

+ +

+
+
+ +
+
+
+
+ +
+
+

+ {{ "attachments" | i18n }} +

+
+ +
+
+
+
+ + + + + + +
+
+
+ +
+
diff --git a/apps/browser/src/popup/vault/view.component.ts b/apps/browser/src/popup/vault/view.component.ts new file mode 100644 index 0000000000..4f08171bf8 --- /dev/null +++ b/apps/browser/src/popup/vault/view.component.ts @@ -0,0 +1,292 @@ +import { Location } from "@angular/common"; +import { ChangeDetectorRef, Component, NgZone } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { ViewComponent as BaseViewComponent } from "jslib-angular/components/view.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { Cipher } from "jslib-common/models/domain/cipher"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; + +import { BrowserApi } from "../../browser/browserApi"; +import { AutofillService } from "../../services/abstractions/autofill.service"; +import { PopupUtilsService } from "../services/popup-utils.service"; + +const BroadcasterSubscriptionId = "ChildViewComponent"; + +@Component({ + selector: "app-vault-view", + templateUrl: "view.component.html", +}) +export class ViewComponent extends BaseViewComponent { + showAttachments = true; + pageDetails: any[] = []; + tab: any; + loadPageDetailsTimeout: number; + inPopout = false; + cipherType = CipherType; + + constructor( + cipherService: CipherService, + totpService: TotpService, + tokenService: TokenService, + i18nService: I18nService, + cryptoService: CryptoService, + platformUtilsService: PlatformUtilsService, + auditService: AuditService, + private route: ActivatedRoute, + private router: Router, + private location: Location, + broadcasterService: BroadcasterService, + ngZone: NgZone, + changeDetectorRef: ChangeDetectorRef, + stateService: StateService, + eventService: EventService, + private autofillService: AutofillService, + private messagingService: MessagingService, + private popupUtilsService: PopupUtilsService, + apiService: ApiService, + passwordRepromptService: PasswordRepromptService, + logService: LogService + ) { + super( + cipherService, + totpService, + tokenService, + i18nService, + cryptoService, + platformUtilsService, + auditService, + window, + broadcasterService, + ngZone, + changeDetectorRef, + eventService, + apiService, + passwordRepromptService, + logService, + stateService + ); + } + + ngOnInit() { + this.inPopout = this.popupUtilsService.inPopout(window); + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (params.cipherId) { + this.cipherId = params.cipherId; + } else { + this.close(); + } + + await this.load(); + }); + + super.ngOnInit(); + + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "collectPageDetailsResponse": + if (message.sender === BroadcasterSubscriptionId) { + this.pageDetails.push({ + frameId: message.webExtSender.frameId, + tab: message.tab, + details: message.details, + }); + } + break; + case "tabChanged": + case "windowChanged": + if (this.loadPageDetailsTimeout != null) { + window.clearTimeout(this.loadPageDetailsTimeout); + } + this.loadPageDetailsTimeout = window.setTimeout(() => this.loadPageDetails(), 500); + break; + default: + break; + } + }); + }); + } + + ngOnDestroy() { + super.ngOnDestroy(); + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async load() { + await super.load(); + await this.loadPageDetails(); + } + + async edit() { + if (this.cipher.isDeleted) { + return false; + } + if (!(await super.edit())) { + return false; + } + + this.router.navigate(["/edit-cipher"], { queryParams: { cipherId: this.cipher.id } }); + return true; + } + + async clone() { + if (this.cipher.isDeleted) { + return false; + } + + if (!(await super.clone())) { + return false; + } + + this.router.navigate(["/clone-cipher"], { + queryParams: { + cloneMode: true, + cipherId: this.cipher.id, + }, + }); + return true; + } + + async share() { + if (!(await super.share())) { + return false; + } + + if (this.cipher.organizationId == null) { + this.router.navigate(["/share-cipher"], { + replaceUrl: true, + queryParams: { cipherId: this.cipher.id }, + }); + } + return true; + } + + async fillCipher() { + const didAutofill = await this.doAutofill(); + if (didAutofill) { + this.platformUtilsService.showToast("success", null, this.i18nService.t("autoFillSuccess")); + } + } + + async fillCipherAndSave() { + const didAutofill = await this.doAutofill(); + + if (didAutofill) { + if (this.tab == null) { + throw new Error("No tab found."); + } + + if (this.cipher.login.uris == null) { + this.cipher.login.uris = []; + } else { + if (this.cipher.login.uris.some((uri) => uri.uri === this.tab.url)) { + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("autoFillSuccessAndSavedUri") + ); + return; + } + } + + const loginUri = new LoginUriView(); + loginUri.uri = this.tab.url; + this.cipher.login.uris.push(loginUri); + + try { + const cipher: Cipher = await this.cipherService.encrypt(this.cipher); + await this.cipherService.saveWithServer(cipher); + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("autoFillSuccessAndSavedUri") + ); + this.messagingService.send("editedCipher"); + } catch { + this.platformUtilsService.showToast("error", null, this.i18nService.t("unexpectedError")); + } + } + } + + async restore() { + if (!this.cipher.isDeleted) { + return false; + } + if (await super.restore()) { + this.close(); + return true; + } + return false; + } + + async delete() { + if (await super.delete()) { + this.messagingService.send("deletedCipher"); + this.close(); + return true; + } + return false; + } + + close() { + this.location.back(); + } + + private async loadPageDetails() { + this.pageDetails = []; + this.tab = await BrowserApi.getTabFromCurrentWindow(); + if (this.tab == null) { + return; + } + BrowserApi.tabSendMessage(this.tab, { + command: "collectPageDetails", + tab: this.tab, + sender: BroadcasterSubscriptionId, + }); + } + + private async doAutofill() { + if (!(await this.promptPassword())) { + return false; + } + + if (this.pageDetails == null || this.pageDetails.length === 0) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("autofillError")); + return false; + } + + try { + this.totpCode = await this.autofillService.doAutoFill({ + cipher: this.cipher, + pageDetails: this.pageDetails, + doc: window.document, + fillNewPassword: true, + }); + if (this.totpCode != null) { + this.platformUtilsService.copyToClipboard(this.totpCode, { window: window }); + } + } catch { + this.platformUtilsService.showToast("error", null, this.i18nService.t("autofillError")); + this.changeDetectorRef.detectChanges(); + return false; + } + + return true; + } +} diff --git a/apps/browser/src/safari/desktop.xcodeproj/project.pbxproj b/apps/browser/src/safari/desktop.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..fc05760fc9 --- /dev/null +++ b/apps/browser/src/safari/desktop.xcodeproj/project.pbxproj @@ -0,0 +1,558 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 55E0374D2577FA6B00979016 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E0374C2577FA6B00979016 /* AppDelegate.swift */; }; + 55E037502577FA6B00979016 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 55E0374E2577FA6B00979016 /* Main.storyboard */; }; + 55E037522577FA6B00979016 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E037512577FA6B00979016 /* ViewController.swift */; }; + 55E037542577FA6E00979016 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55E037532577FA6E00979016 /* Assets.xcassets */; }; + 55E0375B2577FA6F00979016 /* safari.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 55E0375A2577FA6F00979016 /* safari.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 55E037602577FA6F00979016 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55E0375F2577FA6F00979016 /* Cocoa.framework */; }; + 55E037632577FA6F00979016 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55E037622577FA6F00979016 /* SafariWebExtensionHandler.swift */; }; + 55E037792577FA6F00979016 /* popup in Resources */ = {isa = PBXBuildFile; fileRef = 55E037702577FA6F00979016 /* popup */; }; + 55E0377A2577FA6F00979016 /* background.js in Resources */ = {isa = PBXBuildFile; fileRef = 55E037712577FA6F00979016 /* background.js */; }; + 55E0377B2577FA6F00979016 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 55E037722577FA6F00979016 /* images */; }; + 55E0377C2577FA6F00979016 /* notification in Resources */ = {isa = PBXBuildFile; fileRef = 55E037732577FA6F00979016 /* notification */; }; + 55E0377D2577FA6F00979016 /* content in Resources */ = {isa = PBXBuildFile; fileRef = 55E037742577FA6F00979016 /* content */; }; + 55E0377E2577FA6F00979016 /* vendor.js in Resources */ = {isa = PBXBuildFile; fileRef = 55E037752577FA6F00979016 /* vendor.js */; }; + 55E0377F2577FA6F00979016 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = 55E037762577FA6F00979016 /* manifest.json */; }; + 55E037802577FA6F00979016 /* background.html in Resources */ = {isa = PBXBuildFile; fileRef = 55E037772577FA6F00979016 /* background.html */; }; + 55E037812577FA6F00979016 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 55E037782577FA6F00979016 /* _locales */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 55E0375C2577FA6F00979016 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 55E037402577FA6B00979016 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 55E037592577FA6F00979016; + remoteInfo = safari; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 55E0376B2577FA6F00979016 /* Embed App Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 55E0375B2577FA6F00979016 /* safari.appex in Embed App Extensions */, + ); + name = "Embed App Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 5508DD7926051B5900A85C58 /* libswiftAppKit.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libswiftAppKit.tbd; path = usr/lib/swift/libswiftAppKit.tbd; sourceTree = SDKROOT; }; + 55E037482577FA6B00979016 /* desktop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = desktop.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 55E0374B2577FA6B00979016 /* desktop.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = desktop.entitlements; sourceTree = ""; }; + 55E0374C2577FA6B00979016 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 55E0374F2577FA6B00979016 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 55E037512577FA6B00979016 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 55E037532577FA6E00979016 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 55E037552577FA6E00979016 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 55E0375A2577FA6F00979016 /* safari.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = safari.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 55E0375F2577FA6F00979016 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 55E037622577FA6F00979016 /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = ""; }; + 55E037642577FA6F00979016 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 55E037652577FA6F00979016 /* safari.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = safari.entitlements; sourceTree = ""; }; + 55E037702577FA6F00979016 /* popup */ = {isa = PBXFileReference; lastKnownFileType = folder; name = popup; path = ../../../build/popup; sourceTree = ""; }; + 55E037712577FA6F00979016 /* background.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = background.js; path = ../../../build/background.js; sourceTree = ""; }; + 55E037722577FA6F00979016 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../../../build/images; sourceTree = ""; }; + 55E037732577FA6F00979016 /* notification */ = {isa = PBXFileReference; lastKnownFileType = folder; name = notification; path = ../../../build/notification; sourceTree = ""; }; + 55E037742577FA6F00979016 /* content */ = {isa = PBXFileReference; lastKnownFileType = folder; name = content; path = ../../../build/content; sourceTree = ""; }; + 55E037752577FA6F00979016 /* vendor.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = vendor.js; path = ../../../build/vendor.js; sourceTree = ""; }; + 55E037762577FA6F00979016 /* manifest.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = manifest.json; path = ../../../build/manifest.json; sourceTree = ""; }; + 55E037772577FA6F00979016 /* background.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = background.html; path = ../../../build/background.html; sourceTree = ""; }; + 55E037782577FA6F00979016 /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; name = _locales; path = ../../../build/_locales; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 55E037452577FA6B00979016 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 55E037572577FA6F00979016 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 55E037602577FA6F00979016 /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 55E0373F2577FA6B00979016 = { + isa = PBXGroup; + children = ( + 55E0374A2577FA6B00979016 /* desktop */, + 55E037612577FA6F00979016 /* safari */, + 55E0375E2577FA6F00979016 /* Frameworks */, + 55E037492577FA6B00979016 /* Products */, + ); + sourceTree = ""; + }; + 55E037492577FA6B00979016 /* Products */ = { + isa = PBXGroup; + children = ( + 55E037482577FA6B00979016 /* desktop.app */, + 55E0375A2577FA6F00979016 /* safari.appex */, + ); + name = Products; + sourceTree = ""; + }; + 55E0374A2577FA6B00979016 /* desktop */ = { + isa = PBXGroup; + children = ( + 55E0374B2577FA6B00979016 /* desktop.entitlements */, + 55E0374C2577FA6B00979016 /* AppDelegate.swift */, + 55E0374E2577FA6B00979016 /* Main.storyboard */, + 55E037512577FA6B00979016 /* ViewController.swift */, + 55E037532577FA6E00979016 /* Assets.xcassets */, + 55E037552577FA6E00979016 /* Info.plist */, + ); + path = desktop; + sourceTree = ""; + }; + 55E0375E2577FA6F00979016 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 5508DD7926051B5900A85C58 /* libswiftAppKit.tbd */, + 55E0375F2577FA6F00979016 /* Cocoa.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 55E037612577FA6F00979016 /* safari */ = { + isa = PBXGroup; + children = ( + 55E0376F2577FA6F00979016 /* Resources */, + 55E037622577FA6F00979016 /* SafariWebExtensionHandler.swift */, + 55E037642577FA6F00979016 /* Info.plist */, + 55E037652577FA6F00979016 /* safari.entitlements */, + ); + path = safari; + sourceTree = ""; + }; + 55E0376F2577FA6F00979016 /* Resources */ = { + isa = PBXGroup; + children = ( + 55E037702577FA6F00979016 /* popup */, + 55E037712577FA6F00979016 /* background.js */, + 55E037722577FA6F00979016 /* images */, + 55E037732577FA6F00979016 /* notification */, + 55E037742577FA6F00979016 /* content */, + 55E037752577FA6F00979016 /* vendor.js */, + 55E037762577FA6F00979016 /* manifest.json */, + 55E037772577FA6F00979016 /* background.html */, + 55E037782577FA6F00979016 /* _locales */, + ); + name = Resources; + path = safari; + sourceTree = SOURCE_ROOT; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 55E037472577FA6B00979016 /* desktop */ = { + isa = PBXNativeTarget; + buildConfigurationList = 55E0376C2577FA6F00979016 /* Build configuration list for PBXNativeTarget "desktop" */; + buildPhases = ( + 55E037442577FA6B00979016 /* Sources */, + 55E037452577FA6B00979016 /* Frameworks */, + 55E037462577FA6B00979016 /* Resources */, + 55E0376B2577FA6F00979016 /* Embed App Extensions */, + ); + buildRules = ( + ); + dependencies = ( + 55E0375D2577FA6F00979016 /* PBXTargetDependency */, + ); + name = desktop; + productName = desktop; + productReference = 55E037482577FA6B00979016 /* desktop.app */; + productType = "com.apple.product-type.application"; + }; + 55E037592577FA6F00979016 /* safari */ = { + isa = PBXNativeTarget; + buildConfigurationList = 55E037682577FA6F00979016 /* Build configuration list for PBXNativeTarget "safari" */; + buildPhases = ( + 55E037562577FA6F00979016 /* Sources */, + 55E037572577FA6F00979016 /* Frameworks */, + 55E037582577FA6F00979016 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = safari; + productName = safari; + productReference = 55E0375A2577FA6F00979016 /* safari.appex */; + productType = "com.apple.product-type.app-extension"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 55E037402577FA6B00979016 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1220; + LastUpgradeCheck = 1220; + ORGANIZATIONNAME = "8bit Solutions LLC"; + TargetAttributes = { + 55E037472577FA6B00979016 = { + CreatedOnToolsVersion = 12.2; + }; + 55E037592577FA6F00979016 = { + CreatedOnToolsVersion = 12.2; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + }; + }; + buildConfigurationList = 55E037432577FA6B00979016 /* Build configuration list for PBXProject "desktop" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 55E0373F2577FA6B00979016; + productRefGroup = 55E037492577FA6B00979016 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 55E037472577FA6B00979016 /* desktop */, + 55E037592577FA6F00979016 /* safari */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 55E037462577FA6B00979016 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 55E037542577FA6E00979016 /* Assets.xcassets in Resources */, + 55E037502577FA6B00979016 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 55E037582577FA6F00979016 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 55E037812577FA6F00979016 /* _locales in Resources */, + 55E0377B2577FA6F00979016 /* images in Resources */, + 55E0377F2577FA6F00979016 /* manifest.json in Resources */, + 55E037802577FA6F00979016 /* background.html in Resources */, + 55E0377A2577FA6F00979016 /* background.js in Resources */, + 55E037792577FA6F00979016 /* popup in Resources */, + 55E0377C2577FA6F00979016 /* notification in Resources */, + 55E0377E2577FA6F00979016 /* vendor.js in Resources */, + 55E0377D2577FA6F00979016 /* content in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 55E037442577FA6B00979016 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 55E037522577FA6B00979016 /* ViewController.swift in Sources */, + 55E0374D2577FA6B00979016 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 55E037562577FA6F00979016 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 55E037632577FA6F00979016 /* SafariWebExtensionHandler.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 55E0375D2577FA6F00979016 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 55E037592577FA6F00979016 /* safari */; + targetProxy = 55E0375C2577FA6F00979016 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 55E0374E2577FA6B00979016 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 55E0374F2577FA6B00979016 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 55E037662577FA6F00979016 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "Mac Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 55E037672577FA6F00979016 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "Mac Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 55E037692577FA6F00979016 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_ENTITLEMENTS = safari/safari.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = LTZ2PFU5D6; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = safari/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop.safari; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 55E0376A2577FA6F00979016 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_ENTITLEMENTS = safari/safari.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = LTZ2PFU5D6; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = safari/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@executable_path/../../../../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop.safari; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 55E0376D2577FA6F00979016 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = desktop/desktop.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = LTZ2PFU5D6; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = desktop/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 55E0376E2577FA6F00979016 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_ENTITLEMENTS = desktop/desktop.entitlements; + CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = LTZ2PFU5D6; + ENABLE_HARDENED_RUNTIME = YES; + INFOPLIST_FILE = desktop/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 10.14; + PRODUCT_BUNDLE_IDENTIFIER = com.bitwarden.desktop; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 55E037432577FA6B00979016 /* Build configuration list for PBXProject "desktop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 55E037662577FA6F00979016 /* Debug */, + 55E037672577FA6F00979016 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 55E037682577FA6F00979016 /* Build configuration list for PBXNativeTarget "safari" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 55E037692577FA6F00979016 /* Debug */, + 55E0376A2577FA6F00979016 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 55E0376C2577FA6F00979016 /* Build configuration list for PBXNativeTarget "desktop" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 55E0376D2577FA6F00979016 /* Debug */, + 55E0376E2577FA6F00979016 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 55E037402577FA6B00979016 /* Project object */; +} diff --git a/apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..919434a625 --- /dev/null +++ b/apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000000..18d981003d --- /dev/null +++ b/apps/browser/src/safari/desktop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/apps/browser/src/safari/desktop.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme b/apps/browser/src/safari/desktop.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme new file mode 100644 index 0000000000..7dd13c8dc8 --- /dev/null +++ b/apps/browser/src/safari/desktop.xcodeproj/xcshareddata/xcschemes/desktop.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/browser/src/safari/desktop/AppDelegate.swift b/apps/browser/src/safari/desktop/AppDelegate.swift new file mode 100644 index 0000000000..6222982a6e --- /dev/null +++ b/apps/browser/src/safari/desktop/AppDelegate.swift @@ -0,0 +1,18 @@ +import Cocoa + +@main +class AppDelegate: NSObject, NSApplicationDelegate { + + func applicationDidFinishLaunching(_ notification: Notification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(_ notification: Notification) { + // Insert code here to tear down your application + } + + func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + +} diff --git a/apps/browser/src/safari/desktop/Assets.xcassets/AccentColor.colorset/Contents.json b/apps/browser/src/safari/desktop/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000000..eb87897008 --- /dev/null +++ b/apps/browser/src/safari/desktop/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/Contents.json b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..6bf9a9b330 --- /dev/null +++ b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,62 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon32.png", + "scale" : "1x" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon128.png", + "scale" : "1x" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon128.png b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon128.png new file mode 100644 index 0000000000..7268b7041d Binary files /dev/null and b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon128.png differ diff --git a/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon16.png b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon16.png new file mode 100644 index 0000000000..dadec18fbb Binary files /dev/null and b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon16.png differ diff --git a/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon32.png b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon32.png new file mode 100644 index 0000000000..c1289d156f Binary files /dev/null and b/apps/browser/src/safari/desktop/Assets.xcassets/AppIcon.appiconset/icon32.png differ diff --git a/apps/browser/src/safari/desktop/Assets.xcassets/Contents.json b/apps/browser/src/safari/desktop/Assets.xcassets/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/apps/browser/src/safari/desktop/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/browser/src/safari/desktop/Base.lproj/Main.storyboard b/apps/browser/src/safari/desktop/Base.lproj/Main.storyboard new file mode 100644 index 0000000000..5a53dedcec --- /dev/null +++ b/apps/browser/src/safari/desktop/Base.lproj/Main.storyboard @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/browser/src/safari/desktop/Info.plist b/apps/browser/src/safari/desktop/Info.plist new file mode 100644 index 0000000000..30a64ff889 --- /dev/null +++ b/apps/browser/src/safari/desktop/Info.plist @@ -0,0 +1,34 @@ + + + + + LSApplicationCategoryType + public.app-category.productivity + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2015-2022 Bitwarden Inc. All rights reserved. + NSMainStoryboardFile + Main + NSPrincipalClass + NSApplication + + diff --git a/apps/browser/src/safari/desktop/ViewController.swift b/apps/browser/src/safari/desktop/ViewController.swift new file mode 100644 index 0000000000..fbda5decf8 --- /dev/null +++ b/apps/browser/src/safari/desktop/ViewController.swift @@ -0,0 +1,44 @@ +import Cocoa +import SafariServices.SFSafariApplication +import SafariServices.SFSafariExtensionManager + +let appName = "desktop" +let extensionBundleIdentifier = "com.bitwarden.desktop.Extension" + +class ViewController: NSViewController { + + @IBOutlet var appNameLabel: NSTextField! + + override func viewDidLoad() { + super.viewDidLoad() + self.appNameLabel.stringValue = appName + SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in + guard let state = state, error == nil else { + // Insert code to inform the user that something went wrong. + return + } + + DispatchQueue.main.async { + if (state.isEnabled) { + self.appNameLabel.stringValue = "\(appName)'s extension is currently on." + } else { + self.appNameLabel.stringValue = "\(appName)'s extension is currently off. You can turn it on in Safari Extensions preferences." + } + } + } + } + + @IBAction func openSafariExtensionPreferences(_ sender: AnyObject?) { + SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in + guard error == nil else { + // Insert code to inform the user that something went wrong. + return + } + + DispatchQueue.main.async { + NSApplication.shared.terminate(nil) + } + } + } + +} diff --git a/apps/browser/src/safari/desktop/desktop.entitlements b/apps/browser/src/safari/desktop/desktop.entitlements new file mode 100644 index 0000000000..6d968edb4f --- /dev/null +++ b/apps/browser/src/safari/desktop/desktop.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-write + + + diff --git a/apps/browser/src/safari/safari/Info.plist b/apps/browser/src/safari/safari/Info.plist new file mode 100644 index 0000000000..e085116c43 --- /dev/null +++ b/apps/browser/src/safari/safari/Info.plist @@ -0,0 +1,41 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Bitwarden + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 0.0.1 + CFBundleVersion + 0.0.2 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSExtension + + NSExtensionPointIdentifier + com.apple.Safari.web-extension + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler + + NSHumanReadableCopyright + Copyright © 2015-2022 Bitwarden Inc. All rights reserved. + NSHumanReadableDescription + A secure and free password manager for all of your devices. + SFSafariAppExtensionBundleIdentifiersToReplace + + com.bitwarden.desktop.safari + + + diff --git a/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift b/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift new file mode 100644 index 0000000000..5a12da3a02 --- /dev/null +++ b/apps/browser/src/safari/safari/SafariWebExtensionHandler.swift @@ -0,0 +1,200 @@ +import SafariServices +import os.log +import LocalAuthentication + +let SFExtensionMessageKey = "message" +let ServiceName = "Bitwarden" +let ServiceNameBiometric = ServiceName + "_biometric" + +class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { + + func beginRequest(with context: NSExtensionContext) { + let item = context.inputItems[0] as! NSExtensionItem + let message = item.userInfo?[SFExtensionMessageKey] as AnyObject? + os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg) + + let response = NSExtensionItem() + + guard let command = message?["command"] as? String else { + return + } + + switch (command) { + case "readFromClipboard": + let pasteboard = NSPasteboard.general + response.userInfo = [ SFExtensionMessageKey: pasteboard.pasteboardItems?.first?.string(forType: .string) as Any ] + break + case "copyToClipboard": + guard let msg = message?["data"] as? String else { + return + } + let pasteboard = NSPasteboard.general + pasteboard.clearContents() + pasteboard.setString(msg, forType: .string) + case "showPopover": + SFSafariApplication.getActiveWindow { win in + win?.getToolbarItem(completionHandler: { item in + item?.showPopover() + }) + } + break + case "downloadFile": + guard let jsonData = message?["data"] as? String else { + return + } + guard let dlMsg: DownloadFileMessage = jsonDeserialize(json: jsonData) else { + return + } + var blobData: Data? + if dlMsg.blobOptions?.type == "text/plain" { + blobData = dlMsg.blobData?.data(using: .utf8) + } else if let blob = dlMsg.blobData { + blobData = Data(base64Encoded: blob) + } + guard let data = blobData else { + return + } + let panel = NSSavePanel() + panel.isFloatingPanel = true + panel.canCreateDirectories = true + panel.nameFieldStringValue = dlMsg.fileName + panel.begin { response in + if response == NSApplication.ModalResponse.OK { + if let url = panel.url { + do { + let fileManager = FileManager.default + if !fileManager.fileExists(atPath: url.absoluteString) { + fileManager.createFile(atPath: url.absoluteString, contents: Data(), + attributes: nil) + } + try data.write(to: url) + } catch { + print(error) + NSLog("ERROR in downloadFile, \(error)") + } + } + } + } + break + case "sleep": + DispatchQueue.main.asyncAfter(deadline: .now() + 10) { + context.completeRequest(returningItems: [response], completionHandler: nil) + } + return + case "biometricUnlock": + + var error: NSError? + let laContext = LAContext() + + laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) + + if let e = error, e.code != kLAErrorBiometryLockout { + response.userInfo = [ + SFExtensionMessageKey: [ + "message": [ + "command": "biometricUnlock", + "response": "not supported", + "timestamp": Int64(NSDate().timeIntervalSince1970 * 1000), + ], + ], + ] + break + } + + guard let accessControl = SecAccessControlCreateWithFlags(nil, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, [.privateKeyUsage, .userPresence], nil) else { + response.userInfo = [ + SFExtensionMessageKey: [ + "message": [ + "command": "biometricUnlock", + "response": "not supported", + "timestamp": Int64(NSDate().timeIntervalSince1970 * 1000), + ], + ], + ] + break + } + laContext.evaluateAccessControl(accessControl, operation: .useKeySign, localizedReason: "Bitwarden Safari Extension") { (success, error) in + if success { + guard let userId = message?["userId"] as? String else { + return + } + let passwordName = userId + "_masterkey_biometric" + var passwordLength: UInt32 = 0 + var passwordPtr: UnsafeMutableRawPointer? = nil + + var status = SecKeychainFindGenericPassword(nil, UInt32(ServiceNameBiometric.utf8.count), ServiceNameBiometric, UInt32(passwordName.utf8.count), passwordName, &passwordLength, &passwordPtr, nil) + if status != errSecSuccess { + let fallbackName = "key" + status = SecKeychainFindGenericPassword(nil, UInt32(ServiceNameBiometric.utf8.count), ServiceNameBiometric, UInt32(fallbackName.utf8.count), fallbackName, &passwordLength, &passwordPtr, nil) + } + + if status == errSecSuccess { + let result = NSString(bytes: passwordPtr!, length: Int(passwordLength), encoding: String.Encoding.utf8.rawValue) as String? + SecKeychainItemFreeContent(nil, passwordPtr) + + response.userInfo = [ SFExtensionMessageKey: [ + "message": [ + "command": "biometricUnlock", + "response": "unlocked", + "timestamp": Int64(NSDate().timeIntervalSince1970 * 1000), + "keyB64": result!.replacingOccurrences(of: "\"", with: ""), + ], + ]] + } else { + response.userInfo = [ + SFExtensionMessageKey: [ + "message": [ + "command": "biometricUnlock", + "response": "not enabled", + "timestamp": Int64(NSDate().timeIntervalSince1970 * 1000), + ], + ], + ] + } + } + + context.completeRequest(returningItems: [response], completionHandler: nil) + } + + return + default: + return + } + + context.completeRequest(returningItems: [response], completionHandler: nil) + } + +} + +func jsonSerialize(obj: T?) -> String? { + let encoder = JSONEncoder() + do { + let data = try encoder.encode(obj) + return String(data: data, encoding: .utf8) ?? "null" + } catch _ { + return "null" + } +} + +func jsonDeserialize(json: String?) -> T? { + if json == nil { + return nil + } + let decoder = JSONDecoder() + do { + let obj = try decoder.decode(T.self, from: json!.data(using: .utf8)!) + return obj + } catch _ { + return nil + } +} + +class DownloadFileMessage: Decodable, Encodable { + var fileName: String + var blobData: String? + var blobOptions: DownloadFileMessageBlobOptions? +} + +class DownloadFileMessageBlobOptions: Decodable, Encodable { + var type: String? +} diff --git a/apps/browser/src/safari/safari/safari.entitlements b/apps/browser/src/safari/safari/safari.entitlements new file mode 100644 index 0000000000..85c03d7b48 --- /dev/null +++ b/apps/browser/src/safari/safari/safari.entitlements @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-write + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/apps/browser/src/scripts/duo.js b/apps/browser/src/scripts/duo.js new file mode 100644 index 0000000000..8b712dcf25 --- /dev/null +++ b/apps/browser/src/scripts/duo.js @@ -0,0 +1,418 @@ +/** + * Duo Web SDK v2 + * Copyright 2017, Duo Security + */ + +var Duo; +(function (root, factory) { + // Browser globals (root is window) + var d = factory(); + // If the Javascript was loaded via a script tag, attempt to autoload + // the frame. + d._onReady(d.init); + // Attach Duo to the `window` object + root.Duo = Duo = d; +}(window, function () { + var DUO_MESSAGE_FORMAT = /^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/; + var DUO_ERROR_FORMAT = /^ERR\|[\w\s\.\(\)]+$/; + var DUO_OPEN_WINDOW_FORMAT = /^DUO_OPEN_WINDOW\|/; + var VALID_OPEN_WINDOW_DOMAINS = [ + 'duo.com', + 'duosecurity.com', + 'duomobile.s3-us-west-1.amazonaws.com' + ]; + + var iframeId = 'duo_iframe', + postAction = '', + postArgument = 'sig_response', + host, + sigRequest, + duoSig, + appSig, + iframe, + submitCallback; + + function throwError(message, url) { + throw new Error( + 'Duo Web SDK error: ' + message + + (url ? ('\n' + 'See ' + url + ' for more information') : '') + ); + } + + function hyphenize(str) { + return str.replace(/([a-z])([A-Z])/, '$1-$2').toLowerCase(); + } + + // cross-browser data attributes + function getDataAttribute(element, name) { + if ('dataset' in element) { + return element.dataset[name]; + } else { + return element.getAttribute('data-' + hyphenize(name)); + } + } + + // cross-browser event binding/unbinding + function on(context, event, fallbackEvent, callback) { + if ('addEventListener' in window) { + context.addEventListener(event, callback, false); + } else { + context.attachEvent(fallbackEvent, callback); + } + } + + function off(context, event, fallbackEvent, callback) { + if ('removeEventListener' in window) { + context.removeEventListener(event, callback, false); + } else { + context.detachEvent(fallbackEvent, callback); + } + } + + function onReady(callback) { + on(document, 'DOMContentLoaded', 'onreadystatechange', callback); + } + + function offReady(callback) { + off(document, 'DOMContentLoaded', 'onreadystatechange', callback); + } + + function onMessage(callback) { + on(window, 'message', 'onmessage', callback); + } + + function offMessage(callback) { + off(window, 'message', 'onmessage', callback); + } + + /** + * Parse the sig_request parameter, throwing errors if the token contains + * a server error or if the token is invalid. + * + * @param {String} sig Request token + */ + function parseSigRequest(sig) { + if (!sig) { + // nothing to do + return; + } + + // see if the token contains an error, throwing it if it does + if (sig.indexOf('ERR|') === 0) { + throwError(sig.split('|')[1]); + } + + // validate the token + if (sig.indexOf(':') === -1 || sig.split(':').length !== 2) { + throwError( + 'Duo was given a bad token. This might indicate a configuration ' + + 'problem with one of Duo\'s client libraries.', + 'https://www.duosecurity.com/docs/duoweb#first-steps' + ); + } + + var sigParts = sig.split(':'); + + // hang on to the token, and the parsed duo and app sigs + sigRequest = sig; + duoSig = sigParts[0]; + appSig = sigParts[1]; + + return { + sigRequest: sig, + duoSig: sigParts[0], + appSig: sigParts[1] + }; + } + + /** + * This function is set up to run when the DOM is ready, if the iframe was + * not available during `init`. + */ + function onDOMReady() { + iframe = document.getElementById(iframeId); + + if (!iframe) { + throw new Error( + 'This page does not contain an iframe for Duo to use.' + + 'Add an element like ' + + 'to this page. ' + + 'See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe ' + + 'for more information.' + ); + } + + // we've got an iframe, away we go! + ready(); + + // always clean up after yourself + offReady(onDOMReady); + } + + /** + * Validate that a MessageEvent came from the Duo service, and that it + * is a properly formatted payload. + * + * The Google Chrome sign-in page injects some JS into pages that also + * make use of postMessage, so we need to do additional validation above + * and beyond the origin. + * + * @param {MessageEvent} event Message received via postMessage + */ + function isDuoMessage(event) { + return Boolean( + event.origin === ('https://' + host) && + typeof event.data === 'string' && + ( + event.data.match(DUO_MESSAGE_FORMAT) || + event.data.match(DUO_ERROR_FORMAT) || + event.data.match(DUO_OPEN_WINDOW_FORMAT) + ) + ); + } + + /** + * Validate the request token and prepare for the iframe to become ready. + * + * All options below can be passed into an options hash to `Duo.init`, or + * specified on the iframe using `data-` attributes. + * + * Options specified using the options hash will take precedence over + * `data-` attributes. + * + * Example using options hash: + * ```javascript + * Duo.init({ + * iframe: "some_other_id", + * host: "api-main.duo.test", + * sig_request: "...", + * post_action: "/auth", + * post_argument: "resp" + * }); + * ``` + * + * Example using `data-` attributes: + * ``` + * + * ``` + * + * @param {Object} options + * @param {String} options.iframe The iframe, or id of an iframe to set up + * @param {String} options.host Hostname + * @param {String} options.sig_request Request token + * @param {String} [options.post_action=''] URL to POST back to after successful auth + * @param {String} [options.post_argument='sig_response'] Parameter name to use for response token + * @param {Function} [options.submit_callback] If provided, duo will not submit the form instead execute + * the callback function with reference to the "duo_form" form object + * submit_callback can be used to prevent the webpage from reloading. + */ + function init(options) { + if (options) { + if (options.host) { + host = options.host; + } + + if (options.sig_request) { + parseSigRequest(options.sig_request); + } + + if (options.post_action) { + postAction = options.post_action; + } + + if (options.post_argument) { + postArgument = options.post_argument; + } + + if (options.iframe) { + if (options.iframe.tagName) { + iframe = options.iframe; + } else if (typeof options.iframe === 'string') { + iframeId = options.iframe; + } + } + + if (typeof options.submit_callback === 'function') { + submitCallback = options.submit_callback; + } + } + + // if we were given an iframe, no need to wait for the rest of the DOM + if (false && iframe) { + ready(); + } else { + // try to find the iframe in the DOM + iframe = document.getElementById(iframeId); + + // iframe is in the DOM, away we go! + if (iframe) { + ready(); + } else { + // wait until the DOM is ready, then try again + onReady(onDOMReady); + } + } + + // always clean up after yourself! + offReady(init); + } + + /** + * This function is called when a message was received from another domain + * using the `postMessage` API. Check that the event came from the Duo + * service domain, and that the message is a properly formatted payload, + * then perform the post back to the primary service. + * + * @param event Event object (contains origin and data) + */ + function onReceivedMessage(event) { + if (isDuoMessage(event)) { + if (event.data.match(DUO_OPEN_WINDOW_FORMAT)) { + var url = event.data.substring("DUO_OPEN_WINDOW|".length); + if (isValidUrlToOpen(url)) { + // Open the URL that comes after the DUO_WINDOW_OPEN token. + window.open(url, "_self"); + } + } + else { + // the event came from duo, do the post back + doPostBack(event.data); + + // always clean up after yourself! + offMessage(onReceivedMessage); + } + } + } + + /** + * Validate that this passed in URL is one that we will actually allow to + * be opened. + * @param url String URL that the message poster wants to open + * @returns {boolean} true if we allow this url to be opened in the window + */ + function isValidUrlToOpen(url) { + if (!url) { + return false; + } + + var parser = document.createElement('a'); + parser.href = url; + + if (parser.protocol === "duotrustedendpoints:") { + return true; + } else if (parser.protocol !== "https:") { + return false; + } + + for (var i = 0; i < VALID_OPEN_WINDOW_DOMAINS.length; i++) { + if (parser.hostname.endsWith("." + VALID_OPEN_WINDOW_DOMAINS[i]) || + parser.hostname === VALID_OPEN_WINDOW_DOMAINS[i]) { + return true; + } + } + return false; + } + + /** + * Point the iframe at Duo, then wait for it to postMessage back to us. + */ + function ready() { + if (!host) { + host = getDataAttribute(iframe, 'host'); + + if (!host) { + throwError( + 'No API hostname is given for Duo to use. Be sure to pass ' + + 'a `host` parameter to Duo.init, or through the `data-host` ' + + 'attribute on the iframe element.', + 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' + ); + } + } + + if (!duoSig || !appSig) { + parseSigRequest(getDataAttribute(iframe, 'sigRequest')); + + if (!duoSig || !appSig) { + throwError( + 'No valid signed request is given. Be sure to give the ' + + '`sig_request` parameter to Duo.init, or use the ' + + '`data-sig-request` attribute on the iframe element.', + 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' + ); + } + } + + // if postAction/Argument are defaults, see if they are specified + // as data attributes on the iframe + if (postAction === '') { + postAction = getDataAttribute(iframe, 'postAction') || postAction; + } + + if (postArgument === 'sig_response') { + postArgument = getDataAttribute(iframe, 'postArgument') || postArgument; + } + + // point the iframe at Duo + iframe.src = [ + 'https://', host, '/frame/web/v1/auth?tx=', duoSig, + '&parent=', encodeURIComponent(document.location.href), + '&v=2.6' + ].join(''); + + // listen for the 'message' event + onMessage(onReceivedMessage); + } + + /** + * We received a postMessage from Duo. POST back to the primary service + * with the response token, and any additional user-supplied parameters + * given in form#duo_form. + */ + function doPostBack(response) { + // create a hidden input to contain the response token + var input = document.createElement('input'); + input.type = 'hidden'; + input.name = postArgument; + input.value = response + ':' + appSig; + + // user may supply their own form with additional inputs + var form = document.getElementById('duo_form'); + + // if the form doesn't exist, create one + if (!form) { + form = document.createElement('form'); + + // insert the new form after the iframe + iframe.parentElement.insertBefore(form, iframe.nextSibling); + } + + // make sure we are actually posting to the right place + form.method = 'POST'; + form.action = postAction; + + // add the response token input to the form + form.appendChild(input); + + // away we go! + if (typeof submitCallback === "function") { + submitCallback.call(null, form); + } else { + form.submit(); + } + } + + return { + init: init, + _onReady: onReady, + _parseSigRequest: parseSigRequest, + _isDuoMessage: isDuoMessage, + _doPostBack: doPostBack + }; +})); diff --git a/apps/browser/src/services/abstractions/autofill.service.ts b/apps/browser/src/services/abstractions/autofill.service.ts new file mode 100644 index 0000000000..68fb1b8dba --- /dev/null +++ b/apps/browser/src/services/abstractions/autofill.service.ts @@ -0,0 +1,7 @@ +import AutofillPageDetails from "../../models/autofillPageDetails"; + +export abstract class AutofillService { + getFormsWithPasswordFields: (pageDetails: AutofillPageDetails) => any[]; + doAutoFill: (options: any) => Promise; + doAutoFillActiveTab: (pageDetails: any, fromCommand: boolean) => Promise; +} diff --git a/apps/browser/src/services/abstractions/state.service.ts b/apps/browser/src/services/abstractions/state.service.ts new file mode 100644 index 0000000000..4d61cd61cf --- /dev/null +++ b/apps/browser/src/services/abstractions/state.service.ts @@ -0,0 +1,32 @@ +import { StateService as BaseStateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { StorageOptions } from "jslib-common/models/domain/storageOptions"; + +import { Account } from "src/models/account"; +import { BrowserComponentState } from "src/models/browserComponentState"; +import { BrowserGroupingsComponentState } from "src/models/browserGroupingsComponentState"; +import { BrowserSendComponentState } from "src/models/browserSendComponentState"; + +export abstract class StateService extends BaseStateServiceAbstraction { + getBrowserGroupingComponentState: ( + options?: StorageOptions + ) => Promise; + setBrowserGroupingComponentState: ( + value: BrowserGroupingsComponentState, + options?: StorageOptions + ) => Promise; + getBrowserCipherComponentState: (options?: StorageOptions) => Promise; + setBrowserCipherComponentState: ( + value: BrowserComponentState, + options?: StorageOptions + ) => Promise; + getBrowserSendComponentState: (options?: StorageOptions) => Promise; + setBrowserSendComponentState: ( + value: BrowserSendComponentState, + options?: StorageOptions + ) => Promise; + getBrowserSendTypeComponentState: (options?: StorageOptions) => Promise; + setBrowserSendTypeComponentState: ( + value: BrowserComponentState, + options?: StorageOptions + ) => Promise; +} diff --git a/apps/browser/src/services/autofill.service.ts b/apps/browser/src/services/autofill.service.ts new file mode 100644 index 0000000000..406bc15547 --- /dev/null +++ b/apps/browser/src/services/autofill.service.ts @@ -0,0 +1,1320 @@ +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { EventType } from "jslib-common/enums/eventType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { FieldView } from "jslib-common/models/view/fieldView"; + +import { BrowserApi } from "../browser/browserApi"; +import AutofillField from "../models/autofillField"; +import AutofillPageDetails from "../models/autofillPageDetails"; +import AutofillScript from "../models/autofillScript"; +import { StateService } from "../services/abstractions/state.service"; + +import { AutofillService as AutofillServiceInterface } from "./abstractions/autofill.service"; +import { + AutoFillConstants, + CreditCardAutoFillConstants, + IdentityAutoFillConstants, +} from "./autofillConstants"; + +export default class AutofillService implements AutofillServiceInterface { + constructor( + private cipherService: CipherService, + private stateService: StateService, + private totpService: TotpService, + private eventService: EventService, + private logService: LogService + ) {} + + getFormsWithPasswordFields(pageDetails: AutofillPageDetails): any[] { + const formData: any[] = []; + + const passwordFields = this.loadPasswordFields(pageDetails, true, true, false, false); + if (passwordFields.length === 0) { + return formData; + } + + for (const formKey in pageDetails.forms) { + // eslint-disable-next-line + if (!pageDetails.forms.hasOwnProperty(formKey)) { + continue; + } + + const formPasswordFields = passwordFields.filter((pf) => formKey === pf.form); + if (formPasswordFields.length > 0) { + let uf = this.findUsernameField(pageDetails, formPasswordFields[0], false, false, false); + if (uf == null) { + // not able to find any viewable username fields. maybe there are some "hidden" ones? + uf = this.findUsernameField(pageDetails, formPasswordFields[0], true, true, false); + } + formData.push({ + form: pageDetails.forms[formKey], + password: formPasswordFields[0], + username: uf, + passwords: formPasswordFields, + }); + } + } + + return formData; + } + + async doAutoFill(options: any) { + let totpPromise: Promise = null; + const tab = await this.getActiveTab(); + if (!tab || !options.cipher || !options.pageDetails || !options.pageDetails.length) { + throw new Error("Nothing to auto-fill."); + } + + const canAccessPremium = await this.stateService.getCanAccessPremium(); + let didAutofill = false; + options.pageDetails.forEach((pd: any) => { + // make sure we're still on correct tab + if (pd.tab.id !== tab.id || pd.tab.url !== tab.url) { + return; + } + + const fillScript = this.generateFillScript(pd.details, { + skipUsernameOnlyFill: options.skipUsernameOnlyFill || false, + onlyEmptyFields: options.onlyEmptyFields || false, + onlyVisibleFields: options.onlyVisibleFields || false, + fillNewPassword: options.fillNewPassword || false, + cipher: options.cipher, + }); + + if (!fillScript || !fillScript.script || !fillScript.script.length) { + return; + } + + // Add a small delay between operations + fillScript.properties.delay_between_operations = 20; + + didAutofill = true; + if (!options.skipLastUsed) { + this.cipherService.updateLastUsedDate(options.cipher.id); + } + + BrowserApi.tabSendMessage( + tab, + { + command: "fillForm", + fillScript: fillScript, + url: tab.url, + }, + { frameId: pd.frameId } + ); + + if ( + options.cipher.type !== CipherType.Login || + totpPromise || + !options.cipher.login.totp || + (!canAccessPremium && !options.cipher.organizationUseTotp) + ) { + return; + } + + totpPromise = this.totpService.isAutoCopyEnabled().then((enabled) => { + if (enabled) { + return this.totpService.getCode(options.cipher.login.totp); + } + return null; + }); + }); + + if (didAutofill) { + this.eventService.collect(EventType.Cipher_ClientAutofilled, options.cipher.id); + if (totpPromise != null) { + return await totpPromise; + } else { + return null; + } + } else { + throw new Error("Did not auto-fill."); + } + } + + async doAutoFillActiveTab(pageDetails: any, fromCommand: boolean) { + const tab = await this.getActiveTab(); + if (!tab || !tab.url) { + return; + } + + let cipher: CipherView; + if (fromCommand) { + cipher = await this.cipherService.getNextCipherForUrl(tab.url); + } else { + const lastLaunchedCipher = await this.cipherService.getLastLaunchedForUrl(tab.url, true); + if ( + lastLaunchedCipher && + Date.now().valueOf() - lastLaunchedCipher.localData?.lastLaunched?.valueOf() < 30000 + ) { + cipher = lastLaunchedCipher; + } else { + cipher = await this.cipherService.getLastUsedForUrl(tab.url, true); + } + + if (cipher == null) { + return null; + } + } + + if (cipher.reprompt !== CipherRepromptType.None) { + return; + } + + const totpCode = await this.doAutoFill({ + cipher: cipher, + pageDetails: pageDetails, + skipLastUsed: !fromCommand, + skipUsernameOnlyFill: !fromCommand, + onlyEmptyFields: !fromCommand, + onlyVisibleFields: !fromCommand, + fillNewPassword: fromCommand, + }); + + // Update last used index as autofill has succeed + if (fromCommand) { + this.cipherService.updateLastUsedIndexForUrl(tab.url); + } + + return totpCode; + } + + // Helpers + + private async getActiveTab(): Promise { + const tab = await BrowserApi.getTabFromCurrentWindow(); + if (!tab) { + throw new Error("No tab found."); + } + + return tab; + } + + private generateFillScript(pageDetails: AutofillPageDetails, options: any): AutofillScript { + if (!pageDetails || !options.cipher) { + return null; + } + + let fillScript = new AutofillScript(pageDetails.documentUUID); + const filledFields: { [id: string]: AutofillField } = {}; + const fields = options.cipher.fields; + + if (fields && fields.length) { + const fieldNames: string[] = []; + + fields.forEach((f: any) => { + if (this.hasValue(f.name)) { + fieldNames.push(f.name.toLowerCase()); + } + }); + + pageDetails.fields.forEach((field: any) => { + // eslint-disable-next-line + if (filledFields.hasOwnProperty(field.opid)) { + return; + } + + if (!field.viewable && field.tagName !== "span") { + return; + } + + const matchingIndex = this.findMatchingFieldIndex(field, fieldNames); + if (matchingIndex > -1) { + const matchingField: FieldView = fields[matchingIndex]; + let val; + if (matchingField.type === FieldType.Linked) { + // Assumption: Linked Field is not being used to autofill a boolean value + val = options.cipher.linkedFieldValue(matchingField.linkedId); + } else { + val = matchingField.value; + if (val == null && matchingField.type === FieldType.Boolean) { + val = "false"; + } + } + + filledFields[field.opid] = field; + this.fillByOpid(fillScript, field, val); + } + }); + } + + switch (options.cipher.type) { + case CipherType.Login: + fillScript = this.generateLoginFillScript(fillScript, pageDetails, filledFields, options); + break; + case CipherType.Card: + fillScript = this.generateCardFillScript(fillScript, pageDetails, filledFields, options); + break; + case CipherType.Identity: + fillScript = this.generateIdentityFillScript( + fillScript, + pageDetails, + filledFields, + options + ); + break; + default: + return null; + } + + return fillScript; + } + + private generateLoginFillScript( + fillScript: AutofillScript, + pageDetails: any, + filledFields: { [id: string]: AutofillField }, + options: any + ): AutofillScript { + if (!options.cipher.login) { + return null; + } + + const passwords: AutofillField[] = []; + const usernames: AutofillField[] = []; + let pf: AutofillField = null; + let username: AutofillField = null; + const login = options.cipher.login; + + if (!login.password || login.password === "") { + // No password for this login. Maybe they just wanted to auto-fill some custom fields? + fillScript = this.setFillScriptForFocus(filledFields, fillScript); + return fillScript; + } + + let passwordFields = this.loadPasswordFields( + pageDetails, + false, + false, + options.onlyEmptyFields, + options.fillNewPassword + ); + if (!passwordFields.length && !options.onlyVisibleFields) { + // not able to find any viewable password fields. maybe there are some "hidden" ones? + passwordFields = this.loadPasswordFields( + pageDetails, + true, + true, + options.onlyEmptyFields, + options.fillNewPassword + ); + } + + for (const formKey in pageDetails.forms) { + // eslint-disable-next-line + if (!pageDetails.forms.hasOwnProperty(formKey)) { + continue; + } + + const passwordFieldsForForm: AutofillField[] = []; + passwordFields.forEach((passField) => { + if (formKey === passField.form) { + passwordFieldsForForm.push(passField); + } + }); + + passwordFields.forEach((passField) => { + pf = passField; + passwords.push(pf); + + if (login.username) { + username = this.findUsernameField(pageDetails, pf, false, false, false); + + if (!username && !options.onlyVisibleFields) { + // not able to find any viewable username fields. maybe there are some "hidden" ones? + username = this.findUsernameField(pageDetails, pf, true, true, false); + } + + if (username) { + usernames.push(username); + } + } + }); + } + + if (passwordFields.length && !passwords.length) { + // The page does not have any forms with password fields. Use the first password field on the page and the + // input field just before it as the username. + + pf = passwordFields[0]; + passwords.push(pf); + + if (login.username && pf.elementNumber > 0) { + username = this.findUsernameField(pageDetails, pf, false, false, true); + + if (!username && !options.onlyVisibleFields) { + // not able to find any viewable username fields. maybe there are some "hidden" ones? + username = this.findUsernameField(pageDetails, pf, true, true, true); + } + + if (username) { + usernames.push(username); + } + } + } + + if (!passwordFields.length && !options.skipUsernameOnlyFill) { + // No password fields on this page. Let's try to just fuzzy fill the username. + pageDetails.fields.forEach((f: any) => { + if ( + f.viewable && + (f.type === "text" || f.type === "email" || f.type === "tel") && + this.fieldIsFuzzyMatch(f, AutoFillConstants.UsernameFieldNames) + ) { + usernames.push(f); + } + }); + } + + usernames.forEach((u) => { + // eslint-disable-next-line + if (filledFields.hasOwnProperty(u.opid)) { + return; + } + + filledFields[u.opid] = u; + this.fillByOpid(fillScript, u, login.username); + }); + + passwords.forEach((p) => { + // eslint-disable-next-line + if (filledFields.hasOwnProperty(p.opid)) { + return; + } + + filledFields[p.opid] = p; + this.fillByOpid(fillScript, p, login.password); + }); + + fillScript = this.setFillScriptForFocus(filledFields, fillScript); + return fillScript; + } + + private generateCardFillScript( + fillScript: AutofillScript, + pageDetails: any, + filledFields: { [id: string]: AutofillField }, + options: any + ): AutofillScript { + if (!options.cipher.card) { + return null; + } + + const fillFields: { [id: string]: AutofillField } = {}; + + pageDetails.fields.forEach((f: any) => { + if (this.forCustomFieldsOnly(f)) { + return; + } + + if (this.isExcludedType(f.type, AutoFillConstants.ExcludedAutofillTypes)) { + return; + } + + for (let i = 0; i < CreditCardAutoFillConstants.CardAttributes.length; i++) { + const attr = CreditCardAutoFillConstants.CardAttributes[i]; + // eslint-disable-next-line + if (!f.hasOwnProperty(attr) || !f[attr] || !f.viewable) { + continue; + } + + // ref https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill + // ref https://developers.google.com/web/fundamentals/design-and-ux/input/forms/ + if ( + !fillFields.cardholderName && + this.isFieldMatch( + f[attr], + CreditCardAutoFillConstants.CardHolderFieldNames, + CreditCardAutoFillConstants.CardHolderFieldNameValues + ) + ) { + fillFields.cardholderName = f; + break; + } else if ( + !fillFields.number && + this.isFieldMatch( + f[attr], + CreditCardAutoFillConstants.CardNumberFieldNames, + CreditCardAutoFillConstants.CardNumberFieldNameValues + ) + ) { + fillFields.number = f; + break; + } else if ( + !fillFields.exp && + this.isFieldMatch( + f[attr], + CreditCardAutoFillConstants.CardExpiryFieldNames, + CreditCardAutoFillConstants.CardExpiryFieldNameValues + ) + ) { + fillFields.exp = f; + break; + } else if ( + !fillFields.expMonth && + this.isFieldMatch(f[attr], CreditCardAutoFillConstants.ExpiryMonthFieldNames) + ) { + fillFields.expMonth = f; + break; + } else if ( + !fillFields.expYear && + this.isFieldMatch(f[attr], CreditCardAutoFillConstants.ExpiryYearFieldNames) + ) { + fillFields.expYear = f; + break; + } else if ( + !fillFields.code && + this.isFieldMatch(f[attr], CreditCardAutoFillConstants.CVVFieldNames) + ) { + fillFields.code = f; + break; + } else if ( + !fillFields.brand && + this.isFieldMatch(f[attr], CreditCardAutoFillConstants.CardBrandFieldNames) + ) { + fillFields.brand = f; + break; + } + } + }); + + const card = options.cipher.card; + this.makeScriptAction(fillScript, card, fillFields, filledFields, "cardholderName"); + this.makeScriptAction(fillScript, card, fillFields, filledFields, "number"); + this.makeScriptAction(fillScript, card, fillFields, filledFields, "code"); + this.makeScriptAction(fillScript, card, fillFields, filledFields, "brand"); + + if (fillFields.expMonth && this.hasValue(card.expMonth)) { + let expMonth: string = card.expMonth; + + if (fillFields.expMonth.selectInfo && fillFields.expMonth.selectInfo.options) { + let index: number = null; + const siOptions = fillFields.expMonth.selectInfo.options; + if (siOptions.length === 12) { + index = parseInt(card.expMonth, null) - 1; + } else if (siOptions.length === 13) { + if ( + siOptions[0][0] != null && + siOptions[0][0] !== "" && + (siOptions[12][0] == null || siOptions[12][0] === "") + ) { + index = parseInt(card.expMonth, null) - 1; + } else { + index = parseInt(card.expMonth, null); + } + } + + if (index != null) { + const option = siOptions[index]; + if (option.length > 1) { + expMonth = option[1]; + } + } + } else if ( + (this.fieldAttrsContain(fillFields.expMonth, "mm") || + fillFields.expMonth.maxLength === 2) && + expMonth.length === 1 + ) { + expMonth = "0" + expMonth; + } + + filledFields[fillFields.expMonth.opid] = fillFields.expMonth; + this.fillByOpid(fillScript, fillFields.expMonth, expMonth); + } + + if (fillFields.expYear && this.hasValue(card.expYear)) { + let expYear: string = card.expYear; + if (fillFields.expYear.selectInfo && fillFields.expYear.selectInfo.options) { + for (let i = 0; i < fillFields.expYear.selectInfo.options.length; i++) { + const o: [string, string] = fillFields.expYear.selectInfo.options[i]; + if (o[0] === card.expYear || o[1] === card.expYear) { + expYear = o[1]; + break; + } + if ( + o[1].length === 2 && + card.expYear.length === 4 && + o[1] === card.expYear.substring(2) + ) { + expYear = o[1]; + break; + } + const colonIndex = o[1].indexOf(":"); + if (colonIndex > -1 && o[1].length > colonIndex + 1) { + const val = o[1].substring(colonIndex + 2); + if (val != null && val.trim() !== "" && val === card.expYear) { + expYear = o[1]; + break; + } + } + } + } else if ( + this.fieldAttrsContain(fillFields.expYear, "yyyy") || + fillFields.expYear.maxLength === 4 + ) { + if (expYear.length === 2) { + expYear = "20" + expYear; + } + } else if ( + this.fieldAttrsContain(fillFields.expYear, "yy") || + fillFields.expYear.maxLength === 2 + ) { + if (expYear.length === 4) { + expYear = expYear.substr(2); + } + } + + filledFields[fillFields.expYear.opid] = fillFields.expYear; + this.fillByOpid(fillScript, fillFields.expYear, expYear); + } + + if (fillFields.exp && this.hasValue(card.expMonth) && this.hasValue(card.expYear)) { + const fullMonth = ("0" + card.expMonth).slice(-2); + + let fullYear: string = card.expYear; + let partYear: string = null; + if (fullYear.length === 2) { + partYear = fullYear; + fullYear = "20" + fullYear; + } else if (fullYear.length === 4) { + partYear = fullYear.substr(2, 2); + } + + let exp: string = null; + for (let i = 0; i < CreditCardAutoFillConstants.MonthAbbr.length; i++) { + if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.MonthAbbr[i] + + "/" + + CreditCardAutoFillConstants.YearAbbrShort[i] + ) && + partYear != null + ) { + exp = fullMonth + "/" + partYear; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.MonthAbbr[i] + + "/" + + CreditCardAutoFillConstants.YearAbbrLong[i] + ) + ) { + exp = fullMonth + "/" + fullYear; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.YearAbbrShort[i] + + "/" + + CreditCardAutoFillConstants.MonthAbbr[i] + ) && + partYear != null + ) { + exp = partYear + "/" + fullMonth; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.YearAbbrLong[i] + + "/" + + CreditCardAutoFillConstants.MonthAbbr[i] + ) + ) { + exp = fullYear + "/" + fullMonth; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.MonthAbbr[i] + + "-" + + CreditCardAutoFillConstants.YearAbbrShort[i] + ) && + partYear != null + ) { + exp = fullMonth + "-" + partYear; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.MonthAbbr[i] + + "-" + + CreditCardAutoFillConstants.YearAbbrLong[i] + ) + ) { + exp = fullMonth + "-" + fullYear; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.YearAbbrShort[i] + + "-" + + CreditCardAutoFillConstants.MonthAbbr[i] + ) && + partYear != null + ) { + exp = partYear + "-" + fullMonth; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.YearAbbrLong[i] + + "-" + + CreditCardAutoFillConstants.MonthAbbr[i] + ) + ) { + exp = fullYear + "-" + fullMonth; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.YearAbbrShort[i] + CreditCardAutoFillConstants.MonthAbbr[i] + ) && + partYear != null + ) { + exp = partYear + fullMonth; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.YearAbbrLong[i] + CreditCardAutoFillConstants.MonthAbbr[i] + ) + ) { + exp = fullYear + fullMonth; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.MonthAbbr[i] + CreditCardAutoFillConstants.YearAbbrShort[i] + ) && + partYear != null + ) { + exp = fullMonth + partYear; + } else if ( + this.fieldAttrsContain( + fillFields.exp, + CreditCardAutoFillConstants.MonthAbbr[i] + CreditCardAutoFillConstants.YearAbbrLong[i] + ) + ) { + exp = fullMonth + fullYear; + } + + if (exp != null) { + break; + } + } + + if (exp == null) { + exp = fullYear + "-" + fullMonth; + } + + this.makeScriptActionWithValue(fillScript, exp, fillFields.exp, filledFields); + } + + return fillScript; + } + + private fieldAttrsContain(field: any, containsVal: string) { + if (!field) { + return false; + } + + let doesContain = false; + CreditCardAutoFillConstants.CardAttributesExtended.forEach((attr) => { + // eslint-disable-next-line + if (doesContain || !field.hasOwnProperty(attr) || !field[attr]) { + return; + } + + let val = field[attr]; + val = val.replace(/ /g, "").toLowerCase(); + doesContain = val.indexOf(containsVal) > -1; + }); + + return doesContain; + } + + private generateIdentityFillScript( + fillScript: AutofillScript, + pageDetails: any, + filledFields: { [id: string]: AutofillField }, + options: any + ): AutofillScript { + if (!options.cipher.identity) { + return null; + } + + const fillFields: { [id: string]: AutofillField } = {}; + + pageDetails.fields.forEach((f: any) => { + if (this.forCustomFieldsOnly(f)) { + return; + } + + if (this.isExcludedType(f.type, AutoFillConstants.ExcludedAutofillTypes)) { + return; + } + + for (let i = 0; i < IdentityAutoFillConstants.IdentityAttributes.length; i++) { + const attr = IdentityAutoFillConstants.IdentityAttributes[i]; + // eslint-disable-next-line + if (!f.hasOwnProperty(attr) || !f[attr] || !f.viewable) { + continue; + } + + // ref https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill + // ref https://developers.google.com/web/fundamentals/design-and-ux/input/forms/ + if ( + !fillFields.name && + this.isFieldMatch( + f[attr], + IdentityAutoFillConstants.FullNameFieldNames, + IdentityAutoFillConstants.FullNameFieldNameValues + ) + ) { + fillFields.name = f; + break; + } else if ( + !fillFields.firstName && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.FirstnameFieldNames) + ) { + fillFields.firstName = f; + break; + } else if ( + !fillFields.middleName && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.MiddlenameFieldNames) + ) { + fillFields.middleName = f; + break; + } else if ( + !fillFields.lastName && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.LastnameFieldNames) + ) { + fillFields.lastName = f; + break; + } else if ( + !fillFields.title && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.TitleFieldNames) + ) { + fillFields.title = f; + break; + } else if ( + !fillFields.email && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.EmailFieldNames) + ) { + fillFields.email = f; + break; + } else if ( + !fillFields.address && + this.isFieldMatch( + f[attr], + IdentityAutoFillConstants.AddressFieldNames, + IdentityAutoFillConstants.AddressFieldNameValues + ) + ) { + fillFields.address = f; + break; + } else if ( + !fillFields.address1 && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.Address1FieldNames) + ) { + fillFields.address1 = f; + break; + } else if ( + !fillFields.address2 && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.Address2FieldNames) + ) { + fillFields.address2 = f; + break; + } else if ( + !fillFields.address3 && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.Address3FieldNames) + ) { + fillFields.address3 = f; + break; + } else if ( + !fillFields.postalCode && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.PostalCodeFieldNames) + ) { + fillFields.postalCode = f; + break; + } else if ( + !fillFields.city && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.CityFieldNames) + ) { + fillFields.city = f; + break; + } else if ( + !fillFields.state && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.StateFieldNames) + ) { + fillFields.state = f; + break; + } else if ( + !fillFields.country && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.CountryFieldNames) + ) { + fillFields.country = f; + break; + } else if ( + !fillFields.phone && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.PhoneFieldNames) + ) { + fillFields.phone = f; + break; + } else if ( + !fillFields.username && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.UserNameFieldNames) + ) { + fillFields.username = f; + break; + } else if ( + !fillFields.company && + this.isFieldMatch(f[attr], IdentityAutoFillConstants.CompanyFieldNames) + ) { + fillFields.company = f; + break; + } + } + }); + + const identity = options.cipher.identity; + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "title"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "firstName"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "middleName"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "lastName"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "address1"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "address2"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "address3"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "city"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "postalCode"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "company"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "email"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "phone"); + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "username"); + + let filledState = false; + if (fillFields.state && identity.state && identity.state.length > 2) { + const stateLower = identity.state.toLowerCase(); + const isoState = + IdentityAutoFillConstants.IsoStates[stateLower] || + IdentityAutoFillConstants.IsoProvinces[stateLower]; + if (isoState) { + filledState = true; + this.makeScriptActionWithValue(fillScript, isoState, fillFields.state, filledFields); + } + } + + if (!filledState) { + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "state"); + } + + let filledCountry = false; + if (fillFields.country && identity.country && identity.country.length > 2) { + const countryLower = identity.country.toLowerCase(); + const isoCountry = IdentityAutoFillConstants.IsoCountries[countryLower]; + if (isoCountry) { + filledCountry = true; + this.makeScriptActionWithValue(fillScript, isoCountry, fillFields.country, filledFields); + } + } + + if (!filledCountry) { + this.makeScriptAction(fillScript, identity, fillFields, filledFields, "country"); + } + + if (fillFields.name && (identity.firstName || identity.lastName)) { + let fullName = ""; + if (this.hasValue(identity.firstName)) { + fullName = identity.firstName; + } + if (this.hasValue(identity.middleName)) { + if (fullName !== "") { + fullName += " "; + } + fullName += identity.middleName; + } + if (this.hasValue(identity.lastName)) { + if (fullName !== "") { + fullName += " "; + } + fullName += identity.lastName; + } + + this.makeScriptActionWithValue(fillScript, fullName, fillFields.name, filledFields); + } + + if (fillFields.address && this.hasValue(identity.address1)) { + let address = ""; + if (this.hasValue(identity.address1)) { + address = identity.address1; + } + if (this.hasValue(identity.address2)) { + if (address !== "") { + address += ", "; + } + address += identity.address2; + } + if (this.hasValue(identity.address3)) { + if (address !== "") { + address += ", "; + } + address += identity.address3; + } + + this.makeScriptActionWithValue(fillScript, address, fillFields.address, filledFields); + } + + return fillScript; + } + + private isExcludedType(type: string, excludedTypes: string[]) { + return excludedTypes.indexOf(type) > -1; + } + + private isFieldMatch(value: string, options: string[], containsOptions?: string[]): boolean { + value = value + .trim() + .toLowerCase() + .replace(/[^a-zA-Z0-9]+/g, ""); + for (let i = 0; i < options.length; i++) { + let option = options[i]; + const checkValueContains = containsOptions == null || containsOptions.indexOf(option) > -1; + option = option.toLowerCase().replace(/-/g, ""); + if (value === option || (checkValueContains && value.indexOf(option) > -1)) { + return true; + } + } + + return false; + } + + private makeScriptAction( + fillScript: AutofillScript, + cipherData: any, + fillFields: { [id: string]: AutofillField }, + filledFields: { [id: string]: AutofillField }, + dataProp: string, + fieldProp?: string + ) { + fieldProp = fieldProp || dataProp; + this.makeScriptActionWithValue( + fillScript, + cipherData[dataProp], + fillFields[fieldProp], + filledFields + ); + } + + private makeScriptActionWithValue( + fillScript: AutofillScript, + dataValue: any, + field: AutofillField, + filledFields: { [id: string]: AutofillField } + ) { + let doFill = false; + if (this.hasValue(dataValue) && field) { + if (field.type === "select-one" && field.selectInfo && field.selectInfo.options) { + for (let i = 0; i < field.selectInfo.options.length; i++) { + const option = field.selectInfo.options[i]; + for (let j = 0; j < option.length; j++) { + if (this.hasValue(option[j]) && option[j].toLowerCase() === dataValue.toLowerCase()) { + doFill = true; + if (option.length > 1) { + dataValue = option[1]; + } + break; + } + } + + if (doFill) { + break; + } + } + } else { + doFill = true; + } + } + + if (doFill) { + filledFields[field.opid] = field; + this.fillByOpid(fillScript, field, dataValue); + } + } + + private loadPasswordFields( + pageDetails: AutofillPageDetails, + canBeHidden: boolean, + canBeReadOnly: boolean, + mustBeEmpty: boolean, + fillNewPassword: boolean + ) { + const arr: AutofillField[] = []; + pageDetails.fields.forEach((f) => { + if (this.forCustomFieldsOnly(f)) { + return; + } + + const isPassword = f.type === "password"; + const valueIsLikePassword = (value: string) => { + if (value == null) { + return false; + } + // Removes all whitespace, _ and - characters + // eslint-disable-next-line + const cleanedValue = value.toLowerCase().replace(/[\s_\-]/g, ""); + + if (cleanedValue.indexOf("password") < 0) { + return false; + } + + if (AutoFillConstants.PasswordFieldIgnoreList.some((i) => cleanedValue.indexOf(i) > -1)) { + return false; + } + + return true; + }; + const isLikePassword = () => { + if (f.type !== "text") { + return false; + } + if (valueIsLikePassword(f.htmlID)) { + return true; + } + if (valueIsLikePassword(f.htmlName)) { + return true; + } + if (valueIsLikePassword(f.placeholder)) { + return true; + } + return false; + }; + if ( + !f.disabled && + (canBeReadOnly || !f.readonly) && + (isPassword || isLikePassword()) && + (canBeHidden || f.viewable) && + (!mustBeEmpty || f.value == null || f.value.trim() === "") && + (fillNewPassword || f.autoCompleteType !== "new-password") + ) { + arr.push(f); + } + }); + return arr; + } + + private findUsernameField( + pageDetails: AutofillPageDetails, + passwordField: AutofillField, + canBeHidden: boolean, + canBeReadOnly: boolean, + withoutForm: boolean + ) { + let usernameField: AutofillField = null; + for (let i = 0; i < pageDetails.fields.length; i++) { + const f = pageDetails.fields[i]; + if (this.forCustomFieldsOnly(f)) { + continue; + } + + if (f.elementNumber >= passwordField.elementNumber) { + break; + } + + if ( + !f.disabled && + (canBeReadOnly || !f.readonly) && + (withoutForm || f.form === passwordField.form) && + (canBeHidden || f.viewable) && + (f.type === "text" || f.type === "email" || f.type === "tel") + ) { + usernameField = f; + + if (this.findMatchingFieldIndex(f, AutoFillConstants.UsernameFieldNames) > -1) { + // We found an exact match. No need to keep looking. + break; + } + } + } + + return usernameField; + } + + private findMatchingFieldIndex(field: AutofillField, names: string[]): number { + for (let i = 0; i < names.length; i++) { + if (names[i].indexOf("=") > -1) { + if (this.fieldPropertyIsPrefixMatch(field, "htmlID", names[i], "id")) { + return i; + } + if (this.fieldPropertyIsPrefixMatch(field, "htmlName", names[i], "name")) { + return i; + } + if (this.fieldPropertyIsPrefixMatch(field, "label-tag", names[i], "label")) { + return i; + } + if (this.fieldPropertyIsPrefixMatch(field, "label-aria", names[i], "label")) { + return i; + } + if (this.fieldPropertyIsPrefixMatch(field, "placeholder", names[i], "placeholder")) { + return i; + } + } + + if (this.fieldPropertyIsMatch(field, "htmlID", names[i])) { + return i; + } + if (this.fieldPropertyIsMatch(field, "htmlName", names[i])) { + return i; + } + if (this.fieldPropertyIsMatch(field, "label-tag", names[i])) { + return i; + } + if (this.fieldPropertyIsMatch(field, "label-aria", names[i])) { + return i; + } + if (this.fieldPropertyIsMatch(field, "placeholder", names[i])) { + return i; + } + } + + return -1; + } + + private fieldPropertyIsPrefixMatch( + field: any, + property: string, + name: string, + prefix: string, + separator = "=" + ): boolean { + if (name.indexOf(prefix + separator) === 0) { + const sepIndex = name.indexOf(separator); + const val = name.substring(sepIndex + 1); + return val != null && this.fieldPropertyIsMatch(field, property, val); + } + return false; + } + + private fieldPropertyIsMatch(field: any, property: string, name: string): boolean { + let fieldVal = field[property] as string; + if (!this.hasValue(fieldVal)) { + return false; + } + + fieldVal = fieldVal.trim().replace(/(?:\r\n|\r|\n)/g, ""); + if (name.startsWith("regex=")) { + try { + const regexParts = name.split("=", 2); + if (regexParts.length === 2) { + const regex = new RegExp(regexParts[1], "i"); + return regex.test(fieldVal); + } + } catch (e) { + this.logService.error(e); + } + } else if (name.startsWith("csv=")) { + const csvParts = name.split("=", 2); + if (csvParts.length === 2) { + const csvVals = csvParts[1].split(","); + for (let i = 0; i < csvVals.length; i++) { + const val = csvVals[i]; + if (val != null && val.trim().toLowerCase() === fieldVal.toLowerCase()) { + return true; + } + } + return false; + } + } + + return fieldVal.toLowerCase() === name; + } + + private fieldIsFuzzyMatch(field: AutofillField, names: string[]): boolean { + if (this.hasValue(field.htmlID) && this.fuzzyMatch(names, field.htmlID)) { + return true; + } + if (this.hasValue(field.htmlName) && this.fuzzyMatch(names, field.htmlName)) { + return true; + } + if (this.hasValue(field["label-tag"]) && this.fuzzyMatch(names, field["label-tag"])) { + return true; + } + if (this.hasValue(field.placeholder) && this.fuzzyMatch(names, field.placeholder)) { + return true; + } + if (this.hasValue(field["label-left"]) && this.fuzzyMatch(names, field["label-left"])) { + return true; + } + if (this.hasValue(field["label-top"]) && this.fuzzyMatch(names, field["label-top"])) { + return true; + } + if (this.hasValue(field["label-aria"]) && this.fuzzyMatch(names, field["label-aria"])) { + return true; + } + + return false; + } + + private fuzzyMatch(options: string[], value: string): boolean { + if (options == null || options.length === 0 || value == null || value === "") { + return false; + } + + value = value + .replace(/(?:\r\n|\r|\n)/g, "") + .trim() + .toLowerCase(); + + for (let i = 0; i < options.length; i++) { + if (value.indexOf(options[i]) > -1) { + return true; + } + } + + return false; + } + + private hasValue(str: string): boolean { + return str && str !== ""; + } + + private setFillScriptForFocus( + filledFields: { [id: string]: AutofillField }, + fillScript: AutofillScript + ): AutofillScript { + let lastField: AutofillField = null; + let lastPasswordField: AutofillField = null; + + for (const opid in filledFields) { + // eslint-disable-next-line + if (filledFields.hasOwnProperty(opid) && filledFields[opid].viewable) { + lastField = filledFields[opid]; + + if (filledFields[opid].type === "password") { + lastPasswordField = filledFields[opid]; + } + } + } + + // Prioritize password field over others. + if (lastPasswordField) { + fillScript.script.push(["focus_by_opid", lastPasswordField.opid]); + } else if (lastField) { + fillScript.script.push(["focus_by_opid", lastField.opid]); + } + + return fillScript; + } + + private fillByOpid(fillScript: AutofillScript, field: AutofillField, value: string): void { + if (field.maxLength && value && value.length > field.maxLength) { + value = value.substr(0, value.length); + } + if (field.tagName !== "span") { + fillScript.script.push(["click_on_opid", field.opid]); + fillScript.script.push(["focus_by_opid", field.opid]); + } + fillScript.script.push(["fill_by_opid", field.opid, value]); + } + + private forCustomFieldsOnly(field: AutofillField): boolean { + return field.tagName === "span"; + } +} diff --git a/apps/browser/src/services/autofillConstants.ts b/apps/browser/src/services/autofillConstants.ts new file mode 100644 index 0000000000..94b54a7150 --- /dev/null +++ b/apps/browser/src/services/autofillConstants.ts @@ -0,0 +1,739 @@ +export class AutoFillConstants { + static readonly UsernameFieldNames: string[] = [ + // English + "username", + "user name", + "email", + "email address", + "e-mail", + "e-mail address", + "userid", + "user id", + "customer id", + "login id", + // German + "benutzername", + "benutzer name", + "email adresse", + "e-mail adresse", + "benutzerid", + "benutzer id", + ]; + + static readonly PasswordFieldIgnoreList: string[] = [ + "onetimepassword", + "captcha", + "findanything", + "forgot", + ]; + + static readonly ExcludedAutofillTypes: string[] = [ + "radio", + "checkbox", + "hidden", + "file", + "button", + "image", + "reset", + "search", + ]; +} + +export class CreditCardAutoFillConstants { + static readonly CardAttributes: string[] = [ + "autoCompleteType", + "data-stripe", + "htmlName", + "htmlID", + "label-tag", + "placeholder", + "label-left", + "label-top", + "data-recurly", + ]; + + static readonly CardAttributesExtended: string[] = [ + ...CreditCardAutoFillConstants.CardAttributes, + "label-right", + ]; + + static readonly CardHolderFieldNames: string[] = [ + "cc-name", + "card-name", + "cardholder-name", + "cardholder", + "name", + "nom", + ]; + + static readonly CardHolderFieldNameValues: string[] = [ + "cc-name", + "card-name", + "cardholder-name", + "cardholder", + "tbName", + ]; + + static readonly CardNumberFieldNames: string[] = [ + "cc-number", + "cc-num", + "card-number", + "card-num", + "number", + "cc", + "cc-no", + "card-no", + "credit-card", + "numero-carte", + "carte", + "carte-credit", + "num-carte", + "cb-num", + ]; + + static readonly CardNumberFieldNameValues: string[] = [ + "cc-number", + "cc-num", + "card-number", + "card-num", + "cc-no", + "card-no", + "numero-carte", + "num-carte", + "cb-num", + ]; + + static readonly CardExpiryFieldNames: string[] = [ + "cc-exp", + "card-exp", + "cc-expiration", + "card-expiration", + "cc-ex", + "card-ex", + "card-expire", + "card-expiry", + "validite", + "expiration", + "expiry", + "mm-yy", + "mm-yyyy", + "yy-mm", + "yyyy-mm", + "expiration-date", + "payment-card-expiration", + "payment-cc-date", + ]; + + static readonly CardExpiryFieldNameValues: string[] = [ + "mm-yy", + "mm-yyyy", + "yy-mm", + "yyyy-mm", + "expiration-date", + "payment-card-expiration", + ]; + + static readonly ExpiryMonthFieldNames: string[] = [ + "exp-month", + "cc-exp-month", + "cc-month", + "card-month", + "cc-mo", + "card-mo", + "exp-mo", + "card-exp-mo", + "cc-exp-mo", + "card-expiration-month", + "expiration-month", + "cc-mm", + "cc-m", + "card-mm", + "card-m", + "card-exp-mm", + "cc-exp-mm", + "exp-mm", + "exp-m", + "expire-month", + "expire-mo", + "expiry-month", + "expiry-mo", + "card-expire-month", + "card-expire-mo", + "card-expiry-month", + "card-expiry-mo", + "mois-validite", + "mois-expiration", + "m-validite", + "m-expiration", + "expiry-date-field-month", + "expiration-date-month", + "expiration-date-mm", + "exp-mon", + "validity-mo", + "exp-date-mo", + "cb-date-mois", + "date-m", + ]; + + static readonly ExpiryYearFieldNames: string[] = [ + "exp-year", + "cc-exp-year", + "cc-year", + "card-year", + "cc-yr", + "card-yr", + "exp-yr", + "card-exp-yr", + "cc-exp-yr", + "card-expiration-year", + "expiration-year", + "cc-yy", + "cc-y", + "card-yy", + "card-y", + "card-exp-yy", + "cc-exp-yy", + "exp-yy", + "exp-y", + "cc-yyyy", + "card-yyyy", + "card-exp-yyyy", + "cc-exp-yyyy", + "expire-year", + "expire-yr", + "expiry-year", + "expiry-yr", + "card-expire-year", + "card-expire-yr", + "card-expiry-year", + "card-expiry-yr", + "an-validite", + "an-expiration", + "annee-validite", + "annee-expiration", + "expiry-date-field-year", + "expiration-date-year", + "cb-date-ann", + "expiration-date-yy", + "expiration-date-yyyy", + "validity-year", + "exp-date-year", + "date-y", + ]; + + static readonly CVVFieldNames: string[] = [ + "cvv", + "cvc", + "cvv2", + "cc-csc", + "cc-cvv", + "card-csc", + "card-cvv", + "cvd", + "cid", + "cvc2", + "cnv", + "cvn2", + "cc-code", + "card-code", + "code-securite", + "security-code", + "crypto", + "card-verif", + "verification-code", + "csc", + "ccv", + ]; + + static readonly CardBrandFieldNames: string[] = [ + "cc-type", + "card-type", + "card-brand", + "cc-brand", + "cb-type", + ]; + + // Each index represents a language. These three arrays should all be the same length. + // 0: English, 1: Danish, 2: German/Dutch, 3: French/Spanish/Italian, 4: Russian, 5: Portuguese + static readonly MonthAbbr = ["mm", "mm", "mm", "mm", "mm", "mm"]; + static readonly YearAbbrShort = ["yy", "åå", "jj", "aa", "гг", "rr"]; + static readonly YearAbbrLong = ["yyyy", "åååå", "jjjj", "aa", "гггг", "rrrr"]; +} + +export class IdentityAutoFillConstants { + static readonly IdentityAttributes: string[] = [ + "autoCompleteType", + "data-stripe", + "htmlName", + "htmlID", + "label-tag", + "placeholder", + "label-left", + "label-top", + "data-recurly", + ]; + + static readonly FullNameFieldNames: string[] = ["name", "full-name", "your-name"]; + + static readonly FullNameFieldNameValues: string[] = ["full-name", "your-name"]; + + static readonly TitleFieldNames: string[] = ["honorific-prefix", "prefix", "title"]; + + static readonly FirstnameFieldNames: string[] = [ + // English + "f-name", + "first-name", + "given-name", + "first-n", + // German + "vorname", + ]; + + static readonly MiddlenameFieldNames: string[] = [ + "m-name", + "middle-name", + "additional-name", + "middle-initial", + "middle-n", + "middle-i", + ]; + + static readonly LastnameFieldNames: string[] = [ + // English + "l-name", + "last-name", + "s-name", + "surname", + "family-name", + "family-n", + "last-n", + // German + "nachname", + "familienname", + ]; + + static readonly EmailFieldNames: string[] = ["e-mail", "email-address"]; + + static readonly AddressFieldNames: string[] = [ + "address", + "street-address", + "addr", + "street", + "mailing-addr", + "billing-addr", + "mail-addr", + "bill-addr", + ]; + + static readonly AddressFieldNameValues: string[] = [ + "mailing-addr", + "billing-addr", + "mail-addr", + "bill-addr", + ]; + + static readonly Address1FieldNames: string[] = [ + "address-1", + "address-line-1", + "addr-1", + "street-1", + ]; + + static readonly Address2FieldNames: string[] = [ + "address-2", + "address-line-2", + "addr-2", + "street-2", + ]; + + static readonly Address3FieldNames: string[] = [ + "address-3", + "address-line-3", + "addr-3", + "street-3", + ]; + + static readonly PostalCodeFieldNames: string[] = [ + "postal", + "zip", + "zip2", + "zip-code", + "postal-code", + "post-code", + "address-zip", + "address-postal", + "address-code", + "address-postal-code", + "address-zip-code", + ]; + + static readonly CityFieldNames: string[] = [ + "city", + "town", + "address-level-2", + "address-city", + "address-town", + ]; + + static readonly StateFieldNames: string[] = [ + "state", + "province", + "provence", + "address-level-1", + "address-state", + "address-province", + ]; + + static readonly CountryFieldNames: string[] = [ + "country", + "country-code", + "country-name", + "address-country", + "address-country-name", + "address-country-code", + ]; + + static readonly PhoneFieldNames: string[] = [ + "phone", + "mobile", + "mobile-phone", + "tel", + "telephone", + "phone-number", + ]; + + static readonly UserNameFieldNames: string[] = ["user-name", "user-id", "screen-name"]; + + static readonly CompanyFieldNames: string[] = [ + "company", + "company-name", + "organization", + "organization-name", + ]; + + static readonly IsoCountries: { [id: string]: string } = { + afghanistan: "AF", + "aland islands": "AX", + albania: "AL", + algeria: "DZ", + "american samoa": "AS", + andorra: "AD", + angola: "AO", + anguilla: "AI", + antarctica: "AQ", + "antigua and barbuda": "AG", + argentina: "AR", + armenia: "AM", + aruba: "AW", + australia: "AU", + austria: "AT", + azerbaijan: "AZ", + bahamas: "BS", + bahrain: "BH", + bangladesh: "BD", + barbados: "BB", + belarus: "BY", + belgium: "BE", + belize: "BZ", + benin: "BJ", + bermuda: "BM", + bhutan: "BT", + bolivia: "BO", + "bosnia and herzegovina": "BA", + botswana: "BW", + "bouvet island": "BV", + brazil: "BR", + "british indian ocean territory": "IO", + "brunei darussalam": "BN", + bulgaria: "BG", + "burkina faso": "BF", + burundi: "BI", + cambodia: "KH", + cameroon: "CM", + canada: "CA", + "cape verde": "CV", + "cayman islands": "KY", + "central african republic": "CF", + chad: "TD", + chile: "CL", + china: "CN", + "christmas island": "CX", + "cocos (keeling) islands": "CC", + colombia: "CO", + comoros: "KM", + congo: "CG", + "congo, democratic republic": "CD", + "cook islands": "CK", + "costa rica": "CR", + "cote d'ivoire": "CI", + croatia: "HR", + cuba: "CU", + cyprus: "CY", + "czech republic": "CZ", + denmark: "DK", + djibouti: "DJ", + dominica: "DM", + "dominican republic": "DO", + ecuador: "EC", + egypt: "EG", + "el salvador": "SV", + "equatorial guinea": "GQ", + eritrea: "ER", + estonia: "EE", + ethiopia: "ET", + "falkland islands": "FK", + "faroe islands": "FO", + fiji: "FJ", + finland: "FI", + france: "FR", + "french guiana": "GF", + "french polynesia": "PF", + "french southern territories": "TF", + gabon: "GA", + gambia: "GM", + georgia: "GE", + germany: "DE", + ghana: "GH", + gibraltar: "GI", + greece: "GR", + greenland: "GL", + grenada: "GD", + guadeloupe: "GP", + guam: "GU", + guatemala: "GT", + guernsey: "GG", + guinea: "GN", + "guinea-bissau": "GW", + guyana: "GY", + haiti: "HT", + "heard island & mcdonald islands": "HM", + "holy see (vatican city state)": "VA", + honduras: "HN", + "hong kong": "HK", + hungary: "HU", + iceland: "IS", + india: "IN", + indonesia: "ID", + "iran, islamic republic of": "IR", + iraq: "IQ", + ireland: "IE", + "isle of man": "IM", + israel: "IL", + italy: "IT", + jamaica: "JM", + japan: "JP", + jersey: "JE", + jordan: "JO", + kazakhstan: "KZ", + kenya: "KE", + kiribati: "KI", + "republic of korea": "KR", + "south korea": "KR", + "democratic people's republic of korea": "KP", + "north korea": "KP", + kuwait: "KW", + kyrgyzstan: "KG", + "lao people's democratic republic": "LA", + latvia: "LV", + lebanon: "LB", + lesotho: "LS", + liberia: "LR", + "libyan arab jamahiriya": "LY", + liechtenstein: "LI", + lithuania: "LT", + luxembourg: "LU", + macao: "MO", + macedonia: "MK", + madagascar: "MG", + malawi: "MW", + malaysia: "MY", + maldives: "MV", + mali: "ML", + malta: "MT", + "marshall islands": "MH", + martinique: "MQ", + mauritania: "MR", + mauritius: "MU", + mayotte: "YT", + mexico: "MX", + "micronesia, federated states of": "FM", + moldova: "MD", + monaco: "MC", + mongolia: "MN", + montenegro: "ME", + montserrat: "MS", + morocco: "MA", + mozambique: "MZ", + myanmar: "MM", + namibia: "NA", + nauru: "NR", + nepal: "NP", + netherlands: "NL", + "netherlands antilles": "AN", + "new caledonia": "NC", + "new zealand": "NZ", + nicaragua: "NI", + niger: "NE", + nigeria: "NG", + niue: "NU", + "norfolk island": "NF", + "northern mariana islands": "MP", + norway: "NO", + oman: "OM", + pakistan: "PK", + palau: "PW", + "palestinian territory, occupied": "PS", + panama: "PA", + "papua new guinea": "PG", + paraguay: "PY", + peru: "PE", + philippines: "PH", + pitcairn: "PN", + poland: "PL", + portugal: "PT", + "puerto rico": "PR", + qatar: "QA", + reunion: "RE", + romania: "RO", + "russian federation": "RU", + rwanda: "RW", + "saint barthelemy": "BL", + "saint helena": "SH", + "saint kitts and nevis": "KN", + "saint lucia": "LC", + "saint martin": "MF", + "saint pierre and miquelon": "PM", + "saint vincent and grenadines": "VC", + samoa: "WS", + "san marino": "SM", + "sao tome and principe": "ST", + "saudi arabia": "SA", + senegal: "SN", + serbia: "RS", + seychelles: "SC", + "sierra leone": "SL", + singapore: "SG", + slovakia: "SK", + slovenia: "SI", + "solomon islands": "SB", + somalia: "SO", + "south africa": "ZA", + "south georgia and sandwich isl.": "GS", + spain: "ES", + "sri lanka": "LK", + sudan: "SD", + suriname: "SR", + "svalbard and jan mayen": "SJ", + swaziland: "SZ", + sweden: "SE", + switzerland: "CH", + "syrian arab republic": "SY", + taiwan: "TW", + tajikistan: "TJ", + tanzania: "TZ", + thailand: "TH", + "timor-leste": "TL", + togo: "TG", + tokelau: "TK", + tonga: "TO", + "trinidad and tobago": "TT", + tunisia: "TN", + turkey: "TR", + turkmenistan: "TM", + "turks and caicos islands": "TC", + tuvalu: "TV", + uganda: "UG", + ukraine: "UA", + "united arab emirates": "AE", + "united kingdom": "GB", + "united states": "US", + "united states outlying islands": "UM", + uruguay: "UY", + uzbekistan: "UZ", + vanuatu: "VU", + venezuela: "VE", + vietnam: "VN", + "virgin islands, british": "VG", + "virgin islands, u.s.": "VI", + "wallis and futuna": "WF", + "western sahara": "EH", + yemen: "YE", + zambia: "ZM", + zimbabwe: "ZW", + }; + + static readonly IsoStates: { [id: string]: string } = { + alabama: "AL", + alaska: "AK", + "american samoa": "AS", + arizona: "AZ", + arkansas: "AR", + california: "CA", + colorado: "CO", + connecticut: "CT", + delaware: "DE", + "district of columbia": "DC", + "federated states of micronesia": "FM", + florida: "FL", + georgia: "GA", + guam: "GU", + hawaii: "HI", + idaho: "ID", + illinois: "IL", + indiana: "IN", + iowa: "IA", + kansas: "KS", + kentucky: "KY", + louisiana: "LA", + maine: "ME", + "marshall islands": "MH", + maryland: "MD", + massachusetts: "MA", + michigan: "MI", + minnesota: "MN", + mississippi: "MS", + missouri: "MO", + montana: "MT", + nebraska: "NE", + nevada: "NV", + "new hampshire": "NH", + "new jersey": "NJ", + "new mexico": "NM", + "new york": "NY", + "north carolina": "NC", + "north dakota": "ND", + "northern mariana islands": "MP", + ohio: "OH", + oklahoma: "OK", + oregon: "OR", + palau: "PW", + pennsylvania: "PA", + "puerto rico": "PR", + "rhode island": "RI", + "south carolina": "SC", + "south dakota": "SD", + tennessee: "TN", + texas: "TX", + utah: "UT", + vermont: "VT", + "virgin islands": "VI", + virginia: "VA", + washington: "WA", + "west virginia": "WV", + wisconsin: "WI", + wyoming: "WY", + }; + + static readonly IsoProvinces: { [id: string]: string } = { + alberta: "AB", + "british columbia": "BC", + manitoba: "MB", + "new brunswick": "NB", + "newfoundland and labrador": "NL", + "nova scotia": "NS", + ontario: "ON", + "prince edward island": "PE", + quebec: "QC", + saskatchewan: "SK", + }; +} diff --git a/apps/browser/src/services/browserCrypto.service.ts b/apps/browser/src/services/browserCrypto.service.ts new file mode 100644 index 0000000000..0eb0f94b17 --- /dev/null +++ b/apps/browser/src/services/browserCrypto.service.ts @@ -0,0 +1,13 @@ +import { KeySuffixOptions } from "jslib-common/enums/keySuffixOptions"; +import { CryptoService } from "jslib-common/services/crypto.service"; + +export class BrowserCryptoService extends CryptoService { + protected async retrieveKeyFromStorage(keySuffix: KeySuffixOptions) { + if (keySuffix === "biometric") { + await this.platformUtilService.authenticateBiometric(); + return (await this.getKey())?.keyB64; + } + + return await super.retrieveKeyFromStorage(keySuffix); + } +} diff --git a/apps/browser/src/services/browserMessaging.service.ts b/apps/browser/src/services/browserMessaging.service.ts new file mode 100644 index 0000000000..f59ac88774 --- /dev/null +++ b/apps/browser/src/services/browserMessaging.service.ts @@ -0,0 +1,8 @@ +import { MessagingService } from "jslib-common/abstractions/messaging.service"; + +export default class BrowserMessagingService implements MessagingService { + send(subscriber: string, arg: any = {}) { + const message = Object.assign({}, { command: subscriber }, arg); + chrome.runtime.sendMessage(message); + } +} diff --git a/apps/browser/src/services/browserMessagingPrivateModeBackground.service.ts b/apps/browser/src/services/browserMessagingPrivateModeBackground.service.ts new file mode 100644 index 0000000000..4ffdf763da --- /dev/null +++ b/apps/browser/src/services/browserMessagingPrivateModeBackground.service.ts @@ -0,0 +1,8 @@ +import { MessagingService } from "jslib-common/abstractions/messaging.service"; + +export default class BrowserMessagingPrivateModeBackgroundService implements MessagingService { + send(subscriber: string, arg: any = {}) { + const message = Object.assign({}, { command: subscriber }, arg); + (window as any).bitwardenPopupMainMessageListener(message); + } +} diff --git a/apps/browser/src/services/browserMessagingPrivateModePopup.service.ts b/apps/browser/src/services/browserMessagingPrivateModePopup.service.ts new file mode 100644 index 0000000000..0f3af10d86 --- /dev/null +++ b/apps/browser/src/services/browserMessagingPrivateModePopup.service.ts @@ -0,0 +1,8 @@ +import { MessagingService } from "jslib-common/abstractions/messaging.service"; + +export default class BrowserMessagingPrivateModePopupService implements MessagingService { + send(subscriber: string, arg: any = {}) { + const message = Object.assign({}, { command: subscriber }, arg); + (window as any).bitwardenBackgroundMessageListener(message); + } +} diff --git a/apps/browser/src/services/browserPlatformUtils.service.spec.ts b/apps/browser/src/services/browserPlatformUtils.service.spec.ts new file mode 100644 index 0000000000..8b93e15c21 --- /dev/null +++ b/apps/browser/src/services/browserPlatformUtils.service.spec.ts @@ -0,0 +1,88 @@ +import { DeviceType } from "jslib-common/enums/deviceType"; + +import BrowserPlatformUtilsService from "./browserPlatformUtils.service"; + +describe("Browser Utils Service", () => { + describe("getBrowser", () => { + const originalUserAgent = navigator.userAgent; + + // Reset the userAgent. + afterAll(() => { + Object.defineProperty(navigator, "userAgent", { + value: originalUserAgent, + }); + }); + + let browserPlatformUtilsService: BrowserPlatformUtilsService; + beforeEach(() => { + (window as any).matchMedia = jest.fn().mockReturnValueOnce({}); + browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null, null); + }); + + afterEach(() => { + window.matchMedia = undefined; + (window as any).chrome = undefined; + }); + + it("should detect chrome", () => { + Object.defineProperty(navigator, "userAgent", { + configurable: true, + value: + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36", + }); + + (window as any).chrome = {}; + + expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.ChromeExtension); + }); + + it("should detect firefox", () => { + Object.defineProperty(navigator, "userAgent", { + configurable: true, + value: "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0", + }); + + expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.FirefoxExtension); + }); + + it("should detect opera", () => { + Object.defineProperty(navigator, "userAgent", { + configurable: true, + value: + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3175.3 Safari/537.36 OPR/49.0.2695.0 (Edition developer)", + }); + + expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.OperaExtension); + }); + + it("should detect edge", () => { + Object.defineProperty(navigator, "userAgent", { + configurable: true, + value: + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.74 Safari/537.36 Edg/79.0.309.43", + }); + + expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.EdgeExtension); + }); + + it("should detect safari", () => { + Object.defineProperty(navigator, "userAgent", { + configurable: true, + value: + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/602.4.8 (KHTML, like Gecko) Version/10.0.3 Safari/602.4.8", + }); + + expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.SafariExtension); + }); + + it("should detect vivaldi", () => { + Object.defineProperty(navigator, "userAgent", { + configurable: true, + value: + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.97 Safari/537.36 Vivaldi/1.94.1008.40", + }); + + expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.VivaldiExtension); + }); + }); +}); diff --git a/apps/browser/src/services/browserPlatformUtils.service.ts b/apps/browser/src/services/browserPlatformUtils.service.ts new file mode 100644 index 0000000000..f641d14950 --- /dev/null +++ b/apps/browser/src/services/browserPlatformUtils.service.ts @@ -0,0 +1,377 @@ +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { ClientType } from "jslib-common/enums/clientType"; +import { DeviceType } from "jslib-common/enums/deviceType"; +import { ThemeType } from "jslib-common/enums/themeType"; + +import { BrowserApi } from "../browser/browserApi"; +import { SafariApp } from "../browser/safariApp"; +import { StateService } from "../services/abstractions/state.service"; + +const DialogPromiseExpiration = 600000; // 10 minutes + +export default class BrowserPlatformUtilsService implements PlatformUtilsService { + private showDialogResolves = new Map void; date: Date }>(); + private passwordDialogResolves = new Map< + number, + { tryResolve: (canceled: boolean, password: string) => Promise; date: Date } + >(); + private deviceCache: DeviceType = null; + private prefersColorSchemeDark = window.matchMedia("(prefers-color-scheme: dark)"); + + constructor( + private messagingService: MessagingService, + private stateService: StateService, + private clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void, + private biometricCallback: () => Promise + ) {} + + getDevice(): DeviceType { + if (this.deviceCache) { + return this.deviceCache; + } + + if ( + navigator.userAgent.indexOf(" Firefox/") !== -1 || + navigator.userAgent.indexOf(" Gecko/") !== -1 + ) { + this.deviceCache = DeviceType.FirefoxExtension; + } else if ( + (!!(window as any).opr && !!opr.addons) || + !!(window as any).opera || + navigator.userAgent.indexOf(" OPR/") >= 0 + ) { + this.deviceCache = DeviceType.OperaExtension; + } else if (navigator.userAgent.indexOf(" Edg/") !== -1) { + this.deviceCache = DeviceType.EdgeExtension; + } else if (navigator.userAgent.indexOf(" Vivaldi/") !== -1) { + this.deviceCache = DeviceType.VivaldiExtension; + } else if ((window as any).chrome && navigator.userAgent.indexOf(" Chrome/") !== -1) { + this.deviceCache = DeviceType.ChromeExtension; + } else if (navigator.userAgent.indexOf(" Safari/") !== -1) { + this.deviceCache = DeviceType.SafariExtension; + } + + return this.deviceCache; + } + + getDeviceString(): string { + const device = DeviceType[this.getDevice()].toLowerCase(); + return device.replace("extension", ""); + } + + getClientType(): ClientType { + return ClientType.Browser; + } + + isFirefox(): boolean { + return this.getDevice() === DeviceType.FirefoxExtension; + } + + isChrome(): boolean { + return this.getDevice() === DeviceType.ChromeExtension; + } + + isEdge(): boolean { + return this.getDevice() === DeviceType.EdgeExtension; + } + + isOpera(): boolean { + return this.getDevice() === DeviceType.OperaExtension; + } + + isVivaldi(): boolean { + return this.getDevice() === DeviceType.VivaldiExtension; + } + + isSafari(): boolean { + return this.getDevice() === DeviceType.SafariExtension; + } + + isIE(): boolean { + return false; + } + + isMacAppStore(): boolean { + return false; + } + + async isViewOpen(): Promise { + if (await BrowserApi.isPopupOpen()) { + return true; + } + + if (this.isSafari()) { + return false; + } + + const sidebarView = this.sidebarViewName(); + const sidebarOpen = + sidebarView != null && chrome.extension.getViews({ type: sidebarView }).length > 0; + if (sidebarOpen) { + return true; + } + + const tabOpen = chrome.extension.getViews({ type: "tab" }).length > 0; + return tabOpen; + } + + lockTimeout(): number { + return null; + } + + launchUri(uri: string, options?: any): void { + BrowserApi.createNewTab(uri, options && options.extensionPage === true); + } + + saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void { + BrowserApi.downloadFile(win, blobData, blobOptions, fileName); + } + + getApplicationVersion(): Promise { + return Promise.resolve(BrowserApi.getApplicationVersion()); + } + + supportsWebAuthn(win: Window): boolean { + return typeof PublicKeyCredential !== "undefined"; + } + + supportsDuo(): boolean { + return true; + } + + showToast( + type: "error" | "success" | "warning" | "info", + title: string, + text: string | string[], + options?: any + ): void { + this.messagingService.send("showToast", { + text: text, + title: title, + type: type, + options: options, + }); + } + + showDialog( + body: string, + title?: string, + confirmText?: string, + cancelText?: string, + type?: string, + bodyIsHtml = false + ) { + const dialogId = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); + this.messagingService.send("showDialog", { + text: bodyIsHtml ? null : body, + html: bodyIsHtml ? body : null, + title: title, + confirmText: confirmText, + cancelText: cancelText, + type: type, + dialogId: dialogId, + }); + return new Promise((resolve) => { + this.showDialogResolves.set(dialogId, { resolve: resolve, date: new Date() }); + }); + } + + isDev(): boolean { + return process.env.ENV === "development"; + } + + isSelfHost(): boolean { + return false; + } + + copyToClipboard(text: string, options?: any): void { + let win = window; + let doc = window.document; + if (options && (options.window || options.win)) { + win = options.window || options.win; + doc = win.document; + } else if (options && options.doc) { + doc = options.doc; + } + const clearing = options ? !!options.clearing : false; + const clearMs: number = options && options.clearMs ? options.clearMs : null; + + if (this.isSafari()) { + SafariApp.sendMessageToApp("copyToClipboard", text).then(() => { + if (!clearing && this.clipboardWriteCallback != null) { + this.clipboardWriteCallback(text, clearMs); + } + }); + } else if ( + this.isFirefox() && + (win as any).navigator.clipboard && + (win as any).navigator.clipboard.writeText + ) { + (win as any).navigator.clipboard.writeText(text).then(() => { + if (!clearing && this.clipboardWriteCallback != null) { + this.clipboardWriteCallback(text, clearMs); + } + }); + } else if ((win as any).clipboardData && (win as any).clipboardData.setData) { + // IE specific code path to prevent textarea being shown while dialog is visible. + (win as any).clipboardData.setData("Text", text); + if (!clearing && this.clipboardWriteCallback != null) { + this.clipboardWriteCallback(text, clearMs); + } + } else if (doc.queryCommandSupported && doc.queryCommandSupported("copy")) { + if (this.isChrome() && text === "") { + text = "\u0000"; + } + + const textarea = doc.createElement("textarea"); + textarea.textContent = text == null || text === "" ? " " : text; + // Prevent scrolling to bottom of page in MS Edge. + textarea.style.position = "fixed"; + doc.body.appendChild(textarea); + textarea.select(); + + try { + // Security exception may be thrown by some browsers. + if (doc.execCommand("copy") && !clearing && this.clipboardWriteCallback != null) { + this.clipboardWriteCallback(text, clearMs); + } + } catch (e) { + // eslint-disable-next-line + console.warn("Copy to clipboard failed.", e); + } finally { + doc.body.removeChild(textarea); + } + } + } + + async readFromClipboard(options?: any): Promise { + let win = window; + let doc = window.document; + if (options && (options.window || options.win)) { + win = options.window || options.win; + doc = win.document; + } else if (options && options.doc) { + doc = options.doc; + } + + if (this.isSafari()) { + return await SafariApp.sendMessageToApp("readFromClipboard"); + } else if ( + this.isFirefox() && + (win as any).navigator.clipboard && + (win as any).navigator.clipboard.readText + ) { + return await (win as any).navigator.clipboard.readText(); + } else if (doc.queryCommandSupported && doc.queryCommandSupported("paste")) { + const textarea = doc.createElement("textarea"); + // Prevent scrolling to bottom of page in MS Edge. + textarea.style.position = "fixed"; + doc.body.appendChild(textarea); + textarea.focus(); + try { + // Security exception may be thrown by some browsers. + if (doc.execCommand("paste")) { + return textarea.value; + } + } catch (e) { + // eslint-disable-next-line + console.warn("Read from clipboard failed.", e); + } finally { + doc.body.removeChild(textarea); + } + } + return null; + } + + resolveDialogPromise(dialogId: number, confirmed: boolean) { + if (this.showDialogResolves.has(dialogId)) { + const resolveObj = this.showDialogResolves.get(dialogId); + resolveObj.resolve(confirmed); + this.showDialogResolves.delete(dialogId); + } + + // Clean up old promises + this.showDialogResolves.forEach((val, key) => { + const age = new Date().getTime() - val.date.getTime(); + if (age > DialogPromiseExpiration) { + this.showDialogResolves.delete(key); + } + }); + } + + async resolvePasswordDialogPromise( + dialogId: number, + canceled: boolean, + password: string + ): Promise { + let result = false; + if (this.passwordDialogResolves.has(dialogId)) { + const resolveObj = this.passwordDialogResolves.get(dialogId); + if (await resolveObj.tryResolve(canceled, password)) { + this.passwordDialogResolves.delete(dialogId); + result = true; + } + } + + // Clean up old promises + this.passwordDialogResolves.forEach((val, key) => { + const age = new Date().getTime() - val.date.getTime(); + if (age > DialogPromiseExpiration) { + this.passwordDialogResolves.delete(key); + } + }); + + return result; + } + + async supportsBiometric() { + const platformInfo = await BrowserApi.getPlatformInfo(); + if (platformInfo.os === "android") { + return false; + } + + if (this.isFirefox()) { + return parseInt((await browser.runtime.getBrowserInfo()).version.split(".")[0], 10) >= 87; + } + + return true; + } + + authenticateBiometric() { + return this.biometricCallback(); + } + + sidebarViewName(): string { + if ((window as any).chrome.sidebarAction && this.isFirefox()) { + return "sidebar"; + } else if (this.isOpera() && typeof opr !== "undefined" && opr.sidebarAction) { + return "sidebar_panel"; + } + + return null; + } + + supportsSecureStorage(): boolean { + return false; + } + + getDefaultSystemTheme(): Promise { + return Promise.resolve(this.prefersColorSchemeDark.matches ? ThemeType.Dark : ThemeType.Light); + } + + onDefaultSystemThemeChange(callback: (theme: ThemeType.Light | ThemeType.Dark) => unknown) { + this.prefersColorSchemeDark.addEventListener("change", ({ matches }) => { + callback(matches ? ThemeType.Dark : ThemeType.Light); + }); + } + + async getEffectiveTheme() { + const theme = (await this.stateService.getTheme()) as ThemeType; + if (theme == null || theme === ThemeType.System) { + return this.getDefaultSystemTheme(); + } else { + return theme; + } + } +} diff --git a/apps/browser/src/services/browserStorage.service.ts b/apps/browser/src/services/browserStorage.service.ts new file mode 100644 index 0000000000..455d541959 --- /dev/null +++ b/apps/browser/src/services/browserStorage.service.ts @@ -0,0 +1,55 @@ +import { StorageService } from "jslib-common/abstractions/storage.service"; + +export default class BrowserStorageService implements StorageService { + private chromeStorageApi: any; + + constructor() { + this.chromeStorageApi = chrome.storage.local; + } + + async get(key: string): Promise { + return new Promise((resolve) => { + this.chromeStorageApi.get(key, (obj: any) => { + if (obj != null && obj[key] != null) { + resolve(obj[key] as T); + return; + } + resolve(null); + }); + }); + } + + async has(key: string): Promise { + return (await this.get(key)) != null; + } + + async save(key: string, obj: any): Promise { + if (obj == null) { + // Fix safari not liking null in set + return new Promise((resolve) => { + this.chromeStorageApi.remove(key, () => { + resolve(); + }); + }); + } + + if (obj instanceof Set) { + obj = Array.from(obj); + } + + const keyedObj = { [key]: obj }; + return new Promise((resolve) => { + this.chromeStorageApi.set(keyedObj, () => { + resolve(); + }); + }); + } + + async remove(key: string): Promise { + return new Promise((resolve) => { + this.chromeStorageApi.remove(key, () => { + resolve(); + }); + }); + } +} diff --git a/apps/browser/src/services/i18n.service.ts b/apps/browser/src/services/i18n.service.ts new file mode 100644 index 0000000000..eab97affed --- /dev/null +++ b/apps/browser/src/services/i18n.service.ts @@ -0,0 +1,94 @@ +import { I18nService as BaseI18nService } from "jslib-common/services/i18n.service"; + +export default class I18nService extends BaseI18nService { + constructor(systemLanguage: string) { + super(systemLanguage, null, async (formattedLocale: string) => { + // Deprecated + const file = await fetch(this.localesDirectory + formattedLocale + "/messages.json"); + return await file.json(); + }); + + // Please leave 'en' where it is, as it's our fallback language in case no translation can be found + this.supportedTranslationLocales = [ + "en", + "az", + "be", + "bg", + "bn", + "bs", + "ca", + "cs", + "da", + "de", + "el", + "en-GB", + "en-IN", + "es", + "et", + "fa", + "fi", + "fil", + "fr", + "he", + "hi", + "hr", + "hu", + "id", + "it", + "ja", + "ka", + "km", + "kn", + "ko", + "lt", + "lv", + "ml", + "nb", + "nl", + "nn", + "pl", + "pt-BR", + "pt-PT", + "ro", + "ru", + "si", + "sk", + "sl", + "sr", + "sv", + "th", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW", + ]; + } + + t(id: string, p1?: string, p2?: string, p3?: string): string { + return this.translate(id, p1, p2, p3); + } + + translate(id: string, p1?: string, p2?: string, p3?: string): string { + if (this.localesDirectory == null) { + const placeholders: string[] = []; + if (p1 != null) { + placeholders.push(p1); + } + if (p2 != null) { + placeholders.push(p2); + } + if (p3 != null) { + placeholders.push(p3); + } + + if (placeholders.length) { + return chrome.i18n.getMessage(id, placeholders); + } else { + return chrome.i18n.getMessage(id); + } + } + + return super.translate(id, p1, p2, p3); + } +} diff --git a/apps/browser/src/services/state.service.ts b/apps/browser/src/services/state.service.ts new file mode 100644 index 0000000000..4d632baa43 --- /dev/null +++ b/apps/browser/src/services/state.service.ts @@ -0,0 +1,95 @@ +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { StorageOptions } from "jslib-common/models/domain/storageOptions"; +import { StateService as BaseStateService } from "jslib-common/services/state.service"; + +import { Account } from "../models/account"; +import { BrowserComponentState } from "../models/browserComponentState"; +import { BrowserGroupingsComponentState } from "../models/browserGroupingsComponentState"; +import { BrowserSendComponentState } from "../models/browserSendComponentState"; + +import { StateService as StateServiceAbstraction } from "./abstractions/state.service"; + +export class StateService + extends BaseStateService + implements StateServiceAbstraction +{ + async addAccount(account: Account) { + // Apply browser overrides to default account values + account = new Account(account); + await super.addAccount(account); + } + + async getIsAuthenticated(options?: StorageOptions): Promise { + // Firefox Private Mode can clash with non-Private Mode because they both read from the same onDiskOptions + // Check that there is an account in memory before considering the user authenticated + return ( + (await super.getIsAuthenticated(options)) && + (await this.getAccount(this.defaultInMemoryOptions)) != null + ); + } + + async getBrowserGroupingComponentState( + options?: StorageOptions + ): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.groupings; + } + + async setBrowserGroupingComponentState( + value: BrowserGroupingsComponentState, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.groupings = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getBrowserCipherComponentState(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.ciphers; + } + + async setBrowserCipherComponentState( + value: BrowserComponentState, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.ciphers = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getBrowserSendComponentState(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.send; + } + + async setBrowserSendComponentState( + value: BrowserSendComponentState, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.send = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + async getBrowserSendTypeComponentState(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.sendType; + } + + async setBrowserSendTypeComponentState( + value: BrowserComponentState, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.sendType = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } +} diff --git a/apps/browser/src/services/vaultFilter.service.ts b/apps/browser/src/services/vaultFilter.service.ts new file mode 100644 index 0000000000..28ada46ae1 --- /dev/null +++ b/apps/browser/src/services/vaultFilter.service.ts @@ -0,0 +1,73 @@ +import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model"; +import { VaultFilterService as BaseVaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +export class VaultFilterService extends BaseVaultFilterService { + vaultFilter: VaultFilter = new VaultFilter(); + + allVaults = "allVaults"; + myVault = "myVault"; + + constructor( + stateService: StateService, + organizationService: OrganizationService, + folderService: FolderService, + cipherService: CipherService, + collectionService: CollectionService, + policyService: PolicyService + ) { + super( + stateService, + organizationService, + folderService, + cipherService, + collectionService, + policyService + ); + this.vaultFilter.myVaultOnly = false; + this.vaultFilter.selectedOrganizationId = null; + } + + getVaultFilter() { + return this.vaultFilter; + } + + setVaultFilter(filter: string) { + if (filter === this.allVaults) { + this.vaultFilter.myVaultOnly = false; + this.vaultFilter.selectedOrganizationId = null; + } else if (filter === this.myVault) { + this.vaultFilter.myVaultOnly = true; + this.vaultFilter.selectedOrganizationId = null; + } else { + this.vaultFilter.myVaultOnly = false; + this.vaultFilter.selectedOrganizationId = filter; + } + } + + clear() { + this.setVaultFilter(this.allVaults); + } + + filterCipherForSelectedVault(cipher: CipherView) { + if (!this.vaultFilter.selectedOrganizationId && !this.vaultFilter.myVaultOnly) { + return false; + } + if (this.vaultFilter.selectedOrganizationId) { + if (cipher.organizationId === this.vaultFilter.selectedOrganizationId) { + return false; + } + } else if (this.vaultFilter.myVaultOnly) { + if (!cipher.organizationId) { + return false; + } + } + return true; + } +} diff --git a/apps/browser/src/services/vaultTimeout.service.ts b/apps/browser/src/services/vaultTimeout.service.ts new file mode 100644 index 0000000000..4678a4f522 --- /dev/null +++ b/apps/browser/src/services/vaultTimeout.service.ts @@ -0,0 +1,30 @@ +import { VaultTimeoutService as BaseVaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; + +import { SafariApp } from "../browser/safariApp"; + +export default class VaultTimeoutService extends BaseVaultTimeoutService { + startCheck() { + this.checkVaultTimeout(); + if (this.platformUtilsService.isSafari()) { + this.checkSafari(); + } else { + setInterval(() => this.checkVaultTimeout(), 10 * 1000); // check every 10 seconds + } + } + + // This is a work-around to safari adding an arbitary delay to setTimeout and + // setIntervals. It works by calling the native extension which sleeps for 10s, + // efficiently replicating setInterval. + async checkSafari() { + // eslint-disable-next-line + while (true) { + try { + await SafariApp.sendMessageToApp("sleep"); + this.checkVaultTimeout(); + } catch (e) { + // eslint-disable-next-line + console.log("Exception Safari VaultTimeout", e); + } + } + } +} diff --git a/apps/browser/store/icons/chrome-icon128.png b/apps/browser/store/icons/chrome-icon128.png new file mode 100644 index 0000000000..9bce320e73 Binary files /dev/null and b/apps/browser/store/icons/chrome-icon128.png differ diff --git a/apps/browser/store/icons/icon64.png b/apps/browser/store/icons/icon64.png new file mode 100644 index 0000000000..5b9d09d51d Binary files /dev/null and b/apps/browser/store/icons/icon64.png differ diff --git a/apps/browser/store/icons/windows-icon300.png b/apps/browser/store/icons/windows-icon300.png new file mode 100644 index 0000000000..ba18ac07bb Binary files /dev/null and b/apps/browser/store/icons/windows-icon300.png differ diff --git a/apps/browser/store/locales/az/copy.resx b/apps/browser/store/locales/az/copy.resx new file mode 100644 index 0000000000..c6ae1c74cc --- /dev/null +++ b/apps/browser/store/locales/az/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Ödənişsiz Parol Meneceri + + + Bütün cihazlarınız üçün təhlükəsiz və ödənişsiz bir parol meneceri + + + Bitwarden, Inc., 8bit Solutions LLC-nin ana şirkətidir. + +THE VERGE, U.S. NEWS & WORLD REPORT, CNET VƏ BİR ÇOXUNA GÖRƏ ƏN YAXŞI PAROL MENECERİDİR. + +Hər yerdən limitsiz cihazda limitsiz parolu idarə edin, saxlayın, qoruyun və paylaşın. Bitwarden evdə, işdə və ya yolda hər kəsə açıq mənbəli parol idarəetmə həllərini təqdim edir. + +Çox istifadə etdiyiniz hər veb sayt üçün təhlükəsizlik tələblərinə görə güclü, unikal və təsadüfi parollar yaradın. + +Bitwarden Send şifrələnmiş məlumatların (fayl və sadə mətnləri) birbaşa və sürətli göndərilməsini təmin edir. + +Bitwarden, parolları iş yoldaşlarınızla təhlükəsiz paylaşa bilməyiniz üçün şirkətlərə Teams və Enterprise planları təklif edir. + +Nəyə görə Bitwarden-i seçməliyik: + +Yüksək səviyyə şifrələmə +Parollarınız qabaqcıl ucdan-uca şifrələmə (AES-256 bit, salted hashtag və PBKDF2 SHA-256) ilə qorunur, beləcə verilənlərinizin təhlükəsiz və gizli qalmasını təmin edir. + +Daxili parol yaradıcı +Çox istifadə etdiyiniz hər veb sayt üçün təhlükəsizlik tələblərinə görə güclü, unikal və təsadüfi şifrələr yaradın. + +Qlobal tərcümələr +Bitwarden tərcümələri 40 dildə mövcuddur və qlobal cəmiyyətimiz sayəsində böyüməyə davam edir. + +Çarpaz platform tətbiqləri +Bitwarden anbarındakı həssas verilənləri, istənilən səyyahdan, mobil cihazdan və ya masaüstü əməliyyat sistemindən və daha çoxundan qoruyub paylaşın. + + + Bütün cihazlarınız üçün təhlükəsiz və ödənişsiz bir parol meneceri + + + Anbarınıza bir neçə cihazdan eyniləşdirərək müraciət edin + + + Bütün giriş məlumatlarınızı və parollarınızı təhlükəsiz bir anbardan idarə edin + + + Giriş kimlik məlumatlarınızı ziyarət etdiyiniz istənilən veb sayta dərhal avtomatik doldurun + + + Anbarınıza sağ klikləmə menyusundan da asanlıqla müraciət edə bilərsiniz + + + Güclü, təsadüfi və etibarlı parolların avtomatik yaradılması + + + Məlumatlarınız AES-256 bit şifrələmə istifadə edilərək təhlükəsiz şəkildə idarə olunur + + diff --git a/apps/browser/store/locales/be/copy.resx b/apps/browser/store/locales/be/copy.resx new file mode 100644 index 0000000000..76c10a400e --- /dev/null +++ b/apps/browser/store/locales/be/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – бясплатны менеджар пароляў + + + Бяспечны і бясплатны менеджар пароляў для ўсіх вашых прылад + + + Bitwarden - просты і бяспечны спосаб захоўваць усе вашы імёны карыстальніка і паролі, а таксама лёгка іх сінхранізаваць паміж усімі вашымі прыладамі. Пашырэнне праграмы Bitwarden дазваляе хутка ўвайсці на любы вэб-сайт з дапамогай Safari або Chrome і падтрымліваецца сотнямі іншых папулярных праграм. + +Крадзеж пароляў — сур'ёзная праблема. Сайты і праграмы, якія вы выкарыстоўваеце падвяргаюцца нападам кожны дзень. Праблемы ў іх бяспецы могуць прывесці да крадзяжу вашага пароля. Акрамя таго, калі вы выкарыстоўваеце адны і тыя ж паролі на розных сайтах і праграмах, то хакеры могуць лёгка атрымаць доступ да некалькіх вашых уліковых запісаў адразу (да паштовай скрыні, да банкаўскага рахунку ды г. д.). + +Эксперты па бяспецы рэкамендуюць выкарыстоўваць розныя выпадкова знегерыраваныя паролі для кожнага створанага вамі ўліковага запісу. Але як жа кіраваць усімі гэтымі паролямі? Bitwarden дазваляе вам лёгка атрымаць доступ да вашых пароляў, а гэтак жа ствараць і захоўваць іх. + +Bitwarden захоўвае ўсе вашы імёны карыстальніка і паролі ў зашыфраваным сховішчы, якое сінхранізуецца паміж усімі вашымі прыладамі. Да таго, як даныя пакінуць вашу прыладу, яны будуць зашыфраваны і толькі потым адпраўлены. Мы ў Bitwarden не зможам прачытаць вашы даныя, нават калі мы гэтага захочам. Вашы даныя зашыфраваны пры дапамозе алгарытму AES-256 і PBKDF2 SHA-256. + +Bitwarden — гэта праграмнае забеспячэнне з адкрытым на 100% зыходным кодам. Зыходны код Bitwarden размешчаны на GitHub, і кожны можа свабодна праглядаць, правяраць і рабіць унёсак у код Bitwarden. + + + Бяспечны і бясплатны менеджар пароляў для ўсіх вашых прылад + + + Сінхранізацыя і доступ да сховішча з некалькіх прылад + + + Кіруйце ўсімі вашымі імёнамі карыстальніка і паролямі з бяспечнага сховішча + + + Хутка і аўтаматычна запаўняйце свае ўліковыя даныя на любым вэб-сайце + + + У вас ёсць зручны доступ да сховішча з кантэкстнага меню + + + Аўтаматычна генерыруйце моцныя, выпадковыя і бяспечныя паролі + + + Вашыя звесткі надзейна захоўваюцца, дзякуючы шыфраванню AES-256 + + diff --git a/apps/browser/store/locales/bg/copy.resx b/apps/browser/store/locales/bg/copy.resx new file mode 100644 index 0000000000..d632c325ce --- /dev/null +++ b/apps/browser/store/locales/bg/copy.resx @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden — безплатен управител на пароли + + + Сигурен и свободен управител на пароли за всички устройства + + + Bitwarden е най-лесният и надежден начин да съхранявате регистрации и пароли като ги синхронизирате на всички свои устройства. +Кражбата на пароли е тежък проблем. Сайтовете в Интернет, програмите и мобилните приложения биват атакувани всеки ден. Пробивите в сигурността са факт и паролите биват откраднати. Ако използвате една и съща парола в много програми или сайтове, злонамерени лица могат лесно да достъпят вашата е-поща, електронно банкиране и други важни регистрации. +Експертите по сигурността препоръчват да ползвате различна, случайно генерирана парола за всяка отделна регистрация. Как да управлявате всичките тези пароли? Bitwarden ви позволява лесно да ги създавате, съхранявате и ползвате. +Bitwarden съхранява всички данни в шифриран трезор, който се синхронизира на всички устройства, които ползвате. Шифрирането се извършва преди данните да напуснат устройството ви — така само вие имате достъп до тях. Дори и екипът на Bitwarden не може да прочете данните, дори и да се опита. Данните са защитени чрез AES с 256-битов ключ, контролни суми с добавени случайни данни и удължаване на ключа с PBKDF2 SHA-256. +Bitwarden е със 100% отворен код! Изходният код е наличен в сайта GitHub и всеки може да го преглежда, извърши одит и даже да допринесе за Bitwarden. + + + Сигурен и свободен управител на пароли за всички устройства + + + Удобен достъп до трезора, който се синхронизира от всички устройства + + + Управление на всички регистрации и пароли чрез защитен трезор + + + Бързо автоматично попълване на данни и пароли във всички сайтове, които посещавате + + + Трезорът е достъпен и от контекстното меню при щракване с дясното копче на мишката + + + Автоматично създаване на силни, сигурни, случайни пароли + + + Данните ви са управлявани сигурно чрез AES-256 битово шифроване + + diff --git a/apps/browser/store/locales/bn/copy.resx b/apps/browser/store/locales/bn/copy.resx new file mode 100644 index 0000000000..3a40359b33 --- /dev/null +++ b/apps/browser/store/locales/bn/copy.resx @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – বিনামূল্যের পাসওয়ার্ড ব্যবস্থাপক + + + আপনার সমস্ত ডিভাইসের জন্য একটি সুরক্ষিত এবং বিনামূল্যের পাসওয়ার্ড ব্যবস্থাপক + + + বিটওয়ার্ডেন আপনার সমস্ত লগইন এবং পাসওয়ার্ডগুলি সহজেই আপনার সমস্ত ডিভাইসের সাথে সিঙ্ক করার সময় সংরক্ষণ করার সবচেয়ে সহজ এবং নিরাপদ উপায়। +পাসওয়ার্ড চুরি একটি গুরুতর সমস্যা। আপনি যে ওয়েবসাইটগুলি এবং অ্যাপ্লিকেশনগুলি ব্যবহার করেন সেগুলি প্রতিদিন আক্রমণের শিকার হয়। সুরক্ষা লঙ্ঘন ঘটে এবং আপনার পাসওয়ার্ডগুলি চুরি হয়ে যায়। আপনি যখন অ্যাপ্লিকেশন এবং ওয়েবসাইট জুড়ে একই পাসওয়ার্ডগুলি পুনরায় ব্যবহার করেন হ্যাকাররা সহজেই আপনার ইমেল, ব্যাংক এবং অন্যান্য গুরুত্বপূর্ণ অ্যাকাউন্টগুলিতে ব্যাবহার করতে পারে। +সুরক্ষা বিশেষজ্ঞরা আপনার তৈরি প্রতিটি অ্যাকাউন্টের জন্য একটি পৃথক, এলোমেলোভাবে উৎপন্ন পাসওয়ার্ড ব্যবহার করার পরামর্শ দেয়। কিন্তু আপনি কীভাবে এই সমস্ত পাসওয়ার্ড পরিচালনা করবেন? Bitwarden আপনার পাসওয়ার্ডগুলি তৈরি, সঞ্চয় এবং ব্যাবহার করা আপনার পক্ষে সহজ করে তোলে। +Bitwarden আপনার সমস্ত লগইন একটি এনক্রিপ্ট করা ভল্টে সঞ্চয় করে যা আপনার সমস্ত ডিভাইস জুড়ে সিঙ্ক করে। যেহেতু আপনার ডিভাইসটি ছাড়ার আগে এটি সম্পূর্ণরূপে এনক্রিপ্ট করা হয়েছে, শুধুমাত্র আপনারই ডেটাতে ব্যাবহারাধিকার রয়েছে। এমনকি আমরা Bitwarden এর দল চাইলেও আপনার তথ্যগুলি পড়তে পারব না। আপনার ডেটা AES-256 বিট এনক্রিপশন, সল্টেড হ্যাশিং এবং PBKDF2 SHA-256 দিয়ে নামমুদ্রাম্কিত করা হয়েছে। +Bitwarden ১০০% মুক্ত সফ্টওয়্যার। Bitwarden এর উৎস কোডটি গিটহাবটিতে হোস্ট করা হয়েছে এবং Bitwarden কোডবেস সকলের পর্যালোচনা, নিরীক্ষণ এবং অবদানের জন্য মুক্ত। + + + আপনার সমস্ত ডিভাইসের জন্য একটি সুরক্ষিত এবং বিনামূল্যের পাসওয়ার্ড ব্যবস্থাপক + + + একাধিক ডিভাইস থেকে আপনার ভল্ট সিঙ্ক এবং ব্যাবহার করুন + + + সুরক্ষিত ভল্ট থেকে আপনার সমস্ত লগইন এবং পাসওয়ার্ড পরিচালনা করুন + + + যে কোনও ওয়েবসাইটে দ্রুত আপনার লগইন শংসাপত্রগুলি স্বয়ংক্রিয়ভাবে পূরণ করুন + + + আপনার ভল্টটি ডান ক্লিক মেনু থেকে সুবিধামত ব্যাবহারযোগ্য + + + স্বয়ংক্রিয়ভাবে শক্তিশালী, এলোমেলো এবং সুরক্ষিত পাসওয়ার্ড তৈরি করুন + + + আপনার তথ্য AES-256 বিট এনক্রিপশন ব্যবহার করে সুরক্ষিতভাবে পরিচালিত হয় + + diff --git a/apps/browser/store/locales/bs/copy.resx b/apps/browser/store/locales/bs/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/bs/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/ca/copy.resx b/apps/browser/store/locales/ca/copy.resx new file mode 100644 index 0000000000..aaabe81d59 --- /dev/null +++ b/apps/browser/store/locales/ca/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Administrador de contrasenyes gratuït + + + Administrador de contrasenyes segur i gratuït per a tots els vostres dispositius + + + Bitwarden, Inc. és la companyia matriu de solucions de 8 bits LLC. + +Nomenada Millor gestor de contrasenyes per THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Gestioneu, emmagatzemeu, segures i compartiu contrasenyes il·limitades a través de dispositius il·limitats des de qualsevol lloc. Bitwarden lliura solucions de gestió de contrasenyes de codi obert a tothom, ja siga a casa, a la feina o sobre la marxa. + +Genereu contrasenyes fortes, úniques i aleatòries basades en els requisits de seguretat per a cada lloc web que freqüenteu. + +Bitwarden Send transmet ràpidament informació xifrada --- Fitxers i text complet - directament a qualsevol persona. + +Bitwarden ofereix equips i plans empresarials per a empreses perquè pugueu compartir amb seguretat contrasenyes amb els companys. + +Per què triar Bitwarden: + +Xifratge de classe mundial +Les contrasenyes estan protegides amb un xifratge avançat fi-a-fi (AES-256 bit, salted hashtag, and PBKDF2 SHA-256), de manera que les vostres dades es mantenen segures i privades. + +Generador de contrasenyes integrat +Genereu contrasenyes fortes, úniques i aleatòries basades en els requisits de seguretat per a cada lloc web que freqüenteu. + +Traduccions globals +Les traduccions de Bitwarden existeixen en 40 idiomes i creixen, gràcies a la nostra comunitat global. + +Aplicacions de plataforma creuada +Assegureu-vos i compartiu dades sensibles a la vostra caixa forta de Bitwarden des de qualsevol navegador, dispositiu mòbil o S.O. d'escriptori, i molt més. + + + Administrador de contrasenyes segur i gratuït per a tots els vostres dispositius + + + Sincronitzeu i accediu a la vostra caixa forta des de diversos dispositius + + + Administreu tots els inicis de sessió i contrasenyes des d'una caixa forta segura + + + Ompli automàticament les vostres credencials d'inici de sessió a qualsevol lloc web que visiteu + + + La vostra caixa forta també es pot accedir des del menú del botó dret + + + Genera automàticament contrasenyes fortes, aleatòries i segures + + + La vostra informació s'administra amb seguretat utilitzant el xifratge AES-256 bit + + diff --git a/apps/browser/store/locales/cs/copy.resx b/apps/browser/store/locales/cs/copy.resx new file mode 100644 index 0000000000..36a54971d2 --- /dev/null +++ b/apps/browser/store/locales/cs/copy.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Bezplatný správce hesel + + + Bezpečný a bezplatný správce hesel pro všechna vaše zařízení + + + bitwarden je nejjednodušší a nejbezpečnější způsob, jak uchovávat veškeré své přihlašovací údaje a zároveň je mít pohodlně synchronizované mezi všemi svými zařízeními. + +Krádež hesla je velice vážný problém. Stránky a aplikace, které každodenně používáte, jsou často pod útokem a vaše hesla mohou být odcizena. Pokud používáte stejné heslo mezi více aplikacemi nebo stránkami, hackeři se mohou snadno dostat k vaší emailové schránce, bankovnímu účtu či do jiných důležitých účtů. + +Bezpečnostní experti proto doporučují používat různá, silná a náhodně generovaná hesla pro každý účet zvlášť. Ale jak tato všechna hesla spravovat? bitwarden vám ulehčí jejich správu, ale také jejich generování nebo sdílení. + +bitwarden uchovává veškeré vaše přihlašovací údaje v zašifrovaném trezoru, který se synchronizuje mezi všemi vašimi zařízeními. Jelikož jsou zašifrována ještě před opuštěním vašeho zařízení, máte přístup ke svým datům pouze vy. Dokonce ani tým v bitwardenu nemůže číst vaše data a to ani kdybychom chtěli. Vaše data jsou totiž zakódována pomocí šifrovávání AES-256, náhodným hashem a PBKDF2 SHA-256. + + + Bezpečný a bezplatný správce hesel pro všechna vaše zařízení + + + Synchronizujte a přistupujte ke svému trezoru z různých zařízení + + + Spravujte veškeré své přihlašovací údaje z bezpečného trezoru + + + Rychle vyplňte své přihlašovací údaje na webových stránkách + + + Ovládejte svůj trezor pohodlně z kontextové nabídky + + + Vygenerujte si silná, jedinečná a bezpečná hesla + + + Vaše informace jsou bezpečně zašifrovány pomocí AES-256 šifrování + + diff --git a/apps/browser/store/locales/da/copy.resx b/apps/browser/store/locales/da/copy.resx new file mode 100644 index 0000000000..6159bb2d67 --- /dev/null +++ b/apps/browser/store/locales/da/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Gratis adgangskodemanager + + + En sikker og gratis adgangskodemanager til alle dine enheder + + + Bitwarden, Inc. er moderselskab for 8bit Solutions LLC. + +UDNÆVNT BEDSTE PASSWORD MANAGER AF THE VERGE, U.S. NEWS & WORLD REPORT, CNET OG FLERE. + +Administrér, gem, sikr og del adgangskoder ubegrænset på tværs af enheder hvor som helst. Bitwarden leverer open source adgangskodeadministrationsløsninger til alle, hvad enten det er hjemme, på arbejdspladsen eller på farten. + +Generér stærke, unikke og tilfældige adgangskoder baseret på sikkerhedskrav til hvert websted, du besøger. + +Bitwarden Send overfører hurtigt krypterede oplysninger --- filer og almindelig tekst - direkte til enhver. + +Bitwarden tilbyder Teams og Enterprise-planer for virksomheder, så du sikkert kan dele adgangskoder med kolleger. + +Hvorfor vælge Bitwarden: + +Kryptering i verdensklasse +Adgangskoder er beskyttet med avanceret end-to-end-kryptering (AES-256 bit, saltet hashtag og PBKDF2 SHA-256), så dine data forbliver sikre og private. + +Indbygget adgangskodegenerator +Generér stærke, unikke og tilfældige adgangskoder baseret på sikkerhedskrav til hvert websted, du besøger. + +Globale oversættelser +Bitwarden findes på 40 sprog, og flere kommer til, takket være vores globale fællesskab. + +Applikationer på tværs af platforme +Beskyt og del følsomme data i din Bitwarden boks fra enhver browser, mobilenhed eller desktop OS og mere. + + + En sikker og gratis adgangskodemanager til alle dine enheder + + + Synkroniser og få adgang til din boks fra flere enheder + + + Håndtér alle din logins og adgangskoder fra en sikker boks + + + Auto-udfyld hurtigt dine loginoplysninger på enhver hjemmeside, som du besøger + + + Din boks er også bekvemt tilgængelig fra højreklik-menuen + + + Opret automatisk stærke, tilfældige og sikre adgangskoder + + + Dine oplysninger håndteres sikkert ved hjælp af AES-256 bit kryptering + + diff --git a/apps/browser/store/locales/de/copy.resx b/apps/browser/store/locales/de/copy.resx new file mode 100644 index 0000000000..93b0cd99c2 --- /dev/null +++ b/apps/browser/store/locales/de/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Kostenloser Passwort-Manager + + + Ein sicherer und kostenloser Passwort-Manager für all deine Geräte + + + Bitwarden, Inc. ist die Muttergesellschaft von 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER DY THE VERGE, U.S. NEWS & WORLD REPORT, CNET UND MORE. + +Verwalte, speichere, sichere und teile unbegrenzte Passwörter von überall auf unbegrenzten Geräten. Bitwarden liefert Open-Source-Passwort-Management-Lösungen für jedermann, sei es zu Hause, am Arbeitsplatz oder unterwegs. + +Generiere starke, einzigartige und zufällige Passwörter basierend auf Sicherheitsanforderungen für jede Website, die du häufig besuchst. + +Bitwarden Send überträgt schnell verschlüsselte Informationen - Dateien und Klartext - direkt an jeden. + +Bitwarden bietet Teams und Enterprise Pläne für Unternehmen an, damit du Passwörter sicher mit Kollegen teilen kannst. + +Warum Bitwarden: + +Weltklasse Verschlüsselung +Passwörter sind durch erweiterte Ende-zu-Ende-Verschlüsselung (AES-256 Bit, salted hashtag und PBKDF2 SHA-256) so bleiben deine Daten sicher und privat. + +Integrierter Passwortgenerator +Generiere starke, einzigartige und zufällige Passwörter basierend auf Sicherheitsanforderungen für jede Website, die du häufig besuchst. + +Globale Übersetzungen +Bitwarden Übersetzungen existieren in 40 Sprachen und wachsen dank unserer globalen Gemeinschaft. + +Plattformübergreifende Anwendungen +Sichere und teile vertrauliche Daten in deinem Bitwarden Vault von jedem Browser, jedem mobilen Gerät oder Desktop-Betriebssystem und mehr. + + + + Ein sicherer und kostenloser Passwort-Manager für all deine Geräte + + + Synchronisiere und greife auf deinen Tresor von unterschiedlichen Geräten aus zu + + + Verwalte all deine Logins und Passwörter mit einem sicheren Tresor + + + Auto-Vervollständige alle Login-Informationen schnell auf jeder Website, die du besuchst + + + Dein Tresor kann auch über das Kontextmenü einfach erreicht werden + + + Generiere automatisch starke, zufällige und sichere Passwörter + + + Deine Informationen sind sicher dank AES-256-Bit-Verschlüsselung + + diff --git a/apps/browser/store/locales/el/copy.resx b/apps/browser/store/locales/el/copy.resx new file mode 100644 index 0000000000..de4f9e5ff6 --- /dev/null +++ b/apps/browser/store/locales/el/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Δωρεάν Διαχειριστής Κωδικών + + + Ένας ασφαλής και δωρεάν διαχειριστής κωδικών για όλες τις συσκευές σας + + + Το Bitwarden είναι ο ευκολότερος και ασφαλέστερος τρόπος για να αποθηκεύσετε όλες τις συνδέσεις και τους κωδικούς πρόσβασης σας, διατηρώντας παράλληλα το συγχρονισμό μεταξύ όλων των συσκευών σας. Η επέκταση της εφαρμογής Bitwarden σας επιτρέπει να συνδεθείτε γρήγορα σε οποιαδήποτε ιστοσελίδα μέσω του Safari ή του Chrome και υποστηρίζεται από εκατοντάδες άλλες δημοφιλείς εφαρμογές. + +Η κλοπή κωδικού πρόσβασης είναι ένα σοβαρό πρόβλημα. Οι ιστοσελίδες και οι εφαρμογές που χρησιμοποιείτε υποβάλλονται σε επίθεση κάθε μέρα. Παραβιάσεις ασφαλείας συμβαίνουν και οι κωδικοί ίσως κλαπούν. Όταν επαναχρησιμοποιείτε τους ίδιους κωδικούς πρόσβασης σε εφαρμογές και ιστοσελίδες, οι χάκερ μπορούν εύκολα να έχουν πρόσβαση στο ηλεκτρονικό σας ταχυδρομείο, στην τράπεζα σας και σε άλλους σημαντικούς λογαριασμούς. + +Οι ειδικοί ασφαλείας συστήνουν να χρησιμοποιείτε διαφορετικό, τυχαία δημιουργημένο κωδικό πρόσβασης για κάθε λογαριασμό που δημιουργείτε. Αλλά πώς διαχειρίζεστε όλους αυτούς τους κωδικούς πρόσβασης; Το Bitwarden σας διευκολύνει να δημιουργείτε, να αποθηκεύετε και να έχετε πρόσβαση στους κωδικούς πρόσβασης σας. + +Το Bitwarden αποθηκεύει όλες τις συνδέσεις σας σε κρυπτογραφημένη μορφή που συγχρονίζεται σε όλες τις συσκευές σας. Δεδομένου ότι είναι πλήρως κρυπτογραφημένο, μόνο εσείς έχετε πρόσβαση στα δεδομένα σας. Ούτε η ομάδα του Bitwarden μπορεί να διαβάσει τα δεδομένα σας, ακόμα κι αν θέλουμε. Τα δεδομένα σας είναι σφραγισμένα με κρυπτογράφηση AES-256 bit, salted hashing και PBKDF2 SHA-256. + +Το Bitwarden είναι 100% λογισμικό ανοικτού κώδικα. Ο πηγαίος κώδικας για το Bitwarden φιλοξενείται στο GitHub και ο καθένας είναι ελεύθερος να επανεξετάσει, να ελέγξει και να συνεισφέρει στον κώδικα βάσης του Bitwarden. + + + Ένας ασφαλής και δωρεάν διαχειριστής κωδικών για όλες τις συσκευές σας + + + Συγχρονίστε και αποκτήστε πρόσβαση στο vault σας, από πολλές συσκευές + + + Διαχειριστείτε όλες τις συνδέσεις και τους κωδικούς σας με ασφάλεια + + + Συμπληρώστε γρήγορα και αυτόματα, τα διαπιστευτήρια της σύνδεσης σας, σε οποιονδήποτε ιστότοπο επισκέπτεστε + + + Το vault σας είναι επίσης εύκολα προσβάσιμο, με το μενού που ανοίγει με δεξί-κλικ + + + Δημιουργήστε αυτόματα ισχυρούς, τυχαίους και ασφαλείς κωδικούς + + + Οι πληροφορίες σας διαχειρίζονται με ασφάλεια χρησιμοποιώντας κρυπτογράφηση AES-256 bit + + diff --git a/apps/browser/store/locales/en/assets/chrome-tile-large.png b/apps/browser/store/locales/en/assets/chrome-tile-large.png new file mode 100644 index 0000000000..5ebb2d3fcb Binary files /dev/null and b/apps/browser/store/locales/en/assets/chrome-tile-large.png differ diff --git a/apps/browser/store/locales/en/assets/chrome-tile-marquee.png b/apps/browser/store/locales/en/assets/chrome-tile-marquee.png new file mode 100644 index 0000000000..3c12d50a2d Binary files /dev/null and b/apps/browser/store/locales/en/assets/chrome-tile-marquee.png differ diff --git a/apps/browser/store/locales/en/assets/chrome-tile-small.png b/apps/browser/store/locales/en/assets/chrome-tile-small.png new file mode 100644 index 0000000000..19907ed03c Binary files /dev/null and b/apps/browser/store/locales/en/assets/chrome-tile-small.png differ diff --git a/apps/browser/store/locales/en/copy.resx b/apps/browser/store/locales/en/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/en/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/en/screenshots/Chrome/Chrome01.png b/apps/browser/store/locales/en/screenshots/Chrome/Chrome01.png new file mode 100644 index 0000000000..4572dde4e5 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/Chrome01.png differ diff --git a/apps/browser/store/locales/en/screenshots/Chrome/Chrome02.png b/apps/browser/store/locales/en/screenshots/Chrome/Chrome02.png new file mode 100644 index 0000000000..55d8cd32f7 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/Chrome02.png differ diff --git a/apps/browser/store/locales/en/screenshots/Chrome/Chrome03.png b/apps/browser/store/locales/en/screenshots/Chrome/Chrome03.png new file mode 100644 index 0000000000..bdd0fbc415 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/Chrome03.png differ diff --git a/apps/browser/store/locales/en/screenshots/Chrome/Chrome04.png b/apps/browser/store/locales/en/screenshots/Chrome/Chrome04.png new file mode 100644 index 0000000000..736ca65ce2 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/Chrome04.png differ diff --git a/apps/browser/store/locales/en/screenshots/Chrome/Chrome05.png b/apps/browser/store/locales/en/screenshots/Chrome/Chrome05.png new file mode 100644 index 0000000000..d4ff9a184f Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/Chrome05.png differ diff --git a/apps/browser/store/locales/en/screenshots/Chrome/promo_01.png b/apps/browser/store/locales/en/screenshots/Chrome/promo_01.png new file mode 100644 index 0000000000..9478b91d8d Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/promo_01.png differ diff --git a/apps/browser/store/locales/en/screenshots/Chrome/promo_02.png b/apps/browser/store/locales/en/screenshots/Chrome/promo_02.png new file mode 100644 index 0000000000..1041eb177f Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/promo_02.png differ diff --git a/apps/browser/store/locales/en/screenshots/Chrome/promo_03.png b/apps/browser/store/locales/en/screenshots/Chrome/promo_03.png new file mode 100644 index 0000000000..42eb0131cd Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Chrome/promo_03.png differ diff --git a/apps/browser/store/locales/en/screenshots/Firefox/Firefox01.png b/apps/browser/store/locales/en/screenshots/Firefox/Firefox01.png new file mode 100644 index 0000000000..1211da6aab Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Firefox/Firefox01.png differ diff --git a/apps/browser/store/locales/en/screenshots/Firefox/Firefox02.png b/apps/browser/store/locales/en/screenshots/Firefox/Firefox02.png new file mode 100644 index 0000000000..4c9852dccb Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Firefox/Firefox02.png differ diff --git a/apps/browser/store/locales/en/screenshots/Firefox/Firefox03.png b/apps/browser/store/locales/en/screenshots/Firefox/Firefox03.png new file mode 100644 index 0000000000..3eb1075230 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Firefox/Firefox03.png differ diff --git a/apps/browser/store/locales/en/screenshots/Firefox/Firefox04.png b/apps/browser/store/locales/en/screenshots/Firefox/Firefox04.png new file mode 100644 index 0000000000..475d4106df Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Firefox/Firefox04.png differ diff --git a/apps/browser/store/locales/en/screenshots/Firefox/Firefox05.png b/apps/browser/store/locales/en/screenshots/Firefox/Firefox05.png new file mode 100644 index 0000000000..e448ab8f7e Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Firefox/Firefox05.png differ diff --git a/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge01.png b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge01.png new file mode 100644 index 0000000000..79e414a7d5 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge01.png differ diff --git a/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge02.png b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge02.png new file mode 100644 index 0000000000..0ef6da39f8 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge02.png differ diff --git a/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge03.png b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge03.png new file mode 100644 index 0000000000..d2b10f25bc Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge03.png differ diff --git a/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge04.png b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge04.png new file mode 100644 index 0000000000..aa8e9c0a45 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge04.png differ diff --git a/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge05.png b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge05.png new file mode 100644 index 0000000000..dc36bf1033 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/MicrosoftEdge/Edge05.png differ diff --git a/apps/browser/store/locales/en/screenshots/Opera/Opera01.png b/apps/browser/store/locales/en/screenshots/Opera/Opera01.png new file mode 100644 index 0000000000..a3b42b006d Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Opera/Opera01.png differ diff --git a/apps/browser/store/locales/en/screenshots/Opera/Opera02.png b/apps/browser/store/locales/en/screenshots/Opera/Opera02.png new file mode 100644 index 0000000000..9f081532fb Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Opera/Opera02.png differ diff --git a/apps/browser/store/locales/en/screenshots/Opera/Opera03.png b/apps/browser/store/locales/en/screenshots/Opera/Opera03.png new file mode 100644 index 0000000000..d42b7a0177 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Opera/Opera03.png differ diff --git a/apps/browser/store/locales/en/screenshots/Opera/Opera04.png b/apps/browser/store/locales/en/screenshots/Opera/Opera04.png new file mode 100644 index 0000000000..2186cb1652 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Opera/Opera04.png differ diff --git a/apps/browser/store/locales/en/screenshots/Opera/Opera05.png b/apps/browser/store/locales/en/screenshots/Opera/Opera05.png new file mode 100644 index 0000000000..41674b0251 Binary files /dev/null and b/apps/browser/store/locales/en/screenshots/Opera/Opera05.png differ diff --git a/apps/browser/store/locales/en_GB/copy.resx b/apps/browser/store/locales/en_GB/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/en_GB/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/en_IN/copy.resx b/apps/browser/store/locales/en_IN/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/en_IN/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/es/copy.resx b/apps/browser/store/locales/es/copy.resx new file mode 100644 index 0000000000..c1b0243221 --- /dev/null +++ b/apps/browser/store/locales/es/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Gestor de contraseñas gratuito + + + Un gestor de contraseñas seguro y gratuito para todos tus dispositivos + + + Bitwarden, Inc. es la compañía matriz de 8bit Solutions LLC. + +NOMBRADO EL MEJOR ADMINITRADOR DE CONTRASEÑAS POR THE VERGE, U.S. NEWS & WORLD REPORT Y CNET, ENTRE OTROS. + +Administra, almacena, protege y comparte contraseñas ilimitadas entre dispositivos ilimitados desde cualquier parte. Bitwarden ofrece soluciones de administración de contraseñas de código abierto para todos, ya sea en casa, en el trabajo o mientras viajas. + +Genera contraseñas fuertes, únicas y aleatorias basadas en los requisitos de seguridad de cada sitio web que frecuentes. + +Bitwarden Send transmite rápidamente información cifrada --- archivos y texto simple -- de forma directa a cualquier persona. + +Bitwarden ofrece los planes Teams y Enterprise para que puedas compartir contraseñas de forma segura entre colegas de la misma empresa. + +Por qué elegir Bitwarden: + +Cifrado de clase mundial +Las contraseñas están protegidas con un cifrado avanzado de extremo a extremo (AES-256 bits, salted hashtag, y PBKDF2 SHA-256) para que tu información permanezca segura y privada. + +Generador de contraseñas incorporado +Genera contraseñas fuertes, únicas y aleatorias basadas en los requisitos de seguridad de cada sitio web que frecuentes. + +Traducciones Globales +Existen traducciones de Bitwarden en 40 idiomas y van en aumento, gracias a nuestra comunidad global. + +Aplicaciones multiplataforma +Protege y comparte información confidencial de tu bóveda Bitwarden desde cualquier navegador, dispositivo móvil, aplicación de escritorio y más. + + + + Un gestor de contraseñas seguro y gratuito para todos tus dispositivos + + + Sincroniza y accede a tu caja fuerte desde múltiples dispositivos + + + Gestiona todos tus usuarios y contraseñas desde una caja fuerte segura + + + Autorellena rápidamente tus datos de acceso en cualquier página web que visites + + + Tu caja fuerte también es fácilmente accesible desde el menú de clic derecho + + + Genera automáticamente contraseñas fuertes, aleatorias y seguras + + + Tu información es gestionada de forma segura con cifrado AES de 256 bits + + diff --git a/apps/browser/store/locales/et/copy.resx b/apps/browser/store/locales/et/copy.resx new file mode 100644 index 0000000000..333b4e0ccd --- /dev/null +++ b/apps/browser/store/locales/et/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + bitwarden - Tasuta paroolihaldur + + + Tasuta ja turvaline paroolihaldur kõikidele sinu seadmetele + + + Bitwarden muudab kontoandmete ja teiste isiklike andmete kasutamise erinevate seadmete vahel lihtsaks ja turvaliseks. + +Paroolivargustest on saamas järjest tõsisem probleem. Veebilehed ja rakendused, mida igapäevaselt kasutad, on pidevalt rünnakute all. Muuhulgas toimuvad alalõpmata andmelekked, millega koos saadakse ligipääs ka Sinu paroolidele. Kasutades erinevatel veebilehtedel ühesugust parooli, on häkkeritel lihtne ligi pääseda nii sinu e-postile, pangakontole või teistele tähtsatele kontodele. + +Turvaeksperdid soovitavad kasutada kõikides kasutajakontodes erinevaid, juhuslikult koostatud paroole. Kuidas aga kõiki neid paroole hallata? Bitwarden muudab paroolide loomise, talletamise ja nendele ligipääsu lihtsaks ja turvaliseks. + +Bitwarden talletab kõik Sinu andmed krüpteeritud hoidlas, mis sünkroniseeritakse kõikide Sinu poolt kasutatavate seadmete vahel. Kuna hoidla sisu krüpteeritakse enne selle enne seadmest lahkumist, omad andmetele ligipääsu ainult sina. Ka bitwardeni meeskond ei saa Sinu andmeid vaadata, isegi kui neil selleks tahtmine oleks. Sinu andmed kaitsevad AES-256 bitine krüpteering, salted hashing ja PBKDF2 SHA-256. + +Bitwarden on 100% avatud koodiga tarkvara. Bitwarden lähtekood on saadaval GitHubis ja kõik saavad sellega tasuta tutvuda, seda kontrollida ja Bitwardeni koodibaasi panustada. + + + Tasuta ja turvaline paroolihaldur kõikidele Sinu seadmetele + + + Sünkroniseeri ja halda oma kontot erinevates seadmetes + + + Halda kõiki kontoandmeid turvalises paroolihoidlas + + + Täida külastatavatel veebilehtedel oma kasutajakonto andmeid automaatselt ja lihtsalt + + + Pääsed paroolihaldurile hõlpsasti ligi ka parema kliki menüüst + + + Loo automaatselt tugevaid, erinevaid ja turvalisi paroole + + + Sisestatud andmeid käitatakse turvaliselt, kasutades AES-256 bitist krüpteeringut + + diff --git a/apps/browser/store/locales/fa/copy.resx b/apps/browser/store/locales/fa/copy.resx new file mode 100644 index 0000000000..116e66369c --- /dev/null +++ b/apps/browser/store/locales/fa/copy.resx @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - مدیریت کلمه عبور رایگان + + + یک مدیریت کننده کلمه عبور رایگان برای تمامی دستگاههایتان + + + Bitwarden ساده ترین و امن ترین راه گردآوری تمام داده های ورودی و پسوردها است در حالی که به راحتی آنها را بین تمامی دستگاه ها همگام میکند. + + +سرقت پسورد یک مشکل جدی است. وبسایت ها و اپلیکیشن هایی که شما از آنها استفاده میکنید هر روز تحت حملات قرار دارند. نقص های امنیتی رخ میدهند و پسوردها به سرقت میروند. زمانی که شما مجدداً از همان پسورد برای تمام وبسایت ها و اپلیکیشن ها استفاده میکنید هکرها می‌توانند به راحتی به ایمیل، حساب بانکی، و سایر حسابهای کاربریتان دسترسی داشته باشند. + + +متخصصان امنیتی توصیه میکنند که برای هر حساب کاربری که ایجاد میکنید از پسوردهای متفاوت و تصادفی تولید شده استفاده کنید. اما چطور تمامی این پسورها را مدیریت میکنید؟ بیت واردن ساختن، نگهداری، ودسترسی به پسوردهایتان را آسان میکند. + + +Bitwarden تمامی داده های ورودی شما را در یک گاو صندوق رمزنگاری شده نگهداری میکند که قابل همگام سازی توسط تمامی دستگاه های شماست. از آنجا که این داده ها هر زمان قبل از ترک دستگاهتان کاملا رمزنگاری میشود، فقط شما به اطلاعاتتان دسترسی دارید. حتی اگر تیم ما در بیت واردن هم بخواهند نمیتوانند اطلاعات شما را مشاهده کنند. داده های شما توسط رمزگذاری AES-256 بیتی، هَش خرد شده، و PBKDF2SHA-256 رمزنگاری شده است. + +Bitwarden ۱۰۰٪ یک برنامه متن باز است. کد منبع بیت واردن در GitHub میزبانی میشود و هر کس آزاد است برای بررسی، تفتیش و کمک به کد دسترسی داشته باشد. + + + یک مدیریت کننده کلمه عبور رایگان برای تمامی دستگاههایتان + + + همگام سازی و دسترسی به گاوصندوق خود را از دستگاه های مختلف + + + مدیریت تمام اطلاعات ورود و کلمه های عبورتان از یک گاوصندوق امن + + + پرکردن خودکار معتبر ورودی شما بصورت سریع برای هر وبسایتی که از آن بازدید میکنید + + + گاوصندوق شما نیز به راحتی از منوی راست کلیک قابل دسترسی است + + + به صورت خودکار کلمات عبور قوی، تصادفی و امن ایجاد کنید + + + اطلاعات شما با استفاده از رمزگذاری AES-256 بیتی ایمن مدیریت می شود + + diff --git a/apps/browser/store/locales/fi/copy.resx b/apps/browser/store/locales/fi/copy.resx new file mode 100644 index 0000000000..a27f806bb7 --- /dev/null +++ b/apps/browser/store/locales/fi/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Ilmainen salasanojen hallinta + + + Turvallinen ja ilmainen salasanojen hallinta kaikille laitteillesi + + + Bitwarden, inc. on 8bit Solutions LLC:n emoyhtiö. + +NIMENNYT PARHAAKSI SALASANOJEN HALLINNAKSI MM. THE VERGE, U.S. NEWS & WORLD REPORT JA CNET. + +Hallinnoi, säilytä, suojaa ja jaa rajattomasti salasanoja missä tahansa ja miltä tahansa laitteelta. Bitwarden tarjoaa avoimeen lähdekoodin perustuvan salasanojen hallintaratkaisun kaikille, olitpa sitten kotona, töissä tai liikkeellä. + +Luo usein käyttämillesi sivustoille automaattisesti vahvoja, yksilöllisiä ja satunnaisia salasanoja. + +Bitwarden Send -ominaisuudella lähetät tietoa nopeasti salattuna — tiedostoja ja tekstiä — suoraan kenelle tahansa. + +Yrityksille Bitwarden tarjoaa Teams ja Enterprise -tilaukset, jotta voit jakaa salasanoja kollegoiden kesken turvallisesti. + +Miksi Bitwarden?: + +Maailmanluokan salaus +Salasanat on suojattu tehokkaalla päästä päähän salauksella (AES-256 Bit, suolattu hajautus ja PBKDF2 SHA-256), joten tietosi pysyvät turvassa ja yksityisinä. + +Sisäänrakennettu salasanageneraattori +Luo usein käyttämillesi sivustoille vahvoja, yksilöllisiä ja satunnaisia salasanoja. + +Monikielinen +Bitwardenin sovelluksia on käännetty yli 40 kielelle ja määrä kasvaa jatkuvasti, kiitos kansainvälisen yhteisömme. + +Alustariippumattomaton +Suojaa, käytä ja jaa Bitwarden-holvisi arkaluontoisia tietoja kaikilla selaimilla, mobiililaitteilla, pöytätietokoneilla ja muissa järjestelmissä. + + + Turvallinen ja ilmainen salasanojen hallinta kaikille laitteillesi + + + Synkronoi ja hallitse holviasi useilla laitteilla + + + Hallitse käyttäjätunnuksiasi ja salasanojasi suojatussa holvissa + + + Täytä kirjautumistietosi automaattisesti ja nopeasti kaikilla käyttämilläsi sivustoilla + + + Pääse käsiksi holviisi myös suoraan hiiren kakkospainikkeen pikavalikosta + + + Luo automaattisesti vahvoja, satunnaisia ja turvallisia salasanoja + + + Käsittele 256-bittisellä AES-salauksella suojattuja tietojasi turvallisesti + + diff --git a/apps/browser/store/locales/fil/copy.resx b/apps/browser/store/locales/fil/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/fil/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/fr/copy.resx b/apps/browser/store/locales/fr/copy.resx new file mode 100644 index 0000000000..f8687ca5c4 --- /dev/null +++ b/apps/browser/store/locales/fr/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Gestionnaire de mots de passe gratuit + + + Un gestionnaire de mots de passe sécurisé et gratuit pour tous vos appareils + + + Bitwarden, Inc. est la société mère de 8bit Solutions LLC. + +NOMMÉ MEILLEUR GESTIONNAIRE DE MOTS DE PASSE PAR THE VERGE, U.S. NEWS & WORLD REPORT, CNET, ET PLUS ENCORE. + +Gérez, stockez, sécurisez et partagez un nombre illimité de mots de passe sur un nombre illimité d'appareils, où que vous soyez. Bitwarden fournit des solutions de gestion de mots de passe open source à tout le monde, que ce soit à la maison, au travail ou en déplacement. + +Générez des mots de passe forts, uniques et aléatoires basés sur des exigences de sécurité pour chaque site web que vous fréquentez. + +Bitwarden Send transmet rapidement des informations chiffrées --- fichiers et texte --- directement à quiconque. + +Bitwarden propose les plans Teams et Enterprise pour les entreprises afin que vous puissiez partager des mots de passe en toute sécurité avec vos collègues. + +Pourquoi choisir Bitwarden : + +Un chiffrement de classe internationale +Les mots de passe sont protégés par un chiffrement avancé de bout en bout (AES-256 bit, salted hashtag, et PBKDF2 SHA-256) afin que vos données restent sécurisées et privées. + +Générateur de mots de passe intégré +Générez des mots de passe forts, uniques et aléatoires en fonction des exigences de sécurité pour chaque site web que vous fréquentez. + +Traductions mondiales +Les traductions de Bitwarden existent dans 40 langues et ne cessent de croître, grâce à notre communauté mondiale. + +Applications multiplateformes +Sécurisez et partagez des données sensibles dans votre coffre-fort Bitwarden à partir de n'importe quel navigateur, appareil mobile ou système d'exploitation de bureau, et plus encore. + + + Un gestionnaire de mots de passe sécurisé et gratuit pour tous vos appareils + + + Synchroniser et accéder à votre coffre depuis plusieurs appareils + + + Gérer tous vos identifiants depuis un coffre sécurisé + + + Remplissage automatique et rapide de vos identifiants sur n'importe quel site que vous visitez + + + Votre coffre est également facilement accessible depuis le menu contextuel + + + Générer automatiquement des mots de passe forts, aléatoires et sécurisés + + + Vos informations sont gérées de manière sécurisée grâce à un chiffrement AES-256 bit + + diff --git a/apps/browser/store/locales/he/copy.resx b/apps/browser/store/locales/he/copy.resx new file mode 100644 index 0000000000..3ceccc9b9c --- /dev/null +++ b/apps/browser/store/locales/he/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – מנהל ססמאות חינמי + + + מנהל ססמאות חינמי ומאובטח עבור כל המכשירים שלך + + + תוכנת Bitwarden היא הדרך הקלה והבטוחה לשמירת הסיסמאות שלך ועוזרת לסנכרן את הסיסמאות בין כל המכשירים שברשותך. + +גניבת סיסמאות היא בעיה רצינית. אתרים ואפליקציות מותקפים באופן יום יומי. פירצות אבטחה קורות מדי פעם ומאגרי סיסמאות נחשפים במלואם. כשאתה משתמש באותה סיסמה עבור כמה אתרים או אפליקציות, האקרים יכולים לנצל את אותה הסיסמה עבור אותם האתרים והאפליקציות ויכולים להשיג גישה למייל, לבנק, ולחשבונות חשובים אחרים. + +מומחי אבטחה ממליצים להשתמש בסיסמאות שונות ורנדומליות עבור כל חשבון שאתה יוצר. אבל איך אפשר לנהל את כל הסיסמאות הללו? תוכנת Bitwarden עוזרת לך ליצור, לשמור, ולגשת לכל הסיסמאות שלך. + +תוכנת Bitwarden מאחסנת את כל הפרטים בכספת מוצפנת שמסתנכרנת בין כל המכשירים שלך. מאחר שהמידע מוצפן עוד לפני שהוא יוצא מהמכשיר שלך, רק לך יש גישה למידע. גם הצוות שלנו בBitwarden לא יכול לקרוא את המידע, אפילו אם ירצה. המידע שלך מוגן עם הצפנת AES-256 ביט, salted hashing, וPBKDF2 SHA-256. + +תוכנת Bitwarden היא 100% תוכנת קוד פתוח. קוד המקור של Bitwarden מאוחסן בGitHub וכל מי שרוצה יכול לתת ביקורת, להוסיף הערות, וכמובן לתרום מזמנו לפיתוח הקוד של Bitwarden. + + + מנהל סיסמאות חינמי ומאובטח עבור כל המכשירים שלך + + + סנכרון וגישה לכספת שלך ממגוון מכשירים + + + ניהול כל הססמאות ופרטי הגישה שלך בכספת מאובטחת + + + מילוי אוטומטי של פרטי הגישה שלך במהירות בכל אתר שתבקר + + + גישה נוחה לכספת שלך דרך תפריט לחיצה-ימנית + + + יצירה אוטומטית של סיסמאות חזקות, אקראיות ומאובטחות + + + המידע שלך מנוהל בצורה מאובטחת תוך שימוש בהצפנת AES‏-256 ביט + + diff --git a/apps/browser/store/locales/hi/copy.resx b/apps/browser/store/locales/hi/copy.resx new file mode 100644 index 0000000000..9edb8288ab --- /dev/null +++ b/apps/browser/store/locales/hi/copy.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + बिटवार्डन - मुक्त कूटशब्द प्रबंधक + + + आपके सभी उपकरणों के लिए एक सुरक्षित और नि: शुल्क कूटशब्द प्रबंधक + + + bitwarden is the easiest and safest way to store all of your logins and passwords while conveniently keeping them synced between all of your devices. + +Password theft is a serious problem. The websites and apps that you use are under attack every day. Security breaches occur and your passwords are stolen. When you reuse the same passwords across apps and websites hackers can easily access your email, bank, and other important accounts. + +Security experts recommend that you use a different, randomly generated password for every account that you create. But how do you manage all those passwords? bitwarden makes it easy for you to create, store, and access your passwords. + +bitwarden stores all of your logins in an encrypted vault that syncs across all of your devices. Since it's fully encrypted before it ever leaves your device, only you have access to your data. Not even the team at bitwarden can read your data, even if we wanted to. Your data is sealed with AES-256 bit encryption, salted hashing, and PBKDF2 SHA-256. + + + आपके सभी उपकरणों के लिए एक सुरक्षित और नि: शुल्क पासवर्ड प्रबंधक + + + अनेक उपकरणों से अपने तिजोरी सिंक और एक्सेस करें + + + एक सुरक्षित तिजोरी से अपने सभी लॉगिन डाटा और पासवर्ड प्रबंधित करें + + + आप गए हुए किसी भी वेबसाइट में अपने लॉगिन क्रेडेंशियल को जल्दी से ऑटोमैटिक भरें + + + आपका तिजोरी भी राइट-क्लिक मेनू मे सुलभ और आसानी से उपलब्ध है + + + स्वचालित रूप से मजबूत, यादृच्छिक, सुरक्षित पासवर्ड उत्पन्न करते हैं + + + AES-256 बिट एन्क्रिप्शन का उपयोग करके आपकी जानकारी सुरक्षित रूप से प्रबंधित की जाती है + + diff --git a/apps/browser/store/locales/hr/copy.resx b/apps/browser/store/locales/hr/copy.resx new file mode 100644 index 0000000000..5ff2bcbe01 --- /dev/null +++ b/apps/browser/store/locales/hr/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - besplatni upravitelj lozinki + + + Siguran i besplatan upravitelj lozinki za sve vaše uređaje + + + Bitwarden, Inc. je vlasnik tvrtke 8bit Solutions LLC. + +THE VERGE, U.S. NEWS & WORLD REPORT, CNET I DRUGI ODABRALI SU BITWARDEN NAJBOLJIM UPRAVITELJEM LOZINKI. + +Upravljajte, spremajte, osigurajte i dijelite neograničen broj lozinki na neograničenom broju uređaja bilo gdje. Bitwarden omogućuje upravljanje lozinkama, bazirano na otvorenom kodu, svima, bilo kod kuće, na poslu ili u pokretu. + +Generirajte jake, jedinstvene i nasumične lozinke bazirane na sigurnosnim zahtjevima za svaku web stranicu koju često posjećujete. + +Bitwarden Send omoguzćuje jednostavno i brzo slanje šifriranih podataka --- datoteki ili teksta -- direktno, bilo kome. + +Bitwarden nudi Teams i Enterprise planove za tvrtke kako biste sigurno mogli dijeliti lozinke s kolegama na poslu. + +Zašto odabrati Bitwarden? + +Svjetski priznata enkripcija +Lozinke su zaštićene naprednim end-to-end šifriranjem (AES-256 bit, salted hashtag i PBKDF2 SHA-256) kako bi vaši osobni podaci ostali sigurni i samo vaši. + +Ugrađen generator lozinki +Generirajte jake, jedinstvene i nasumične lozinke bazirane na sigurnosnim zahtjevima za svako web mjesto koje često posjećujete. + +Svjetski dostupan +Bitwarden je, zahvaljujući našoj globalnoj zajednici, dostupan na više od 40 jezika. + +Podržani svi OS +Osigurajte i sigurno dijelite osjetljive podatke sadržane u vašem Bitwarden trezoru iz bilo kojeg preglednika, mobilnog uređaja ili stolnog računala s bilo kojim OS. + + + Siguran i besplatan upravitelj lozinki za sve tvoje uređaje + + + Sinkroniziraj i pristupi svojem trezoru s više uređaja + + + Upravljaj svojim korisničkim imenima i lozinkama iz sigurnog trezora + + + Brza auto-ispuna vjerodajnica za prijavu na bilo kojoj web stranici + + + Tvoj trezor je lako dostupan iz izbornika desnim klikom + + + Automatski generiraj jake, nasumične i sigurne lozinke + + + Tvojim se podacima sigurno upravlja AES-256 bitnim šifriranjem + + diff --git a/apps/browser/store/locales/hu/copy.resx b/apps/browser/store/locales/hu/copy.resx new file mode 100644 index 0000000000..0b3761a8ad --- /dev/null +++ b/apps/browser/store/locales/hu/copy.resx @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Ingyenes jelszókezelő + + + Egy biztonságos és ingyenes jelszókezelő az összes eszközre. + + + A Bitwarden, Inc. a 8bit Solutions LLC anyavállalata. + +A VERGE, A US NEWS & WORLD REPORT, a CNET ÉS MÁSOK LEGJOBB JELSZÓKEZELŐJE. + +Korlátlan számú jelszavak kezelése, tárolása, védelme és megosztása korlátlan eszközökön bárhonnan. A Bitwarden nyílt forráskódú jelszókezelési megoldásokat kínál mindenkinek, legyen az otthon, a munkahelyen vagy útközben. + +Hozzunk létre erős, egyedi és véletlenszerű jelszavakat a biztonsági követelmények alapján minden webhelyre, amelyet gyakran látogatunk. + +A Bitwarden Send gyorsan továbbítja a titkosított információkat-fájlokat és egyszerű szöveget közvetlenül bárkinek. + +A Bitwarden csapatokat és vállalati terveket kínál a vállalatok számára, így biztonságosan megoszthatja jelszavait kollégáival. + +Miért válasszuk a Bitwardent: + +Világszínvonalú titkosítási jelszavak fejlett végpontok közötti titkosítással (AES-256 bit, titkosított hashtag és PBKDF2 SHA-256) védettek, így az adatok biztonságban és titokban maradnak. + +Beépített jelszógenerátor A biztonsági követelmények alapján erős, egyedi és véletlenszerű jelszavakat hozhat létre minden gyakran látogatott webhelyen. + +Globális fordítások + +A Bitwarden fordítások 40 nyelven léteznek és globális közösségünknek köszönhetően egyre bővülnek. Többplatformos alkalmazások Biztonságos és megoszthatja az érzékeny adatokat a Bitwarden Széfben bármely böngészőből, mobileszközről vagy asztali operációs rendszerből stb. + + + Egy biztonságos és ingyenes jelszókezelő az összes eszközre + + + A széf szinkronizálása és elérése több eszközön. + + + Az összes bejelentkezés és jelszó kezelése egy biztonságos széfben. + + + A hitelesítő adatok gyors és automatikus kitöltése bármelyik felkeresett webhelyen. + + + A széf kényelmesen elérhető a jobb egérkattintásos menüből. + + + Erős, véletlenszerű és biztonságos jelszavak generálása automatikusan. + + + Az információ biztonsággal kezelhető az AES-256 bit titkosítása. + + diff --git a/apps/browser/store/locales/id/copy.resx b/apps/browser/store/locales/id/copy.resx new file mode 100644 index 0000000000..bf601db1dc --- /dev/null +++ b/apps/browser/store/locales/id/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Pengelola Sandi Gratis + + + Pengelola sandi yang aman dan gratis untuk semua perangkat Anda + + + Bitwarden adalah cara termudah dan teraman untuk menyimpan semua info masuk dan sandi Anda sambil tetap menjaga mereka disinkronkan di antara semua perangkat Anda. + +Pencurian sandi adalah masalah serius. Situs web dan aplikasi yang Anda gunakan diserang setiap hari. Pelanggaran keamanan terjadi dan sandi Anda dicuri. Ketika Anda menggunakan sandi yang sama di aplikasi dan situs web peretas dapat dengan mudah mengakses email, bank, dan akun penting Anda yang lain. + +Pakar keamanan merekomendasikan agar Anda menggunakan sandi yang berbeda dan dibuat secara acak untuk setiap akun yang Anda buat. Tapi bagaimana mengelola semua sandi tersebut? Bitwarden membuatnya menjadi mudah untuk Anda membuat, menyimpan dan mengakses sandi Anda. + +Bitwarden menyimpan semua info masuk Anda di brankas terenkripsi yang disinkronkan di semua perangkat Anda. Karena sepenuhnya dienkripsi sebelum meninggalkan perangkat Anda, hanya Anda yang memiliki akses ke data Anda. Bahkan tim di Bitwarden tidak dapat membaca data Anda, bahkan jika kami mau. Data Anda disegel dengan ekripsi AES-256 bit, hash yang di-salt, dan PBKDF2 SHA-256. + +Bitwarden adalah 100% perangkat lunak sumber terbuka. Kode sumber untuk Bitwarden berada di GitHub dan setiap orang bebas untuk meninjau, mengaudit, dan berkontribusi ke basis kode Bitwarden. + + + Pengelola sandi yang aman dan gratis untuk semua perangkat Anda + + + Sinkronkan dan akses brankas Anda dari beberapa perangkat + + + Kelola semua info masuk dan sandi Anda dari brankas yang aman + + + Mengisi info masuk dengan cepat dan otomatis ke situs web yang Anda kunjungi + + + Brankas Anda juga mudah diakses dari menu klik kanan + + + Secara otomatis menghasilkan sandi yang kuat, acak dan aman + + + Informasi Anda dikelola dengan aman menggunakan enkripsi AES-256 bit + + diff --git a/apps/browser/store/locales/it/copy.resx b/apps/browser/store/locales/it/copy.resx new file mode 100644 index 0000000000..477fd25b55 --- /dev/null +++ b/apps/browser/store/locales/it/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Gestore di password gratuito + + + Un gestore di password sicuro e gratuito per tutti i tuoi dispositivi + + + Bitwarden, Inc. è la società madre di 8bit Solutions LLC. + +NOMINATO MIGLIOR PASSWORD MANAGER DA THE VERGE, US NEWS & WORLD REPORT, CNET E ALTRO. + +Gestisci, archivia, proteggi e condividi password illimitate su dispositivi illimitati da qualsiasi luogo. Bitwarden offre soluzioni di gestione delle password open source a tutti, a casa, al lavoro o in viaggio. + +Genera password complesse, uniche e casuali in base ai requisiti di sicurezza per ogni sito web che frequenti. + +Bitwarden Send trasmette rapidamente informazioni cifrate --- file e testo in chiaro - direttamente a chiunque. + +Bitwarden offre piani Teams ed Enterprise per le aziende in modo da poter condividere le password in modo sicuro con i colleghi. + +Perché scegliere Bitwarden: + +Crittografia di livello mondiale +Le password sono protette con cifratura end-to-end avanzata (AES-256 bit, hashtag con sale e PBKDF2 SHA-256) in modo che i tuoi dati rimangano al sicuro e privati. + +Generatore di password integrato +Genera password complesse, uniche e casuali in base ai requisiti di sicurezza per ogni sito web che frequenti. + +Traduzioni globali +Le traduzioni di Bitwarden esistono in 40 lingue e sono in crescita, grazie alla nostra comunità globale. + +Applicazioni multipiattaforma +Proteggi e condividi i dati sensibili all'interno del tuo Bitwarden Vault da qualsiasi browser, dispositivo mobile o sistema operativo desktop e altro ancora. + + + Un gestore di password sicuro e gratuito per tutti i tuoi dispositivi + + + Sincronizza e accedi alla tua cassaforte da più dispositivi + + + Gestisci tutte le tue password ed i tuoi login da una cassaforte sicura + + + Completa velocemente tutte le tue credenziali di accesso in qualunque sito tu visiti + + + La tua cassaforte è facilmente accessibile dal menu contestuale del tasto destro del mouse + + + Genera automaticamente password complesse, casuali e sicure + + + Le tue informazioni sono salvate in modo sicuro grazie all'algoritmo di cifratura AES-256 + + diff --git a/apps/browser/store/locales/ja/copy.resx b/apps/browser/store/locales/ja/copy.resx new file mode 100644 index 0000000000..660708153d --- /dev/null +++ b/apps/browser/store/locales/ja/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - 無料パスワードマネージャー + + + あらゆる端末で使える、安全な無料パスワードマネージャー + + + Bitwarden は、あらゆる端末間で同期しつつログイン情報やパスワードを保管しておける、最も簡単で安全なサービスです。 + +パスワードの盗難は深刻な問題になっています。ウェブサイトやアプリは毎日攻撃を受けており、もしセキュリティに問題があればパスワードが盗難されてしまいます。 同じパスワードを他のアプリでも再利用していると、攻撃者はメールや銀行口座など大切なアカウントに簡単に侵入できてしまいます。 + +セキュリティの専門家は、アカウント毎に別のランダムに生成したパスワードを使うことを推奨していますが、ランダムなパスワードをすべて覚えていられますか? Bitwarden を使えば、わざわざパスワードを覚えなくても簡単にパスワードの生成、保管や利用ができます。 + +Bitwarden は端末間で同期できる、暗号化された保管庫にログイン情報を保管します。端末から送信される前に暗号化されるので、あなただけがそのデータにアクセスできるのです。Bitwarden の開発者チームですら、あなたに頼まれたとしてもデータを読み取ることはできません。データは AES-256 bit 暗号化、ソルト化ハッシュ、PBKDF2 SHA-256 で保護されます。 + +Bitwarden は100%オープンソースソフトウェアです。Bitwarden のソースコードは GitHub にホストされており、誰でもBitwardenのコードを自由にレビュー、監査、貢献できます。 + + + あらゆる端末で使える、安全な無料パスワードマネージャー + + + 複数の端末で保管庫に同期&アクセス + + + 安全な保管庫でログイン情報やパスワードを管理します + + + 開いたウェブサイトのログイン情報を素早く自動入力します + + + 右クリックメニューから保管庫に簡単にアクセス + + + 強固な、ランダムで安全なパスワードを自動生成 + + + AES-256bit 暗号化を使用して安全に情報が管理されます + + diff --git a/apps/browser/store/locales/ka/copy.resx b/apps/browser/store/locales/ka/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/ka/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/km/copy.resx b/apps/browser/store/locales/km/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/km/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/kn/copy.resx b/apps/browser/store/locales/kn/copy.resx new file mode 100644 index 0000000000..6928f557e4 --- /dev/null +++ b/apps/browser/store/locales/kn/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ಬಿಟ್ವರ್ಡ್ – ಉಚಿತ ಪಾಸ್ವರ್ಡ್ ನಿರ್ವಾಹಕ + + + ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಿಗೆ ಸುರಕ್ಷಿತ ಮತ್ತು ಉಚಿತ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕ + + + ಬಿಟ್ವಾರ್ಡೆನ್, ಇಂಕ್. 8 ಬಿಟ್ ಸೊಲ್ಯೂಷನ್ಸ್ ಎಲ್ಎಲ್ ಸಿ ಯ ಮೂಲ ಕಂಪನಿಯಾಗಿದೆ. + +ವರ್ಜ್, ಯು.ಎಸ್. ನ್ಯೂಸ್ & ವರ್ಲ್ಡ್ ರಿಪೋರ್ಟ್, ಸಿನೆಟ್ ಮತ್ತು ಹೆಚ್ಚಿನದರಿಂದ ಉತ್ತಮ ಪಾಸ್‌ವರ್ಡ್ ವ್ಯವಸ್ಥಾಪಕ ಎಂದು ಹೆಸರಿಸಲಾಗಿದೆ. + +ಎಲ್ಲಿಂದಲಾದರೂ ಅನಿಯಮಿತ ಸಾಧನಗಳಲ್ಲಿ ಅನಿಯಮಿತ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ನಿರ್ವಹಿಸಿ, ಸಂಗ್ರಹಿಸಿ, ಸುರಕ್ಷಿತಗೊಳಿಸಿ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳಿ. ಮನೆಯಲ್ಲಿ, ಕೆಲಸದಲ್ಲಿ ಅಥವಾ ಪ್ರಯಾಣದಲ್ಲಿರಲಿ ಪ್ರತಿಯೊಬ್ಬರಿಗೂ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಓಪನ್ ಸೋರ್ಸ್ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಹಣಾ ಪರಿಹಾರಗಳನ್ನು ನೀಡುತ್ತದೆ. + +ನೀವು ಆಗಾಗ್ಗೆ ಪ್ರತಿ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಸುರಕ್ಷತಾ ಅವಶ್ಯಕತೆಗಳನ್ನು ಆಧರಿಸಿ ಬಲವಾದ, ಅನನ್ಯ ಮತ್ತು ಯಾದೃಚ್ pass ಿಕ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ರಚಿಸಿ. + +ಬಿಟ್‌ವಾರ್ಡೆನ್ ಕಳುಹಿಸಿ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಮಾಹಿತಿಯನ್ನು ತ್ವರಿತವಾಗಿ ರವಾನಿಸುತ್ತದೆ --- ಫೈಲ್‌ಗಳು ಮತ್ತು ಸರಳ ಪಠ್ಯ - ನೇರವಾಗಿ ಯಾರಿಗಾದರೂ. + +ಬಿಟ್‌ವಾರ್ಡೆನ್ ಕಂಪೆನಿಗಳಿಗೆ ತಂಡಗಳು ಮತ್ತು ಎಂಟರ್‌ಪ್ರೈಸ್ ಯೋಜನೆಗಳನ್ನು ನೀಡುತ್ತದೆ ಆದ್ದರಿಂದ ನೀವು ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಸಹೋದ್ಯೋಗಿಗಳೊಂದಿಗೆ ಸುರಕ್ಷಿತವಾಗಿ ಹಂಚಿಕೊಳ್ಳಬಹುದು. + +ಬಿಟ್‌ವಾರ್ಡೆನ್ ಅನ್ನು ಏಕೆ ಆರಿಸಬೇಕು: + +ವಿಶ್ವ ದರ್ಜೆಯ ಗೂ ry ಲಿಪೀಕರಣ +ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಸುಧಾರಿತ ಎಂಡ್-ಟು-ಎಂಡ್ ಎನ್‌ಕ್ರಿಪ್ಶನ್ (ಎಇಎಸ್ -256 ಬಿಟ್, ಉಪ್ಪುಸಹಿತ ಹ್ಯಾಶ್‌ಟ್ಯಾಗ್ ಮತ್ತು ಪಿಬಿಕೆಡಿಎಫ್ 2 ಎಸ್‌ಎಚ್‌ಎ -256) ನೊಂದಿಗೆ ರಕ್ಷಿಸಲಾಗಿದೆ ಆದ್ದರಿಂದ ನಿಮ್ಮ ಡೇಟಾ ಸುರಕ್ಷಿತ ಮತ್ತು ಖಾಸಗಿಯಾಗಿರುತ್ತದೆ. + +ಅಂತರ್ನಿರ್ಮಿತ ಪಾಸ್ವರ್ಡ್ ಜನರೇಟರ್ +ನೀವು ಆಗಾಗ್ಗೆ ಪ್ರತಿ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಸುರಕ್ಷತಾ ಅವಶ್ಯಕತೆಗಳನ್ನು ಆಧರಿಸಿ ಬಲವಾದ, ಅನನ್ಯ ಮತ್ತು ಯಾದೃಚ್ pass ಿಕ ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ರಚಿಸಿ. + +ಜಾಗತಿಕ ಅನುವಾದಗಳು +ಬಿಟ್ವಾರ್ಡೆನ್ ಅನುವಾದಗಳು 40 ಭಾಷೆಗಳಲ್ಲಿ ಅಸ್ತಿತ್ವದಲ್ಲಿವೆ ಮತ್ತು ಬೆಳೆಯುತ್ತಿವೆ, ನಮ್ಮ ಜಾಗತಿಕ ಸಮುದಾಯಕ್ಕೆ ಧನ್ಯವಾದಗಳು. + +ಕ್ರಾಸ್ ಪ್ಲಾಟ್‌ಫಾರ್ಮ್ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು +ಯಾವುದೇ ಬ್ರೌಸರ್, ಮೊಬೈಲ್ ಸಾಧನ, ಅಥವಾ ಡೆಸ್ಕ್‌ಟಾಪ್ ಓಎಸ್ ಮತ್ತು ಹೆಚ್ಚಿನವುಗಳಿಂದ ನಿಮ್ಮ ಬಿಟ್‌ವಾರ್ಡನ್ ವಾಲ್ಟ್‌ನಲ್ಲಿ ಸೂಕ್ಷ್ಮ ಡೇಟಾವನ್ನು ಸುರಕ್ಷಿತಗೊಳಿಸಿ ಮತ್ತು ಹಂಚಿಕೊಳ್ಳಿ. + + + ನಿಮ್ಮ ಎಲ್ಲಾ ಸಾಧನಗಳಿಗೆ ಸುರಕ್ಷಿತ ಮತ್ತು ಉಚಿತ ಪಾಸ್‌ವರ್ಡ್ ನಿರ್ವಾಹಕ + + + ಅನೇಕ ಸಾಧನಗಳಿಂದ ನಿಮ್ಮ ವಾಲ್ಟ್ ಅನ್ನು ಸಿಂಕ್ ಮಾಡಿ ಮತ್ತು ಪ್ರವೇಶಿಸಿ + + + ನಿಮ್ಮ ಎಲ್ಲಾ ಲಾಗಿನ್‌ಗಳು ಮತ್ತು ಪಾಸ್‌ವರ್ಡ್‌ಗಳನ್ನು ಸುರಕ್ಷಿತ ವಾಲ್ಟ್‌ನಿಂದ ನಿರ್ವಹಿಸಿ + + + ನೀವು ಭೇಟಿ ನೀಡುವ ಯಾವುದೇ ವೆಬ್ಸೈಟ್ಗೆ ನಿಮ್ಮ ಲಾಗಿನ್ ರುಜುವಾತುಗಳನ್ನು ತ್ವರಿತವಾಗಿ ಸ್ವಯಂ ತುಂಬಿಸಿ + + + ನಿಮ್ಮ ಚಾವಣಿ ಬಲ-ಕ್ಲಿಕ್ ಮೆನುವಿನಿಂದ ಅನುಕೂಲಕರವಾಗಿ ಪ್ರವೇಶಿಸಬಹುದು + + + ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಪ್ರಬಲ ಯಾದೃಚ್ಛಿಕ, ಮತ್ತು ಸುರಕ್ಷಿತ ಪಾಸ್ವರ್ಡ್ಗಳನ್ನು ರಚಿಸಲು + + + ನಿಮ್ಮ ಮಾಹಿತಿಯನ್ನು AES-256 ಬಿಟ್ ಗೂಢಲಿಪೀಕರಣವನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ನಿರ್ವಹಿಸಲಾಗುತ್ತದೆ + + diff --git a/apps/browser/store/locales/ko/copy.resx b/apps/browser/store/locales/ko/copy.resx new file mode 100644 index 0000000000..c726ad687d --- /dev/null +++ b/apps/browser/store/locales/ko/copy.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - 무료 비밀번호 관리자 + + + 당신의 모든 기기에서 사용할 수 있는, 안전한 무료 비밀번호 관리자 + + + Bitwarden은 당신의 로그인과 비밀번호를 보관하고 여러 기기에서 동기화할 수 있는 가장 쉽고 안전한 방법입니다. + +계정 도용은 매우 위험한 문제입니다. 당신이 사용하는 앱 및 웹 사이트는 거의 매일 공격을 당하고 있습니다. 보안 결함이 생겨 비밀번호를 탈취당하고, 그 비밀번호를 앱 및 웹 사이트에 다시 사용하게 되면 해커들은 이메일, 은행 계좌 등 사용자의 중요한 계정에 쉽게 접근할 수 있게 됩니다. + +Bitwarden은 사용자의 모든 로그인을 여러 기기에서 동기화할 수 있는 암호화된 보관함에 저장합니다. 보관함은 완벽히 암호화되어 있으므로 오직 사용자 본인만이 데이터에 접근할 수 있습니다. Bitwarden 팀 멤버조차 아무리 읽고자 한다 해도 사용자의 데이터를 읽을 수 없습니다. 사용자의 데이터는 AES-256비트, 솔트 해싱 및 PBKDF2 SHA-256 방식으로 암호화됩니다. + +Bitwarden은 100% 오픈 소스 소프트웨어입니다. Bitwarden의 소스 코드는 GitHub에 공개되어 있어 모든 사람들이 Bitwarden의 코드를 검토하고 기여할 수 있습니다. + + + 당신의 모든 기기에서 사용할 수 있는, 안전한 무료 비밀번호 관리자 + + + 여러 기기에서 보관함에 접근하고 동기화할 수 있습니다. + + + 안전한 보관함에서 모든 로그인과 비밀번호를 관리하세요. + + + 방문하는 모든 웹 사이트에 자동 완성 기능을 통해 빠르게 로그인할 수 있습니다. + + + 오른쪽 클릭 메뉴를 통해 보관함에 간편하게 접근할 수 있습니다. + + + 강하고 안전한 무작위 비밀번호 자동 생성 기능을 제공합니다. + + + 사용자의 정보는 AES-256 비트 암호화를 통하여 안전하게 관리됩니다. + + diff --git a/apps/browser/store/locales/lt/copy.resx b/apps/browser/store/locales/lt/copy.resx new file mode 100644 index 0000000000..d7929c0b51 --- /dev/null +++ b/apps/browser/store/locales/lt/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – nemokamas slaptažodžių tvarkyklė + + + Saugi ir nemokama slaptažodžių tvarkyklė visiems įrenginiams + + + „Bitwarden“ yra paprasčiausias ir saugiausias būdas išsaugoti visus prisijungimus ir slaptažodžius, tuo pačiu patogu juos pasiekti iš visų jūsų įrenginių. + +Slaptažodžių vagystė yra rimta problema. Jūsų naudojamos svetainės ir programos yra atakuojamos kiekvieną dieną. Įvykus saugumo pažeidimų jūsų slaptažodžiai yra pavogiami. Kai pakartotinai naudojate tuos pačius slaptažodžius programose ir svetainėse, įsilaužėliai gali lengvai pasiekti jūsų el. pašto, banko ir kitas svarbias paskiras. + +Saugumo ekspertai rekomenduoja kiekvienai jūsų sukurtai paskyrai naudoti kitą, atsitiktinai sugeneruotą slaptažodį. Bet kaip valdyti visus tuos slaptažodžius? „Bitwarden“ leidžia jums lengvai kurti, saugoti ir pasiekti slaptažodžius. + +„Bitwarden“ visus jūsų prisijungimus saugo šifruotoje saugykloje, kuri pasiekiama visuose jūsų įrenginiuose. Kadangi duomenys visiškai užšifruoti dar neišėjus iš jūsų įrenginio, prieigą prie savo duomenų turite tik jūs. Net „Bitwarden“ komanda negali perskaityti jūsų duomenų, net jei mes to ir norėtume. Jūsų duomenys užklijuojami naudojant AES-256 bitų šifravimą, druskinta maišos funkcija ir PBKDF2 SHA-256. + +„Bitwarden“ yra 100% atvirojo kodo programinė įranga. „Bitwarden“ kodas yra „GitHub“ ir visi gali peržiūrėti, tikrinti ir prisidėti prie „Bitwarden“ kodo bazės. + + + Saugi ir nemokama slaptažodžių tvarkyklė visiems įrenginiams + + + Pasiekite savo saugyklą iš kelių įrenginių + + + Tvarkykite visus prisijungimus ir slaptažodžius iš saugios saugyklos + + + Greitai automatiškai užpildykite prisijungimo duomenis bet kurioje jūsų lankomoje svetainėje + + + Jūsų saugyklą taip pat galima patogiai pasiekti spustelėjus dešiniuoju pelės mygtuku + + + Automatiškai sugeneruokite stiprius, atsitiktinius ir saugius slaptažodžius + + + Jūsų informacija yra saugiai tvarkoma naudojant AES-256 bitų šifravimą + + diff --git a/apps/browser/store/locales/lv/copy.resx b/apps/browser/store/locales/lv/copy.resx new file mode 100644 index 0000000000..252b6f0344 --- /dev/null +++ b/apps/browser/store/locales/lv/copy.resx @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – bezmaksas paroļu pārvaldnieks + + + Drošs bezmaksas paroļu pārvaldnieks visām Tavām ierīcēm + + + Bitwarden ir vieglākais un drošākais veids, kā glabāt visus pierakstīšanās vienumus un paroles, vienlaicīgi ērti uzturot tās sinhronizētas visās ierīcēs. + +Paroļu zagšana ir nopietna nebūšana. Tīmekļa vietnēm un lietotnēm uzbrūk katru dienu. Datu drošības pārkāpumos tiek nozagtas paroles. Kad viena un tā pati parole tiek izmantota lietotnēs un tīmekļa vietnēs, urķi var viegli piekļūt e-pasta, banku un citiem būtiskiem kontiem. + +Drošības lietpratēji iesaka katram izveidotajam kontam izmantot dažādas, nejauši veidotas paroles. Kā tās visas pārvaldīt? Bitwarden atvieglo paroļu izveidošanu, glabāšanu un piekļūšanu tām. + +Bitwarden uzglabā visus pierakstīšanās vienumus šifrētā glabātavā, kas tiek sinhronizēta visās izmantotajās ierīcēs. Tā kā tā dati tiek pilnībā šifrēti, pirms tie tiek izsūtīti no izmantotās ierīces, piekļuve tiem ir tikai glabātavas īpašniekam. Pat Bitwarden izstrādātāji nevar lasīt datus, pat ja to gribētu. Informācija tiek aizsargāta ar AES-256 bitu šifrēšanu, "sālīto" jaukšanu un PBKDF2 SHA-256. + +Bitwarden ir pilnībā atvērtā pirmkoda programmatūra. Bitwarden atvērtais pirmkods ir izvietots GitHub, un ikkatram ir iespēja pārskatīt, pārbaudīt un sniegt ieguldījumu Bitwarden pirmkodā. + + + + Drošs bezmaksas paroļu pārvaldnieks visām Tavām ierīcēm + + + Sinhronizē un piekļūsti savai glabātavai no vairākām ierīcēm + + + Pārvaldi visus savus pierakstīšanās vienumus un paroles no drošas glabātavas + + + Ātra automātiskā aizpilde Taviem pierakstīšanās datiem jebkurā lapā, ko apmeklē + + + Tava glabātava ir arī ērti pieejama labā klikšķa izvēlnē + + + Automātiski veido spēcīgas, sarežģītas un drošas paroles + + + Tava informācija ir droši pārvaldīta, izmantojot AES-256 bitu šifrēšanu + + diff --git a/apps/browser/store/locales/ml/copy.resx b/apps/browser/store/locales/ml/copy.resx new file mode 100644 index 0000000000..78c3eea8dd --- /dev/null +++ b/apps/browser/store/locales/ml/copy.resx @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ബിറ്റ്വാർഡൻ - സൗജന്യമായി പാസ്‌വേഡ് മാനേജർ + + + നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങൾക്കും സുരക്ഷിതവും സൗജന്യവുമായ പാസ്‌വേഡ് മാനേജർ. + + + നിങ്ങളുടെ എല്ലാ ലോഗിനുകളും പാസ്‌വേഡുകളും സംഭരിക്കുന്നതിനുള്ള ഏറ്റവും എളുപ്പവും സുരക്ഷിതവുമായ മാർഗ്ഗമാണ് Bitwarden, ഒപ്പം നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങളും തമ്മിൽ സമന്വയിപ്പിക്കുകയും ചെയ്യുന്നു. + +പാസ്‌വേഡ് മോഷണം ഗുരുതരമായ പ്രശ്‌നമാണ്. നിങ്ങൾ ഉപയോഗിക്കുന്ന വെബ്‌സൈറ്റുകളും അപ്ലിക്കേഷനുകളും എല്ലാ ദിവസവും ആക്രമണത്തിലാണ്. സുരക്ഷാ ലംഘനങ്ങൾ സംഭവിക്കുകയും നിങ്ങളുടെ പാസ്‌വേഡുകൾ മോഷ്‌ടിക്കപ്പെടുകയും ചെയ്യുന്നു. അപ്ലിക്കേഷനുകളിലും വെബ്‌സൈറ്റുകളിലും ഉടനീളം സമാന പാസ്‌വേഡുകൾ നിങ്ങൾ വീണ്ടും ഉപയോഗിക്കുമ്പോൾ ഹാക്കർമാർക്ക് നിങ്ങളുടെ ഇമെയിൽ, ബാങ്ക്, മറ്റ് പ്രധാനപ്പെട്ട അക്കൗണ്ടുകൾ എന്നിവ എളുപ്പത്തിൽ ആക്‌സസ്സുചെയ്യാനാകും. + +നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങളിലും സമന്വയിപ്പിക്കുന്ന ഒരു എൻ‌ക്രിപ്റ്റ് ചെയ്ത വാൾട്ടിൽ Bitwarden നിങ്ങളുടെ എല്ലാ ലോഗിനുകളും സംഭരിക്കുന്നു. നിങ്ങളുടെ ഉപകരണം വിടുന്നതിനുമുമ്പ് ഇത് പൂർണ്ണമായും എൻ‌ക്രിപ്റ്റ് ചെയ്‌തിരിക്കുന്നതിനാൽ, നിങ്ങളുടെ ഡാറ്റ നിങ്ങൾക്ക് മാത്രമേ ആക്‌സസ് ചെയ്യാൻ കഴിയൂ . Bitwarden ടീമിന് പോലും നിങ്ങളുടെ ഡാറ്റ വായിക്കാൻ കഴിയില്ല. നിങ്ങളുടെ ഡാറ്റ AES-256 ബിറ്റ് എൻ‌ക്രിപ്ഷൻ, സാൾട്ടിങ് ഹാഷിംഗ്, PBKDF2 SHA-256 എന്നിവ ഉപയോഗിച്ച് അടച്ചിരിക്കുന്നു. + +100% ഓപ്പൺ സോഴ്‌സ് സോഫ്റ്റ്വെയറാണ് Bitwarden . Bitwarden സോഴ്‌സ് കോഡ് GitHub- ൽ ഹോസ്റ്റുചെയ്‌തിരിക്കുന്നു, മാത്രമല്ല എല്ലാവർക്കും ഇത് അവലോകനം ചെയ്യാനും ഓഡിറ്റുചെയ്യാനും ബിറ്റ് വാർഡൻ കോഡ്ബേസിലേക്ക് സംഭാവന ചെയ്യാനും സ്വാതന്ത്ര്യമുണ്ട്. + + + + + + + + നിങ്ങളുടെ എല്ലാ ഉപകരണങ്ങൾക്കും സുരക്ഷിതവും സൗജന്യവുമായ പാസ്‌വേഡ് മാനേജർ. + + + ഒന്നിലധികം ഉപകരണങ്ങളിൽ നിന്ന് നിങ്ങളുടെ വാൾട് സമന്വയിപ്പിച്ച് ആക്‌സസ്സുചെയ്യുക + + + + നിങ്ങളുടെ എല്ലാ ലോഗിനുകളും പാസ്‌വേഡുകളും സുരക്ഷിത വാൾട്ടിൽ നിന്ന് കൈകാര്യം ചെയ്യുക + + + നിങ്ങൾ സന്ദർശിക്കുന്ന ഏത് വെബ്‌സൈറ്റിലേക്കും നിങ്ങളുടെ ലോഗിൻ ക്രെഡൻഷ്യലുകൾ വേഗത്തിൽ യാന്ത്രികമായി പൂരിപ്പിക്കുക + + + വലത്-ക്ലിക്ക് മെനുവിൽ നിന്ന് നിങ്ങളുടെ നിലവറയും സ access കര്യപ്രദമായി ആക്സസ് ചെയ്യാൻ കഴിയും. + + + ശക്തവും ക്രമരഹിതവും സുരക്ഷിതവുമായ പാസ്‌വേഡുകൾ യാന്ത്രികമായി സൃഷ്‌ടിക്കുക + + + AES-256 ബിറ്റ് എൻ‌ക്രിപ്ഷൻ ഉപയോഗിച്ച് നിങ്ങളുടെ വിവരങ്ങൾ സുരക്ഷിതമായി കൈകാര്യം ചെയ്യുന്നു + + diff --git a/apps/browser/store/locales/nb/copy.resx b/apps/browser/store/locales/nb/copy.resx new file mode 100644 index 0000000000..67d9a80450 --- /dev/null +++ b/apps/browser/store/locales/nb/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden — Fri passordbehandling + + + En sikker og fri passordbehandler for alle dine PCer og mobiler + + + Bitwarden er den enkleste og tryggeste måten å lagre alle dine innlogginger og passord på, samtidig som de blir synkronisert mellom alle dine PCer og mobiler. + +Passordtyveri er et seriøst problem. Nettstedene og appene som du bruker er under angrep hver eneste dag. Sikkerhetsbrudd forekommer, og dine passord blir stjålet. Når du bruker de samme passordene over flere apper og nettsteder, kan hackere lett få tilgang til din e-post, bankkonto, og andre viktige kontoer. + +Sikkerhetseksperter anbefaler at du bruker forskjellig og tilfeldig genererte passord for hver eneste konto du lager. Men hvordan håndterer du alle de passordene? Bitwarden gjør det lett for deg å lage, lagre, og få tilgang til dine passord. + +Bitwarden lagrer alle dine innlogginger i et kryptert hvelv som synkroniseres mellom alle dine PCer og mobiler. Ettersom hvelvet er fullstendig kryptert før det noensinne forlater enheten din, har bare du tilgang til dine dataer. Selv ikke de som jobber hos Bitwarden kan lese dine dataer, om vi så ville det. Dine dataer er forseglet med AES 256-bitkryptering, saltet hashing, og PBKDF2 SHA-256. + +Bitwardens programvare har 100% åpen kildekode. Kildekoden til Bitwarden betjenes på GitHub, og alle har all rett til å undersøke, gjennomgå og bidra til Bitwarden sin kodebase. + + + En sikker og fri passordbehandler for alle dine PCer og mobiler + + + Synkroniser og få tilgang til ditt hvelv fra alle dine enheter + + + Administrer alle dine innlogginger og passord fra et sikkert hvelv + + + Auto-utfyll dine innloggingslegitimasjoner raskt på ethvert nettsted du besøker + + + Ditt hvelv er også praktisk tilgjengelig fra høyreklikkmenyen + + + Automatisk generer sterke, tilfeldige og sikre passord + + + Din informasjon blir trygt håndtert ved bruk av AES 256-bitkryptering + + diff --git a/apps/browser/store/locales/nl/copy.resx b/apps/browser/store/locales/nl/copy.resx new file mode 100644 index 0000000000..e0779ba777 --- /dev/null +++ b/apps/browser/store/locales/nl/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Gratis wachtwoordbeheer + + + Een veilige en gratis oplossing voor wachtwoordbeheer voor al je apparaten + + + Bitwarden, Inc. is het moederbedrijf van 8bit Solutions LLC. + +BESTE WACHTWOORDBEHEERDER VOLGENS THE VERGE, U.S. NEWS & WORLD REPORT, CNET EN ANDEREN. + +Beheer, bewaar, beveilig en deel een onbeperkt aantal wachtwoorden op een onbeperkt aantal apparaten, waar je ook bent. Bitwarden levert open source wachtwoordbeheeroplossingen voor iedereen, of dat nu thuis, op het werk of onderweg is. + +Genereer sterke, unieke en willekeurige wachtwoorden op basis van beveiligingsvereisten voor elke website die je bezoekt. + +Bitwarden Send verzendt snel versleutelde informatie --- bestanden en platte tekst -- rechtstreeks naar iedereen. + +Bitwarden biedt Teams- en Enterprise-abonnementen voor bedrijven, zodat je veilig wachtwoorden kunt delen met collega's. + +Waarom Bitwarden: + +Versleuteling van wereldklasse +Wachtwoorden worden beschermd met geavanceerde end-to-end-codering (AES-256 bit, salted hashtag en PBKDF2 SHA-256) zodat jouw gegevens veilig en privé blijven. + +Ingebouwde wachtwoordgenerator +Genereer sterke, unieke en willekeurige wachtwoorden op basis van beveiligingsvereisten voor elke website die je bezoekt. + +Wereldwijde vertalingen +Bitwarden-vertalingen bestaan ​​in 40 talen en groeien dankzij onze wereldwijde community. + +Platformoverschrijdende toepassingen +Beveilig en deel gevoelige gegevens binnen uw Bitwarden Vault vanuit elke browser, mobiel apparaat of desktop-besturingssysteem, en meer. + + + Een veilige en gratis oplossing voor wachtwoordbeheer voor al uw apparaten + + + Synchroniseer en gebruik je kluis op meerdere apparaten + + + Beheer al je logins en wachtwoorden vanuit een beveiligde kluis + + + Vul snel automatisch je logingegevens in op elke website die je bezoekt + + + Je kluis is ook handig te bereiken vanuit het contextmenu (rechts klikken) + + + Automatische generatie van sterke, willekeurige en veilige wachtwoorden + + + Jouw informatie wordt veilig beheerd met AES-256 bit versleuteling + + diff --git a/apps/browser/store/locales/nn/copy.resx b/apps/browser/store/locales/nn/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/nn/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/pl/copy.resx b/apps/browser/store/locales/pl/copy.resx new file mode 100644 index 0000000000..5b3941cb7e --- /dev/null +++ b/apps/browser/store/locales/pl/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - darmowy menedżer haseł + + + Bezpieczny i darmowy menedżer haseł dla wszystkich Twoich urządzeń + + + Bitwarden, Inc. jest macierzystą firmą 8bit Solutions LLC. + +NAZWANY NAJLEPSZYM MENEDŻEREM HASEŁ PRZEZ THE VERGE, US NEWS & WORLD REPORT, CNET I WIĘCEJ. + +Zarządzaj, przechowuj, zabezpieczaj i udostępniaj nieograniczoną liczbę haseł na nieograniczonej liczbie urządzeń z każdego miejsca. Bitwarden dostarcza rozwiązania do zarządzania hasłami z otwartym kodem źródłowym każdemu, niezależnie od tego, czy jest w domu, w pracy, czy w podróży. + +Generuj silne, unikalne i losowe hasła w oparciu o wymagania bezpieczeństwa dla każdej odwiedzanej strony. + +Funkcja Bitwarden Send szybko przesyła zaszyfrowane informacje --- pliki i zwykły tekst -- bezpośrednio do każdego. + +Bitwarden oferuje plany dla zespołów i firm, dzięki czemu możesz bezpiecznie udostępniać hasła współpracownikom. + +Dlaczego warto wybrać Bitwarden: + +Szyfrowanie światowej klasy +Hasła są chronione za pomocą zaawansowanego szyfrowania typu end-to-end (AES-256 bitów, dodatkowy ciąg zaburzający i PBKDF2 SHA-256), dzięki czemu Twoje dane pozostają bezpieczne i prywatne. + +Wbudowany generator haseł +Generuj silne, unikalne i losowe hasła w oparciu o wymagania bezpieczeństwa dla każdej odwiedzanej strony. + +Przetłumaczone aplikacje +Tłumaczenia Bitwarden są dostępne w 40 językach i rosną dzięki naszej globalnej społeczności. + +Aplikacje wieloplatformowe +Zabezpiecz i udostępniaj poufne dane w swoim sejfie Bitwarden z dowolnej przeglądarki, urządzenia mobilnego, systemu operacyjnego i nie tylko. + + + Bezpieczny i darmowy menedżer haseł dla wszystkich Twoich urządzeń + + + Synchronizacja i dostęp do sejfu z różnych urządzeń + + + Przechowuj wszystkie dane logowania i hasła w bezpiecznym sejfie + + + Szybko, automatycznie uzupełnij dane logowania na każdej odwiedzanej stronie + + + Twój sejf jest także łatwo dostępny z menu kontekstowego + + + Automatycznie wygeneruj silne, losowe i bezpieczne hasło + + + Twoje dane są zabezpieczone z wykorzystaniem szyfrowania AES-256-bit + + diff --git a/apps/browser/store/locales/pt_BR/copy.resx b/apps/browser/store/locales/pt_BR/copy.resx new file mode 100644 index 0000000000..536ad080ec --- /dev/null +++ b/apps/browser/store/locales/pt_BR/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Gerenciador de Senhas Gratuito + + + Um gerenciador de senhas gratuito e seguro para todos os seus dispositivos + + + O Bitwarden é a maneira mais fácil e segura de armazenar todos os seus usuários e senhas mantendo-os convenientemente sincronizados entre todos os seus dispositivos. + +O furto de senhas é um problema sério. Os sites e aplicativos que os utiliza estão sob ataque todos os dias. Brechas de segurança ocorrem e as suas senhas são furtadas. Quando você reutiliza as mesmas senhas entre aplicativos e sites, os hackers podem facilmente acessar o seu e-mail, banco, e outras contas importantes. + +Os especialistas de segurança recomendam que utilize uma senha diferente e aleatoriamente gerada para todas as contas que você cria. Mas como gerenciar todas essas senhas? O Bitwarden torna-lhe fácil criar, armazenar, e acessar as suas senhas. + +O Bitwarden armazena todas as suas credenciais num cofre encriptado que sincroniza entre todos os seus dispositivos. Como são completamente encriptados antes de se quer sair do seu dispositivo, apenas você tem acesso aos seus dados. Nem se quer a equipe do Bitwarden pode ler os seus dados, mesmo se quiséssemos. Os seus dados são selados com encriptação AES-256 bits, salted hashing, e PBKDF2 SHA-256. + +Bitwarden é um software 100% de código aberto. O código-fonte do Bitwarden está hospedado no GitHub e todos são livres para revisar, auditar e contribuir com a base de códigos do Bitwarden. + + + Um gerenciador de senhas gratuito e seguro para todos os seus dispositivos + + + Sincronize e acesse o seu cofre através de múltiplos dispositivos + + + Gerencie todas as suas credenciais a partir de um cofre seguro + + + Autopreencha rapidamente as suas credenciais dentro de qualquer site que visitar + + + O seu cofre é também acessível a partir do menu de contexto pelo clique no botão direito do mouse + + + Gera automaticamente senhas fortes, aleatórias e seguras + + + A sua informação é gerenciada com segurança utilizando encriptação AES-256 bits + + diff --git a/apps/browser/store/locales/pt_PT/copy.resx b/apps/browser/store/locales/pt_PT/copy.resx new file mode 100644 index 0000000000..9f0230000c --- /dev/null +++ b/apps/browser/store/locales/pt_PT/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Gestor de palavras-passe gratuito + + + Um gestor de palavras-passe seguro e gratuito para todos os seus dispositivos + + + O Bitwarden é a maneira mais fácil e segura de armazenar todas as suas credenciais e palavras-passe mantendo-as convenientemente sincronizadas entre todos os seus dispositivos. + +O furto de palavras-passe é um problema sério. Os websites e aplicações que utiliza estão sob ataque todos os dias. Quebras de segurança ocorrem e as suas palavras-passe são furtadas. Quando reutiliza as mesmas palavras-passe entre aplicações e websites, os hackers podem facilmente aceder ao seu email, banco, e outras contas importantes. + +Os especialistas de segurança recomendam que utilize uma palavra-passe diferente e aleatoriamente gerada para todas as contas que cria. Mas como é que gere todas essas palavras-passe? O Bitwarden torna-lhe fácil criar, armazenar, e aceder às suas palavras-passe. + +O Bitwarden armazena todas as suas credenciais num cofre encriptado que sincroniza entre todos os seus dispositivos. Como são completamente encriptados antes de se quer sair do seu dispositivo, apenas você tem acesso aos seus dados. Nem se quer a equipa do Bitwarden pode ler os seus dados, mesmo se quiséssemos. Os seus dados são selados com encriptação AES-256 bits, salted hashing, e PBKDF2 SHA-256. + +O Bitwarden é 100% software de código aberto. O código fonte para o Bitwarden está hospedado no GitHub e todos podem revisar, auditar, e contribuir para a base de código do Bitwarden. + + + Um gestor de palavras-passe seguro e gratuito para todos os seus dispositivos + + + Sincronize e acesse o seu cofre através de múltiplos dispositivos + + + Gira todas as suas credenciais e palavras-passe a partir de um cofre seguro + + + Rapidamente auto-preencha as suas credenciais dentro de qualquer website que visitar + + + O seu cofre é também convenientemente acessível a partir do menu de contexto de clique de lado direito do rato + + + Gira automaticamente palvras-passe fortes, aleatórias e seguras + + + A sua informação é gerida com segurança utilizando encriptação AES-256 bits + + diff --git a/apps/browser/store/locales/ro/copy.resx b/apps/browser/store/locales/ro/copy.resx new file mode 100644 index 0000000000..d8beda8c80 --- /dev/null +++ b/apps/browser/store/locales/ro/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Manager de parole gratuit + + + Un manager de parole sigur și gratuit pentru toate dispozitivele dvs. + + + Bitwarden, Inc. este compania mamă a 8bit Solutions LLC. + +NUMIT CEL MAI BUN MANAGER DE PAROLE DE CĂTRE THE VERGE, U.S. NEWS & WORLD REPORT, CNET, ȘI MULȚI ALȚII. + +Gestionează, stochează, securizează și partajează parole nelimitate, pe dispozitive nelimitate, de oriunde. Bitwarden oferă soluții de gestionare a parolelor open source pentru toată lumea, fie acasă, la serviciu sau în deplasare. + +Generează parole puternice, unice și aleatorii pe baza cerințelor de securitate a fiecărui site web pe care îl frecventați. + +Bitwarden Send transmite rapid informații criptate --- fișiere și text simplu -- direct către oricine. + +Bitwarden oferă planurile Echipe și Organizație pentru companii, astfel încât să puteți partaja în siguranță parolele cu colegii. + +De ce să alegeți Bitwarden: + +Criptare de clasă mondială +Parolele sunt protejate cu criptare avansată completă (AES-256 bit, hashtag experimentat și PBKDF2 SHA-256), astfel încât datele dvs. să rămână sigure și private. + +Generator de parole încorporat +Generează parole puternice, unice și aleatorii pe baza cerințelor de securitate a fiecărui site web pe care îl frecventați. + +Traducere în mai multe limbi +Bitwarden este deja tradus în 40 de limbi și numărul lor crește, datorită comunității noastre mondiale. + +Aplicații multi-platformă +Asigură și partajează date sensibile din seiful Bitwarden de pe orice browser, dispozitiv mobil sau sistem de operare desktop și multe altele. + + + Un manager de parole sigur și gratuit, pentru toate dispozitivele dvs. + + + Sincronizează și accesează seiful dvs. de pe multiple dispozitive + + + Gestionează toate datele de autentificare și parolele dintr-un seif securizat + + + Completează automat și rapid datele dvs. de autentificare în orice sait web pe care îl vizitați + + + Asigură accesarea seifului dvs., într-un mod convenabil, din meniul contextual + + + Generează automat parole puternice, aleatorii și sigure + + + Gestionează informațiile dvs. în siguranța folosind criptarea AES pe 256 de biți + + diff --git a/apps/browser/store/locales/ru/copy.resx b/apps/browser/store/locales/ru/copy.resx new file mode 100644 index 0000000000..6932fab16d --- /dev/null +++ b/apps/browser/store/locales/ru/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – бесплатный менеджер паролей + + + Защищенный и бесплатный менеджер паролей для всех ваших устройств + + + Bitwarden, Inc. является материнской компанией 8bit Solutions LLC. + +НАЗВАН ЛУЧШИМ ДИСПЕТЧЕРОМ ПАРОЛЕЙ VERGE, US NEWS & WORLD REPORT, CNET И МНОГИМИ ДРУГИМИ. + +Управляйте, храните, защищайте и делитесь неограниченным количеством паролей на неограниченном количестве устройств из любого места. Bitwarden предоставляет решения с открытым исходным кодом по управлению паролями для всех, дома, на работе или в дороге. + +Создавайте надежные, уникальные и случайные пароли на основе требований безопасности для каждого посещаемого вами веб-сайта. + +Bitwarden Send быстро передает зашифрованную информацию - файлы и простой текст - напрямую кому угодно. + +Bitwarden предлагает для компаний планы Teams и Enterprise, чтобы вы могли безопасно делиться паролями с коллегами. + +Почему выбирают Bitwarden: + +Шифрование мирового класса +Пароли защищены передовым сквозным шифрованием (AES-256 bit, соленый хэштег и PBKDF2 SHA-256), поэтому ваши данные остаются в безопасности и конфиденциальности. + +Встроенный генератор паролей +Создавайте надежные, уникальные и случайные пароли на основе требований безопасности для каждого посещаемого вами веб-сайта. + + Глобальные переводы + Переводы Bitwarden существуют на 40 языках и постоянно растут благодаря нашему глобальному сообществу. + + Кросс-платформенные приложения + Защищайте и делитесь конфиденциальными данными в вашем Bitwarden Vault из любого браузера, мобильного устройства, настольной ОС и т. д. + + + Защищенный и бесплатный менеджер паролей для всех ваших устройств + + + Синхронизация и доступ к хранилищу с нескольких устройств + + + Управляйте всеми своими логинами и паролями из защищенного хранилища + + + Быстро и автоматически заполняйте свои учетные данные на любом веб-сайте + + + Предусмотрен удобный доступ к хранилищу из контекстного меню + + + Автоматически генерируйте сильные, случайные и надежные пароли + + + Ваша информация надежно хранится благодаря шифрованию AES-256 + + diff --git a/apps/browser/store/locales/si/copy.resx b/apps/browser/store/locales/si/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/si/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/sk/copy.resx b/apps/browser/store/locales/sk/copy.resx new file mode 100644 index 0000000000..a548d10a60 --- /dev/null +++ b/apps/browser/store/locales/sk/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Bezplatný správca hesiel + + + Bezpečný a bezplatný správca hesiel pre všetky vaše zariadenia + + + Bitwarden, Inc. je materská spoločnosť spoločnosti 8bit Solutions LLC. + +OHODNOTENÝ AKO NAJLEPŠÍ SPRÁVCA HESIEL V THE VERGE, U.S. NEWS & WORLD REPORT, CNET A ĎALŠÍMI. + +Spravujte, ukladajte, zabezpečte a zdieľajte neobmedzený počet hesiel naprieč neobmedzeným počtom zariadení odkiaľkoľvek. Bitwarden ponúka open source riešenie na správu hesiel komukoľvek, kdekoľvek doma, v práci alebo na ceste. + +Vygenerujte si silné, unikátne a náhodné heslá podľa bezpečnostných požiadaviek na každej stránke, ktorú navštevujete. + +Bitwarden Send rýchlo prenesie šifrované informácie -- súbory a text -- priamo komukoľvek. + +Bitwarden ponúka Teams a Enterprise paušály pre firmy, aby ste mohli bezpečne zdieľať hesla s kolegami. + +Prečo si vybrať Bitwarden: + +Svetová trieda v šifrovaní +Heslá sú chránené pokročilým end-to-end šifrovaním (AES-256 bit, salted hashtag a PBKDF2 SHA-256), takže Vaše dáta zostanú bezpečné a súkromné. + +Vstavaný generátor hesiel +Vygenerujte si silné, unikátne a náhodné heslá podľa bezpečnostných požiadaviek na každej stránke, ktorú navštevujete. + +Svetová lokalizácia +Vďaka našej globálnej komunite má Bitwarden neustále rastúcu lokalizáciu už do 40 jazykov. + +Aplikácie pre rôzne platformy +Zabezpečte a zdieľajte súkromné dáta prostredníctvom Bitwarden trezora z ktoréhokoľvek prehliadača, mobilného zariadenia, alebo stolného počítača a ďalších. + + + + Bezpečný a bezplatný správca hesiel pre všetky vaše zariadenia + + + Synchronizujte a pristupujte k vášmu trezoru z viacerých zariadení + + + Spravujte všetky vaše prihlasovacie mená a heslá z bezpečného trezoru + + + Rýchlo automaticky vyplňte vaše prihlasovacie údaje na akejkoľvek stránke, ktorú navštívite + + + Váš trezor je pohodlne dostupný aj z kontextovej ponuky + + + Automaticky generujte silné, náhodné a bezpečné heslá + + + Vaše informácie sú spravované bezpečne, použitím AES-256 bitového šifrovania + + diff --git a/apps/browser/store/locales/sl/copy.resx b/apps/browser/store/locales/sl/copy.resx new file mode 100644 index 0000000000..cfb4c5df10 --- /dev/null +++ b/apps/browser/store/locales/sl/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Free Password Manager + + + A secure and free password manager for all of your devices + + + Bitwarden, Inc. is the parent company of 8bit Solutions LLC. + +NAMED BEST PASSWORD MANAGER BY THE VERGE, U.S. NEWS & WORLD REPORT, CNET, AND MORE. + +Manage, store, secure, and share unlimited passwords across unlimited devices from anywhere. Bitwarden delivers open source password management solutions to everyone, whether at home, at work, or on the go. + +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Bitwarden Send quickly transmits encrypted information --- files and plaintext -- directly to anyone. + +Bitwarden offers Teams and Enterprise plans for companies so you can securely share passwords with colleagues. + +Why Choose Bitwarden: + +World-Class Encryption +Passwords are protected with advanced end-to-end encryption (AES-256 bit, salted hashtag, and PBKDF2 SHA-256) so your data stays secure and private. + +Built-in Password Generator +Generate strong, unique, and random passwords based on security requirements for every website you frequent. + +Global Translations +Bitwarden translations exist in 40 languages and are growing, thanks to our global community. + +Cross-Platform Applications +Secure and share sensitive data within your Bitwarden Vault from any browser, mobile device, or desktop OS, and more. + + + + A secure and free password manager for all of your devices + + + Sync and access your vault from multiple devices + + + Manage all your logins and passwords from a secure vault + + + Quickly auto-fill your login credentials into any website that you visit + + + Your vault is also conveniently accessible from the right-click menu + + + Automatically generate strong, random, and secure passwords + + + Your information is managed securely using AES-256 bit encryption + + diff --git a/apps/browser/store/locales/sr/copy.resx b/apps/browser/store/locales/sr/copy.resx new file mode 100644 index 0000000000..d67314a07c --- /dev/null +++ b/apps/browser/store/locales/sr/copy.resx @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Бесплатни Менаџер Лозинке + + + Сигурни и бесплатни менаџер лозинке за сва Ваша уређаја + + + Bitwarden је најједноставнији и најсигурнији начин за складиштење свих ваших података за пријављивање и лозинки, док их истовремено усклађујете на свим својим уређајима. + +Крађа лозинке је озбиљан проблем. Веб локације и апликације које користите свакодневно су на удару. Дошло је до нарушавања безбедности и крађе лозинки. Када поново користите исте лозинке у апликацијама и на веб локацијама, хакери могу лако да приступе вашој е-пошти, банци и другим важним рачунима. + +Стручњаци за безбедност препоручују употребу различите, насумично генерисане лозинке за сваки налог који креирате. Али како управљате свим тим лозинкама? Bitwarden вам олакшава стварање, чување и приступ вашим лозинкама. + +Bitwarden чува све ваше пријаве у шифрованом сефу који се синхронизује на свим вашим уређајима. Пошто је потпуно шифровано пре него што напусти уређај, само ви имате приступ подацима. Чак ни тим у Bitwarden не може да прочита ваше податке, чак и да то желимо. Ваши подаци су запечаћени са AES-256 битном енкрипцијом, усољеним хеширањем и PBKDF2 SHA-256. + +Bitwardenје софтвер са 100% отвореног кода. Изворни код Bitwarden-а се налази на GitHub и сви могу слободно да прегледају, провере и дају свој допринос за Bitwarden. + + + Сигурни и бесплатни менаџер лозинке за сва Ваша уређаја + + + Синхронизујте и приступите сефу са више уређаја + + + Управљајте свим својим пријавама и лозинкама из сигурног сефа + + + Брзо аутоматски попуните своје податке за пријављивање на било коју веб локацију коју посетите + + + Ваш сеф је такође доступан из менија десним кликом миша + + + Аутоматски генеришите јаке, насумичне и сигурне лозинке + + + Вашим подацима се сигурносно управља помоћу AES-256 битне енкрипције + + diff --git a/apps/browser/store/locales/sv/copy.resx b/apps/browser/store/locales/sv/copy.resx new file mode 100644 index 0000000000..8b3cb2a402 --- /dev/null +++ b/apps/browser/store/locales/sv/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Gratis lösenordshanterare + + + En säker och gratis lösenordshanterare för alla dina enheter + + + Bitwarden, Inc. är moderbolag till 8bit Solutions LLC. + +UTNÄMND TILL DEN BÄSTA LÖSENORDSHANTERAREN AV THE VERGE, U.S. NEWS & WORLD REPORT, CNET MED FLERA. + +Hantera, lagra, säkra och dela ett obegränsat antal lösenord mellan ett obegränsat antal enheter var som helst ifrån. Bitwarden levererar lösningar för lösenordshantering med öppen källkod till alla, vare sig det är hemma, på jobbet eller på språng. + +Generera starka, unika och slumpmässiga lösenord baserat på säkerhetskrav för varje webbplats du besöker. + +Bitwarden Send överför snabbt krypterad information --- filer och klartext -- direkt till vem som helst. + +Bitwarden erbjuder abonnemang för team och företag så att du säkert kan dela lösenord med kollegor. + +Varför välja Bitwarden: + +Kryptering i världsklass +Lösenord skyddas med avancerad end-to-end-kryptering (AES-256 bitar, saltad hashtag och PBKDF2 SHA-256) så att dina data förblir säkra och privata. + +Inbyggd lösenordsgenerator +Generera starka, unika och slumpmässiga lösenord baserat på säkerhetskrav för varje webbplats du besöker. + +Globala översättningar +Översättningar av Bitwarden finns på 40 språk och antalet växer tack vare vår globala gemenskap. + +Plattformsoberoende program +Säkra och dela känsliga data i ditt Bitwardenvalv från alla webbläsare, mobiler och datorer. + + + + En säker och gratis lösenordshanterare för alla dina enheter + + + Synkronisera och kom åt ditt valv från flera enheter + + + Hantera alla dina inloggningar och lösenord från ett säkert valv + + + Fyll snabbt och automatiskt in din inloggningsinformation på alla webbplatser du besöker + + + Ditt valv är bekvämt tillgängligt genom högerklicksmenyn + + + Skapa automatiskt starka, slumpmässiga, och säkra lösenord + + + Din information är säkert hanterad med AES-256 bitars kryptering + + diff --git a/apps/browser/store/locales/th/copy.resx b/apps/browser/store/locales/th/copy.resx new file mode 100644 index 0000000000..9c8965b01f --- /dev/null +++ b/apps/browser/store/locales/th/copy.resx @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – โปรแกรมจัดการรหัสผ่านฟรี + + + โปรแกรมจัดการรหัสผ่านที่ปลอดภัยและฟรี สำหรับอุปกรณ์ทั้งหมดของคุณ + + + Bitwarden, Inc. เป็นบริษัทแม่ของ 8bit Solutions LLC + +ได้รับการระบุชื่อเป็น โปรแกรมจัดการรหัสผ่านที่ดีที่สุด โดย The Verge, U.S. News & World Report, CNET, และที่อื่นๆ + +สามารถจัดการ จัดเก็บ ปกป้อง และแชร์รหัสผ่านไม่จำกัดจำนวนระหว่างอุปกรณ์ต่างๆ โดยไม่จำกัดจำนวนจากที่ไหนก็ได้ Bitwarden เสนอโซลูชันจัดการรหัสผ่านโอเพนซอร์สให้กับทุกคน ไม่ว่าจะอยู่ที่บ้าน ที่ทำงาน หรือนอกสถานที่ + +สามารถส่มสร้างรหัสผ่านที่ปลอดภัยและไม่ซ้ำกัน ตามเงื่อนไขความปลอดภัยที่กำหนดได้ สำหรับเว็บไซต์ทุกแห่งที่คุณใช้งานบ่อย + +Bitwarden Send สามารถส่งข้อมูลที่ถูกเข้ารหัส --- ไฟล์ หรือ ข้อความ -- ตรงไปยังใครก็ได้ได้อย่างรวดเร็ว + +Bitwarden มีแผนแบบ Teams และ Enterprise สำหรับบริษัทต่างๆ ซึางคุณสามารถแชร์รหัสผ่านกับเพื่อนร่วมงานได้อย่างปลอดภัย + +ทำไมควรเลือก Bitwarden: + +การเข้ารหัสมาตรฐานโลก +รหัสผ่านจะได้รับการปกป้องด้วยการเข้ารหัสชั้นสูง (AES-256 บิต, salted hashtag, และ PBKDF2 SHA-256) แบบต้นทางถึงปลายทาง เพื่อให้ข้อมูลของคุณปลอดภัยและเป็นส่วนตัว + +มีตัวช่วยส่มสร้างรหัสผ่าน +สามารถสุ่มสร้างรหัสผ่านที่ปลอดภัยและไม่ซ้ำกัน ตามเงื่อนไขความปลอดภัยที่กำหนดได้ สำหรับเว็บไซต์ทุกแห่งที่คุณใช้งานบ่อย + +แปลเป็นภาษาต่างๆ ทั่วโลก +Bitwarden ได้รับการแปลเป็นภาษาต่างๆ กว่า 40 ภาษา และกำลังเพิ่มขึ้นเรื่อยๆ ด้วยความสนับสนุนจากชุมชนผู้ใช้งานทั่วโลก + +แอปพลิเคชันข้ามแพลตฟอร์ม +ปกป้องและแชร์ข้อมูลอ่อนไหวในตู้เซฟ Bitwarden จากเว็บเบราว์เซอร์ อุปกรณ์มือถือ หรือเดสท็อป หรือช่องทางอื่นๆ + + + + โปรแกรมจัดการรหัสผ่านที่ปลอดภัยและฟรี สำหรับอุปกรณ์ทั้งหมดของคุณ + + + ซิงค์และเข้าถึงตู้นิรภัยของคุณจากหลายอุปกรณ์ + + + จัดการล็อกอินและรหัสผ่านทั้งหมดของคุณจากตู้นิรภัยที่ปลอดภัย + + + กรอกข้อมูลล็อกอินโดยอัตโนมัติบนทุกเว็บไซต์ที่คุณใช้งานได้อย่างรวดเร็ว + + + ตู้เซฟของคุณยังสามารถเข้าถึงได้โดยสะดวกผ่านเมนูคลิกขวา + + + ส่มสร้างรหัสผ่านที่แข็งแกร่งและปลอดภัยโดยอัตโนมัติ + + + ข้อมูลของคุณได้รับการจัดการอย่างปลอดภัยโดยใช้การเข้ารหัส AES 256 บิต + + diff --git a/apps/browser/store/locales/tr/copy.resx b/apps/browser/store/locales/tr/copy.resx new file mode 100644 index 0000000000..2763c3ec91 --- /dev/null +++ b/apps/browser/store/locales/tr/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Ücretsiz Parola Yöneticisi + + + Tüm aygıtlarınız için güvenli ve ücretsiz bir parola yöneticisi + + + Bitwarden, Inc., 8bit Solutions LLC’nin ana şirketidir. + +THE VERGE, U.S. NEWS & WORLD REPORT, CNET VE BİRÇOK MEDYA KURULUŞUNA GÖRE EN İYİ PAROLA YÖNETİCİSİ. + +Sınırsız sayıda parolayı istediğiniz kadar cihazda yönetin, saklayın, koruyun ve paylaşın. Bitwarden; herkesin evde, işte veya yolda kullanabileceği açık kaynaklı parola yönetim çözümleri sunuyor. + +Sık kullandığınız web siteleri için güvenlik gereksinimlerinize uygun, güçlü, benzersiz ve rastgele parolalar oluşturabilirsiniz. + +Bitwarden Send, şifrelenmiş bilgileri (dosyalar ve düz metinler) herkese hızlı bir şekilde iletmenizi sağlıyor. + +Bitwarden, parolaları iş arkadaşlarınızla güvenli bir şekilde paylaşabilmeniz için şirketlere yönelik Teams ve Enterprise paketleri de sunuyor. + +Neden Bitwarden? + +Üst düzey şifreleme +Parolalarınız gelişmiş uçtan uca şifreleme (AES-256 bit, salted hashtag ve PBKDF2 SHA-256) ile korunuyor, böylece verileriniz güvende ve gizli kalıyor. + +Dahili parola oluşturucu +Sık kullandığınız web siteleri için güvenlik gereksinimlerinize uygun, güçlü, benzersiz ve rastgele parolalar oluşturabilirsiniz. + +Çeviriler +Bitwarden 40 dilde kullanılabiliyor ve gönüllü topluluğumuz sayesinde çeviri sayısı giderek artıyor. + +Her platformla uyumlu uygulamalar +Bitwarden kasanızdaki hassas verilere her tarayıcıdan, mobil cihazdan veya masaüstü işletim sisteminden ulaşabilir ve onları paylaşabilirsiniz. + + + Tüm cihazarınız için güvenli ve ücretsiz bir parola yöneticisi + + + Hesabınızı senkronize ederek kasanıza tüm cihazlarınızdan ulaşın + + + Tüm giriş bilgilerinizi ve parolalarınızı güvenli bir kasadan yönetin + + + Ziyaret ettiğiniz web sitelerindeki giriş bilgilerinizi otomatik olarak anında doldurun + + + Kasanıza sağ tıklama menüsünden de rahatlıkla erişebilirsiniz + + + Otomatik olarak güçlü, rastgele ve güvenli parolalar oluşturun + + + Bilgileriniz AES-256 bit şifreleme kullanılarak güvenle yönetilir + + diff --git a/apps/browser/store/locales/uk/copy.resx b/apps/browser/store/locales/uk/copy.resx new file mode 100644 index 0000000000..77f9820d59 --- /dev/null +++ b/apps/browser/store/locales/uk/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – Безкоштовний менеджер паролів + + + Захищений і безкоштовний менеджер паролів для всіх ваших пристроїв + + + 8bit Solutions LLC є дочірньою компанією Bitwarden, Inc. + +НАЙКРАЩИЙ МЕНЕДЖЕР ПАРОЛІВ ЗА ВЕРСІЄЮ THE VERGE, U.S. NEWS & WORLD REPORT, CNET, А ТАКОЖ ІНШИХ ВИДАНЬ. + +Зберігайте, захищайте, керуйте і надавайте доступ до паролів на різних пристроях де завгодно. Bitwarden пропонує рішення для керування паролями на основі відкритого програмного коду особистим та корпоративним користувачам на всіх пристроях. + +Генеруйте випадкові, надійні та унікальні паролі, які задовольняють вимоги безпеки, для кожного вебсайту та сервісу. + +Функція Bitwarden Send швидко та безпосередньо передає зашифровану інформацію будь-кому - файли та звичайний текст. + +Bitwarden пропонує командні та корпоративні тарифні плани для компаній, щоб ви могли безпечно обмінюватися паролями з колегами. + +Чому варто обрати Bitwarden: + +Шифрування світового рівня +Паролі захищаються з використанням розширеного наскрізного шифрування (AES-256 bit, salted hashtag, та PBKDF2 SHA-256), тому ваші дані завжди захищені та приватні. + +Вбудований генератор паролів +Генеруйте випадкові, надійні та унікальні паролі, які задовольняють вимоги безпеки, для кожного вебсайту та сервісу. + +Переклад багатьма мовами +Завдяки нашій глобальній спільноті, Bitwarden перекладено 40 мовами, і їх кількість продовжує зростати. + +Програми для різних платформ +Зберігайте і діліться важливими даними, а також користуйтеся іншими можливостями у вашому сховищі Bitwarden в будь-якому браузері, мобільному пристрої, чи комп'ютерній операційній системі. + + + Захищений і безкоштовний менеджер паролів для всіх ваших пристроїв + + + Синхронізуйте й отримуйте доступ до вашого сховища на багатьох пристроях + + + Керуйте всіма своїми записами в захищеному сховищі + + + Швидко й автоматично заповнюйте свої облікові дані на будь-якому веб-сайті + + + Ви також можете зручно отримати доступ до свого сховища з контекстного меню + + + Автоматично генеруйте стійкі, випадкові та надійні паролі + + + Ваша інформація надійно захищена алгоритмом шифрування AES-256 + + diff --git a/apps/browser/store/locales/vi/copy.resx b/apps/browser/store/locales/vi/copy.resx new file mode 100644 index 0000000000..52beeca10b --- /dev/null +++ b/apps/browser/store/locales/vi/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden - Trình quản lý mật khẩu miễn phí + + + Một trình quản lý mật khẩu an toàn và miễn phí cho mọi thiết bị của bạn + + + Bitwarden, Inc là công ty mẹ của 8bit Solutions LLC + +ĐƯỢC ĐÁNH GIÁ LÀ TRÌNH QUẢN LÝ MẬT KHẨU TỐT NHẤT BỞI NHÀ BÁO LỚN NHƯ THE VERGE, CNET, U.S. NEWS & WORLD REPORT VÀ HƠN NỮA + +Quản lý, lưu trữ, bảo mật và chia sẻ mật khẩu không giới hạn trên các thiết bị không giới hạn mọi lúc, mọi nơi. Bitwarden cung cấp các giải pháp quản lý mật khẩu mã nguồn mở cho tất cả mọi người, cho dù ở nhà, tại cơ quan hay khi đang di chuyển . + +Tạo mật khẩu mạnh, không bị trùng và ngẫu nhiên dựa trên các yêu cầu bảo mật cho mọi trang web bạn thường xuyên sử dụng. + +Tính năng 'Bitwarden Send' nhanh chóng truyền thông tin được mã hóa --- tệp và bản rõ - trực tiếp đến bất kỳ ai. + +Bitwarden cung cấp các gói 'Nhóm' và 'Doanh nghiệp' cho các công ty để bạn có thể chia sẻ mật khẩu với đồng nghiệp một cách an toàn. + +Tại sao bạn nên chọn Bitwarden: + +Mã hóa tốt nhất thế giới +Mật khẩu được bảo vệ bằng mã hóa đầu cuối (end-to-end encryption) tiên tiến như AES-256 bit, salted hashtag, và PBKDF2 SHA-256 nên dữ liệu của bạn luôn an toàn và riêng tư. + +Trình tạo mật khẩu tích hợp +Tạo mật khẩu mạnh, không bị trùng và ngẫu nhiên dựa trên các yêu cầu bảo mật cho mọi trang web bạn thường xuyên sử dụng. + +Bản dịch ngôn ngữ từ cộng đồng +Bitwarden đã có bản dịch 40 ngôn ngữ và đang phát triển nhờ vào cộng đồng toàn cầu của chúng tôi. + +Ứng dụng đa nền tảng +Bảo mật và chia sẻ dữ liệu nhạy cảm trong kho lưu trữ Bitwarden của bạn từ bất kỳ trình duyệt, điện thoại thông minh hoặc hệ điều hành máy tính nào, vân vân + + + Một trình quản lý mật khẩu an toàn và miễn phí cho mọi thiết bị của bạn + + + Đồng bộ hóa và truy cập vào kho mật khẩu của bạn từ nhiều thiết bị + + + Quản lý tất cả đăng nhập và mật khẩu của bạn từ một kho mật khẩu an toàn + + + Nhanh chóng tự động điền thông tin đăng nhập của bạn vào bất kỳ trang web nào mà bạn truy cập + + + Dễ dàng truy cập kho mật khẩu của bạn từ menu chuột phải + + + Tự động tạo mật khẩu mạnh, ngẫu nhiên và an toàn + + + Thông tin của bạn được quản lý một cách an toàn bằng cách sử dụng mã hóa AES-256 bit + + diff --git a/apps/browser/store/locales/zh_CN/copy.resx b/apps/browser/store/locales/zh_CN/copy.resx new file mode 100644 index 0000000000..055a736e2a --- /dev/null +++ b/apps/browser/store/locales/zh_CN/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – 免费密码管理器 + + + 安全免费的跨平台密码管理器 + + + Bitwarden, Inc. 是 8bit Solutions LLC 的母公司。 + +被 the verge、U.S. news & world report、cnet 等评为最佳密码管理器。 + +从任何地方,不限制设备,管理、存储、保护和共享无限的密码。Bitwarden 为每个人提供开源的密码管理解决方案,无论是在家里,在工作中,还是在旅途中。 + +基于安全要求,为你经常访问的每个网站生成强大、唯一和随机的密码。 + +Bitwarden Send 快速传输加密的信息---文件和文本---直接给任何人。 + +Bitwarden 为公司提供团队和企业计划,因此你可以安全地与同事共享密码。 + +为何选择 Bitwarden: + +世界级的加密技术 +密码受到先进的端到端加密(AES-256 位、盐化标签和 PBKDF2 SHA-256)的保护,为您的数据保持安全和隐密。 + +内置密码生成器 +基于安全要求,为你经常访问的每个网站生成强大、唯一和随机的密码。 + +全球翻译 +Bitwarden 的翻译有 40 种语言,而且还在不断增加,感谢我们的全球社区。 + +跨平台的应用程序 +从任何浏览器、移动设备或桌面操作系统,以及更多的地方,在您的 Bitwarden 密码库中保护和分享敏感数据。 + + + 安全免费的跨平台密码管理器 + + + 从多台设备同步和访问密码库 + + + 在一个安全的密码库中管理您所有的登录信息和密码 + + + 在您访问的任何网站中快速自动填充登录项目 + + + 您也可以通过右击菜单快捷方便地访问密码库 + + + 自动生成强大、随机和安全的密码 + + + 您的信息使用 AES-256 位加密进行安全管理 + + diff --git a/apps/browser/store/locales/zh_TW/copy.resx b/apps/browser/store/locales/zh_TW/copy.resx new file mode 100644 index 0000000000..96b4f92f17 --- /dev/null +++ b/apps/browser/store/locales/zh_TW/copy.resx @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Bitwarden – 免費密碼管理工具 + + + 安全、免費、跨平台的密碼管理工具 + + + Bitwarden, Inc. 是 8bit Solutions LLC 的母公司。 + +被 THE VERGE、U.S. NEWS & WORLD REPORT、CNET 等評為最佳密碼管理器。 + +從任何地方,不限制設備,管理、存儲、保護和共享無限的密碼。Bitwarden 為每個人提供開源的密碼管理解決方案,無論是在家裡,在工作中,還是在旅途中。 + +基於安全要求,為你經常訪問的每個網站生成強大、唯一和隨機的密碼。 + +Bitwarden Send 快速傳輸加密的信息---文檔和文本---直接給任何人。 + +Bitwarden 為公司提供團隊和企業計劃,因此你可以安全地與同事共享密碼。 + +為何選擇 Bitwarden: + +世界級的加密技術 +密碼受到先進的端到端加密(AES-256 位、鹽化標籤和 PBKDF2 SHA-256)的保護,為您的數據保持安全和隱密。 + +內置密碼生成器 +基於安全要求,為你經常訪問的每個網站生成強大、唯一和隨機的密碼。 + +全球翻譯 +Bitwarden 的翻譯有 40 種語言,而且還在不斷增加,感謝我們的全球社區。 + +跨平台的應用程式 +從任何瀏覽器、行動裝置或桌面作業系統,以及更多的地方,在您的 Bitwarden 密碼庫中保護和分享敏感數據。 + + + 安全、免費、跨平台的密碼管理工具 + + + 在多部裝置上同步和存取密碼庫 + + + 在一個安全的密碼庫中管理密碼 + + + 快速自動填入登入憑據到您造訪的任何網站中 + + + 您可以透過滑鼠右鍵選單快速地存取密碼庫 + + + 自動生成高強度、隨機且安全的密碼 + + + 您的資訊採用 AES-256 位加密安全管理 + + diff --git a/apps/browser/store/windows/AppxManifest.xml b/apps/browser/store/windows/AppxManifest.xml new file mode 100644 index 0000000000..f57b3db988 --- /dev/null +++ b/apps/browser/store/windows/AppxManifest.xml @@ -0,0 +1,50 @@ + + + + + + + Bitwarden Extension - Free Password Manager + 8bit Solutions LLC + Assets/icon_50.png + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/browser/store/windows/Assets/icon_150.png b/apps/browser/store/windows/Assets/icon_150.png new file mode 100644 index 0000000000..cd7fda75d9 Binary files /dev/null and b/apps/browser/store/windows/Assets/icon_150.png differ diff --git a/apps/browser/store/windows/Assets/icon_44.png b/apps/browser/store/windows/Assets/icon_44.png new file mode 100644 index 0000000000..10ab6fe65a Binary files /dev/null and b/apps/browser/store/windows/Assets/icon_44.png differ diff --git a/apps/browser/store/windows/Assets/icon_50.png b/apps/browser/store/windows/Assets/icon_50.png new file mode 100644 index 0000000000..4865f4abe3 Binary files /dev/null and b/apps/browser/store/windows/Assets/icon_50.png differ diff --git a/apps/browser/tsconfig.json b/apps/browser/tsconfig.json new file mode 100644 index 0000000000..17b727079c --- /dev/null +++ b/apps/browser/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "noImplicitAny": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "es6", + "target": "ES2016", + "allowJs": true, + "sourceMap": true, + "baseUrl": ".", + "paths": { + "jslib-common/*": ["../../libs/common/src/*"], + "jslib-angular/*": ["../../libs/angular/src/*"] + } + }, + "angularCompilerOptions": { + "preserveWhitespaces": true + }, + "include": ["src"] +} diff --git a/apps/browser/tsconfig.spec.json b/apps/browser/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/apps/browser/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/apps/browser/webpack.config.js b/apps/browser/webpack.config.js new file mode 100644 index 0000000000..dc6f512ee6 --- /dev/null +++ b/apps/browser/webpack.config.js @@ -0,0 +1,199 @@ +const path = require("path"); +const webpack = require("webpack"); +const { CleanWebpackPlugin } = require("clean-webpack-plugin"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const { AngularWebpackPlugin } = require("@ngtools/webpack"); +const TerserPlugin = require("terser-webpack-plugin"); + +if (process.env.NODE_ENV == null) { + process.env.NODE_ENV = "development"; +} +const ENV = (process.env.ENV = process.env.NODE_ENV); + +const moduleRules = [ + { + test: /\.(html)$/, + loader: "html-loader", + }, + { + test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, + exclude: /loading.svg/, + generator: { + filename: "popup/fonts/[name][ext]", + }, + type: "asset/resource", + }, + { + test: /\.(jpe?g|png|gif|svg)$/i, + exclude: /.*(bwi-font|glyphicons-halflings-regular)\.svg/, + generator: { + filename: "popup/images/[name][ext]", + }, + type: "asset/resource", + }, + { + test: /\.scss$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + }, + "css-loader", + "sass-loader", + ], + }, + // Hide System.import warnings. ref: https://github.com/angular/angular/issues/21560 + { + test: /[\/\\]@angular[\/\\].+\.js$/, + parser: { system: true }, + }, + { + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + loader: "@ngtools/webpack", + }, +]; + +const plugins = [ + new HtmlWebpackPlugin({ + template: "./src/popup/index.html", + filename: "popup/index.html", + chunks: ["popup/polyfills", "popup/vendor-angular", "popup/vendor", "popup/main"], + }), + new HtmlWebpackPlugin({ + template: "./src/background.html", + filename: "background.html", + chunks: ["vendor", "background"], + }), + new HtmlWebpackPlugin({ + template: "./src/notification/bar.html", + filename: "notification/bar.html", + chunks: ["notification/bar"], + }), + new CopyWebpackPlugin({ + patterns: [ + "./src/manifest.json", + { from: "./src/_locales", to: "_locales" }, + { from: "./src/images", to: "images" }, + { from: "./src/popup/images", to: "popup/images" }, + { from: "./src/content/autofill.css", to: "content" }, + ], + }), + new MiniCssExtractPlugin({ + filename: "[name].css", + chunkFilename: "chunk-[id].css", + }), + new webpack.DefinePlugin({ + "process.env": { + ENV: JSON.stringify(ENV), + }, + }), + new AngularWebpackPlugin({ + tsConfigPath: "tsconfig.json", + entryModule: "src/popup/app.module#AppModule", + sourceMap: true, + }), + new CleanWebpackPlugin({ + cleanAfterEveryBuildPatterns: ["!popup/fonts/**/*"], + }), + new webpack.ProvidePlugin({ + process: "process/browser", + }), + new webpack.SourceMapDevToolPlugin({ + exclude: [/content\/.*/, /notification\/.*/], + filename: "[file].map", + }), +]; + +const config = { + mode: ENV, + devtool: false, + entry: { + "popup/polyfills": "./src/popup/polyfills.ts", + "popup/main": "./src/popup/main.ts", + background: "./src/background.ts", + "content/autofill": "./src/content/autofill.js", + "content/autofiller": "./src/content/autofiller.ts", + "content/notificationBar": "./src/content/notificationBar.ts", + "content/contextMenuHandler": "./src/content/contextMenuHandler.ts", + "content/shortcuts": "./src/content/shortcuts.ts", + "content/message_handler": "./src/content/message_handler.ts", + "notification/bar": "./src/notification/bar.js", + }, + optimization: { + minimize: true, + minimizer: [ + new TerserPlugin({ + exclude: [/content\/.*/, /notification\/.*/], + terserOptions: { + // Replicate Angular CLI behaviour + compress: { + global_defs: { + ngDevMode: false, + ngI18nClosureMode: false, + }, + }, + }, + }), + ], + splitChunks: { + cacheGroups: { + commons: { + test(module, chunks) { + return ( + module.resource != null && + module.resource.includes(`${path.sep}node_modules${path.sep}`) && + !module.resource.includes(`${path.sep}node_modules${path.sep}@angular${path.sep}`) + ); + }, + name: "popup/vendor", + chunks: (chunk) => { + return chunk.name === "popup/main"; + }, + }, + angular: { + test(module, chunks) { + return ( + module.resource != null && + module.resource.includes(`${path.sep}node_modules${path.sep}@angular${path.sep}`) + ); + }, + name: "popup/vendor-angular", + chunks: (chunk) => { + return chunk.name === "popup/main"; + }, + }, + commons2: { + test: /[\\/]node_modules[\\/]/, + name: "vendor", + chunks: (chunk) => { + return chunk.name === "background"; + }, + }, + }, + }, + }, + resolve: { + extensions: [".ts", ".js"], + symlinks: false, + modules: [path.resolve("../../node_modules")], + alias: { + sweetalert2: require.resolve("sweetalert2/dist/sweetalert2.js"), + "#sweetalert2": require.resolve("sweetalert2/src/sweetalert2.scss"), + }, + fallback: { + assert: false, + buffer: require.resolve("buffer/"), + util: require.resolve("util/"), + url: require.resolve("url/"), + }, + }, + output: { + filename: "[name].js", + path: path.resolve(__dirname, "build"), + }, + module: { rules: moduleRules }, + plugins: plugins, +}; + +module.exports = config; diff --git a/apps/cli/.eslintrc.json b/apps/cli/.eslintrc.json new file mode 100644 index 0000000000..10d2238837 --- /dev/null +++ b/apps/cli/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "env": { + "node": true + } +} diff --git a/apps/cli/.gitignore b/apps/cli/.gitignore new file mode 100644 index 0000000000..b6c18808b0 --- /dev/null +++ b/apps/cli/.gitignore @@ -0,0 +1,5 @@ +node_modules +build +dist + +config/local.json diff --git a/apps/cli/.npmignore b/apps/cli/.npmignore new file mode 100644 index 0000000000..6e4ac06144 --- /dev/null +++ b/apps/cli/.npmignore @@ -0,0 +1,3 @@ +* +!/build +!/build/**/* diff --git a/apps/cli/.vscode/launch.json b/apps/cli/.vscode/launch.json new file mode 100644 index 0000000000..ac4d00db2c --- /dev/null +++ b/apps/cli/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "protocol": "inspector", + "cwd": "${workspaceRoot}", + "program": "${workspaceFolder}/build/bw.js", + "env": { + "BW_SESSION": "fPZb0J+1NBzQ+HB512pLhSIIt2aRoOjqs6SrbxbTHVcsZdFk1cthzjBIMqBa2X7fjOOA3VU0bnR42fYeuWj2Vw==" + }, + "sourceMapPathOverrides": { + "meteor://💻app/*": "${workspaceFolder}/*", + "webpack:///./~/*": "${workspaceFolder}/node_modules/*", + "webpack://?:*/*": "${workspaceFolder}/*", + "webpack://@bitwarden/cli/*": "${workspaceFolder}/*" + }, + "smartStep": true, + "console": "integratedTerminal", + "args": ["login", "sdfsd@sdfdf.com", "ddddddd"] + } + ] +} diff --git a/apps/cli/.vscode/settings.json b/apps/cli/.vscode/settings.json new file mode 100644 index 0000000000..4570edf3bc --- /dev/null +++ b/apps/cli/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "debug.javascript.terminalOptions": { + "sourceMapPathOverrides": { + "meteor://💻app/*": "${workspaceFolder}/*", + "webpack:///./~/*": "${workspaceFolder}/node_modules/*", + "webpack://?:*/*": "${workspaceFolder}/*", + "webpack://@bitwarden/cli/*": "${workspaceFolder}/*" + } + } +} diff --git a/apps/cli/README.md b/apps/cli/README.md new file mode 100644 index 0000000000..544b397fdc --- /dev/null +++ b/apps/cli/README.md @@ -0,0 +1,84 @@ +[![Github Workflow build on master](https://github.com/bitwarden/clients/actions/workflows/build-cli.yml/badge.svg?branch=master)](https://github.com/bitwarden/clients/actions/workflows/build-cli.yml?query=branch:master) +[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby) + +# Bitwarden Command-line Interface + +[![Platforms](https://imgur.com/AnTLX0S.png "Platforms")](https://help.bitwarden.com/article/cli/#download--install) + +The Bitwarden CLI is a powerful, full-featured command-line interface (CLI) tool to access and manage a Bitwarden vault. The CLI is written with TypeScript and Node.js and can be run on Windows, macOS, and Linux distributions. + +![CLI](https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/cli-macos.png "CLI") + +## Download/Install + +You can install the Bitwarden CLI multiple different ways: + +**NPM** + +If you already have the Node.js runtime installed on your system, you can install the CLI using NPM. NPM makes it easy to keep your installation updated and should be the preferred installation method if you are already using Node.js. + +```bash +npm install -g @bitwarden/cli +``` + +**Native Executable** + +We provide natively packaged versions of the CLI for each platform which have no requirements on installing the Node.js runtime. You can obtain these from the [downloads section](https://help.bitwarden.com/article/cli/#download--install) in the documentation. + +**Other Package Managers** + +- [Chocolatey](https://chocolatey.org/packages/bitwarden-cli) + ```powershell + choco install bitwarden-cli + ``` +- [Homebrew](https://formulae.brew.sh/formula/bitwarden-cli) + ```bash + brew install bitwarden-cli + ``` +- [Snap](https://snapcraft.io/bw) + ```bash + sudo snap install bw + ``` + +## Documentation + +The Bitwarden CLI is self-documented with `--help` content and examples for every command. You should start exploring the CLI by using the global `--help` option: + +```bash +bw --help +``` + +This option will list all available commands that you can use with the CLI. + +Additionally, you can run the `--help` option on a specific command to learn more about it: + +```bash +bw list --help +bw create --help +``` + +**Detailed Documentation** + +We provide detailed documentation and examples for using the CLI in our help center at https://help.bitwarden.com/article/cli/. + +## Build/Run + +**Requirements** + +- [Node.js](https://nodejs.org) v16.13.1. + - Testing is done against Node 16, other versions may work, but are not guaranteed. +- NPM v8 + +**Run the app** + +```bash +npm install +npm run sub:init # initialize the git submodule for jslib +npm run build:watch +``` + +You can then run commands from the `./build` folder: + +```bash +node ./build/bw.js login +``` diff --git a/apps/cli/config/config.js b/apps/cli/config/config.js new file mode 100644 index 0000000000..2b2516e7c2 --- /dev/null +++ b/apps/cli/config/config.js @@ -0,0 +1,31 @@ +/* eslint-disable no-console */ +function load(envName) { + return { + ...loadConfig(envName), + ...loadConfig("local"), + }; +} + +function log(configObj) { + const repeatNum = 50; + console.log(`${"=".repeat(repeatNum)}\nenvConfig`); + console.log(JSON.stringify(configObj, null, 2)); + console.log(`${"=".repeat(repeatNum)}`); +} + +function loadConfig(configName) { + try { + return require(`./${configName}.json`); + } catch (e) { + if (e instanceof Error && e.code === "MODULE_NOT_FOUND") { + return {}; + } else { + throw e; + } + } +} + +module.exports = { + load, + log, +}; diff --git a/apps/cli/config/development.json b/apps/cli/config/development.json new file mode 100644 index 0000000000..d8e5c04e7e --- /dev/null +++ b/apps/cli/config/development.json @@ -0,0 +1,5 @@ +{ + "flags": { + "serve": true + } +} diff --git a/apps/cli/config/production.json b/apps/cli/config/production.json new file mode 100644 index 0000000000..d8e5c04e7e --- /dev/null +++ b/apps/cli/config/production.json @@ -0,0 +1,5 @@ +{ + "flags": { + "serve": true + } +} diff --git a/apps/cli/examples/git-credential-bw.sh b/apps/cli/examples/git-credential-bw.sh new file mode 100644 index 0000000000..9195471bb5 --- /dev/null +++ b/apps/cli/examples/git-credential-bw.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# bw git-credential helper +# Based on: +# * https://github.com/lastpass/lastpass-cli/blob/master/contrib/examples/git-credential-lastpass +# * https://gist.github.com/mikeboiko/58ab730afd65bca0a125bc12b6f4670d + +# A credential helper for git to retrieve usernames and passwords from bw. +# For general usage, see https://git-scm.com/docs/gitcredentials. +# Here's a quick version: +# 1. Put this somewhere in your path. +# 2. git config --global credential.helper bw + +declare -A params + +if [[ "$1" == "get" ]]; then + read -r line + while [ -n "$line" ]; do + key=${line%%=*} + value=${line#*=} + params[$key]=$value + read -r line + done + + if [[ "${params['protocol']}" != "https" ]]; then + exit + fi + + if [[ -z "${params["host"]}" ]]; then + exit + fi + + if ! bw list items --search "asdf" > /dev/null 2>&1; then + echo "Please login to Bitwarden to use git credential helper" > /dev/stderr + exit + fi + + id=$(bw list items --search "${params["host"]}"|jq ".[] | select(.name == \"${params["host"]}\").id" -r) + + if [[ -z "$id" ]]; then + echo "Couldn't find item id in Bitwarden DB." > /dev/stderr + echo "${params}" + exit + fi + + user=$(bw get username "${id}") + pass=$(bw get password "${id}") + + if [[ -z "$user" ]] || [[ -z "$pass" ]]; then + echo "Couldn't find host in Bitwarden DB." > /dev/stderr + exit + fi + + echo username="$user" + echo password="$pass" +fi diff --git a/apps/cli/jest.config.js b/apps/cli/jest.config.js new file mode 100644 index 0000000000..48c4b61d3a --- /dev/null +++ b/apps/cli/jest.config.js @@ -0,0 +1,15 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + preset: "ts-jest", + testMatch: ["**/+(*.)+(spec).+(ts)"], + setupFilesAfterEnv: ["/spec/test.ts"], + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), +}; diff --git a/apps/cli/package.json b/apps/cli/package.json new file mode 100644 index 0000000000..58da0c15fe --- /dev/null +++ b/apps/cli/package.json @@ -0,0 +1,46 @@ +{ + "name": "@bitwarden/cli", + "description": "A secure and free password manager for all of your devices.", + "version": "1.22.1", + "keywords": [ + "bitwarden", + "password", + "vault", + "password manager", + "cli" + ], + "author": "Bitwarden Inc. (https://bitwarden.com)", + "homepage": "https://bitwarden.com", + "repository": { + "type": "git", + "url": "https://github.com/bitwarden/cli" + }, + "license": "GPL-3.0-only", + "scripts": { + "clean": "rimraf dist/**/*", + "build": "webpack", + "build:debug": "npm run build && node --inspect ./build/bw.js", + "build:watch": "webpack --watch", + "build:prod": "cross-env NODE_ENV=production webpack", + "build:prod:watch": "cross-env NODE_ENV=production webpack --watch", + "package": "npm run package:win && npm run package:mac && npm run package:lin", + "package:win": "pkg . --targets win-x64 --output ./dist/windows/bw.exe --build", + "package:mac": "pkg . --targets macos-x64 --output ./dist/macos/bw", + "package:lin": "pkg . --targets linux-x64 --output ./dist/linux/bw", + "debug": "node --inspect ./build/bw.js", + "dist": "npm run build:prod && npm run clean && npm run package", + "dist:win": "npm run build:prod && npm run clean && npm run package:win", + "dist:mac": "npm run build:prod && npm run clean && npm run package:mac", + "dist:lin": "npm run build:prod && npm run clean && npm run package:lin", + "publish:npm": "npm run build:prod && npm publish --access public", + "test": "jest", + "test:watch": "jest --watch", + "test:watch:all": "jest --watchAll" + }, + "bin": { + "bw": "build/bw.js" + }, + "pkg": { + "assets": "./build/**/*" + } +} diff --git a/apps/cli/scripts/brew-update.ps1 b/apps/cli/scripts/brew-update.ps1 new file mode 100644 index 0000000000..f9b7ce6a3d --- /dev/null +++ b/apps/cli/scripts/brew-update.ps1 @@ -0,0 +1,23 @@ +param ( + [Parameter(Mandatory=$true)] + [string] $version +) + +# Dependencies: +# 1. brew cask install powershell +# 2. Environment variables for HOMEBREW_GITHUB_USER and HOMEBREW_GITHUB_API_TOKEN set. +# +# To run: +# pwsh ./brew-update.ps1 -version 1.1.0 + +# Cleaning up +cd $("$(brew --repository)" + "/Library/Taps/homebrew/homebrew-core/Formula") +git checkout master +git reset --hard origin/master +git push $env:HOMEBREW_GITHUB_USER master +git branch -D $("bitwarden-cli-" + $version) +git push $env:HOMEBREW_GITHUB_USER --delete $("bitwarden-cli-" + $version) + +# Bump +$url = 'https://registry.npmjs.org/@bitwarden/cli/-/cli-' + $version + '.tgz'; +brew bump-formula-pr --url="$url" bitwarden-cli diff --git a/apps/cli/scripts/choco-pack.ps1 b/apps/cli/scripts/choco-pack.ps1 new file mode 100644 index 0000000000..a43b4aa4ed --- /dev/null +++ b/apps/cli/scripts/choco-pack.ps1 @@ -0,0 +1,34 @@ +param ( + [switch] $push +) + +# To run: +# .\choco-pack.ps1 + +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path; +$rootDir = $dir + "\.."; +$distDir = $rootDir + "\dist"; +$chocoDir = $rootDir + "\stores\chocolatey"; +$distChocoDir = $distDir + "\chocolatey"; +$distChocoToolsDir = $distDir + "\chocolatey\tools"; + +if(Test-Path -Path $distChocoDir) { + Remove-Item -Recurse -Force $distChocoDir +} + +$exe = $distDir + "\windows\bw.exe"; +$license = $rootDir + "\LICENSE.txt"; +Copy-Item -Path $chocoDir -Destination $distChocoDir –Recurse +Copy-Item $exe -Destination $distChocoToolsDir; +Copy-Item $license -Destination $distChocoToolsDir; + +$srcPackage = $rootDir + "\package.json"; +$srcPackageVersion = (Get-Content -Raw -Path $srcPackage | ConvertFrom-Json).version; +$nuspec = $distChocoDir + "\bitwarden-cli.nuspec"; +choco pack $nuspec --version $srcPackageVersion --out $distChocoDir + +if ($push) { + cd $distChocoDir + choco push + cd $rootDir +} diff --git a/apps/cli/scripts/choco-update.ps1 b/apps/cli/scripts/choco-update.ps1 new file mode 100644 index 0000000000..f1b5e295be --- /dev/null +++ b/apps/cli/scripts/choco-update.ps1 @@ -0,0 +1,26 @@ +param ( + [Parameter(Mandatory=$true)] + [string] $version +) + +# To run: +# .\choco-update.ps1 -version 1.3.0 + +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path; +$rootDir = $dir + "\.."; +$distDir = $rootDir + "\dist"; +$distChocoDir = $distDir + "\chocolatey"; + +if(Test-Path -Path $distChocoDir) { + Remove-Item -Recurse -Force $distChocoDir +} +New-Item -ItemType directory -Path $distChocoDir | Out-Null + +$nupkg = "bitwarden-cli." + $version + ".nupkg" +$uri = "https://github.com/bitwarden/cli/releases/download/v" + $version + "/" + $nupkg; +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +Invoke-RestMethod -Uri $uri -OutFile $($distChocoDir + "\" + $nupkg) + +cd $distChocoDir +choco push +cd $rootDir diff --git a/apps/cli/scripts/snap-build.ps1 b/apps/cli/scripts/snap-build.ps1 new file mode 100644 index 0000000000..dfae76682d --- /dev/null +++ b/apps/cli/scripts/snap-build.ps1 @@ -0,0 +1,32 @@ +param ( + [Parameter(Mandatory=$true)] + [string] $version +) + +# Dependencies: +# 1. Install powershell, ex `sudo apt-get install -y powershell` +# +# To run: +# ./snap-build.ps1 -version 1.1.0 +# +# and then push to snap with: +# cd ../dist/snap +# snap push bw*.snap +# or, use the ./snap-update.ps1 script + +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path +$rootDir = $dir + "/.." +$distDir = $rootDir + "/dist" +$snapDir = $rootDir + "/stores/snap" +$distSnapDir = $distDir + "/snap" +$snapDistYaml = $distSnapDir + "/snapcraft.yaml" + +if(Test-Path -Path $distSnapDir) { + Remove-Item -Recurse -Force $distSnapDir +} + +Copy-Item -Path $snapDir -Destination $distSnapDir –Recurse +(Get-Content $snapDistYaml).replace('__version__', $version) | Set-Content $snapDistYaml +cd $distSnapDir +snapcraft +cd $rootDir diff --git a/apps/cli/scripts/snap-update.ps1 b/apps/cli/scripts/snap-update.ps1 new file mode 100644 index 0000000000..7c68284579 --- /dev/null +++ b/apps/cli/scripts/snap-update.ps1 @@ -0,0 +1,12 @@ +# Dependencies: +# 1. Install powershell, ex `sudo apt-get install -y powershell` +# +# To run: +# pwsh ./snap-update.ps1 + +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path; +$rootDir = $dir + "/.."; +$distDir = $rootDir + "/dist"; +$distSnap = $distDir + "/snap/bw*.snap"; + +snapcraft push $distSnap --release stable diff --git a/apps/cli/spec/bw.spec.ts b/apps/cli/spec/bw.spec.ts new file mode 100644 index 0000000000..9ce5fc2cd1 --- /dev/null +++ b/apps/cli/spec/bw.spec.ts @@ -0,0 +1,3 @@ +describe("bw", () => { + test.todo("is a placeholder test"); +}); diff --git a/apps/cli/spec/test.ts b/apps/cli/spec/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/cli/spec/utils.spec.ts b/apps/cli/spec/utils.spec.ts new file mode 100644 index 0000000000..c7d47075ef --- /dev/null +++ b/apps/cli/spec/utils.spec.ts @@ -0,0 +1,27 @@ +import { FlagName } from "../src/flags"; +import { CliUtils } from "../src/utils"; +describe("flagEnabled", () => { + it("is true if flag is null", () => { + process.env.FLAGS = JSON.stringify({ test: null }); + + expect(CliUtils.flagEnabled("test" as FlagName)).toBe(true); + }); + + it("is true if flag is undefined", () => { + process.env.FLAGS = JSON.stringify({}); + + expect(CliUtils.flagEnabled("test" as FlagName)).toBe(true); + }); + + it("is true if flag is true", () => { + process.env.FLAGS = JSON.stringify({ test: true }); + + expect(CliUtils.flagEnabled("test" as FlagName)).toBe(true); + }); + + it("is false if flag is false", () => { + process.env.FLAGS = JSON.stringify({ test: false }); + + expect(CliUtils.flagEnabled("test" as FlagName)).toBe(false); + }); +}); diff --git a/apps/cli/src/bw.ts b/apps/cli/src/bw.ts new file mode 100644 index 0000000000..7006a18d21 --- /dev/null +++ b/apps/cli/src/bw.ts @@ -0,0 +1,381 @@ +import * as fs from "fs"; +import * as path from "path"; + +import * as program from "commander"; +import * as jsdom from "jsdom"; + +import { ClientType } from "jslib-common/enums/clientType"; +import { KeySuffixOptions } from "jslib-common/enums/keySuffixOptions"; +import { LogLevelType } from "jslib-common/enums/logLevelType"; +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { Account } from "jslib-common/models/domain/account"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { AppIdService } from "jslib-common/services/appId.service"; +import { AuditService } from "jslib-common/services/audit.service"; +import { AuthService } from "jslib-common/services/auth.service"; +import { CipherService } from "jslib-common/services/cipher.service"; +import { CollectionService } from "jslib-common/services/collection.service"; +import { ContainerService } from "jslib-common/services/container.service"; +import { CryptoService } from "jslib-common/services/crypto.service"; +import { EnvironmentService } from "jslib-common/services/environment.service"; +import { ExportService } from "jslib-common/services/export.service"; +import { FileUploadService } from "jslib-common/services/fileUpload.service"; +import { FolderService } from "jslib-common/services/folder.service"; +import { ImportService } from "jslib-common/services/import.service"; +import { KeyConnectorService } from "jslib-common/services/keyConnector.service"; +import { NoopMessagingService } from "jslib-common/services/noopMessaging.service"; +import { OrganizationService } from "jslib-common/services/organization.service"; +import { PasswordGenerationService } from "jslib-common/services/passwordGeneration.service"; +import { PolicyService } from "jslib-common/services/policy.service"; +import { ProviderService } from "jslib-common/services/provider.service"; +import { SearchService } from "jslib-common/services/search.service"; +import { SendService } from "jslib-common/services/send.service"; +import { SettingsService } from "jslib-common/services/settings.service"; +import { StateService } from "jslib-common/services/state.service"; +import { StateMigrationService } from "jslib-common/services/stateMigration.service"; +import { SyncService } from "jslib-common/services/sync.service"; +import { TokenService } from "jslib-common/services/token.service"; +import { TotpService } from "jslib-common/services/totp.service"; +import { TwoFactorService } from "jslib-common/services/twoFactor.service"; +import { UserVerificationService } from "jslib-common/services/userVerification.service"; +import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; +import { CliPlatformUtilsService } from "jslib-node/cli/services/cliPlatformUtils.service"; +import { ConsoleLogService } from "jslib-node/cli/services/consoleLog.service"; +import { NodeApiService } from "jslib-node/services/nodeApi.service"; +import { NodeCryptoFunctionService } from "jslib-node/services/nodeCryptoFunction.service"; + +import { Program } from "./program"; +import { SendProgram } from "./send.program"; +import { I18nService } from "./services/i18n.service"; +import { LowdbStorageService } from "./services/lowdbStorage.service"; +import { NodeEnvSecureStorageService } from "./services/nodeEnvSecureStorage.service"; +import { VaultProgram } from "./vault.program"; + +// Polyfills +(global as any).DOMParser = new jsdom.JSDOM().window.DOMParser; + +// eslint-disable-next-line +const packageJson = require("../package.json"); + +export class Main { + messagingService: NoopMessagingService; + storageService: LowdbStorageService; + secureStorageService: NodeEnvSecureStorageService; + i18nService: I18nService; + platformUtilsService: CliPlatformUtilsService; + cryptoService: CryptoService; + tokenService: TokenService; + appIdService: AppIdService; + apiService: NodeApiService; + environmentService: EnvironmentService; + settingsService: SettingsService; + cipherService: CipherService; + folderService: FolderService; + collectionService: CollectionService; + vaultTimeoutService: VaultTimeoutService; + syncService: SyncService; + passwordGenerationService: PasswordGenerationService; + totpService: TotpService; + containerService: ContainerService; + auditService: AuditService; + importService: ImportService; + exportService: ExportService; + searchService: SearchService; + cryptoFunctionService: NodeCryptoFunctionService; + authService: AuthService; + policyService: PolicyService; + program: Program; + vaultProgram: VaultProgram; + sendProgram: SendProgram; + logService: ConsoleLogService; + sendService: SendService; + fileUploadService: FileUploadService; + keyConnectorService: KeyConnectorService; + userVerificationService: UserVerificationService; + stateService: StateService; + stateMigrationService: StateMigrationService; + organizationService: OrganizationService; + providerService: ProviderService; + twoFactorService: TwoFactorService; + + constructor() { + let p = null; + const relativeDataDir = path.join(path.dirname(process.execPath), "bw-data"); + if (fs.existsSync(relativeDataDir)) { + p = relativeDataDir; + } else if (process.env.BITWARDENCLI_APPDATA_DIR) { + p = path.resolve(process.env.BITWARDENCLI_APPDATA_DIR); + } else if (process.platform === "darwin") { + p = path.join(process.env.HOME, "Library/Application Support/Bitwarden CLI"); + } else if (process.platform === "win32") { + p = path.join(process.env.APPDATA, "Bitwarden CLI"); + } else if (process.env.XDG_CONFIG_HOME) { + p = path.join(process.env.XDG_CONFIG_HOME, "Bitwarden CLI"); + } else { + p = path.join(process.env.HOME, ".config/Bitwarden CLI"); + } + + this.i18nService = new I18nService("en", "./locales"); + this.platformUtilsService = new CliPlatformUtilsService(ClientType.Cli, packageJson); + this.logService = new ConsoleLogService( + this.platformUtilsService.isDev(), + (level) => process.env.BITWARDENCLI_DEBUG !== "true" && level <= LogLevelType.Info + ); + this.cryptoFunctionService = new NodeCryptoFunctionService(); + this.storageService = new LowdbStorageService(this.logService, null, p, false, true); + this.secureStorageService = new NodeEnvSecureStorageService( + this.storageService, + this.logService, + () => this.cryptoService + ); + + this.stateMigrationService = new StateMigrationService( + this.storageService, + this.secureStorageService, + new StateFactory(GlobalState, Account) + ); + + this.stateService = new StateService( + this.storageService, + this.secureStorageService, + this.logService, + this.stateMigrationService, + new StateFactory(GlobalState, Account) + ); + + this.cryptoService = new CryptoService( + this.cryptoFunctionService, + this.platformUtilsService, + this.logService, + this.stateService + ); + + this.appIdService = new AppIdService(this.storageService); + this.tokenService = new TokenService(this.stateService); + this.messagingService = new NoopMessagingService(); + this.environmentService = new EnvironmentService(this.stateService); + + const customUserAgent = + "Bitwarden_CLI/" + + this.platformUtilsService.getApplicationVersionSync() + + " (" + + this.platformUtilsService.getDeviceString().toUpperCase() + + ")"; + this.apiService = new NodeApiService( + this.tokenService, + this.platformUtilsService, + this.environmentService, + this.appIdService, + async (expired: boolean) => await this.logout(), + customUserAgent + ); + this.containerService = new ContainerService(this.cryptoService); + + this.settingsService = new SettingsService(this.stateService); + + this.fileUploadService = new FileUploadService(this.logService, this.apiService); + + this.cipherService = new CipherService( + this.cryptoService, + this.settingsService, + this.apiService, + this.fileUploadService, + this.i18nService, + null, + this.logService, + this.stateService + ); + + this.folderService = new FolderService( + this.cryptoService, + this.apiService, + this.i18nService, + this.cipherService, + this.stateService + ); + + this.collectionService = new CollectionService( + this.cryptoService, + this.i18nService, + this.stateService + ); + + this.searchService = new SearchService(this.cipherService, this.logService, this.i18nService); + + this.providerService = new ProviderService(this.stateService); + + this.organizationService = new OrganizationService(this.stateService); + + this.policyService = new PolicyService( + this.stateService, + this.organizationService, + this.apiService + ); + + this.sendService = new SendService( + this.cryptoService, + this.apiService, + this.fileUploadService, + this.i18nService, + this.cryptoFunctionService, + this.stateService + ); + + this.keyConnectorService = new KeyConnectorService( + this.stateService, + this.cryptoService, + this.apiService, + this.tokenService, + this.logService, + this.organizationService, + this.cryptoFunctionService, + async (expired: boolean) => await this.logout() + ); + + this.twoFactorService = new TwoFactorService(this.i18nService, this.platformUtilsService); + + this.authService = new AuthService( + this.cryptoService, + this.apiService, + this.tokenService, + this.appIdService, + this.platformUtilsService, + this.messagingService, + this.logService, + this.keyConnectorService, + this.environmentService, + this.stateService, + this.twoFactorService, + this.i18nService + ); + + const lockedCallback = async () => + await this.cryptoService.clearStoredKey(KeySuffixOptions.Auto); + + this.vaultTimeoutService = new VaultTimeoutService( + this.cipherService, + this.folderService, + this.collectionService, + this.cryptoService, + this.platformUtilsService, + this.messagingService, + this.searchService, + this.tokenService, + this.policyService, + this.keyConnectorService, + this.stateService, + this.authService, + lockedCallback, + null + ); + + this.syncService = new SyncService( + this.apiService, + this.settingsService, + this.folderService, + this.cipherService, + this.cryptoService, + this.collectionService, + this.messagingService, + this.policyService, + this.sendService, + this.logService, + this.keyConnectorService, + this.stateService, + this.organizationService, + this.providerService, + async (expired: boolean) => await this.logout() + ); + + this.passwordGenerationService = new PasswordGenerationService( + this.cryptoService, + this.policyService, + this.stateService + ); + + this.totpService = new TotpService( + this.cryptoFunctionService, + this.logService, + this.stateService + ); + + this.importService = new ImportService( + this.cipherService, + this.folderService, + this.apiService, + this.i18nService, + this.collectionService, + this.platformUtilsService, + this.cryptoService + ); + this.exportService = new ExportService( + this.folderService, + this.cipherService, + this.apiService, + this.cryptoService, + this.cryptoFunctionService + ); + + this.auditService = new AuditService(this.cryptoFunctionService, this.apiService); + this.program = new Program(this); + this.vaultProgram = new VaultProgram(this); + this.sendProgram = new SendProgram(this); + this.userVerificationService = new UserVerificationService( + this.cryptoService, + this.i18nService, + this.apiService + ); + } + + async run() { + await this.init(); + + await this.program.register(); + await this.vaultProgram.register(); + await this.sendProgram.register(); + + program.parse(process.argv); + + if (process.argv.slice(2).length === 0) { + program.outputHelp(); + } + } + + async logout() { + this.authService.logOut(() => { + /* Do nothing */ + }); + const userId = await this.stateService.getUserId(); + await Promise.all([ + this.syncService.setLastSync(new Date(0)), + this.cryptoService.clearKeys(), + this.settingsService.clear(userId), + this.cipherService.clear(userId), + this.folderService.clear(userId), + this.collectionService.clear(userId), + this.policyService.clear(userId), + this.passwordGenerationService.clear(), + ]); + await this.stateService.clean(); + process.env.BW_SESSION = null; + } + + private async init() { + await this.storageService.init(); + await this.stateService.init(); + this.containerService.attachToWindow(global); + await this.environmentService.setUrlsFromStorage(); + const locale = await this.stateService.getLocale(); + await this.i18nService.init(locale); + this.twoFactorService.init(); + + const installedVersion = await this.stateService.getInstalledVersion(); + const currentVersion = await this.platformUtilsService.getApplicationVersion(); + if (installedVersion == null || installedVersion !== currentVersion) { + await this.stateService.setInstalledVersion(currentVersion); + } + } +} + +const main = new Main(); +main.run(); diff --git a/apps/cli/src/commands/completion.command.ts b/apps/cli/src/commands/completion.command.ts new file mode 100644 index 0000000000..2deaef4903 --- /dev/null +++ b/apps/cli/src/commands/completion.command.ts @@ -0,0 +1,119 @@ +import * as program from "commander"; + +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +interface IOption { + long?: string; + short?: string; + description: string; +} + +interface ICommand { + commands?: ICommand[]; + options?: IOption[]; + _name: string; + _description: string; +} + +const validShells = ["zsh"]; + +export class CompletionCommand { + async run(options: program.OptionValues) { + const shell: typeof validShells[number] = options.shell; + + if (!shell) { + return Response.badRequest("`shell` option was not provided."); + } + + if (!validShells.includes(shell)) { + return Response.badRequest("Unsupported shell."); + } + + let content = ""; + + if (shell === "zsh") { + content = this.zshCompletion("bw", program as any as ICommand).render(); + } + + const res = new MessageResponse(content, null); + return Response.success(res); + } + + private zshCompletion(rootName: string, rootCommand: ICommand) { + return { + render: () => { + return [ + `#compdef _${rootName} ${rootName}`, + "", + this.renderCommandBlock(rootName, rootCommand), + ].join("\n"); + }, + }; + } + + private renderCommandBlock(name: string, command: ICommand): string { + const { commands = [], options = [] } = command; + const hasOptions = options.length > 0; + const hasCommands = commands.length > 0; + + const args = options + .map(({ long, short, description }) => { + const aliases = [short, long].filter(Boolean); + const opts = aliases.join(","); + const desc = `[${description.replace(`'`, `'"'"'`)}]`; + return aliases.length > 1 + ? `'(${aliases.join(" ")})'{${opts}}'${desc}'` + : `'${opts}${desc}'`; + }) + .concat( + `'(-h --help)'{-h,--help}'[output usage information]'`, + hasCommands ? '"1: :->cmnds"' : null, + '"*::arg:->args"' + ) + .filter(Boolean); + + const commandBlockFunctionParts = []; + + if (hasCommands) { + commandBlockFunctionParts.push("local -a commands"); + } + + if (hasOptions) { + commandBlockFunctionParts.push(`_arguments -C \\\n ${args.join(` \\\n `)}`); + } + + if (hasCommands) { + commandBlockFunctionParts.push( + `case $state in + cmnds) + commands=( + ${commands + .map(({ _name, _description }) => `"${_name}:${_description}"`) + .join("\n ")} + ) + _describe "command" commands + ;; + esac + + case "$words[1]" in + ${commands + .map(({ _name }) => [`${_name})`, `_${name}_${_name}`, ";;"].join("\n ")) + .join("\n ")} + esac` + ); + } + + const commandBlocParts = [ + `function _${name} {\n ${commandBlockFunctionParts.join("\n\n ")}\n}`, + ]; + + if (hasCommands) { + commandBlocParts.push( + commands.map((c) => this.renderCommandBlock(`${name}_${c._name}`, c)).join("\n\n") + ); + } + + return commandBlocParts.join("\n\n"); + } +} diff --git a/apps/cli/src/commands/config.command.ts b/apps/cli/src/commands/config.command.ts new file mode 100644 index 0000000000..89fc81296f --- /dev/null +++ b/apps/cli/src/commands/config.command.ts @@ -0,0 +1,53 @@ +import * as program from "commander"; + +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; +import { StringResponse } from "jslib-node/cli/models/response/stringResponse"; + +export class ConfigCommand { + constructor(private environmentService: EnvironmentService) {} + + async run(setting: string, value: string, options: program.OptionValues): Promise { + setting = setting.toLowerCase(); + switch (setting) { + case "server": + return await this.getOrSetServer(value, options); + default: + return Response.badRequest("Unknown setting."); + } + } + + private async getOrSetServer(url: string, options: program.OptionValues): Promise { + if ( + (url == null || url.trim() === "") && + !options.webVault && + !options.api && + !options.identity && + !options.icons && + !options.notifications && + !options.events + ) { + const stringRes = new StringResponse( + this.environmentService.hasBaseUrl() + ? this.environmentService.getUrls().base + : "https://bitwarden.com" + ); + return Response.success(stringRes); + } + + url = url === "null" || url === "bitwarden.com" || url === "https://bitwarden.com" ? null : url; + await this.environmentService.setUrls({ + base: url, + webVault: options.webVault || null, + api: options.api || null, + identity: options.identity || null, + icons: options.icons || null, + notifications: options.notifications || null, + events: options.events || null, + keyConnector: options.keyConnector || null, + }); + const res = new MessageResponse("Saved setting `config`.", null); + return Response.success(res); + } +} diff --git a/apps/cli/src/commands/confirm.command.ts b/apps/cli/src/commands/confirm.command.ts new file mode 100644 index 0000000000..68c203be5c --- /dev/null +++ b/apps/cli/src/commands/confirm.command.ts @@ -0,0 +1,62 @@ +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { Utils } from "jslib-common/misc/utils"; +import { OrganizationUserConfirmRequest } from "jslib-common/models/request/organizationUserConfirmRequest"; +import { Response } from "jslib-node/cli/models/response"; + +export class ConfirmCommand { + constructor(private apiService: ApiService, private cryptoService: CryptoService) {} + + async run(object: string, id: string, cmdOptions: Record): Promise { + if (id != null) { + id = id.toLowerCase(); + } + + const normalizedOptions = new Options(cmdOptions); + switch (object.toLowerCase()) { + case "org-member": + return await this.confirmOrganizationMember(id, normalizedOptions); + default: + return Response.badRequest("Unknown object."); + } + } + + private async confirmOrganizationMember(id: string, options: Options) { + if (options.organizationId == null || options.organizationId === "") { + return Response.badRequest("--organizationid required."); + } + if (!Utils.isGuid(id)) { + return Response.badRequest("`" + id + "` is not a GUID."); + } + if (!Utils.isGuid(options.organizationId)) { + return Response.badRequest("`" + options.organizationId + "` is not a GUID."); + } + try { + const orgKey = await this.cryptoService.getOrgKey(options.organizationId); + if (orgKey == null) { + throw new Error("No encryption key for this organization."); + } + const orgUser = await this.apiService.getOrganizationUser(options.organizationId, id); + if (orgUser == null) { + throw new Error("Member id does not exist for this organization."); + } + const publicKeyResponse = await this.apiService.getUserPublicKey(orgUser.userId); + const publicKey = Utils.fromB64ToArray(publicKeyResponse.publicKey); + const key = await this.cryptoService.rsaEncrypt(orgKey.key, publicKey.buffer); + const req = new OrganizationUserConfirmRequest(); + req.key = key.encryptedString; + await this.apiService.postOrganizationUserConfirm(options.organizationId, id, req); + return Response.success(); + } catch (e) { + return Response.error(e); + } + } +} + +class Options { + organizationId: string; + + constructor(passedOptions: Record) { + this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId; + } +} diff --git a/apps/cli/src/commands/convertToKeyConnector.command.ts b/apps/cli/src/commands/convertToKeyConnector.command.ts new file mode 100644 index 0000000000..7774f79a69 --- /dev/null +++ b/apps/cli/src/commands/convertToKeyConnector.command.ts @@ -0,0 +1,84 @@ +import * as inquirer from "inquirer"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +export class ConvertToKeyConnectorCommand { + constructor( + private apiService: ApiService, + private keyConnectorService: KeyConnectorService, + private environmentService: EnvironmentService, + private syncService: SyncService, + private logout: () => Promise + ) {} + + async run(): Promise { + // If no interaction available, alert user to use web vault + const canInteract = process.env.BW_NOINTERACTION !== "true"; + if (!canInteract) { + await this.logout(); + return Response.error( + new MessageResponse( + "An organization you are a member of is using Key Connector. " + + "In order to access the vault, you must opt-in to Key Connector now via the web vault. You have been logged out.", + null + ) + ); + } + + const organization = await this.keyConnectorService.getManagingOrganization(); + + const answer: inquirer.Answers = await inquirer.createPromptModule({ output: process.stderr })({ + type: "list", + name: "convert", + message: + organization.name + + " is using a self-hosted key server. A master password is no longer required to log in for members of this organization. ", + choices: [ + { + name: "Remove master password and unlock", + value: "remove", + }, + { + name: "Leave organization and unlock", + value: "leave", + }, + { + name: "Log out", + value: "exit", + }, + ], + }); + + if (answer.convert === "remove") { + try { + await this.keyConnectorService.migrateUser(); + } catch (e) { + await this.logout(); + throw e; + } + + await this.keyConnectorService.removeConvertAccountRequired(); + await this.keyConnectorService.setUsesKeyConnector(true); + + // Update environment URL - required for api key login + const urls = this.environmentService.getUrls(); + urls.keyConnector = organization.keyConnectorUrl; + await this.environmentService.setUrls(urls); + + return Response.success(); + } else if (answer.convert === "leave") { + await this.apiService.postLeaveOrganization(organization.id); + await this.keyConnectorService.removeConvertAccountRequired(); + await this.syncService.fullSync(true); + return Response.success(); + } else { + await this.logout(); + return Response.error("You have been logged out."); + } + } +} diff --git a/apps/cli/src/commands/create.command.ts b/apps/cli/src/commands/create.command.ts new file mode 100644 index 0000000000..fa80861654 --- /dev/null +++ b/apps/cli/src/commands/create.command.ts @@ -0,0 +1,206 @@ +import * as fs from "fs"; +import * as path from "path"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; +import { CipherExport } from "jslib-common/models/export/cipherExport"; +import { CollectionExport } from "jslib-common/models/export/collectionExport"; +import { FolderExport } from "jslib-common/models/export/folderExport"; +import { CollectionRequest } from "jslib-common/models/request/collectionRequest"; +import { SelectionReadOnlyRequest } from "jslib-common/models/request/selectionReadOnlyRequest"; +import { Response } from "jslib-node/cli/models/response"; + +import { OrganizationCollectionRequest } from "../models/request/organizationCollectionRequest"; +import { CipherResponse } from "../models/response/cipherResponse"; +import { FolderResponse } from "../models/response/folderResponse"; +import { OrganizationCollectionResponse } from "../models/response/organizationCollectionResponse"; +import { CliUtils } from "../utils"; + +export class CreateCommand { + constructor( + private cipherService: CipherService, + private folderService: FolderService, + private stateService: StateService, + private cryptoService: CryptoService, + private apiService: ApiService + ) {} + + async run( + object: string, + requestJson: string, + cmdOptions: Record, + additionalData: any = null + ): Promise { + let req: any = null; + if (object !== "attachment") { + if (process.env.BW_SERVE !== "true" && (requestJson == null || requestJson === "")) { + requestJson = await CliUtils.readStdin(); + } + + if (requestJson == null || requestJson === "") { + return Response.badRequest("`requestJson` was not provided."); + } + + if (typeof requestJson !== "string") { + req = requestJson; + } else { + try { + const reqJson = Buffer.from(requestJson, "base64").toString(); + req = JSON.parse(reqJson); + } catch (e) { + return Response.badRequest("Error parsing the encoded request data."); + } + } + } + + const normalizedOptions = new Options(cmdOptions); + switch (object.toLowerCase()) { + case "item": + return await this.createCipher(req); + case "attachment": + return await this.createAttachment(normalizedOptions, additionalData); + case "folder": + return await this.createFolder(req); + case "org-collection": + return await this.createOrganizationCollection(req, normalizedOptions); + default: + return Response.badRequest("Unknown object."); + } + } + + private async createCipher(req: CipherExport) { + const cipher = await this.cipherService.encrypt(CipherExport.toView(req)); + try { + await this.cipherService.saveWithServer(cipher); + const newCipher = await this.cipherService.get(cipher.id); + const decCipher = await newCipher.decrypt(); + const res = new CipherResponse(decCipher); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async createAttachment(options: Options, additionalData: any) { + if (options.itemId == null || options.itemId === "") { + return Response.badRequest("`itemid` option is required."); + } + let fileBuf: Buffer = null; + let fileName: string = null; + if (process.env.BW_SERVE === "true") { + fileBuf = additionalData.fileBuffer; + fileName = additionalData.fileName; + } else { + if (options.file == null || options.file === "") { + return Response.badRequest("`file` option is required."); + } + const filePath = path.resolve(options.file); + if (!fs.existsSync(options.file)) { + return Response.badRequest("Cannot find file at " + filePath); + } + fileBuf = fs.readFileSync(filePath); + fileName = path.basename(filePath); + } + + if (fileBuf == null) { + return Response.badRequest("File not provided."); + } + if (fileName == null || fileName.trim() === "") { + return Response.badRequest("File name not provided."); + } + + const itemId = options.itemId.toLowerCase(); + const cipher = await this.cipherService.get(itemId); + if (cipher == null) { + return Response.notFound(); + } + + if (cipher.organizationId == null && !(await this.stateService.getCanAccessPremium())) { + return Response.error("Premium status is required to use this feature."); + } + + const encKey = await this.cryptoService.getEncKey(); + if (encKey == null) { + return Response.error( + "You must update your encryption key before you can use this feature. " + + "See https://help.bitwarden.com/article/update-encryption-key/" + ); + } + + try { + await this.cipherService.saveAttachmentRawWithServer( + cipher, + fileName, + new Uint8Array(fileBuf).buffer + ); + const updatedCipher = await this.cipherService.get(cipher.id); + const decCipher = await updatedCipher.decrypt(); + return Response.success(new CipherResponse(decCipher)); + } catch (e) { + return Response.error(e); + } + } + + private async createFolder(req: FolderExport) { + const folder = await this.folderService.encrypt(FolderExport.toView(req)); + try { + await this.folderService.saveWithServer(folder); + const newFolder = await this.folderService.get(folder.id); + const decFolder = await newFolder.decrypt(); + const res = new FolderResponse(decFolder); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async createOrganizationCollection(req: OrganizationCollectionRequest, options: Options) { + if (options.organizationId == null || options.organizationId === "") { + return Response.badRequest("`organizationid` option is required."); + } + if (!Utils.isGuid(options.organizationId)) { + return Response.badRequest("`" + options.organizationId + "` is not a GUID."); + } + if (options.organizationId !== req.organizationId) { + return Response.badRequest("`organizationid` option does not match request object."); + } + try { + const orgKey = await this.cryptoService.getOrgKey(req.organizationId); + if (orgKey == null) { + throw new Error("No encryption key for this organization."); + } + + const groups = + req.groups == null + ? null + : req.groups.map((g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords)); + const request = new CollectionRequest(); + request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; + request.externalId = req.externalId; + request.groups = groups; + const response = await this.apiService.postCollection(req.organizationId, request); + const view = CollectionExport.toView(req); + view.id = response.id; + const res = new OrganizationCollectionResponse(view, groups); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } +} + +class Options { + itemId: string; + organizationId: string; + file: string; + + constructor(passedOptions: Record) { + this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId; + this.itemId = passedOptions?.itemid || passedOptions?.itemId; + this.file = passedOptions?.file; + } +} diff --git a/apps/cli/src/commands/delete.command.ts b/apps/cli/src/commands/delete.command.ts new file mode 100644 index 0000000000..7fee0d485e --- /dev/null +++ b/apps/cli/src/commands/delete.command.ts @@ -0,0 +1,131 @@ +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; +import { Response } from "jslib-node/cli/models/response"; + +import { CliUtils } from "src/utils"; + +export class DeleteCommand { + constructor( + private cipherService: CipherService, + private folderService: FolderService, + private stateService: StateService, + private apiService: ApiService + ) {} + + async run(object: string, id: string, cmdOptions: Record): Promise { + if (id != null) { + id = id.toLowerCase(); + } + + const normalizedOptions = new Options(cmdOptions); + switch (object.toLowerCase()) { + case "item": + return await this.deleteCipher(id, normalizedOptions); + case "attachment": + return await this.deleteAttachment(id, normalizedOptions); + case "folder": + return await this.deleteFolder(id); + case "org-collection": + return await this.deleteOrganizationCollection(id, normalizedOptions); + default: + return Response.badRequest("Unknown object."); + } + } + + private async deleteCipher(id: string, options: Options) { + const cipher = await this.cipherService.get(id); + if (cipher == null) { + return Response.notFound(); + } + + try { + if (options.permanent) { + await this.cipherService.deleteWithServer(id); + } else { + await this.cipherService.softDeleteWithServer(id); + } + return Response.success(); + } catch (e) { + return Response.error(e); + } + } + + private async deleteAttachment(id: string, options: Options) { + if (options.itemId == null || options.itemId === "") { + return Response.badRequest("`itemid` option is required."); + } + + const itemId = options.itemId.toLowerCase(); + const cipher = await this.cipherService.get(itemId); + if (cipher == null) { + return Response.notFound(); + } + + if (cipher.attachments == null || cipher.attachments.length === 0) { + return Response.error("No attachments available for this item."); + } + + const attachments = cipher.attachments.filter((a) => a.id.toLowerCase() === id); + if (attachments.length === 0) { + return Response.error("Attachment `" + id + "` was not found."); + } + + if (cipher.organizationId == null && !(await this.stateService.getCanAccessPremium())) { + return Response.error("Premium status is required to use this feature."); + } + + try { + await this.cipherService.deleteAttachmentWithServer(cipher.id, attachments[0].id); + return Response.success(); + } catch (e) { + return Response.error(e); + } + } + + private async deleteFolder(id: string) { + const folder = await this.folderService.get(id); + if (folder == null) { + return Response.notFound(); + } + + try { + await this.folderService.deleteWithServer(id); + return Response.success(); + } catch (e) { + return Response.error(e); + } + } + + private async deleteOrganizationCollection(id: string, options: Options) { + if (options.organizationId == null || options.organizationId === "") { + return Response.badRequest("`organizationid` options is required."); + } + if (!Utils.isGuid(id)) { + return Response.badRequest("`" + id + "` is not a GUID."); + } + if (!Utils.isGuid(options.organizationId)) { + return Response.badRequest("`" + options.organizationId + "` is not a GUID."); + } + try { + await this.apiService.deleteCollection(options.organizationId, id); + return Response.success(); + } catch (e) { + return Response.error(e); + } + } +} + +class Options { + itemId: string; + organizationId: string; + permanent: boolean; + + constructor(passedOptions: Record) { + this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId; + this.itemId = passedOptions?.itemid || passedOptions?.itemId; + this.permanent = CliUtils.convertBooleanOption(passedOptions?.permanent); + } +} diff --git a/apps/cli/src/commands/download.command.ts b/apps/cli/src/commands/download.command.ts new file mode 100644 index 0000000000..bf3773a16d --- /dev/null +++ b/apps/cli/src/commands/download.command.ts @@ -0,0 +1,43 @@ +import * as fet from "node-fetch"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { Response } from "jslib-node/cli/models/response"; +import { FileResponse } from "jslib-node/cli/models/response/fileResponse"; + +import { CliUtils } from "../utils"; + +export abstract class DownloadCommand { + constructor(protected cryptoService: CryptoService) {} + + protected async saveAttachmentToFile( + url: string, + key: SymmetricCryptoKey, + fileName: string, + output?: string + ) { + const response = await fet.default(new fet.Request(url, { headers: { cache: "no-cache" } })); + if (response.status !== 200) { + return Response.error( + "A " + response.status + " error occurred while downloading the attachment." + ); + } + + try { + const buf = await response.arrayBuffer(); + const decBuf = await this.cryptoService.decryptFromBytes(buf, key); + if (process.env.BW_SERVE === "true") { + const res = new FileResponse(Buffer.from(decBuf), fileName); + return Response.success(res); + } else { + return await CliUtils.saveResultToFile(Buffer.from(decBuf), output, fileName); + } + } catch (e) { + if (typeof e === "string") { + return Response.error(e); + } else { + return Response.error("An error occurred while saving the attachment."); + } + } + } +} diff --git a/apps/cli/src/commands/edit.command.ts b/apps/cli/src/commands/edit.command.ts new file mode 100644 index 0000000000..17b1c4b58b --- /dev/null +++ b/apps/cli/src/commands/edit.command.ts @@ -0,0 +1,186 @@ +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { Utils } from "jslib-common/misc/utils"; +import { CipherExport } from "jslib-common/models/export/cipherExport"; +import { CollectionExport } from "jslib-common/models/export/collectionExport"; +import { FolderExport } from "jslib-common/models/export/folderExport"; +import { CollectionRequest } from "jslib-common/models/request/collectionRequest"; +import { SelectionReadOnlyRequest } from "jslib-common/models/request/selectionReadOnlyRequest"; +import { Response } from "jslib-node/cli/models/response"; + +import { OrganizationCollectionRequest } from "../models/request/organizationCollectionRequest"; +import { CipherResponse } from "../models/response/cipherResponse"; +import { FolderResponse } from "../models/response/folderResponse"; +import { OrganizationCollectionResponse } from "../models/response/organizationCollectionResponse"; +import { CliUtils } from "../utils"; + +export class EditCommand { + constructor( + private cipherService: CipherService, + private folderService: FolderService, + private cryptoService: CryptoService, + private apiService: ApiService + ) {} + + async run( + object: string, + id: string, + requestJson: any, + cmdOptions: Record + ): Promise { + if (process.env.BW_SERVE !== "true" && (requestJson == null || requestJson === "")) { + requestJson = await CliUtils.readStdin(); + } + + if (requestJson == null || requestJson === "") { + return Response.badRequest("`requestJson` was not provided."); + } + + let req: any = null; + if (typeof requestJson !== "string") { + req = requestJson; + } else { + try { + const reqJson = Buffer.from(requestJson, "base64").toString(); + req = JSON.parse(reqJson); + } catch (e) { + return Response.badRequest("Error parsing the encoded request data."); + } + } + + if (id != null) { + id = id.toLowerCase(); + } + + const normalizedOptions = new Options(cmdOptions); + switch (object.toLowerCase()) { + case "item": + return await this.editCipher(id, req); + case "item-collections": + return await this.editCipherCollections(id, req); + case "folder": + return await this.editFolder(id, req); + case "org-collection": + return await this.editOrganizationCollection(id, req, normalizedOptions); + default: + return Response.badRequest("Unknown object."); + } + } + + private async editCipher(id: string, req: CipherExport) { + const cipher = await this.cipherService.get(id); + if (cipher == null) { + return Response.notFound(); + } + + let cipherView = await cipher.decrypt(); + if (cipherView.isDeleted) { + return Response.badRequest("You may not edit a deleted item. Use the restore command first."); + } + cipherView = CipherExport.toView(req, cipherView); + const encCipher = await this.cipherService.encrypt(cipherView); + try { + await this.cipherService.saveWithServer(encCipher); + const updatedCipher = await this.cipherService.get(cipher.id); + const decCipher = await updatedCipher.decrypt(); + const res = new CipherResponse(decCipher); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async editCipherCollections(id: string, req: string[]) { + const cipher = await this.cipherService.get(id); + if (cipher == null) { + return Response.notFound(); + } + if (cipher.organizationId == null) { + return Response.badRequest( + "Item does not belong to an organization. Consider moving it first." + ); + } + + cipher.collectionIds = req; + try { + await this.cipherService.saveCollectionsWithServer(cipher); + const updatedCipher = await this.cipherService.get(cipher.id); + const decCipher = await updatedCipher.decrypt(); + const res = new CipherResponse(decCipher); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async editFolder(id: string, req: FolderExport) { + const folder = await this.folderService.get(id); + if (folder == null) { + return Response.notFound(); + } + + let folderView = await folder.decrypt(); + folderView = FolderExport.toView(req, folderView); + const encFolder = await this.folderService.encrypt(folderView); + try { + await this.folderService.saveWithServer(encFolder); + const updatedFolder = await this.folderService.get(folder.id); + const decFolder = await updatedFolder.decrypt(); + const res = new FolderResponse(decFolder); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async editOrganizationCollection( + id: string, + req: OrganizationCollectionRequest, + options: Options + ) { + if (options.organizationId == null || options.organizationId === "") { + return Response.badRequest("`organizationid` option is required."); + } + if (!Utils.isGuid(id)) { + return Response.badRequest("`" + id + "` is not a GUID."); + } + if (!Utils.isGuid(options.organizationId)) { + return Response.badRequest("`" + options.organizationId + "` is not a GUID."); + } + if (options.organizationId !== req.organizationId) { + return Response.badRequest("`organizationid` option does not match request object."); + } + try { + const orgKey = await this.cryptoService.getOrgKey(req.organizationId); + if (orgKey == null) { + throw new Error("No encryption key for this organization."); + } + + const groups = + req.groups == null + ? null + : req.groups.map((g) => new SelectionReadOnlyRequest(g.id, g.readOnly, g.hidePasswords)); + const request = new CollectionRequest(); + request.name = (await this.cryptoService.encrypt(req.name, orgKey)).encryptedString; + request.externalId = req.externalId; + request.groups = groups; + const response = await this.apiService.putCollection(req.organizationId, id, request); + const view = CollectionExport.toView(req); + view.id = response.id; + const res = new OrganizationCollectionResponse(view, groups); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } +} + +class Options { + organizationId: string; + + constructor(passedOptions: Record) { + this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId; + } +} diff --git a/apps/cli/src/commands/encode.command.ts b/apps/cli/src/commands/encode.command.ts new file mode 100644 index 0000000000..c7de9a11b3 --- /dev/null +++ b/apps/cli/src/commands/encode.command.ts @@ -0,0 +1,16 @@ +import { Response } from "jslib-node/cli/models/response"; +import { StringResponse } from "jslib-node/cli/models/response/stringResponse"; + +import { CliUtils } from "../utils"; + +export class EncodeCommand { + async run(): Promise { + if (process.stdin.isTTY) { + return Response.badRequest("No stdin was piped in."); + } + const input = await CliUtils.readStdin(); + const b64 = Buffer.from(input, "utf8").toString("base64"); + const res = new StringResponse(b64); + return Response.success(res); + } +} diff --git a/apps/cli/src/commands/export.command.ts b/apps/cli/src/commands/export.command.ts new file mode 100644 index 0000000000..e8ed33423a --- /dev/null +++ b/apps/cli/src/commands/export.command.ts @@ -0,0 +1,97 @@ +import * as program from "commander"; +import * as inquirer from "inquirer"; + +import { ExportFormat, ExportService } from "jslib-common/abstractions/export.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { PolicyType } from "jslib-common/enums/policyType"; +import { Utils } from "jslib-common/misc/utils"; +import { Response } from "jslib-node/cli/models/response"; + +import { CliUtils } from "../utils"; + +export class ExportCommand { + constructor(private exportService: ExportService, private policyService: PolicyService) {} + + async run(options: program.OptionValues): Promise { + if ( + options.organizationid == null && + (await this.policyService.policyAppliesToUser(PolicyType.DisablePersonalVaultExport)) + ) { + return Response.badRequest( + "One or more organization policies prevents you from exporting your personal vault." + ); + } + + const format = options.format ?? "csv"; + + if (options.organizationid != null && !Utils.isGuid(options.organizationid)) { + return Response.error("`" + options.organizationid + "` is not a GUID."); + } + + let exportContent: string = null; + try { + exportContent = + format === "encrypted_json" + ? await this.getProtectedExport(options.password, options.organizationid) + : await this.getUnprotectedExport(format, options.organizationid); + } catch (e) { + return Response.error(e); + } + return await this.saveFile(exportContent, options, format); + } + + private async getProtectedExport(passwordOption: string | boolean, organizationId?: string) { + const password = await this.promptPassword(passwordOption); + return password == null + ? await this.exportService.getExport("encrypted_json", organizationId) + : await this.exportService.getPasswordProtectedExport(password, organizationId); + } + + private async getUnprotectedExport(format: ExportFormat, organizationId?: string) { + return this.exportService.getExport(format, organizationId); + } + + private async saveFile( + exportContent: string, + options: program.OptionValues, + format: ExportFormat + ): Promise { + try { + const fileName = this.getFileName(format, options.organizationid != null ? "org" : null); + return await CliUtils.saveResultToFile(exportContent, options.output, fileName); + } catch (e) { + return Response.error(e.toString()); + } + } + + private getFileName(format: ExportFormat, prefix?: string) { + if (format === "encrypted_json") { + if (prefix == null) { + prefix = "encrypted"; + } else { + prefix = "encrypted_" + prefix; + } + format = "json"; + } + return this.exportService.getFileName(prefix, format); + } + + private async promptPassword(password: string | boolean) { + // boolean => flag set with no value, we need to prompt for password + // string => flag set with value, use this value for password + // undefined/null/false => account protect, not password, no password needed + if (typeof password === "string") { + return password; + } else if (password) { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "password", + name: "password", + message: "Export file password:", + }); + return answer.password as string; + } + return null; + } +} diff --git a/apps/cli/src/commands/generate.command.ts b/apps/cli/src/commands/generate.command.ts new file mode 100644 index 0000000000..d6d0c89819 --- /dev/null +++ b/apps/cli/src/commands/generate.command.ts @@ -0,0 +1,80 @@ +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Response } from "jslib-node/cli/models/response"; +import { StringResponse } from "jslib-node/cli/models/response/stringResponse"; + +import { CliUtils } from "../utils"; + +export class GenerateCommand { + constructor( + private passwordGenerationService: PasswordGenerationService, + private stateService: StateService + ) {} + + async run(cmdOptions: Record): Promise { + const normalizedOptions = new Options(cmdOptions); + const options = { + uppercase: normalizedOptions.uppercase, + lowercase: normalizedOptions.lowercase, + number: normalizedOptions.number, + special: normalizedOptions.special, + length: normalizedOptions.length, + type: normalizedOptions.type, + wordSeparator: normalizedOptions.separator, + numWords: normalizedOptions.words, + capitalize: normalizedOptions.capitalize, + includeNumber: normalizedOptions.includeNumber, + }; + + const enforcedOptions = (await this.stateService.getIsAuthenticated()) + ? (await this.passwordGenerationService.enforcePasswordGeneratorPoliciesOnOptions(options))[0] + : options; + + const password = await this.passwordGenerationService.generatePassword(enforcedOptions); + const res = new StringResponse(password); + return Response.success(res); + } +} + +class Options { + uppercase: boolean; + lowercase: boolean; + number: boolean; + special: boolean; + length: number; + type: "passphrase" | "password"; + separator: string; + words: number; + capitalize: boolean; + includeNumber: boolean; + + constructor(passedOptions: Record) { + this.uppercase = CliUtils.convertBooleanOption(passedOptions?.uppercase); + this.lowercase = CliUtils.convertBooleanOption(passedOptions?.lowercase); + this.number = CliUtils.convertBooleanOption(passedOptions?.number); + this.special = CliUtils.convertBooleanOption(passedOptions?.special); + this.capitalize = CliUtils.convertBooleanOption(passedOptions?.capitalize); + this.includeNumber = CliUtils.convertBooleanOption(passedOptions?.includeNumber); + this.length = passedOptions?.length != null ? parseInt(passedOptions?.length, null) : 14; + this.type = passedOptions?.passphrase ? "passphrase" : "password"; + this.separator = passedOptions?.separator == null ? "-" : passedOptions.separator + ""; + this.words = passedOptions?.words != null ? parseInt(passedOptions.words, null) : 3; + + if (!this.uppercase && !this.lowercase && !this.special && !this.number) { + this.lowercase = true; + this.uppercase = true; + this.number = true; + } + if (this.length < 5) { + this.length = 5; + } + if (this.words < 3) { + this.words = 3; + } + if (this.separator === "space") { + this.separator = " "; + } else if (this.separator != null && this.separator.length > 1) { + this.separator = this.separator[0]; + } + } +} diff --git a/apps/cli/src/commands/get.command.ts b/apps/cli/src/commands/get.command.ts new file mode 100644 index 0000000000..27ad8a99ea --- /dev/null +++ b/apps/cli/src/commands/get.command.ts @@ -0,0 +1,540 @@ +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { SendType } from "jslib-common/enums/sendType"; +import { Utils } from "jslib-common/misc/utils"; +import { EncString } from "jslib-common/models/domain/encString"; +import { Organization } from "jslib-common/models/domain/organization"; +import { CardExport } from "jslib-common/models/export/cardExport"; +import { CipherExport } from "jslib-common/models/export/cipherExport"; +import { CollectionExport } from "jslib-common/models/export/collectionExport"; +import { FieldExport } from "jslib-common/models/export/fieldExport"; +import { FolderExport } from "jslib-common/models/export/folderExport"; +import { IdentityExport } from "jslib-common/models/export/identityExport"; +import { LoginExport } from "jslib-common/models/export/loginExport"; +import { LoginUriExport } from "jslib-common/models/export/loginUriExport"; +import { SecureNoteExport } from "jslib-common/models/export/secureNoteExport"; +import { ErrorResponse } from "jslib-common/models/response/errorResponse"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; +import { Response } from "jslib-node/cli/models/response"; +import { StringResponse } from "jslib-node/cli/models/response/stringResponse"; + +import { OrganizationCollectionRequest } from "../models/request/organizationCollectionRequest"; +import { CipherResponse } from "../models/response/cipherResponse"; +import { CollectionResponse } from "../models/response/collectionResponse"; +import { FolderResponse } from "../models/response/folderResponse"; +import { OrganizationCollectionResponse } from "../models/response/organizationCollectionResponse"; +import { OrganizationResponse } from "../models/response/organizationResponse"; +import { SendResponse } from "../models/response/sendResponse"; +import { TemplateResponse } from "../models/response/templateResponse"; +import { SelectionReadOnly } from "../models/selectionReadOnly"; +import { CliUtils } from "../utils"; + +import { DownloadCommand } from "./download.command"; + +export class GetCommand extends DownloadCommand { + constructor( + private cipherService: CipherService, + private folderService: FolderService, + private collectionService: CollectionService, + private totpService: TotpService, + private auditService: AuditService, + cryptoService: CryptoService, + private stateService: StateService, + private searchService: SearchService, + private apiService: ApiService, + private organizationService: OrganizationService + ) { + super(cryptoService); + } + + async run(object: string, id: string, cmdOptions: Record): Promise { + if (id != null) { + id = id.toLowerCase(); + } + + const normalizedOptions = new Options(cmdOptions); + switch (object.toLowerCase()) { + case "item": + return await this.getCipher(id); + case "username": + return await this.getUsername(id); + case "password": + return await this.getPassword(id); + case "uri": + return await this.getUri(id); + case "totp": + return await this.getTotp(id); + case "notes": + return await this.getNotes(id); + case "exposed": + return await this.getExposed(id); + case "attachment": + return await this.getAttachment(id, normalizedOptions); + case "folder": + return await this.getFolder(id); + case "collection": + return await this.getCollection(id); + case "org-collection": + return await this.getOrganizationCollection(id, normalizedOptions); + case "organization": + return await this.getOrganization(id); + case "template": + return await this.getTemplate(id); + case "fingerprint": + return await this.getFingerprint(id); + default: + return Response.badRequest("Unknown object."); + } + } + + private async getCipherView(id: string): Promise { + let decCipher: CipherView = null; + if (Utils.isGuid(id)) { + const cipher = await this.cipherService.get(id); + if (cipher != null) { + decCipher = await cipher.decrypt(); + } + } else if (id.trim() !== "") { + let ciphers = await this.cipherService.getAllDecrypted(); + ciphers = this.searchService.searchCiphersBasic(ciphers, id); + if (ciphers.length > 1) { + return ciphers; + } + if (ciphers.length > 0) { + decCipher = ciphers[0]; + } + } + + return decCipher; + } + + private async getCipher(id: string, filter?: (c: CipherView) => boolean) { + let decCipher = await this.getCipherView(id); + if (decCipher == null) { + return Response.notFound(); + } + if (Array.isArray(decCipher)) { + if (filter != null) { + decCipher = decCipher.filter(filter); + if (decCipher.length === 1) { + decCipher = decCipher[0]; + } + } + if (Array.isArray(decCipher)) { + return Response.multipleResults(decCipher.map((c) => c.id)); + } + } + const res = new CipherResponse(decCipher); + return Response.success(res); + } + + private async getUsername(id: string) { + const cipherResponse = await this.getCipher( + id, + (c) => c.type === CipherType.Login && !Utils.isNullOrWhitespace(c.login.username) + ); + if (!cipherResponse.success) { + return cipherResponse; + } + + const cipher = cipherResponse.data as CipherResponse; + if (cipher.type !== CipherType.Login) { + return Response.badRequest("Not a login."); + } + + if (Utils.isNullOrWhitespace(cipher.login.username)) { + return Response.error("No username available for this login."); + } + + const res = new StringResponse(cipher.login.username); + return Response.success(res); + } + + private async getPassword(id: string) { + const cipherResponse = await this.getCipher( + id, + (c) => c.type === CipherType.Login && !Utils.isNullOrWhitespace(c.login.password) + ); + if (!cipherResponse.success) { + return cipherResponse; + } + + const cipher = cipherResponse.data as CipherResponse; + if (cipher.type !== CipherType.Login) { + return Response.badRequest("Not a login."); + } + + if (Utils.isNullOrWhitespace(cipher.login.password)) { + return Response.error("No password available for this login."); + } + + const res = new StringResponse(cipher.login.password); + return Response.success(res); + } + + private async getUri(id: string) { + const cipherResponse = await this.getCipher( + id, + (c) => + c.type === CipherType.Login && + c.login.uris != null && + c.login.uris.length > 0 && + c.login.uris[0].uri !== "" + ); + if (!cipherResponse.success) { + return cipherResponse; + } + + const cipher = cipherResponse.data as CipherResponse; + if (cipher.type !== CipherType.Login) { + return Response.badRequest("Not a login."); + } + + if ( + cipher.login.uris == null || + cipher.login.uris.length === 0 || + cipher.login.uris[0].uri === "" + ) { + return Response.error("No uri available for this login."); + } + + const res = new StringResponse(cipher.login.uris[0].uri); + return Response.success(res); + } + + private async getTotp(id: string) { + const cipherResponse = await this.getCipher( + id, + (c) => c.type === CipherType.Login && !Utils.isNullOrWhitespace(c.login.totp) + ); + if (!cipherResponse.success) { + return cipherResponse; + } + + const cipher = cipherResponse.data as CipherResponse; + if (cipher.type !== CipherType.Login) { + return Response.badRequest("Not a login."); + } + + if (Utils.isNullOrWhitespace(cipher.login.totp)) { + return Response.error("No TOTP available for this login."); + } + + const totp = await this.totpService.getCode(cipher.login.totp); + if (totp == null) { + return Response.error("Couldn't generate TOTP code."); + } + + const canAccessPremium = await this.stateService.getCanAccessPremium(); + if (!canAccessPremium) { + const originalCipher = await this.cipherService.get(cipher.id); + if ( + originalCipher == null || + originalCipher.organizationId == null || + !originalCipher.organizationUseTotp + ) { + return Response.error("Premium status is required to use this feature."); + } + } + + const res = new StringResponse(totp); + return Response.success(res); + } + + private async getNotes(id: string) { + const cipherResponse = await this.getCipher(id, (c) => !Utils.isNullOrWhitespace(c.notes)); + if (!cipherResponse.success) { + return cipherResponse; + } + + const cipher = cipherResponse.data as CipherResponse; + if (Utils.isNullOrWhitespace(cipher.notes)) { + return Response.error("No notes available for this item."); + } + + const res = new StringResponse(cipher.notes); + return Response.success(res); + } + + private async getExposed(id: string) { + const passwordResponse = await this.getPassword(id); + if (!passwordResponse.success) { + return passwordResponse; + } + + const exposedNumber = await this.auditService.passwordLeaked( + (passwordResponse.data as StringResponse).data + ); + const res = new StringResponse(exposedNumber.toString()); + return Response.success(res); + } + + private async getAttachment(id: string, options: Options) { + if (options.itemId == null || options.itemId === "") { + return Response.badRequest("--itemid required."); + } + + const itemId = options.itemId.toLowerCase(); + const cipherResponse = await this.getCipher(itemId); + if (!cipherResponse.success) { + return cipherResponse; + } + + const cipher = await this.getCipherView(itemId); + if ( + cipher == null || + Array.isArray(cipher) || + cipher.attachments == null || + cipher.attachments.length === 0 + ) { + return Response.error("No attachments available for this item."); + } + + let attachments = cipher.attachments.filter( + (a) => + a.id.toLowerCase() === id || + (a.fileName != null && a.fileName.toLowerCase().indexOf(id) > -1) + ); + if (attachments.length === 0) { + return Response.error("Attachment `" + id + "` was not found."); + } + + const exactMatches = attachments.filter((a) => a.fileName.toLowerCase() === id); + if (exactMatches.length === 1) { + attachments = exactMatches; + } + + if (attachments.length > 1) { + return Response.multipleResults(attachments.map((a) => a.id)); + } + + if (!(await this.stateService.getCanAccessPremium())) { + const originalCipher = await this.cipherService.get(cipher.id); + if (originalCipher == null || originalCipher.organizationId == null) { + return Response.error("Premium status is required to use this feature."); + } + } + + let url: string; + try { + const attachmentDownloadResponse = await this.apiService.getAttachmentData( + cipher.id, + attachments[0].id + ); + url = attachmentDownloadResponse.url; + } catch (e) { + if (e instanceof ErrorResponse && (e as ErrorResponse).statusCode === 404) { + url = attachments[0].url; + } else if (e instanceof ErrorResponse) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } else { + throw e; + } + } + + const key = + attachments[0].key != null + ? attachments[0].key + : await this.cryptoService.getOrgKey(cipher.organizationId); + return await this.saveAttachmentToFile(url, key, attachments[0].fileName, options.output); + } + + private async getFolder(id: string) { + let decFolder: FolderView = null; + if (Utils.isGuid(id)) { + const folder = await this.folderService.get(id); + if (folder != null) { + decFolder = await folder.decrypt(); + } + } else if (id.trim() !== "") { + let folders = await this.folderService.getAllDecrypted(); + folders = CliUtils.searchFolders(folders, id); + if (folders.length > 1) { + return Response.multipleResults(folders.map((f) => f.id)); + } + if (folders.length > 0) { + decFolder = folders[0]; + } + } + + if (decFolder == null) { + return Response.notFound(); + } + const res = new FolderResponse(decFolder); + return Response.success(res); + } + + private async getCollection(id: string) { + let decCollection: CollectionView = null; + if (Utils.isGuid(id)) { + const collection = await this.collectionService.get(id); + if (collection != null) { + decCollection = await collection.decrypt(); + } + } else if (id.trim() !== "") { + let collections = await this.collectionService.getAllDecrypted(); + collections = CliUtils.searchCollections(collections, id); + if (collections.length > 1) { + return Response.multipleResults(collections.map((c) => c.id)); + } + if (collections.length > 0) { + decCollection = collections[0]; + } + } + + if (decCollection == null) { + return Response.notFound(); + } + const res = new CollectionResponse(decCollection); + return Response.success(res); + } + + private async getOrganizationCollection(id: string, options: Options) { + if (options.organizationId == null || options.organizationId === "") { + return Response.badRequest("`organizationid` option is required."); + } + if (!Utils.isGuid(id)) { + return Response.badRequest("`" + id + "` is not a GUID."); + } + if (!Utils.isGuid(options.organizationId)) { + return Response.badRequest("`" + options.organizationId + "` is not a GUID."); + } + try { + const orgKey = await this.cryptoService.getOrgKey(options.organizationId); + if (orgKey == null) { + throw new Error("No encryption key for this organization."); + } + + const response = await this.apiService.getCollectionDetails(options.organizationId, id); + const decCollection = new CollectionView(response); + decCollection.name = await this.cryptoService.decryptToUtf8( + new EncString(response.name), + orgKey + ); + const groups = + response.groups == null + ? null + : response.groups.map((g) => new SelectionReadOnly(g.id, g.readOnly, g.hidePasswords)); + const res = new OrganizationCollectionResponse(decCollection, groups); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async getOrganization(id: string) { + let org: Organization = null; + if (Utils.isGuid(id)) { + org = await this.organizationService.get(id); + } else if (id.trim() !== "") { + let orgs = await this.organizationService.getAll(); + orgs = CliUtils.searchOrganizations(orgs, id); + if (orgs.length > 1) { + return Response.multipleResults(orgs.map((c) => c.id)); + } + if (orgs.length > 0) { + org = orgs[0]; + } + } + + if (org == null) { + return Response.notFound(); + } + const res = new OrganizationResponse(org); + return Response.success(res); + } + + private async getTemplate(id: string) { + let template: any = null; + switch (id.toLowerCase()) { + case "item": + template = CipherExport.template(); + break; + case "item.field": + template = FieldExport.template(); + break; + case "item.login": + template = LoginExport.template(); + break; + case "item.login.uri": + template = LoginUriExport.template(); + break; + case "item.card": + template = CardExport.template(); + break; + case "item.identity": + template = IdentityExport.template(); + break; + case "item.securenote": + template = SecureNoteExport.template(); + break; + case "folder": + template = FolderExport.template(); + break; + case "collection": + template = CollectionExport.template(); + break; + case "item-collections": + template = ["collection-id1", "collection-id2"]; + break; + case "org-collection": + template = OrganizationCollectionRequest.template(); + break; + case "send.text": + template = SendResponse.template(SendType.Text); + break; + case "send.file": + template = SendResponse.template(SendType.File); + break; + default: + return Response.badRequest("Unknown template object."); + } + + const res = new TemplateResponse(template); + return Response.success(res); + } + + private async getFingerprint(id: string) { + let fingerprint: string[] = null; + if (id === "me") { + fingerprint = await this.cryptoService.getFingerprint(await this.stateService.getUserId()); + } else if (Utils.isGuid(id)) { + try { + const response = await this.apiService.getUserPublicKey(id); + const pubKey = Utils.fromB64ToArray(response.publicKey); + fingerprint = await this.cryptoService.getFingerprint(id, pubKey.buffer); + } catch { + // eslint-disable-next-line + } + } + + if (fingerprint == null) { + return Response.notFound(); + } + const res = new StringResponse(fingerprint.join("-")); + return Response.success(res); + } +} + +class Options { + itemId: string; + organizationId: string; + output: string; + + constructor(passedOptions: Record) { + this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId; + this.itemId = passedOptions?.itemid || passedOptions?.itemId; + this.output = passedOptions?.output; + } +} diff --git a/apps/cli/src/commands/import.command.ts b/apps/cli/src/commands/import.command.ts new file mode 100644 index 0000000000..23f5ddaa1d --- /dev/null +++ b/apps/cli/src/commands/import.command.ts @@ -0,0 +1,127 @@ +import * as program from "commander"; +import * as inquirer from "inquirer"; + +import { ImportService } from "jslib-common/abstractions/import.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { ImportType } from "jslib-common/enums/importOptions"; +import { Importer } from "jslib-common/importers/importer"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +import { CliUtils } from "../utils"; + +export class ImportCommand { + constructor( + private importService: ImportService, + private organizationService: OrganizationService + ) {} + + async run( + format: ImportType, + filepath: string, + options: program.OptionValues + ): Promise { + const organizationId = options.organizationid; + if (organizationId != null) { + const organization = await this.organizationService.get(organizationId); + + if (organization == null) { + return Response.badRequest( + `You do not belong to an organization with the ID of ${organizationId}. Check the organization ID and sync your vault.` + ); + } + + if (!organization.canAccessImportExport) { + return Response.badRequest( + "You are not authorized to import into the provided organization." + ); + } + } + + if (options.formats || false) { + return await this.list(); + } else { + return await this.import(format, filepath, organizationId); + } + } + + private async import(format: ImportType, filepath: string, organizationId: string) { + if (format == null) { + return Response.badRequest("`format` was not provided."); + } + if (filepath == null || filepath === "") { + return Response.badRequest("`filepath` was not provided."); + } + + const importer = await this.importService.getImporter(format, organizationId); + if (importer === null) { + return Response.badRequest("Proper importer type required."); + } + + try { + let contents; + if (format === "1password1pux") { + contents = await CliUtils.extract1PuxContent(filepath); + } else { + contents = await CliUtils.readFile(filepath); + } + + if (contents === null || contents === "") { + return Response.badRequest("Import file was empty."); + } + + const response = await this.doImport(importer, contents, organizationId); + if (response.success) { + response.data = new MessageResponse("Imported " + filepath, null); + } + return response; + } catch (err) { + return Response.badRequest(err); + } + } + + private async list() { + const options = this.importService + .getImportOptions() + .sort((a, b) => { + return a.id < b.id ? -1 : a.id > b.id ? 1 : 0; + }) + .map((option) => option.id) + .join("\n"); + const res = new MessageResponse("Supported input formats:", options); + res.raw = options; + return Response.success(res); + } + + private async doImport( + importer: Importer, + contents: string, + organizationId?: string + ): Promise { + const err = await this.importService.import(importer, contents, organizationId); + if (err != null) { + if (err.passwordRequired) { + importer = this.importService.getImporter( + "bitwardenpasswordprotected", + organizationId, + await this.promptPassword() + ); + return this.doImport(importer, contents, organizationId); + } + return Response.badRequest(err.message); + } + + return Response.success(); + } + + private async promptPassword() { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "password", + name: "password", + message: "Import file password:", + }); + return answer.password; + } +} diff --git a/apps/cli/src/commands/list.command.ts b/apps/cli/src/commands/list.command.ts new file mode 100644 index 0000000000..04727a4f45 --- /dev/null +++ b/apps/cli/src/commands/list.command.ts @@ -0,0 +1,252 @@ +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { Utils } from "jslib-common/misc/utils"; +import { CollectionData } from "jslib-common/models/data/collectionData"; +import { Collection } from "jslib-common/models/domain/collection"; +import { + CollectionDetailsResponse as ApiCollectionDetailsResponse, + CollectionResponse as ApiCollectionResponse, +} from "jslib-common/models/response/collectionResponse"; +import { ListResponse as ApiListResponse } from "jslib-common/models/response/listResponse"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { Response } from "jslib-node/cli/models/response"; +import { ListResponse } from "jslib-node/cli/models/response/listResponse"; + +import { CipherResponse } from "../models/response/cipherResponse"; +import { CollectionResponse } from "../models/response/collectionResponse"; +import { FolderResponse } from "../models/response/folderResponse"; +import { OrganizationResponse } from "../models/response/organizationResponse"; +import { OrganizationUserResponse } from "../models/response/organizationUserResponse"; +import { CliUtils } from "../utils"; + +export class ListCommand { + constructor( + private cipherService: CipherService, + private folderService: FolderService, + private collectionService: CollectionService, + private organizationService: OrganizationService, + private searchService: SearchService, + private apiService: ApiService + ) {} + + async run(object: string, cmdOptions: Record): Promise { + const normalizedOptions = new Options(cmdOptions); + switch (object.toLowerCase()) { + case "items": + return await this.listCiphers(normalizedOptions); + case "folders": + return await this.listFolders(normalizedOptions); + case "collections": + return await this.listCollections(normalizedOptions); + case "org-collections": + return await this.listOrganizationCollections(normalizedOptions); + case "org-members": + return await this.listOrganizationMembers(normalizedOptions); + case "organizations": + return await this.listOrganizations(normalizedOptions); + default: + return Response.badRequest("Unknown object."); + } + } + + private async listCiphers(options: Options) { + let ciphers: CipherView[]; + options.trash = options.trash || false; + if (options.url != null && options.url.trim() !== "") { + ciphers = await this.cipherService.getAllDecryptedForUrl(options.url); + } else { + ciphers = await this.cipherService.getAllDecrypted(); + } + + if ( + options.folderId != null || + options.collectionId != null || + options.organizationId != null + ) { + ciphers = ciphers.filter((c) => { + if (options.trash !== c.isDeleted) { + return false; + } + if (options.folderId != null) { + if (options.folderId === "notnull" && c.folderId != null) { + return true; + } + const folderId = options.folderId === "null" ? null : options.folderId; + if (folderId === c.folderId) { + return true; + } + } + + if (options.organizationId != null) { + if (options.organizationId === "notnull" && c.organizationId != null) { + return true; + } + const organizationId = options.organizationId === "null" ? null : options.organizationId; + if (organizationId === c.organizationId) { + return true; + } + } + + if (options.collectionId != null) { + if ( + options.collectionId === "notnull" && + c.collectionIds != null && + c.collectionIds.length > 0 + ) { + return true; + } + const collectionId = options.collectionId === "null" ? null : options.collectionId; + if (collectionId == null && (c.collectionIds == null || c.collectionIds.length === 0)) { + return true; + } + if ( + collectionId != null && + c.collectionIds != null && + c.collectionIds.indexOf(collectionId) > -1 + ) { + return true; + } + } + return false; + }); + } else if (options.search == null || options.search.trim() === "") { + ciphers = ciphers.filter((c) => options.trash === c.isDeleted); + } + + if (options.search != null && options.search.trim() !== "") { + ciphers = this.searchService.searchCiphersBasic(ciphers, options.search, options.trash); + } + + const res = new ListResponse(ciphers.map((o) => new CipherResponse(o))); + return Response.success(res); + } + + private async listFolders(options: Options) { + let folders = await this.folderService.getAllDecrypted(); + + if (options.search != null && options.search.trim() !== "") { + folders = CliUtils.searchFolders(folders, options.search); + } + + const res = new ListResponse(folders.map((o) => new FolderResponse(o))); + return Response.success(res); + } + + private async listCollections(options: Options) { + let collections = await this.collectionService.getAllDecrypted(); + + if (options.organizationId != null) { + collections = collections.filter((c) => { + if (options.organizationId === c.organizationId) { + return true; + } + return false; + }); + } + + if (options.search != null && options.search.trim() !== "") { + collections = CliUtils.searchCollections(collections, options.search); + } + + const res = new ListResponse(collections.map((o) => new CollectionResponse(o))); + return Response.success(res); + } + + private async listOrganizationCollections(options: Options) { + if (options.organizationId == null || options.organizationId === "") { + return Response.badRequest("`organizationid` option is required."); + } + if (!Utils.isGuid(options.organizationId)) { + return Response.badRequest("`" + options.organizationId + "` is not a GUID."); + } + const organization = await this.organizationService.get(options.organizationId); + if (organization == null) { + return Response.error("Organization not found."); + } + + try { + let response: ApiListResponse; + if (organization.canViewAllCollections) { + response = await this.apiService.getCollections(options.organizationId); + } else { + response = await this.apiService.getUserCollections(); + } + const collections = response.data + .filter((c) => c.organizationId === options.organizationId) + .map((r) => new Collection(new CollectionData(r as ApiCollectionDetailsResponse))); + let decCollections = await this.collectionService.decryptMany(collections); + if (options.search != null && options.search.trim() !== "") { + decCollections = CliUtils.searchCollections(decCollections, options.search); + } + const res = new ListResponse(decCollections.map((o) => new CollectionResponse(o))); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async listOrganizationMembers(options: Options) { + if (options.organizationId == null || options.organizationId === "") { + return Response.badRequest("`organizationid` option is required."); + } + if (!Utils.isGuid(options.organizationId)) { + return Response.badRequest("`" + options.organizationId + "` is not a GUID."); + } + const organization = await this.organizationService.get(options.organizationId); + if (organization == null) { + return Response.error("Organization not found."); + } + + try { + const response = await this.apiService.getOrganizationUsers(options.organizationId); + const res = new ListResponse( + response.data.map((r) => { + const u = new OrganizationUserResponse(); + u.email = r.email; + u.name = r.name; + u.id = r.id; + u.status = r.status; + u.type = r.type; + u.twoFactorEnabled = r.twoFactorEnabled; + return u; + }) + ); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } + + private async listOrganizations(options: Options) { + let organizations = await this.organizationService.getAll(); + + if (options.search != null && options.search.trim() !== "") { + organizations = CliUtils.searchOrganizations(organizations, options.search); + } + + const res = new ListResponse(organizations.map((o) => new OrganizationResponse(o))); + return Response.success(res); + } +} + +class Options { + organizationId: string; + collectionId: string; + folderId: string; + search: string; + url: string; + trash: boolean; + + constructor(passedOptions: Record) { + this.organizationId = passedOptions?.organizationid || passedOptions?.organizationId; + this.collectionId = passedOptions?.collectionid || passedOptions?.collectionId; + this.folderId = passedOptions?.folderid || passedOptions?.folderId; + this.search = passedOptions?.search; + this.url = passedOptions?.url; + this.trash = CliUtils.convertBooleanOption(passedOptions?.trash); + } +} diff --git a/apps/cli/src/commands/lock.command.ts b/apps/cli/src/commands/lock.command.ts new file mode 100644 index 0000000000..52f331ab5e --- /dev/null +++ b/apps/cli/src/commands/lock.command.ts @@ -0,0 +1,14 @@ +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +export class LockCommand { + constructor(private vaultTimeoutService: VaultTimeoutService) {} + + async run() { + await this.vaultTimeoutService.lock(); + process.env.BW_SESSION = null; + const res = new MessageResponse("Your vault is locked.", null); + return Response.success(res); + } +} diff --git a/apps/cli/src/commands/login.command.ts b/apps/cli/src/commands/login.command.ts new file mode 100644 index 0000000000..6fa1b12c61 --- /dev/null +++ b/apps/cli/src/commands/login.command.ts @@ -0,0 +1,99 @@ +import * as program from "commander"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { Utils } from "jslib-common/misc/utils"; +import { LoginCommand as BaseLoginCommand } from "jslib-node/cli/commands/login.command"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +export class LoginCommand extends BaseLoginCommand { + private options: program.OptionValues; + + constructor( + authService: AuthService, + apiService: ApiService, + cryptoFunctionService: CryptoFunctionService, + i18nService: I18nService, + environmentService: EnvironmentService, + passwordGenerationService: PasswordGenerationService, + platformUtilsService: PlatformUtilsService, + stateService: StateService, + cryptoService: CryptoService, + policyService: PolicyService, + twoFactorService: TwoFactorService, + private syncService: SyncService, + private keyConnectorService: KeyConnectorService, + private logoutCallback: () => Promise + ) { + super( + authService, + apiService, + i18nService, + environmentService, + passwordGenerationService, + cryptoFunctionService, + platformUtilsService, + stateService, + cryptoService, + policyService, + twoFactorService, + "cli" + ); + this.logout = this.logoutCallback; + this.validatedParams = async () => { + const key = await cryptoFunctionService.randomBytes(64); + process.env.BW_SESSION = Utils.fromBufferToB64(key); + }; + this.success = async () => { + await this.syncService.fullSync(true); + + const usesKeyConnector = await this.keyConnectorService.getUsesKeyConnector(); + + if ( + (this.options.sso != null || this.options.apikey != null) && + this.canInteract && + !usesKeyConnector + ) { + const res = new MessageResponse( + "You are logged in!", + "\n" + "To unlock your vault, use the `unlock` command. ex:\n" + "$ bw unlock" + ); + return res; + } else { + const res = new MessageResponse( + "You are logged in!", + "\n" + + "To unlock your vault, set your session key to the `BW_SESSION` environment variable. ex:\n" + + '$ export BW_SESSION="' + + process.env.BW_SESSION + + '"\n' + + '> $env:BW_SESSION="' + + process.env.BW_SESSION + + '"\n\n' + + "You can also pass the session key to any command with the `--session` option. ex:\n" + + "$ bw list items --session " + + process.env.BW_SESSION + ); + res.raw = process.env.BW_SESSION; + return res; + } + }; + } + + run(email: string, password: string, options: program.OptionValues) { + this.options = options; + this.email = email; + return super.run(email, password, options); + } +} diff --git a/apps/cli/src/commands/restore.command.ts b/apps/cli/src/commands/restore.command.ts new file mode 100644 index 0000000000..51247698db --- /dev/null +++ b/apps/cli/src/commands/restore.command.ts @@ -0,0 +1,36 @@ +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { Response } from "jslib-node/cli/models/response"; + +export class RestoreCommand { + constructor(private cipherService: CipherService) {} + + async run(object: string, id: string): Promise { + if (id != null) { + id = id.toLowerCase(); + } + + switch (object.toLowerCase()) { + case "item": + return await this.restoreCipher(id); + default: + return Response.badRequest("Unknown object."); + } + } + + private async restoreCipher(id: string) { + const cipher = await this.cipherService.get(id); + if (cipher == null) { + return Response.notFound(); + } + if (cipher.deletedDate == null) { + return Response.badRequest("Cipher is not in trash."); + } + + try { + await this.cipherService.restoreWithServer(id); + return Response.success(); + } catch (e) { + return Response.error(e); + } + } +} diff --git a/apps/cli/src/commands/send/create.command.ts b/apps/cli/src/commands/send/create.command.ts new file mode 100644 index 0000000000..bbf0adc65a --- /dev/null +++ b/apps/cli/src/commands/send/create.command.ts @@ -0,0 +1,149 @@ +import * as fs from "fs"; +import * as path from "path"; + +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SendType } from "jslib-common/enums/sendType"; +import { NodeUtils } from "jslib-common/misc/nodeUtils"; +import { Response } from "jslib-node/cli/models/response"; + +import { SendResponse } from "../../models/response/sendResponse"; +import { SendTextResponse } from "../../models/response/sendTextResponse"; +import { CliUtils } from "../../utils"; + +export class SendCreateCommand { + constructor( + private sendService: SendService, + private stateService: StateService, + private environmentService: EnvironmentService + ) {} + + async run(requestJson: any, cmdOptions: Record) { + let req: any = null; + if (process.env.BW_SERVE !== "true" && (requestJson == null || requestJson === "")) { + requestJson = await CliUtils.readStdin(); + } + + if (requestJson == null || requestJson === "") { + return Response.badRequest("`requestJson` was not provided."); + } + + if (typeof requestJson !== "string") { + req = requestJson; + req.deletionDate = req.deletionDate == null ? null : new Date(req.deletionDate); + req.expirationDate = req.expirationDate == null ? null : new Date(req.expirationDate); + } else { + try { + const reqJson = Buffer.from(requestJson, "base64").toString(); + req = SendResponse.fromJson(reqJson); + + if (req == null) { + throw new Error("Null request"); + } + } catch (e) { + return Response.badRequest("Error parsing the encoded request data."); + } + } + + if ( + req.deletionDate == null || + isNaN(new Date(req.deletionDate).getTime()) || + new Date(req.deletionDate) <= new Date() + ) { + return Response.badRequest("Must specify a valid deletion date after the current time"); + } + + if (req.expirationDate != null && isNaN(new Date(req.expirationDate).getTime())) { + return Response.badRequest("Unable to parse expirationDate: " + req.expirationDate); + } + + const normalizedOptions = new Options(cmdOptions); + return this.createSend(req, normalizedOptions); + } + + private async createSend(req: SendResponse, options: Options) { + const filePath = req.file?.fileName ?? options.file; + const text = req.text?.text ?? options.text; + const hidden = req.text?.hidden ?? options.hidden; + const password = req.password ?? options.password; + const maxAccessCount = req.maxAccessCount ?? options.maxAccessCount; + + req.key = null; + req.maxAccessCount = maxAccessCount; + + switch (req.type) { + case SendType.File: + if (process.env.BW_SERVE === "true") { + return Response.error( + "Creating a file-based Send is unsupported through the `serve` command at this time." + ); + } + + if (!(await this.stateService.getCanAccessPremium())) { + return Response.error("Premium status is required to use this feature."); + } + + if (filePath == null) { + return Response.badRequest( + "Must specify a file to Send either with the --file option or in the request JSON." + ); + } + + req.file.fileName = path.basename(filePath); + break; + case SendType.Text: + if (text == null) { + return Response.badRequest( + "Must specify text content to Send either with the --text option or in the request JSON." + ); + } + req.text = new SendTextResponse(); + req.text.text = text; + req.text.hidden = hidden; + break; + default: + return Response.badRequest( + "Unknown Send type " + SendType[req.type] + ". Valid types are: file, text" + ); + } + + try { + let fileBuffer: ArrayBuffer = null; + if (req.type === SendType.File) { + fileBuffer = NodeUtils.bufferToArrayBuffer(fs.readFileSync(filePath)); + } + + const sendView = SendResponse.toView(req); + const [encSend, fileData] = await this.sendService.encrypt(sendView, fileBuffer, password); + // Add dates from template + encSend.deletionDate = sendView.deletionDate; + encSend.expirationDate = sendView.expirationDate; + + await this.sendService.saveWithServer([encSend, fileData]); + const newSend = await this.sendService.get(encSend.id); + const decSend = await newSend.decrypt(); + const res = new SendResponse(decSend, this.environmentService.getWebVaultUrl()); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } +} + +class Options { + file: string; + text: string; + maxAccessCount: number; + password: string; + hidden: boolean; + + constructor(passedOptions: Record) { + this.file = passedOptions?.file; + this.text = passedOptions?.text; + this.password = passedOptions?.password; + this.hidden = CliUtils.convertBooleanOption(passedOptions?.hidden); + this.maxAccessCount = + passedOptions?.maxAccessCount != null ? parseInt(passedOptions.maxAccessCount, null) : null; + } +} diff --git a/apps/cli/src/commands/send/delete.command.ts b/apps/cli/src/commands/send/delete.command.ts new file mode 100644 index 0000000000..72a9cbf600 --- /dev/null +++ b/apps/cli/src/commands/send/delete.command.ts @@ -0,0 +1,21 @@ +import { SendService } from "jslib-common/abstractions/send.service"; +import { Response } from "jslib-node/cli/models/response"; + +export class SendDeleteCommand { + constructor(private sendService: SendService) {} + + async run(id: string) { + const send = await this.sendService.get(id); + + if (send == null) { + return Response.notFound(); + } + + try { + await this.sendService.deleteWithServer(id); + return Response.success(); + } catch (e) { + return Response.error(e); + } + } +} diff --git a/apps/cli/src/commands/send/edit.command.ts b/apps/cli/src/commands/send/edit.command.ts new file mode 100644 index 0000000000..4aac124079 --- /dev/null +++ b/apps/cli/src/commands/send/edit.command.ts @@ -0,0 +1,90 @@ +import { SendService } from "jslib-common/abstractions/send.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SendType } from "jslib-common/enums/sendType"; +import { Response } from "jslib-node/cli/models/response"; + +import { SendResponse } from "../../models/response/sendResponse"; +import { CliUtils } from "../../utils"; + +import { SendGetCommand } from "./get.command"; + +export class SendEditCommand { + constructor( + private sendService: SendService, + private stateService: StateService, + private getCommand: SendGetCommand + ) {} + + async run(requestJson: string, cmdOptions: Record): Promise { + if (process.env.BW_SERVE !== "true" && (requestJson == null || requestJson === "")) { + requestJson = await CliUtils.readStdin(); + } + + if (requestJson == null || requestJson === "") { + return Response.badRequest("`requestJson` was not provided."); + } + + let req: SendResponse = null; + if (typeof requestJson !== "string") { + req = requestJson; + req.deletionDate = req.deletionDate == null ? null : new Date(req.deletionDate); + req.expirationDate = req.expirationDate == null ? null : new Date(req.expirationDate); + } else { + try { + const reqJson = Buffer.from(requestJson, "base64").toString(); + req = SendResponse.fromJson(reqJson); + } catch (e) { + return Response.badRequest("Error parsing the encoded request data."); + } + } + + const normalizedOptions = new Options(cmdOptions); + req.id = normalizedOptions.itemId || req.id; + + if (req.id != null) { + req.id = req.id.toLowerCase(); + } + + const send = await this.sendService.get(req.id); + + if (send == null) { + return Response.notFound(); + } + + if (send.type !== req.type) { + return Response.badRequest("Cannot change a Send's type"); + } + + if (send.type === SendType.File && !(await this.stateService.getCanAccessPremium())) { + return Response.error("Premium status is required to use this feature."); + } + + let sendView = await send.decrypt(); + sendView = SendResponse.toView(req, sendView); + + if (typeof req.password !== "string" || req.password === "") { + req.password = null; + } + + try { + const [encSend, encFileData] = await this.sendService.encrypt(sendView, null, req.password); + // Add dates from template + encSend.deletionDate = sendView.deletionDate; + encSend.expirationDate = sendView.expirationDate; + + await this.sendService.saveWithServer([encSend, encFileData]); + } catch (e) { + return Response.error(e); + } + + return await this.getCommand.run(send.id, {}); + } +} + +class Options { + itemId: string; + + constructor(passedOptions: Record) { + this.itemId = passedOptions?.itemId || passedOptions?.itemid; + } +} diff --git a/apps/cli/src/commands/send/get.command.ts b/apps/cli/src/commands/send/get.command.ts new file mode 100644 index 0000000000..cef7d66256 --- /dev/null +++ b/apps/cli/src/commands/send/get.command.ts @@ -0,0 +1,83 @@ +import * as program from "commander"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { Utils } from "jslib-common/misc/utils"; +import { SendView } from "jslib-common/models/view/sendView"; +import { Response } from "jslib-node/cli/models/response"; + +import { SendResponse } from "../../models/response/sendResponse"; +import { DownloadCommand } from "../download.command"; + +export class SendGetCommand extends DownloadCommand { + constructor( + private sendService: SendService, + private environmentService: EnvironmentService, + private searchService: SearchService, + cryptoService: CryptoService + ) { + super(cryptoService); + } + + async run(id: string, options: program.OptionValues) { + const serveCommand = process.env.BW_SERVE === "true"; + if (serveCommand && !Utils.isGuid(id)) { + return Response.badRequest("`" + id + "` is not a GUID."); + } + + let sends = await this.getSendView(id); + if (sends == null) { + return Response.notFound(); + } + + const webVaultUrl = this.environmentService.getWebVaultUrl(); + let filter = (s: SendView) => true; + let selector = async (s: SendView): Promise => + Response.success(new SendResponse(s, webVaultUrl)); + if (!serveCommand && options?.text != null) { + filter = (s) => { + return filter(s) && s.text != null; + }; + selector = async (s) => { + // Write to stdout and response success so we get the text string only to stdout + process.stdout.write(s.text.text); + return Response.success(); + }; + } + + if (Array.isArray(sends)) { + if (filter != null) { + sends = sends.filter(filter); + } + if (sends.length > 1) { + return Response.multipleResults(sends.map((s) => s.id)); + } + if (sends.length > 0) { + return selector(sends[0]); + } else { + return Response.notFound(); + } + } + + return selector(sends); + } + + private async getSendView(id: string): Promise { + if (Utils.isGuid(id)) { + const send = await this.sendService.get(id); + if (send != null) { + return await send.decrypt(); + } + } else if (id.trim() !== "") { + let sends = await this.sendService.getAllDecrypted(); + sends = this.searchService.searchSends(sends, id); + if (sends.length > 1) { + return sends; + } else if (sends.length > 0) { + return sends[0]; + } + } + } +} diff --git a/apps/cli/src/commands/send/list.command.ts b/apps/cli/src/commands/send/list.command.ts new file mode 100644 index 0000000000..3b888d3345 --- /dev/null +++ b/apps/cli/src/commands/send/list.command.ts @@ -0,0 +1,36 @@ +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { Response } from "jslib-node/cli/models/response"; +import { ListResponse } from "jslib-node/cli/models/response/listResponse"; + +import { SendResponse } from "../..//models/response/sendResponse"; + +export class SendListCommand { + constructor( + private sendService: SendService, + private environmentService: EnvironmentService, + private searchService: SearchService + ) {} + + async run(cmdOptions: Record): Promise { + let sends = await this.sendService.getAllDecrypted(); + + const normalizedOptions = new Options(cmdOptions); + if (normalizedOptions.search != null && normalizedOptions.search.trim() !== "") { + sends = this.searchService.searchSends(sends, normalizedOptions.search); + } + + const webVaultUrl = this.environmentService.getWebVaultUrl(); + const res = new ListResponse(sends.map((s) => new SendResponse(s, webVaultUrl))); + return Response.success(res); + } +} + +class Options { + search: string; + + constructor(passedOptions: Record) { + this.search = passedOptions?.search; + } +} diff --git a/apps/cli/src/commands/send/receive.command.ts b/apps/cli/src/commands/send/receive.command.ts new file mode 100644 index 0000000000..6cab9dfb68 --- /dev/null +++ b/apps/cli/src/commands/send/receive.command.ts @@ -0,0 +1,170 @@ +import * as program from "commander"; +import * as inquirer from "inquirer"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { SendType } from "jslib-common/enums/sendType"; +import { NodeUtils } from "jslib-common/misc/nodeUtils"; +import { Utils } from "jslib-common/misc/utils"; +import { SendAccess } from "jslib-common/models/domain/sendAccess"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { SendAccessRequest } from "jslib-common/models/request/sendAccessRequest"; +import { ErrorResponse } from "jslib-common/models/response/errorResponse"; +import { SendAccessView } from "jslib-common/models/view/sendAccessView"; +import { Response } from "jslib-node/cli/models/response"; + +import { SendAccessResponse } from "../../models/response/sendAccessResponse"; +import { DownloadCommand } from "../download.command"; + +export class SendReceiveCommand extends DownloadCommand { + private canInteract: boolean; + private decKey: SymmetricCryptoKey; + private sendAccessRequest: SendAccessRequest; + + constructor( + private apiService: ApiService, + cryptoService: CryptoService, + private cryptoFunctionService: CryptoFunctionService, + private platformUtilsService: PlatformUtilsService, + private environmentService: EnvironmentService + ) { + super(cryptoService); + } + + async run(url: string, options: program.OptionValues): Promise { + this.canInteract = process.env.BW_NOINTERACTION !== "true"; + + let urlObject: URL; + try { + urlObject = new URL(url); + } catch (e) { + return Response.badRequest("Failed to parse the provided Send url"); + } + + const apiUrl = this.getApiUrl(urlObject); + const [id, key] = this.getIdAndKey(urlObject); + + if (Utils.isNullOrWhitespace(id) || Utils.isNullOrWhitespace(key)) { + return Response.badRequest("Failed to parse url, the url provided is not a valid Send url"); + } + + const keyArray = Utils.fromUrlB64ToArray(key); + this.sendAccessRequest = new SendAccessRequest(); + + let password = options.password; + if (password == null || password === "") { + if (options.passwordfile) { + password = await NodeUtils.readFirstLine(options.passwordfile); + } else if (options.passwordenv && process.env[options.passwordenv]) { + password = process.env[options.passwordenv]; + } + } + + if (password != null && password !== "") { + this.sendAccessRequest.password = await this.getUnlockedPassword(password, keyArray); + } + + const response = await this.sendRequest(apiUrl, id, keyArray); + + if (response instanceof Response) { + // Error scenario + return response; + } + + if (options.obj != null) { + return Response.success(new SendAccessResponse(response)); + } + + switch (response.type) { + case SendType.Text: + // Write to stdout and response success so we get the text string only to stdout + process.stdout.write(response?.text?.text); + return Response.success(); + case SendType.File: { + const downloadData = await this.apiService.getSendFileDownloadData( + response, + this.sendAccessRequest, + apiUrl + ); + return await this.saveAttachmentToFile( + downloadData.url, + this.decKey, + response?.file?.fileName, + options.output + ); + } + default: + return Response.success(new SendAccessResponse(response)); + } + } + + private getIdAndKey(url: URL): [string, string] { + const result = url.hash.slice(1).split("/").slice(-2); + return [result[0], result[1]]; + } + + private getApiUrl(url: URL) { + const urls = this.environmentService.getUrls(); + if (url.origin === "https://send.bitwarden.com") { + return "https://vault.bitwarden.com/api"; + } else if (url.origin === urls.api) { + return url.origin; + } else if (this.platformUtilsService.isDev() && url.origin === urls.webVault) { + return urls.api; + } else { + return url.origin + "/api"; + } + } + + private async getUnlockedPassword(password: string, keyArray: ArrayBuffer) { + const passwordHash = await this.cryptoFunctionService.pbkdf2( + password, + keyArray, + "sha256", + 100000 + ); + return Utils.fromBufferToB64(passwordHash); + } + + private async sendRequest( + url: string, + id: string, + key: ArrayBuffer + ): Promise { + try { + const sendResponse = await this.apiService.postSendAccess(id, this.sendAccessRequest, url); + + const sendAccess = new SendAccess(sendResponse); + this.decKey = await this.cryptoService.makeSendKey(key); + return await sendAccess.decrypt(this.decKey); + } catch (e) { + if (e instanceof ErrorResponse) { + if (e.statusCode === 401) { + if (this.canInteract) { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "password", + name: "password", + message: "Send password:", + }); + + // reattempt with new password + this.sendAccessRequest.password = await this.getUnlockedPassword(answer.password, key); + return await this.sendRequest(url, id, key); + } + + return Response.badRequest("Incorrect or missing password"); + } else if (e.statusCode === 405) { + return Response.badRequest("Bad Request"); + } else if (e.statusCode === 404) { + return Response.notFound(); + } + } + return Response.error(e); + } + } +} diff --git a/apps/cli/src/commands/send/removePassword.command.ts b/apps/cli/src/commands/send/removePassword.command.ts new file mode 100644 index 0000000000..1da6becf28 --- /dev/null +++ b/apps/cli/src/commands/send/removePassword.command.ts @@ -0,0 +1,21 @@ +import { SendService } from "jslib-common/abstractions/send.service"; +import { Response } from "jslib-node/cli/models/response"; + +import { SendResponse } from "../../models/response/sendResponse"; + +export class SendRemovePasswordCommand { + constructor(private sendService: SendService) {} + + async run(id: string) { + try { + await this.sendService.removePasswordWithServer(id); + + const updatedSend = await this.sendService.get(id); + const decSend = await updatedSend.decrypt(); + const res = new SendResponse(decSend); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } +} diff --git a/apps/cli/src/commands/serve.command.ts b/apps/cli/src/commands/serve.command.ts new file mode 100644 index 0000000000..f5685efeac --- /dev/null +++ b/apps/cli/src/commands/serve.command.ts @@ -0,0 +1,394 @@ +import * as koaMulter from "@koa/multer"; +import * as koaRouter from "@koa/router"; +import * as program from "commander"; +import * as koa from "koa"; +import * as koaBodyParser from "koa-bodyparser"; +import * as koaJson from "koa-json"; + +import { KeySuffixOptions } from "jslib-common/enums/keySuffixOptions"; +import { Response } from "jslib-node/cli/models/response"; +import { FileResponse } from "jslib-node/cli/models/response/fileResponse"; + +import { Main } from "../bw"; + +import { ConfirmCommand } from "./confirm.command"; +import { CreateCommand } from "./create.command"; +import { DeleteCommand } from "./delete.command"; +import { EditCommand } from "./edit.command"; +import { GenerateCommand } from "./generate.command"; +import { GetCommand } from "./get.command"; +import { ListCommand } from "./list.command"; +import { LockCommand } from "./lock.command"; +import { RestoreCommand } from "./restore.command"; +import { SendCreateCommand } from "./send/create.command"; +import { SendDeleteCommand } from "./send/delete.command"; +import { SendEditCommand } from "./send/edit.command"; +import { SendGetCommand } from "./send/get.command"; +import { SendListCommand } from "./send/list.command"; +import { SendRemovePasswordCommand } from "./send/removePassword.command"; +import { ShareCommand } from "./share.command"; +import { StatusCommand } from "./status.command"; +import { SyncCommand } from "./sync.command"; +import { UnlockCommand } from "./unlock.command"; + +export class ServeCommand { + private listCommand: ListCommand; + private getCommand: GetCommand; + private createCommand: CreateCommand; + private editCommand: EditCommand; + private generateCommand: GenerateCommand; + private shareCommand: ShareCommand; + private statusCommand: StatusCommand; + private syncCommand: SyncCommand; + private deleteCommand: DeleteCommand; + private confirmCommand: ConfirmCommand; + private restoreCommand: RestoreCommand; + private lockCommand: LockCommand; + private unlockCommand: UnlockCommand; + + private sendCreateCommand: SendCreateCommand; + private sendDeleteCommand: SendDeleteCommand; + private sendEditCommand: SendEditCommand; + private sendGetCommand: SendGetCommand; + private sendListCommand: SendListCommand; + private sendRemovePasswordCommand: SendRemovePasswordCommand; + + constructor(protected main: Main) { + this.getCommand = new GetCommand( + this.main.cipherService, + this.main.folderService, + this.main.collectionService, + this.main.totpService, + this.main.auditService, + this.main.cryptoService, + this.main.stateService, + this.main.searchService, + this.main.apiService, + this.main.organizationService + ); + this.listCommand = new ListCommand( + this.main.cipherService, + this.main.folderService, + this.main.collectionService, + this.main.organizationService, + this.main.searchService, + this.main.apiService + ); + this.createCommand = new CreateCommand( + this.main.cipherService, + this.main.folderService, + this.main.stateService, + this.main.cryptoService, + this.main.apiService + ); + this.editCommand = new EditCommand( + this.main.cipherService, + this.main.folderService, + this.main.cryptoService, + this.main.apiService + ); + this.generateCommand = new GenerateCommand( + this.main.passwordGenerationService, + this.main.stateService + ); + this.syncCommand = new SyncCommand(this.main.syncService); + this.statusCommand = new StatusCommand( + this.main.environmentService, + this.main.syncService, + this.main.stateService, + this.main.authService + ); + this.deleteCommand = new DeleteCommand( + this.main.cipherService, + this.main.folderService, + this.main.stateService, + this.main.apiService + ); + this.confirmCommand = new ConfirmCommand(this.main.apiService, this.main.cryptoService); + this.restoreCommand = new RestoreCommand(this.main.cipherService); + this.shareCommand = new ShareCommand(this.main.cipherService); + this.lockCommand = new LockCommand(this.main.vaultTimeoutService); + this.unlockCommand = new UnlockCommand( + this.main.cryptoService, + this.main.stateService, + this.main.cryptoFunctionService, + this.main.apiService, + this.main.logService, + this.main.keyConnectorService, + this.main.environmentService, + this.main.syncService, + async () => await this.main.logout() + ); + + this.sendCreateCommand = new SendCreateCommand( + this.main.sendService, + this.main.stateService, + this.main.environmentService + ); + this.sendDeleteCommand = new SendDeleteCommand(this.main.sendService); + this.sendGetCommand = new SendGetCommand( + this.main.sendService, + this.main.environmentService, + this.main.searchService, + this.main.cryptoService + ); + this.sendEditCommand = new SendEditCommand( + this.main.sendService, + this.main.stateService, + this.sendGetCommand + ); + this.sendListCommand = new SendListCommand( + this.main.sendService, + this.main.environmentService, + this.main.searchService + ); + this.sendRemovePasswordCommand = new SendRemovePasswordCommand(this.main.sendService); + } + + async run(options: program.OptionValues) { + const port = options.port || 8087; + const hostname = options.hostname || "localhost"; + const server = new koa(); + const router = new koaRouter(); + process.env.BW_SERVE = "true"; + process.env.BW_NOINTERACTION = "true"; + + server.use(koaBodyParser()).use(koaJson({ pretty: false, param: "pretty" })); + + router.get("/generate", async (ctx, next) => { + const response = await this.generateCommand.run(ctx.request.query); + this.processResponse(ctx.response, response); + await next(); + }); + + router.get("/status", async (ctx, next) => { + const response = await this.statusCommand.run(); + this.processResponse(ctx.response, response); + await next(); + }); + + router.get("/list/object/:object", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + let response: Response = null; + if (ctx.params.object === "send") { + response = await this.sendListCommand.run(ctx.request.query); + } else { + response = await this.listCommand.run(ctx.params.object, ctx.request.query); + } + this.processResponse(ctx.response, response); + await next(); + }); + + router.get("/send/list", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + const response = await this.sendListCommand.run(ctx.request.query); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/sync", async (ctx, next) => { + const response = await this.syncCommand.run(ctx.request.query); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/lock", async (ctx, next) => { + const response = await this.lockCommand.run(); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/unlock", async (ctx, next) => { + const response = await this.unlockCommand.run( + ctx.request.body.password == null ? null : (ctx.request.body.password as string), + ctx.request.query + ); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/confirm/:object/:id", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + const response = await this.confirmCommand.run( + ctx.params.object, + ctx.params.id, + ctx.request.query + ); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/restore/:object/:id", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + const response = await this.restoreCommand.run(ctx.params.object, ctx.params.id); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/move/:id/:organizationId", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + const response = await this.shareCommand.run( + ctx.params.id, + ctx.params.organizationId, + ctx.request.body // TODO: Check the format of this body for an array of collection ids + ); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/attachment", koaMulter().single("file"), async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + const response = await this.createCommand.run( + "attachment", + ctx.request.body, + ctx.request.query, + { + fileBuffer: ctx.request.file.buffer, + fileName: ctx.request.file.originalname, + } + ); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/send/:id/remove-password", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + const response = await this.sendRemovePasswordCommand.run(ctx.params.id); + this.processResponse(ctx.response, response); + await next(); + }); + + router.post("/object/:object", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + let response: Response = null; + if (ctx.params.object === "send") { + response = await this.sendCreateCommand.run(ctx.request.body, ctx.request.query); + } else { + response = await this.createCommand.run( + ctx.params.object, + ctx.request.body, + ctx.request.query + ); + } + this.processResponse(ctx.response, response); + await next(); + }); + + router.put("/object/:object/:id", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + let response: Response = null; + if (ctx.params.object === "send") { + ctx.request.body.id = ctx.params.id; + response = await this.sendEditCommand.run(ctx.request.body, ctx.request.query); + } else { + response = await this.editCommand.run( + ctx.params.object, + ctx.params.id, + ctx.request.body, + ctx.request.query + ); + } + this.processResponse(ctx.response, response); + await next(); + }); + + router.get("/object/:object/:id", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + let response: Response = null; + if (ctx.params.object === "send") { + response = await this.sendGetCommand.run(ctx.params.id, null); + } else { + response = await this.getCommand.run(ctx.params.object, ctx.params.id, ctx.request.query); + } + this.processResponse(ctx.response, response); + await next(); + }); + + router.delete("/object/:object/:id", async (ctx, next) => { + if (await this.errorIfLocked(ctx.response)) { + await next(); + return; + } + let response: Response = null; + if (ctx.params.object === "send") { + response = await this.sendDeleteCommand.run(ctx.params.id); + } else { + response = await this.deleteCommand.run( + ctx.params.object, + ctx.params.id, + ctx.request.query + ); + } + this.processResponse(ctx.response, response); + await next(); + }); + + server + .use(router.routes()) + .use(router.allowedMethods()) + .listen(port, hostname === "all" ? null : hostname, () => { + this.main.logService.info("Listening on " + hostname + ":" + port); + }); + } + + private processResponse(res: koa.Response, commandResponse: Response) { + if (!commandResponse.success) { + res.status = 400; + } + if (commandResponse.data instanceof FileResponse) { + res.body = commandResponse.data.data; + res.attachment(commandResponse.data.fileName); + res.set("Content-Type", "application/octet-stream"); + res.set("Content-Length", commandResponse.data.data.length.toString()); + } else { + res.body = commandResponse; + } + } + + private async errorIfLocked(res: koa.Response) { + const authed = await this.main.stateService.getIsAuthenticated(); + if (!authed) { + this.processResponse(res, Response.error("You are not logged in.")); + return true; + } + if (await this.main.cryptoService.hasKeyInMemory()) { + return false; + } else if (await this.main.cryptoService.hasKeyStored(KeySuffixOptions.Auto)) { + // load key into memory + await this.main.cryptoService.getKey(); + return false; + } + this.processResponse(res, Response.error("Vault is locked.")); + return true; + } +} diff --git a/apps/cli/src/commands/share.command.ts b/apps/cli/src/commands/share.command.ts new file mode 100644 index 0000000000..924ed01259 --- /dev/null +++ b/apps/cli/src/commands/share.command.ts @@ -0,0 +1,59 @@ +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { Response } from "jslib-node/cli/models/response"; + +import { CipherResponse } from "../models/response/cipherResponse"; +import { CliUtils } from "../utils"; + +export class ShareCommand { + constructor(private cipherService: CipherService) {} + + async run(id: string, organizationId: string, requestJson: string): Promise { + if (process.env.BW_SERVE !== "true" && (requestJson == null || requestJson === "")) { + requestJson = await CliUtils.readStdin(); + } + + if (requestJson == null || requestJson === "") { + return Response.badRequest("`requestJson` was not provided."); + } + + let req: string[] = []; + if (typeof requestJson !== "string") { + req = requestJson; + } else { + try { + const reqJson = Buffer.from(requestJson, "base64").toString(); + req = JSON.parse(reqJson); + if (req == null || req.length === 0) { + return Response.badRequest("You must provide at least one collection id for this item."); + } + } catch (e) { + return Response.badRequest("Error parsing the encoded request data."); + } + } + + if (id != null) { + id = id.toLowerCase(); + } + if (organizationId != null) { + organizationId = organizationId.toLowerCase(); + } + + const cipher = await this.cipherService.get(id); + if (cipher == null) { + return Response.notFound(); + } + if (cipher.organizationId != null) { + return Response.badRequest("This item already belongs to an organization."); + } + const cipherView = await cipher.decrypt(); + try { + await this.cipherService.shareWithServer(cipherView, organizationId, req); + const updatedCipher = await this.cipherService.get(cipher.id); + const decCipher = await updatedCipher.decrypt(); + const res = new CipherResponse(decCipher); + return Response.success(res); + } catch (e) { + return Response.error(e); + } + } +} diff --git a/apps/cli/src/commands/status.command.ts b/apps/cli/src/commands/status.command.ts new file mode 100644 index 0000000000..724b2b03d5 --- /dev/null +++ b/apps/cli/src/commands/status.command.ts @@ -0,0 +1,54 @@ +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { Response } from "jslib-node/cli/models/response"; + +import { TemplateResponse } from "../models/response/templateResponse"; + +export class StatusCommand { + constructor( + private envService: EnvironmentService, + private syncService: SyncService, + private stateService: StateService, + private authService: AuthService + ) {} + + async run(): Promise { + try { + const baseUrl = this.baseUrl(); + const status = await this.status(); + const lastSync = await this.syncService.getLastSync(); + const userId = await this.stateService.getUserId(); + const email = await this.stateService.getEmail(); + + return Response.success( + new TemplateResponse({ + serverUrl: baseUrl, + lastSync: lastSync, + userEmail: email, + userId: userId, + status: status, + }) + ); + } catch (e) { + return Response.error(e); + } + } + + private baseUrl(): string { + return this.envService.getUrls().base; + } + + private async status(): Promise<"unauthenticated" | "locked" | "unlocked"> { + const authStatus = await this.authService.getAuthStatus(); + if (authStatus === AuthenticationStatus.Unlocked) { + return "unlocked"; + } else if (authStatus === AuthenticationStatus.Locked) { + return "locked"; + } else { + return "unauthenticated"; + } + } +} diff --git a/apps/cli/src/commands/sync.command.ts b/apps/cli/src/commands/sync.command.ts new file mode 100644 index 0000000000..7df7510c19 --- /dev/null +++ b/apps/cli/src/commands/sync.command.ts @@ -0,0 +1,41 @@ +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; +import { StringResponse } from "jslib-node/cli/models/response/stringResponse"; + +import { CliUtils } from "src/utils"; + +export class SyncCommand { + constructor(private syncService: SyncService) {} + + async run(cmdOptions: Record): Promise { + const normalizedOptions = new Options(cmdOptions); + if (normalizedOptions.last) { + return await this.getLastSync(); + } + + try { + await this.syncService.fullSync(normalizedOptions.force, true); + const res = new MessageResponse("Syncing complete.", null); + return Response.success(res); + } catch (e) { + return Response.error("Syncing failed: " + e.toString()); + } + } + + private async getLastSync() { + const lastSyncDate = await this.syncService.getLastSync(); + const res = new StringResponse(lastSyncDate == null ? null : lastSyncDate.toISOString()); + return Response.success(res); + } +} + +class Options { + last: boolean; + force: boolean; + + constructor(passedOptions: Record) { + this.last = CliUtils.convertBooleanOption(passedOptions?.last); + this.force = CliUtils.convertBooleanOption(passedOptions?.force); + } +} diff --git a/apps/cli/src/commands/unlock.command.ts b/apps/cli/src/commands/unlock.command.ts new file mode 100644 index 0000000000..9332a2a83c --- /dev/null +++ b/apps/cli/src/commands/unlock.command.ts @@ -0,0 +1,132 @@ +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { HashPurpose } from "jslib-common/enums/hashPurpose"; +import { Utils } from "jslib-common/misc/utils"; +import { SecretVerificationRequest } from "jslib-common/models/request/secretVerificationRequest"; +import { ConsoleLogService } from "jslib-common/services/consoleLog.service"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +import { CliUtils } from "../utils"; + +import { ConvertToKeyConnectorCommand } from "./convertToKeyConnector.command"; + +export class UnlockCommand { + constructor( + private cryptoService: CryptoService, + private stateService: StateService, + private cryptoFunctionService: CryptoFunctionService, + private apiService: ApiService, + private logService: ConsoleLogService, + private keyConnectorService: KeyConnectorService, + private environmentService: EnvironmentService, + private syncService: SyncService, + private logout: () => Promise + ) {} + + async run(password: string, cmdOptions: Record) { + const normalizedOptions = new Options(cmdOptions); + const passwordResult = await CliUtils.getPassword(password, normalizedOptions, this.logService); + + if (passwordResult instanceof Response) { + return passwordResult; + } else { + password = passwordResult; + } + + await this.setNewSessionKey(); + const email = await this.stateService.getEmail(); + const kdf = await this.stateService.getKdfType(); + const kdfIterations = await this.stateService.getKdfIterations(); + const key = await this.cryptoService.makeKey(password, email, kdf, kdfIterations); + const storedKeyHash = await this.cryptoService.getKeyHash(); + + let passwordValid = false; + if (key != null) { + if (storedKeyHash != null) { + passwordValid = await this.cryptoService.compareAndUpdateKeyHash(password, key); + } else { + const serverKeyHash = await this.cryptoService.hashPassword( + password, + key, + HashPurpose.ServerAuthorization + ); + const request = new SecretVerificationRequest(); + request.masterPasswordHash = serverKeyHash; + try { + await this.apiService.postAccountVerifyPassword(request); + passwordValid = true; + const localKeyHash = await this.cryptoService.hashPassword( + password, + key, + HashPurpose.LocalAuthorization + ); + await this.cryptoService.setKeyHash(localKeyHash); + } catch { + // Ignore + } + } + } + + if (passwordValid) { + await this.cryptoService.setKey(key); + + if (await this.keyConnectorService.getConvertAccountRequired()) { + const convertToKeyConnectorCommand = new ConvertToKeyConnectorCommand( + this.apiService, + this.keyConnectorService, + this.environmentService, + this.syncService, + this.logout + ); + const convertResponse = await convertToKeyConnectorCommand.run(); + if (!convertResponse.success) { + return convertResponse; + } + } + + return this.successResponse(); + } else { + return Response.error("Invalid master password."); + } + } + + private async setNewSessionKey() { + const key = await this.cryptoFunctionService.randomBytes(64); + process.env.BW_SESSION = Utils.fromBufferToB64(key); + } + + private async successResponse() { + const res = new MessageResponse( + "Your vault is now unlocked!", + "\n" + + "To unlock your vault, set your session key to the `BW_SESSION` environment variable. ex:\n" + + '$ export BW_SESSION="' + + process.env.BW_SESSION + + '"\n' + + '> $env:BW_SESSION="' + + process.env.BW_SESSION + + '"\n\n' + + "You can also pass the session key to any command with the `--session` option. ex:\n" + + "$ bw list items --session " + + process.env.BW_SESSION + ); + res.raw = process.env.BW_SESSION; + return Response.success(res); + } +} + +class Options { + passwordEnv: string; + passwordFile: string; + + constructor(passedOptions: Record) { + this.passwordEnv = passedOptions?.passwordenv || passedOptions?.passwordEnv; + this.passwordFile = passedOptions?.passwordfile || passedOptions?.passwordFile; + } +} diff --git a/apps/cli/src/flags.ts b/apps/cli/src/flags.ts new file mode 100644 index 0000000000..b0db46132d --- /dev/null +++ b/apps/cli/src/flags.ts @@ -0,0 +1,5 @@ +export type Flags = { + serve?: boolean; +}; + +export type FlagName = keyof Flags; diff --git a/apps/cli/src/locales/en/messages.json b/apps/cli/src/locales/en/messages.json new file mode 100644 index 0000000000..ca1e8317a8 --- /dev/null +++ b/apps/cli/src/locales/en/messages.json @@ -0,0 +1,47 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "emailTitle": { + "message": "Email" + }, + "noneFolder": { + "message": "No Folder" + }, + "importEncKeyError": { + "message": "Invalid file password." + }, + "importPasswordRequired": { + "message": "File is password protected, please provide a decryption password." + }, + "importFormatError": { + "message": "Data is not formatted correctly. Please check your import file and try again." + }, + "importNothingError": { + "message": "Nothing was imported." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "invalidMasterPassword": { + "message": "Invalid master password." + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "ssoKeyConnectorError": { + "message": "Key Connector error: make sure Key Connector is available and working correctly." + } +} diff --git a/apps/cli/src/models/request/organizationCollectionRequest.ts b/apps/cli/src/models/request/organizationCollectionRequest.ts new file mode 100644 index 0000000000..71106ef70b --- /dev/null +++ b/apps/cli/src/models/request/organizationCollectionRequest.ts @@ -0,0 +1,16 @@ +import { CollectionExport } from "jslib-common/models/export/collectionExport"; + +import { SelectionReadOnly } from "../selectionReadOnly"; + +export class OrganizationCollectionRequest extends CollectionExport { + static template(): OrganizationCollectionRequest { + const req = new OrganizationCollectionRequest(); + req.organizationId = "00000000-0000-0000-0000-000000000000"; + req.name = "Collection name"; + req.externalId = null; + req.groups = [SelectionReadOnly.template(), SelectionReadOnly.template()]; + return req; + } + + groups: SelectionReadOnly[]; +} diff --git a/apps/cli/src/models/response/attachmentResponse.ts b/apps/cli/src/models/response/attachmentResponse.ts new file mode 100644 index 0000000000..d67cfc9c2d --- /dev/null +++ b/apps/cli/src/models/response/attachmentResponse.ts @@ -0,0 +1,17 @@ +import { AttachmentView } from "jslib-common/models/view/attachmentView"; + +export class AttachmentResponse { + id: string; + fileName: string; + size: string; + sizeName: string; + url: string; + + constructor(o: AttachmentView) { + this.id = o.id; + this.fileName = o.fileName; + this.size = o.size; + this.sizeName = o.sizeName; + this.url = o.url; + } +} diff --git a/apps/cli/src/models/response/cipherResponse.ts b/apps/cli/src/models/response/cipherResponse.ts new file mode 100644 index 0000000000..3c61a5347b --- /dev/null +++ b/apps/cli/src/models/response/cipherResponse.ts @@ -0,0 +1,33 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { CipherWithIdExport } from "jslib-common/models/export/cipherWithIdsExport"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +import { AttachmentResponse } from "./attachmentResponse"; +import { LoginResponse } from "./loginResponse"; +import { PasswordHistoryResponse } from "./passwordHistoryResponse"; + +export class CipherResponse extends CipherWithIdExport implements BaseResponse { + object: string; + attachments: AttachmentResponse[]; + revisionDate: Date; + deletedDate: Date; + passwordHistory: PasswordHistoryResponse[]; + + constructor(o: CipherView) { + super(); + this.object = "item"; + this.build(o); + if (o.attachments != null) { + this.attachments = o.attachments.map((a) => new AttachmentResponse(a)); + } + this.revisionDate = o.revisionDate; + this.deletedDate = o.deletedDate; + if (o.passwordHistory != null) { + this.passwordHistory = o.passwordHistory.map((h) => new PasswordHistoryResponse(h)); + } + if (o.type === CipherType.Login && o.login != null) { + this.login = new LoginResponse(o.login); + } + } +} diff --git a/apps/cli/src/models/response/collectionResponse.ts b/apps/cli/src/models/response/collectionResponse.ts new file mode 100644 index 0000000000..6a7228b237 --- /dev/null +++ b/apps/cli/src/models/response/collectionResponse.ts @@ -0,0 +1,13 @@ +import { CollectionWithIdExport } from "jslib-common/models/export/collectionWithIdExport"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +export class CollectionResponse extends CollectionWithIdExport implements BaseResponse { + object: string; + + constructor(o: CollectionView) { + super(); + this.object = "collection"; + this.build(o); + } +} diff --git a/apps/cli/src/models/response/folderResponse.ts b/apps/cli/src/models/response/folderResponse.ts new file mode 100644 index 0000000000..f1bc18eb31 --- /dev/null +++ b/apps/cli/src/models/response/folderResponse.ts @@ -0,0 +1,13 @@ +import { FolderWithIdExport } from "jslib-common/models/export/folderWithIdExport"; +import { FolderView } from "jslib-common/models/view/folderView"; +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +export class FolderResponse extends FolderWithIdExport implements BaseResponse { + object: string; + + constructor(o: FolderView) { + super(); + this.object = "folder"; + this.build(o); + } +} diff --git a/apps/cli/src/models/response/loginResponse.ts b/apps/cli/src/models/response/loginResponse.ts new file mode 100644 index 0000000000..226ca4e8c5 --- /dev/null +++ b/apps/cli/src/models/response/loginResponse.ts @@ -0,0 +1,11 @@ +import { LoginExport } from "jslib-common/models/export/loginExport"; +import { LoginView } from "jslib-common/models/view/loginView"; + +export class LoginResponse extends LoginExport { + passwordRevisionDate: Date; + + constructor(o: LoginView) { + super(o); + this.passwordRevisionDate = o.passwordRevisionDate != null ? o.passwordRevisionDate : null; + } +} diff --git a/apps/cli/src/models/response/organizationCollectionResponse.ts b/apps/cli/src/models/response/organizationCollectionResponse.ts new file mode 100644 index 0000000000..66cb2ab90e --- /dev/null +++ b/apps/cli/src/models/response/organizationCollectionResponse.ts @@ -0,0 +1,15 @@ +import { CollectionView } from "jslib-common/models/view/collectionView"; + +import { SelectionReadOnly } from "../selectionReadOnly"; + +import { CollectionResponse } from "./collectionResponse"; + +export class OrganizationCollectionResponse extends CollectionResponse { + groups: SelectionReadOnly[]; + + constructor(o: CollectionView, groups: SelectionReadOnly[]) { + super(o); + this.object = "org-collection"; + this.groups = groups; + } +} diff --git a/apps/cli/src/models/response/organizationResponse.ts b/apps/cli/src/models/response/organizationResponse.ts new file mode 100644 index 0000000000..7ca1e96234 --- /dev/null +++ b/apps/cli/src/models/response/organizationResponse.ts @@ -0,0 +1,22 @@ +import { OrganizationUserStatusType } from "jslib-common/enums/organizationUserStatusType"; +import { OrganizationUserType } from "jslib-common/enums/organizationUserType"; +import { Organization } from "jslib-common/models/domain/organization"; +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +export class OrganizationResponse implements BaseResponse { + object: string; + id: string; + name: string; + status: OrganizationUserStatusType; + type: OrganizationUserType; + enabled: boolean; + + constructor(o: Organization) { + this.object = "organization"; + this.id = o.id; + this.name = o.name; + this.status = o.status; + this.type = o.type; + this.enabled = o.enabled; + } +} diff --git a/apps/cli/src/models/response/organizationUserResponse.ts b/apps/cli/src/models/response/organizationUserResponse.ts new file mode 100644 index 0000000000..6a200a8735 --- /dev/null +++ b/apps/cli/src/models/response/organizationUserResponse.ts @@ -0,0 +1,17 @@ +import { OrganizationUserStatusType } from "jslib-common/enums/organizationUserStatusType"; +import { OrganizationUserType } from "jslib-common/enums/organizationUserType"; +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +export class OrganizationUserResponse implements BaseResponse { + object: string; + id: string; + email: string; + name: string; + status: OrganizationUserStatusType; + type: OrganizationUserType; + twoFactorEnabled: boolean; + + constructor() { + this.object = "org-member"; + } +} diff --git a/apps/cli/src/models/response/passwordHistoryResponse.ts b/apps/cli/src/models/response/passwordHistoryResponse.ts new file mode 100644 index 0000000000..628ed13f84 --- /dev/null +++ b/apps/cli/src/models/response/passwordHistoryResponse.ts @@ -0,0 +1,11 @@ +import { PasswordHistoryView } from "jslib-common/models/view/passwordHistoryView"; + +export class PasswordHistoryResponse { + lastUsedDate: Date; + password: string; + + constructor(o: PasswordHistoryView) { + this.lastUsedDate = o.lastUsedDate; + this.password = o.password; + } +} diff --git a/apps/cli/src/models/response/sendAccessResponse.ts b/apps/cli/src/models/response/sendAccessResponse.ts new file mode 100644 index 0000000000..40b5d2d7da --- /dev/null +++ b/apps/cli/src/models/response/sendAccessResponse.ts @@ -0,0 +1,40 @@ +import { SendType } from "jslib-common/enums/sendType"; +import { SendAccessView } from "jslib-common/models/view/sendAccessView"; +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +import { SendFileResponse } from "./sendFileResponse"; +import { SendTextResponse } from "./sendTextResponse"; + +export class SendAccessResponse implements BaseResponse { + static template(): SendAccessResponse { + const req = new SendAccessResponse(); + req.name = "Send name"; + req.type = SendType.Text; + req.text = null; + req.file = null; + return req; + } + + object = "send-access"; + id: string; + name: string; + type: SendType; + text: SendTextResponse; + file: SendFileResponse; + + constructor(o?: SendAccessView) { + if (o == null) { + return; + } + this.id = o.id; + this.name = o.name; + this.type = o.type; + + if (o.type === SendType.Text && o.text != null) { + this.text = new SendTextResponse(o.text); + } + if (o.type === SendType.File && o.file != null) { + this.file = new SendFileResponse(o.file); + } + } +} diff --git a/apps/cli/src/models/response/sendFileResponse.ts b/apps/cli/src/models/response/sendFileResponse.ts new file mode 100644 index 0000000000..384646167a --- /dev/null +++ b/apps/cli/src/models/response/sendFileResponse.ts @@ -0,0 +1,36 @@ +import { SendFileView } from "jslib-common/models/view/sendFileView"; + +export class SendFileResponse { + static template(fileName = "file attachment location"): SendFileResponse { + const req = new SendFileResponse(); + req.fileName = fileName; + return req; + } + + static toView(file: SendFileResponse, view = new SendFileView()) { + if (file == null) { + return null; + } + + view.id = file.id; + view.size = file.size; + view.sizeName = file.sizeName; + view.fileName = file.fileName; + return view; + } + + id: string; + size: string; + sizeName: string; + fileName: string; + + constructor(o?: SendFileView) { + if (o == null) { + return; + } + this.id = o.id; + this.size = o.size; + this.sizeName = o.sizeName; + this.fileName = o.fileName; + } +} diff --git a/apps/cli/src/models/response/sendResponse.ts b/apps/cli/src/models/response/sendResponse.ts new file mode 100644 index 0000000000..c41e7aaceb --- /dev/null +++ b/apps/cli/src/models/response/sendResponse.ts @@ -0,0 +1,123 @@ +import { SendType } from "jslib-common/enums/sendType"; +import { Utils } from "jslib-common/misc/utils"; +import { SendView } from "jslib-common/models/view/sendView"; +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +import { SendFileResponse } from "./sendFileResponse"; +import { SendTextResponse } from "./sendTextResponse"; + +const dateProperties: string[] = [ + Utils.nameOf("deletionDate"), + Utils.nameOf("expirationDate"), +]; + +export class SendResponse implements BaseResponse { + static template(sendType?: SendType, deleteInDays = 7): SendResponse { + const req = new SendResponse(); + req.name = "Send name"; + req.notes = "Some notes about this send."; + req.type = sendType === SendType.File ? SendType.File : SendType.Text; + req.text = sendType === SendType.Text ? SendTextResponse.template() : null; + req.file = sendType === SendType.File ? SendFileResponse.template() : null; + req.maxAccessCount = null; + req.deletionDate = this.getStandardDeletionDate(deleteInDays); + req.expirationDate = null; + req.password = null; + req.disabled = false; + req.hideEmail = false; + return req; + } + + static toView(send: SendResponse, view = new SendView()): SendView { + if (send == null) { + return null; + } + + view.id = send.id; + view.accessId = send.accessId; + view.name = send.name; + view.notes = send.notes; + view.key = send.key == null ? null : Utils.fromB64ToArray(send.key); + view.type = send.type; + view.file = SendFileResponse.toView(send.file); + view.text = SendTextResponse.toView(send.text); + view.maxAccessCount = send.maxAccessCount; + view.accessCount = send.accessCount; + view.revisionDate = send.revisionDate; + view.deletionDate = send.deletionDate; + view.expirationDate = send.expirationDate; + view.password = send.password; + view.disabled = send.disabled; + view.hideEmail = send.hideEmail; + return view; + } + + static fromJson(json: string) { + return JSON.parse(json, (key, value) => { + if (dateProperties.includes(key)) { + return value == null ? null : new Date(value); + } + return value; + }); + } + + private static getStandardDeletionDate(days: number) { + const d = new Date(); + d.setTime(d.getTime() + days * 86400000); // ms per day + return d; + } + + object = "send"; + id: string; + accessId: string; + accessUrl: string; + name: string; + notes: string; + key: string; + type: SendType; + text: SendTextResponse; + file: SendFileResponse; + maxAccessCount?: number; + accessCount: number; + revisionDate: Date; + deletionDate: Date; + expirationDate: Date; + password: string; + passwordSet: boolean; + disabled: boolean; + hideEmail: boolean; + + constructor(o?: SendView, webVaultUrl?: string) { + if (o == null) { + return; + } + this.id = o.id; + this.accessId = o.accessId; + let sendLinkBaseUrl = webVaultUrl; + if (sendLinkBaseUrl == null) { + sendLinkBaseUrl = "https://send.bitwarden.com/#"; + } else { + sendLinkBaseUrl += "/#/send/"; + } + this.accessUrl = sendLinkBaseUrl + this.accessId + "/" + o.urlB64Key; + this.name = o.name; + this.notes = o.notes; + this.key = Utils.fromBufferToB64(o.key); + this.type = o.type; + this.maxAccessCount = o.maxAccessCount; + this.accessCount = o.accessCount; + this.revisionDate = o.revisionDate; + this.deletionDate = o.deletionDate; + this.expirationDate = o.expirationDate; + this.passwordSet = o.password != null; + this.disabled = o.disabled; + this.hideEmail = o.hideEmail; + + if (o.type === SendType.Text && o.text != null) { + this.text = new SendTextResponse(o.text); + } + if (o.type === SendType.File && o.file != null) { + this.file = new SendFileResponse(o.file); + } + } +} diff --git a/apps/cli/src/models/response/sendTextResponse.ts b/apps/cli/src/models/response/sendTextResponse.ts new file mode 100644 index 0000000000..68decd9fb7 --- /dev/null +++ b/apps/cli/src/models/response/sendTextResponse.ts @@ -0,0 +1,30 @@ +import { SendTextView } from "jslib-common/models/view/sendTextView"; + +export class SendTextResponse { + static template(text = "Text contained in the send.", hidden = false): SendTextResponse { + const req = new SendTextResponse(); + req.text = text; + req.hidden = hidden; + return req; + } + + static toView(text: SendTextResponse, view = new SendTextView()) { + if (text == null) { + return null; + } + + view.text = text.text; + view.hidden = text.hidden; + return view; + } + text: string; + hidden: boolean; + + constructor(o?: SendTextView) { + if (o == null) { + return; + } + this.text = o.text; + this.hidden = o.hidden; + } +} diff --git a/apps/cli/src/models/response/templateResponse.ts b/apps/cli/src/models/response/templateResponse.ts new file mode 100644 index 0000000000..aa494af342 --- /dev/null +++ b/apps/cli/src/models/response/templateResponse.ts @@ -0,0 +1,11 @@ +import { BaseResponse } from "jslib-node/cli/models/response/baseResponse"; + +export class TemplateResponse implements BaseResponse { + object: string; + template: any; + + constructor(template: any) { + this.object = "template"; + this.template = template; + } +} diff --git a/apps/cli/src/models/selectionReadOnly.ts b/apps/cli/src/models/selectionReadOnly.ts new file mode 100644 index 0000000000..48c4399120 --- /dev/null +++ b/apps/cli/src/models/selectionReadOnly.ts @@ -0,0 +1,15 @@ +export class SelectionReadOnly { + static template(): SelectionReadOnly { + return new SelectionReadOnly("00000000-0000-0000-0000-000000000000", false, false); + } + + id: string; + readOnly: boolean; + hidePasswords: boolean; + + constructor(id: string, readOnly: boolean, hidePasswords: boolean) { + this.id = id; + this.readOnly = readOnly; + this.hidePasswords = hidePasswords || false; + } +} diff --git a/apps/cli/src/program.ts b/apps/cli/src/program.ts new file mode 100644 index 0000000000..4299eb34d3 --- /dev/null +++ b/apps/cli/src/program.ts @@ -0,0 +1,546 @@ +import * as chalk from "chalk"; +import * as program from "commander"; + +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { KeySuffixOptions } from "jslib-common/enums/keySuffixOptions"; +import { BaseProgram } from "jslib-node/cli/baseProgram"; +import { LogoutCommand } from "jslib-node/cli/commands/logout.command"; +import { UpdateCommand } from "jslib-node/cli/commands/update.command"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +import { Main } from "./bw"; +import { CompletionCommand } from "./commands/completion.command"; +import { ConfigCommand } from "./commands/config.command"; +import { EncodeCommand } from "./commands/encode.command"; +import { GenerateCommand } from "./commands/generate.command"; +import { LockCommand } from "./commands/lock.command"; +import { LoginCommand } from "./commands/login.command"; +import { ServeCommand } from "./commands/serve.command"; +import { StatusCommand } from "./commands/status.command"; +import { SyncCommand } from "./commands/sync.command"; +import { UnlockCommand } from "./commands/unlock.command"; +import { TemplateResponse } from "./models/response/templateResponse"; +import { CliUtils } from "./utils"; + +const writeLn = CliUtils.writeLn; + +export class Program extends BaseProgram { + constructor(protected main: Main) { + super(main.stateService, writeLn); + } + + async register() { + program + .option("--pretty", "Format output. JSON is tabbed with two spaces.") + .option("--raw", "Return raw output instead of a descriptive message.") + .option("--response", "Return a JSON formatted version of response output.") + .option("--cleanexit", "Exit with a success exit code (0) unless an error is thrown.") + .option("--quiet", "Don't return anything to stdout.") + .option("--nointeraction", "Do not prompt for interactive user input.") + .option("--session ", "Pass session key instead of reading from env.") + .version(await this.main.platformUtilsService.getApplicationVersion(), "-v, --version"); + + program.on("option:pretty", () => { + process.env.BW_PRETTY = "true"; + }); + + program.on("option:raw", () => { + process.env.BW_RAW = "true"; + }); + + program.on("option:quiet", () => { + process.env.BW_QUIET = "true"; + }); + + program.on("option:response", () => { + process.env.BW_RESPONSE = "true"; + }); + + program.on("option:cleanexit", () => { + process.env.BW_CLEANEXIT = "true"; + }); + + program.on("option:nointeraction", () => { + process.env.BW_NOINTERACTION = "true"; + }); + + program.on("option:session", (key) => { + process.env.BW_SESSION = key; + }); + + program.on("command:*", () => { + writeLn(chalk.redBright("Invalid command: " + program.args.join(" ")), false, true); + writeLn("See --help for a list of available commands.", true, true); + process.exitCode = 1; + }); + + program.on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw login"); + writeLn(" bw lock"); + writeLn(" bw unlock myPassword321"); + writeLn(" bw list --help"); + writeLn(" bw list items --search google"); + writeLn(" bw get item 99ee88d2-6046-4ea7-92c2-acac464b1412"); + writeLn(" bw get password google.com"); + writeLn(' echo \'{"name":"My Folder"}\' | bw encode'); + writeLn(" bw create folder eyJuYW1lIjoiTXkgRm9sZGVyIn0K"); + writeLn( + " bw edit folder c7c7b60b-9c61-40f2-8ccd-36c49595ed72 eyJuYW1lIjoiTXkgRm9sZGVyMiJ9Cg==" + ); + writeLn(" bw delete item 99ee88d2-6046-4ea7-92c2-acac464b1412"); + writeLn(" bw generate -lusn --length 18"); + writeLn(" bw config server https://bitwarden.example.com"); + writeLn(" bw send -f ./file.ext"); + writeLn(' bw send "text to send"'); + writeLn(' echo "text to send" | bw send'); + writeLn( + " bw receive https://vault.bitwarden.com/#/send/rg3iuoS_Akm2gqy6ADRHmg/Ht7dYjsqjmgqUM3rjzZDSQ" + ); + writeLn("", true); + }); + + program + .command("login [email] [password]") + .description("Log into a user account.") + .option("--method ", "Two-step login method.") + .option("--code ", "Two-step login code.") + .option("--sso", "Log in with Single-Sign On.") + .option("--apikey", "Log in with an Api Key.") + .option("--passwordenv ", "Environment variable storing your password") + .option( + "--passwordfile ", + "Path to a file containing your password as its first line" + ) + .option("--check", "Check login status.", async () => { + const authed = await this.main.stateService.getIsAuthenticated(); + if (authed) { + const res = new MessageResponse("You are logged in!", null); + this.processResponse(Response.success(res), true); + } + this.processResponse(Response.error("You are not logged in."), true); + }) + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" See docs for valid `method` enum values."); + writeLn(""); + writeLn(" Pass `--raw` option to only return the session key."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw login"); + writeLn(" bw login john@example.com myPassword321 --raw"); + writeLn(" bw login john@example.com myPassword321 --method 1 --code 249213"); + writeLn(" bw login --sso"); + writeLn("", true); + }) + .action(async (email: string, password: string, options: program.OptionValues) => { + if (!options.check) { + await this.exitIfAuthed(); + const command = new LoginCommand( + this.main.authService, + this.main.apiService, + this.main.cryptoFunctionService, + this.main.i18nService, + this.main.environmentService, + this.main.passwordGenerationService, + this.main.platformUtilsService, + this.main.stateService, + this.main.cryptoService, + this.main.policyService, + this.main.twoFactorService, + this.main.syncService, + this.main.keyConnectorService, + async () => await this.main.logout() + ); + const response = await command.run(email, password, options); + this.processResponse(response); + } + }); + + program + .command("logout") + .description("Log out of the current user account.") + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw logout"); + writeLn("", true); + }) + .action(async (cmd) => { + await this.exitIfNotAuthed(); + const command = new LogoutCommand( + this.main.authService, + this.main.i18nService, + async () => await this.main.logout() + ); + const response = await command.run(); + this.processResponse(response); + }); + + program + .command("lock") + .description("Lock the vault and destroy active session keys.") + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw lock"); + writeLn("", true); + }) + .action(async (cmd) => { + await this.exitIfNotAuthed(); + + if (await this.main.keyConnectorService.getUsesKeyConnector()) { + const logoutCommand = new LogoutCommand( + this.main.authService, + this.main.i18nService, + async () => await this.main.logout() + ); + await logoutCommand.run(); + this.processResponse( + Response.error( + "You cannot lock your vault because you are using Key Connector. " + + "To protect your vault, you have been logged out." + ), + true + ); + return; + } + + const command = new LockCommand(this.main.vaultTimeoutService); + const response = await command.run(); + this.processResponse(response); + }); + + program + .command("unlock [password]") + .description("Unlock the vault and return a new session key.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" After unlocking, any previous session keys will no longer be valid."); + writeLn(""); + writeLn(" Pass `--raw` option to only return the session key."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw unlock"); + writeLn(" bw unlock myPassword321"); + writeLn(" bw unlock myPassword321 --raw"); + writeLn("", true); + }) + .option("--check", "Check lock status.", async () => { + await this.exitIfNotAuthed(); + + const authStatus = await this.main.authService.getAuthStatus(); + if (authStatus === AuthenticationStatus.Unlocked) { + const res = new MessageResponse("Vault is unlocked!", null); + this.processResponse(Response.success(res), true); + } else { + this.processResponse(Response.error("Vault is locked."), true); + } + }) + .option("--passwordenv ", "Environment variable storing your password") + .option( + "--passwordfile ", + "Path to a file containing your password as its first line" + ) + .action(async (password, cmd) => { + if (!cmd.check) { + await this.exitIfNotAuthed(); + const command = new UnlockCommand( + this.main.cryptoService, + this.main.stateService, + this.main.cryptoFunctionService, + this.main.apiService, + this.main.logService, + this.main.keyConnectorService, + this.main.environmentService, + this.main.syncService, + async () => await this.main.logout() + ); + const response = await command.run(password, cmd); + this.processResponse(response); + } + }); + + program + .command("sync") + .description("Pull the latest vault data from server.") + .option("-f, --force", "Force a full sync.") + .option("--last", "Get the last sync date.") + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw sync"); + writeLn(" bw sync -f"); + writeLn(" bw sync --last"); + writeLn("", true); + }) + .action(async (cmd) => { + await this.exitIfLocked(); + const command = new SyncCommand(this.main.syncService); + const response = await command.run(cmd); + this.processResponse(response); + }); + + program + .command("generate") + .description("Generate a password/passphrase.") + .option("-u, --uppercase", "Include uppercase characters.") + .option("-l, --lowercase", "Include lowercase characters.") + .option("-n, --number", "Include numeric characters.") + .option("-s, --special", "Include special characters.") + .option("-p, --passphrase", "Generate a passphrase.") + .option("--length ", "Length of the password.") + .option("--words ", "Number of words.") + .option("--separator ", "Word separator.") + .option("-c, --capitalize", "Title case passphrase.") + .option("--includeNumber", "Passphrase includes number.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" Default options are `-uln --length 14`."); + writeLn(""); + writeLn(" Minimum `length` is 5."); + writeLn(""); + writeLn(" Minimum `words` is 3."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw generate"); + writeLn(" bw generate -u -l --length 18"); + writeLn(" bw generate -ulns --length 25"); + writeLn(" bw generate -ul"); + writeLn(" bw generate -p --separator _"); + writeLn(" bw generate -p --words 5 --separator space"); + writeLn("", true); + }) + .action(async (options) => { + const command = new GenerateCommand( + this.main.passwordGenerationService, + this.main.stateService + ); + const response = await command.run(options); + this.processResponse(response); + }); + + program + .command("encode") + .description("Base 64 encode stdin.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" Use to create `encodedJson` for `create` and `edit` commands."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(' echo \'{"name":"My Folder"}\' | bw encode'); + writeLn("", true); + }) + .action(async () => { + const command = new EncodeCommand(); + const response = await command.run(); + this.processResponse(response); + }); + + program + .command("config [value]") + .description("Configure CLI settings.") + .option( + "--web-vault ", + "Provides a custom web vault URL that differs from the base URL." + ) + .option("--api ", "Provides a custom API URL that differs from the base URL.") + .option("--identity ", "Provides a custom identity URL that differs from the base URL.") + .option( + "--icons ", + "Provides a custom icons service URL that differs from the base URL." + ) + .option( + "--notifications ", + "Provides a custom notifications URL that differs from the base URL." + ) + .option("--events ", "Provides a custom events URL that differs from the base URL.") + .option("--key-connector ", "Provides the URL for your Key Connector server.") + .on("--help", () => { + writeLn("\n Settings:"); + writeLn(""); + writeLn(" server - On-premises hosted installation URL."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw config server"); + writeLn(" bw config server https://bw.company.com"); + writeLn(" bw config server bitwarden.com"); + writeLn( + " bw config server --api http://localhost:4000 --identity http://localhost:33656" + ); + writeLn("", true); + }) + .action(async (setting, value, options) => { + const command = new ConfigCommand(this.main.environmentService); + const response = await command.run(setting, value, options); + this.processResponse(response); + }); + + program + .command("update") + .description("Check for updates.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" Returns the URL to download the newest version of this CLI tool."); + writeLn(""); + writeLn(" Use the `--raw` option to return only the download URL for the update."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw update"); + writeLn(" bw update --raw"); + writeLn("", true); + }) + .action(async () => { + const command = new UpdateCommand( + this.main.platformUtilsService, + this.main.i18nService, + "cli", + "bw", + true + ); + const response = await command.run(); + this.processResponse(response); + }); + + program + .command("completion") + .description("Generate shell completions.") + .option("--shell ", "Shell to generate completions for.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" Valid shells are `zsh`."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw completion --shell zsh"); + writeLn("", true); + }) + .action(async (options: program.OptionValues, cmd: program.Command) => { + const command = new CompletionCommand(); + const response = await command.run(options); + this.processResponse(response); + }); + + program + .command("status") + .description("Show server, last sync, user information, and vault status.") + .on("--help", () => { + writeLn(""); + writeLn(""); + writeLn(" Example return value:"); + writeLn(""); + writeLn(" {"); + writeLn(' "serverUrl": "https://bitwarden.example.com",'); + writeLn(' "lastSync": "2020-06-16T06:33:51.419Z",'); + writeLn(' "userEmail": "user@example.com,'); + writeLn(' "userId": "00000000-0000-0000-0000-000000000000",'); + writeLn(' "status": "locked"'); + writeLn(" }"); + writeLn(""); + writeLn(" Notes:"); + writeLn(""); + writeLn(" `status` is one of:"); + writeLn(" - `unauthenticated` when you are not logged in"); + writeLn(" - `locked` when you are logged in and the vault is locked"); + writeLn(" - `unlocked` when you are logged in and the vault is unlocked"); + writeLn("", true); + }) + .action(async () => { + const command = new StatusCommand( + this.main.environmentService, + this.main.syncService, + this.main.stateService, + this.main.authService + ); + const response = await command.run(); + this.processResponse(response); + }); + + if (CliUtils.flagEnabled("serve")) { + program + .command("serve") + .description("Start a RESTful API webserver.") + .option("--hostname ", "The hostname to bind your API webserver to.") + .option("--port ", "The port to run your API webserver on.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" Default hostname is `localhost`."); + writeLn(" Use hostname `all` for no hostname binding."); + writeLn(" Default port is `8087`."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw serve"); + writeLn(" bw serve --port 8080"); + writeLn(" bw serve --hostname bwapi.mydomain.com --port 80"); + writeLn("", true); + }) + .action(async (cmd) => { + await this.exitIfNotAuthed(); + const command = new ServeCommand(this.main); + await command.run(cmd); + }); + } + } + + protected processResponse(response: Response, exitImmediately = false) { + super.processResponse(response, exitImmediately, () => { + if (response.data.object === "template") { + return this.getJson((response.data as TemplateResponse).template); + } + return null; + }); + } + + protected async exitIfLocked() { + await this.exitIfNotAuthed(); + if (await this.main.cryptoService.hasKeyInMemory()) { + return; + } else if (await this.main.cryptoService.hasKeyStored(KeySuffixOptions.Auto)) { + // load key into memory + await this.main.cryptoService.getKey(); + } else if (process.env.BW_NOINTERACTION !== "true") { + // must unlock + if (await this.main.keyConnectorService.getUsesKeyConnector()) { + const response = Response.error( + "Your vault is locked. You must unlock your vault using your session key.\n" + + "If you do not have your session key, you can get a new one by logging out and logging in again." + ); + this.processResponse(response, true); + } else { + const command = new UnlockCommand( + this.main.cryptoService, + this.main.stateService, + this.main.cryptoFunctionService, + this.main.apiService, + this.main.logService, + this.main.keyConnectorService, + this.main.environmentService, + this.main.syncService, + this.main.logout + ); + const response = await command.run(null, null); + if (!response.success) { + this.processResponse(response, true); + } + } + } else { + this.processResponse(Response.error("Vault is locked."), true); + } + } +} diff --git a/apps/cli/src/send.program.ts b/apps/cli/src/send.program.ts new file mode 100644 index 0000000000..15d1d766b9 --- /dev/null +++ b/apps/cli/src/send.program.ts @@ -0,0 +1,334 @@ +import * as fs from "fs"; +import * as path from "path"; + +import * as chalk from "chalk"; +import * as program from "commander"; + +import { SendType } from "jslib-common/enums/sendType"; +import { Utils } from "jslib-common/misc/utils"; +import { Response } from "jslib-node/cli/models/response"; + +import { Main } from "./bw"; +import { GetCommand } from "./commands/get.command"; +import { SendCreateCommand } from "./commands/send/create.command"; +import { SendDeleteCommand } from "./commands/send/delete.command"; +import { SendEditCommand } from "./commands/send/edit.command"; +import { SendGetCommand } from "./commands/send/get.command"; +import { SendListCommand } from "./commands/send/list.command"; +import { SendReceiveCommand } from "./commands/send/receive.command"; +import { SendRemovePasswordCommand } from "./commands/send/removePassword.command"; +import { SendFileResponse } from "./models/response/sendFileResponse"; +import { SendResponse } from "./models/response/sendResponse"; +import { SendTextResponse } from "./models/response/sendTextResponse"; +import { Program } from "./program"; +import { CliUtils } from "./utils"; + +const writeLn = CliUtils.writeLn; + +export class SendProgram extends Program { + constructor(main: Main) { + super(main); + } + + async register() { + program.addCommand(this.sendCommand()); + // receive is accessible both at `bw receive` and `bw send receive` + program.addCommand(this.receiveCommand()); + } + + private sendCommand(): program.Command { + return new program.Command("send") + .arguments("") + .description( + "Work with Bitwarden sends. A Send can be quickly created using this command or subcommands can be used to fine-tune the Send", + { + data: "The data to Send. Specify as a filepath with the --file option", + } + ) + .option("-f, --file", "Specifies that is a filepath") + .option( + "-d, --deleteInDays ", + "The number of days in the future to set deletion date, defaults to 7", + "7" + ) + .option("-a, --maxAccessCount ", "The amount of max possible accesses.") + .option("--hidden", "Hide in web by default. Valid only if --file is not set.") + .option( + "-n, --name ", + "The name of the Send. Defaults to a guid for text Sends and the filename for files." + ) + .option("--notes ", "Notes to add to the Send.") + .option( + "--fullObject", + "Specifies that the full Send object should be returned rather than just the access url." + ) + .addCommand(this.listCommand()) + .addCommand(this.templateCommand()) + .addCommand(this.getCommand()) + .addCommand(this.receiveCommand()) + .addCommand(this.createCommand()) + .addCommand(this.editCommand()) + .addCommand(this.removePasswordCommand()) + .addCommand(this.deleteCommand()) + .action(async (data: string, options: program.OptionValues) => { + const encodedJson = this.makeSendJson(data, options); + + let response: Response; + if (encodedJson instanceof Response) { + response = encodedJson; + } else { + response = await this.runCreate(encodedJson, options); + } + + this.processResponse(response); + }); + } + + private receiveCommand(): program.Command { + return new program.Command("receive") + .arguments("") + .description("Access a Bitwarden Send from a url") + .option("--password ", "Password needed to access the Send.") + .option("--passwordenv ", "Environment variable storing the Send's password") + .option( + "--passwordfile ", + "Path to a file containing the Sends password as its first line" + ) + .option("--obj", "Return the Send's json object rather than the Send's content") + .option("--output ", "Specify a file path to save a File-type Send to") + .on("--help", () => { + writeLn(""); + writeLn( + "If a password is required, the provided password is used or the user is prompted." + ); + writeLn("", true); + }) + .action(async (url: string, options: program.OptionValues) => { + const cmd = new SendReceiveCommand( + this.main.apiService, + this.main.cryptoService, + this.main.cryptoFunctionService, + this.main.platformUtilsService, + this.main.environmentService + ); + const response = await cmd.run(url, options); + this.processResponse(response); + }); + } + + private listCommand(): program.Command { + return new program.Command("list") + + .description("List all the Sends owned by you") + .on("--help", () => { + writeLn(chalk("This is in the list command")); + }) + .action(async (options: program.OptionValues) => { + await this.exitIfLocked(); + const cmd = new SendListCommand( + this.main.sendService, + this.main.environmentService, + this.main.searchService + ); + const response = await cmd.run(options); + this.processResponse(response); + }); + } + + private templateCommand(): program.Command { + return new program.Command("template") + .arguments("") + .description("Get json templates for send objects", { + object: "Valid objects are: send, send.text, send.file", + }) + .action(async (object) => { + const cmd = new GetCommand( + this.main.cipherService, + this.main.folderService, + this.main.collectionService, + this.main.totpService, + this.main.auditService, + this.main.cryptoService, + this.main.stateService, + this.main.searchService, + this.main.apiService, + this.main.organizationService + ); + const response = await cmd.run("template", object, null); + this.processResponse(response); + }); + } + + private getCommand(): program.Command { + return new program.Command("get") + .arguments("") + .description("Get Sends owned by you.") + .option("--output ", "Output directory or filename for attachment.") + .option("--text", "Specifies to return the text content of a Send") + .on("--help", () => { + writeLn(""); + writeLn(" Id:"); + writeLn(""); + writeLn(" Search term or Send's globally unique `id`."); + writeLn(""); + writeLn(" If raw output is specified and no output filename or directory is given for"); + writeLn(" an attachment query, the attachment content is written to stdout."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw get send searchText"); + writeLn(" bw get send id"); + writeLn(" bw get send searchText --text"); + writeLn(" bw get send searchText --file"); + writeLn(" bw get send searchText --file --output ../Photos/photo.jpg"); + writeLn(" bw get send searchText --file --raw"); + writeLn("", true); + }) + .action(async (id: string, options: program.OptionValues) => { + await this.exitIfLocked(); + const cmd = new SendGetCommand( + this.main.sendService, + this.main.environmentService, + this.main.searchService, + this.main.cryptoService + ); + const response = await cmd.run(id, options); + this.processResponse(response); + }); + } + + private createCommand(): program.Command { + return new program.Command("create") + .arguments("[encodedJson]") + .description("create a Send", { + encodedJson: "JSON object to upload. Can also be piped in through stdin.", + }) + .option("--file ", "file to Send. Can also be specified in parent's JSON.") + .option("--text ", "text to Send. Can also be specified in parent's JSON.") + .option("--hidden", "text hidden flag. Valid only with the --text option.") + .option( + "--password ", + "optional password to access this Send. Can also be specified in JSON" + ) + .on("--help", () => { + writeLn(""); + writeLn("Note:"); + writeLn(" Options specified in JSON take precedence over command options"); + writeLn("", true); + }) + .action( + async ( + encodedJson: string, + options: program.OptionValues, + args: { parent: program.Command } + ) => { + // Work-around to support `--fullObject` option for `send create --fullObject` + // Calling `option('--fullObject', ...)` above won't work due to Commander doesn't like same option + // to be defind on both parent-command and sub-command + const { fullObject = false } = args.parent.opts(); + const mergedOptions = { + ...options, + fullObject: fullObject, + }; + + const response = await this.runCreate(encodedJson, mergedOptions); + this.processResponse(response); + } + ); + } + + private editCommand(): program.Command { + return new program.Command("edit") + .arguments("[encodedJson]") + .description("edit a Send", { + encodedJson: + "Updated JSON object to save. If not provided, encodedJson is read from stdin.", + }) + .option("--itemid ", "Overrides the itemId provided in [encodedJson]") + .on("--help", () => { + writeLn(""); + writeLn("Note:"); + writeLn(" You cannot update a File-type Send's file. Just delete and remake it"); + writeLn("", true); + }) + .action(async (encodedJson: string, options: program.OptionValues) => { + await this.exitIfLocked(); + const getCmd = new SendGetCommand( + this.main.sendService, + this.main.environmentService, + this.main.searchService, + this.main.cryptoService + ); + const cmd = new SendEditCommand(this.main.sendService, this.main.stateService, getCmd); + const response = await cmd.run(encodedJson, options); + this.processResponse(response); + }); + } + + private deleteCommand(): program.Command { + return new program.Command("delete") + .arguments("") + .description("delete a Send", { + id: "The id of the Send to delete.", + }) + .action(async (id: string) => { + await this.exitIfLocked(); + const cmd = new SendDeleteCommand(this.main.sendService); + const response = await cmd.run(id); + this.processResponse(response); + }); + } + + private removePasswordCommand(): program.Command { + return new program.Command("remove-password") + .arguments("") + .description("removes the saved password from a Send.", { + id: "The id of the Send to alter.", + }) + .action(async (id: string) => { + await this.exitIfLocked(); + const cmd = new SendRemovePasswordCommand(this.main.sendService); + const response = await cmd.run(id); + this.processResponse(response); + }); + } + + private makeSendJson(data: string, options: program.OptionValues) { + let sendFile = null; + let sendText = null; + let name = Utils.newGuid(); + let type = SendType.Text; + if (options.file != null) { + data = path.resolve(data); + if (!fs.existsSync(data)) { + return Response.badRequest("data path does not exist"); + } + + sendFile = SendFileResponse.template(data); + name = path.basename(data); + type = SendType.File; + } else { + sendText = SendTextResponse.template(data, options.hidden); + } + + const template = Utils.assign(SendResponse.template(null, options.deleteInDays), { + name: options.name ?? name, + notes: options.notes, + file: sendFile, + text: sendText, + type: type, + }); + + return Buffer.from(JSON.stringify(template), "utf8").toString("base64"); + } + + private async runCreate(encodedJson: string, options: program.OptionValues) { + await this.exitIfLocked(); + const cmd = new SendCreateCommand( + this.main.sendService, + this.main.stateService, + this.main.environmentService + ); + return await cmd.run(encodedJson, options); + } +} diff --git a/apps/cli/src/services/i18n.service.ts b/apps/cli/src/services/i18n.service.ts new file mode 100644 index 0000000000..d408c4ef6f --- /dev/null +++ b/apps/cli/src/services/i18n.service.ts @@ -0,0 +1,20 @@ +import * as fs from "fs"; +import * as path from "path"; + +import { I18nService as BaseI18nService } from "jslib-common/services/i18n.service"; + +export class I18nService extends BaseI18nService { + constructor(systemLanguage: string, localesDirectory: string) { + super(systemLanguage, localesDirectory, (formattedLocale: string) => { + const filePath = path.join( + __dirname, + this.localesDirectory + "/" + formattedLocale + "/messages.json" + ); + const localesJson = fs.readFileSync(filePath, "utf8"); + const locales = JSON.parse(localesJson.replace(/^\uFEFF/, "")); // strip the BOM + return Promise.resolve(locales); + }); + + this.supportedTranslationLocales = ["en"]; + } +} diff --git a/apps/cli/src/services/lowdbStorage.service.ts b/apps/cli/src/services/lowdbStorage.service.ts new file mode 100644 index 0000000000..e46997d529 --- /dev/null +++ b/apps/cli/src/services/lowdbStorage.service.ts @@ -0,0 +1,40 @@ +import * as lock from "proper-lockfile"; +import { OperationOptions } from "retry"; + +import { LogService } from "jslib-common/abstractions/log.service"; +import { Utils } from "jslib-common/misc/utils"; +import { LowdbStorageService as LowdbStorageServiceBase } from "jslib-node/services/lowdbStorage.service"; + +const retries: OperationOptions = { + retries: 50, + minTimeout: 100, + maxTimeout: 250, + factor: 2, +}; + +export class LowdbStorageService extends LowdbStorageServiceBase { + constructor( + logService: LogService, + defaults?: any, + dir?: string, + allowCache = false, + private requireLock = false + ) { + super(logService, defaults, dir, allowCache); + } + + protected async lockDbFile(action: () => T): Promise { + if (this.requireLock && !Utils.isNullOrWhitespace(this.dataFilePath)) { + this.logService.info("acquiring db file lock"); + return await lock.lock(this.dataFilePath, { retries: retries }).then((release) => { + try { + return action(); + } finally { + release(); + } + }); + } else { + return action(); + } + } +} diff --git a/apps/cli/src/services/nodeEnvSecureStorage.service.ts b/apps/cli/src/services/nodeEnvSecureStorage.service.ts new file mode 100644 index 0000000000..facba943fc --- /dev/null +++ b/apps/cli/src/services/nodeEnvSecureStorage.service.ts @@ -0,0 +1,103 @@ +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { StorageService } from "jslib-common/abstractions/storage.service"; +import { Utils } from "jslib-common/misc/utils"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; + +export class NodeEnvSecureStorageService implements StorageService { + constructor( + private storageService: StorageService, + private logService: LogService, + private cryptoService: () => CryptoService + ) {} + + async get(key: string): Promise { + const value = await this.storageService.get(this.makeProtectedStorageKey(key)); + if (value == null) { + return null; + } + const obj = await this.decrypt(value); + return obj as any; + } + + async has(key: string): Promise { + return (await this.get(key)) != null; + } + + async save(key: string, obj: any): Promise { + if (obj == null) { + return this.remove(key); + } + + if (obj !== null && typeof obj !== "string") { + throw new Error("Only string storage is allowed."); + } + const protectedObj = await this.encrypt(obj); + await this.storageService.save(this.makeProtectedStorageKey(key), protectedObj); + } + + remove(key: string): Promise { + return this.storageService.remove(this.makeProtectedStorageKey(key)); + } + + private async encrypt(plainValue: string): Promise { + const sessionKey = this.getSessionKey(); + if (sessionKey == null) { + throw new Error("No session key available."); + } + const encValue = await this.cryptoService().encryptToBytes( + Utils.fromB64ToArray(plainValue).buffer, + sessionKey + ); + if (encValue == null) { + throw new Error("Value didn't encrypt."); + } + + return Utils.fromBufferToB64(encValue.buffer); + } + + private async decrypt(encValue: string): Promise { + try { + const sessionKey = this.getSessionKey(); + if (sessionKey == null) { + return null; + } + + const decValue = await this.cryptoService().decryptFromBytes( + Utils.fromB64ToArray(encValue).buffer, + sessionKey + ); + if (decValue == null) { + this.logService.info("Failed to decrypt."); + return null; + } + + return Utils.fromBufferToB64(decValue); + } catch (e) { + this.logService.info("Decrypt error."); + return null; + } + } + + private getSessionKey() { + try { + if (process.env.BW_SESSION != null) { + const sessionBuffer = Utils.fromB64ToArray(process.env.BW_SESSION).buffer; + if (sessionBuffer != null) { + const sessionKey = new SymmetricCryptoKey(sessionBuffer); + if (sessionBuffer != null) { + return sessionKey; + } + } + } + } catch (e) { + this.logService.info("Session key is invalid."); + } + + return null; + } + + private makeProtectedStorageKey(key: string) { + return "__PROTECTED__" + key; + } +} diff --git a/apps/cli/src/utils.ts b/apps/cli/src/utils.ts new file mode 100644 index 0000000000..deb4085398 --- /dev/null +++ b/apps/cli/src/utils.ts @@ -0,0 +1,270 @@ +import * as fs from "fs"; +import * as path from "path"; + +import * as inquirer from "inquirer"; +import * as JSZip from "jszip"; + +import { LogService } from "jslib-common/abstractions/log.service"; +import { NodeUtils } from "jslib-common/misc/nodeUtils"; +import { Utils } from "jslib-common/misc/utils"; +import { Organization } from "jslib-common/models/domain/organization"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; +import { Response } from "jslib-node/cli/models/response"; +import { MessageResponse } from "jslib-node/cli/models/response/messageResponse"; + +import { FlagName, Flags } from "./flags"; + +export class CliUtils { + static writeLn(s: string, finalLine = false, error = false) { + const stream = error ? process.stderr : process.stdout; + if (finalLine && (process.platform === "win32" || !stream.isTTY)) { + stream.write(s); + } else { + stream.write(s + "\n"); + } + } + + static readFile(input: string): Promise { + return new Promise((resolve, reject) => { + let p: string = null; + if (input != null && input !== "") { + const osInput = path.join(input); + if (osInput.indexOf(path.sep) === -1) { + p = path.join(process.cwd(), osInput); + } else { + p = osInput; + } + } else { + reject("You must specify a file path."); + } + fs.readFile(p, "utf8", (err, data) => { + if (err != null) { + reject(err.message); + } + resolve(data); + }); + }); + } + + static extract1PuxContent(input: string): Promise { + return new Promise((resolve, reject) => { + let p: string = null; + if (input != null && input !== "") { + const osInput = path.join(input); + if (osInput.indexOf(path.sep) === -1) { + p = path.join(process.cwd(), osInput); + } else { + p = osInput; + } + } else { + reject("You must specify a file path."); + } + fs.readFile(p, function (err, data) { + if (err) { + reject(err); + } + JSZip.loadAsync(data).then( + (zip) => { + resolve(zip.file("export.data").async("string")); + }, + (reason) => { + reject(reason); + } + ); + }); + }); + } + /** + * Save the given data to a file and determine the target file if necessary. + * If output is non-empty, it is used as target filename. Otherwise the target filename is + * built from the current working directory and the given defaultFileName. + * + * @param data to be written to the file. + * @param output file to write to or empty to choose automatically. + * @param defaultFileName to use when no explicit output filename is given. + * @return the chosen output file. + */ + static saveFile(data: string | Buffer, output: string, defaultFileName: string) { + let p: string = null; + let mkdir = false; + if (output != null && output !== "") { + const osOutput = path.join(output); + if (osOutput.indexOf(path.sep) === -1) { + p = path.join(process.cwd(), osOutput); + } else { + mkdir = true; + if (osOutput.endsWith(path.sep)) { + p = path.join(osOutput, defaultFileName); + } else { + p = osOutput; + } + } + } else { + p = path.join(process.cwd(), defaultFileName); + } + + p = path.resolve(p); + if (mkdir) { + const dir = p.substring(0, p.lastIndexOf(path.sep)); + if (!fs.existsSync(dir)) { + NodeUtils.mkdirpSync(dir, "700"); + } + } + + return new Promise((resolve, reject) => { + fs.writeFile(p, data, { encoding: "utf8", mode: 0o600 }, (err) => { + if (err != null) { + reject("Cannot save file to " + p); + } + resolve(p); + }); + }); + } + + /** + * Process the given data and write it to a file if possible. If the user requested RAW output and + * no output name is given, the file is directly written to stdout. The resulting Response contains + * an otherwise empty message then to prevent writing other information to stdout. + * + * If an output is given or no RAW output is requested, the rules from [saveFile] apply. + * + * @param data to be written to the file or stdout. + * @param output file to write to or empty to choose automatically. + * @param defaultFileName to use when no explicit output filename is given. + * @return an empty [Response] if written to stdout or a [Response] with the chosen output file otherwise. + */ + static async saveResultToFile(data: string | Buffer, output: string, defaultFileName: string) { + if ((output == null || output === "") && process.env.BW_RAW === "true") { + // No output is given and the user expects raw output. Since the command result is about content, + // we directly return the command result to stdout (and suppress further messages). + process.stdout.write(data); + return Response.success(); + } + + const filePath = await this.saveFile(data, output, defaultFileName); + const res = new MessageResponse("Saved " + filePath, null); + res.raw = filePath; + return Response.success(res); + } + + static readStdin(): Promise { + return new Promise((resolve, reject) => { + let input = ""; + + if (process.stdin.isTTY) { + resolve(input); + return; + } + + process.stdin.setEncoding("utf8"); + process.stdin.on("readable", () => { + // eslint-disable-next-line + while (true) { + const chunk = process.stdin.read(); + if (chunk == null) { + break; + } + input += chunk; + } + }); + + process.stdin.on("end", () => { + resolve(input); + }); + }); + } + + static searchFolders(folders: FolderView[], search: string) { + search = search.toLowerCase(); + return folders.filter((f) => { + if (f.name != null && f.name.toLowerCase().indexOf(search) > -1) { + return true; + } + return false; + }); + } + + static searchCollections(collections: CollectionView[], search: string) { + search = search.toLowerCase(); + return collections.filter((c) => { + if (c.name != null && c.name.toLowerCase().indexOf(search) > -1) { + return true; + } + return false; + }); + } + + static searchOrganizations(organizations: Organization[], search: string) { + search = search.toLowerCase(); + return organizations.filter((o) => { + if (o.name != null && o.name.toLowerCase().indexOf(search) > -1) { + return true; + } + return false; + }); + } + + /** + * Gets a password from all available sources. In order of priority these are: + * * passwordfile + * * passwordenv + * * user interaction + * + * Returns password string if successful, Response if not. + */ + static async getPassword( + password: string, + options: { passwordFile?: string; passwordEnv?: string }, + logService?: LogService + ): Promise { + if (Utils.isNullOrEmpty(password)) { + if (options?.passwordFile) { + password = await NodeUtils.readFirstLine(options.passwordFile); + } else if (options?.passwordEnv) { + if (process.env[options.passwordEnv]) { + password = process.env[options.passwordEnv]; + } else if (logService) { + logService.warning(`Warning: Provided passwordenv ${options.passwordEnv} is not set`); + } + } + } + + if (Utils.isNullOrEmpty(password)) { + if (process.env.BW_NOINTERACTION !== "true") { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "password", + name: "password", + message: "Master password:", + }); + + password = answer.password; + } else { + return Response.badRequest( + "Master password is required. Try again in interactive mode or provide a password file or environment variable." + ); + } + } + return password; + } + + static convertBooleanOption(optionValue: any) { + return optionValue || optionValue === "" ? true : false; + } + + static flagEnabled(flag: FlagName) { + return this.flags[flag] == null || this.flags[flag]; + } + + private static get flags(): Flags { + const envFlags = process.env.FLAGS; + + if (typeof envFlags === "string") { + return JSON.parse(envFlags) as Flags; + } else { + return envFlags as Flags; + } + } +} diff --git a/apps/cli/src/vault.program.ts b/apps/cli/src/vault.program.ts new file mode 100644 index 0000000000..df909bf8b2 --- /dev/null +++ b/apps/cli/src/vault.program.ts @@ -0,0 +1,486 @@ +import * as program from "commander"; + +import { Response } from "jslib-node/cli/models/response"; + +import { Main } from "./bw"; +import { ConfirmCommand } from "./commands/confirm.command"; +import { CreateCommand } from "./commands/create.command"; +import { DeleteCommand } from "./commands/delete.command"; +import { EditCommand } from "./commands/edit.command"; +import { ExportCommand } from "./commands/export.command"; +import { GetCommand } from "./commands/get.command"; +import { ImportCommand } from "./commands/import.command"; +import { ListCommand } from "./commands/list.command"; +import { RestoreCommand } from "./commands/restore.command"; +import { ShareCommand } from "./commands/share.command"; +import { Program } from "./program"; +import { CliUtils } from "./utils"; + +const writeLn = CliUtils.writeLn; + +export class VaultProgram extends Program { + constructor(protected main: Main) { + super(main); + } + + async register() { + program + .addCommand(this.listCommand()) + .addCommand(this.getCommand()) + .addCommand(this.createCommand()) + .addCommand(this.editCommand()) + .addCommand(this.deleteCommand()) + .addCommand(this.restoreCommand()) + .addCommand(this.shareCommand("move", false)) + .addCommand(this.confirmCommand()) + .addCommand(this.importCommand()) + .addCommand(this.exportCommand()) + .addCommand(this.shareCommand("share", true)); + } + + private validateObject(requestedObject: string, validObjects: string[]): boolean { + let success = true; + if (!validObjects.includes(requestedObject)) { + success = false; + this.processResponse( + Response.badRequest( + 'Unknown object "' + + requestedObject + + '". Allowed objects are ' + + validObjects.join(", ") + + "." + ) + ); + } + return success; + } + + private listCommand(): program.Command { + const listObjects = [ + "items", + "folders", + "collections", + "org-collections", + "org-members", + "organizations", + ]; + + return new program.Command("list") + .arguments("") + .description("List an array of objects from the vault.", { + object: "Valid objects are: " + listObjects.join(", "), + }) + .option("--search ", "Perform a search on the listed objects.") + .option("--url ", "Filter items of type login with a url-match search.") + .option("--folderid ", "Filter items by folder id.") + .option("--collectionid ", "Filter items by collection id.") + .option( + "--organizationid ", + "Filter items or collections by organization id." + ) + .option("--trash", "Filter items that are deleted and in the trash.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn(" Combining search with a filter performs a logical AND operation."); + writeLn(""); + writeLn(" Combining multiple filters performs a logical OR operation."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw list items"); + writeLn(" bw list items --folderid 60556c31-e649-4b5d-8daf-fc1c391a1bf2"); + writeLn( + " bw list items --search google --folderid 60556c31-e649-4b5d-8daf-fc1c391a1bf2" + ); + writeLn(" bw list items --url https://google.com"); + writeLn(" bw list items --folderid null"); + writeLn(" bw list items --organizationid notnull"); + writeLn( + " bw list items --folderid 60556c31-e649-4b5d-8daf-fc1c391a1bf2 --organizationid notnull" + ); + writeLn(" bw list items --trash"); + writeLn(" bw list folders --search email"); + writeLn(" bw list org-members --organizationid 60556c31-e649-4b5d-8daf-fc1c391a1bf2"); + writeLn("", true); + }) + .action(async (object, cmd) => { + if (!this.validateObject(object, listObjects)) { + return; + } + + await this.exitIfLocked(); + const command = new ListCommand( + this.main.cipherService, + this.main.folderService, + this.main.collectionService, + this.main.organizationService, + this.main.searchService, + this.main.apiService + ); + const response = await command.run(object, cmd); + + this.processResponse(response); + }); + } + + private getCommand(): program.Command { + const getObjects = [ + "item", + "username", + "password", + "uri", + "totp", + "notes", + "exposed", + "attachment", + "folder", + "collection", + "org-collection", + "organization", + "template", + "fingerprint", + "send", + ]; + return new program.Command("get") + .arguments(" ") + .description("Get an object from the vault.", { + object: "Valid objects are: " + getObjects.join(", "), + id: "Search term or object's globally unique `id`.", + }) + .option("--itemid ", "Attachment's item id.") + .option("--output ", "Output directory or filename for attachment.") + .option("--organizationid ", "Organization id for an organization object.") + .on("--help", () => { + writeLn("\n If raw output is specified and no output filename or directory is given for"); + writeLn(" an attachment query, the attachment content is written to stdout."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw get item 99ee88d2-6046-4ea7-92c2-acac464b1412"); + writeLn(" bw get password https://google.com"); + writeLn(" bw get totp google.com"); + writeLn(" bw get notes google.com"); + writeLn(" bw get exposed yahoo.com"); + writeLn( + " bw get attachment b857igwl1dzrs2 --itemid 99ee88d2-6046-4ea7-92c2-acac464b1412 " + + "--output ./photo.jpg" + ); + writeLn( + " bw get attachment photo.jpg --itemid 99ee88d2-6046-4ea7-92c2-acac464b1412 --raw" + ); + writeLn(" bw get folder email"); + writeLn(" bw get template folder"); + writeLn("", true); + }) + .action(async (object, id, cmd) => { + if (!this.validateObject(object, getObjects)) { + return; + } + + await this.exitIfLocked(); + const command = new GetCommand( + this.main.cipherService, + this.main.folderService, + this.main.collectionService, + this.main.totpService, + this.main.auditService, + this.main.cryptoService, + this.main.stateService, + this.main.searchService, + this.main.apiService, + this.main.organizationService + ); + const response = await command.run(object, id, cmd); + this.processResponse(response); + }); + } + + private createCommand() { + const createObjects = ["item", "attachment", "folder", "org-collection"]; + return new program.Command("create") + .arguments(" [encodedJson]") + .description("Create an object in the vault.", { + object: "Valid objects are: " + createObjects.join(", "), + encodedJson: "Encoded json of the object to create. Can also be piped into stdin.", + }) + .option("--file ", "Path to file for attachment.") + .option("--itemid ", "Attachment's item id.") + .option("--organizationid ", "Organization id for an organization object.") + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw create folder eyJuYW1lIjoiTXkgRm9sZGVyIn0K"); + writeLn(" echo 'eyJuYW1lIjoiTXkgRm9sZGVyIn0K' | bw create folder"); + writeLn( + " bw create attachment --file ./myfile.csv " + + "--itemid 16b15b89-65b3-4639-ad2a-95052a6d8f66" + ); + writeLn("", true); + }) + .action(async (object, encodedJson, cmd) => { + if (!this.validateObject(object, createObjects)) { + return; + } + + await this.exitIfLocked(); + const command = new CreateCommand( + this.main.cipherService, + this.main.folderService, + this.main.stateService, + this.main.cryptoService, + this.main.apiService + ); + const response = await command.run(object, encodedJson, cmd); + this.processResponse(response); + }); + } + + private editCommand(): program.Command { + const editObjects = ["item", "item-collections", "folder", "org-collection"]; + return new program.Command("edit") + .arguments(" [encodedJson]") + .description("Edit an object from the vault.", { + object: "Valid objects are: " + editObjects.join(", "), + id: "Object's globally unique `id`.", + encodedJson: "Encoded json of the object to create. Can also be piped into stdin.", + }) + .option("--organizationid ", "Organization id for an organization object.") + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn( + " bw edit folder 5cdfbd80-d99f-409b-915b-f4c5d0241b02 eyJuYW1lIjoiTXkgRm9sZGVyMiJ9Cg==" + ); + writeLn( + " echo 'eyJuYW1lIjoiTXkgRm9sZGVyMiJ9Cg==' | " + + "bw edit folder 5cdfbd80-d99f-409b-915b-f4c5d0241b02" + ); + writeLn( + " bw edit item-collections 78307355-fd25-416b-88b8-b33fd0e88c82 " + + "WyI5NzQwNTNkMC0zYjMzLTRiOTgtODg2ZS1mZWNmNWM4ZGJhOTYiXQ==" + ); + writeLn("", true); + }) + .action(async (object, id, encodedJson, cmd) => { + if (!this.validateObject(object, editObjects)) { + return; + } + + await this.exitIfLocked(); + const command = new EditCommand( + this.main.cipherService, + this.main.folderService, + this.main.cryptoService, + this.main.apiService + ); + const response = await command.run(object, id, encodedJson, cmd); + this.processResponse(response); + }); + } + + private deleteCommand(): program.Command { + const deleteObjects = ["item", "attachment", "folder", "org-collection"]; + return new program.Command("delete") + .arguments(" ") + .description("Delete an object from the vault.", { + object: "Valid objects are: " + deleteObjects.join(", "), + id: "Object's globally unique `id`.", + }) + .option("--itemid ", "Attachment's item id.") + .option("--organizationid ", "Organization id for an organization object.") + .option( + "-p, --permanent", + "Permanently deletes the item instead of soft-deleting it (item only)." + ) + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw delete item 7063feab-4b10-472e-b64c-785e2b870b92"); + writeLn(" bw delete item 89c21cd2-fab0-4f69-8c6e-ab8a0168f69a --permanent"); + writeLn(" bw delete folder 5cdfbd80-d99f-409b-915b-f4c5d0241b02"); + writeLn( + " bw delete attachment b857igwl1dzrs2 --itemid 310d5ffd-e9a2-4451-af87-ea054dce0f78" + ); + writeLn("", true); + }) + .action(async (object, id, cmd) => { + if (!this.validateObject(object, deleteObjects)) { + return; + } + + await this.exitIfLocked(); + const command = new DeleteCommand( + this.main.cipherService, + this.main.folderService, + this.main.stateService, + this.main.apiService + ); + const response = await command.run(object, id, cmd); + this.processResponse(response); + }); + } + + private restoreCommand(): program.Command { + const restoreObjects = ["item"]; + return new program.Command("restore") + .arguments(" ") + .description("Restores an object from the trash.", { + object: "Valid objects are: " + restoreObjects.join(", "), + id: "Object's globally unique `id`.", + }) + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw restore item 7063feab-4b10-472e-b64c-785e2b870b92"); + writeLn("", true); + }) + .action(async (object, id, cmd) => { + if (!this.validateObject(object, restoreObjects)) { + return; + } + + await this.exitIfLocked(); + const command = new RestoreCommand(this.main.cipherService); + const response = await command.run(object, id); + this.processResponse(response); + }); + } + + private shareCommand(commandName: string, deprecated: boolean): program.Command { + return new program.Command(commandName) + .arguments(" [encodedJson]") + .description((deprecated ? "--DEPRECATED-- " : "") + "Move an item to an organization.", { + id: "Object's globally unique `id`.", + organizationId: "Organization's globally unique `id`.", + encodedJson: "Encoded json of an array of collection ids. Can also be piped into stdin.", + }) + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn( + " bw " + + commandName + + " 4af958ce-96a7-45d9-beed-1e70fabaa27a " + + "6d82949b-b44d-468a-adae-3f3bacb0ea32 WyI5NzQwNTNkMC0zYjMzLTRiOTgtODg2ZS1mZWNmNWM4ZGJhOTYiXQ==" + ); + writeLn( + " echo '[\"974053d0-3b33-4b98-886e-fecf5c8dba96\"]' | bw encode | " + + "bw " + + commandName + + " 4af958ce-96a7-45d9-beed-1e70fabaa27a 6d82949b-b44d-468a-adae-3f3bacb0ea32" + ); + if (deprecated) { + writeLn(""); + writeLn('--DEPRECATED See "bw move" for the current implementation--'); + } + writeLn("", true); + }) + .action(async (id, organizationId, encodedJson, cmd) => { + await this.exitIfLocked(); + const command = new ShareCommand(this.main.cipherService); + const response = await command.run(id, organizationId, encodedJson); + this.processResponse(response); + }); + } + + private confirmCommand(): program.Command { + const confirmObjects = ["org-member"]; + return new program.Command("confirm") + .arguments(" ") + .description("Confirm an object to the organization.", { + object: "Valid objects are: " + confirmObjects.join(", "), + id: "Object's globally unique `id`.", + }) + .option("--organizationid ", "Organization id for an organization object.") + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn( + " bw confirm org-member 7063feab-4b10-472e-b64c-785e2b870b92 " + + "--organizationid 310d5ffd-e9a2-4451-af87-ea054dce0f78" + ); + writeLn("", true); + }) + .action(async (object, id, cmd) => { + if (!this.validateObject(object, confirmObjects)) { + return; + } + + await this.exitIfLocked(); + const command = new ConfirmCommand(this.main.apiService, this.main.cryptoService); + const response = await command.run(object, id, cmd); + this.processResponse(response); + }); + } + + private importCommand(): program.Command { + return new program.Command("import") + .arguments("[format] [input]") + .description("Import vault data from a file.", { + format: "The format of [input]", + input: "Filepath to data to import", + }) + .option("--formats", "List formats") + .option("--organizationid ", "ID of the organization to import to.") + .on("--help", () => { + writeLn("\n Examples:"); + writeLn(""); + writeLn(" bw import --formats"); + writeLn(" bw import bitwardencsv ./from/source.csv"); + writeLn(" bw import keepass2xml keepass_backup.xml"); + writeLn( + " bw import --organizationid cf14adc3-aca5-4573-890a-f6fa231436d9 keepass2xml keepass_backup.xml" + ); + }) + .action(async (format, filepath, options) => { + await this.exitIfLocked(); + const command = new ImportCommand(this.main.importService, this.main.organizationService); + const response = await command.run(format, filepath, options); + this.processResponse(response); + }); + } + + private exportCommand(): program.Command { + return new program.Command("export") + .description("Export vault data to a CSV or JSON file.", {}) + .option("--output ", "Output directory or filename.") + .option("--format ", "Export file format.") + .option( + "--password [password]", + "Use password to encrypt instead of your Bitwarden account encryption key. Only applies to the encrypted_json format." + ) + .option("--organizationid ", "Organization id for an organization.") + .on("--help", () => { + writeLn("\n Notes:"); + writeLn(""); + writeLn( + " Valid formats are `csv`, `json`, and `encrypted_json`. Default format is `csv`." + ); + writeLn(""); + writeLn( + " If --raw option is specified and no output filename or directory is given, the" + ); + writeLn(" result is written to stdout."); + writeLn(""); + writeLn(" Examples:"); + writeLn(""); + writeLn(" bw export"); + writeLn(" bw --raw export"); + writeLn(" bw export myPassword321"); + writeLn(" bw export myPassword321 --format json"); + writeLn(" bw export --output ./exp/bw.csv"); + writeLn(" bw export myPassword321 --output bw.json --format json"); + writeLn( + " bw export myPassword321 --organizationid 7063feab-4b10-472e-b64c-785e2b870b92" + ); + writeLn("", true); + }) + .action(async (options) => { + await this.exitIfLocked(); + const command = new ExportCommand(this.main.exportService, this.main.policyService); + const response = await command.run(options); + this.processResponse(response); + }); + } +} diff --git a/apps/cli/stores/chocolatey/bitwarden-cli.nuspec b/apps/cli/stores/chocolatey/bitwarden-cli.nuspec new file mode 100644 index 0000000000..30de1c6f43 --- /dev/null +++ b/apps/cli/stores/chocolatey/bitwarden-cli.nuspec @@ -0,0 +1,41 @@ + + + + + bitwarden-cli + 0.0.0 + https://github.com/bitwarden/cli/tree/master/stores/chocolatey + kspearrin + Bitwarden CLI + Bitwarden Inc. + https://bitwarden.com/ + https://cdn.rawgit.com/bitwarden/desktop/51dd1341/resources/icon.png + Copyright © 2015-2022 Bitwarden Inc. + https://github.com/bitwarden/cli/ + https://help.bitwarden.com/article/cli/ + https://github.com/bitwarden/cli/issues + https://github.com/bitwarden/cli/releases + https://github.com/bitwarden/cli/blob/master/LICENSE.txt + false + bitwarden password manager cli + A secure and free password manager for all of your devices. + + For CLI documentation, please visit https://help.bitwarden.com/article/cli/ + + ----------------- + + Bitwarden is the easiest and safest way to store all of your logins and passwords while conveniently keeping them synced between all of your devices. + + Password theft is a serious problem. The websites and apps that you use are under attack every day. Security breaches occur and your passwords are stolen. When you reuse the same passwords across apps and websites hackers can easily access your email, bank, and other important accounts. + + Security experts recommend that you use a different, randomly generated password for every account that you create. But how do you manage all those passwords? Bitwarden makes it easy for you to create, store, and access your passwords. + + Bitwarden stores all of your logins in an encrypted vault that syncs across all of your devices. Since it's fully encrypted before it ever leaves your device, only you have access to your data. Not even the team at Bitwarden can read your data, even if we wanted to. Your data is sealed with AES-256 bit encryption, salted hashing, and PBKDF2 SHA-256. + + Bitwarden is 100% open source software. The source code for Bitwarden is hosted on GitHub and everyone is free to review, audit, and contribute to the Bitwarden codebase. + + + + + + diff --git a/apps/cli/stores/chocolatey/tools/VERIFICATION.txt b/apps/cli/stores/chocolatey/tools/VERIFICATION.txt new file mode 100644 index 0000000000..67231a84c9 --- /dev/null +++ b/apps/cli/stores/chocolatey/tools/VERIFICATION.txt @@ -0,0 +1,6 @@ +VERIFICATION +Verification is intended to assist the Chocolatey moderators and community +in verifying that this package's contents are trustworthy. + +This package is published by the Bitwarden project itself. Any binaries will +be identical to other package types published by the project. diff --git a/apps/cli/stores/snap/snapcraft.yaml b/apps/cli/stores/snap/snapcraft.yaml new file mode 100644 index 0000000000..b358a58687 --- /dev/null +++ b/apps/cli/stores/snap/snapcraft.yaml @@ -0,0 +1,17 @@ +name: bw +version: __version__ +summary: Bitwarden CLI +description: A secure and free password manager for all of your devices. +confinement: strict +base: core18 +apps: + bw: + command: bw + plugs: [network, home, network-bind] +parts: + bw: + plugin: dump + source: ./bw-linux-$SNAPCRAFT_PROJECT_VERSION.zip + override-build: | + chmod +x bw + snapcraftctl build diff --git a/apps/cli/tsconfig.json b/apps/cli/tsconfig.json new file mode 100644 index 0000000000..a39ab45d7a --- /dev/null +++ b/apps/cli/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "pretty": true, + "moduleResolution": "node", + "target": "ES2016", + "module": "es6", + "noImplicitAny": true, + "allowSyntheticDefaultImports": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowJs": true, + "sourceMap": true, + "baseUrl": ".", + "paths": { + "jslib-common/*": ["../../libs/common/src/*"], + "jslib-node/*": ["../../libs/node/src/*"] + } + }, + "include": ["src"] +} diff --git a/apps/cli/tsconfig.spec.json b/apps/cli/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/apps/cli/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/apps/cli/webpack.config.js b/apps/cli/webpack.config.js new file mode 100644 index 0000000000..1c0c2e2b08 --- /dev/null +++ b/apps/cli/webpack.config.js @@ -0,0 +1,79 @@ +const path = require("path"); +const webpack = require("webpack"); +const { CleanWebpackPlugin } = require("clean-webpack-plugin"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const nodeExternals = require("webpack-node-externals"); +const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin"); +const config = require("./config/config"); + +if (process.env.NODE_ENV == null) { + process.env.NODE_ENV = "development"; +} +const ENV = (process.env.ENV = process.env.NODE_ENV); + +const envConfig = config.load(ENV); +config.log(envConfig); + +const moduleRules = [ + { + test: /\.ts$/, + use: "ts-loader", + exclude: path.resolve(__dirname, "node_modules"), + }, +]; + +const plugins = [ + new CleanWebpackPlugin(), + new CopyWebpackPlugin({ + patterns: [{ from: "./src/locales", to: "locales" }], + }), + new webpack.DefinePlugin({ + "process.env.BWCLI_ENV": JSON.stringify(ENV), + }), + new webpack.BannerPlugin({ + banner: "#!/usr/bin/env node", + raw: true, + }), + new webpack.IgnorePlugin({ + resourceRegExp: /^encoding$/, + contextRegExp: /node-fetch/, + }), + new webpack.EnvironmentPlugin({ + BWCLI_ENV: ENV, + FLAGS: envConfig.flags, + }), + new webpack.IgnorePlugin({ + resourceRegExp: /canvas/, + contextRegExp: /jsdom$/, + }), +]; + +const webpackConfig = { + mode: ENV, + target: "node", + devtool: ENV === "development" ? "eval-source-map" : "source-map", + node: { + __dirname: false, + __filename: false, + }, + entry: { + bw: "./src/bw.ts", + }, + optimization: { + minimize: false, + }, + resolve: { + extensions: [".ts", ".js"], + symlinks: false, + modules: [path.resolve("../../node_modules")], + plugins: [new TsconfigPathsPlugin({ configFile: "./tsconfig.json" })], + }, + output: { + filename: "[name].js", + path: path.resolve(__dirname, "build"), + }, + module: { rules: moduleRules }, + plugins: plugins, +}; + +module.exports = webpackConfig; diff --git a/apps/desktop/.eslintrc.json b/apps/desktop/.eslintrc.json new file mode 100644 index 0000000000..5d9ea457c3 --- /dev/null +++ b/apps/desktop/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "env": { + "browser": true, + "node": true + } +} diff --git a/apps/desktop/.gitignore b/apps/desktop/.gitignore new file mode 100644 index 0000000000..1781b9ed5e --- /dev/null +++ b/apps/desktop/.gitignore @@ -0,0 +1,18 @@ +.vs +.idea +node_modules +npm-debug.log +vwd.webinfo +dist/ +dist-safari/ +css/ +*.crx +*.pem +build/ +yarn-error.log +.DS_Store +*.nupkg +*.provisionprofile +*.env +PlugIns/safari.appex/ +PlugIns/safari-legacy.appex/ diff --git a/apps/desktop/.vscode/launch.json b/apps/desktop/.vscode/launch.json new file mode 100644 index 0000000000..66c1161be4 --- /dev/null +++ b/apps/desktop/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Main Process", + "type": "node", + "request": "launch", + "cwd": "${workspaceRoot}/build", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron", + "windows": { + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd" + }, + "args": ["."] + } + ] +} diff --git a/apps/desktop/README.md b/apps/desktop/README.md new file mode 100644 index 0000000000..eeffe1cef4 --- /dev/null +++ b/apps/desktop/README.md @@ -0,0 +1,41 @@ +[![Github Workflow build on master](https://github.com/bitwarden/clients/actions/workflows/build-desktop.yml/badge.svg?branch=master)](https://github.com/bitwarden/clients/actions/workflows/build-desktop.yml?query=branch:master) +[![Crowdin](https://d322cqt584bo4o.cloudfront.net/bitwarden-desktop/localized.svg)](https://crowdin.com/project/bitwarden-desktop) +[![Join the chat at https://gitter.im/bitwarden/Lobby](https://badges.gitter.im/bitwarden/Lobby.svg)](https://gitter.im/bitwarden/Lobby) + +# Bitwarden Desktop Application + +[![Platforms](https://imgur.com/SLv9paA.png "Windows, macOS, and Linux")](https://bitwarden.com/download/) + +The Bitwarden desktop app is written using Electron and Angular. The application installs on Windows, macOS, and Linux distributions. + +![Desktop Vault](https://github.com/bitwarden/brand/blob/f09f2fa594c8a020c315296074f18ce0a7b3f171/screenshots/desktop-macos-vault.png "My Vault") + +# Build/Run + +## Requirements + +- [Node.js](https://nodejs.org) v16.13.1 (LTS) or greater +- NPM v8 +- Windows: + - To compile the native node modules used in the app you will need the _Visual C++ toolset_, available through the standard Visual Studio installer. You will also need to install the _Microsoft Build Tools 2015_ and _Windows 10 SDK 17134_ as additional dependencies in the Visual Studio installer. +- Linux: + - The following packages `build-essential libsecret-1-dev libglib2.0-dev` + +## Run the app + +```bash +npm ci +npm run electron +``` + +### Debug Native Messaging + +Native Messaging (communication with the browser extension) works by having the browser start a lightweight proxy application baked into our desktop binary. To setup an environment which allows +for easy debugging you will need to build the application for distribution, i.e. `npm run dist:`, start the dist version and enable desktop integration. This will write some manifests +to disk, Consult the [native manifests](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#Manifest_location) documentation for more details of the manifest +format, and the exact locations for the different platforms. _Note_ that disabling the desktop integration will delete the manifests, and the files will need to be updated again. + +The generated manifests are pre-configured with the production ID for the browser extensions. In order to use them with the development builds, the browser extension ID of the development build +needs to be added to the `allowed_extensions` section of the manifest. These IDs are generated by the browser, and can be found in the extension settings within the browser. + +It will then be possible to run the desktop application as usual using `npm run electron` and communicate with the browser. diff --git a/apps/desktop/SECURITY.md b/apps/desktop/SECURITY.md new file mode 100644 index 0000000000..e6edb96da7 --- /dev/null +++ b/apps/desktop/SECURITY.md @@ -0,0 +1,21 @@ +Bitwarden believes that working with security researchers across the globe is crucial to keeping our users safe. If you believe you've found a security issue in our product or service, we encourage you to please submit a report through our [HackerOne Program](https://hackerone.com/bitwarden/). We welcome working with you to resolve the issue promptly. Thanks in advance! + +# Disclosure Policy + +- Let us know as soon as possible upon discovery of a potential security issue, and we'll make every effort to quickly resolve the issue. +- Provide us a reasonable amount of time to resolve the issue before any disclosure to the public or a third-party. We may publicly disclose the issue before resolving it, if appropriate. +- Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our service. Only interact with accounts you own or with explicit permission of the account holder. +- If you would like to encrypt your report, please use the PGP key with long ID `0xDE6887086F892325FEC04CC0D847525B6931381F` (available in the public keyserver pool). + +While researching, we'd like to ask you to refrain from: + +- Denial of service +- Spamming +- Social engineering (including phishing) of Bitwarden staff or contractors +- Any physical attempts against Bitwarden property or data centers + +# We want to help you! + +If you have something that you feel is close to exploitation, or if you'd like some information regarding the internal API, or generally have any questions regarding the app that would help in your efforts, please email us at https://bitwarden.com/contact and ask for that information. As stated above, Bitwarden wants to help you find issues, and is more than willing to help. + +Thank you for helping keep Bitwarden and our users safe! diff --git a/apps/desktop/crowdin.yml b/apps/desktop/crowdin.yml new file mode 100644 index 0000000000..fc9743d760 --- /dev/null +++ b/apps/desktop/crowdin.yml @@ -0,0 +1,16 @@ +project_id_env: CROWDIN_PROJECT_ID +api_token_env: CROWDIN_API_TOKEN +preserve_hierarchy: true +files: + - source: /src/locales/en/messages.json + dest: /src/locales/en/%original_file_name% + translation: /src/locales/%two_letters_code%/%original_file_name% + update_option: update_as_unapproved + languages_mapping: + two_letters_code: + pt-PT: pt_PT + pt-BR: pt_BR + zh-CN: zh_CN + zh-TW: zh_TW + en-GB: en_GB + en-IN: en_IN diff --git a/apps/desktop/desktop_native/.gitignore b/apps/desktop/desktop_native/.gitignore new file mode 100644 index 0000000000..96e7a71e1b --- /dev/null +++ b/apps/desktop/desktop_native/.gitignore @@ -0,0 +1,6 @@ +target +index.node +**/node_modules +**/.DS_Store +npm-debug.log* +*.node diff --git a/apps/desktop/desktop_native/Cargo.lock b/apps/desktop/desktop_native/Cargo.lock new file mode 100644 index 0000000000..aec92d256a --- /dev/null +++ b/apps/desktop/desktop_native/Cargo.lock @@ -0,0 +1,946 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-expr" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e068cb2806bbc15b439846dc16c5f89f8599f2c3e4d73d4449d38f9b2f0b6c5" +dependencies = [ + "smallvec", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "convert_case" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" + +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "ctor" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "cxx" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce2295fe8865279f404147e9b2328e5af0ad11a2c016e58c13acfd48a07d8a55" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aaaa055d4908326f1b4524b23ae53758019b806c0c4f382ea240982e9766b26" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a670224c6686471df12560a0b97a08145082e70bd38e2b0b5383b79e46c3da7" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b700096ca0dece28d9535fdb17ab784a8ae155d7f29d39c273643e6292c9620" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "desktop_native" +version = "0.0.0" +dependencies = [ + "anyhow", + "core-foundation", + "gio", + "keytar", + "libsecret", + "napi", + "napi-build", + "napi-derive", + "scopeguard", + "security-framework", + "security-framework-sys", + "tokio", + "widestring", + "windows 0.32.0", +] + +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-executor" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "gio" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96efd8a1c00d890f6b45671916e165b5e43ccec61957d443aff6d7e44f62d348" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-io", + "gio-sys", + "glib", + "libc", + "once_cell", + "thiserror", +] + +[[package]] +name = "gio-sys" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d0fa5052773f5a56b8ae47dab09d040f5d9ce1311f4f99006e16e9a08269296" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa570813c504bdf7539a9400180c2dd4b789a819556fb86da7226d7d1b037b49" +dependencies = [ + "bitflags", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "once_cell", + "smallvec", + "thiserror", +] + +[[package]] +name = "glib-macros" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41bfd8d227dead0829ac142454e97531b93f576d0805d779c42bfd799c65c572" +dependencies = [ + "anyhow", + "heck", + "proc-macro-crate", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glib-sys" +version = "0.15.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4366377bd56697de8aaee24e673c575d2694d72e7756324ded2b0428829a7b8" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "gobject-sys" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df6859463843c20cf3837e3a9069b6ab2051aeeadf4c899d33344f4aea83189a" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "keytar" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d361c55fba09829ac620b040f5425bf239b1030c3d6820a84acac8da867dca4d" +dependencies = [ + "keytar-sys", +] + +[[package]] +name = "keytar-sys" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe908c6896705a1cb516cd6a5d956c63f08d95ace81b93253a98cd93e1e6a65a" +dependencies = [ + "cc", + "cxx", + "cxx-build", + "pkg-config", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" + +[[package]] +name = "libsecret" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4af5a2342942fa42d706a424e9f9914287fb8317132750fd73a241140ac38c1" +dependencies = [ + "bitflags", + "gio", + "glib", + "libc", + "libsecret-sys", + "once_cell", +] + +[[package]] +name = "libsecret-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287d2a0fcd95e4d7b0ac6fc9f802691a790d7e522138713b0cacebc4e63cab91" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cae2cd7ba2f3f63938b9c724475dfb7b9861b545a90324476324ed21dbc8c8" +dependencies = [ + "cc", +] + +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] +name = "mio" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + +[[package]] +name = "napi" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ec66e60f000c78dd7c6215b6fa260e0591e09805024332bc5b3f55acc12244" +dependencies = [ + "ctor", + "lazy_static", + "napi-sys", + "tokio", + "windows 0.30.0", +] + +[[package]] +name = "napi-build" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd4419172727423cf30351406c54f6cc1b354a2cfb4f1dba3e6cd07f6d5522b" + +[[package]] +name = "napi-derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74ac5287a5e94a8728fc82d16c5127acc5eb5b8ad6404ef5f82d6a4ce8d5bdd2" +dependencies = [ + "convert_case", + "napi-derive-backend", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "napi-derive-backend" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "427f4f04525635cdf22005d1be62d6d671bcb5550d694a1efb480a315422b4af" +dependencies = [ + "convert_case", + "once_cell", + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "napi-sys" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a385494dac3c52cbcacb393bb3b42669e7db8ab240c7ad5115f549eb061f2cc" + +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi", +] + +[[package]] +name = "num_cpus" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] +name = "proc-macro-crate" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" +dependencies = [ + "thiserror", + "toml", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "scratch" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96311ef4a16462c757bb6a39152c40f58f31cd2602a40fceb937e2bc34e6cbab" + +[[package]] +name = "security-framework" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" + +[[package]] +name = "signal-hook-registry" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" + +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "system-deps" +version = "6.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "once_cell", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "winapi", +] + +[[package]] +name = "tokio-macros" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "version-compare" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "widestring" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b749ebd2304aa012c5992d11a25d07b406bdbe5f79d371cb7a918ce501a19eb0" +dependencies = [ + "windows_aarch64_msvc 0.30.0", + "windows_i686_gnu 0.30.0", + "windows_i686_msvc 0.30.0", + "windows_x86_64_gnu 0.30.0", + "windows_x86_64_msvc 0.30.0", +] + +[[package]] +name = "windows" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec" +dependencies = [ + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", +] + +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc 0.32.0", + "windows_i686_gnu 0.32.0", + "windows_i686_msvc 0.32.0", + "windows_x86_64_gnu 0.32.0", + "windows_x86_64_msvc 0.32.0", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" diff --git a/apps/desktop/desktop_native/Cargo.toml b/apps/desktop/desktop_native/Cargo.toml new file mode 100644 index 0000000000..dbc2760295 --- /dev/null +++ b/apps/desktop/desktop_native/Cargo.toml @@ -0,0 +1,43 @@ +[package] +edition = "2021" +exclude = ["index.node"] +license = "GPL-3.0" +name = "desktop_native" +version = "0.0.0" + +[lib] +crate-type = ["cdylib"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0" +napi = {version = "2", features = ["async"]} +napi-derive = "2" +scopeguard = "1.1.0" +tokio = {version = "1.17.0", features = ["full"]} + +[build-dependencies] +napi-build = "1" + +[target.'cfg(windows)'.dependencies] +widestring = "0.5.1" +windows = {version = "0.32.0", features = [ + "alloc", + "Foundation", + "Storage_Streams", + "Win32_Foundation", + "Win32_Security_Credentials", +]} + +[target.'cfg(windows)'.dev-dependencies] +keytar = "0.1.6" + +[target.'cfg(target_os = "macos")'.dependencies] +core-foundation = "0.9.3" +security-framework = "2.6.1" +security-framework-sys = "2.6.1" + +[target.'cfg(target_os = "linux")'.dependencies] +gio = "0.15.6" +libsecret = "0.1.4" diff --git a/apps/desktop/desktop_native/build.js b/apps/desktop/desktop_native/build.js new file mode 100644 index 0000000000..ca42f7b0c2 --- /dev/null +++ b/apps/desktop/desktop_native/build.js @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +const child_process = require("child_process"); +const process = require("process"); + +let targets = []; +switch (process.platform) { + case "win32": + targets = ["i686-pc-windows-msvc", "x86_64-pc-windows-msvc", "aarch64-pc-windows-msvc"]; + break; + + case "darwin": + targets = ["x86_64-apple-darwin", "aarch64-apple-darwin"]; + break; + + default: + targets = ['x86_64-unknown-linux-gnu']; + break; +} + +targets.forEach(target => { + child_process.execSync(`npm run build -- --target ${target}`, {stdio: 'inherit'}); +}); diff --git a/apps/desktop/desktop_native/build.rs b/apps/desktop/desktop_native/build.rs new file mode 100644 index 0000000000..9fc2367889 --- /dev/null +++ b/apps/desktop/desktop_native/build.rs @@ -0,0 +1,5 @@ +extern crate napi_build; + +fn main() { + napi_build::setup(); +} diff --git a/apps/desktop/desktop_native/index.d.ts b/apps/desktop/desktop_native/index.d.ts new file mode 100644 index 0000000000..6ac55a1558 --- /dev/null +++ b/apps/desktop/desktop_native/index.d.ts @@ -0,0 +1,15 @@ +/* tslint:disable */ +/* eslint-disable */ + +/* auto-generated by NAPI-RS */ + +export namespace passwords { + /** Fetch the stored password from the keychain. */ + export function getPassword(service: string, account: string): Promise + /** Fetch the stored password from the keychain that was stored with Keytar. */ + export function getPasswordKeytar(service: string, account: string): Promise + /** Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. */ + export function setPassword(service: string, account: string, password: string): Promise + /** Delete the stored password from the keychain. */ + export function deletePassword(service: string, account: string): Promise +} diff --git a/apps/desktop/desktop_native/index.js b/apps/desktop/desktop_native/index.js new file mode 100644 index 0000000000..8866118c01 --- /dev/null +++ b/apps/desktop/desktop_native/index.js @@ -0,0 +1,241 @@ +const { existsSync, readFileSync } = require('fs') +const { join } = require('path') + +const { platform, arch } = process + +let nativeBinding = null +let localFileExisted = false +let loadError = null + +function isMusl() { + // For Node 10 + if (!process.report || typeof process.report.getReport !== 'function') { + try { + return readFileSync('/usr/bin/ldd', 'utf8').includes('musl') + } catch (e) { + return true + } + } else { + const { glibcVersionRuntime } = process.report.getReport().header + return !glibcVersionRuntime + } +} + +switch (platform) { + case 'android': + switch (arch) { + case 'arm64': + localFileExisted = existsSync(join(__dirname, 'desktop_native.android-arm64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.android-arm64.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-android-arm64') + } + } catch (e) { + loadError = e + } + break + case 'arm': + localFileExisted = existsSync(join(__dirname, 'desktop_native.android-arm-eabi.node')) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.android-arm-eabi.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-android-arm-eabi') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Android ${arch}`) + } + break + case 'win32': + switch (arch) { + case 'x64': + localFileExisted = existsSync( + join(__dirname, 'desktop_native.win32-x64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.win32-x64-msvc.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-win32-x64-msvc') + } + } catch (e) { + loadError = e + } + break + case 'ia32': + localFileExisted = existsSync( + join(__dirname, 'desktop_native.win32-ia32-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.win32-ia32-msvc.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-win32-ia32-msvc') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'desktop_native.win32-arm64-msvc.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.win32-arm64-msvc.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-win32-arm64-msvc') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Windows: ${arch}`) + } + break + case 'darwin': + switch (arch) { + case 'x64': + localFileExisted = existsSync(join(__dirname, 'desktop_native.darwin-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.darwin-x64.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-darwin-x64') + } + } catch (e) { + loadError = e + } + break + case 'arm64': + localFileExisted = existsSync( + join(__dirname, 'desktop_native.darwin-arm64.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.darwin-arm64.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-darwin-arm64') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on macOS: ${arch}`) + } + break + case 'freebsd': + if (arch !== 'x64') { + throw new Error(`Unsupported architecture on FreeBSD: ${arch}`) + } + localFileExisted = existsSync(join(__dirname, 'desktop_native.freebsd-x64.node')) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.freebsd-x64.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-freebsd-x64') + } + } catch (e) { + loadError = e + } + break + case 'linux': + switch (arch) { + case 'x64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'desktop_native.linux-x64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.linux-x64-musl.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-linux-x64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'desktop_native.linux-x64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.linux-x64-gnu.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-linux-x64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm64': + if (isMusl()) { + localFileExisted = existsSync( + join(__dirname, 'desktop_native.linux-arm64-musl.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.linux-arm64-musl.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-linux-arm64-musl') + } + } catch (e) { + loadError = e + } + } else { + localFileExisted = existsSync( + join(__dirname, 'desktop_native.linux-arm64-gnu.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.linux-arm64-gnu.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-linux-arm64-gnu') + } + } catch (e) { + loadError = e + } + } + break + case 'arm': + localFileExisted = existsSync( + join(__dirname, 'desktop_native.linux-arm-gnueabihf.node') + ) + try { + if (localFileExisted) { + nativeBinding = require('./desktop_native.linux-arm-gnueabihf.node') + } else { + nativeBinding = require('@bitwarden/desktop_native-linux-arm-gnueabihf') + } + } catch (e) { + loadError = e + } + break + default: + throw new Error(`Unsupported architecture on Linux: ${arch}`) + } + break + default: + throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`) +} + +if (!nativeBinding) { + if (loadError) { + throw loadError + } + throw new Error(`Failed to load native binding`) +} + +const { passwords } = nativeBinding + +module.exports.passwords = passwords diff --git a/apps/desktop/desktop_native/package-lock.json b/apps/desktop/desktop_native/package-lock.json new file mode 100644 index 0000000000..70e590de3d --- /dev/null +++ b/apps/desktop/desktop_native/package-lock.json @@ -0,0 +1,41 @@ +{ + "name": "@bitwarden/desktop_native", + "version": "0.1.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@bitwarden/desktop_native", + "version": "0.1.0", + "hasInstallScript": true, + "license": "GPL-3.0", + "devDependencies": { + "@napi-rs/cli": "^2.6.2" + } + }, + "node_modules/@napi-rs/cli": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.6.2.tgz", + "integrity": "sha512-EmH+DQDEBUIoqMim0cc+X96ImtcIZLFjgW5WWORpzYnA9Ug7zNPO7jCLMhIQRd/p5AdWaXrT4SVXc/aip09rKQ==", + "dev": true, + "bin": { + "napi": "scripts/index.js" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + } + }, + "dependencies": { + "@napi-rs/cli": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@napi-rs/cli/-/cli-2.6.2.tgz", + "integrity": "sha512-EmH+DQDEBUIoqMim0cc+X96ImtcIZLFjgW5WWORpzYnA9Ug7zNPO7jCLMhIQRd/p5AdWaXrT4SVXc/aip09rKQ==", + "dev": true + } + } +} diff --git a/apps/desktop/desktop_native/package.json b/apps/desktop/desktop_native/package.json new file mode 100644 index 0000000000..97f12ce0bf --- /dev/null +++ b/apps/desktop/desktop_native/package.json @@ -0,0 +1,32 @@ +{ + "name": "@bitwarden/desktop_native", + "version": "0.1.0", + "description": "", + "main": "index.node", + "scripts": { + "build": "napi build --release --platform", + "build:debug": "napi build --platform", + "build:cross-platform": "node build.js", + "test": "cargo test" + }, + "author": "", + "license": "GPL-3.0", + "devDependencies": { + "@napi-rs/cli": "^2.6.2" + }, + "napi": { + "name": "desktop_native", + "triples": { + "defaults": true, + "additional": [ + "x86_64-unknown-linux-musl", + "aarch64-unknown-linux-gnu", + "i686-pc-windows-msvc", + "armv7-unknown-linux-gnueabihf", + "aarch64-apple-darwin", + "aarch64-unknown-linux-musl", + "aarch64-pc-windows-msvc" + ] + } + } +} diff --git a/apps/desktop/desktop_native/src/lib.rs b/apps/desktop/desktop_native/src/lib.rs new file mode 100644 index 0000000000..96417a8bb5 --- /dev/null +++ b/apps/desktop/desktop_native/src/lib.rs @@ -0,0 +1,39 @@ +#[macro_use] +extern crate napi_derive; + +mod password; + +#[napi] +pub mod passwords { + /// Fetch the stored password from the keychain. + #[napi] + pub async fn get_password(service: String, account: String) -> napi::Result { + super::password::get_password(&service, &account) + .map_err(|e| napi::Error::from_reason(e.to_string())) + } + + /// Fetch the stored password from the keychain that was stored with Keytar. + #[napi] + pub async fn get_password_keytar(service: String, account: String) -> napi::Result { + super::password::get_password_keytar(&service, &account) + .map_err(|e| napi::Error::from_reason(e.to_string())) + } + + /// Save the password to the keychain. Adds an entry if none exists otherwise updates the existing entry. + #[napi] + pub async fn set_password( + service: String, + account: String, + password: String, + ) -> napi::Result<()> { + super::password::set_password(&service, &account, &password) + .map_err(|e| napi::Error::from_reason(e.to_string())) + } + + /// Delete the stored password from the keychain. + #[napi] + pub async fn delete_password(service: String, account: String) -> napi::Result<()> { + super::password::delete_password(&service, &account) + .map_err(|e| napi::Error::from_reason(e.to_string())) + } +} diff --git a/apps/desktop/desktop_native/src/password/macos.rs b/apps/desktop/desktop_native/src/password/macos.rs new file mode 100644 index 0000000000..7f0c3d9f61 --- /dev/null +++ b/apps/desktop/desktop_native/src/password/macos.rs @@ -0,0 +1,59 @@ +use anyhow::Result; +use security_framework::passwords::{ + delete_generic_password, get_generic_password, set_generic_password, +}; + +pub fn get_password(service: &str, account: &str) -> Result { + let result = String::from_utf8(get_generic_password(&service, &account)?)?; + Ok(result) +} + +pub fn get_password_keytar(service: &str, account: &str) -> Result { + get_password(service, account) +} + +pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> { + let result = set_generic_password(&service, &account, password.as_bytes())?; + Ok(result) +} + +pub fn delete_password(service: &str, account: &str) -> Result<()> { + let result = delete_generic_password(&service, &account)?; + Ok(result) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({});); + set_password("BitwardenTest", "BitwardenTest", "Random").unwrap(); + assert_eq!( + "Random", + get_password("BitwardenTest", "BitwardenTest").unwrap() + ); + delete_password("BitwardenTest", "BitwardenTest").unwrap(); + + // Ensure password is deleted + match get_password("BitwardenTest", "BitwardenTest") { + Ok(_) => panic!("Got a result"), + Err(e) => assert_eq!( + "The specified item could not be found in the keychain.", + e.to_string() + ), + } + } + + #[test] + fn test_error_no_password() { + match get_password("Unknown", "Unknown") { + Ok(_) => panic!("Got a result"), + Err(e) => assert_eq!( + "The specified item could not be found in the keychain.", + e.to_string() + ), + } + } +} diff --git a/apps/desktop/desktop_native/src/password/mod.rs b/apps/desktop/desktop_native/src/password/mod.rs new file mode 100644 index 0000000000..3cc0c28e04 --- /dev/null +++ b/apps/desktop/desktop_native/src/password/mod.rs @@ -0,0 +1,5 @@ +#[cfg_attr(target_os = "linux", path = "unix.rs")] +#[cfg_attr(target_os = "windows", path = "windows.rs")] +#[cfg_attr(target_os = "macos", path = "macos.rs")] +mod password; +pub use password::*; diff --git a/apps/desktop/desktop_native/src/password/unix.rs b/apps/desktop/desktop_native/src/password/unix.rs new file mode 100644 index 0000000000..fa808613df --- /dev/null +++ b/apps/desktop/desktop_native/src/password/unix.rs @@ -0,0 +1,91 @@ +use anyhow::{anyhow, Result}; +use libsecret::{password_clear_sync, password_lookup_sync, password_store_sync, Schema}; +use std::collections::HashMap; + +pub fn get_password(service: &str, account: &str) -> Result { + let res = password_lookup_sync( + Some(&get_schema()), + build_attributes(service, account), + gio::Cancellable::NONE, + )?; + + match res { + Some(s) => Ok(String::from(s)), + None => Err(anyhow!("No password found")), + } +} + +pub fn get_password_keytar(service: &str, account: &str) -> Result { + get_password(service, account) +} + +pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> { + let result = password_store_sync( + Some(&get_schema()), + build_attributes(service, account), + Some(&libsecret::COLLECTION_DEFAULT), + &format!("{}/{}", service, account), + password, + gio::Cancellable::NONE, + )?; + Ok(result) +} + +pub fn delete_password(service: &str, account: &str) -> Result<()> { + let result = password_clear_sync( + Some(&get_schema()), + build_attributes(service, account), + gio::Cancellable::NONE, + )?; + Ok(result) +} + +fn get_schema() -> Schema { + let mut attributes = std::collections::HashMap::new(); + attributes.insert("service", libsecret::SchemaAttributeType::String); + attributes.insert("account", libsecret::SchemaAttributeType::String); + + libsecret::Schema::new( + "org.freedesktop.Secret.Generic", + libsecret::SchemaFlags::NONE, + attributes, + ) +} + +fn build_attributes<'a>(service: &'a str, account: &'a str) -> HashMap<&'a str, &'a str> { + let mut attributes = HashMap::new(); + attributes.insert("service", service); + attributes.insert("account", account); + + attributes +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({});); + set_password("BitwardenTest", "BitwardenTest", "Random").unwrap(); + assert_eq!( + "Random", + get_password("BitwardenTest", "BitwardenTest").unwrap() + ); + delete_password("BitwardenTest", "BitwardenTest").unwrap(); + + // Ensure password is deleted + match get_password("BitwardenTest", "BitwardenTest") { + Ok(_) => panic!("Got a result"), + Err(e) => assert_eq!("No password found", e.to_string()), + } + } + + #[test] + fn test_error_no_password() { + match get_password("BitwardenTest", "BitwardenTest") { + Ok(_) => panic!("Got a result"), + Err(e) => assert_eq!("No password found", e.to_string()), + } + } +} diff --git a/apps/desktop/desktop_native/src/password/windows.rs b/apps/desktop/desktop_native/src/password/windows.rs new file mode 100644 index 0000000000..ed2e643c2f --- /dev/null +++ b/apps/desktop/desktop_native/src/password/windows.rs @@ -0,0 +1,180 @@ +use anyhow::{anyhow, Result}; +use widestring::{U16CString, U16String}; +use windows::Win32::{ + Foundation::{GetLastError, ERROR_NOT_FOUND, FILETIME, PWSTR, WIN32_ERROR}, + Security::Credentials::{ + CredDeleteW, CredFree, CredReadW, CredWriteW, CREDENTIALW, CRED_FLAGS, + CRED_PERSIST_ENTERPRISE, CRED_TYPE_GENERIC, + }, +}; + +const CRED_FLAGS_NONE: u32 = 0; + +pub fn get_password<'a>(service: &str, account: &str) -> Result { + let target_name = U16CString::from_str(target_name(service, account))?; + + let mut credential: *mut CREDENTIALW = std::ptr::null_mut(); + let credential_ptr = &mut credential; + + let result = unsafe { + CredReadW( + PWSTR(target_name.as_ptr()), + CRED_TYPE_GENERIC.0, + CRED_FLAGS_NONE, + credential_ptr, + ) + }; + + scopeguard::defer!({ + unsafe { CredFree(credential as *mut _) }; + }); + + if !result.as_bool() { + return Err(anyhow!(convert_error(unsafe { GetLastError() }))); + } + + let password = unsafe { + U16String::from_ptr( + (*credential).CredentialBlob as *const u16, + (*credential).CredentialBlobSize as usize / 2, + ) + .to_string_lossy() + }; + + Ok(String::from(password)) +} + +// Remove this after sufficient releases +pub fn get_password_keytar<'a>(service: &str, account: &str) -> Result { + let target_name = U16CString::from_str(target_name(service, account))?; + + let mut credential: *mut CREDENTIALW = std::ptr::null_mut(); + let credential_ptr = &mut credential; + + let result = unsafe { + CredReadW( + PWSTR(target_name.as_ptr()), + CRED_TYPE_GENERIC.0, + CRED_FLAGS_NONE, + credential_ptr, + ) + }; + + scopeguard::defer!({ + unsafe { CredFree(credential as *mut _) }; + }); + + if !result.as_bool() { + return Err(anyhow!(unsafe { GetLastError() }.0.to_string())); + } + + let password = unsafe { + std::str::from_utf8_unchecked(std::slice::from_raw_parts( + (*credential).CredentialBlob, + (*credential).CredentialBlobSize as usize, + )) + }; + + Ok(String::from(password)) +} + +pub fn set_password(service: &str, account: &str, password: &str) -> Result<()> { + let target_name = U16CString::from_str(target_name(service, account))?; + let user_name = U16CString::from_str(account)?; + let last_written = FILETIME { + dwLowDateTime: 0, + dwHighDateTime: 0, + }; + + let credential = U16CString::from_str(password)?; + let credential_len = password.len() as u32 * 2; + + let credential = CREDENTIALW { + Flags: CRED_FLAGS(CRED_FLAGS_NONE), + Type: CRED_TYPE_GENERIC, + TargetName: PWSTR(target_name.as_ptr()), + Comment: PWSTR::default(), + LastWritten: last_written, + CredentialBlobSize: credential_len, + CredentialBlob: credential.as_ptr() as *mut u8, + Persist: CRED_PERSIST_ENTERPRISE, + AttributeCount: 0, + Attributes: std::ptr::null_mut(), + TargetAlias: PWSTR::default(), + UserName: PWSTR(user_name.as_ptr()), + }; + + let result = unsafe { CredWriteW(&credential, 0) }; + if !result.as_bool() { + return Err(anyhow!(unsafe { GetLastError() }.0.to_string())); + } + + Ok(()) +} + +pub fn delete_password(service: &str, account: &str) -> Result<()> { + let target_name = U16CString::from_str(target_name(service, account))?; + + unsafe { + CredDeleteW( + PWSTR(target_name.as_ptr()), + CRED_TYPE_GENERIC.0, + CRED_FLAGS_NONE, + ) + .ok()? + }; + + Ok(()) +} + +fn target_name(service: &str, account: &str) -> String { + format!("{}/{}", service, account) +} + +// Convert the internal WIN32 errors to descriptive messages +fn convert_error(code: WIN32_ERROR) -> String { + match code { + ERROR_NOT_FOUND => String::from("Password not found."), + _ => code.0.to_string(), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({});); + set_password("BitwardenTest", "BitwardenTest", "Random").unwrap(); + assert_eq!( + "Random", + get_password("BitwardenTest", "BitwardenTest").unwrap() + ); + delete_password("BitwardenTest", "BitwardenTest").unwrap(); + + // Ensure password is deleted + match get_password("BitwardenTest", "BitwardenTest") { + Ok(_) => panic!("Got a result"), + Err(e) => assert_eq!("Password not found.", e.to_string()), + } + } + + #[test] + fn test_get_password_keytar() { + scopeguard::defer!(delete_password("BitwardenTest", "BitwardenTest").unwrap_or({});); + keytar::set_password("BitwardenTest", "BitwardenTest", "HelloFromKeytar").unwrap(); + assert_eq!( + "HelloFromKeytar", + get_password_keytar("BitwardenTest", "BitwardenTest").unwrap() + ); + } + + #[test] + fn test_error_no_password() { + match get_password("BitwardenTest", "BitwardenTest") { + Ok(_) => panic!("Got a result"), + Err(e) => assert_eq!("Password not found.", e.to_string()), + } + } +} diff --git a/apps/desktop/electron-builder.json b/apps/desktop/electron-builder.json new file mode 100644 index 0000000000..4a45d151bc --- /dev/null +++ b/apps/desktop/electron-builder.json @@ -0,0 +1,122 @@ +{ + "extraMetadata": { "name": "bitwarden" }, + "productName": "Bitwarden", + "appId": "com.bitwarden.desktop", + "buildDependenciesFromSource": true, + "copyright": "Copyright © 2015-2022 Bitwarden Inc.", + "directories": { "buildResources": "resources", "output": "dist", "app": "build" }, + "afterSign": "scripts/after-sign.js", + "asarUnpack": ["**/*.node"], + "files": ["**/*", "!**/node_modules/@bitwarden/desktop-native/**/*"], + "electronVersion": "16.2.7", + "publish": { + "provider": "generic", + "url": "https://artifacts.bitwarden.com/desktop" + }, + "mac": { + "electronUpdaterCompatibility": ">=0.0.1", + "category": "public.app-category.productivity", + "darkModeSupport": true, + "gatekeeperAssess": false, + "hardenedRuntime": true, + "entitlements": "resources/entitlements.mac.plist", + "entitlementsInherit": "resources/entitlements.mac.plist", + "extendInfo": { + "ITSAppUsesNonExemptEncryption": false, + "CFBundleLocalizations": [ + "en", + "cs", + "da", + "de", + "es", + "et", + "fi", + "fr", + "hr", + "hu", + "id", + "it", + "ja", + "nb", + "nl", + "pl", + "pt-BR", + "pt-PT", + "ro", + "ru", + "sk", + "sv", + "tr", + "uk", + "vi", + "zh-Hans", + "zh-Hant" + ], + "CFBundleDevelopmentRegion": "en" + }, + "target": ["dmg", "zip"] + }, + "win": { + "electronUpdaterCompatibility": ">=0.0.1", + "target": ["portable", "nsis-web", "appx"], + "sign": "./sign.js", + "extraResources": [ + { "from": "node_modules/regedit/vbs", "to": "regedit/vbs", "filter": ["**/*"] }, + { "from": "resources/native-messaging.bat", "to": "native-messaging.bat" } + ] + }, + "linux": { + "category": "Utility", + "synopsis": "A secure and free password manager for all of your devices.", + "target": ["deb", "freebsd", "rpm", "AppImage", "snap"], + "desktop": { "Name": "Bitwarden", "Type": "Application", "GenericName": "Password Manager" } + }, + "dmg": { + "icon": "dmg.icns", + "contents": [ + { "x": 150, "y": 185, "type": "file" }, + { "x": 390, "y": 180, "type": "link", "path": "/Applications" } + ], + "window": { "width": 540, "height": 380 } + }, + "mas": { + "entitlements": "resources/entitlements.mas.plist", + "entitlementsInherit": "resources/entitlements.mas.inherit.plist", + "hardenedRuntime": false, + "extendInfo": { "LSMinimumSystemVersion": "10.14.0" } + }, + "nsisWeb": { + "oneClick": false, + "perMachine": false, + "allowToChangeInstallationDirectory": false, + "artifactName": "${productName}-Installer-${version}.${ext}", + "uninstallDisplayName": "${productName}", + "deleteAppDataOnUninstall": true + }, + "portable": { "artifactName": "${productName}-Portable-${version}.${ext}" }, + "appx": { + "artifactName": "${productName}-${version}-${arch}.${ext}", + "backgroundColor": "#175DDC", + "applicationId": "bitwardendesktop", + "identityName": "8bitSolutionsLLC.bitwardendesktop", + "publisher": "CN=14D52771-DE3C-4886-B8BF-825BA7690418", + "publisherDisplayName": "8bit Solutions LLC", + "languages": ["en-US"] + }, + "deb": { + "artifactName": "${productName}-${version}-${arch}.${ext}", + "depends": ["libnotify4", "libxtst6", "libnss3", "libsecret-1-0", "libxss1"] + }, + "appImage": { + "artifactName": "${productName}-${version}-${arch}.${ext}" + }, + "rpm": { "artifactName": "${productName}-${version}-${arch}.${ext}" }, + "freebsd": { "artifactName": "${productName}-${version}-${arch}.${ext}" }, + "snap": { + "autoStart": true, + "confinement": "strict", + "plugs": ["default", "password-manager-service"], + "stagePackages": ["default"] + }, + "protocols": [{ "name": "Bitwarden", "schemes": ["bitwarden"] }] +} diff --git a/apps/desktop/package.json b/apps/desktop/package.json new file mode 100644 index 0000000000..c1efa274cb --- /dev/null +++ b/apps/desktop/package.json @@ -0,0 +1,54 @@ +{ + "name": "@bitwarden/desktop", + "description": "A secure and free password manager for all of your devices.", + "version": "0.0.0", + "keywords": [ + "bitwarden", + "password", + "vault", + "password manager" + ], + "author": "Bitwarden Inc. (https://bitwarden.com)", + "homepage": "https://bitwarden.com", + "repository": { + "type": "git", + "url": "git+https://github.com/bitwarden/clients.git" + }, + "license": "GPL-3.0", + "scripts": { + "start": "cross-env ELECTRON_IS_DEV=0 ELECTRON_NO_UPDATER=1 electron ./build", + "preinstall": "npm run sub:init", + "postinstall": "electron-rebuild", + "build": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main\" \"npm run build:renderer\"", + "build:dev": "concurrently -n Main,Rend -c yellow,cyan \"npm run build:main:dev\" \"npm run build:renderer:dev\"", + "build:main": "cross-env NODE_ENV=production webpack --config webpack.main.js", + "build:main:dev": "cross-env NODE_ENV=development webpack --config webpack.main.js", + "build:renderer": "cross-env NODE_ENV=production webpack --config webpack.renderer.js", + "build:renderer:dev": "cross-env NODE_ENV=development webpack --config webpack.renderer.js", + "build:renderer:watch": "cross-env NODE_ENV=development webpack --config webpack.renderer.js --watch", + "electron": "npm run build:main:dev && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 ./build --watch\" \"npm run build:renderer:watch\"", + "electron:ignore": "npm run build:main:dev && concurrently -k -n Main,Rend -c yellow,cyan \"electron --inspect=5858 --ignore-certificate-errors ./build --watch\" \"npm run build:renderer:watch\"", + "clean:dist": "rimraf ./dist/*", + "pack:dir": "npm run clean:dist && electron-builder --dir -p never", + "pack:lin": "npm run clean:dist && electron-builder --linux --x64 -p never", + "pack:mac": "npm run clean:dist && electron-builder --mac --universal -p never", + "pack:mac:arm64": "npm run clean:dist && electron-builder --mac --arm64 -p never", + "pack:mac:mas": "npm run clean:dist && electron-builder --mac mas --universal -p never", + "pack:mac:masdev": "npm run clean:dist && electron-builder --mac mas-dev --universal -p never", + "pack:win": "npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p never -c.win.certificateSubjectName=\"8bit Solutions LLC\"", + "pack:win:ci": "npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p never", + "dist:dir": "npm run build && npm run pack:dir", + "dist:lin": "npm run build && npm run pack:lin", + "dist:mac": "npm run build && npm run pack:mac", + "dist:mac:mas": "npm run build && npm run pack:mac:mas", + "dist:mac:masdev": "npm run build && npm run pack:mac:masdev", + "dist:win": "npm run build && npm run pack:win", + "dist:win:ci": "npm run build && npm run pack:win:ci", + "publish:lin": "npm run build && npm run clean:dist && electron-builder --linux --x64 -p always", + "publish:mac": "npm run build && npm run clean:dist && electron-builder --mac -p always", + "publish:mac:mas": "npm run dist:mac:mas && npm run upload:mas", + "publish:win": "npm run build && npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p always -c.win.certificateSubjectName=\"8bit Solutions LLC\"", + "publish:win:dev": "npm run build && npm run clean:dist && electron-builder --win --x64 --arm64 --ia32 -p always", + "upload:mas": "xcrun altool --upload-app --type osx --file \"$(find ./dist/mas-universal/Bitwarden*.pkg)\" --username $APPLE_ID_USERNAME --password $APPLE_ID_PASSWORD" + } +} diff --git a/apps/desktop/resources/appx/BadgeLogo.png b/apps/desktop/resources/appx/BadgeLogo.png new file mode 100644 index 0000000000..f4043de9a2 Binary files /dev/null and b/apps/desktop/resources/appx/BadgeLogo.png differ diff --git a/apps/desktop/resources/appx/SplashScreen.png b/apps/desktop/resources/appx/SplashScreen.png new file mode 100644 index 0000000000..ae593f8116 Binary files /dev/null and b/apps/desktop/resources/appx/SplashScreen.png differ diff --git a/apps/desktop/resources/appx/Square150x150Logo.png b/apps/desktop/resources/appx/Square150x150Logo.png new file mode 100644 index 0000000000..912f49b923 Binary files /dev/null and b/apps/desktop/resources/appx/Square150x150Logo.png differ diff --git a/apps/desktop/resources/appx/Square44x44Logo.png b/apps/desktop/resources/appx/Square44x44Logo.png new file mode 100644 index 0000000000..99d45c500e Binary files /dev/null and b/apps/desktop/resources/appx/Square44x44Logo.png differ diff --git a/apps/desktop/resources/appx/StoreLogo.png b/apps/desktop/resources/appx/StoreLogo.png new file mode 100644 index 0000000000..7a111642a1 Binary files /dev/null and b/apps/desktop/resources/appx/StoreLogo.png differ diff --git a/apps/desktop/resources/appx/Wide310x150Logo.png b/apps/desktop/resources/appx/Wide310x150Logo.png new file mode 100644 index 0000000000..cab6b888a2 Binary files /dev/null and b/apps/desktop/resources/appx/Wide310x150Logo.png differ diff --git a/apps/desktop/resources/background.png b/apps/desktop/resources/background.png new file mode 100644 index 0000000000..0cbe160e60 Binary files /dev/null and b/apps/desktop/resources/background.png differ diff --git a/apps/desktop/resources/dmg.icns b/apps/desktop/resources/dmg.icns new file mode 100644 index 0000000000..936ae4cd38 Binary files /dev/null and b/apps/desktop/resources/dmg.icns differ diff --git a/apps/desktop/resources/dmg.iconset/icon_128x128.png b/apps/desktop/resources/dmg.iconset/icon_128x128.png new file mode 100644 index 0000000000..032e3a7bdb Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_128x128.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_128x128@2x.png b/apps/desktop/resources/dmg.iconset/icon_128x128@2x.png new file mode 100644 index 0000000000..23b4d2447d Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_128x128@2x.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_16x16.png b/apps/desktop/resources/dmg.iconset/icon_16x16.png new file mode 100644 index 0000000000..c2d9f33f73 Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_16x16.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_16x16@2x.png b/apps/desktop/resources/dmg.iconset/icon_16x16@2x.png new file mode 100644 index 0000000000..9bcd22b6b3 Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_16x16@2x.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_256x256.png b/apps/desktop/resources/dmg.iconset/icon_256x256.png new file mode 100644 index 0000000000..b52a826526 Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_256x256.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_256x256@2x.png b/apps/desktop/resources/dmg.iconset/icon_256x256@2x.png new file mode 100644 index 0000000000..3f89a1aa2e Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_256x256@2x.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_32x32.png b/apps/desktop/resources/dmg.iconset/icon_32x32.png new file mode 100644 index 0000000000..6f91f5a38b Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_32x32.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_32x32@2x.png b/apps/desktop/resources/dmg.iconset/icon_32x32@2x.png new file mode 100644 index 0000000000..3d4aa29ee4 Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_32x32@2x.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_512x512.png b/apps/desktop/resources/dmg.iconset/icon_512x512.png new file mode 100644 index 0000000000..51ebc7bed8 Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_512x512.png differ diff --git a/apps/desktop/resources/dmg.iconset/icon_512x512@2x.png b/apps/desktop/resources/dmg.iconset/icon_512x512@2x.png new file mode 100644 index 0000000000..0d6635c229 Binary files /dev/null and b/apps/desktop/resources/dmg.iconset/icon_512x512@2x.png differ diff --git a/apps/desktop/resources/entitlements.mac.plist b/apps/desktop/resources/entitlements.mac.plist new file mode 100644 index 0000000000..48f7bf5cec --- /dev/null +++ b/apps/desktop/resources/entitlements.mac.plist @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/apps/desktop/resources/entitlements.mas.inherit.plist b/apps/desktop/resources/entitlements.mas.inherit.plist new file mode 100644 index 0000000000..3ee76423e4 --- /dev/null +++ b/apps/desktop/resources/entitlements.mas.inherit.plist @@ -0,0 +1,14 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.inherit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-library-validation + + + diff --git a/apps/desktop/resources/entitlements.mas.plist b/apps/desktop/resources/entitlements.mas.plist new file mode 100644 index 0000000000..d9f74a1b0a --- /dev/null +++ b/apps/desktop/resources/entitlements.mas.plist @@ -0,0 +1,26 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + com.apple.security.files.user-selected.read-write + + com.apple.security.temporary-exception.files.home-relative-path.read-write + + /Library/Application Support/Mozilla/NativeMessagingHosts/ + /Library/Application Support/Google/Chrome/NativeMessagingHosts/ + /Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/ + /Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/ + /Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/ + /Library/Application Support/Chromium/NativeMessagingHosts/ + /Library/Application Support/Microsoft Edge/NativeMessagingHosts/ + /Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/ + /Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/ + /Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/ + /Library/Application Support/Vivaldi/NativeMessagingHosts/ + + + diff --git a/apps/desktop/resources/icon.icns b/apps/desktop/resources/icon.icns new file mode 100644 index 0000000000..56a9c2e5e1 Binary files /dev/null and b/apps/desktop/resources/icon.icns differ diff --git a/apps/desktop/resources/icon.ico b/apps/desktop/resources/icon.ico new file mode 100644 index 0000000000..b5d2ff46cf Binary files /dev/null and b/apps/desktop/resources/icon.ico differ diff --git a/apps/desktop/resources/icon.iconset/icon_128x128.png b/apps/desktop/resources/icon.iconset/icon_128x128.png new file mode 100644 index 0000000000..7268b7041d Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_128x128.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_128x128@2x.png b/apps/desktop/resources/icon.iconset/icon_128x128@2x.png new file mode 100644 index 0000000000..8f5b955c0c Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_128x128@2x.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_16x16.png b/apps/desktop/resources/icon.iconset/icon_16x16.png new file mode 100644 index 0000000000..dadec18fbb Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_16x16.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_16x16@2x.png b/apps/desktop/resources/icon.iconset/icon_16x16@2x.png new file mode 100644 index 0000000000..c1289d156f Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_16x16@2x.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_256x256.png b/apps/desktop/resources/icon.iconset/icon_256x256.png new file mode 100644 index 0000000000..8f5b955c0c Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_256x256.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_256x256@2x.png b/apps/desktop/resources/icon.iconset/icon_256x256@2x.png new file mode 100644 index 0000000000..76a70f417f Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_256x256@2x.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_32x32.png b/apps/desktop/resources/icon.iconset/icon_32x32.png new file mode 100644 index 0000000000..c1289d156f Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_32x32.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_32x32@2x.png b/apps/desktop/resources/icon.iconset/icon_32x32@2x.png new file mode 100644 index 0000000000..9a05bc7bbd Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_32x32@2x.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_512x512.png b/apps/desktop/resources/icon.iconset/icon_512x512.png new file mode 100644 index 0000000000..76a70f417f Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_512x512.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_512x512@2x.png b/apps/desktop/resources/icon.iconset/icon_512x512@2x.png new file mode 100644 index 0000000000..7f24ca597a Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_512x512@2x.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_64x64.png b/apps/desktop/resources/icon.iconset/icon_64x64.png new file mode 100644 index 0000000000..9a05bc7bbd Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_64x64.png differ diff --git a/apps/desktop/resources/icon.iconset/icon_64x64@2x.png b/apps/desktop/resources/icon.iconset/icon_64x64@2x.png new file mode 100644 index 0000000000..7268b7041d Binary files /dev/null and b/apps/desktop/resources/icon.iconset/icon_64x64@2x.png differ diff --git a/apps/desktop/resources/icon.png b/apps/desktop/resources/icon.png new file mode 100644 index 0000000000..6873acee03 Binary files /dev/null and b/apps/desktop/resources/icon.png differ diff --git a/apps/desktop/resources/icons/1024x1024.png b/apps/desktop/resources/icons/1024x1024.png new file mode 100644 index 0000000000..7f24ca597a Binary files /dev/null and b/apps/desktop/resources/icons/1024x1024.png differ diff --git a/apps/desktop/resources/icons/128x128.png b/apps/desktop/resources/icons/128x128.png new file mode 100644 index 0000000000..7268b7041d Binary files /dev/null and b/apps/desktop/resources/icons/128x128.png differ diff --git a/apps/desktop/resources/icons/16x16.png b/apps/desktop/resources/icons/16x16.png new file mode 100644 index 0000000000..dadec18fbb Binary files /dev/null and b/apps/desktop/resources/icons/16x16.png differ diff --git a/apps/desktop/resources/icons/256x256.png b/apps/desktop/resources/icons/256x256.png new file mode 100644 index 0000000000..8f5b955c0c Binary files /dev/null and b/apps/desktop/resources/icons/256x256.png differ diff --git a/apps/desktop/resources/icons/32x32.png b/apps/desktop/resources/icons/32x32.png new file mode 100644 index 0000000000..c1289d156f Binary files /dev/null and b/apps/desktop/resources/icons/32x32.png differ diff --git a/apps/desktop/resources/icons/512x512.png b/apps/desktop/resources/icons/512x512.png new file mode 100644 index 0000000000..76a70f417f Binary files /dev/null and b/apps/desktop/resources/icons/512x512.png differ diff --git a/apps/desktop/resources/icons/64x64.png b/apps/desktop/resources/icons/64x64.png new file mode 100644 index 0000000000..9a05bc7bbd Binary files /dev/null and b/apps/desktop/resources/icons/64x64.png differ diff --git a/apps/desktop/resources/installerSidebar.bmp b/apps/desktop/resources/installerSidebar.bmp new file mode 100644 index 0000000000..313f776758 Binary files /dev/null and b/apps/desktop/resources/installerSidebar.bmp differ diff --git a/apps/desktop/resources/native-messaging.bat b/apps/desktop/resources/native-messaging.bat new file mode 100644 index 0000000000..45519250dd --- /dev/null +++ b/apps/desktop/resources/native-messaging.bat @@ -0,0 +1,7 @@ +@echo off +:: Helper script for starting the Native Messaging Proxy on Windows. + +cd ../ +set ELECTRON_RUN_AS_NODE=1 +set ELECTRON_NO_ATTACH_CONSOLE=1 +Bitwarden.exe resources/app.asar %* diff --git a/apps/desktop/scripts/after-sign.js b/apps/desktop/scripts/after-sign.js new file mode 100644 index 0000000000..fe82f735a1 --- /dev/null +++ b/apps/desktop/scripts/after-sign.js @@ -0,0 +1,62 @@ +/* eslint-disable @typescript-eslint/no-var-requires, no-console */ +require("dotenv").config(); +const path = require("path"); + +const { deepAssign } = require("builder-util"); +const { notarize } = require("electron-notarize"); +const fse = require("fs-extra"); + +exports.default = run; + +async function run(context) { + console.log("## After sign"); + // console.log(context); + + const appName = context.packager.appInfo.productFilename; + const appPath = `${context.appOutDir}/${appName}.app`; + const macBuild = context.electronPlatformName === "darwin"; + const copyPlugIn = ["darwin", "mas"].includes(context.electronPlatformName); + + if (copyPlugIn) { + // Copy Safari plugin to work-around https://github.com/electron-userland/electron-builder/issues/5552 + const plugIn = path.join(__dirname, "../PlugIns"); + if (fse.existsSync(plugIn)) { + fse.mkdirSync(path.join(appPath, "Contents/PlugIns")); + fse.copySync( + path.join(plugIn, "safari.appex"), + path.join(appPath, "Contents/PlugIns/safari.appex") + ); + + // Resign to sign safari extension + if (context.electronPlatformName === "mas") { + const masBuildOptions = deepAssign( + {}, + context.packager.platformSpecificBuildOptions, + context.packager.config.mas + ); + if (context.targets.some((e) => e.name === "mas-dev")) { + deepAssign(masBuildOptions, { + type: "development", + }); + } + if (context.packager.packagerOptions.prepackaged == null) { + await context.packager.sign(appPath, context.appOutDir, masBuildOptions, context.arch); + } + } else { + await context.packager.signApp(context, true); + } + } + } + + if (macBuild) { + console.log("### Notarizing " + appPath); + const appleId = process.env.APPLE_ID_USERNAME || process.env.APPLEID; + const appleIdPassword = process.env.APPLE_ID_PASSWORD || `@keychain:AC_PASSWORD`; + return await notarize({ + appBundleId: "com.bitwarden.desktop", + appPath: appPath, + appleId: appleId, + appleIdPassword: appleIdPassword, + }); + } +} diff --git a/apps/desktop/scripts/cask-update.ps1 b/apps/desktop/scripts/cask-update.ps1 new file mode 100644 index 0000000000..051708aec9 --- /dev/null +++ b/apps/desktop/scripts/cask-update.ps1 @@ -0,0 +1,17 @@ +param ( + [Parameter(Mandatory=$true)] + [string] $version +) + +# Dependencies: +# 1. brew cask install powershell +# 2. brew install vitorgalvao/tiny-scripts/cask-repair +# see https://github.com/Homebrew/homebrew-cask/blob/master/CONTRIBUTING.md#updating-a-cask +# 3. fork of homebrew-cask repo setup. +# see https://github.com/caskroom/homebrew-cask/blob/master/CONTRIBUTING.md#getting-set-up-to-contribute +# 4. Environment variables for GITHUB_USER and GITHUB_TOKEN set. +# +# To run: +# pwsh ./cask-update.ps1 -version 1.3.0 + +cask-repair --cask-version $version --blind-submit --fail-on-error bitwarden diff --git a/apps/desktop/scripts/choco-update.ps1 b/apps/desktop/scripts/choco-update.ps1 new file mode 100644 index 0000000000..72677357aa --- /dev/null +++ b/apps/desktop/scripts/choco-update.ps1 @@ -0,0 +1,34 @@ +param ( + [Parameter(Mandatory=$true)] + [string] $version +) + +# To run: +# .\choco-update.ps1 -version 1.3.0 + +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path; +$rootDir = $dir + "\.."; +$distDir = $rootDir + "\dist"; +$chocoDir = $rootDir + "\stores\chocolatey"; +$distChocoDir = $distDir + "\chocolatey"; + +if(Test-Path -Path $distChocoDir) { + Remove-Item -Recurse -Force $distChocoDir +} + +Copy-Item -Path $chocoDir -Destination $distChocoDir –Recurse + +$exe = $distChocoDir + "\Bitwarden-Installer-" + $version + ".exe"; +$uri = "https://github.com/bitwarden/desktop/releases/download/v" + $version + "/Bitwarden-Installer-" + $version + ".exe"; +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +Invoke-RestMethod -Uri $uri -OutFile $exe + +$checksum = checksum -t sha256 $exe +$nuspec = $distChocoDir + "\bitwarden.nuspec"; +$chocoInstall = $distChocoDir + "\tools\chocolateyinstall.ps1"; + +(Get-Content $chocoInstall).replace('__version__', $version).replace('__checksum__', $checksum) | Set-Content $chocoInstall +choco pack $nuspec --version $version --out $distChocoDir +cd $distChocoDir +choco push +cd $rootDir diff --git a/apps/desktop/scripts/dev/.gitignore b/apps/desktop/scripts/dev/.gitignore new file mode 100644 index 0000000000..1269488f7f --- /dev/null +++ b/apps/desktop/scripts/dev/.gitignore @@ -0,0 +1 @@ +data diff --git a/apps/desktop/scripts/dev/docker-compose.yml b/apps/desktop/scripts/dev/docker-compose.yml new file mode 100644 index 0000000000..e6332def40 --- /dev/null +++ b/apps/desktop/scripts/dev/docker-compose.yml @@ -0,0 +1,19 @@ +version: "3" + +services: + minio: + image: minio/minio + command: server /data --console-address ":9001" + ports: + - "9000:9000" + - "9001:9001" + # environment: + # MINIO_ROOT_USER: minioadmin + # MINIO_ROOT_PASSWORD: minioadmin + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 30s + timeout: 20s + retries: 3 + volumes: + - ./data:/data diff --git a/apps/desktop/scripts/safari-build.ps1 b/apps/desktop/scripts/safari-build.ps1 new file mode 100644 index 0000000000..ed60c41dd3 --- /dev/null +++ b/apps/desktop/scripts/safari-build.ps1 @@ -0,0 +1,72 @@ +param ( + [string] $version, + [switch] $mas, + [switch] $masdev, + [switch] $skipcheckout, + [switch] $skipoutcopy, + [switch] $copyonly +) + +# Dependencies: +# 1. brew cask install powershell +# +# To run: +# pwsh ./build-safari-appex.ps1 -version 1.41.0 + +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path; +$rootDir = $dir + "\.."; +$distSafariDir = $rootDir + "\dist-safari"; +$distSafariAppexDmg = $distSafariDir + "\browser\dist\Safari\dmg\build\Release\safari.appex"; +$distSafariAppexMas = $distSafariDir + "\browser\dist\Safari\mas\build\Release\safari.appex"; +$distSafariAppexMasDev = $distSafariDir + "\browser\dist\Safari\masdev\build\Release\safari.appex"; +$pluginsAppex = $rootDir + "\PlugIns\safari.appex"; + +function CopyOutput { + if ($mas) { + Copy-Item -Path $distSafariAppexMas -Destination $pluginsAppex –Recurse + } + elseif ($masdev) { + Copy-Item -Path $distSafariAppexMasDev -Destination $pluginsAppex –Recurse + } + else { + Copy-Item -Path $distSafariAppexDmg -Destination $pluginsAppex –Recurse + } +} + +if (Test-Path -Path $pluginsAppex) { + Remove-Item -Recurse -Force $pluginsAppex +} + +if ($copyonly) { + CopyOutput + exit +} + +if(-not $skipcheckout) { + if (Test-Path -Path $distSafariDir) { + Remove-Item -Recurse -Force $distSafariDir + } + New-Item $distSafariDir -ItemType Directory -ea 0 +} + +cd $distSafariDir + +if(-not $skipcheckout) { + git clone git@github.com:bitwarden/browser.git +} + +cd browser + +if (-not ([string]::IsNullOrEmpty($version))) { + $tag = "v" + $version + git checkout tags/$tag +} + +npm i +npm run dist:safari + +if (-not $skipoutcopy) { + CopyOutput +} + +cd $rootDir diff --git a/apps/desktop/scripts/snap-update.ps1 b/apps/desktop/scripts/snap-update.ps1 new file mode 100644 index 0000000000..095c61a393 --- /dev/null +++ b/apps/desktop/scripts/snap-update.ps1 @@ -0,0 +1,28 @@ +param ( + [Parameter(Mandatory=$true)] + [string] $version +) + +# Dependencies: +# 1. Install powershell, ex `sudo apt-get install -y powershell` +# +# To run: +# pwsh ./snap-update.ps1 -version 1.5.0 + +$dir = Split-Path -Parent $MyInvocation.MyCommand.Path; +$rootDir = $dir + "/.."; +$distDir = $rootDir + "/dist"; +$distSnapDir = $distDir + "/snap"; + +if(Test-Path -Path $distSnapDir) { + Remove-Item -Recurse -Force $distSnapDir +} +New-Item -ItemType directory -Path $distSnapDir | Out-Null + +$snap = "bitwarden_" + $version + "_amd64.snap"; +$distSnap = $distSnapDir + "/" + $snap; +$uri = "https://github.com/bitwarden/desktop/releases/download/v" + $version + "/" + $snap; +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +Invoke-RestMethod -Uri $uri -OutFile $distSnap + +snapcraft upload $distSnap --release stable diff --git a/apps/desktop/sign.js b/apps/desktop/sign.js new file mode 100644 index 0000000000..fe57a1343a --- /dev/null +++ b/apps/desktop/sign.js @@ -0,0 +1,22 @@ +/* eslint-disable @typescript-eslint/no-var-requires, no-console */ + +exports.default = async function (configuration) { + if (parseInt(process.env.ELECTRON_BUILDER_SIGN) === 1 && configuration.path.slice(-4) == ".exe") { + console.log(`[*] Signing file: ${configuration.path}`); + require("child_process").execSync( + `azuresigntool sign -v ` + + `-kvu ${process.env.SIGNING_VAULT_URL} ` + + `-kvi ${process.env.SIGNING_CLIENT_ID} ` + + `-kvt ${process.env.SIGNING_TENANT_ID} ` + + `-kvs ${process.env.SIGNING_CLIENT_SECRET} ` + + `-kvc ${process.env.SIGNING_CERT_NAME} ` + + `-fd ${configuration.hash} ` + + `-du ${configuration.site} ` + + `-tr http://timestamp.digicert.com ` + + `${configuration.path}`, + { + stdio: "inherit", + } + ); + } +}; diff --git a/apps/desktop/src/app/accounts/environment.component.html b/apps/desktop/src/app/accounts/environment.component.html new file mode 100644 index 0000000000..eff32641c8 --- /dev/null +++ b/apps/desktop/src/app/accounts/environment.component.html @@ -0,0 +1,93 @@ + diff --git a/apps/desktop/src/app/accounts/environment.component.ts b/apps/desktop/src/app/accounts/environment.component.ts new file mode 100644 index 0000000000..e9077384b2 --- /dev/null +++ b/apps/desktop/src/app/accounts/environment.component.ts @@ -0,0 +1,20 @@ +import { Component } from "@angular/core"; + +import { EnvironmentComponent as BaseEnvironmentComponent } from "jslib-angular/components/environment.component"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-environment", + templateUrl: "environment.component.html", +}) +export class EnvironmentComponent extends BaseEnvironmentComponent { + constructor( + platformUtilsService: PlatformUtilsService, + environmentService: EnvironmentService, + i18nService: I18nService + ) { + super(platformUtilsService, environmentService, i18nService); + } +} diff --git a/apps/desktop/src/app/accounts/hint.component.html b/apps/desktop/src/app/accounts/hint.component.html new file mode 100644 index 0000000000..3ab6088c94 --- /dev/null +++ b/apps/desktop/src/app/accounts/hint.component.html @@ -0,0 +1,31 @@ +
+
+

{{ "passwordHint" | i18n }}

+
+
+
+ + +
+
+ +
+
+ + +
+
+
diff --git a/apps/desktop/src/app/accounts/hint.component.ts b/apps/desktop/src/app/accounts/hint.component.ts new file mode 100644 index 0000000000..5bed1b5858 --- /dev/null +++ b/apps/desktop/src/app/accounts/hint.component.ts @@ -0,0 +1,24 @@ +import { Component } from "@angular/core"; +import { Router } from "@angular/router"; + +import { HintComponent as BaseHintComponent } from "jslib-angular/components/hint.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-hint", + templateUrl: "hint.component.html", +}) +export class HintComponent extends BaseHintComponent { + constructor( + router: Router, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + apiService: ApiService, + logService: LogService + ) { + super(router, i18nService, apiService, platformUtilsService, logService); + } +} diff --git a/apps/desktop/src/app/accounts/lock.component.html b/apps/desktop/src/app/accounts/lock.component.html new file mode 100644 index 0000000000..f5d8b36935 --- /dev/null +++ b/apps/desktop/src/app/accounts/lock.component.html @@ -0,0 +1,75 @@ +
+
+ +

{{ "yourVaultIsLocked" | i18n }}

+
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+
+ +
+
+ + +
+
+
+
diff --git a/apps/desktop/src/app/accounts/lock.component.ts b/apps/desktop/src/app/accounts/lock.component.ts new file mode 100644 index 0000000000..4720e49894 --- /dev/null +++ b/apps/desktop/src/app/accounts/lock.component.ts @@ -0,0 +1,107 @@ +import { Component, NgZone, OnDestroy } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { ipcRenderer } from "electron"; + +import { LockComponent as BaseLockComponent } from "jslib-angular/components/lock.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; + +const BroadcasterSubscriptionId = "LockComponent"; + +@Component({ + selector: "app-lock", + templateUrl: "lock.component.html", +}) +export class LockComponent extends BaseLockComponent implements OnDestroy { + private deferFocus: boolean = null; + + constructor( + router: Router, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + messagingService: MessagingService, + cryptoService: CryptoService, + vaultTimeoutService: VaultTimeoutService, + environmentService: EnvironmentService, + stateService: StateService, + apiService: ApiService, + private route: ActivatedRoute, + private broadcasterService: BroadcasterService, + ngZone: NgZone, + logService: LogService, + keyConnectorService: KeyConnectorService + ) { + super( + router, + i18nService, + platformUtilsService, + messagingService, + cryptoService, + vaultTimeoutService, + environmentService, + stateService, + apiService, + logService, + keyConnectorService, + ngZone + ); + } + + async ngOnInit() { + await super.ngOnInit(); + const autoPromptBiometric = !(await this.stateService.getNoAutoPromptBiometrics()); + + this.route.queryParams.subscribe((params) => { + if (this.supportsBiometric && params.promptBiometric && autoPromptBiometric) { + setTimeout(async () => { + if (await ipcRenderer.invoke("windowVisible")) { + this.unlockBiometric(); + } + }, 1000); + } + }); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case "windowHidden": + this.onWindowHidden(); + break; + case "windowIsFocused": + if (this.deferFocus === null) { + this.deferFocus = !message.windowIsFocused; + if (!this.deferFocus) { + this.focusInput(); + } + } else if (this.deferFocus && message.windowIsFocused) { + this.focusInput(); + this.deferFocus = false; + } + break; + default: + } + }); + }); + this.messagingService.send("getWindowIsFocused"); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + onWindowHidden() { + this.showPassword = false; + } + + private focusInput() { + document.getElementById(this.pinLock ? "pin" : "masterPassword").focus(); + } +} diff --git a/apps/desktop/src/app/accounts/login.component.html b/apps/desktop/src/app/accounts/login.component.html new file mode 100644 index 0000000000..4ec1307f54 --- /dev/null +++ b/apps/desktop/src/app/accounts/login.component.html @@ -0,0 +1,104 @@ +
+ +
+
+ Bitwarden +

{{ "loginOrCreateNewAccount" | i18n }}

+
+
+
+ + +
+
+
+ + +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+ + +
+
+ +
+
+
+ +
+
+
+
+ diff --git a/apps/desktop/src/app/accounts/login.component.ts b/apps/desktop/src/app/accounts/login.component.ts new file mode 100644 index 0000000000..022aae21ea --- /dev/null +++ b/apps/desktop/src/app/accounts/login.component.ts @@ -0,0 +1,128 @@ +import { Component, NgZone, OnDestroy, ViewChild, ViewContainerRef } from "@angular/core"; +import { Router } from "@angular/router"; + +import { LoginComponent as BaseLoginComponent } from "jslib-angular/components/login.component"; +import { ModalService } from "jslib-angular/services/modal.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +import { EnvironmentComponent } from "./environment.component"; + +const BroadcasterSubscriptionId = "LoginComponent"; + +@Component({ + selector: "app-login", + templateUrl: "login.component.html", +}) +export class LoginComponent extends BaseLoginComponent implements OnDestroy { + @ViewChild("environment", { read: ViewContainerRef, static: true }) + environmentModal: ViewContainerRef; + + showingModal = false; + + protected alwaysRememberEmail = true; + + private deferFocus: boolean = null; + + constructor( + authService: AuthService, + router: Router, + i18nService: I18nService, + syncService: SyncService, + private modalService: ModalService, + platformUtilsService: PlatformUtilsService, + stateService: StateService, + environmentService: EnvironmentService, + passwordGenerationService: PasswordGenerationService, + cryptoFunctionService: CryptoFunctionService, + private broadcasterService: BroadcasterService, + ngZone: NgZone, + private messagingService: MessagingService, + logService: LogService + ) { + super( + authService, + router, + platformUtilsService, + i18nService, + stateService, + environmentService, + passwordGenerationService, + cryptoFunctionService, + logService, + ngZone + ); + super.onSuccessfulLogin = () => { + return syncService.fullSync(true); + }; + } + + async ngOnInit() { + await super.ngOnInit(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case "windowHidden": + this.onWindowHidden(); + break; + case "windowIsFocused": + if (this.deferFocus === null) { + this.deferFocus = !message.windowIsFocused; + if (!this.deferFocus) { + this.focusInput(); + } + } else if (this.deferFocus && message.windowIsFocused) { + this.focusInput(); + this.deferFocus = false; + } + break; + default: + } + }); + }); + this.messagingService.send("getWindowIsFocused"); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async settings() { + const [modal, childComponent] = await this.modalService.openViewRef( + EnvironmentComponent, + this.environmentModal + ); + + modal.onShown.subscribe(() => { + this.showingModal = true; + }); + modal.onClosed.subscribe(() => { + this.showingModal = false; + }); + + childComponent.onSaved.subscribe(() => { + modal.close(); + }); + } + + onWindowHidden() { + this.showPassword = false; + } + + async submit() { + await super.submit(); + if (this.captchaSiteKey) { + const content = document.getElementById("content") as HTMLDivElement; + content.setAttribute("style", "width:335px"); + } + } +} diff --git a/apps/desktop/src/app/accounts/premium.component.html b/apps/desktop/src/app/accounts/premium.component.html new file mode 100644 index 0000000000..01c181daa8 --- /dev/null +++ b/apps/desktop/src/app/accounts/premium.component.html @@ -0,0 +1,89 @@ + diff --git a/apps/desktop/src/app/accounts/premium.component.ts b/apps/desktop/src/app/accounts/premium.component.ts new file mode 100644 index 0000000000..7e97860f74 --- /dev/null +++ b/apps/desktop/src/app/accounts/premium.component.ts @@ -0,0 +1,24 @@ +import { Component } from "@angular/core"; + +import { PremiumComponent as BasePremiumComponent } from "jslib-angular/components/premium.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Component({ + selector: "app-premium", + templateUrl: "premium.component.html", +}) +export class PremiumComponent extends BasePremiumComponent { + constructor( + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + apiService: ApiService, + logService: LogService, + stateService: StateService + ) { + super(i18nService, platformUtilsService, apiService, logService, stateService); + } +} diff --git a/apps/desktop/src/app/accounts/register.component.html b/apps/desktop/src/app/accounts/register.component.html new file mode 100644 index 0000000000..3de6aac86c --- /dev/null +++ b/apps/desktop/src/app/accounts/register.component.html @@ -0,0 +1,148 @@ +
+
+

{{ "createAccount" | i18n }}

+
+
+
+ + +
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+ + +
+
+ +
+
+
+ + +
+
+ +
+
+ +
+
+ +
+
+ + +
+
+
diff --git a/apps/desktop/src/app/accounts/register.component.ts b/apps/desktop/src/app/accounts/register.component.ts new file mode 100644 index 0000000000..4188a19495 --- /dev/null +++ b/apps/desktop/src/app/accounts/register.component.ts @@ -0,0 +1,73 @@ +import { Component, NgZone, OnDestroy, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; + +import { RegisterComponent as BaseRegisterComponent } from "jslib-angular/components/register.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +const BroadcasterSubscriptionId = "RegisterComponent"; + +@Component({ + selector: "app-register", + templateUrl: "register.component.html", +}) +export class RegisterComponent extends BaseRegisterComponent implements OnInit, OnDestroy { + constructor( + authService: AuthService, + router: Router, + i18nService: I18nService, + cryptoService: CryptoService, + apiService: ApiService, + stateService: StateService, + platformUtilsService: PlatformUtilsService, + passwordGenerationService: PasswordGenerationService, + environmentService: EnvironmentService, + private broadcasterService: BroadcasterService, + private ngZone: NgZone, + logService: LogService + ) { + super( + authService, + router, + i18nService, + cryptoService, + apiService, + stateService, + platformUtilsService, + passwordGenerationService, + environmentService, + logService + ); + } + + async ngOnInit() { + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case "windowHidden": + this.onWindowHidden(); + break; + default: + } + }); + }); + + super.ngOnInit(); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + onWindowHidden() { + this.showPassword = false; + } +} diff --git a/apps/desktop/src/app/accounts/remove-password.component.html b/apps/desktop/src/app/accounts/remove-password.component.html new file mode 100644 index 0000000000..87f86e7721 --- /dev/null +++ b/apps/desktop/src/app/accounts/remove-password.component.html @@ -0,0 +1,26 @@ +
+
+

{{ "removeMasterPassword" | i18n }}

+

{{ "convertOrganizationEncryptionDesc" | i18n: organization.name }}

+
+ + +
+
+
diff --git a/apps/desktop/src/app/accounts/remove-password.component.ts b/apps/desktop/src/app/accounts/remove-password.component.ts new file mode 100644 index 0000000000..cdb75058ab --- /dev/null +++ b/apps/desktop/src/app/accounts/remove-password.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +import { RemovePasswordComponent as BaseRemovePasswordComponent } from "jslib-angular/components/remove-password.component"; + +@Component({ + selector: "app-remove-password", + templateUrl: "remove-password.component.html", +}) +export class RemovePasswordComponent extends BaseRemovePasswordComponent {} diff --git a/apps/desktop/src/app/accounts/set-password.component.html b/apps/desktop/src/app/accounts/set-password.component.html new file mode 100644 index 0000000000..0e51f5f277 --- /dev/null +++ b/apps/desktop/src/app/accounts/set-password.component.html @@ -0,0 +1,157 @@ +
+
+ Bitwarden +

{{ "setMasterPassword" | i18n }}

+
+ + {{ "loading" | i18n }} +
+
+
+ {{ "ssoCompleteRegistration" | i18n }} + + {{ "resetPasswordAutoEnrollInviteWarning" | i18n }} + + + +
+ +
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+
+ + +
+
+ +
+
+ + +
+ +
+
+ diff --git a/apps/desktop/src/app/accounts/set-password.component.ts b/apps/desktop/src/app/accounts/set-password.component.ts new file mode 100644 index 0000000000..b2aa69738f --- /dev/null +++ b/apps/desktop/src/app/accounts/set-password.component.ts @@ -0,0 +1,104 @@ +import { Component, NgZone, OnDestroy } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { SetPasswordComponent as BaseSetPasswordComponent } from "jslib-angular/components/set-password.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +const BroadcasterSubscriptionId = "SetPasswordComponent"; + +@Component({ + selector: "app-set-password", + templateUrl: "set-password.component.html", +}) +export class SetPasswordComponent extends BaseSetPasswordComponent implements OnDestroy { + constructor( + apiService: ApiService, + i18nService: I18nService, + cryptoService: CryptoService, + messagingService: MessagingService, + passwordGenerationService: PasswordGenerationService, + platformUtilsService: PlatformUtilsService, + policyService: PolicyService, + router: Router, + syncService: SyncService, + route: ActivatedRoute, + private broadcasterService: BroadcasterService, + private ngZone: NgZone, + stateService: StateService + ) { + super( + i18nService, + cryptoService, + messagingService, + passwordGenerationService, + platformUtilsService, + policyService, + router, + apiService, + syncService, + route, + stateService + ); + } + + get masterPasswordScoreWidth() { + return this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20; + } + + get masterPasswordScoreColor() { + switch (this.masterPasswordScore) { + case 4: + return "success"; + case 3: + return "primary"; + case 2: + return "warning"; + default: + return "danger"; + } + } + + get masterPasswordScoreText() { + switch (this.masterPasswordScore) { + case 4: + return this.i18nService.t("strong"); + case 3: + return this.i18nService.t("good"); + case 2: + return this.i18nService.t("weak"); + default: + return this.masterPasswordScore != null ? this.i18nService.t("weak") : null; + } + } + + async ngOnInit() { + await super.ngOnInit(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case "windowHidden": + this.onWindowHidden(); + break; + default: + } + }); + }); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + onWindowHidden() { + this.showPassword = false; + } +} diff --git a/apps/desktop/src/app/accounts/settings.component.html b/apps/desktop/src/app/accounts/settings.component.html new file mode 100644 index 0000000000..9c39a35ebb --- /dev/null +++ b/apps/desktop/src/app/accounts/settings.component.html @@ -0,0 +1,354 @@ + diff --git a/apps/desktop/src/app/accounts/settings.component.ts b/apps/desktop/src/app/accounts/settings.component.ts new file mode 100644 index 0000000000..78ae76ea29 --- /dev/null +++ b/apps/desktop/src/app/accounts/settings.component.ts @@ -0,0 +1,418 @@ +import { Component, OnInit } from "@angular/core"; +import { FormControl } from "@angular/forms"; +import { debounceTime } from "rxjs/operators"; + +import { ModalService } from "jslib-angular/services/modal.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { DeviceType } from "jslib-common/enums/deviceType"; +import { StorageLocation } from "jslib-common/enums/storageLocation"; +import { ThemeType } from "jslib-common/enums/themeType"; +import { Utils } from "jslib-common/misc/utils"; +import { isWindowsStore } from "jslib-electron/utils"; + +import { SetPinComponent } from "../components/set-pin.component"; + +@Component({ + selector: "app-settings", + templateUrl: "settings.component.html", +}) +export class SettingsComponent implements OnInit { + vaultTimeoutAction: string; + pin: boolean = null; + disableFavicons = false; + enableBrowserIntegration = false; + enableBrowserIntegrationFingerprint = false; + enableMinToTray = false; + enableCloseToTray = false; + enableTray = false; + showMinToTray = false; + startToTray = false; + minimizeOnCopyToClipboard = false; + locale: string; + vaultTimeouts: any[]; + localeOptions: any[]; + theme: ThemeType; + themeOptions: any[]; + clearClipboard: number; + clearClipboardOptions: any[]; + supportsBiometric: boolean; + biometric: boolean; + biometricText: string; + noAutoPromptBiometrics: boolean; + noAutoPromptBiometricsText: string; + alwaysShowDock: boolean; + showAlwaysShowDock = false; + openAtLogin: boolean; + requireEnableTray = false; + + enableTrayText: string; + enableTrayDescText: string; + enableMinToTrayText: string; + enableMinToTrayDescText: string; + enableCloseToTrayText: string; + enableCloseToTrayDescText: string; + startToTrayText: string; + startToTrayDescText: string; + + vaultTimeout: FormControl = new FormControl(null); + + showSecurity = true; + showAccountPreferences = true; + showAppPreferences = true; + + currentUserEmail: string; + + constructor( + private i18nService: I18nService, + private platformUtilsService: PlatformUtilsService, + private vaultTimeoutService: VaultTimeoutService, + private stateService: StateService, + private messagingService: MessagingService, + private cryptoService: CryptoService, + private modalService: ModalService + ) { + const isMac = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop; + + // Workaround to avoid ghosting trays https://github.com/electron/electron/issues/17622 + this.requireEnableTray = this.platformUtilsService.getDevice() === DeviceType.LinuxDesktop; + + const trayKey = isMac ? "enableMenuBar" : "enableTray"; + this.enableTrayText = this.i18nService.t(trayKey); + this.enableTrayDescText = this.i18nService.t(trayKey + "Desc"); + + const minToTrayKey = isMac ? "enableMinToMenuBar" : "enableMinToTray"; + this.enableMinToTrayText = this.i18nService.t(minToTrayKey); + this.enableMinToTrayDescText = this.i18nService.t(minToTrayKey + "Desc"); + + const closeToTrayKey = isMac ? "enableCloseToMenuBar" : "enableCloseToTray"; + this.enableCloseToTrayText = this.i18nService.t(closeToTrayKey); + this.enableCloseToTrayDescText = this.i18nService.t(closeToTrayKey + "Desc"); + + const startToTrayKey = isMac ? "startToMenuBar" : "startToTray"; + this.startToTrayText = this.i18nService.t(startToTrayKey); + this.startToTrayDescText = this.i18nService.t(startToTrayKey + "Desc"); + + this.vaultTimeouts = [ + // { name: i18nService.t('immediately'), value: 0 }, + { name: i18nService.t("oneMinute"), value: 1 }, + { name: i18nService.t("fiveMinutes"), value: 5 }, + { name: i18nService.t("fifteenMinutes"), value: 15 }, + { name: i18nService.t("thirtyMinutes"), value: 30 }, + { name: i18nService.t("oneHour"), value: 60 }, + { name: i18nService.t("fourHours"), value: 240 }, + { name: i18nService.t("onIdle"), value: -4 }, + { name: i18nService.t("onSleep"), value: -3 }, + ]; + + if (this.platformUtilsService.getDevice() !== DeviceType.LinuxDesktop) { + this.vaultTimeouts.push({ name: i18nService.t("onLocked"), value: -2 }); + } + + this.vaultTimeouts = this.vaultTimeouts.concat([ + { name: i18nService.t("onRestart"), value: -1 }, + { name: i18nService.t("never"), value: null }, + ]); + + const localeOptions: any[] = []; + i18nService.supportedTranslationLocales.forEach((locale) => { + let name = locale; + if (i18nService.localeNames.has(locale)) { + name += " - " + i18nService.localeNames.get(locale); + } + localeOptions.push({ name: name, value: locale }); + }); + localeOptions.sort(Utils.getSortFunction(i18nService, "name")); + localeOptions.splice(0, 0, { name: i18nService.t("default"), value: null }); + this.localeOptions = localeOptions; + + this.themeOptions = [ + { name: i18nService.t("default"), value: ThemeType.System }, + { name: i18nService.t("light"), value: ThemeType.Light }, + { name: i18nService.t("dark"), value: ThemeType.Dark }, + { name: "Nord", value: ThemeType.Nord }, + ]; + + this.clearClipboardOptions = [ + { name: i18nService.t("never"), value: null }, + { name: i18nService.t("tenSeconds"), value: 10 }, + { name: i18nService.t("twentySeconds"), value: 20 }, + { name: i18nService.t("thirtySeconds"), value: 30 }, + { name: i18nService.t("oneMinute"), value: 60 }, + { name: i18nService.t("twoMinutes"), value: 120 }, + { name: i18nService.t("fiveMinutes"), value: 300 }, + ]; + } + + async ngOnInit() { + // App preferences + this.showMinToTray = this.platformUtilsService.getDevice() !== DeviceType.LinuxDesktop; + this.enableMinToTray = await this.stateService.getEnableMinimizeToTray(); + this.enableCloseToTray = await this.stateService.getEnableCloseToTray(); + this.enableTray = await this.stateService.getEnableTray(); + this.startToTray = await this.stateService.getEnableStartToTray(); + + this.alwaysShowDock = await this.stateService.getAlwaysShowDock(); + this.showAlwaysShowDock = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop; + this.openAtLogin = await this.stateService.getOpenAtLogin(); + + this.locale = await this.stateService.getLocale(); + this.theme = await this.stateService.getTheme(); + + if ((await this.stateService.getUserId()) == null) { + return; + } + this.currentUserEmail = await this.stateService.getEmail(); + + // Security + this.vaultTimeout.setValue(await this.stateService.getVaultTimeout()); + this.vaultTimeoutAction = await this.stateService.getVaultTimeoutAction(); + this.vaultTimeout.valueChanges.pipe(debounceTime(500)).subscribe(() => { + this.saveVaultTimeoutOptions(); + }); + + const pinSet = await this.vaultTimeoutService.isPinLockSet(); + this.pin = pinSet[0] || pinSet[1]; + + // Account preferences + this.disableFavicons = await this.stateService.getDisableFavicon(); + this.enableBrowserIntegration = await this.stateService.getEnableBrowserIntegration(); + this.enableBrowserIntegrationFingerprint = + await this.stateService.getEnableBrowserIntegrationFingerprint(); + this.clearClipboard = await this.stateService.getClearClipboard(); + this.minimizeOnCopyToClipboard = await this.stateService.getMinimizeOnCopyToClipboard(); + this.supportsBiometric = await this.platformUtilsService.supportsBiometric(); + this.biometric = await this.vaultTimeoutService.isBiometricLockSet(); + this.biometricText = await this.stateService.getBiometricText(); + this.noAutoPromptBiometrics = await this.stateService.getNoAutoPromptBiometrics(); + this.noAutoPromptBiometricsText = await this.stateService.getNoAutoPromptBiometricsText(); + } + + async saveVaultTimeoutOptions() { + if (this.vaultTimeoutAction === "logOut") { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("vaultTimeoutLogOutConfirmation"), + this.i18nService.t("vaultTimeoutLogOutConfirmationTitle"), + this.i18nService.t("yes"), + this.i18nService.t("cancel"), + "warning" + ); + if (!confirmed) { + this.vaultTimeoutAction = "lock"; + return; + } + } + + // Avoid saving 0 since it's useless as a timeout value. + if (this.vaultTimeout.value === 0) { + return; + } + + if (!this.vaultTimeout.valid) { + this.platformUtilsService.showToast( + "error", + null, + this.i18nService.t("vaultTimeoutTooLarge") + ); + return; + } + + await this.vaultTimeoutService.setVaultTimeoutOptions( + this.vaultTimeout.value, + this.vaultTimeoutAction + ); + } + + async updatePin() { + if (this.pin) { + const ref = this.modalService.open(SetPinComponent, { allowMultipleModals: true }); + + if (ref == null) { + this.pin = false; + return; + } + + this.pin = await ref.onClosedPromise(); + } + if (!this.pin) { + await this.cryptoService.clearPinProtectedKey(); + await this.vaultTimeoutService.clear(); + } + } + + async updateBiometric() { + const current = this.biometric; + if (this.biometric) { + this.biometric = false; + } else if (this.supportsBiometric) { + this.biometric = await this.platformUtilsService.authenticateBiometric(); + } + if (this.biometric === current) { + return; + } + if (this.biometric) { + await this.stateService.setBiometricUnlock(true); + } else { + await this.stateService.setBiometricUnlock(null); + await this.stateService.setNoAutoPromptBiometrics(null); + this.noAutoPromptBiometrics = false; + } + await this.stateService.setBiometricLocked(false); + await this.cryptoService.toggleKey(); + } + + async updateNoAutoPromptBiometrics() { + if (!this.biometric) { + this.noAutoPromptBiometrics = false; + } + + if (this.noAutoPromptBiometrics) { + await this.stateService.setNoAutoPromptBiometrics(true); + } else { + await this.stateService.setNoAutoPromptBiometrics(null); + } + } + + async saveFavicons() { + await this.stateService.setDisableFavicon(this.disableFavicons); + await this.stateService.setDisableFavicon(this.disableFavicons, { + storageLocation: StorageLocation.Disk, + }); + this.messagingService.send("refreshCiphers"); + } + + async saveMinToTray() { + await this.stateService.setEnableMinimizeToTray(this.enableMinToTray); + } + + async saveCloseToTray() { + if (this.requireEnableTray) { + this.enableTray = true; + await this.stateService.setEnableTray(this.enableTray); + } + + await this.stateService.setEnableCloseToTray(this.enableCloseToTray); + } + + async saveTray() { + if ( + this.requireEnableTray && + !this.enableTray && + (this.startToTray || this.enableCloseToTray) + ) { + const confirm = await this.platformUtilsService.showDialog( + this.i18nService.t("confirmTrayDesc"), + this.i18nService.t("confirmTrayTitle"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + + if (confirm) { + this.startToTray = false; + await this.stateService.setEnableStartToTray(this.startToTray); + this.enableCloseToTray = false; + await this.stateService.setEnableCloseToTray(this.enableCloseToTray); + } else { + this.enableTray = true; + } + + return; + } + + await this.stateService.setEnableTray(this.enableTray); + this.messagingService.send(this.enableTray ? "showTray" : "removeTray"); + } + + async saveStartToTray() { + if (this.requireEnableTray) { + this.enableTray = true; + await this.stateService.setEnableTray(this.enableTray); + } + + await this.stateService.setEnableStartToTray(this.startToTray); + } + + async saveLocale() { + await this.stateService.setLocale(this.locale); + } + + async saveTheme() { + await this.stateService.setTheme(this.theme); + window.setTimeout(() => window.location.reload(), 200); + } + + async saveMinOnCopyToClipboard() { + await this.stateService.setMinimizeOnCopyToClipboard(this.minimizeOnCopyToClipboard); + } + + async saveClearClipboard() { + await this.stateService.setClearClipboard(this.clearClipboard); + } + + async saveAlwaysShowDock() { + await this.stateService.setAlwaysShowDock(this.alwaysShowDock); + } + + async saveOpenAtLogin() { + this.stateService.setOpenAtLogin(this.openAtLogin); + this.messagingService.send(this.openAtLogin ? "addOpenAtLogin" : "removeOpenAtLogin"); + } + + async saveBrowserIntegration() { + if (process.platform === "darwin" && !this.platformUtilsService.isMacAppStore()) { + await this.platformUtilsService.showDialog( + this.i18nService.t("browserIntegrationMasOnlyDesc"), + this.i18nService.t("browserIntegrationUnsupportedTitle"), + this.i18nService.t("ok"), + null, + "warning" + ); + + this.enableBrowserIntegration = false; + return; + } else if (isWindowsStore()) { + await this.platformUtilsService.showDialog( + this.i18nService.t("browserIntegrationWindowsStoreDesc"), + this.i18nService.t("browserIntegrationUnsupportedTitle"), + this.i18nService.t("ok"), + null, + "warning" + ); + + this.enableBrowserIntegration = false; + return; + } else if (process.platform == "linux") { + await this.platformUtilsService.showDialog( + this.i18nService.t("browserIntegrationLinuxDesc"), + this.i18nService.t("browserIntegrationUnsupportedTitle"), + this.i18nService.t("ok"), + null, + "warning" + ); + + this.enableBrowserIntegration = false; + return; + } + + await this.stateService.setEnableBrowserIntegration(this.enableBrowserIntegration); + this.messagingService.send( + this.enableBrowserIntegration ? "enableBrowserIntegration" : "disableBrowserIntegration" + ); + + if (!this.enableBrowserIntegration) { + this.enableBrowserIntegrationFingerprint = false; + this.saveBrowserIntegrationFingerprint(); + } + } + + async saveBrowserIntegrationFingerprint() { + await this.stateService.setEnableBrowserIntegrationFingerprint( + this.enableBrowserIntegrationFingerprint + ); + } +} diff --git a/apps/desktop/src/app/accounts/sso.component.html b/apps/desktop/src/app/accounts/sso.component.html new file mode 100644 index 0000000000..cb5bba9dc6 --- /dev/null +++ b/apps/desktop/src/app/accounts/sso.component.html @@ -0,0 +1,9 @@ +
+
+ Bitwarden +
+ + {{ "loading" | i18n }} +
+
+
diff --git a/apps/desktop/src/app/accounts/sso.component.ts b/apps/desktop/src/app/accounts/sso.component.ts new file mode 100644 index 0000000000..d23dc0ee6b --- /dev/null +++ b/apps/desktop/src/app/accounts/sso.component.ts @@ -0,0 +1,54 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { SsoComponent as BaseSsoComponent } from "jslib-angular/components/sso.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +@Component({ + selector: "app-sso", + templateUrl: "sso.component.html", +}) +export class SsoComponent extends BaseSsoComponent { + constructor( + authService: AuthService, + router: Router, + i18nService: I18nService, + syncService: SyncService, + route: ActivatedRoute, + stateService: StateService, + platformUtilsService: PlatformUtilsService, + apiService: ApiService, + cryptoFunctionService: CryptoFunctionService, + environmentService: EnvironmentService, + passwordGenerationService: PasswordGenerationService, + logService: LogService + ) { + super( + authService, + router, + i18nService, + route, + stateService, + platformUtilsService, + apiService, + cryptoFunctionService, + environmentService, + passwordGenerationService, + logService + ); + super.onSuccessfulLogin = () => { + return syncService.fullSync(true); + }; + this.redirectUri = "bitwarden://sso-callback"; + this.clientId = "desktop"; + } +} diff --git a/apps/desktop/src/app/accounts/two-factor-options.component.html b/apps/desktop/src/app/accounts/two-factor-options.component.html new file mode 100644 index 0000000000..778d2636e3 --- /dev/null +++ b/apps/desktop/src/app/accounts/two-factor-options.component.html @@ -0,0 +1,33 @@ + diff --git a/apps/desktop/src/app/accounts/two-factor-options.component.ts b/apps/desktop/src/app/accounts/two-factor-options.component.ts new file mode 100644 index 0000000000..892c971bf9 --- /dev/null +++ b/apps/desktop/src/app/accounts/two-factor-options.component.ts @@ -0,0 +1,22 @@ +import { Component } from "@angular/core"; +import { Router } from "@angular/router"; + +import { TwoFactorOptionsComponent as BaseTwoFactorOptionsComponent } from "jslib-angular/components/two-factor-options.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; + +@Component({ + selector: "app-two-factor-options", + templateUrl: "two-factor-options.component.html", +}) +export class TwoFactorOptionsComponent extends BaseTwoFactorOptionsComponent { + constructor( + twoFactorService: TwoFactorService, + router: Router, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService + ) { + super(twoFactorService, router, i18nService, platformUtilsService, window); + } +} diff --git a/apps/desktop/src/app/accounts/two-factor.component.html b/apps/desktop/src/app/accounts/two-factor.component.html new file mode 100644 index 0000000000..e18a1dd0d2 --- /dev/null +++ b/apps/desktop/src/app/accounts/two-factor.component.html @@ -0,0 +1,144 @@ +
+
+

{{ title }}

+

+ {{ "enterVerificationCodeApp" | i18n }} +

+

+ {{ "enterVerificationCodeEmail" | i18n: twoFactorEmail }} +

+
+
+
+ + +
+
+ + +
+
+
+ +

{{ "insertYubiKey" | i18n }}

+ +
+
+
+ + +
+
+ + +
+
+
+
+ +
+ +
+
+
+
+ + +
+
+
+
+ +
+
+
+
+ + +
+
+
+
+
+
+
+

{{ "noTwoStepProviders" | i18n }}

+

{{ "noTwoStepProviders2" | i18n }}

+
+
+
+
+
+
+ +
+
+
+
+ + +
+
+ + +
+
+
+ diff --git a/apps/desktop/src/app/accounts/two-factor.component.ts b/apps/desktop/src/app/accounts/two-factor.component.ts new file mode 100644 index 0000000000..acf8919f49 --- /dev/null +++ b/apps/desktop/src/app/accounts/two-factor.component.ts @@ -0,0 +1,94 @@ +import { Component, ViewChild, ViewContainerRef } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; + +import { TwoFactorComponent as BaseTwoFactorComponent } from "jslib-angular/components/two-factor.component"; +import { ModalService } from "jslib-angular/services/modal.service"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType"; + +import { TwoFactorOptionsComponent } from "./two-factor-options.component"; + +@Component({ + selector: "app-two-factor", + templateUrl: "two-factor.component.html", +}) +export class TwoFactorComponent extends BaseTwoFactorComponent { + @ViewChild("twoFactorOptions", { read: ViewContainerRef, static: true }) + twoFactorOptionsModal: ViewContainerRef; + + showingModal = false; + + constructor( + authService: AuthService, + router: Router, + i18nService: I18nService, + apiService: ApiService, + platformUtilsService: PlatformUtilsService, + syncService: SyncService, + environmentService: EnvironmentService, + private modalService: ModalService, + stateService: StateService, + route: ActivatedRoute, + logService: LogService, + twoFactorService: TwoFactorService, + appIdService: AppIdService + ) { + super( + authService, + router, + i18nService, + apiService, + platformUtilsService, + window, + environmentService, + stateService, + route, + logService, + twoFactorService, + appIdService + ); + super.onSuccessfulLogin = () => { + return syncService.fullSync(true); + }; + } + + async anotherMethod() { + const [modal, childComponent] = await this.modalService.openViewRef( + TwoFactorOptionsComponent, + this.twoFactorOptionsModal + ); + + modal.onShown.subscribe(() => { + this.showingModal = true; + }); + modal.onClosed.subscribe(() => { + this.showingModal = false; + }); + + childComponent.onProviderSelected.subscribe(async (provider: TwoFactorProviderType) => { + modal.close(); + this.selectedProviderType = provider; + await this.init(); + }); + childComponent.onRecoverSelected.subscribe(() => { + modal.close(); + }); + } + + async submit() { + await super.submit(); + if (this.captchaSiteKey) { + const content = document.getElementById("content") as HTMLDivElement; + content.setAttribute("style", "width:335px"); + } + } +} diff --git a/apps/desktop/src/app/accounts/update-temp-password.component.html b/apps/desktop/src/app/accounts/update-temp-password.component.html new file mode 100644 index 0000000000..6f5772fc6d --- /dev/null +++ b/apps/desktop/src/app/accounts/update-temp-password.component.html @@ -0,0 +1,122 @@ +
+
+ + {{ "updateMasterPasswordWarning" | i18n }} + + + +
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+ +
+
+
+
+
+
+
+ + +
+
+ +
+
+ + +
+
+
diff --git a/apps/desktop/src/app/accounts/update-temp-password.component.ts b/apps/desktop/src/app/accounts/update-temp-password.component.ts new file mode 100644 index 0000000000..f12191a163 --- /dev/null +++ b/apps/desktop/src/app/accounts/update-temp-password.component.ts @@ -0,0 +1,80 @@ +import { Component } from "@angular/core"; + +import { UpdateTempPasswordComponent as BaseUpdateTempPasswordComponent } from "jslib-angular/components/update-temp-password.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; + +interface MasterPasswordScore { + Color: string; + Text: string; + Width: number; +} + +@Component({ + selector: "app-update-temp-password", + templateUrl: "update-temp-password.component.html", +}) +export class UpdateTempPasswordComponent extends BaseUpdateTempPasswordComponent { + get masterPasswordScoreStyle(): MasterPasswordScore { + const scoreWidth = this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20; + switch (this.masterPasswordScore) { + case 4: + return { + Color: "bg-success", + Text: "strong", + Width: scoreWidth, + }; + case 3: + return { + Color: "bg-primary", + Text: "good", + Width: scoreWidth, + }; + case 2: + return { + Color: "bg-warning", + Text: "weak", + Width: scoreWidth, + }; + default: + return { + Color: "bg-danger", + Text: "weak", + Width: scoreWidth, + }; + } + } + constructor( + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + passwordGenerationService: PasswordGenerationService, + policyService: PolicyService, + cryptoService: CryptoService, + messagingService: MessagingService, + apiService: ApiService, + syncService: SyncService, + logService: LogService, + stateService: StateService + ) { + super( + i18nService, + platformUtilsService, + passwordGenerationService, + policyService, + cryptoService, + messagingService, + apiService, + stateService, + syncService, + logService + ); + } +} diff --git a/apps/desktop/src/app/accounts/vault-timeout-input.component.html b/apps/desktop/src/app/accounts/vault-timeout-input.component.html new file mode 100644 index 0000000000..62e5a104c1 --- /dev/null +++ b/apps/desktop/src/app/accounts/vault-timeout-input.component.html @@ -0,0 +1,45 @@ + + {{ "vaultTimeoutPolicyInEffect" | i18n: vaultTimeoutPolicyHours:vaultTimeoutPolicyMinutes }} + + +
+
+ + + {{ "vaultTimeoutDesc" | i18n }} +
+
+
+ + +
+
+ + +
+
+
+ +
diff --git a/apps/desktop/src/app/accounts/vault-timeout-input.component.ts b/apps/desktop/src/app/accounts/vault-timeout-input.component.ts new file mode 100644 index 0000000000..8eb308b4c0 --- /dev/null +++ b/apps/desktop/src/app/accounts/vault-timeout-input.component.ts @@ -0,0 +1,22 @@ +import { Component } from "@angular/core"; +import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from "@angular/forms"; + +import { VaultTimeoutInputComponent as VaultTimeoutInputComponentBase } from "jslib-angular/components/settings/vault-timeout-input.component"; + +@Component({ + selector: "app-vault-timeout-input", + templateUrl: "vault-timeout-input.component.html", + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: VaultTimeoutInputComponent, + }, + { + provide: NG_VALIDATORS, + multi: true, + useExisting: VaultTimeoutInputComponent, + }, + ], +}) +export class VaultTimeoutInputComponent extends VaultTimeoutInputComponentBase {} diff --git a/apps/desktop/src/app/app-routing.module.ts b/apps/desktop/src/app/app-routing.module.ts new file mode 100644 index 0000000000..38592bf509 --- /dev/null +++ b/apps/desktop/src/app/app-routing.module.ts @@ -0,0 +1,69 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; + +import { AuthGuard } from "jslib-angular/guards/auth.guard"; +import { LockGuard } from "jslib-angular/guards/lock.guard"; + +import { HintComponent } from "./accounts/hint.component"; +import { LockComponent } from "./accounts/lock.component"; +import { LoginComponent } from "./accounts/login.component"; +import { RegisterComponent } from "./accounts/register.component"; +import { RemovePasswordComponent } from "./accounts/remove-password.component"; +import { SetPasswordComponent } from "./accounts/set-password.component"; +import { SsoComponent } from "./accounts/sso.component"; +import { TwoFactorComponent } from "./accounts/two-factor.component"; +import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.component"; +import { LoginGuard } from "./guards/login.guard"; +import { SendComponent } from "./send/send.component"; +import { VaultComponent } from "./vault/vault.component"; + +const routes: Routes = [ + { path: "", redirectTo: "/vault", pathMatch: "full" }, + { + path: "lock", + component: LockComponent, + canActivate: [LockGuard], + }, + { + path: "login", + component: LoginComponent, + canActivate: [LoginGuard], + }, + { path: "2fa", component: TwoFactorComponent }, + { path: "register", component: RegisterComponent }, + { + path: "vault", + component: VaultComponent, + canActivate: [AuthGuard], + }, + { path: "hint", component: HintComponent }, + { path: "set-password", component: SetPasswordComponent }, + { path: "sso", component: SsoComponent }, + { + path: "send", + component: SendComponent, + canActivate: [AuthGuard], + }, + { + path: "update-temp-password", + component: UpdateTempPasswordComponent, + canActivate: [AuthGuard], + }, + { + path: "remove-password", + component: RemovePasswordComponent, + canActivate: [AuthGuard], + data: { titleId: "removeMasterPassword" }, + }, +]; + +@NgModule({ + imports: [ + RouterModule.forRoot(routes, { + useHash: true, + /*enableTracing: true,*/ + }), + ], + exports: [RouterModule], +}) +export class AppRoutingModule {} diff --git a/apps/desktop/src/app/app.component.ts b/apps/desktop/src/app/app.component.ts new file mode 100644 index 0000000000..b824b5fe3a --- /dev/null +++ b/apps/desktop/src/app/app.component.ts @@ -0,0 +1,626 @@ +import { + Component, + NgZone, + OnInit, + SecurityContext, + Type, + ViewChild, + ViewContainerRef, +} from "@angular/core"; +import { DomSanitizer } from "@angular/platform-browser"; +import { Router } from "@angular/router"; +import { IndividualConfig, ToastrService } from "ngx-toastr"; + +import { ModalRef } from "jslib-angular/components/modal/modal.ref"; +import { ModalService } from "jslib-angular/services/modal.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { NotificationsService } from "jslib-common/abstractions/notifications.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SettingsService } from "jslib-common/abstractions/settings.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { SystemService } from "jslib-common/abstractions/system.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { CipherType } from "jslib-common/enums/cipherType"; + +import { MenuUpdateRequest } from "../main/menu/menu.updater"; + +import { PremiumComponent } from "./accounts/premium.component"; +import { SettingsComponent } from "./accounts/settings.component"; +import { ExportComponent } from "./vault/export.component"; +import { FolderAddEditComponent } from "./vault/folder-add-edit.component"; +import { GeneratorComponent } from "./vault/generator.component"; +import { PasswordGeneratorHistoryComponent } from "./vault/password-generator-history.component"; + +const BroadcasterSubscriptionId = "AppComponent"; +const IdleTimeout = 60000 * 10; // 10 minutes +const SyncInterval = 6 * 60 * 60 * 1000; // 6 hours + +const systemTimeoutOptions = { + onLock: -2, + onSuspend: -3, + onIdle: -4, +}; + +@Component({ + selector: "app-root", + styles: [], + template: ` + + + + + + + +
+
+ +
+ +
+ `, +}) +export class AppComponent implements OnInit { + @ViewChild("settings", { read: ViewContainerRef, static: true }) settingsRef: ViewContainerRef; + @ViewChild("premium", { read: ViewContainerRef, static: true }) premiumRef: ViewContainerRef; + @ViewChild("passwordHistory", { read: ViewContainerRef, static: true }) + passwordHistoryRef: ViewContainerRef; + @ViewChild("exportVault", { read: ViewContainerRef, static: true }) + exportVaultModalRef: ViewContainerRef; + @ViewChild("appFolderAddEdit", { read: ViewContainerRef, static: true }) + folderAddEditModalRef: ViewContainerRef; + @ViewChild("appGenerator", { read: ViewContainerRef, static: true }) + generatorModalRef: ViewContainerRef; + + loading = false; + + private lastActivity: number = null; + private modal: ModalRef = null; + private idleTimer: number = null; + private isIdle = false; + private activeUserId: string = null; + + constructor( + private broadcasterService: BroadcasterService, + private tokenService: TokenService, + private folderService: FolderService, + private settingsService: SettingsService, + private syncService: SyncService, + private passwordGenerationService: PasswordGenerationService, + private cipherService: CipherService, + private authService: AuthService, + private router: Router, + private toastrService: ToastrService, + private i18nService: I18nService, + private sanitizer: DomSanitizer, + private ngZone: NgZone, + private vaultTimeoutService: VaultTimeoutService, + private cryptoService: CryptoService, + private logService: LogService, + private messagingService: MessagingService, + private collectionService: CollectionService, + private searchService: SearchService, + private notificationsService: NotificationsService, + private platformUtilsService: PlatformUtilsService, + private systemService: SystemService, + private stateService: StateService, + private eventService: EventService, + private policyService: PolicyService, + private modalService: ModalService, + private keyConnectorService: KeyConnectorService + ) {} + + ngOnInit() { + this.stateService.activeAccount.subscribe((userId) => { + this.activeUserId = userId; + }); + this.ngZone.runOutsideAngular(() => { + setTimeout(async () => { + await this.updateAppMenu(); + }, 1000); + + window.ontouchstart = () => this.recordActivity(); + window.onmousedown = () => this.recordActivity(); + window.onscroll = () => this.recordActivity(); + window.onkeypress = () => this.recordActivity(); + }); + + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "loggedIn": + case "unlocked": + this.notificationsService.updateConnection(); + this.updateAppMenu(); + this.systemService.cancelProcessReload(); + break; + case "loggedOut": + if (this.modal != null) { + this.modal.close(); + } + this.notificationsService.updateConnection(); + this.updateAppMenu(); + await this.systemService.clearPendingClipboard(); + await this.reloadProcess(); + break; + case "authBlocked": + this.router.navigate(["login"]); + break; + case "logout": + this.loading = message.userId == null || message.userId === this.activeUserId; + await this.logOut(!!message.expired, message.userId); + this.loading = false; + break; + case "lockVault": + await this.vaultTimeoutService.lock(true, message.userId); + break; + case "lockAllVaults": + for (const userId in this.stateService.accounts.getValue()) { + if (userId != null) { + await this.vaultTimeoutService.lock(true, userId); + } + } + break; + case "locked": + if (this.modal != null) { + this.modal.close(); + } + if ( + message.userId == null || + message.userId === (await this.stateService.getUserId()) + ) { + await this.router.navigate(["lock"]); + } + this.notificationsService.updateConnection(); + await this.updateAppMenu(); + await this.systemService.clearPendingClipboard(); + await this.reloadProcess(); + break; + case "reloadProcess": + window.location.reload(true); + break; + case "syncStarted": + break; + case "syncCompleted": + await this.updateAppMenu(); + break; + case "openSettings": + await this.openModal(SettingsComponent, this.settingsRef); + break; + case "openPremium": + await this.openModal(PremiumComponent, this.premiumRef); + break; + case "showFingerprintPhrase": { + const fingerprint = await this.cryptoService.getFingerprint( + await this.stateService.getUserId() + ); + const result = await this.platformUtilsService.showDialog( + this.i18nService.t("yourAccountsFingerprint") + ":\n" + fingerprint.join("-"), + this.i18nService.t("fingerprintPhrase"), + this.i18nService.t("learnMore"), + this.i18nService.t("close") + ); + if (result) { + this.platformUtilsService.launchUri("https://bitwarden.com/help/fingerprint-phrase/"); + } + break; + } + case "openPasswordHistory": + await this.openModal( + PasswordGeneratorHistoryComponent, + this.passwordHistoryRef + ); + break; + case "showToast": + this.showToast(message); + break; + case "copiedToClipboard": + if (!message.clearing) { + this.systemService.clearClipboard(message.clipboardValue, message.clearMs); + } + break; + case "ssoCallback": + this.router.navigate(["sso"], { + queryParams: { code: message.code, state: message.state }, + }); + break; + case "premiumRequired": { + const premiumConfirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("premiumRequiredDesc"), + this.i18nService.t("premiumRequired"), + this.i18nService.t("learnMore"), + this.i18nService.t("cancel") + ); + if (premiumConfirmed) { + await this.openModal(PremiumComponent, this.premiumRef); + } + break; + } + case "emailVerificationRequired": { + const emailVerificationConfirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("emailVerificationRequiredDesc"), + this.i18nService.t("emailVerificationRequired"), + this.i18nService.t("learnMore"), + this.i18nService.t("cancel") + ); + if (emailVerificationConfirmed) { + this.platformUtilsService.launchUri( + "https://bitwarden.com/help/create-bitwarden-account/" + ); + } + break; + } + case "syncVault": + try { + await this.syncService.fullSync(true, true); + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("syncingComplete") + ); + } catch { + this.platformUtilsService.showToast( + "error", + null, + this.i18nService.t("syncingFailed") + ); + } + break; + case "checkSyncVault": + try { + const lastSync = await this.syncService.getLastSync(); + let lastSyncAgo = SyncInterval + 1; + if (lastSync != null) { + lastSyncAgo = new Date().getTime() - lastSync.getTime(); + } + + if (lastSyncAgo >= SyncInterval) { + await this.syncService.fullSync(false); + } + } catch (e) { + this.logService.error(e); + } + this.messagingService.send("scheduleNextSync"); + break; + case "exportVault": + await this.openExportVault(); + break; + case "newLogin": + this.routeToVault("add", CipherType.Login); + break; + case "newCard": + this.routeToVault("add", CipherType.Card); + break; + case "newIdentity": + this.routeToVault("add", CipherType.Identity); + break; + case "newSecureNote": + this.routeToVault("add", CipherType.SecureNote); + break; + default: + break; + case "newFolder": + await this.addFolder(); + break; + case "openGenerator": + // openGenerator has extended functionality if called in the vault + if (!this.router.url.includes("vault")) { + await this.openGenerator(); + } + break; + case "convertAccountToKeyConnector": + this.router.navigate(["/remove-password"]); + break; + case "switchAccount": { + if (message.userId != null) { + await this.stateService.setActiveUser(message.userId); + } + const locked = + (await this.authService.getAuthStatus(message.userId)) === + AuthenticationStatus.Locked; + if (locked) { + this.messagingService.send("locked", { userId: message.userId }); + } else { + this.messagingService.send("unlocked"); + this.loading = true; + await this.syncService.fullSync(true); + this.loading = false; + this.router.navigate(["vault"]); + } + break; + } + case "systemSuspended": + await this.checkForSystemTimeout(systemTimeoutOptions.onSuspend); + break; + case "systemLocked": + await this.checkForSystemTimeout(systemTimeoutOptions.onLock); + break; + case "systemIdle": + await this.checkForSystemTimeout(systemTimeoutOptions.onIdle); + break; + } + }); + }); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async openExportVault() { + if (this.modal != null) { + this.modal.close(); + } + + const [modal, childComponent] = await this.modalService.openViewRef( + ExportComponent, + this.exportVaultModalRef + ); + this.modal = modal; + + childComponent.onSaved.subscribe(() => { + this.modal.close(); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + async addFolder() { + if (this.modal != null) { + this.modal.close(); + } + + const [modal, childComponent] = await this.modalService.openViewRef( + FolderAddEditComponent, + this.folderAddEditModalRef, + (comp) => (comp.folderId = null) + ); + this.modal = modal; + + childComponent.onSavedFolder.subscribe(async () => { + this.modal.close(); + this.syncService.fullSync(false); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + async openGenerator() { + if (this.modal != null) { + this.modal.close(); + } + + [this.modal] = await this.modalService.openViewRef( + GeneratorComponent, + this.generatorModalRef, + (comp) => (comp.comingFromAddEdit = false) + ); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + private async updateAppMenu() { + let updateRequest: MenuUpdateRequest; + const stateAccounts = this.stateService.accounts?.getValue(); + if (stateAccounts == null || Object.keys(stateAccounts).length < 1) { + updateRequest = { + accounts: null, + activeUserId: null, + hideChangeMasterPassword: true, + }; + } else { + const accounts: { [userId: string]: any } = {}; + for (const i in stateAccounts) { + if (i != null && stateAccounts[i]?.profile?.userId != null) { + const userId = stateAccounts[i].profile.userId; + accounts[userId] = { + isAuthenticated: await this.stateService.getIsAuthenticated({ + userId: userId, + }), + isLocked: + (await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Locked, + email: stateAccounts[i].profile.email, + userId: stateAccounts[i].profile.userId, + }; + } + } + updateRequest = { + accounts: accounts, + activeUserId: await this.stateService.getUserId(), + hideChangeMasterPassword: await this.keyConnectorService.getUsesKeyConnector(), + }; + } + + this.messagingService.send("updateAppMenu", { updateRequest: updateRequest }); + } + + private async logOut(expired: boolean, userId?: string) { + const userBeingLoggedOut = await this.stateService.getUserId({ userId: userId }); + await Promise.all([ + this.eventService.uploadEvents(userBeingLoggedOut), + this.syncService.setLastSync(new Date(0), userBeingLoggedOut), + this.cryptoService.clearKeys(userBeingLoggedOut), + this.settingsService.clear(userBeingLoggedOut), + this.cipherService.clear(userBeingLoggedOut), + this.folderService.clear(userBeingLoggedOut), + this.collectionService.clear(userBeingLoggedOut), + this.passwordGenerationService.clear(userBeingLoggedOut), + this.vaultTimeoutService.clear(userBeingLoggedOut), + this.policyService.clear(userBeingLoggedOut), + this.keyConnectorService.clear(), + ]); + + await this.stateService.setBiometricLocked(true, { userId: userBeingLoggedOut }); + + if (userBeingLoggedOut === this.activeUserId) { + this.searchService.clearIndex(); + this.authService.logOut(async () => { + if (expired) { + this.platformUtilsService.showToast( + "warning", + this.i18nService.t("loggedOut"), + this.i18nService.t("loginExpired") + ); + } + }); + } + + const preLogoutActiveUserId = this.activeUserId; + await this.stateService.clean({ userId: userBeingLoggedOut }); + + if (this.activeUserId == null) { + this.router.navigate(["login"]); + } else if (preLogoutActiveUserId !== this.activeUserId) { + this.messagingService.send("switchAccount"); + } + + await this.updateAppMenu(); + } + + private async recordActivity() { + if (this.activeUserId == null) { + return; + } + + const now = new Date().getTime(); + if (this.lastActivity != null && now - this.lastActivity < 250) { + return; + } + + this.lastActivity = now; + await this.stateService.setLastActive(now, { userId: this.activeUserId }); + + // Idle states + if (this.isIdle) { + this.isIdle = false; + this.idleStateChanged(); + } + if (this.idleTimer != null) { + window.clearTimeout(this.idleTimer); + this.idleTimer = null; + } + this.idleTimer = window.setTimeout(() => { + if (!this.isIdle) { + this.isIdle = true; + this.idleStateChanged(); + } + }, IdleTimeout); + } + + private idleStateChanged() { + if (this.isIdle) { + this.notificationsService.disconnectFromInactivity(); + } else { + this.notificationsService.reconnectFromActivity(); + } + } + + private async openModal(type: Type, ref: ViewContainerRef) { + if (this.modal != null) { + this.modal.close(); + } + + [this.modal] = await this.modalService.openViewRef(type, ref); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + private showToast(msg: any) { + let message = ""; + + const options: Partial = {}; + + if (typeof msg.text === "string") { + message = msg.text; + } else if (msg.text.length === 1) { + message = msg.text[0]; + } else { + msg.text.forEach( + (t: string) => + (message += "

" + this.sanitizer.sanitize(SecurityContext.HTML, t) + "

") + ); + options.enableHtml = true; + } + if (msg.options != null) { + if (msg.options.trustedHtml === true) { + options.enableHtml = true; + } + if (msg.options.timeout != null && msg.options.timeout > 0) { + options.timeOut = msg.options.timeout; + } + } + + this.toastrService.show(message, msg.title, options, "toast-" + msg.type); + } + + private routeToVault(action: string, cipherType: CipherType) { + if (!this.router.url.includes("vault")) { + this.router.navigate(["/vault"], { + queryParams: { + action: action, + addType: cipherType, + }, + replaceUrl: true, + }); + } + } + + private async reloadProcess(): Promise { + const accounts = this.stateService.accounts.getValue(); + if (accounts != null) { + const keys = Object.keys(accounts); + if (keys.length > 0) { + for (const userId of keys) { + if ((await this.authService.getAuthStatus(userId)) === AuthenticationStatus.Unlocked) { + return; + } + } + } + } + await this.systemService.startProcessReload(); + } + + private async checkForSystemTimeout(timeout: number): Promise { + for (const userId in this.stateService.accounts.getValue()) { + if (userId == null) { + continue; + } + const options = await this.getVaultTimeoutOptions(userId); + if (options[0] === timeout) { + options[1] === "logOut" + ? this.logOut(false, userId) + : await this.vaultTimeoutService.lock(true, userId); + } + } + } + + private async getVaultTimeoutOptions(userId: string): Promise<[number, string]> { + const timeout = await this.stateService.getVaultTimeout({ userId: userId }); + const action = await this.stateService.getVaultTimeoutAction({ userId: userId }); + return [timeout, action]; + } +} diff --git a/apps/desktop/src/app/app.module.ts b/apps/desktop/src/app/app.module.ts new file mode 100644 index 0000000000..9e88eec960 --- /dev/null +++ b/apps/desktop/src/app/app.module.ts @@ -0,0 +1,201 @@ +import "zone.js/dist/zone"; + +import { registerLocaleData } from "@angular/common"; +import localeAf from "@angular/common/locales/af"; +import localeAz from "@angular/common/locales/az"; +import localeBe from "@angular/common/locales/be"; +import localeBg from "@angular/common/locales/bg"; +import localeBn from "@angular/common/locales/bn"; +import localeBs from "@angular/common/locales/bs"; +import localeCa from "@angular/common/locales/ca"; +import localeCs from "@angular/common/locales/cs"; +import localeDa from "@angular/common/locales/da"; +import localeDe from "@angular/common/locales/de"; +import localeEl from "@angular/common/locales/el"; +import localeEnGb from "@angular/common/locales/en-GB"; +import localeEnIn from "@angular/common/locales/en-IN"; +import localeEo from "@angular/common/locales/eo"; +import localeEs from "@angular/common/locales/es"; +import localeEt from "@angular/common/locales/et"; +import localeFa from "@angular/common/locales/fa"; +import localeFi from "@angular/common/locales/fi"; +import localeFil from "@angular/common/locales/fil"; +import localeFr from "@angular/common/locales/fr"; +import localeHe from "@angular/common/locales/he"; +import localeHi from "@angular/common/locales/hi"; +import localeHr from "@angular/common/locales/hr"; +import localeHu from "@angular/common/locales/hu"; +import localeId from "@angular/common/locales/id"; +import localeIt from "@angular/common/locales/it"; +import localeJa from "@angular/common/locales/ja"; +import localeKa from "@angular/common/locales/ka"; +import localeKm from "@angular/common/locales/km"; +import localeKn from "@angular/common/locales/kn"; +import localeKo from "@angular/common/locales/ko"; +import localeLv from "@angular/common/locales/lv"; +import localeMl from "@angular/common/locales/ml"; +import localeNb from "@angular/common/locales/nb"; +import localeNl from "@angular/common/locales/nl"; +import localeNn from "@angular/common/locales/nn"; +import localePl from "@angular/common/locales/pl"; +import localePtBr from "@angular/common/locales/pt"; +import localePtPt from "@angular/common/locales/pt-PT"; +import localeRo from "@angular/common/locales/ro"; +import localeRu from "@angular/common/locales/ru"; +import localeSi from "@angular/common/locales/si"; +import localeSk from "@angular/common/locales/sk"; +import localeSl from "@angular/common/locales/sl"; +import localeSr from "@angular/common/locales/sr"; +import localeMe from "@angular/common/locales/sr-Latn-ME"; +import localeSv from "@angular/common/locales/sv"; +import localeTh from "@angular/common/locales/th"; +import localeTr from "@angular/common/locales/tr"; +import localeUk from "@angular/common/locales/uk"; +import localeVi from "@angular/common/locales/vi"; +import localeZhCn from "@angular/common/locales/zh-Hans"; +import localeZhTw from "@angular/common/locales/zh-Hant"; +import { NgModule } from "@angular/core"; + +import { EnvironmentComponent } from "./accounts/environment.component"; +import { HintComponent } from "./accounts/hint.component"; +import { LockComponent } from "./accounts/lock.component"; +import { LoginComponent } from "./accounts/login.component"; +import { PremiumComponent } from "./accounts/premium.component"; +import { RegisterComponent } from "./accounts/register.component"; +import { RemovePasswordComponent } from "./accounts/remove-password.component"; +import { SetPasswordComponent } from "./accounts/set-password.component"; +import { SettingsComponent } from "./accounts/settings.component"; +import { SsoComponent } from "./accounts/sso.component"; +import { TwoFactorOptionsComponent } from "./accounts/two-factor-options.component"; +import { TwoFactorComponent } from "./accounts/two-factor.component"; +import { UpdateTempPasswordComponent } from "./accounts/update-temp-password.component"; +import { VaultTimeoutInputComponent } from "./accounts/vault-timeout-input.component"; +import { AppRoutingModule } from "./app-routing.module"; +import { AppComponent } from "./app.component"; +import { PasswordRepromptComponent } from "./components/password-reprompt.component"; +import { SetPinComponent } from "./components/set-pin.component"; +import { UserVerificationComponent } from "./components/user-verification.component"; +import { AccountSwitcherComponent } from "./layout/account-switcher.component"; +import { HeaderComponent } from "./layout/header.component"; +import { NavComponent } from "./layout/nav.component"; +import { SearchComponent } from "./layout/search/search.component"; +import { SharedModule } from "./modules/shared.module"; +import { VaultFilterModule } from "./modules/vault-filter/vault-filter.module"; +import { AddEditComponent as SendAddEditComponent } from "./send/add-edit.component"; +import { EffluxDatesComponent as SendEffluxDatesComponent } from "./send/efflux-dates.component"; +import { SendComponent } from "./send/send.component"; +import { AddEditCustomFieldsComponent } from "./vault/add-edit-custom-fields.component"; +import { AddEditComponent } from "./vault/add-edit.component"; +import { AttachmentsComponent } from "./vault/attachments.component"; +import { CiphersComponent } from "./vault/ciphers.component"; +import { CollectionsComponent } from "./vault/collections.component"; +import { ExportComponent } from "./vault/export.component"; +import { FolderAddEditComponent } from "./vault/folder-add-edit.component"; +import { GeneratorComponent } from "./vault/generator.component"; +import { PasswordGeneratorHistoryComponent } from "./vault/password-generator-history.component"; +import { PasswordHistoryComponent } from "./vault/password-history.component"; +import { ShareComponent } from "./vault/share.component"; +import { VaultComponent } from "./vault/vault.component"; +import { ViewCustomFieldsComponent } from "./vault/view-custom-fields.component"; +import { ViewComponent } from "./vault/view.component"; + +registerLocaleData(localeAf, "af"); +registerLocaleData(localeAz, "az"); +registerLocaleData(localeBe, "be"); +registerLocaleData(localeBg, "bg"); +registerLocaleData(localeBn, "bn"); +registerLocaleData(localeBs, "bs"); +registerLocaleData(localeCa, "ca"); +registerLocaleData(localeCs, "cs"); +registerLocaleData(localeDa, "da"); +registerLocaleData(localeDe, "de"); +registerLocaleData(localeEl, "el"); +registerLocaleData(localeEnGb, "en-GB"); +registerLocaleData(localeEnIn, "en-IN"); +registerLocaleData(localeEo, "eo"); +registerLocaleData(localeEs, "es"); +registerLocaleData(localeEt, "et"); +registerLocaleData(localeFa, "fa"); +registerLocaleData(localeFi, "fi"); +registerLocaleData(localeFil, "fil"); +registerLocaleData(localeFr, "fr"); +registerLocaleData(localeHe, "he"); +registerLocaleData(localeHi, "hi"); +registerLocaleData(localeHr, "hr"); +registerLocaleData(localeHu, "hu"); +registerLocaleData(localeId, "id"); +registerLocaleData(localeIt, "it"); +registerLocaleData(localeJa, "ja"); +registerLocaleData(localeKa, "ka"); +registerLocaleData(localeKm, "km"); +registerLocaleData(localeKn, "kn"); +registerLocaleData(localeKo, "ko"); +registerLocaleData(localeLv, "lv"); +registerLocaleData(localeMe, "me"); +registerLocaleData(localeMl, "ml"); +registerLocaleData(localeNb, "nb"); +registerLocaleData(localeNl, "nl"); +registerLocaleData(localeNn, "nn"); +registerLocaleData(localePl, "pl"); +registerLocaleData(localePtBr, "pt-BR"); +registerLocaleData(localePtPt, "pt-PT"); +registerLocaleData(localeRo, "ro"); +registerLocaleData(localeRu, "ru"); +registerLocaleData(localeSi, "si"); +registerLocaleData(localeSk, "sk"); +registerLocaleData(localeSl, "sl"); +registerLocaleData(localeSr, "sr"); +registerLocaleData(localeSv, "sv"); +registerLocaleData(localeTh, "th"); +registerLocaleData(localeTr, "tr"); +registerLocaleData(localeUk, "uk"); +registerLocaleData(localeVi, "vi"); +registerLocaleData(localeZhCn, "zh-CN"); +registerLocaleData(localeZhTw, "zh-TW"); + +@NgModule({ + imports: [SharedModule, AppRoutingModule, VaultFilterModule], + declarations: [ + AccountSwitcherComponent, + AddEditComponent, + AddEditCustomFieldsComponent, + AppComponent, + AttachmentsComponent, + CiphersComponent, + CollectionsComponent, + EnvironmentComponent, + ExportComponent, + FolderAddEditComponent, + HeaderComponent, + HintComponent, + LockComponent, + LoginComponent, + NavComponent, + GeneratorComponent, + PasswordGeneratorHistoryComponent, + PasswordHistoryComponent, + PasswordRepromptComponent, + PremiumComponent, + RegisterComponent, + RemovePasswordComponent, + SearchComponent, + SendAddEditComponent, + SendComponent, + SendEffluxDatesComponent, + SetPasswordComponent, + SetPinComponent, + SettingsComponent, + ShareComponent, + SsoComponent, + TwoFactorComponent, + TwoFactorOptionsComponent, + UpdateTempPasswordComponent, + UserVerificationComponent, + VaultComponent, + VaultTimeoutInputComponent, + ViewComponent, + ViewCustomFieldsComponent, + ], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/apps/desktop/src/app/components/password-reprompt.component.html b/apps/desktop/src/app/components/password-reprompt.component.html new file mode 100644 index 0000000000..07d9abd8fc --- /dev/null +++ b/apps/desktop/src/app/components/password-reprompt.component.html @@ -0,0 +1,54 @@ + diff --git a/apps/desktop/src/app/components/password-reprompt.component.ts b/apps/desktop/src/app/components/password-reprompt.component.ts new file mode 100644 index 0000000000..442a0ab5ee --- /dev/null +++ b/apps/desktop/src/app/components/password-reprompt.component.ts @@ -0,0 +1,8 @@ +import { Component } from "@angular/core"; + +import { PasswordRepromptComponent as BasePasswordRepromptComponent } from "jslib-angular/components/password-reprompt.component"; + +@Component({ + templateUrl: "password-reprompt.component.html", +}) +export class PasswordRepromptComponent extends BasePasswordRepromptComponent {} diff --git a/apps/desktop/src/app/components/set-pin.component.html b/apps/desktop/src/app/components/set-pin.component.html new file mode 100644 index 0000000000..5bd50bbc35 --- /dev/null +++ b/apps/desktop/src/app/components/set-pin.component.html @@ -0,0 +1,65 @@ + diff --git a/apps/desktop/src/app/components/set-pin.component.ts b/apps/desktop/src/app/components/set-pin.component.ts new file mode 100644 index 0000000000..4497f7e774 --- /dev/null +++ b/apps/desktop/src/app/components/set-pin.component.ts @@ -0,0 +1,8 @@ +import { Component } from "@angular/core"; + +import { SetPinComponent as BaseSetPinComponent } from "jslib-angular/components/set-pin.component"; + +@Component({ + templateUrl: "set-pin.component.html", +}) +export class SetPinComponent extends BaseSetPinComponent {} diff --git a/apps/desktop/src/app/components/user-verification.component.html b/apps/desktop/src/app/components/user-verification.component.html new file mode 100644 index 0000000000..2fd78bb907 --- /dev/null +++ b/apps/desktop/src/app/components/user-verification.component.html @@ -0,0 +1,46 @@ + +
+ + +
+
+ +
+ + + + + {{ "codeSent" | i18n }} + +
+ +
+ + +
+
diff --git a/apps/desktop/src/app/components/user-verification.component.ts b/apps/desktop/src/app/components/user-verification.component.ts new file mode 100644 index 0000000000..dc12c94a78 --- /dev/null +++ b/apps/desktop/src/app/components/user-verification.component.ts @@ -0,0 +1,23 @@ +import { animate, style, transition, trigger } from "@angular/animations"; +import { Component } from "@angular/core"; +import { NG_VALUE_ACCESSOR } from "@angular/forms"; + +import { UserVerificationComponent as BaseComponent } from "jslib-angular/components/user-verification.component"; + +@Component({ + selector: "app-user-verification", + templateUrl: "user-verification.component.html", + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: UserVerificationComponent, + }, + ], + animations: [ + trigger("sent", [ + transition(":enter", [style({ opacity: 0 }), animate("100ms", style({ opacity: 1 }))]), + ]), + ], +}) +export class UserVerificationComponent extends BaseComponent {} diff --git a/apps/desktop/src/app/guards/login.guard.ts b/apps/desktop/src/app/guards/login.guard.ts new file mode 100644 index 0000000000..dcf8bbc3b9 --- /dev/null +++ b/apps/desktop/src/app/guards/login.guard.ts @@ -0,0 +1,28 @@ +import { Injectable } from "@angular/core"; +import { CanActivate } from "@angular/router"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +const maxAllowedAccounts = 5; + +@Injectable() +export class LoginGuard implements CanActivate { + protected homepage = "vault"; + constructor( + private stateService: StateService, + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService + ) {} + + async canActivate() { + const accounts = this.stateService.accounts.getValue(); + if (accounts != null && Object.keys(accounts).length >= maxAllowedAccounts) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("accountLimitReached")); + return false; + } + + return true; + } +} diff --git a/apps/desktop/src/app/layout/account-switcher.component.html b/apps/desktop/src/app/layout/account-switcher.component.html new file mode 100644 index 0000000000..0d52b719c9 --- /dev/null +++ b/apps/desktop/src/app/layout/account-switcher.component.html @@ -0,0 +1,100 @@ + + + + + diff --git a/apps/desktop/src/app/layout/account-switcher.component.ts b/apps/desktop/src/app/layout/account-switcher.component.ts new file mode 100644 index 0000000000..1958bed73c --- /dev/null +++ b/apps/desktop/src/app/layout/account-switcher.component.ts @@ -0,0 +1,135 @@ +import { animate, state, style, transition, trigger } from "@angular/animations"; +import { ConnectedPosition } from "@angular/cdk/overlay"; +import { Component, OnInit } from "@angular/core"; + +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; +import { Utils } from "jslib-common/misc/utils"; +import { Account } from "jslib-common/models/domain/account"; + +export class SwitcherAccount extends Account { + get serverUrl() { + return this.removeWebProtocolFromString( + this.settings?.environmentUrls?.base ?? + this.settings?.environmentUrls.api ?? + "https://bitwarden.com" + ); + } + + private removeWebProtocolFromString(urlString: string) { + const regex = /http(s)?(:)?(\/\/)?|(\/\/)?(www\.)?/g; + return urlString.replace(regex, ""); + } +} + +@Component({ + selector: "app-account-switcher", + templateUrl: "account-switcher.component.html", + animations: [ + trigger("transformPanel", [ + state( + "void", + style({ + opacity: 0, + }) + ), + transition( + "void => open", + animate( + "100ms linear", + style({ + opacity: 1, + }) + ) + ), + transition("* => void", animate("100ms linear", style({ opacity: 0 }))), + ]), + ], +}) +export class AccountSwitcherComponent implements OnInit { + isOpen = false; + accounts: { [userId: string]: SwitcherAccount } = {}; + activeAccountEmail: string; + serverUrl: string; + authStatus = AuthenticationStatus; + overlayPostition: ConnectedPosition[] = [ + { + originX: "end", + originY: "bottom", + overlayX: "end", + overlayY: "top", + }, + ]; + + get showSwitcher() { + const userIsInAVault = !Utils.isNullOrWhitespace(this.activeAccountEmail); + const userIsAddingAnAdditionalAccount = Object.keys(this.accounts).length > 0; + return userIsInAVault || userIsAddingAnAdditionalAccount; + } + + get numberOfAccounts() { + if (this.accounts == null) { + this.isOpen = false; + return 0; + } + return Object.keys(this.accounts).length; + } + + constructor( + private stateService: StateService, + private authService: AuthService, + private messagingService: MessagingService + ) {} + + async ngOnInit(): Promise { + this.stateService.accounts.subscribe(async (accounts: { [userId: string]: Account }) => { + for (const userId in accounts) { + accounts[userId].profile.authenticationStatus = await this.authService.getAuthStatus( + userId + ); + } + + this.accounts = await this.createSwitcherAccounts(accounts); + this.activeAccountEmail = await this.stateService.getEmail(); + }); + } + + toggle() { + this.isOpen = !this.isOpen; + } + + close() { + this.isOpen = false; + } + + async switch(userId: string) { + this.close(); + + this.messagingService.send("switchAccount", { userId: userId }); + } + + async addAccount() { + this.close(); + await this.stateService.setActiveUser(null); + } + + private async createSwitcherAccounts(baseAccounts: { + [userId: string]: Account; + }): Promise<{ [userId: string]: SwitcherAccount }> { + const switcherAccounts: { [userId: string]: SwitcherAccount } = {}; + for (const userId in baseAccounts) { + if (userId == null || userId === (await this.stateService.getUserId())) { + continue; + } + + // environmentUrls are stored on disk and must be retrieved seperatly from the in memory state offered from subscribing to accounts + baseAccounts[userId].settings.environmentUrls = await this.stateService.getEnvironmentUrls({ + userId: userId, + }); + switcherAccounts[userId] = new SwitcherAccount(baseAccounts[userId]); + } + return switcherAccounts; + } +} diff --git a/apps/desktop/src/app/layout/header.component.html b/apps/desktop/src/app/layout/header.component.html new file mode 100644 index 0000000000..53ce02fb68 --- /dev/null +++ b/apps/desktop/src/app/layout/header.component.html @@ -0,0 +1,4 @@ +
+ + +
diff --git a/apps/desktop/src/app/layout/header.component.ts b/apps/desktop/src/app/layout/header.component.ts new file mode 100644 index 0000000000..1cf697ad4e --- /dev/null +++ b/apps/desktop/src/app/layout/header.component.ts @@ -0,0 +1,7 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "app-header", + templateUrl: "header.component.html", +}) +export class HeaderComponent {} diff --git a/apps/desktop/src/app/layout/nav.component.html b/apps/desktop/src/app/layout/nav.component.html new file mode 100644 index 0000000000..c9b6358481 --- /dev/null +++ b/apps/desktop/src/app/layout/nav.component.html @@ -0,0 +1,13 @@ + + + diff --git a/apps/desktop/src/app/layout/nav.component.ts b/apps/desktop/src/app/layout/nav.component.ts new file mode 100644 index 0000000000..9cbb6172f5 --- /dev/null +++ b/apps/desktop/src/app/layout/nav.component.ts @@ -0,0 +1,24 @@ +import { Component } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +@Component({ + selector: "app-nav", + templateUrl: "nav.component.html", +}) +export class NavComponent { + items: any[] = [ + { + link: "/vault", + icon: "bwi-lock-f", + label: this.i18nService.translate("myVault"), + }, + { + link: "/send", + icon: "bwi-send-f", + label: "Send", + }, + ]; + + constructor(private i18nService: I18nService) {} +} diff --git a/apps/desktop/src/app/layout/search/search-bar.service.ts b/apps/desktop/src/app/layout/search/search-bar.service.ts new file mode 100644 index 0000000000..340ee3a698 --- /dev/null +++ b/apps/desktop/src/app/layout/search/search-bar.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from "@angular/core"; +import { BehaviorSubject } from "rxjs"; + +export type SearchBarState = { + enabled: boolean; + placeholderText: string; +}; + +@Injectable() +export class SearchBarService { + searchText = new BehaviorSubject(null); + + private _state = { + enabled: false, + placeholderText: "", + }; + + // tslint:disable-next-line:member-ordering + state = new BehaviorSubject(this._state); + + setEnabled(enabled: boolean) { + this._state.enabled = enabled; + this.updateState(); + } + + setPlaceholderText(placeholderText: string) { + this._state.placeholderText = placeholderText; + this.updateState(); + } + + setSearchText(value: string) { + this.searchText.next(value); + } + + private updateState() { + this.state.next(this._state); + } +} diff --git a/apps/desktop/src/app/layout/search/search.component.html b/apps/desktop/src/app/layout/search/search.component.html new file mode 100644 index 0000000000..515385c207 --- /dev/null +++ b/apps/desktop/src/app/layout/search/search.component.html @@ -0,0 +1,11 @@ + diff --git a/apps/desktop/src/app/layout/search/search.component.ts b/apps/desktop/src/app/layout/search/search.component.ts new file mode 100644 index 0000000000..9e2bab6565 --- /dev/null +++ b/apps/desktop/src/app/layout/search/search.component.ts @@ -0,0 +1,36 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { FormControl } from "@angular/forms"; + +import { StateService } from "jslib-common/abstractions/state.service"; + +import { SearchBarService, SearchBarState } from "./search-bar.service"; + +@Component({ + selector: "app-search", + templateUrl: "search.component.html", +}) +export class SearchComponent implements OnInit, OnDestroy { + state: SearchBarState; + searchText: FormControl = new FormControl(null); + + constructor(private searchBarService: SearchBarService, private stateService: StateService) { + this.searchBarService.state.subscribe((state) => { + this.state = state; + }); + + this.searchText.valueChanges.subscribe((value) => { + this.searchBarService.setSearchText(value); + }); + } + + ngOnInit() { + this.stateService.activeAccount.subscribe((value) => { + this.searchBarService.setSearchText(""); + this.searchText.patchValue(""); + }); + } + + ngOnDestroy() { + this.stateService.activeAccount.unsubscribe(); + } +} diff --git a/apps/desktop/src/app/main.ts b/apps/desktop/src/app/main.ts new file mode 100644 index 0000000000..c5ae1b187d --- /dev/null +++ b/apps/desktop/src/app/main.ts @@ -0,0 +1,19 @@ +import { enableProdMode } from "@angular/core"; +import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; + +import { isDev } from "jslib-electron/utils"; + +// tslint:disable-next-line +require("../scss/styles.scss"); + +import { AppModule } from "./app.module"; + +if (!isDev()) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule, { preserveWhitespaces: true }); + +// Disable drag and drop to prevent malicious links from executing in the context of the app +document.addEventListener("dragover", (event) => event.preventDefault()); +document.addEventListener("drop", (event) => event.preventDefault()); diff --git a/apps/desktop/src/app/modules/shared.module.ts b/apps/desktop/src/app/modules/shared.module.ts new file mode 100644 index 0000000000..5108e9b281 --- /dev/null +++ b/apps/desktop/src/app/modules/shared.module.ts @@ -0,0 +1,43 @@ +import { A11yModule } from "@angular/cdk/a11y"; +import { DragDropModule } from "@angular/cdk/drag-drop"; +import { OverlayModule } from "@angular/cdk/overlay"; +import { ScrollingModule } from "@angular/cdk/scrolling"; +import { DatePipe } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; +import { BrowserModule } from "@angular/platform-browser"; +import { BrowserAnimationsModule } from "@angular/platform-browser/animations"; + +import { JslibModule } from "jslib-angular/jslib.module"; + +import { ServicesModule } from "../services/services.module"; + +@NgModule({ + imports: [ + A11yModule, + BrowserAnimationsModule, + BrowserModule, + DragDropModule, + FormsModule, + JslibModule, + OverlayModule, + ReactiveFormsModule, + ScrollingModule, + ServicesModule, + ], + exports: [ + A11yModule, + BrowserAnimationsModule, + BrowserModule, + DatePipe, + DragDropModule, + FormsModule, + JslibModule, + OverlayModule, + ReactiveFormsModule, + ScrollingModule, + ServicesModule, + ], + providers: [DatePipe], +}) +export class SharedModule {} diff --git a/apps/desktop/src/app/modules/vault-filter/components/collection-filter.component.html b/apps/desktop/src/app/modules/vault-filter/components/collection-filter.component.html new file mode 100644 index 0000000000..aa0c1887fe --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/collection-filter.component.html @@ -0,0 +1,76 @@ + +
+ +

 {{ collectionsGrouping.name | i18n }}

+
+
    + +
  • + + + + +
      + + +
    +
  • +
    + + +
+
diff --git a/apps/desktop/src/app/modules/vault-filter/components/collection-filter.component.ts b/apps/desktop/src/app/modules/vault-filter/components/collection-filter.component.ts new file mode 100644 index 0000000000..e08c724a5a --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/collection-filter.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +import { CollectionFilterComponent as BaseCollectionFilterComponent } from "jslib-angular/modules/vault-filter/components/collection-filter.component"; + +@Component({ + selector: "app-collection-filter", + templateUrl: "collection-filter.component.html", +}) +export class CollectionFilterComponent extends BaseCollectionFilterComponent {} diff --git a/apps/desktop/src/app/modules/vault-filter/components/folder-filter.component.html b/apps/desktop/src/app/modules/vault-filter/components/folder-filter.component.html new file mode 100644 index 0000000000..6c91f89d5f --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/folder-filter.component.html @@ -0,0 +1,84 @@ + +
+ +

 {{ foldersGrouping.name | i18n }}

+ +
+
    + +
  • + + + + + +
      + + +
    +
  • +
    + +
+
diff --git a/apps/desktop/src/app/modules/vault-filter/components/folder-filter.component.ts b/apps/desktop/src/app/modules/vault-filter/components/folder-filter.component.ts new file mode 100644 index 0000000000..6205239f77 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/folder-filter.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +import { FolderFilterComponent as BaseFolderFilterComponent } from "jslib-angular/modules/vault-filter/components/folder-filter.component"; + +@Component({ + selector: "app-folder-filter", + templateUrl: "folder-filter.component.html", +}) +export class FolderFilterComponent extends BaseFolderFilterComponent {} diff --git a/apps/desktop/src/app/modules/vault-filter/components/organization-filter.component.html b/apps/desktop/src/app/modules/vault-filter/components/organization-filter.component.html new file mode 100644 index 0000000000..cc62341758 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/organization-filter.component.html @@ -0,0 +1,102 @@ + + + +
+ + +
+
    +
  • + + + +
  • +
+
+ +
+ + +
+
    +
  • + + + +
  • +
  • + + + +
  • +
+
+
+
+
diff --git a/apps/desktop/src/app/modules/vault-filter/components/organization-filter.component.ts b/apps/desktop/src/app/modules/vault-filter/components/organization-filter.component.ts new file mode 100644 index 0000000000..8703102cf6 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/organization-filter.component.ts @@ -0,0 +1,19 @@ +import { Component } from "@angular/core"; + +import { OrganizationFilterComponent as BaseOrganizationFilterComponent } from "jslib-angular/modules/vault-filter/components/organization-filter.component"; +import { DisplayMode } from "jslib-angular/modules/vault-filter/models/display-mode"; + +@Component({ + selector: "app-organization-filter", + templateUrl: "organization-filter.component.html", +}) +export class OrganizationFilterComponent extends BaseOrganizationFilterComponent { + get show() { + const hiddenDisplayModes: DisplayMode[] = ["singleOrganizationAndPersonalOwnershipPolicies"]; + return ( + !this.hide && + this.organizations.length > 0 && + hiddenDisplayModes.indexOf(this.displayMode) === -1 + ); + } +} diff --git a/apps/desktop/src/app/modules/vault-filter/components/status-filter.component.html b/apps/desktop/src/app/modules/vault-filter/components/status-filter.component.html new file mode 100644 index 0000000000..865f24a759 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/status-filter.component.html @@ -0,0 +1,46 @@ + +

{{ "filters" | i18n }}

+
    +
  • + + + +
  • +
  • + + + +
  • +
  • + + + +
  • +
+
diff --git a/apps/desktop/src/app/modules/vault-filter/components/status-filter.component.ts b/apps/desktop/src/app/modules/vault-filter/components/status-filter.component.ts new file mode 100644 index 0000000000..c7c38aa6aa --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/status-filter.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +import { StatusFilterComponent as BaseStatusFilterComponent } from "jslib-angular/modules/vault-filter/components/status-filter.component"; + +@Component({ + selector: "app-status-filter", + templateUrl: "status-filter.component.html", +}) +export class StatusFilterComponent extends BaseStatusFilterComponent {} diff --git a/apps/desktop/src/app/modules/vault-filter/components/type-filter.component.html b/apps/desktop/src/app/modules/vault-filter/components/type-filter.component.html new file mode 100644 index 0000000000..19a06646e4 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/type-filter.component.html @@ -0,0 +1,76 @@ +
+ +

 {{ typesNode.name | i18n }}

+
+
    +
  • + + + +
  • +
  • + + + +
  • +
  • + + + +
  • +
  • + + + +
  • +
diff --git a/apps/desktop/src/app/modules/vault-filter/components/type-filter.component.ts b/apps/desktop/src/app/modules/vault-filter/components/type-filter.component.ts new file mode 100644 index 0000000000..794fc49787 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/components/type-filter.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +import { TypeFilterComponent as BaseTypeFilterComponent } from "jslib-angular/modules/vault-filter/components/type-filter.component"; + +@Component({ + selector: "app-type-filter", + templateUrl: "type-filter.component.html", +}) +export class TypeFilterComponent extends BaseTypeFilterComponent {} diff --git a/apps/desktop/src/app/modules/vault-filter/vault-filter.component.html b/apps/desktop/src/app/modules/vault-filter/vault-filter.component.html new file mode 100644 index 0000000000..62158fd332 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/vault-filter.component.html @@ -0,0 +1,50 @@ +
+ +
+ + + + + + + diff --git a/apps/desktop/src/app/modules/vault-filter/vault-filter.component.ts b/apps/desktop/src/app/modules/vault-filter/vault-filter.component.ts new file mode 100644 index 0000000000..b8a4a3605b --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/vault-filter.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +import { VaultFilterComponent as BaseVaultFilterComponent } from "jslib-angular/modules/vault-filter/vault-filter.component"; + +@Component({ + selector: "app-vault-filter", + templateUrl: "vault-filter.component.html", +}) +export class VaultFilterComponent extends BaseVaultFilterComponent {} diff --git a/apps/desktop/src/app/modules/vault-filter/vault-filter.module.ts b/apps/desktop/src/app/modules/vault-filter/vault-filter.module.ts new file mode 100644 index 0000000000..9aad2bba52 --- /dev/null +++ b/apps/desktop/src/app/modules/vault-filter/vault-filter.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from "@angular/core"; +import { BrowserModule } from "@angular/platform-browser"; + +import { JslibModule } from "jslib-angular/jslib.module"; +import { VaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service"; + +import { CollectionFilterComponent } from "./components/collection-filter.component"; +import { FolderFilterComponent } from "./components/folder-filter.component"; +import { OrganizationFilterComponent } from "./components/organization-filter.component"; +import { StatusFilterComponent } from "./components/status-filter.component"; +import { TypeFilterComponent } from "./components/type-filter.component"; +import { VaultFilterComponent } from "./vault-filter.component"; + +@NgModule({ + imports: [BrowserModule, JslibModule], + declarations: [ + VaultFilterComponent, + CollectionFilterComponent, + FolderFilterComponent, + OrganizationFilterComponent, + StatusFilterComponent, + TypeFilterComponent, + ], + exports: [VaultFilterComponent], + providers: [VaultFilterService], +}) +export class VaultFilterModule {} diff --git a/apps/desktop/src/app/send/add-edit.component.html b/apps/desktop/src/app/send/add-edit.component.html new file mode 100644 index 0000000000..855cd9ca64 --- /dev/null +++ b/apps/desktop/src/app/send/add-edit.component.html @@ -0,0 +1,292 @@ +
+
+
+
+ + {{ "sendDisabledWarning" | i18n }} + + + {{ "sendOptionsPolicyInEffect" | i18n }} + +
+
+
+ {{ title }} +
+
+
+ + +
+
+ +
+ + +
+
+
+ + +
+
+ +
{{ send.file.fileName }} ({{ send.file.sizeName }})
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+
+
+ +
+
+
+ + +
+
+
+ + +
+
+ + +
+
+
+
+
+ + +
+
+ +
+
+
+ +
+
+
+ {{ "notes" | i18n }} +
+
+
+ +
+
+ +
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ {{ "share" | i18n }} +
+
+
+ + +
+
+ + +
+
+
+
+
+ +
diff --git a/apps/desktop/src/app/send/add-edit.component.ts b/apps/desktop/src/app/send/add-edit.component.ts new file mode 100644 index 0000000000..a3e20dc874 --- /dev/null +++ b/apps/desktop/src/app/send/add-edit.component.ts @@ -0,0 +1,62 @@ +import { DatePipe } from "@angular/common"; +import { Component } from "@angular/core"; + +import { AddEditComponent as BaseAddEditComponent } from "jslib-angular/components/send/add-edit.component"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Component({ + selector: "app-send-add-edit", + templateUrl: "add-edit.component.html", +}) +export class AddEditComponent extends BaseAddEditComponent { + constructor( + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + environmentService: EnvironmentService, + datePipe: DatePipe, + sendService: SendService, + stateService: StateService, + messagingService: MessagingService, + policyService: PolicyService, + logService: LogService + ) { + super( + i18nService, + platformUtilsService, + environmentService, + datePipe, + sendService, + messagingService, + policyService, + logService, + stateService + ); + } + + async refresh() { + this.password = null; + const send = await this.loadSend(); + this.send = await send.decrypt(); + this.hasPassword = this.send.password != null && this.send.password.trim() !== ""; + } + + cancel() { + this.onCancelled.emit(this.send); + } + + async copyLinkToClipboard(link: string) { + super.copyLinkToClipboard(link); + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("valueCopied", this.i18nService.t("sendLink")) + ); + } +} diff --git a/apps/desktop/src/app/send/efflux-dates.component.html b/apps/desktop/src/app/send/efflux-dates.component.html new file mode 100644 index 0000000000..e0fc766b12 --- /dev/null +++ b/apps/desktop/src/app/send/efflux-dates.component.html @@ -0,0 +1,55 @@ + +
+
+
+ + + {{ "deletionDateDesc" | i18n }} +
+
+ + + {{ "deletionDateDesc" | i18n }} +
+
+ + + {{ "expirationDateDesc" | i18n }} +
+
+ + + {{ "expirationDateDesc" | i18n }} +
+
+
+
diff --git a/apps/desktop/src/app/send/efflux-dates.component.ts b/apps/desktop/src/app/send/efflux-dates.component.ts new file mode 100644 index 0000000000..db5281da79 --- /dev/null +++ b/apps/desktop/src/app/send/efflux-dates.component.ts @@ -0,0 +1,38 @@ +import { DatePipe } from "@angular/common"; +import { Component, OnChanges } from "@angular/core"; +import { ControlContainer, NgForm } from "@angular/forms"; + +import { EffluxDatesComponent as BaseEffluxDatesComponent } from "jslib-angular/components/send/efflux-dates.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-send-efflux-dates", + templateUrl: "efflux-dates.component.html", + viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], +}) +export class EffluxDatesComponent extends BaseEffluxDatesComponent implements OnChanges { + constructor( + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected datePipe: DatePipe + ) { + super(i18nService, platformUtilsService, datePipe); + } + + // We reuse the same form on desktop and just swap content, so need to watch these to maintin proper values. + ngOnChanges() { + this.selectedExpirationDatePreset.setValue(0); + this.selectedDeletionDatePreset.setValue(0); + this.defaultDeletionDateTime.setValue( + this.datePipe.transform(new Date(this.initialDeletionDate), "yyyy-MM-ddTHH:mm") + ); + if (this.initialExpirationDate) { + this.defaultExpirationDateTime.setValue( + this.datePipe.transform(new Date(this.initialExpirationDate), "yyyy-MM-ddTHH:mm") + ); + } else { + this.defaultExpirationDateTime.setValue(null); + } + } +} diff --git a/apps/desktop/src/app/send/send.component.html b/apps/desktop/src/app/send/send.component.html new file mode 100644 index 0000000000..e4d5dc0d69 --- /dev/null +++ b/apps/desktop/src/app/send/send.component.html @@ -0,0 +1,156 @@ +
+
+
+

{{ "filters" | i18n }}

+
+
    +
  • + + + +
  • +
+
+
+
+

{{ "types" | i18n }}

+
+
    +
  • + + + +
  • +
  • + + + +
  • +
+
+
+ +
+
+
+
+ +
+
+ + + +

{{ "noItemsInList" | i18n }}

+
+
+ +
+
+ + +
diff --git a/apps/desktop/src/app/send/send.component.ts b/apps/desktop/src/app/send/send.component.ts new file mode 100644 index 0000000000..b2ab75dd3a --- /dev/null +++ b/apps/desktop/src/app/send/send.component.ts @@ -0,0 +1,144 @@ +import { Component, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core"; + +import { SendComponent as BaseSendComponent } from "jslib-angular/components/send/send.component"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { SendView } from "jslib-common/models/view/sendView"; +import { invokeMenu, RendererMenuItem } from "jslib-electron/utils"; + +import { SearchBarService } from "../layout/search/search-bar.service"; + +import { AddEditComponent } from "./add-edit.component"; + +enum Action { + None = "", + Add = "add", + Edit = "edit", +} + +const BroadcasterSubscriptionId = "SendComponent"; + +@Component({ + selector: "app-send", + templateUrl: "send.component.html", +}) +export class SendComponent extends BaseSendComponent implements OnInit, OnDestroy { + @ViewChild(AddEditComponent) addEditComponent: AddEditComponent; + + sendId: string; + action: Action = Action.None; + + constructor( + sendService: SendService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + environmentService: EnvironmentService, + private broadcasterService: BroadcasterService, + ngZone: NgZone, + searchService: SearchService, + policyService: PolicyService, + private searchBarService: SearchBarService, + logService: LogService + ) { + super( + sendService, + i18nService, + platformUtilsService, + environmentService, + ngZone, + searchService, + policyService, + logService + ); + this.searchBarService.searchText.subscribe((searchText) => { + this.searchText = searchText; + this.searchTextChanged(); + }); + } + + async ngOnInit() { + this.searchBarService.setEnabled(true); + this.searchBarService.setPlaceholderText(this.i18nService.t("searchSends")); + + super.ngOnInit(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + await this.load(); + break; + } + }); + }); + await this.load(); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + this.searchBarService.setEnabled(false); + } + + addSend() { + this.action = Action.Add; + if (this.addEditComponent != null) { + this.addEditComponent.sendId = null; + this.addEditComponent.send = null; + this.addEditComponent.load(); + } + } + + cancel(s: SendView) { + this.action = Action.None; + this.sendId = null; + } + + async deletedSend(s: SendView) { + await this.refresh(); + this.action = Action.None; + this.sendId = null; + } + + async savedSend(s: SendView) { + await this.refresh(); + this.selectSend(s.id); + } + + async selectSend(sendId: string) { + if (sendId === this.sendId && this.action === Action.Edit) { + return; + } + this.action = Action.Edit; + this.sendId = sendId; + if (this.addEditComponent != null) { + this.addEditComponent.sendId = sendId; + await this.addEditComponent.refresh(); + } + } + + get selectedSendType() { + return this.sends.find((s) => s.id === this.sendId)?.type; + } + + viewSendMenu(send: SendView) { + const menu: RendererMenuItem[] = []; + menu.push({ + label: this.i18nService.t("copyLink"), + click: () => this.copy(send), + }); + menu.push({ + label: this.i18nService.t("delete"), + click: async () => { + await this.delete(send); + await this.deletedSend(send); + }, + }); + + invokeMenu(menu); + } +} diff --git a/apps/desktop/src/app/services/init.service.ts b/apps/desktop/src/app/services/init.service.ts new file mode 100644 index 0000000000..3bc3d49aa9 --- /dev/null +++ b/apps/desktop/src/app/services/init.service.ts @@ -0,0 +1,81 @@ +import { Inject, Injectable } from "@angular/core"; + +import { WINDOW } from "jslib-angular/services/jslib-services.module"; +import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service"; +import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service"; +import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service"; +import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; +import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; +import { ThemeType } from "jslib-common/enums/themeType"; +import { ContainerService } from "jslib-common/services/container.service"; +import { EventService } from "jslib-common/services/event.service"; +import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; + +import { I18nService } from "../../services/i18n.service"; +import { NativeMessagingService } from "../../services/nativeMessaging.service"; + +@Injectable() +export class InitService { + constructor( + @Inject(WINDOW) private win: Window, + private environmentService: EnvironmentServiceAbstraction, + private syncService: SyncServiceAbstraction, + private vaultTimeoutService: VaultTimeoutServiceAbstraction, + private i18nService: I18nServiceAbstraction, + private eventService: EventServiceAbstraction, + private twoFactorService: TwoFactorServiceAbstraction, + private notificationsService: NotificationsServiceAbstraction, + private platformUtilsService: PlatformUtilsServiceAbstraction, + private stateService: StateServiceAbstraction, + private cryptoService: CryptoServiceAbstraction, + private nativeMessagingService: NativeMessagingService + ) {} + + init() { + return async () => { + this.nativeMessagingService.init(); + await this.stateService.init(); + await this.environmentService.setUrlsFromStorage(); + this.syncService.fullSync(true); + (this.vaultTimeoutService as VaultTimeoutService).init(true); + const locale = await this.stateService.getLocale(); + await (this.i18nService as I18nService).init(locale); + (this.eventService as EventService).init(true); + this.twoFactorService.init(); + setTimeout(() => this.notificationsService.init(), 3000); + const htmlEl = this.win.document.documentElement; + htmlEl.classList.add("os_" + this.platformUtilsService.getDeviceString()); + + const theme = await this.platformUtilsService.getEffectiveTheme(); + htmlEl.classList.add("theme_" + theme); + this.platformUtilsService.onDefaultSystemThemeChange(async (sysTheme) => { + const bwTheme = await this.stateService.getTheme(); + if (bwTheme == null || bwTheme === ThemeType.System) { + htmlEl.classList.remove("theme_" + ThemeType.Light, "theme_" + ThemeType.Dark); + htmlEl.classList.add("theme_" + sysTheme); + } + }); + + let installAction = null; + const installedVersion = await this.stateService.getInstalledVersion(); + const currentVersion = await this.platformUtilsService.getApplicationVersion(); + if (installedVersion == null) { + installAction = "install"; + } else if (installedVersion !== currentVersion) { + installAction = "update"; + } + + if (installAction != null) { + await this.stateService.setInstalledVersion(currentVersion); + } + + const containerService = new ContainerService(this.cryptoService); + containerService.attachToGlobal(this.win); + }; + } +} diff --git a/apps/desktop/src/app/services/services.module.ts b/apps/desktop/src/app/services/services.module.ts new file mode 100644 index 0000000000..e014b165c8 --- /dev/null +++ b/apps/desktop/src/app/services/services.module.ts @@ -0,0 +1,134 @@ +import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core"; + +import { + JslibServicesModule, + SECURE_STORAGE, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + CLIENT_TYPE, + LOCALES_DIRECTORY, + SYSTEM_LANGUAGE, +} from "jslib-angular/services/jslib-services.module"; +import { BroadcasterService as BroadcasterServiceAbstraction } from "jslib-common/abstractions/broadcaster.service"; +import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "jslib-common/abstractions/cryptoFunction.service"; +import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { + LogService, + LogService as LogServiceAbstraction, +} from "jslib-common/abstractions/log.service"; +import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service"; +import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service"; +import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; +import { SystemService as SystemServiceAbstraction } from "jslib-common/abstractions/system.service"; +import { ClientType } from "jslib-common/enums/clientType"; +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { SystemService } from "jslib-common/services/system.service"; +import { ElectronCryptoService } from "jslib-electron/services/electronCrypto.service"; +import { ElectronLogService } from "jslib-electron/services/electronLog.service"; +import { ElectronPlatformUtilsService } from "jslib-electron/services/electronPlatformUtils.service"; +import { ElectronRendererMessagingService } from "jslib-electron/services/electronRendererMessaging.service"; +import { ElectronRendererSecureStorageService } from "jslib-electron/services/electronRendererSecureStorage.service"; +import { ElectronRendererStorageService } from "jslib-electron/services/electronRendererStorage.service"; + +import { Account } from "../../models/account"; +import { I18nService } from "../../services/i18n.service"; +import { NativeMessagingService } from "../../services/nativeMessaging.service"; +import { PasswordRepromptService } from "../../services/passwordReprompt.service"; +import { StateService } from "../../services/state.service"; +import { LoginGuard } from "../guards/login.guard"; +import { SearchBarService } from "../layout/search/search-bar.service"; + +import { InitService } from "./init.service"; + +const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK"); + +@NgModule({ + imports: [JslibServicesModule], + declarations: [], + providers: [ + InitService, + NativeMessagingService, + SearchBarService, + LoginGuard, + { + provide: APP_INITIALIZER, + useFactory: (initService: InitService) => initService.init(), + deps: [InitService], + multi: true, + }, + { + provide: STATE_FACTORY, + useValue: new StateFactory(GlobalState, Account), + }, + { + provide: CLIENT_TYPE, + useValue: ClientType.Desktop, + }, + { + provide: RELOAD_CALLBACK, + useValue: null, + }, + { provide: LogServiceAbstraction, useClass: ElectronLogService, deps: [] }, + { + provide: PlatformUtilsServiceAbstraction, + useClass: ElectronPlatformUtilsService, + deps: [ + I18nServiceAbstraction, + MessagingServiceAbstraction, + CLIENT_TYPE, + StateServiceAbstraction, + ], + }, + { + provide: I18nServiceAbstraction, + useClass: I18nService, + deps: [SYSTEM_LANGUAGE, LOCALES_DIRECTORY], + }, + { + provide: MessagingServiceAbstraction, + useClass: ElectronRendererMessagingService, + deps: [BroadcasterServiceAbstraction], + }, + { provide: StorageServiceAbstraction, useClass: ElectronRendererStorageService }, + { provide: SECURE_STORAGE, useClass: ElectronRendererSecureStorageService }, + { + provide: CryptoServiceAbstraction, + useClass: ElectronCryptoService, + deps: [ + CryptoFunctionServiceAbstraction, + PlatformUtilsServiceAbstraction, + LogServiceAbstraction, + StateServiceAbstraction, + ], + }, + { + provide: SystemServiceAbstraction, + useClass: SystemService, + deps: [ + MessagingServiceAbstraction, + PlatformUtilsServiceAbstraction, + RELOAD_CALLBACK, + StateServiceAbstraction, + ], + }, + { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, + { + provide: StateServiceAbstraction, + useClass: StateService, + deps: [ + StorageServiceAbstraction, + SECURE_STORAGE, + LogService, + StateMigrationServiceAbstraction, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + ], + }, + ], +}) +export class ServicesModule {} diff --git a/apps/desktop/src/app/vault/add-edit-custom-fields.component.html b/apps/desktop/src/app/vault/add-edit-custom-fields.component.html new file mode 100644 index 0000000000..cf4635c34c --- /dev/null +++ b/apps/desktop/src/app/vault/add-edit-custom-fields.component.html @@ -0,0 +1,118 @@ +
+
+ {{ "customFields" | i18n }} +
+
+
+
+ + + +
+ + + + + + + +
+ + +
+ +
+
+ +
+
+
+ +
+ + + +
+
+
diff --git a/apps/desktop/src/app/vault/add-edit-custom-fields.component.ts b/apps/desktop/src/app/vault/add-edit-custom-fields.component.ts new file mode 100644 index 0000000000..5ce773e014 --- /dev/null +++ b/apps/desktop/src/app/vault/add-edit-custom-fields.component.ts @@ -0,0 +1,15 @@ +import { Component } from "@angular/core"; + +import { AddEditCustomFieldsComponent as BaseAddEditCustomFieldsComponent } from "jslib-angular/components/add-edit-custom-fields.component"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +@Component({ + selector: "app-vault-add-edit-custom-fields", + templateUrl: "add-edit-custom-fields.component.html", +}) +export class AddEditCustomFieldsComponent extends BaseAddEditCustomFieldsComponent { + constructor(i18nService: I18nService, eventService: EventService) { + super(i18nService, eventService); + } +} diff --git a/apps/desktop/src/app/vault/add-edit.component.html b/apps/desktop/src/app/vault/add-edit.component.html new file mode 100644 index 0000000000..6f78e0ceba --- /dev/null +++ b/apps/desktop/src/app/vault/add-edit.component.html @@ -0,0 +1,611 @@ +
+
+
+
+ + {{ "personalOwnershipPolicyInEffect" | i18n }} + +
+ {{ title }} +
+
+
+ + +
+
+ + +
+ +
+
+
+ + +
+
+ +
+
+
+
+ + +
+
+ + + +
+
+
+ + +
+
+ +
+
+ + +
+
+
+ + +
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+ +
+
+
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ +
+ +
+ + + + +
+
+ +
+
+
+ +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+ + +
+
+
+
+ +
+
+
+ +
+
+
+ + +
+
+ {{ "ownership" | i18n }} +
+
+
+ + +
+
+
+
+
+ {{ "collections" | i18n }} +
+
+ {{ "noCollectionsInList" | i18n }} +
+
+
+ + +
+
+
+
+
+ +
diff --git a/apps/desktop/src/app/vault/add-edit.component.ts b/apps/desktop/src/app/vault/add-edit.component.ts new file mode 100644 index 0000000000..7205986144 --- /dev/null +++ b/apps/desktop/src/app/vault/add-edit.component.ts @@ -0,0 +1,124 @@ +import { Component, NgZone, OnChanges, OnDestroy, ViewChild } from "@angular/core"; +import { NgForm } from "@angular/forms"; + +import { AddEditComponent as BaseAddEditComponent } from "jslib-angular/components/add-edit.component"; +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +const BroadcasterSubscriptionId = "AddEditComponent"; + +@Component({ + selector: "app-vault-add-edit", + templateUrl: "add-edit.component.html", +}) +export class AddEditComponent extends BaseAddEditComponent implements OnChanges, OnDestroy { + @ViewChild("form") + private form: NgForm; + constructor( + cipherService: CipherService, + folderService: FolderService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + auditService: AuditService, + stateService: StateService, + collectionService: CollectionService, + messagingService: MessagingService, + eventService: EventService, + policyService: PolicyService, + passwordRepromptService: PasswordRepromptService, + private broadcasterService: BroadcasterService, + private ngZone: NgZone, + logService: LogService, + organizationService: OrganizationService + ) { + super( + cipherService, + folderService, + i18nService, + platformUtilsService, + auditService, + stateService, + collectionService, + messagingService, + eventService, + policyService, + logService, + passwordRepromptService, + organizationService + ); + } + + async ngOnInit() { + this.broadcasterService.subscribe(BroadcasterSubscriptionId, async (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case "windowHidden": + this.onWindowHidden(); + break; + default: + } + }); + }); + // We use ngOnChanges for everything else instead. + } + + async ngOnChanges() { + await super.init(); + await this.load(); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async load() { + if ( + document.querySelectorAll("app-vault-add-edit .ng-dirty").length === 0 || + (this.cipher != null && this.cipherId !== this.cipher.id) + ) { + this.cipher = null; + } + super.load(); + } + + onWindowHidden() { + this.showPassword = false; + this.showCardNumber = false; + this.showCardCode = false; + if (this.cipher !== null && this.cipher.hasFields) { + this.cipher.fields.forEach((field) => { + field.showValue = false; + }); + } + } + + allowOwnershipOptions(): boolean { + return ( + (!this.editMode || this.cloneMode) && + this.ownershipOptions && + (this.ownershipOptions.length > 1 || !this.allowPersonal) + ); + } + + markPasswordAsDirty() { + this.form.controls["Login.Password"].markAsDirty(); + } + + openHelpReprompt() { + this.platformUtilsService.launchUri( + "https://bitwarden.com/help/managing-items/#protect-individual-items" + ); + } +} diff --git a/apps/desktop/src/app/vault/attachments.component.html b/apps/desktop/src/app/vault/attachments.component.html new file mode 100644 index 0000000000..5981b2b62b --- /dev/null +++ b/apps/desktop/src/app/vault/attachments.component.html @@ -0,0 +1,78 @@ + diff --git a/apps/desktop/src/app/vault/attachments.component.ts b/apps/desktop/src/app/vault/attachments.component.ts new file mode 100644 index 0000000000..660e0a6f3a --- /dev/null +++ b/apps/desktop/src/app/vault/attachments.component.ts @@ -0,0 +1,37 @@ +import { Component } from "@angular/core"; + +import { AttachmentsComponent as BaseAttachmentsComponent } from "jslib-angular/components/attachments.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Component({ + selector: "app-vault-attachments", + templateUrl: "attachments.component.html", +}) +export class AttachmentsComponent extends BaseAttachmentsComponent { + constructor( + cipherService: CipherService, + i18nService: I18nService, + cryptoService: CryptoService, + platformUtilsService: PlatformUtilsService, + apiService: ApiService, + logService: LogService, + stateService: StateService + ) { + super( + cipherService, + i18nService, + cryptoService, + platformUtilsService, + apiService, + window, + logService, + stateService + ); + } +} diff --git a/apps/desktop/src/app/vault/ciphers.component.html b/apps/desktop/src/app/vault/ciphers.component.html new file mode 100644 index 0000000000..b2482e8f8d --- /dev/null +++ b/apps/desktop/src/app/vault/ciphers.component.html @@ -0,0 +1,67 @@ +
+ +
+ +
+ +
+ +
+
+
+ +

{{ "noItemsInList" | i18n }}

+ +
+ +
+
diff --git a/apps/desktop/src/app/vault/ciphers.component.ts b/apps/desktop/src/app/vault/ciphers.component.ts new file mode 100644 index 0000000000..438ffab817 --- /dev/null +++ b/apps/desktop/src/app/vault/ciphers.component.ts @@ -0,0 +1,26 @@ +import { Component } from "@angular/core"; + +import { CiphersComponent as BaseCiphersComponent } from "jslib-angular/components/ciphers.component"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +import { SearchBarService } from "../layout/search/search-bar.service"; + +@Component({ + selector: "app-vault-ciphers", + templateUrl: "ciphers.component.html", +}) +export class CiphersComponent extends BaseCiphersComponent { + constructor(searchService: SearchService, searchBarService: SearchBarService) { + super(searchService); + + searchBarService.searchText.subscribe((searchText) => { + this.searchText = searchText; + this.search(200); + }); + } + + trackByFn(index: number, c: CipherView) { + return c.id; + } +} diff --git a/apps/desktop/src/app/vault/collections.component.html b/apps/desktop/src/app/vault/collections.component.html new file mode 100644 index 0000000000..acdc5ea0a9 --- /dev/null +++ b/apps/desktop/src/app/vault/collections.component.html @@ -0,0 +1,51 @@ + diff --git a/apps/desktop/src/app/vault/collections.component.ts b/apps/desktop/src/app/vault/collections.component.ts new file mode 100644 index 0000000000..2ae20bd53e --- /dev/null +++ b/apps/desktop/src/app/vault/collections.component.ts @@ -0,0 +1,24 @@ +import { Component } from "@angular/core"; + +import { CollectionsComponent as BaseCollectionsComponent } from "jslib-angular/components/collections.component"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-vault-collections", + templateUrl: "collections.component.html", +}) +export class CollectionsComponent extends BaseCollectionsComponent { + constructor( + cipherService: CipherService, + i18nService: I18nService, + collectionService: CollectionService, + platformUtilsService: PlatformUtilsService, + logService: LogService + ) { + super(collectionService, platformUtilsService, i18nService, cipherService, logService); + } +} diff --git a/apps/desktop/src/app/vault/export.component.html b/apps/desktop/src/app/vault/export.component.html new file mode 100644 index 0000000000..09e21b063d --- /dev/null +++ b/apps/desktop/src/app/vault/export.component.html @@ -0,0 +1,45 @@ + diff --git a/apps/desktop/src/app/vault/export.component.ts b/apps/desktop/src/app/vault/export.component.ts new file mode 100644 index 0000000000..1da90e662a --- /dev/null +++ b/apps/desktop/src/app/vault/export.component.ts @@ -0,0 +1,77 @@ +import * as os from "os"; + +import { Component, OnInit } from "@angular/core"; +import { FormBuilder } from "@angular/forms"; + +import { ExportComponent as BaseExportComponent } from "jslib-angular/components/export.component"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { ExportService } from "jslib-common/abstractions/export.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { UserVerificationService } from "jslib-common/abstractions/userVerification.service"; + +const BroadcasterSubscriptionId = "ExportComponent"; + +@Component({ + selector: "app-export", + templateUrl: "export.component.html", +}) +export class ExportComponent extends BaseExportComponent implements OnInit { + constructor( + cryptoService: CryptoService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + exportService: ExportService, + eventService: EventService, + policyService: PolicyService, + userVerificationService: UserVerificationService, + formBuilder: FormBuilder, + private broadcasterService: BroadcasterService, + logService: LogService + ) { + super( + cryptoService, + i18nService, + platformUtilsService, + exportService, + eventService, + policyService, + window, + logService, + userVerificationService, + formBuilder + ); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async warningDialog() { + if (this.encryptedFormat) { + return await this.platformUtilsService.showDialog( + this.i18nService.t("encExportKeyWarningDesc") + + os.EOL + + os.EOL + + this.i18nService.t("encExportAccountWarningDesc"), + this.i18nService.t("confirmVaultExport"), + this.i18nService.t("exportVault"), + this.i18nService.t("cancel"), + "warning", + true + ); + } else { + return await this.platformUtilsService.showDialog( + this.i18nService.t("exportWarningDesc"), + this.i18nService.t("confirmVaultExport"), + this.i18nService.t("exportVault"), + this.i18nService.t("cancel"), + "warning" + ); + } + } +} diff --git a/apps/desktop/src/app/vault/folder-add-edit.component.html b/apps/desktop/src/app/vault/folder-add-edit.component.html new file mode 100644 index 0000000000..6457b223c0 --- /dev/null +++ b/apps/desktop/src/app/vault/folder-add-edit.component.html @@ -0,0 +1,68 @@ + diff --git a/apps/desktop/src/app/vault/folder-add-edit.component.ts b/apps/desktop/src/app/vault/folder-add-edit.component.ts new file mode 100644 index 0000000000..a65f3f0226 --- /dev/null +++ b/apps/desktop/src/app/vault/folder-add-edit.component.ts @@ -0,0 +1,22 @@ +import { Component } from "@angular/core"; + +import { FolderAddEditComponent as BaseFolderAddEditComponent } from "jslib-angular/components/folder-add-edit.component"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-folder-add-edit", + templateUrl: "folder-add-edit.component.html", +}) +export class FolderAddEditComponent extends BaseFolderAddEditComponent { + constructor( + folderService: FolderService, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + logService: LogService + ) { + super(folderService, i18nService, platformUtilsService, logService); + } +} diff --git a/apps/desktop/src/app/vault/generator.component.html b/apps/desktop/src/app/vault/generator.component.html new file mode 100644 index 0000000000..e1a64ca5d4 --- /dev/null +++ b/apps/desktop/src/app/vault/generator.component.html @@ -0,0 +1,560 @@ + diff --git a/apps/desktop/src/app/vault/generator.component.ts b/apps/desktop/src/app/vault/generator.component.ts new file mode 100644 index 0000000000..471fd971af --- /dev/null +++ b/apps/desktop/src/app/vault/generator.component.ts @@ -0,0 +1,41 @@ +import { Component } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; + +import { GeneratorComponent as BaseGeneratorComponent } from "jslib-angular/components/generator.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { UsernameGenerationService } from "jslib-common/abstractions/usernameGeneration.service"; + +@Component({ + selector: "app-generator", + templateUrl: "generator.component.html", +}) +export class GeneratorComponent extends BaseGeneratorComponent { + constructor( + passwordGenerationService: PasswordGenerationService, + usernameGenerationService: UsernameGenerationService, + stateService: StateService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + route: ActivatedRoute, + logService: LogService + ) { + super( + passwordGenerationService, + usernameGenerationService, + platformUtilsService, + stateService, + i18nService, + logService, + route, + window + ); + } + + usernameTypesLearnMore() { + this.platformUtilsService.launchUri("https://bitwarden.com/help/generator/#username-types"); + } +} diff --git a/apps/desktop/src/app/vault/password-generator-history.component.html b/apps/desktop/src/app/vault/password-generator-history.component.html new file mode 100644 index 0000000000..8bef68a689 --- /dev/null +++ b/apps/desktop/src/app/vault/password-generator-history.component.html @@ -0,0 +1,52 @@ + diff --git a/apps/desktop/src/app/vault/password-generator-history.component.ts b/apps/desktop/src/app/vault/password-generator-history.component.ts new file mode 100644 index 0000000000..d7f344365f --- /dev/null +++ b/apps/desktop/src/app/vault/password-generator-history.component.ts @@ -0,0 +1,20 @@ +import { Component } from "@angular/core"; + +import { PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryComponent } from "jslib-angular/components/password-generator-history.component"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-password-generator-history", + templateUrl: "password-generator-history.component.html", +}) +export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHistoryComponent { + constructor( + passwordGenerationService: PasswordGenerationService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService + ) { + super(passwordGenerationService, platformUtilsService, i18nService, window); + } +} diff --git a/apps/desktop/src/app/vault/password-history.component.html b/apps/desktop/src/app/vault/password-history.component.html new file mode 100644 index 0000000000..633cee14c7 --- /dev/null +++ b/apps/desktop/src/app/vault/password-history.component.html @@ -0,0 +1,40 @@ + diff --git a/apps/desktop/src/app/vault/password-history.component.ts b/apps/desktop/src/app/vault/password-history.component.ts new file mode 100644 index 0000000000..06d5158e92 --- /dev/null +++ b/apps/desktop/src/app/vault/password-history.component.ts @@ -0,0 +1,20 @@ +import { Component } from "@angular/core"; + +import { PasswordHistoryComponent as BasePasswordHistoryComponent } from "jslib-angular/components/password-history.component"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-password-history", + templateUrl: "password-history.component.html", +}) +export class PasswordHistoryComponent extends BasePasswordHistoryComponent { + constructor( + cipherService: CipherService, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService + ) { + super(cipherService, platformUtilsService, i18nService, window); + } +} diff --git a/apps/desktop/src/app/vault/share.component.html b/apps/desktop/src/app/vault/share.component.html new file mode 100644 index 0000000000..0f78ae87e4 --- /dev/null +++ b/apps/desktop/src/app/vault/share.component.html @@ -0,0 +1,78 @@ + diff --git a/apps/desktop/src/app/vault/share.component.ts b/apps/desktop/src/app/vault/share.component.ts new file mode 100644 index 0000000000..ebab6fc81c --- /dev/null +++ b/apps/desktop/src/app/vault/share.component.ts @@ -0,0 +1,33 @@ +import { Component } from "@angular/core"; + +import { ShareComponent as BaseShareComponent } from "jslib-angular/components/share.component"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Component({ + selector: "app-vault-share", + templateUrl: "share.component.html", +}) +export class ShareComponent extends BaseShareComponent { + constructor( + cipherService: CipherService, + i18nService: I18nService, + collectionService: CollectionService, + platformUtilsService: PlatformUtilsService, + logService: LogService, + organizationService: OrganizationService + ) { + super( + collectionService, + platformUtilsService, + i18nService, + cipherService, + logService, + organizationService + ); + } +} diff --git a/apps/desktop/src/app/vault/vault.component.html b/apps/desktop/src/app/vault/vault.component.html new file mode 100644 index 0000000000..bf6773e468 --- /dev/null +++ b/apps/desktop/src/app/vault/vault.component.html @@ -0,0 +1,71 @@ +
+ + + + + + + +
+ + +
+
+ + + + + + diff --git a/apps/desktop/src/app/vault/vault.component.ts b/apps/desktop/src/app/vault/vault.component.ts new file mode 100644 index 0000000000..13059d158e --- /dev/null +++ b/apps/desktop/src/app/vault/vault.component.ts @@ -0,0 +1,784 @@ +import { + ChangeDetectorRef, + Component, + NgZone, + OnDestroy, + OnInit, + ViewChild, + ViewContainerRef, +} from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { ModalRef } from "jslib-angular/components/modal/modal.ref"; +import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model"; +import { ModalService } from "jslib-angular/services/modal.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { EventType } from "jslib-common/enums/eventType"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { FolderView } from "jslib-common/models/view/folderView"; +import { invokeMenu, RendererMenuItem } from "jslib-electron/utils"; + +import { SearchBarService } from "../layout/search/search-bar.service"; +import { VaultFilterComponent } from "../modules/vault-filter/vault-filter.component"; + +import { AddEditComponent } from "./add-edit.component"; +import { AttachmentsComponent } from "./attachments.component"; +import { CiphersComponent } from "./ciphers.component"; +import { CollectionsComponent } from "./collections.component"; +import { FolderAddEditComponent } from "./folder-add-edit.component"; +import { GeneratorComponent } from "./generator.component"; +import { PasswordHistoryComponent } from "./password-history.component"; +import { ShareComponent } from "./share.component"; +import { ViewComponent } from "./view.component"; + +const BroadcasterSubscriptionId = "VaultComponent"; + +@Component({ + selector: "app-vault", + templateUrl: "vault.component.html", +}) +export class VaultComponent implements OnInit, OnDestroy { + @ViewChild(ViewComponent) viewComponent: ViewComponent; + @ViewChild(AddEditComponent) addEditComponent: AddEditComponent; + @ViewChild(CiphersComponent, { static: true }) ciphersComponent: CiphersComponent; + @ViewChild("generator", { read: ViewContainerRef, static: true }) + generatorModalRef: ViewContainerRef; + @ViewChild(VaultFilterComponent, { static: true }) vaultFilterComponent: VaultFilterComponent; + @ViewChild("attachments", { read: ViewContainerRef, static: true }) + attachmentsModalRef: ViewContainerRef; + @ViewChild("passwordHistory", { read: ViewContainerRef, static: true }) + passwordHistoryModalRef: ViewContainerRef; + @ViewChild("share", { read: ViewContainerRef, static: true }) shareModalRef: ViewContainerRef; + @ViewChild("collections", { read: ViewContainerRef, static: true }) + collectionsModalRef: ViewContainerRef; + @ViewChild("folderAddEdit", { read: ViewContainerRef, static: true }) + folderAddEditModalRef: ViewContainerRef; + + action: string; + cipherId: string = null; + favorites = false; + type: CipherType = null; + folderId: string = null; + collectionId: string = null; + organizationId: string = null; + myVaultOnly = false; + addType: CipherType = null; + addOrganizationId: string = null; + addCollectionIds: string[] = null; + showingModal = false; + deleted = false; + userHasPremiumAccess = false; + activeFilter: VaultFilter = new VaultFilter(); + + private modal: ModalRef = null; + + constructor( + private route: ActivatedRoute, + private router: Router, + private i18nService: I18nService, + private modalService: ModalService, + private broadcasterService: BroadcasterService, + private changeDetectorRef: ChangeDetectorRef, + private ngZone: NgZone, + private syncService: SyncService, + private messagingService: MessagingService, + private platformUtilsService: PlatformUtilsService, + private eventService: EventService, + private totpService: TotpService, + private passwordRepromptService: PasswordRepromptService, + private stateService: StateService, + private searchBarService: SearchBarService + ) {} + + async ngOnInit() { + this.userHasPremiumAccess = await this.stateService.getCanAccessPremium(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(async () => { + let detectChanges = true; + + switch (message.command) { + case "newLogin": + await this.addCipher(CipherType.Login); + break; + case "newCard": + await this.addCipher(CipherType.Card); + break; + case "newIdentity": + await this.addCipher(CipherType.Identity); + break; + case "newSecureNote": + await this.addCipher(CipherType.SecureNote); + break; + case "focusSearch": + (document.querySelector("#search") as HTMLInputElement).select(); + detectChanges = false; + break; + case "openGenerator": + await this.openGenerator(false); + break; + case "syncCompleted": + await this.ciphersComponent.reload(this.buildFilter()); + await this.vaultFilterComponent.reloadCollectionsAndFolders(this.activeFilter); + await this.vaultFilterComponent.reloadOrganizations(); + break; + case "refreshCiphers": + this.ciphersComponent.refresh(); + break; + case "modalShown": + this.showingModal = true; + break; + case "modalClosed": + this.showingModal = false; + break; + case "copyUsername": { + const uComponent = + this.addEditComponent == null ? this.viewComponent : this.addEditComponent; + const uCipher = uComponent != null ? uComponent.cipher : null; + if ( + this.cipherId != null && + uCipher != null && + uCipher.id === this.cipherId && + uCipher.login != null && + uCipher.login.username != null + ) { + this.copyValue(uCipher, uCipher.login.username, "username", "Username"); + } + break; + } + case "copyPassword": { + const pComponent = + this.addEditComponent == null ? this.viewComponent : this.addEditComponent; + const pCipher = pComponent != null ? pComponent.cipher : null; + if ( + this.cipherId != null && + pCipher != null && + pCipher.id === this.cipherId && + pCipher.login != null && + pCipher.login.password != null && + pCipher.viewPassword + ) { + this.copyValue(pCipher, pCipher.login.password, "password", "Password"); + } + break; + } + case "copyTotp": { + const tComponent = + this.addEditComponent == null ? this.viewComponent : this.addEditComponent; + const tCipher = tComponent != null ? tComponent.cipher : null; + if ( + this.cipherId != null && + tCipher != null && + tCipher.id === this.cipherId && + tCipher.login != null && + tCipher.login.hasTotp && + this.userHasPremiumAccess + ) { + const value = await this.totpService.getCode(tCipher.login.totp); + this.copyValue(tCipher, value, "verificationCodeTotp", "TOTP"); + } + break; + } + default: + detectChanges = false; + break; + } + + if (detectChanges) { + this.changeDetectorRef.detectChanges(); + } + }); + }); + + if (!this.syncService.syncInProgress) { + await this.load(); + } + document.body.classList.remove("layout_frontend"); + + this.searchBarService.setEnabled(true); + this.searchBarService.setPlaceholderText(this.i18nService.t("searchVault")); + } + + ngOnDestroy() { + this.searchBarService.setEnabled(false); + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + document.body.classList.add("layout_frontend"); + } + + async load() { + this.route.queryParams.pipe(first()).subscribe(async (params) => { + if (params.cipherId) { + const cipherView = new CipherView(); + cipherView.id = params.cipherId; + if (params.action === "clone") { + await this.cloneCipher(cipherView); + } else if (params.action === "edit") { + await this.editCipher(cipherView); + } else { + await this.viewCipher(cipherView); + } + } else if (params.action === "add") { + this.addType = Number(params.addType); + this.addCipher(this.addType); + } + + this.activeFilter = new VaultFilter({ + status: params.deleted ? "trash" : params.favorites ? "favorites" : "all", + cipherType: + params.action === "add" || params.type == null ? null : parseInt(params.type, null), + selectedFolderId: params.folderId, + selectedCollectionId: params.selectedCollectionId, + selectedOrganizationId: params.selectedOrganizationId, + myVaultOnly: params.myVaultOnly ?? false, + }); + await this.ciphersComponent.reload(this.buildFilter()); + }); + } + + async viewCipher(cipher: CipherView) { + if (!(await this.canNavigateAway("view", cipher))) { + return; + } + + this.cipherId = cipher.id; + this.action = "view"; + this.go(); + } + + viewCipherMenu(cipher: CipherView) { + const menu: RendererMenuItem[] = [ + { + label: this.i18nService.t("view"), + click: () => + this.functionWithChangeDetection(() => { + this.viewCipher(cipher); + }), + }, + ]; + if (!cipher.isDeleted) { + menu.push({ + label: this.i18nService.t("edit"), + click: () => + this.functionWithChangeDetection(() => { + this.editCipher(cipher); + }), + }); + menu.push({ + label: this.i18nService.t("clone"), + click: () => + this.functionWithChangeDetection(() => { + this.cloneCipher(cipher); + }), + }); + } + + switch (cipher.type) { + case CipherType.Login: + if ( + cipher.login.canLaunch || + cipher.login.username != null || + cipher.login.password != null + ) { + menu.push({ type: "separator" }); + } + if (cipher.login.canLaunch) { + menu.push({ + label: this.i18nService.t("launch"), + click: () => this.platformUtilsService.launchUri(cipher.login.launchUri), + }); + } + if (cipher.login.username != null) { + menu.push({ + label: this.i18nService.t("copyUsername"), + click: () => this.copyValue(cipher, cipher.login.username, "username", "Username"), + }); + } + if (cipher.login.password != null && cipher.viewPassword) { + menu.push({ + label: this.i18nService.t("copyPassword"), + click: () => { + this.copyValue(cipher, cipher.login.password, "password", "Password"); + this.eventService.collect(EventType.Cipher_ClientCopiedPassword, cipher.id); + }, + }); + } + if (cipher.login.hasTotp && (cipher.organizationUseTotp || this.userHasPremiumAccess)) { + menu.push({ + label: this.i18nService.t("copyVerificationCodeTotp"), + click: async () => { + const value = await this.totpService.getCode(cipher.login.totp); + this.copyValue(cipher, value, "verificationCodeTotp", "TOTP"); + }, + }); + } + break; + case CipherType.Card: + if (cipher.card.number != null || cipher.card.code != null) { + menu.push({ type: "separator" }); + } + if (cipher.card.number != null) { + menu.push({ + label: this.i18nService.t("copyNumber"), + click: () => this.copyValue(cipher, cipher.card.number, "number", "Card Number"), + }); + } + if (cipher.card.code != null) { + menu.push({ + label: this.i18nService.t("copySecurityCode"), + click: () => { + this.copyValue(cipher, cipher.card.code, "securityCode", "Security Code"); + this.eventService.collect(EventType.Cipher_ClientCopiedCardCode, cipher.id); + }, + }); + } + break; + default: + break; + } + + invokeMenu(menu); + } + + async editCipher(cipher: CipherView) { + if (!(await this.canNavigateAway("edit", cipher))) { + return; + } else if (!(await this.passwordReprompt(cipher))) { + return; + } + + await this.editCipherWithoutPasswordPrompt(cipher); + } + + async editCipherWithoutPasswordPrompt(cipher: CipherView) { + if (!(await this.canNavigateAway("edit", cipher))) { + return; + } + + this.cipherId = cipher.id; + this.action = "edit"; + this.go(); + } + + async cloneCipher(cipher: CipherView) { + if (!(await this.canNavigateAway("clone", cipher))) { + return; + } else if (!(await this.passwordReprompt(cipher))) { + return; + } + + await this.cloneCipherWithoutPasswordPrompt(cipher); + } + + async cloneCipherWithoutPasswordPrompt(cipher: CipherView) { + if (!(await this.canNavigateAway("edit", cipher))) { + return; + } + + this.cipherId = cipher.id; + this.action = "clone"; + this.go(); + } + + async addCipher(type: CipherType = null) { + if (!(await this.canNavigateAway("add", null))) { + return; + } + + this.addType = type; + this.action = "add"; + this.cipherId = null; + this.prefillNewCipherFromFilter(); + this.go(); + } + + addCipherOptions() { + const menu: RendererMenuItem[] = [ + { + label: this.i18nService.t("typeLogin"), + click: () => this.addCipherWithChangeDetection(CipherType.Login), + }, + { + label: this.i18nService.t("typeCard"), + click: () => this.addCipherWithChangeDetection(CipherType.Card), + }, + { + label: this.i18nService.t("typeIdentity"), + click: () => this.addCipherWithChangeDetection(CipherType.Identity), + }, + { + label: this.i18nService.t("typeSecureNote"), + click: () => this.addCipherWithChangeDetection(CipherType.SecureNote), + }, + ]; + + invokeMenu(menu); + } + + async savedCipher(cipher: CipherView) { + this.cipherId = cipher.id; + this.action = "view"; + this.go(); + await this.ciphersComponent.refresh(); + } + + async deletedCipher(cipher: CipherView) { + this.cipherId = null; + this.action = null; + this.go(); + await this.ciphersComponent.refresh(); + } + + async restoredCipher(cipher: CipherView) { + this.cipherId = null; + this.action = null; + this.go(); + await this.ciphersComponent.refresh(); + } + + async editCipherAttachments(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const [modal, childComponent] = await this.modalService.openViewRef( + AttachmentsComponent, + this.attachmentsModalRef, + (comp) => (comp.cipherId = cipher.id) + ); + this.modal = modal; + + let madeAttachmentChanges = false; + childComponent.onUploadedAttachment.subscribe(() => (madeAttachmentChanges = true)); + childComponent.onDeletedAttachment.subscribe(() => (madeAttachmentChanges = true)); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + if (madeAttachmentChanges) { + await this.ciphersComponent.refresh(); + } + madeAttachmentChanges = false; + }); + } + + async shareCipher(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const [modal, childComponent] = await this.modalService.openViewRef( + ShareComponent, + this.shareModalRef, + (comp) => (comp.cipherId = cipher.id) + ); + this.modal = modal; + + childComponent.onSharedCipher.subscribe(async () => { + this.modal.close(); + this.viewCipher(cipher); + await this.ciphersComponent.refresh(); + }); + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + async cipherCollections(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const [modal, childComponent] = await this.modalService.openViewRef( + CollectionsComponent, + this.collectionsModalRef, + (comp) => (comp.cipherId = cipher.id) + ); + this.modal = modal; + + childComponent.onSavedCollections.subscribe(() => { + this.modal.close(); + this.viewCipher(cipher); + }); + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + async viewCipherPasswordHistory(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + [this.modal] = await this.modalService.openViewRef( + PasswordHistoryComponent, + this.passwordHistoryModalRef, + (comp) => (comp.cipherId = cipher.id) + ); + + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + cancelledAddEdit(cipher: CipherView) { + this.cipherId = cipher.id; + this.action = this.cipherId != null ? "view" : null; + this.go(); + } + + async applyVaultFilter(vaultFilter: VaultFilter) { + this.searchBarService.setPlaceholderText( + this.i18nService.t(this.calculateSearchBarLocalizationString(vaultFilter)) + ); + this.activeFilter = vaultFilter; + await this.ciphersComponent.reload(this.buildFilter(), vaultFilter.status === "trash"); + this.go(); + } + + private calculateSearchBarLocalizationString(vaultFilter: VaultFilter): string { + if (vaultFilter.status === "favorites") { + return "searchFavorites"; + } + if (vaultFilter.status === "trash") { + return "searchTrash"; + } + if (vaultFilter.cipherType != null) { + return "searchType"; + } + if (vaultFilter.selectedFolderId != null && vaultFilter.selectedFolderId != "none") { + return "searchFolder"; + } + if (vaultFilter.selectedCollectionId != null) { + return "searchCollection"; + } + if (vaultFilter.selectedOrganizationId != null) { + return "searchOrganization"; + } + if (vaultFilter.myVaultOnly) { + return "searchMyVault"; + } + + return "searchVault"; + } + + private buildFilter(): (cipher: CipherView) => boolean { + return (cipher) => { + let cipherPassesFilter = true; + if (this.activeFilter.status === "favorites" && cipherPassesFilter) { + cipherPassesFilter = cipher.favorite; + } + if (this.activeFilter.status === "trash" && cipherPassesFilter) { + cipherPassesFilter = cipher.isDeleted; + } + if (this.activeFilter.cipherType != null && cipherPassesFilter) { + cipherPassesFilter = cipher.type === this.activeFilter.cipherType; + } + if ( + this.activeFilter.selectedFolderId != null && + this.activeFilter.selectedFolderId != "none" && + cipherPassesFilter + ) { + cipherPassesFilter = cipher.folderId === this.activeFilter.selectedFolderId; + } + if (this.activeFilter.selectedCollectionId != null && cipherPassesFilter) { + cipherPassesFilter = + cipher.collectionIds != null && + cipher.collectionIds.indexOf(this.activeFilter.selectedCollectionId) > -1; + } + if (this.activeFilter.selectedOrganizationId != null && cipherPassesFilter) { + cipherPassesFilter = cipher.organizationId === this.activeFilter.selectedOrganizationId; + } + if (this.activeFilter.myVaultOnly && cipherPassesFilter) { + cipherPassesFilter = cipher.organizationId === null; + } + return cipherPassesFilter; + }; + } + + async openGenerator(comingFromAddEdit: boolean, passwordType = true) { + if (this.modal != null) { + this.modal.close(); + } + + const cipher = this.addEditComponent?.cipher; + const loginType = cipher != null && cipher.type === CipherType.Login && cipher.login != null; + + const [modal, childComponent] = await this.modalService.openViewRef( + GeneratorComponent, + this.generatorModalRef, + (comp) => { + comp.comingFromAddEdit = comingFromAddEdit; + if (comingFromAddEdit) { + comp.type = passwordType ? "password" : "username"; + if (loginType && cipher.login.hasUris && cipher.login.uris[0].hostname != null) { + comp.usernameWebsite = cipher.login.uris[0].hostname; + } + } + } + ); + this.modal = modal; + + childComponent.onSelected.subscribe((value: string) => { + this.modal.close(); + if (loginType) { + this.addEditComponent.markPasswordAsDirty(); + if (passwordType) { + this.addEditComponent.cipher.login.password = value; + } else { + this.addEditComponent.cipher.login.username = value; + } + } + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + async addFolder() { + this.messagingService.send("newFolder"); + } + + async editFolder(folderId: string) { + if (this.modal != null) { + this.modal.close(); + } + + const [modal, childComponent] = await this.modalService.openViewRef( + FolderAddEditComponent, + this.folderAddEditModalRef, + (comp) => (comp.folderId = folderId) + ); + this.modal = modal; + + childComponent.onSavedFolder.subscribe(async (folder: FolderView) => { + this.modal.close(); + await this.vaultFilterComponent.reloadCollectionsAndFolders(this.activeFilter); + }); + childComponent.onDeletedFolder.subscribe(async (folder: FolderView) => { + this.modal.close(); + await this.vaultFilterComponent.reloadCollectionsAndFolders(this.activeFilter); + }); + + this.modal.onClosed.subscribe(() => { + this.modal = null; + }); + } + + private dirtyInput(): boolean { + return ( + (this.action === "add" || this.action === "edit" || this.action === "clone") && + document.querySelectorAll("app-vault-add-edit .ng-dirty").length > 0 + ); + } + + private async wantsToSaveChanges(): Promise { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("unsavedChangesConfirmation"), + this.i18nService.t("unsavedChangesTitle"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + return !confirmed; + } + + private go(queryParams: any = null) { + if (queryParams == null) { + queryParams = { + action: this.action, + cipherId: this.cipherId, + favorites: this.favorites ? true : null, + type: this.type, + folderId: this.folderId, + collectionId: this.collectionId, + deleted: this.deleted ? true : null, + organizationId: this.organizationId, + myVaultOnly: this.myVaultOnly, + }; + } + + this.router.navigate([], { + relativeTo: this.route, + queryParams: queryParams, + replaceUrl: true, + }); + } + + private addCipherWithChangeDetection(type: CipherType = null) { + this.functionWithChangeDetection(() => this.addCipher(type)); + } + + private copyValue(cipher: CipherView, value: string, labelI18nKey: string, aType: string) { + this.functionWithChangeDetection(async () => { + if ( + cipher.reprompt !== CipherRepromptType.None && + this.passwordRepromptService.protectedFields().includes(aType) && + !(await this.passwordRepromptService.showPasswordPrompt()) + ) { + return; + } + + this.platformUtilsService.copyToClipboard(value); + this.platformUtilsService.showToast( + "info", + null, + this.i18nService.t("valueCopied", this.i18nService.t(labelI18nKey)) + ); + if (this.action === "view") { + this.messagingService.send("minimizeOnCopy"); + } + }); + } + + private functionWithChangeDetection(func: () => void) { + this.ngZone.run(() => { + func(); + this.changeDetectorRef.detectChanges(); + }); + } + + private prefillNewCipherFromFilter() { + if (this.activeFilter.selectedCollectionId != null) { + const collection = this.vaultFilterComponent.collections.fullList.filter( + (c) => c.id === this.activeFilter.selectedCollectionId + ); + if (collection.length > 0) { + this.addOrganizationId = collection[0].organizationId; + this.addCollectionIds = [this.activeFilter.selectedCollectionId]; + } + } else if (this.activeFilter.selectedOrganizationId) { + this.addOrganizationId = this.activeFilter.selectedOrganizationId; + } + if (this.activeFilter.selectedFolderId && this.activeFilter.selectedFolder) { + this.folderId = this.activeFilter.selectedFolderId; + } + } + + private async canNavigateAway(action: string, cipher?: CipherView) { + // Don't navigate to same route + if (this.action === action && (cipher == null || this.cipherId === cipher.id)) { + return false; + } else if (this.dirtyInput() && (await this.wantsToSaveChanges())) { + return false; + } + + return true; + } + + private async passwordReprompt(cipher: CipherView) { + return ( + cipher.reprompt === CipherRepromptType.None || + (await this.passwordRepromptService.showPasswordPrompt()) + ); + } +} diff --git a/apps/desktop/src/app/vault/view-custom-fields.component.html b/apps/desktop/src/app/vault/view-custom-fields.component.html new file mode 100644 index 0000000000..d1980048eb --- /dev/null +++ b/apps/desktop/src/app/vault/view-custom-fields.component.html @@ -0,0 +1,72 @@ +
+
+ {{ "customFields" | i18n }} +
+
+
+
+ {{ field.name }} +
+ {{ field.value || " " }} +
+
+ + {{ field.maskedValue }} +
+
+ + + {{ field.value }} +
+
+
+ + {{ "linkedValue" | i18n }} +
+ {{ cipher.linkedFieldI18nKey(field.linkedId) | i18n }} +
+
+
+ + +
+
+
+
diff --git a/apps/desktop/src/app/vault/view-custom-fields.component.ts b/apps/desktop/src/app/vault/view-custom-fields.component.ts new file mode 100644 index 0000000000..30046a3110 --- /dev/null +++ b/apps/desktop/src/app/vault/view-custom-fields.component.ts @@ -0,0 +1,14 @@ +import { Component } from "@angular/core"; + +import { ViewCustomFieldsComponent as BaseViewCustomFieldsComponent } from "jslib-angular/components/view-custom-fields.component"; +import { EventService } from "jslib-common/abstractions/event.service"; + +@Component({ + selector: "app-vault-view-custom-fields", + templateUrl: "view-custom-fields.component.html", +}) +export class ViewCustomFieldsComponent extends BaseViewCustomFieldsComponent { + constructor(eventService: EventService) { + super(eventService); + } +} diff --git a/apps/desktop/src/app/vault/view.component.html b/apps/desktop/src/app/vault/view.component.html new file mode 100644 index 0000000000..a033cdd827 --- /dev/null +++ b/apps/desktop/src/app/vault/view.component.html @@ -0,0 +1,412 @@ +
+
+
+
+ {{ "itemInformation" | i18n }} +
+
+
+ {{ "name" | i18n }} + {{ cipher.name }} +
+ +
+
+
+ {{ "username" | i18n }} + {{ cipher.login.username }} +
+
+ +
+
+
+
+ {{ "password" | i18n }} +
+ {{ cipher.login.maskedPassword }} +
+
+
+
+ + + +
+
+
+
+ {{ "verificationCodeTotp" | i18n }} + {{ totpCodeFormatted }} +
+ + {{ totpSec }} + + + + + + + +
+ +
+
+
+ +
+
+ {{ "cardholderName" | i18n }} + {{ cipher.card.cardholderName }} +
+
+
+ {{ "number" | i18n }} + {{ + cipher.card.maskedNumber | creditCardNumber: cipher.card.brand + }} + {{ + cipher.card.number | creditCardNumber: cipher.card.brand + }} +
+
+ + +
+
+
+ {{ "brand" | i18n }} + {{ cipher.card.brand }} +
+
+ {{ "expiration" | i18n }} + {{ cipher.card.expiration }} +
+
+
+ {{ "securityCode" | i18n }} + {{ cipher.card.maskedCode }} + {{ cipher.card.code }} +
+
+ + +
+
+
+ +
+
+ {{ "identityName" | i18n }} + {{ cipher.identity.fullName }} +
+
+ {{ "username" | i18n }} + {{ cipher.identity.username }} +
+
+ {{ "company" | i18n }} + {{ cipher.identity.company }} +
+
+ {{ "ssn" | i18n }} + {{ cipher.identity.ssn }} +
+
+ {{ "passportNumber" | i18n }} + {{ cipher.identity.passportNumber }} +
+
+ {{ "licenseNumber" | i18n }} + {{ cipher.identity.licenseNumber }} +
+
+ {{ "email" | i18n }} + {{ cipher.identity.email }} +
+
+ {{ "phone" | i18n }} + {{ cipher.identity.phone }} +
+
+ {{ "address" | i18n }} +
{{ cipher.identity.address1 }}
+
{{ cipher.identity.address2 }}
+
{{ cipher.identity.address3 }}
+
+ {{ cipher.identity.fullAddressPart2 }} +
+
{{ cipher.identity.country }}
+
+
+
+
+
+
+
+
+ {{ "uri" | i18n }} + {{ "website" | i18n }} + {{ u.hostOrUri }} +
+
+ + +
+
+
+
+
+
+ {{ "notes" | i18n }} +
+
+
{{ cipher.notes }}
+
+
+ + +
+
+ {{ "attachments" | i18n }} +
+
+ +
+
+
+ +
+
+
+ diff --git a/apps/desktop/src/app/vault/view.component.ts b/apps/desktop/src/app/vault/view.component.ts new file mode 100644 index 0000000000..6c2dd85828 --- /dev/null +++ b/apps/desktop/src/app/vault/view.component.ts @@ -0,0 +1,115 @@ +import { + ChangeDetectorRef, + Component, + EventEmitter, + NgZone, + OnChanges, + Output, +} from "@angular/core"; + +import { ViewComponent as BaseViewComponent } from "jslib-angular/components/view.component"; +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +const BroadcasterSubscriptionId = "ViewComponent"; + +@Component({ + selector: "app-vault-view", + templateUrl: "view.component.html", +}) +export class ViewComponent extends BaseViewComponent implements OnChanges { + @Output() onViewCipherPasswordHistory = new EventEmitter(); + + constructor( + cipherService: CipherService, + totpService: TotpService, + tokenService: TokenService, + i18nService: I18nService, + cryptoService: CryptoService, + platformUtilsService: PlatformUtilsService, + auditService: AuditService, + broadcasterService: BroadcasterService, + ngZone: NgZone, + changeDetectorRef: ChangeDetectorRef, + eventService: EventService, + apiService: ApiService, + private messagingService: MessagingService, + passwordRepromptService: PasswordRepromptService, + logService: LogService, + stateService: StateService + ) { + super( + cipherService, + totpService, + tokenService, + i18nService, + cryptoService, + platformUtilsService, + auditService, + window, + broadcasterService, + ngZone, + changeDetectorRef, + eventService, + apiService, + passwordRepromptService, + logService, + stateService + ); + } + ngOnInit() { + super.ngOnInit(); + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(() => { + switch (message.command) { + case "windowHidden": + this.onWindowHidden(); + break; + default: + } + }); + }); + } + + ngOnDestroy() { + super.ngOnDestroy(); + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + } + + async ngOnChanges() { + await super.load(); + } + + viewHistory() { + this.onViewCipherPasswordHistory.emit(this.cipher); + } + + async copy(value: string, typeI18nKey: string, aType: string) { + super.copy(value, typeI18nKey, aType); + this.messagingService.send("minimizeOnCopy"); + } + + onWindowHidden() { + this.showPassword = false; + this.showCardNumber = false; + this.showCardCode = false; + if (this.cipher !== null && this.cipher.hasFields) { + this.cipher.fields.forEach((field) => { + field.showValue = false; + }); + } + } +} diff --git a/apps/desktop/src/entry.ts b/apps/desktop/src/entry.ts new file mode 100644 index 0000000000..78fe51e8b9 --- /dev/null +++ b/apps/desktop/src/entry.ts @@ -0,0 +1,35 @@ +import { NativeMessagingProxy } from "./proxy/native-messaging-proxy"; + +// We need to import the other dependencies using `require` since `import` will +// generate `Error: Cannot find module 'electron'`. The cause of this error is +// due to native messaging setting the ELECTRON_RUN_AS_NODE env flag on windows +// which removes the electron module. This flag is needed for stdin/out to work +// properly on Windows. + +if ( + process.argv.some((arg) => arg.indexOf("chrome-extension://") !== -1 || arg.indexOf("{") !== -1) +) { + if (process.platform === "darwin") { + // eslint-disable-next-line + const app = require("electron").app; + + app.on("ready", () => { + app.dock.hide(); + }); + } + + process.stdout.on("error", (e) => { + if (e.code === "EPIPE") { + process.exit(0); + } + }); + + const proxy = new NativeMessagingProxy(); + proxy.run(); +} else { + // eslint-disable-next-line + const Main = require("./main").Main; + + const main = new Main(); + main.bootstrap(); +} diff --git a/apps/desktop/src/global.d.ts b/apps/desktop/src/global.d.ts new file mode 100644 index 0000000000..1b85bb1b6b --- /dev/null +++ b/apps/desktop/src/global.d.ts @@ -0,0 +1 @@ +declare module "forcefocus"; diff --git a/apps/desktop/src/images/bwi-globe.png b/apps/desktop/src/images/bwi-globe.png new file mode 100644 index 0000000000..cceeaefbcf Binary files /dev/null and b/apps/desktop/src/images/bwi-globe.png differ diff --git a/apps/desktop/src/images/close-button-white.svg b/apps/desktop/src/images/close-button-white.svg new file mode 100644 index 0000000000..8aea346478 --- /dev/null +++ b/apps/desktop/src/images/close-button-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/desktop/src/images/icon-highlight.png b/apps/desktop/src/images/icon-highlight.png new file mode 100644 index 0000000000..6cfa837250 Binary files /dev/null and b/apps/desktop/src/images/icon-highlight.png differ diff --git a/apps/desktop/src/images/icon-highlight@2x.png b/apps/desktop/src/images/icon-highlight@2x.png new file mode 100644 index 0000000000..e2b9486938 Binary files /dev/null and b/apps/desktop/src/images/icon-highlight@2x.png differ diff --git a/apps/desktop/src/images/icon-template.png b/apps/desktop/src/images/icon-template.png new file mode 100644 index 0000000000..9eff66254a Binary files /dev/null and b/apps/desktop/src/images/icon-template.png differ diff --git a/apps/desktop/src/images/icon-template@2x.png b/apps/desktop/src/images/icon-template@2x.png new file mode 100644 index 0000000000..3bde303826 Binary files /dev/null and b/apps/desktop/src/images/icon-template@2x.png differ diff --git a/apps/desktop/src/images/icon.ico b/apps/desktop/src/images/icon.ico new file mode 100644 index 0000000000..a18e8341b5 Binary files /dev/null and b/apps/desktop/src/images/icon.ico differ diff --git a/apps/desktop/src/images/icon.png b/apps/desktop/src/images/icon.png new file mode 100644 index 0000000000..6636b04b61 Binary files /dev/null and b/apps/desktop/src/images/icon.png differ diff --git a/apps/desktop/src/images/loading.svg b/apps/desktop/src/images/loading.svg new file mode 100644 index 0000000000..7076310516 --- /dev/null +++ b/apps/desktop/src/images/loading.svg @@ -0,0 +1,6 @@ + + + Loading... + + diff --git a/apps/desktop/src/images/logo-dark@2x.png b/apps/desktop/src/images/logo-dark@2x.png new file mode 100644 index 0000000000..3fc3c6d7a5 Binary files /dev/null and b/apps/desktop/src/images/logo-dark@2x.png differ diff --git a/apps/desktop/src/images/logo-white@2x.png b/apps/desktop/src/images/logo-white@2x.png new file mode 100644 index 0000000000..519cbc75e1 Binary files /dev/null and b/apps/desktop/src/images/logo-white@2x.png differ diff --git a/apps/desktop/src/images/search-desktop-dark.svg b/apps/desktop/src/images/search-desktop-dark.svg new file mode 100644 index 0000000000..029d464afa --- /dev/null +++ b/apps/desktop/src/images/search-desktop-dark.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/desktop/src/images/search-desktop-light.svg b/apps/desktop/src/images/search-desktop-light.svg new file mode 100644 index 0000000000..273bcff401 --- /dev/null +++ b/apps/desktop/src/images/search-desktop-light.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/desktop/src/images/two-factor/0.png b/apps/desktop/src/images/two-factor/0.png new file mode 100644 index 0000000000..f37e3f17b4 Binary files /dev/null and b/apps/desktop/src/images/two-factor/0.png differ diff --git a/apps/desktop/src/images/two-factor/1.png b/apps/desktop/src/images/two-factor/1.png new file mode 100644 index 0000000000..b47a12b1db Binary files /dev/null and b/apps/desktop/src/images/two-factor/1.png differ diff --git a/apps/desktop/src/images/two-factor/2.png b/apps/desktop/src/images/two-factor/2.png new file mode 100644 index 0000000000..ab2e434036 Binary files /dev/null and b/apps/desktop/src/images/two-factor/2.png differ diff --git a/apps/desktop/src/images/two-factor/3.png b/apps/desktop/src/images/two-factor/3.png new file mode 100644 index 0000000000..21aac2da67 Binary files /dev/null and b/apps/desktop/src/images/two-factor/3.png differ diff --git a/apps/desktop/src/images/two-factor/4.png b/apps/desktop/src/images/two-factor/4.png new file mode 100644 index 0000000000..ae7d7b55e4 Binary files /dev/null and b/apps/desktop/src/images/two-factor/4.png differ diff --git a/apps/desktop/src/images/two-factor/6.png b/apps/desktop/src/images/two-factor/6.png new file mode 100644 index 0000000000..ab2e434036 Binary files /dev/null and b/apps/desktop/src/images/two-factor/6.png differ diff --git a/apps/desktop/src/images/u2fkey.jpg b/apps/desktop/src/images/u2fkey.jpg new file mode 100644 index 0000000000..8013df0e56 Binary files /dev/null and b/apps/desktop/src/images/u2fkey.jpg differ diff --git a/apps/desktop/src/images/yubikey.jpg b/apps/desktop/src/images/yubikey.jpg new file mode 100644 index 0000000000..9ddf755dec Binary files /dev/null and b/apps/desktop/src/images/yubikey.jpg differ diff --git a/apps/desktop/src/index.html b/apps/desktop/src/index.html new file mode 100644 index 0000000000..6005361c0c --- /dev/null +++ b/apps/desktop/src/index.html @@ -0,0 +1,19 @@ + + + + + + + Bitwarden + + + + +
+
+ + diff --git a/apps/desktop/src/locales/af/messages.json b/apps/desktop/src/locales/af/messages.json new file mode 100644 index 0000000000..177d727e73 --- /dev/null +++ b/apps/desktop/src/locales/af/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "Alle Items" + }, + "favorites": { + "message": "Gunstelinge" + }, + "types": { + "message": "Tipes" + }, + "typeLogin": { + "message": "Aantekening" + }, + "typeCard": { + "message": "Kaart" + }, + "typeIdentity": { + "message": "Identiteit" + }, + "typeSecureNote": { + "message": "Beveiligde Nota" + }, + "folders": { + "message": "Vouers" + }, + "collections": { + "message": "Versamelings" + }, + "searchVault": { + "message": "Deursoek kluis" + }, + "addItem": { + "message": "Voeg item toe" + }, + "shared": { + "message": "Gedeel" + }, + "share": { + "message": "Deel" + }, + "moveToOrganization": { + "message": "Skuif na organisasie" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ geskuif na $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Kies ’n organisasie waarheen u hierdie item wil skuif. Deur te skuif kry die organisasie die einaarskap van die item. U is dan nie meer die direkte eienaar van die item wanneer dit geskuif is nie." + }, + "attachments": { + "message": "Aanhegsels" + }, + "viewItem": { + "message": "Bekyk Item" + }, + "name": { + "message": "Naam" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nuwe URI" + }, + "username": { + "message": "Gebruikersnaam" + }, + "password": { + "message": "Wagwoord" + }, + "passphrase": { + "message": "Wagfrase" + }, + "editItem": { + "message": "Wysig Item" + }, + "emailAddress": { + "message": "E-posadres" + }, + "verificationCodeTotp": { + "message": "Bevestigingskode (TOTP)" + }, + "website": { + "message": "Webwerf" + }, + "notes": { + "message": "Notas" + }, + "customFields": { + "message": "Pasgemaakte Velde" + }, + "launch": { + "message": "Lanseer" + }, + "copyValue": { + "message": "Kopieer Waarde", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimaliseer by kopieer na knipbord" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimaliseer by die kopieer van itemdata na die knipbord." + }, + "toggleVisibility": { + "message": "Tokkel sigbaarheid" + }, + "toggleCollapse": { + "message": "Tokkel invou", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kaarthouernaam" + }, + "number": { + "message": "Nommer" + }, + "brand": { + "message": "Handelsmerk" + }, + "expiration": { + "message": "Vervaldatum" + }, + "securityCode": { + "message": "Sekuriteitskode" + }, + "identityName": { + "message": "Identiteitnaam" + }, + "company": { + "message": "Maatskappy" + }, + "ssn": { + "message": "Identiteitsnommer" + }, + "passportNumber": { + "message": "Paspoortnommer" + }, + "licenseNumber": { + "message": "Lisensienommer" + }, + "email": { + "message": "E-pos" + }, + "phone": { + "message": "Telefoon" + }, + "address": { + "message": "Adres" + }, + "premiumRequired": { + "message": "Premie word vereis" + }, + "premiumRequiredDesc": { + "message": "’n Premie-lidmaatskap is nodig om hierdie funksie te gebruik." + }, + "errorOccurred": { + "message": "’n Fout het voorgekom." + }, + "error": { + "message": "Fout" + }, + "january": { + "message": "Januarie" + }, + "february": { + "message": "Februarie" + }, + "march": { + "message": "Maart" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Mei" + }, + "june": { + "message": "Junie" + }, + "july": { + "message": "Julie" + }, + "august": { + "message": "Augustus" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Desember" + }, + "ex": { + "message": "bv.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titel" + }, + "mr": { + "message": "Mnr." + }, + "mrs": { + "message": "Mev." + }, + "ms": { + "message": "Mej." + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Vervalmaand" + }, + "expirationYear": { + "message": "Vervaljaar" + }, + "select": { + "message": "Kies" + }, + "other": { + "message": "Ander" + }, + "generatePassword": { + "message": "Genereer Wagwoord" + }, + "type": { + "message": "Tipe" + }, + "firstName": { + "message": "Voornaam" + }, + "middleName": { + "message": "Middelnaam" + }, + "lastName": { + "message": "Van" + }, + "fullName": { + "message": "Volle naam" + }, + "address1": { + "message": "Adres 1" + }, + "address2": { + "message": "Adres 2" + }, + "address3": { + "message": "Adres 3" + }, + "cityTown": { + "message": "Stad / Dorp" + }, + "stateProvince": { + "message": "Staat / Provinsie" + }, + "zipPostalCode": { + "message": "Poskode" + }, + "country": { + "message": "Land" + }, + "save": { + "message": "Bewaar" + }, + "cancel": { + "message": "Kanselleer" + }, + "delete": { + "message": "Skrap" + }, + "favorite": { + "message": "Gunsteling" + }, + "edit": { + "message": "Wysig" + }, + "authenticatorKeyTotp": { + "message": "Waarmerksleutel (TOTP)" + }, + "folder": { + "message": "Vouer" + }, + "newCustomField": { + "message": "Nuwe Pasgemaakte Veld" + }, + "value": { + "message": "Waarde" + }, + "dragToSort": { + "message": "Sleep om te sorteer" + }, + "cfTypeText": { + "message": "Teks" + }, + "cfTypeHidden": { + "message": "Versteek" + }, + "cfTypeBoolean": { + "message": "Booleaans" + }, + "cfTypeLinked": { + "message": "Gekoppel", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Gekoppelde waarde", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Verwyder" + }, + "nameRequired": { + "message": "Naam word vereis." + }, + "addedItem": { + "message": "Toegevoegde item" + }, + "editedItem": { + "message": "Gewysigde item" + }, + "deleteItem": { + "message": "Skrap Item" + }, + "deleteFolder": { + "message": "Skrap Vouer" + }, + "deleteAttachment": { + "message": "Skrap Aanhegsel" + }, + "deleteItemConfirmation": { + "message": "Is u seker u wil hierdie item skrap?" + }, + "deletedItem": { + "message": "Geskrapte item" + }, + "overwritePasswordConfirmation": { + "message": "Is u seker u wil oor die huidige wagwoord skryf?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Geen Vouer", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Voeg Vouer Toe" + }, + "editFolder": { + "message": "Wysig Vouer" + }, + "regeneratePassword": { + "message": "Hergenereer Wagwoord" + }, + "copyPassword": { + "message": "Kopieer Wagwoord" + }, + "copyUri": { + "message": "Kopieer URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopieer bevestigingskode (TOTP)" + }, + "length": { + "message": "Lengte" + }, + "numWords": { + "message": "Aantal Woorde" + }, + "wordSeparator": { + "message": "Woordskeier" + }, + "capitalize": { + "message": "Maak beginhoofletters", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Voeg syfer toe" + }, + "close": { + "message": "Sluit" + }, + "minNumbers": { + "message": "Min. aantal syfers" + }, + "minSpecial": { + "message": "Min. aantal spesiaal", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Vermy dubbelsinnige karakters" + }, + "searchCollection": { + "message": "Deursoek versameling" + }, + "searchFolder": { + "message": "Deursoek Vouer" + }, + "searchFavorites": { + "message": "Deursoek Gunstelinge" + }, + "searchType": { + "message": "Deursoek Tipe", + "description": "Search item type" + }, + "newAttachment": { + "message": "Voeg Nuwe Aanhegsel Toe" + }, + "deletedAttachment": { + "message": "Geskrapte aanhegsel" + }, + "deleteAttachmentConfirmation": { + "message": "Is u seker u wil hierdie aanhegsel skrap?" + }, + "attachmentSaved": { + "message": "Die aanhegsel is bewaar." + }, + "file": { + "message": "Lêer" + }, + "selectFile": { + "message": "Kies ’n lêer." + }, + "maxFileSize": { + "message": "Maksimumlêergrootte is 500 MB." + }, + "updateKey": { + "message": "U kan nie hierdie funksie gebruik tot u u enkripsiesleutel bygewerk het nie." + }, + "editedFolder": { + "message": "Gewysigde vouer" + }, + "addedFolder": { + "message": "Toegevoegde vouer" + }, + "deleteFolderConfirmation": { + "message": "Is u seker u wil hierdie vouer skrap?" + }, + "deletedFolder": { + "message": "Geskrapte vouer" + }, + "loginOrCreateNewAccount": { + "message": "Teken aan of skep ’n nuwe rekening vir toegang tot u beveiligde kluis." + }, + "createAccount": { + "message": "Skep Rekening" + }, + "logIn": { + "message": "Teken Aan" + }, + "submit": { + "message": "Dien In" + }, + "masterPass": { + "message": "Hoofwagwoord" + }, + "masterPassDesc": { + "message": "Die hoofwagwoord is die wagwoord wat u gebruik vir toegang tot die kluis. Dit is baie belangrik dat u dit onthou. Dit kan op geen manier teruggevind word indien u dit vergeet nie." + }, + "masterPassHintDesc": { + "message": "’n Hoofwagwoordwenk kan u help om u wagwoord te onthou indien u dit sou vergeet." + }, + "reTypeMasterPass": { + "message": "Tik weer hoofwagwoord in" + }, + "masterPassHint": { + "message": "Hoofwagwoordwenk (opsioneel)" + }, + "settings": { + "message": "Instellings" + }, + "passwordHint": { + "message": "Wagwoordwenk" + }, + "enterEmailToGetHint": { + "message": "Voer u e-posadres in om u hoofwagwoordwenk te ontvang." + }, + "getMasterPasswordHint": { + "message": "Kry hoofwagwoordwenk" + }, + "emailRequired": { + "message": "E-posadres word benodig." + }, + "invalidEmail": { + "message": "Ongeldige e-posadres." + }, + "masterPassRequired": { + "message": "Hoofwagwoord word benodig." + }, + "masterPassLength": { + "message": "Hoofwagwoord moet ten minste 8 karakters lank wees." + }, + "masterPassDoesntMatch": { + "message": "Hoofwagwoordbevestiging stem nie ooreen nie." + }, + "newAccountCreated": { + "message": "U nuwe rekening is geskep! U kan nou aanteken." + }, + "masterPassSent": { + "message": "Ons het ’n e-pos gestuur met u hoofwagwoordwenk." + }, + "unexpectedError": { + "message": "'n Onverwagte fout het voorgekom." + }, + "itemInformation": { + "message": "Iteminligting" + }, + "noItemsInList": { + "message": "Daar is geen items om te lys nie." + }, + "sendVerificationCode": { + "message": "Stuur ’n bevestigingskode na u e-pos" + }, + "sendCode": { + "message": "Verstuur kode" + }, + "codeSent": { + "message": "Kode verstuur" + }, + "verificationCode": { + "message": "Bevestigingskode" + }, + "confirmIdentity": { + "message": "Bevestig u identiteit om voort te gaan." + }, + "verificationCodeRequired": { + "message": "Bevestigingskode word vereis." + }, + "invalidVerificationCode": { + "message": "Ongeldige bevestigingskode" + }, + "continue": { + "message": "Gaan Voort" + }, + "enterVerificationCodeApp": { + "message": "Voer die 6-syferbevestigingskode van u waarmerktoep in." + }, + "enterVerificationCodeEmail": { + "message": "Voer die 8-syferbevestigingskode in wat aan $EMAIL$ gestuur is.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-pos met bevestigingskode is na $EMAIL$ gestuur.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Onthou my" + }, + "sendVerificationCodeEmailAgain": { + "message": "Stuur weer e-pos met bevestigingskode" + }, + "useAnotherTwoStepMethod": { + "message": "Gebruik ’n ander tweestapaantekenmetode" + }, + "insertYubiKey": { + "message": "Plaas u YubiKey in u rekenaar se USB-poort en druk dan op sy knop." + }, + "insertU2f": { + "message": "Plaas u beveilingsleutel in u rekenaar se USB-poort. Indien dit ’n knop het, druk dit dan." + }, + "recoveryCodeDesc": { + "message": "Het u toegang tot al u tweestapaanbieders verloor? Gebruik dan u terugstelkode om alle tweestapaanbieders op u rekening te deaktiveer." + }, + "recoveryCodeTitle": { + "message": "Terugstelkode" + }, + "authenticatorAppTitle": { + "message": "Waarmerktoep" + }, + "authenticatorAppDesc": { + "message": "Gebruik ’n waarmerktoep (soos Authy of Google Authenticator) om tydgebaseerde bevestigingskodes te genereer.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey-OTP-beveiligingsleutel" + }, + "yubiKeyDesc": { + "message": "Gebruik ’n YubiKey vir toegang tot u rekening. Werk met YubiKey 4, 4 Nano, 4C en NEO-toestelle." + }, + "duoDesc": { + "message": "Bevestig met Duo Security d.m.v. die Duo Mobile-toep, SMS, spraakoproep of ’n U2F-beveiligingsleutel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Bevestig met Duo Security vir u organisasie d.m.v. die Duo Mobile-toep, SMS, spraakoproep of ’n U2F-beveiligingsleutel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Gebruik ’n WebAuthn-beveilingssleutel om toegang tot u rekening te verkry." + }, + "emailTitle": { + "message": "E-pos" + }, + "emailDesc": { + "message": "U sal bevestigingskodes per e-pos ontvang." + }, + "loginUnavailable": { + "message": "Aantekening onbeskikbaar" + }, + "noTwoStepProviders": { + "message": "Tweestapaantekening is op die rekening geaktiveer, maar hierdie toestel ondersteun geen van die gekonfigureerde aanbieders nie." + }, + "noTwoStepProviders2": { + "message": "Voeg bykomende aanbieders toe wat beter ondersteun word op verskillende toestelle (soos n waarmerktoep)." + }, + "twoStepOptions": { + "message": "Opsies vir tweestapaantekening" + }, + "selfHostedEnvironment": { + "message": "Selfgehuisveste omgewing" + }, + "selfHostedEnvironmentFooter": { + "message": "Spesifiseer die basisbronadres van u selfgehuisveste Bitwarden-installasie." + }, + "customEnvironment": { + "message": "Pasgemaakte omgewing" + }, + "customEnvironmentFooter": { + "message": "Vir gevorderde gebruikers. U kan die basisbronadres van elke diens onafhanklik instel." + }, + "baseUrl": { + "message": "Bedienerbronadres" + }, + "apiUrl": { + "message": "API-bedienerbronadres" + }, + "webVaultUrl": { + "message": "Webkluisbedienerbronadres" + }, + "identityUrl": { + "message": "Identiteitbedienerbronadres" + }, + "notificationsUrl": { + "message": "Kennisgewingsbedienerbronadres" + }, + "iconsUrl": { + "message": "Ikoonbedienerbronadres" + }, + "environmentSaved": { + "message": "Die omgewingbronadresse is bewaar." + }, + "ok": { + "message": "Goed" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nee" + }, + "overwritePassword": { + "message": "Skryf oor wagwoord" + }, + "learnMore": { + "message": "Leer meer" + }, + "featureUnavailable": { + "message": "Funksie Onbeskikbaar" + }, + "loggedOut": { + "message": "Uitgeteken" + }, + "loginExpired": { + "message": "U aantekensessie het verstryk." + }, + "logOutConfirmation": { + "message": "Is u seker u wil uitteken?" + }, + "logOut": { + "message": "Teken Uit" + }, + "addNewLogin": { + "message": "Voeg Nuwe Intekening Toe" + }, + "addNewItem": { + "message": "Voeg Nuwe Item Toe" + }, + "addNewFolder": { + "message": "Voeg Nuwe Vouer Toe" + }, + "view": { + "message": "Bekyk" + }, + "account": { + "message": "Rekening" + }, + "loading": { + "message": "Laai tans…" + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Wagwoordgenereerder" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Rapporteer ’n fout" + }, + "blog": { + "message": "Woernaal" + }, + "followUs": { + "message": "Volg Ons" + }, + "syncVault": { + "message": "Sichroniseer Kluis" + }, + "changeMasterPass": { + "message": "Verander Hoofwagwoord" + }, + "changeMasterPasswordConfirmation": { + "message": "U kan u hoofwagwoord op die bitwarden.com-webkluis verander. Wil u die webwerf nou besoek?" + }, + "fingerprintPhrase": { + "message": "Vingerafdrukfrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "U rekening se vingerafdrukfrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Gaan Na Webkluis" + }, + "getMobileApp": { + "message": "Kry Mobiele Toep" + }, + "getBrowserExtension": { + "message": "Kry Blaaieruitbreiding" + }, + "syncingComplete": { + "message": "Klaar gesinchroniseer" + }, + "syncingFailed": { + "message": "Sinkronisasie het misluk" + }, + "yourVaultIsLocked": { + "message": "U kluis is vergrendel. Verifieer u hoofwagwoord om voort te gaan." + }, + "unlock": { + "message": "Ontgrendel" + }, + "loggedInAsOn": { + "message": "Aangeteken as $EMAIL$ by $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ongeldige hoofwagwoord" + }, + "twoStepLoginConfirmation": { + "message": "Tweestapsaantekening maak u rekening veiliger deur u aantekenpoging te bevestig met ’n ander toestel soos ’n beveiligingsleutel, waarmerktoep, SMS, telefoonoproep of e-pos. U kan tweestapsaantekening in die webkluis op bitwarden.com aktiveer. Wil u die webwerf nou besoek?" + }, + "twoStepLogin": { + "message": "Tweestapaantekening" + }, + "vaultTimeout": { + "message": "Kluis-uittel" + }, + "vaultTimeoutDesc": { + "message": "Kies wanneer u kluis sal uittel en die gekose aksie sal uitvoer." + }, + "immediately": { + "message": "Onmiddellik" + }, + "tenSeconds": { + "message": "10 sekondes" + }, + "twentySeconds": { + "message": "20 sekondes" + }, + "thirtySeconds": { + "message": "30 sekondes" + }, + "oneMinute": { + "message": "1 minuut" + }, + "twoMinutes": { + "message": "2 minute" + }, + "fiveMinutes": { + "message": "5 minute" + }, + "fifteenMinutes": { + "message": "15 minute" + }, + "thirtyMinutes": { + "message": "30 minute" + }, + "oneHour": { + "message": "1 uur" + }, + "fourHours": { + "message": "4 uur" + }, + "onIdle": { + "message": "By stelselonaktiwiteit" + }, + "onSleep": { + "message": "By slaapmodus" + }, + "onLocked": { + "message": "By stelselvergrendeling" + }, + "onRestart": { + "message": "Nadat toep herbegin is" + }, + "never": { + "message": "Nooit" + }, + "security": { + "message": "Sekuriteit" + }, + "clearClipboard": { + "message": "Wis Knipbord", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Wis gekopieerde waardes outomaties vanuit u knipbord.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Deaktiveer Webwerfikone" + }, + "disableFaviconDesc": { + "message": "Webwerfikone verskaf ’n herkenbare beeld langs elke aantekenitem in u kluis." + }, + "enableMinToTray": { + "message": "Minimaliseer na stelsellaai" + }, + "enableMinToTrayDesc": { + "message": "By die minimaliseer van die venster, toon eerder ’n ikoon in die stelsellaai." + }, + "enableMinToMenuBar": { + "message": "Minimaliseer na kieslysbalk" + }, + "enableMinToMenuBarDesc": { + "message": "By die minimaliseer van die venster, toon eerder ’n ikoon in die kieslysbalk." + }, + "enableCloseToTray": { + "message": "Sluit na stelsellaai" + }, + "enableCloseToTrayDesc": { + "message": "By die sluit van die venster, toon eerder ’n ikoon in die stelsellaai." + }, + "enableCloseToMenuBar": { + "message": "Sluit na kieslysbalk" + }, + "enableCloseToMenuBarDesc": { + "message": "By die sluit van die venster, toon eerder ’n ikoon in die kieslysbalk." + }, + "enableTray": { + "message": "Aktiveer stelsellaai" + }, + "enableTrayDesc": { + "message": "Toon altyd ’n ikoon in die stelsellaai." + }, + "startToTray": { + "message": "Begin na stelsellaai" + }, + "startToTrayDesc": { + "message": "Wanneer die toepassing aanvanklik begin word, toon slegs ’n ikoon in die stelsellaai." + }, + "startToMenuBar": { + "message": "Begin na kieslysbalk" + }, + "startToMenuBarDesc": { + "message": "Wanneer die toepassing aanvanklik begin word, toon slegs ’n ikoon in die kieslysbalk." + }, + "openAtLogin": { + "message": "Begin outomaties by aanskakel" + }, + "openAtLoginDesc": { + "message": "Begin die Bitwarden-werkskermtoep outomaties wanneer rekenaar aangeskakel word." + }, + "alwaysShowDock": { + "message": "Toon altyd in die dok" + }, + "alwaysShowDockDesc": { + "message": "Toon die Bitwarden-ikoon in die dok, selfs wanneer geminimaliseer in die kieslysbalk." + }, + "confirmTrayTitle": { + "message": "Bevestig deaktivering van stelsellaai" + }, + "confirmTrayDesc": { + "message": "Deaktivering van hierdie instelling sal ook alle ander instellings van die stelsellaai deaktiveer." + }, + "language": { + "message": "Taal" + }, + "languageDesc": { + "message": "Verander die taal van die toepassing. Herbegin word vereis." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Verander die toepassing se kleurtema." + }, + "dark": { + "message": "Donker", + "description": "Dark color" + }, + "light": { + "message": "Lig", + "description": "Light color" + }, + "copy": { + "message": "Kopieer", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Gaan na vir bywerkings" + }, + "version": { + "message": "Weergawe $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Herbegin om by te werk" + }, + "restartToUpdateDesc": { + "message": "Weergawe $VERSION_NUM$ is gereed vir installasie. U moet die toepassing herbegin om die installasie te voltooi. Wil u nou herbegin en bywerk?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Bywerking Beskikbaar" + }, + "updateAvailableDesc": { + "message": "’n Bywerking is gevind. Wil u dit nou aflaai?" + }, + "restart": { + "message": "Herbegin" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "Geen bywerkings is tans beskikbaar nie. U gebruik die nuutste weergawe." + }, + "updateError": { + "message": "Bywerkfout" + }, + "unknown": { + "message": "Onbekend" + }, + "copyUsername": { + "message": "Kopieer Gebruikersnaam" + }, + "copyNumber": { + "message": "Kopieer Nommer", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopieer Sekureiteitskode", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premie-lidmaatskap" + }, + "premiumManage": { + "message": "Bestuur Lidmaatskap" + }, + "premiumManageAlert": { + "message": "U kan u lidmaatskap op die bitwarden.com-webkluis bestuur. Wil u nou na die webwerf gaan?" + }, + "premiumRefresh": { + "message": "Verfris lidmaatskap" + }, + "premiumNotCurrentMember": { + "message": "U is nie tans ’n premie-lid nie." + }, + "premiumSignUpAndGet": { + "message": "Teken aan vir ’n premie-lidmaatskap en kry:" + }, + "premiumSignUpStorage": { + "message": "1 GG geënkripteerde berging vir lêeraanhegsels." + }, + "premiumSignUpTwoStep": { + "message": "Bykomende tweestapaantekenopsies soos YubiKey, FIDO U2F en Duo." + }, + "premiumSignUpReports": { + "message": "Wagwoordhigiëne, rekeningwelstand en databreukverslae om u kluis veilig te hou." + }, + "premiumSignUpTotp": { + "message": "TOTP-bevestigingskodegenereerder (2FA) vir aantekenings in u kluis." + }, + "premiumSignUpSupport": { + "message": "Klantediens met hoë prioriteit." + }, + "premiumSignUpFuture": { + "message": "Alle toekomstige premie-funksies. Binnekort meer!" + }, + "premiumPurchase": { + "message": "Koop Premie" + }, + "premiumPurchaseAlert": { + "message": "U kan lidmaatskap op die bitwarden.com-webkluis koop. Wil u nou na die webwerf gaan?" + }, + "premiumCurrentMember": { + "message": "U is ’n premie-lid!" + }, + "premiumCurrentMemberThanks": { + "message": "Dankie dat u Bitwarden ondersteun." + }, + "premiumPrice": { + "message": "Alles vir slegs $PRICE$ /jaar!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Klaar verfris" + }, + "passwordHistory": { + "message": "Wagwoordgeskiedenis" + }, + "clear": { + "message": "Wis", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Daar is geen wagwoorde om te lys nie." + }, + "undo": { + "message": "Ontdoen" + }, + "redo": { + "message": "Herdoen" + }, + "cut": { + "message": "Knip", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Plak", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Kies Alles" + }, + "zoomIn": { + "message": "Zoem in" + }, + "zoomOut": { + "message": "Zoem uit" + }, + "resetZoom": { + "message": "Stel zoem terug" + }, + "toggleFullScreen": { + "message": "Tokkel Volskerm" + }, + "reload": { + "message": "Herlaai" + }, + "toggleDevTools": { + "message": "Tokkel Ontwikkelaarsnutsmiddels" + }, + "minimize": { + "message": "Verklein", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoem" + }, + "bringAllToFront": { + "message": "Bring Alles na Vore", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Oor Bitwarden" + }, + "services": { + "message": "Dienste" + }, + "hideBitwarden": { + "message": "Versteek Bitwarden" + }, + "hideOthers": { + "message": "Versteek Ander" + }, + "showAll": { + "message": "Toon Alles" + }, + "quitBitwarden": { + "message": "Sluit Bitwarden Af" + }, + "valueCopied": { + "message": "$VALUE$ gekopieer", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Venster" + }, + "checkPassword": { + "message": "Gaan na of wagwoord blootgestel is." + }, + "passwordExposed": { + "message": "Hierdie wagwoord is $VALUE$ keer in databreuke blootgestel. U behoort dit te verander.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Hierdie wagwoord is in geen bekende databreuke gevind nie. Dit behoort veilig vir gebruik te wees." + }, + "baseDomain": { + "message": "Basisdomein", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Gasheer", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Presies" + }, + "startsWith": { + "message": "Begin met" + }, + "regEx": { + "message": "Gewone uitdrukking", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Ooreenkomsbespeuring", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Verstekooreenkomsbespeuring", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Tokkel Opsies" + }, + "organization": { + "message": "Organisasie", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Verstek" + }, + "exit": { + "message": "Verlaat" + }, + "showHide": { + "message": "Vertoon/Versteek", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Versteek na stelsellaai" + }, + "alwaysOnTop": { + "message": "Altyd Bo", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Bygewerk", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Wagwoord bygewerk", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Stuur Kluis Uit" + }, + "fileFormat": { + "message": "Lêerformaat" + }, + "warning": { + "message": "WAARSKUWING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Bevestig kluisuitstuur" + }, + "exportWarningDesc": { + "message": "Hierdie uitstuur bevat u kluisdata in ’n ongeënkripteerde formaat. U behoort dit nie oor onbeveiligde kanale (soos e-pos) te bewaar of verstuur nie. Skrap dit sodra u dit klaar gebruik het." + }, + "encExportKeyWarningDesc": { + "message": "Hierdie uitstuur vergrendel u data met u rekening se enkripsiesleutel. Indien u ooit u rekening se enkripsiesleitel wil verander moet u dit weer uitstuur aangesien u dan nie hierdie uitstuurlêer sal kan dekripteer nie." + }, + "encExportAccountWarningDesc": { + "message": "Rekeningenkripsiesleutels is uniek tot elke Bitwarden-gebruikersrekening, daarom kan u nie ’n geënkripteerde uitstuur in ’n ander rekening invoer nie." + }, + "noOrganizationsList": { + "message": "U behoort aan geen organisasies nie. Organisasies laat u toe om items op beveiligde wyse met ander gebruikers te deel." + }, + "noCollectionsInList": { + "message": "Daar is geen versamelings om te lys nie." + }, + "ownership": { + "message": "Eienaarskap" + }, + "whoOwnsThisItem": { + "message": "Wie besit hierdie item?" + }, + "strong": { + "message": "Sterk", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Goed", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Swak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Swak Hoofwagwoord" + }, + "weakMasterPasswordDesc": { + "message": "U gekose hoofwagwoord is swak. U moet ’n sterk hoofwagwoord (of ’n wagfrase) gebruik ten einde u Bitwarde-rekening te beveilig. Is u seker u wil hierdie wagwoord gebruik?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Ontgrendel met PIN" + }, + "setYourPinCode": { + "message": "Stel u PIN-kode in om Bitwarden te ontgrendel. U PIN-kode word heringestel indien u ooit volledig by die toep uitteken." + }, + "pinRequired": { + "message": "PIN-kode word vereis." + }, + "invalidPin": { + "message": "Ongeldige PIN-kode." + }, + "unlockWithWindowsHello": { + "message": "Ontgrendel met Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Bevestig vir Bitwarden." + }, + "unlockWithTouchId": { + "message": "Ontgrendel met Touch ID" + }, + "touchIdConsentMessage": { + "message": "ontgrendel u kluis" + }, + "noAutoPromptWindowsHello": { + "message": "Moenie by lansering vra vir Windows Hello nie." + }, + "noAutoPromptTouchId": { + "message": "Moenie by lansering vra vir Touch ID nie." + }, + "lockWithMasterPassOnRestart": { + "message": "Vergrendel by herbegin met hoofwagwoord" + }, + "preferences": { + "message": "Voorkeure" + }, + "enableMenuBar": { + "message": "Aktiveer Kieslysstaafikoon" + }, + "enableMenuBarDesc": { + "message": "Toon altyd ’n ikoon in die kieslysstaaf." + }, + "hideToMenuBar": { + "message": "Versteek na kieslysbalk" + }, + "selectOneCollection": { + "message": "U moet ten minste een versameling kies." + }, + "premiumUpdated": { + "message": "U het na premie opgegradeer." + }, + "restore": { + "message": "Stel terug" + }, + "premiumManageAlertAppStore": { + "message": "U kan u intekening vanuit die App Store bestuur. Wil u die App Store nou besoek?" + }, + "legal": { + "message": "Juridies", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Gebruiksvoorwaardes" + }, + "privacyPolicy": { + "message": "Privaatheidsbeleid" + }, + "unsavedChangesConfirmation": { + "message": "Is u seker u wil afsluit? Indien u nou afsluit sal u huidige inligting nie bewaar word nie." + }, + "unsavedChangesTitle": { + "message": "Onbewaarde Veranderinge" + }, + "clone": { + "message": "Kloon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Een of meer organisasiebeleide beïnvloed u genereerderinstellings." + }, + "vaultTimeoutAction": { + "message": "Kluis-uittelaksie" + }, + "vaultTimeoutActionLockDesc": { + "message": "Om toegang tot ’n vergendelde kluis te kry moet die hoofwagwoord weer ingevoer word." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Om toegang tot ’n uitgetekende kluis te kry moet u weer waarmerk." + }, + "lock": { + "message": "Vergrendel", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Asblik", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Deursoek Asblik" + }, + "permanentlyDeleteItem": { + "message": "Skrap item permanent" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Is u seker u wil hierdie item permanent skrap?" + }, + "permanentlyDeletedItem": { + "message": "Permanent geskrapte item" + }, + "restoreItem": { + "message": "Stel item terug" + }, + "restoreItemConfirmation": { + "message": "Is u seker u wil hierdie item terugstel?" + }, + "restoredItem": { + "message": "Teruggestelde item" + }, + "permanentlyDelete": { + "message": "Skrap permanent" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Deur uit te teken word alle toegang tot u kluis verwyder en word waarmerking na die uitteltydperk vereis. Is u seker u wil hierdie instelling gebruik?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Uittelaksiebevestiging" + }, + "enterpriseSingleSignOn": { + "message": "Onderneming-enkelaanteken" + }, + "setMasterPassword": { + "message": "Stel Hoofwagwoord" + }, + "ssoCompleteRegistration": { + "message": "Om aantekening met SSO te voltooi moet u ’n hoofwagwoord instel vir toegang tot en beskerming van u kluis." + }, + "newMasterPass": { + "message": "Nuwe hoofwagwoord" + }, + "confirmNewMasterPass": { + "message": "Bevestig nuwe hoofwagwoord" + }, + "masterPasswordPolicyInEffect": { + "message": "Een of meer organisasiebeleide stel die volgende eise aan u hoofwagwoord:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum ingewikkeldheidstelling van $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum lengte van $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Bevat een of meer hoofletterkarakters" + }, + "policyInEffectLowercase": { + "message": "Bevat een of meer kleinletterkarakters" + }, + "policyInEffectNumbers": { + "message": "Bevat een of meer syfers" + }, + "policyInEffectSpecial": { + "message": "Bevat een of meer van die volgende spesiale karakters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "U nuwe hoofwagwoord voldoen nie aan die beleidsvereistes nie." + }, + "acceptPolicies": { + "message": "Deur hierdie kassie af te merk stem u in tot die volgende:" + }, + "acceptPoliciesError": { + "message": "Gebruiksvoorwaardes en privaatheidsbeleid is nie erken nie." + }, + "enableBrowserIntegration": { + "message": "Aktiveer blaaierintegrasie" + }, + "enableBrowserIntegrationDesc": { + "message": "Blaaierintegrasie word gebruik vir biometrie in blaaier." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Blaaierintegrasie word nie ondersteun nie" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Ongelukkig word blaaierintegrasie tans slegs in die weergawe vir die Mac-toepwinkel ondersteun." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Blaaierintegrasie word nie ondersteun nie" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Ongelukkig word blaaierintegrasie tans nie in die weergawe vir die Windows-winkel ondersteun nie." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Vereis bevestiging vir blaaierintegrasie" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Aktiveer ’n bykomende sekuriteitsvlak deur ’n vingerafdrukfrase te vereis wanneer u rekenaar en blaaier gekoppel word. Wanneer geaktiveer moet u elke verbinding bevestig." + }, + "approve": { + "message": "Keur goed" + }, + "verifyBrowserTitle": { + "message": "Bevestig blaaierverbinding" + }, + "verifyBrowserDesc": { + "message": "Maak seker dat die getoonde vingerafdruk identies is aan dié wat in die blaaieruitbreiding vertoon word." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrie is geaktiveer" + }, + "biometricsNotEnabledDesc": { + "message": "Vir blaaierbiometrie moet werkskermbiometrie eers in instellings geaktiveer wees." + }, + "personalOwnershipSubmitError": { + "message": "Weens ’n ondernemingsbeleid mag u geen wagwoorde in u persoonlike kluis bewaar nie. Verander die eienaarskap na ’n organisasie en kies uit ’n van die beskikbare versamelings." + }, + "hintEqualsPassword": { + "message": "U wagwoordwenk kan nie dieselfde as u wagwoord wees nie." + }, + "personalOwnershipPolicyInEffect": { + "message": "’n Organisasiebeleid beïnvloed u eienaarskapopsies." + }, + "allSends": { + "message": "Alle Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Lêer" + }, + "sendTypeText": { + "message": "Teks" + }, + "searchSends": { + "message": "Deursoek Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Wysig Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My kluis" + }, + "text": { + "message": "Teks" + }, + "deletionDate": { + "message": "Skrapdatum" + }, + "deletionDateDesc": { + "message": "Die Send sal outomaties op die aangewese datum en tyd geskrap word.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Vervaldatum" + }, + "expirationDateDesc": { + "message": "Indien ingestel sal toegang tot hierdie Send op die aangewese datum en tyd verstryk.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maksimum toegangsaantal" + }, + "maxAccessCountDesc": { + "message": "Indien ingestel het gebruikers ne meer toegang tot hierdie Send sodra die maksimum aantal toegang bereik is.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Huidige toegangsaantal" + }, + "disableSend": { + "message": "Deaktiveer hierdie Send sodat niemand toegang daartoe het nie.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Vereis opsioneel ’n wagwoord vir gebruikers om toegang tot hierdie Send te verkry.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privaat notas oor hierdie Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send-skakel", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send-skakel", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Versteek die teks be verstek wanneer die Send gebruik word", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send geskep", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send gewysig", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send geskrap", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nuwe wagwoord" + }, + "whatTypeOfSend": { + "message": "Welke tipe Send is dit?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Skep Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Die teks wat u wil verstuur." + }, + "sendFileDesc": { + "message": "Die lêer wat u wil verstuur." + }, + "days": { + "message": "$DAYS$ dae", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dag" + }, + "custom": { + "message": "Pasgemaak" + }, + "deleteSendConfirmation": { + "message": "Is u seker u wil hierdie Send skrap?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopieer Send-skakel na knipbord", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kopieer die skakel om hierdie Send te deel tydens bewaar na my knipbord." + }, + "sendDisabled": { + "message": "Send gedeaktiveer", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "A.g.v. ’n ondernemingsbeleid kan u slegs ’n bestaande Send skrap.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopieer skakel" + }, + "disabled": { + "message": "Gedeaktiveer" + }, + "maxAccessCountReached": { + "message": "Maks toegangsaantal bereik" + }, + "expired": { + "message": "Verstreke" + }, + "pendingDeletion": { + "message": "Word geskrap" + }, + "webAuthnAuthenticate": { + "message": "Waarmerk WebAuthn" + }, + "hideEmail": { + "message": "Versteek my e-posadres vir ontvangers." + }, + "sendOptionsPolicyInEffect": { + "message": "Een of meer organisasiebeleide beïnvloed u Send-opsies." + }, + "emailVerificationRequired": { + "message": "Vereis e-posbevestiging" + }, + "emailVerificationRequiredDesc": { + "message": "U moet u e-pos bevestig om die funksie te gebruik." + }, + "passwordPrompt": { + "message": "Vra weer vir hoofwagwoord" + }, + "passwordConfirmation": { + "message": "Hoofwagwoordbevestiging" + }, + "passwordConfirmationDesc": { + "message": "Hierdie aksie is beskerm. Voer u hoofwagwoord in om u identiteit te bevestig om voort te gaan." + }, + "updatedMasterPassword": { + "message": "Hoofwagwoord bygewerk" + }, + "updateMasterPassword": { + "message": "Werk hoofwagwoord by" + }, + "updateMasterPasswordWarning": { + "message": "U hoofwagwoord is onlangs deur ’n administrateur in u organisasie verander. Om toegang tot u kluis te verkry moet u dit nóú bywerk. Deur voort te gaan word u uit u huidige sessie geteken, waarna u weer sal moet aanteken. Aktiewe sessies op ander toestelle kan vir tot ’n uur steeds aktief bly." + }, + "hours": { + "message": "Uur" + }, + "minutes": { + "message": "Minute" + }, + "vaultTimeoutPolicyInEffect": { + "message": "U organisasiebeleide beïnvloed u kluisuitelling. Maksimum toegelate kluisuittelling is $HOURS$ uur en $MINUTES$ minuut(e)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "U kluisuittelling oorskry die beperkinge wat deur u organisasie daargestel is." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Outomatiese inskrywing" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Hierdie organisasie het ’n ondernemingsbeleid wat u outomaties inskryf in die terugstel van u wagwoord. Inskrywing stel organisasiebeheerders in staat om u hoofwagwoord te wysig." + }, + "vaultExportDisabled": { + "message": "Kluisuitstuur gedeaktiveer" + }, + "personalVaultExportPolicyInEffect": { + "message": "Een of meer organisasiebeleide verhoed u om u persoonlike kluis uit te stuur." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Verwyder hoofwagwoord" + }, + "removedMasterPassword": { + "message": "Hoofwagwoord is verwyder." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ gebruik SSO met ’n sleutelbediener op ’n eie gasheer. ’n Hoofwagwoord word nie meer vereis vir aantekening vir lede van hierdie organisasie nie.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Verlaat organisasie" + }, + "leaveOrganizationConfirmation": { + "message": "Is u seker u wil hierdie organisasie verlaat?" + }, + "leftOrganization": { + "message": "U het die organisasie verlaat." + }, + "ssoKeyConnectorUnavailable": { + "message": "Kan nie die sleutelkoppelstuk bereik nie, probeer later weer." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/az/messages.json b/apps/desktop/src/locales/az/messages.json new file mode 100644 index 0000000000..7ab6a7428c --- /dev/null +++ b/apps/desktop/src/locales/az/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtrlər" + }, + "allItems": { + "message": "Bütün elementlər" + }, + "favorites": { + "message": "Sevimlilər" + }, + "types": { + "message": "Növlər" + }, + "typeLogin": { + "message": "Giriş" + }, + "typeCard": { + "message": "Kart" + }, + "typeIdentity": { + "message": "Kimlik" + }, + "typeSecureNote": { + "message": "Təhlükəsizlik qeydi" + }, + "folders": { + "message": "Qovluqlar" + }, + "collections": { + "message": "Kolleksiyalar" + }, + "searchVault": { + "message": "Anbarda axtar" + }, + "addItem": { + "message": "Element əlavə et" + }, + "shared": { + "message": "Paylaşılan" + }, + "share": { + "message": "Paylaş" + }, + "moveToOrganization": { + "message": "Təşkilata daşı" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ $ORGNAME$ şirkətinə daşındı", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Bu elementi daşımaq istədiyiniz təşkilatı seçin. Bir təşkilata daşımaq, elementin sahibliyini də həmin təşkilata daşıyacaq. Daşıdıqdan sonra bu elementə birbaşa sahibliyiniz olmayacaq." + }, + "attachments": { + "message": "Qoşmalar" + }, + "viewItem": { + "message": "Elementə bax" + }, + "name": { + "message": "Ad" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Yeni URI" + }, + "username": { + "message": "İstifadəçi adı" + }, + "password": { + "message": "Parol" + }, + "passphrase": { + "message": "Uzun ifadə" + }, + "editItem": { + "message": "Elementə düzəliş et" + }, + "emailAddress": { + "message": "E-poçt ünvanı" + }, + "verificationCodeTotp": { + "message": "Təsdiqləmə kodu (TOTP)" + }, + "website": { + "message": "Veb sayt" + }, + "notes": { + "message": "Notlar" + }, + "customFields": { + "message": "Özəl sahələr" + }, + "launch": { + "message": "Başlat" + }, + "copyValue": { + "message": "Dəyəri kopyala", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Lövhəyə kopyalananda kiçilt" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Elementin verilənlərini lövhəyə kopyalayarkən kiçilt." + }, + "toggleVisibility": { + "message": "Görünməni aç/bağla" + }, + "toggleCollapse": { + "message": "Yığcam etməni aç/bağla", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kart sahibinin adı" + }, + "number": { + "message": "Nömrə" + }, + "brand": { + "message": "Brend" + }, + "expiration": { + "message": "Bitmə vaxtı" + }, + "securityCode": { + "message": "Təhlükəsizlik kodu" + }, + "identityName": { + "message": "Kimlik adı" + }, + "company": { + "message": "Şirkət" + }, + "ssn": { + "message": "Sosial təhlükəsizlik nömrəsi" + }, + "passportNumber": { + "message": "Pasport nömrəsi" + }, + "licenseNumber": { + "message": "Lisenziya nömrəsi" + }, + "email": { + "message": "E-poçt" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Ünvan" + }, + "premiumRequired": { + "message": "Premium üzvlük lazımdır" + }, + "premiumRequiredDesc": { + "message": "Bu özəlliyi istifadə etmək üçün premium üzvlük lazımdır." + }, + "errorOccurred": { + "message": "Bir xəta baş verdi." + }, + "error": { + "message": "Xəta" + }, + "january": { + "message": "Yanvar" + }, + "february": { + "message": "Fevral" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "Aprel" + }, + "may": { + "message": "May" + }, + "june": { + "message": "İyun" + }, + "july": { + "message": "İyul" + }, + "august": { + "message": "Avqust" + }, + "september": { + "message": "Sentyabr" + }, + "october": { + "message": "Oktyabr" + }, + "november": { + "message": "Noyabr" + }, + "december": { + "message": "Dekabr" + }, + "ex": { + "message": "məs.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Başlıq" + }, + "mr": { + "message": "Cənab" + }, + "mrs": { + "message": "Xanım" + }, + "ms": { + "message": "Hörmətli" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Son istifadə ayı" + }, + "expirationYear": { + "message": "Son istifadə ili" + }, + "select": { + "message": "Seçin" + }, + "other": { + "message": "Digər" + }, + "generatePassword": { + "message": "Parol yarat" + }, + "type": { + "message": "Növ" + }, + "firstName": { + "message": "Ad" + }, + "middleName": { + "message": "Orta ad" + }, + "lastName": { + "message": "Soyad" + }, + "fullName": { + "message": "Tam ad" + }, + "address1": { + "message": "Ünvan 1" + }, + "address2": { + "message": "Ünvan 2" + }, + "address3": { + "message": "Ünvan 3" + }, + "cityTown": { + "message": "Şəhər/Rayon" + }, + "stateProvince": { + "message": "Ölkə/Əyalət" + }, + "zipPostalCode": { + "message": "Zip/ Poçt kodu" + }, + "country": { + "message": "Ölkə" + }, + "save": { + "message": "Saxla" + }, + "cancel": { + "message": "İmtina" + }, + "delete": { + "message": "Sil" + }, + "favorite": { + "message": "Sevimli" + }, + "edit": { + "message": "Düzəliş et" + }, + "authenticatorKeyTotp": { + "message": "Kimlik təsdiqləyici açarı (TOTP)" + }, + "folder": { + "message": "Qovluq" + }, + "newCustomField": { + "message": "Yeni özəl sahə" + }, + "value": { + "message": "Dəyər" + }, + "dragToSort": { + "message": "Sıralamaq üçün sürüşdürün" + }, + "cfTypeText": { + "message": "Mətn" + }, + "cfTypeHidden": { + "message": "Gizli" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Əlaqə yaradıldı", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Əlaqəli dəyər", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Çıxart" + }, + "nameRequired": { + "message": "Ad lazımdır." + }, + "addedItem": { + "message": "Element əlavə edildi" + }, + "editedItem": { + "message": "Elementə düzəliş edildi" + }, + "deleteItem": { + "message": "Elementi sil" + }, + "deleteFolder": { + "message": "Qovluğu sil" + }, + "deleteAttachment": { + "message": "Qoşmanı sil" + }, + "deleteItemConfirmation": { + "message": "Həqiqətən tullantı qutusuna göndərmək istəyirsiniz?" + }, + "deletedItem": { + "message": "Element tullantı qutusuna göndərildi" + }, + "overwritePasswordConfirmation": { + "message": "Hazırkı parolun üzərinə yazmaq istədiyinizə əminsiniz?" + }, + "overwriteUsername": { + "message": "İstifadəçi adının üzərinə yaz" + }, + "overwriteUsernameConfirmation": { + "message": "Hazırkı istifadəçi adının üzərinə yazmaq istədiyinizə əminsiniz?" + }, + "noneFolder": { + "message": "Qovluq yoxdur", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Qovluq əlavə et" + }, + "editFolder": { + "message": "Qovluğa düzəliş et" + }, + "regeneratePassword": { + "message": "Parolu yenidən yarat" + }, + "copyPassword": { + "message": "Parolu kopyala" + }, + "copyUri": { + "message": "URI-ni kopyala" + }, + "copyVerificationCodeTotp": { + "message": "Təsdiqləmə kodunu kopyala (TOTP)" + }, + "length": { + "message": "Uzunluq" + }, + "numWords": { + "message": "Söz sayı" + }, + "wordSeparator": { + "message": "Söz ayırıcı" + }, + "capitalize": { + "message": "İlk hərfi böyük yaz", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Rəqəm əlavə et" + }, + "close": { + "message": "Bağla" + }, + "minNumbers": { + "message": "Minimum rəqəm" + }, + "minSpecial": { + "message": "Minimum simvol", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Anlaşılmaz simvollardan çəkinin" + }, + "searchCollection": { + "message": "Kolleksiya axtar" + }, + "searchFolder": { + "message": "Qovluq axtar" + }, + "searchFavorites": { + "message": "Sevimliləri axtar" + }, + "searchType": { + "message": "Axtarış növü", + "description": "Search item type" + }, + "newAttachment": { + "message": "Yeni qoşma əlavə et" + }, + "deletedAttachment": { + "message": "Qoşma silindi" + }, + "deleteAttachmentConfirmation": { + "message": "Bu qoşmanı silmək istədiyinizə əminsiniz?" + }, + "attachmentSaved": { + "message": "Qoşma saxlanıldı." + }, + "file": { + "message": "Fayl" + }, + "selectFile": { + "message": "Fayl seçin." + }, + "maxFileSize": { + "message": "Maksimal fayl həcmi 500 MB-dır." + }, + "updateKey": { + "message": "Şifrələmə açarınızı yeniləyənə qədər bu özəlliyi istifadə edə bilməzsiniz." + }, + "editedFolder": { + "message": "Qovluğa düzəliş edildi" + }, + "addedFolder": { + "message": "Qovluq əlavə edildi" + }, + "deleteFolderConfirmation": { + "message": "Bu qovluğu silmək istədiyinizə əminsiniz?" + }, + "deletedFolder": { + "message": "Qovluq silindi" + }, + "loginOrCreateNewAccount": { + "message": "Təhlükəsiz anbarınıza müraciət etmək üçün giriş edin və ya yeni bir hesab yaradın." + }, + "createAccount": { + "message": "Hesab yarat" + }, + "logIn": { + "message": "Giriş et" + }, + "submit": { + "message": "Göndər" + }, + "masterPass": { + "message": "Ana parol" + }, + "masterPassDesc": { + "message": "Ana parol, anbarınıza müraciət etmək üçün istifadə edəcəyiniz paroldur. Ana parolu yadda saxlamaq çox vacibdir. Unutsanız, parolu bərpa etməyin heç bir yolu yoxdur." + }, + "masterPassHintDesc": { + "message": "Ana parol məsləhəti, unutduğunuz parolunuzu xatırlamağınıza kömək edir." + }, + "reTypeMasterPass": { + "message": "Ana parolu yenidən yaz" + }, + "masterPassHint": { + "message": "Ana parol məsləhəti (ixtiyari)" + }, + "settings": { + "message": "Tənzimləmələr" + }, + "passwordHint": { + "message": "Parol məsləhəti" + }, + "enterEmailToGetHint": { + "message": "Ana parol məsləhətini alacağınız hesabınızın e-poçt ünvanını daxil edin." + }, + "getMasterPasswordHint": { + "message": "Ana parol üçün məsləhət alın" + }, + "emailRequired": { + "message": "E-poçt ünvanı lazımdır." + }, + "invalidEmail": { + "message": "Etibarsız e-poçt ünvanı." + }, + "masterPassRequired": { + "message": "Ana parol lazımdır." + }, + "masterPassLength": { + "message": "Ana parol ən azı 8 simvol uzunluğunda olmalıdır." + }, + "masterPassDoesntMatch": { + "message": "Ana parol təsdiqləməsi uyğun gəlmir." + }, + "newAccountCreated": { + "message": "Yeni hesabınız yaradıldı! İndi giriş edə bilərsiniz." + }, + "masterPassSent": { + "message": "Ana parol məsləhətini ehtiva edən bir e-poçt göndərdik." + }, + "unexpectedError": { + "message": "Gözlənilməz bir səhv baş verdi." + }, + "itemInformation": { + "message": "Element məlumatları" + }, + "noItemsInList": { + "message": "Siyahılanacaq heç bir element yoxdur." + }, + "sendVerificationCode": { + "message": "E-poçtunuza bir təsdiqləmə kodu göndərin" + }, + "sendCode": { + "message": "Kod göndər" + }, + "codeSent": { + "message": "Kod göndərildi" + }, + "verificationCode": { + "message": "Təsdiqləmə kodu" + }, + "confirmIdentity": { + "message": "Davam etmək üçün kimliyinizi təsdiqləyin." + }, + "verificationCodeRequired": { + "message": "Təsdiq kodu lazımdır." + }, + "invalidVerificationCode": { + "message": "Etibarsız təsdiqləmə kodu" + }, + "continue": { + "message": "Davam" + }, + "enterVerificationCodeApp": { + "message": "Kimlik təsdiqləyici tətbiqindən 6 rəqəmli təsdiqləmə kodunu daxil edin." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ ünvanına göndərilən e-poçtdakı 6 rəqəmli təsdiqləmə kodunu daxil edin.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Təsdiqləmə poçtu $EMAIL$ ünvanına göndərildi.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Məni xatırla" + }, + "sendVerificationCodeEmailAgain": { + "message": "Təsdiqləmə kodu olan e-poçtu yenidən göndər" + }, + "useAnotherTwoStepMethod": { + "message": "Başqa bir iki mərhələli giriş metodu istifadə edin" + }, + "insertYubiKey": { + "message": "\"YubiKey\"i kompüterinizin USB portuna taxın, daha sonra düyməsinə toxunun." + }, + "insertU2f": { + "message": "Təhlükəsizlik açarını kompüterinizin USB portun taxın. Düyməsi varsa toxunun." + }, + "recoveryCodeDesc": { + "message": "İki mərhələli təsdiqləmə təchizatçılarına müraciəti itirmisiniz? Bərpa kodunuzu istifadə edərək hesabınızdakı bütün iki mərhələli təchizatçıları sıradan çıxara bilərsiniz." + }, + "recoveryCodeTitle": { + "message": "Bərpa kodu" + }, + "authenticatorAppTitle": { + "message": "Kimlik təsdiqləyici tətbiqi" + }, + "authenticatorAppDesc": { + "message": "Vaxt əsaslı təsdiqləmə kodları yaratmaq üçün (Authy və ya Google Authenticator kimi) kimlik təsdiqləyici tətbiq istifadə edin.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP təhlükəsizlik açarı" + }, + "yubiKeyDesc": { + "message": "Hesabınıza müraciət etmək üçün bir YubiKey istifadə edin. YubiKey 4, 4 Nano, 4C və NEO cihazları ilə işləyir." + }, + "duoDesc": { + "message": "Duo Security ilə təsdiqləmək üçün Duo Mobile tətbiqi, SMS, telefon zəngi və ya U2F təhlükəsizlik açarını istifadə edin.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Təşkilatınızını Duo Security ilə təsdiqləmək üçün Duo Mobile tətbiqi, SMS, telefon zəngi və ya U2F təhlükəsizlik açarını istifadə edin.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Hesabınıza müraciət etmək üçün hər hansısa bir WebAuthn fəallaşdırılan təhlükəsizlik açarı istifadə edin." + }, + "emailTitle": { + "message": "E-poçt" + }, + "emailDesc": { + "message": "Təsdiqləmə kodları e-poçt ünvanınıza göndəriləcək." + }, + "loginUnavailable": { + "message": "Giriş edilə bilmir" + }, + "noTwoStepProviders": { + "message": "Bu hesabın iki mərhələli giriş özəlliyi fəaldır, ancaq, konfiqurasiya edilmiş iki mərhələli təchizatçıların heç biri bu cihaz tərəfindən dəstəklənmir." + }, + "noTwoStepProviders2": { + "message": "Zəhmət olmasa daha yaxşı cihazlar (tətbiq təsdiqləyici tətbiqi) arasında dəstəklənən əlavə təchizatçıları əlavə edin." + }, + "twoStepOptions": { + "message": "İki mərhələli giriş seçimləri" + }, + "selfHostedEnvironment": { + "message": "Öz-özünə sahiblik edən mühit" + }, + "selfHostedEnvironmentFooter": { + "message": "Öz-özünə sahiblik edən Bitwarden quraşdırmasının baza URL-sini müəyyənləşdirin." + }, + "customEnvironment": { + "message": "Özəl mühit" + }, + "customEnvironmentFooter": { + "message": "Qabaqcıl istifadəçilər üçündür. Hər xidmətin baza URL-sini müstəqil olaraq müəyyənləşdirə bilərsiniz." + }, + "baseUrl": { + "message": "Server URL-si" + }, + "apiUrl": { + "message": "API server URL-si" + }, + "webVaultUrl": { + "message": "Veb anbar server URL-si" + }, + "identityUrl": { + "message": "Kimlik server URL-si" + }, + "notificationsUrl": { + "message": "Bildiriş server URL-si" + }, + "iconsUrl": { + "message": "Nişan server URL-si" + }, + "environmentSaved": { + "message": "Mühit URL-ləri saxlanıldı." + }, + "ok": { + "message": "Oldu" + }, + "yes": { + "message": "Bəli" + }, + "no": { + "message": "Xeyr" + }, + "overwritePassword": { + "message": "Parolun üzərinə yaz" + }, + "learnMore": { + "message": "Daha ətraflı" + }, + "featureUnavailable": { + "message": "Özəllik əlçatmazdır" + }, + "loggedOut": { + "message": "Çıxış edildi" + }, + "loginExpired": { + "message": "Seansın müddəti bitdi." + }, + "logOutConfirmation": { + "message": "Çıxış etmək istədiyinizə əminsiniz?" + }, + "logOut": { + "message": "Çıxış" + }, + "addNewLogin": { + "message": "Yeni hesab əlavə et" + }, + "addNewItem": { + "message": "Yeni element əlavə et" + }, + "addNewFolder": { + "message": "Yeni qovluq əlavə et" + }, + "view": { + "message": "Bax" + }, + "account": { + "message": "Hesab" + }, + "loading": { + "message": "Yüklənir..." + }, + "lockVault": { + "message": "Anbarı kilidlə" + }, + "passwordGenerator": { + "message": "Parol yaradıcı" + }, + "contactUs": { + "message": "Bizimlə əlaqə" + }, + "getHelp": { + "message": "Kömək alın" + }, + "fileBugReport": { + "message": "Xəta hesabatı göndərin" + }, + "blog": { + "message": "Bloq" + }, + "followUs": { + "message": "Bizi izləyin" + }, + "syncVault": { + "message": "Anbarı eyniləşdir" + }, + "changeMasterPass": { + "message": "Ana parolu dəyişdir" + }, + "changeMasterPasswordConfirmation": { + "message": "Ana parolunuzu bitwarden.com veb anbarında dəyişdirə bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?" + }, + "fingerprintPhrase": { + "message": "Barmaq izi ifadəsi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Hesabınızın barmaq izi ifadəsi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Veb anbara get" + }, + "getMobileApp": { + "message": "Mobil tətbiqə get" + }, + "getBrowserExtension": { + "message": "Səyyah genişləndirməsini əldə et" + }, + "syncingComplete": { + "message": "Eyniləşdirmə tamamlandı" + }, + "syncingFailed": { + "message": "Uğursuz eyniləşdirmə" + }, + "yourVaultIsLocked": { + "message": "Anbarınız kilidlənib. Davam etmək üçün ana parolunuzu təsdiqləyin." + }, + "unlock": { + "message": "Kilidi aç" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ üzərində $EMAIL$ kimi giriş edildi.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Etibarsız ana parol" + }, + "twoStepLoginConfirmation": { + "message": "İki mərhələli giriş, təhlükəsizlik açarı, kimlik təsdiqləyici tətbiq, SMS, telefon zəngi və ya e-poçt kimi digər cihazlarla girişinizi təsdiqləməyinizi tələb edərək hesabınızı daha da təhlükəsiz edir. İki mərhələli giriş, bitwarden.com veb anbarında fəallaşdırıla bilər. Veb saytı indi ziyarət etmək istəyirsiniz?" + }, + "twoStepLogin": { + "message": "İki mərhələli giriş" + }, + "vaultTimeout": { + "message": "Anbara müraciət bitəcək" + }, + "vaultTimeoutDesc": { + "message": "Anbara müraciətin bitəcəyi vaxtı seçin və seçilən əməliyyatı icra edin." + }, + "immediately": { + "message": "Dərhal" + }, + "tenSeconds": { + "message": "10 saniyə" + }, + "twentySeconds": { + "message": "20 saniyə" + }, + "thirtySeconds": { + "message": "30 saniyə" + }, + "oneMinute": { + "message": "1 dəqiqə" + }, + "twoMinutes": { + "message": "2 dəqiqə" + }, + "fiveMinutes": { + "message": "5 dəqiqə" + }, + "fifteenMinutes": { + "message": "15 dəqiqə" + }, + "thirtyMinutes": { + "message": "30 dəqiqə" + }, + "oneHour": { + "message": "1 saat" + }, + "fourHours": { + "message": "4 saat" + }, + "onIdle": { + "message": "Sistem boşda olanda" + }, + "onSleep": { + "message": "Sistem yatanda" + }, + "onLocked": { + "message": "Sistem kilidlənəndə" + }, + "onRestart": { + "message": "Yenidən başladılanda" + }, + "never": { + "message": "Heç vaxt" + }, + "security": { + "message": "Təhlükəsizlik" + }, + "clearClipboard": { + "message": "Lövhəni təmizlə", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Kopyalanmış dəyərləri lövhədən avtomatik təmizlə.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Veb sayt nişanlarını sıradan çıxart" + }, + "disableFaviconDesc": { + "message": "Veb sayt nişanları, anbarınızda hər bir giriş elementinin yanında tanımağınıza kömək edən bir təsvir təqdim edir." + }, + "enableMinToTray": { + "message": "Bildiriş nişanına kiçildin" + }, + "enableMinToTrayDesc": { + "message": "Pəncərə kiçildiləndə, bildiriş sahəsində bir nişan göstər." + }, + "enableMinToMenuBar": { + "message": "Menyu sətrinə kiçilt" + }, + "enableMinToMenuBarDesc": { + "message": "Pəncərəni kiçildəndə, menyu sətrində bir nişan göstər." + }, + "enableCloseToTray": { + "message": "Bildiriş nişanına bağla" + }, + "enableCloseToTrayDesc": { + "message": "Pəncərə bağlananda, bildiriş sahəsində bir nişan göstər." + }, + "enableCloseToMenuBar": { + "message": "Menyu sətrini bağla" + }, + "enableCloseToMenuBarDesc": { + "message": "Pəncərəni bağlananda, menyu sətrində bir nişan göstər." + }, + "enableTray": { + "message": "Bildiriş sahəsi nişanını fəallaşdır" + }, + "enableTrayDesc": { + "message": "Bildiriş sahəsində həmişə bir nişan göstər." + }, + "startToTray": { + "message": "Bildiriş sahəsi nişanı kimi başlat" + }, + "startToTrayDesc": { + "message": "Tətbiq ilk başladılanda, yalnız bildiriş sahəsi nişanı görünsün." + }, + "startToMenuBar": { + "message": "Menyu sətrini başlat" + }, + "startToMenuBarDesc": { + "message": "Tətbiq ilk başladılanda, menyu sətri sadəcə nişan kimi görünsün." + }, + "openAtLogin": { + "message": "Giriş ediləndə avtomatik başlat" + }, + "openAtLoginDesc": { + "message": "Giriş ediləndə Bitwarden masaüstü tətbiqini avtomatik başlat." + }, + "alwaysShowDock": { + "message": "\"Dock\"da həmişə göstər" + }, + "alwaysShowDockDesc": { + "message": "Menyu sətrinə kiçildiləndə belə Bitwarden nişanını \"Dock\"da göstər." + }, + "confirmTrayTitle": { + "message": "Bildiriş sahəsi nişanını ləğv et" + }, + "confirmTrayDesc": { + "message": "Bu tənzimləməni ləğv etsəniz, bütün əlaqəli tənzimləmələr də ləğv ediləcək." + }, + "language": { + "message": "Dil" + }, + "languageDesc": { + "message": "Tətbiq tərəfindən istifadə edilən dili dəyişdirin. Yenidən başlatma lazımdır." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Tətbiqin rəng temasını dəyişdirin." + }, + "dark": { + "message": "Tünd", + "description": "Dark color" + }, + "light": { + "message": "Açıq", + "description": "Light color" + }, + "copy": { + "message": "Kopyala", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Yeniləmələri yoxla" + }, + "version": { + "message": "Versiya $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Yeniləmək üçün yenidən başlat" + }, + "restartToUpdateDesc": { + "message": "$VERSION_NUM$ versiyası quraşdırılmağa hazırdır. Quraşdırmanı tamamlamaq üçün tətbiqi yenidən başlatmalısınız. Yenidən başladıb indi yeniləmək istəyirsiniz?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Yeniləmə mövcuddur" + }, + "updateAvailableDesc": { + "message": "Bir yeniləmə tapıldı. İndi endirmək istəyirsiniz?" + }, + "restart": { + "message": "Yenidən başlat" + }, + "later": { + "message": "Sonra" + }, + "noUpdatesAvailable": { + "message": "Hazırda heç bir yeniləmə yoxdur. Ən son versiyanı istifadə edirsiniz." + }, + "updateError": { + "message": "Yeniləmə xətası" + }, + "unknown": { + "message": "Bilinməyən" + }, + "copyUsername": { + "message": "İstifadəçi adını kopyala" + }, + "copyNumber": { + "message": "Nömrəni kopyala", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Təhlükəsizlik kodunu kopyala", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium üzvlük" + }, + "premiumManage": { + "message": "Üzvlüyü idarə edin" + }, + "premiumManageAlert": { + "message": "Üzvlüyünüzü bitwarden.com veb anbarında idarə edə bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?" + }, + "premiumRefresh": { + "message": "Üzvlüyü təzələ" + }, + "premiumNotCurrentMember": { + "message": "Hazırda premium bir üzvlüyünüz yoxdur." + }, + "premiumSignUpAndGet": { + "message": "Premium üzvlük üçün qeydiyyatdan keçin və bunları əldə edin:" + }, + "premiumSignUpStorage": { + "message": "Fayl qoşmaları üçün 1 GB şifrələnmiş saxlama sahəsi." + }, + "premiumSignUpTwoStep": { + "message": "YubiKey, FIDO U2F və Duo kimi iki mərhələli giriş seçimləri." + }, + "premiumSignUpReports": { + "message": "Anbarınızın təhlükəsiyini təmin etmək üçün parol gigiyenası, hesab sağlamlığı və verilənlərin pozulması hesabatları." + }, + "premiumSignUpTotp": { + "message": "Anbarınızdakı hesablar üçün TOTP təsdiqləmə kodu (2FA) yaradıcısı." + }, + "premiumSignUpSupport": { + "message": "Prioritet müştəri dəstəyi." + }, + "premiumSignUpFuture": { + "message": "Bütün gələcək premium özəlliklər. Daha çoxu tezliklə!" + }, + "premiumPurchase": { + "message": "Premium satın al" + }, + "premiumPurchaseAlert": { + "message": "Premium üzvlüyü bitwarden.com veb anbarında satın ala bilərsiniz. İndi saytı ziyarət etmək istəyirsiniz?" + }, + "premiumCurrentMember": { + "message": "Premium üzvsünüz!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden-i dəstəklədiyiniz üçün təşəkkürlər." + }, + "premiumPrice": { + "message": "Hamısı sadəcə ildə $PRICE$!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Təzələmə tamamlandı" + }, + "passwordHistory": { + "message": "Parol tarixçəsi" + }, + "clear": { + "message": "Təmizlə", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Siyahılanacaq heç bir parol yoxdur." + }, + "undo": { + "message": "Geri al" + }, + "redo": { + "message": "Təkrarla" + }, + "cut": { + "message": "Kəs", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Yapışdır", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Hamısını seç" + }, + "zoomIn": { + "message": "Yaxınlaşdır" + }, + "zoomOut": { + "message": "Uzaqlaşdır" + }, + "resetZoom": { + "message": "Yaxınlaşdırmanı sıfırla" + }, + "toggleFullScreen": { + "message": "Tam ekranı aç/bağla" + }, + "reload": { + "message": "Təkrar yüklə" + }, + "toggleDevTools": { + "message": "Tərtibatçı alətlərini aç/bağla" + }, + "minimize": { + "message": "Kiçilt", + "description": "Minimize window" + }, + "zoom": { + "message": "Yaxınlaşdır" + }, + "bringAllToFront": { + "message": "Tamamını Önə Gətir", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Bitwarden haqqında" + }, + "services": { + "message": "Xidmətlər" + }, + "hideBitwarden": { + "message": "Bitwarden-i gizlət" + }, + "hideOthers": { + "message": "Digərlərini gizlət" + }, + "showAll": { + "message": "Hamısını göstər" + }, + "quitBitwarden": { + "message": "Bitwarden-dən çıx" + }, + "valueCopied": { + "message": "$VALUE$ kopyalandı", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Kömək" + }, + "window": { + "message": "Pəncərə" + }, + "checkPassword": { + "message": "Parolunuzun oğurlanıb oğurlanmadığını yoxlayın." + }, + "passwordExposed": { + "message": "Bu parol, məlumat pozuntularında $VALUE$ dəfə üzə çıxıb. Dəyişdirməyi məsləhət görürük.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Bu parol, məlumat pozuntularında qeydə alınmayıb. Rahatlıqla istifadə edə bilərsiniz." + }, + "baseDomain": { + "message": "Baza domeni", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domen adı", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tam" + }, + "startsWith": { + "message": "Başlayır" + }, + "regEx": { + "message": "Müntəzəm ifadə", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Uyğunluq aşkarlaması", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "İlkin uyğunluq aşkarlaması", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Seçimləri aç/bağla" + }, + "organization": { + "message": "Təşkilat", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "İlkin" + }, + "exit": { + "message": "Çıxış" + }, + "showHide": { + "message": "Göstər / gizlət", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Bildiriş nişanına gizlət" + }, + "alwaysOnTop": { + "message": "Həmişə üstdə", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Yeniləndi", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parol yeniləndi", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Anbarı ixrac et" + }, + "fileFormat": { + "message": "Fayl formatı" + }, + "warning": { + "message": "XƏBƏRDARLIQ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Anbarın ixracını təsdiqləyin" + }, + "exportWarningDesc": { + "message": "Bu ixrac faylındakı anbar verilənləriniz şifrələnməmiş formatdadır. İxrac edilən faylı saxlamamalı və etibarsız yollarla (e-poçt kimi) göndərməməlisiniz. Bu faylı işiniz bitdikdən sonra dərhal silin." + }, + "encExportKeyWarningDesc": { + "message": "Bu ixrac faylı, hesabınızın şifrələmə açarını istifadə edərək verilənlərinizi şifrələyir. Hesabınızın şifrələmə açarını döndərsəniz, bu ixrac faylının şifrəsini aça bilməyəcəyiniz üçün yenidən ixrac etməli olacaqsınız." + }, + "encExportAccountWarningDesc": { + "message": "Hesab şifrələmə açarları, hər Bitwarden istifadəçi hesabı üçün unikaldır, buna görə də şifrələnmiş bir ixracı, fərqli bir hesaba idxal edə bilməzsiniz." + }, + "noOrganizationsList": { + "message": "Heç bir təşkilata aid deyilsiniz. Təşkilatlar, elementlərinizi digər istifadəçilərlə təhlükəsiz şəkildə paylaşmağınızı təmin edir." + }, + "noCollectionsInList": { + "message": "Siyahılanacaq heç bir kolleksiya yoxdur." + }, + "ownership": { + "message": "Sahiblik" + }, + "whoOwnsThisItem": { + "message": "Bu elementin sahibi kimdir?" + }, + "strong": { + "message": "Güclü", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Yaxşı", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Zəif", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Zəif ana parol" + }, + "weakMasterPasswordDesc": { + "message": "Seçdiyiniz ana parol zəifdir. Bitwarden hesabınızı daha yaxşı qorumaq üçün güclü bir ana parol (və ya uzun ifadə) istifadə etməlisiniz. Bu ana parol istifadə etmək istədiyinizə əminsiniz?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "PIN ilə kilidi açın" + }, + "setYourPinCode": { + "message": "Bitwarden-in kilidini açmaq üçün PIN kod tənzimləyin. Hər tətbiqdən tam çıxış edəndə PIN tənzimləmələriniz sıfırlanacaq." + }, + "pinRequired": { + "message": "PIN kod lazımdır." + }, + "invalidPin": { + "message": "Etibarsız PIN kod." + }, + "unlockWithWindowsHello": { + "message": "Windows Hello ilə kilidi aç" + }, + "windowsHelloConsentMessage": { + "message": "Bitwarden üçün təsdiqlə." + }, + "unlockWithTouchId": { + "message": "Touch ID kilidini aç" + }, + "touchIdConsentMessage": { + "message": "anbarınızın kilidini açın" + }, + "noAutoPromptWindowsHello": { + "message": "Açılışda Windows Hello üçün soruşma." + }, + "noAutoPromptTouchId": { + "message": "Açılışda Touch ID üçün soruşma." + }, + "lockWithMasterPassOnRestart": { + "message": "Yenidən başladılanda ana parol ilə kilidlə" + }, + "preferences": { + "message": "Tercihlər" + }, + "enableMenuBar": { + "message": "Menyu sətri nişanını fəallaşdır" + }, + "enableMenuBarDesc": { + "message": "Menyu sətrində həmişə bir nişan göstər." + }, + "hideToMenuBar": { + "message": "Menyu sətrini gizlət" + }, + "selectOneCollection": { + "message": "Ən azı bir kolleksiya seçməlisiniz." + }, + "premiumUpdated": { + "message": "Premium-a yüksəltdiniz." + }, + "restore": { + "message": "Bərpa et" + }, + "premiumManageAlertAppStore": { + "message": "Abunəliyinizi App Store-dan idarə edə bilərsiniz. App Store-u indi ziyarət etmək istəyirsiniz?" + }, + "legal": { + "message": "Qanuni", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Xidmət Şərtləri" + }, + "privacyPolicy": { + "message": "Gizlilik Siyasəti" + }, + "unsavedChangesConfirmation": { + "message": "Tərk etmək istədiyinizə əminsiniz? Əgər indi tərk etsəniz, hazırkı məlumatlarınız saxlanılmayacaq." + }, + "unsavedChangesTitle": { + "message": "Saxlanılmamış dəyişikliklər" + }, + "clone": { + "message": "Klonla" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasətləri yaradıcı seçimlərinizə təsir edir." + }, + "vaultTimeoutAction": { + "message": "Anbara müraciət vaxtının bitmə əməliyyatı" + }, + "vaultTimeoutActionLockDesc": { + "message": "Kilidli bir anbar, təkrar müraciət etmək üçün ana parolunuzu yenidən yazmağınızı tələb edir." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Çıxış edilmiş bir anbar, təkrar müraciət etmək üçün yenidən kimlik təsdiqləmə tələb edir." + }, + "lock": { + "message": "Kilidlə", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Tullantı qutusu", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Tullantı qutusunda axtar" + }, + "permanentlyDeleteItem": { + "message": "Elementi birdəfəlik sil" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Bu elementi birdəfəlik silmək istədiyinizə əminsiniz?" + }, + "permanentlyDeletedItem": { + "message": "Element birdəfəlik silindi" + }, + "restoreItem": { + "message": "Elementi bərpa et" + }, + "restoreItemConfirmation": { + "message": "Elementi bərpa etmək istədiyinizə əminsiniz?" + }, + "restoredItem": { + "message": "Element bərpa edildi" + }, + "permanentlyDelete": { + "message": "Birdəfəlik sil" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Çıxış edəndə, anbarınıza bütün müraciətiniz dayanacaq və vaxt bitməsindən sonra onlayn kimlik təsdiqləməsi tələb olunacaq. Bu tənzimləməni istifadə etmək istədiyinizə əminsiniz?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Vaxt bitmə əməliyyat təsdiqi" + }, + "enterpriseSingleSignOn": { + "message": "Müəssisə üçün tək daxil olma" + }, + "setMasterPassword": { + "message": "Ana parolu tənzimlə" + }, + "ssoCompleteRegistration": { + "message": "SSO ilə giriş prosesini tamamlamaq üçün zəhmət olmasa anbarınıza müraciət etmək və onu qorumaq üçün bir ana parol tənzimləyin." + }, + "newMasterPass": { + "message": "Yeni ana parol" + }, + "confirmNewMasterPass": { + "message": "Yeni ana parolu təsdiqlə" + }, + "masterPasswordPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasəti, aşağıdakı tələbləri qarşılamaq üçün ana parolunuzu tələb edir:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum mürəkkəblik xalı: $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum uzunluq: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Bir və ya daha çox böyük hərf ehtiva etməlidir" + }, + "policyInEffectLowercase": { + "message": "Bir və ya daha çox kiçik hərf ehtiva etməlidir" + }, + "policyInEffectNumbers": { + "message": "Bir və ya daha çox rəqəm ehtiva etməlidir" + }, + "policyInEffectSpecial": { + "message": "Bu özəl simvollardan biri və ya daha çoxunu ehtiva etməlidir: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Yeni ana parolunuz siyasət tələblərini qarşılamır." + }, + "acceptPolicies": { + "message": "Bu qutunu işarələyərək aşağıdakılarla razılaşırsınız:" + }, + "acceptPoliciesError": { + "message": "Xidmət Şərtləri və Gizlilik Siyasəti qəbul edilməyib." + }, + "enableBrowserIntegration": { + "message": "Səyyah inteqrasiyasını fəallaşdır" + }, + "enableBrowserIntegrationDesc": { + "message": "Səyyah inteqrasiyası səyyahda biometrik təsdiqləmə üçün istifadə olunur." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Səyyah inteqrasiyası dəstəklənmir" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Təəssüf ki, səyyah inteqrasiyası yalnız Mac App Store versiyasında dəstəklənir." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Səyyah inteqrasiyası dəstəklənmir" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Təəssüf ki, səyyah inteqrasiyası hazır Windows Store versiyasında dəstəklənmir." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Səyyah inteqrasiyası üçün təsdiqləmə tələb et" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Masaüstü tətbiqlə səyyah arasında bağlantı qurularkən barmaq izi ifadəsinin təsdiqlənməsini tələb edərək əlavə bir təhlükəsizlik qatını fəallaşdıra bilərsiniz. Fəal olanda, bu, hər bağlantı qurulanda istifadəçi müdaxiləsi və təsdiqləməsini tələb edir." + }, + "approve": { + "message": "Təsdiqlə" + }, + "verifyBrowserTitle": { + "message": "Səyyah bağlantısını təsdiqlə" + }, + "verifyBrowserDesc": { + "message": "Zəhmət olmasa göstərilən barmaq izinin səyyah genişləndirməsində göstərilən barmaq izi ilə eyni olduğuna əmin olun." + }, + "biometricsNotEnabledTitle": { + "message": "Biometriklə fəal deyil" + }, + "biometricsNotEnabledDesc": { + "message": "Səyyah biometrikləri, əvvəlcə tənzimləmələrdə masaüstü biometriklərinin fəallaşdırılmasını tələb edir." + }, + "personalOwnershipSubmitError": { + "message": "Müəssisə Siyasətinə görə, elementləri şəxsi anbarınızda saxlamağınız məhdudlaşdırılıb. Sahiblik seçimini təşkilat olaraq dəyişdirin və mövcud kolleksiyalar arasından seçim edin." + }, + "hintEqualsPassword": { + "message": "Parol məsləhəti, parolunuzla eyni ola bilməz." + }, + "personalOwnershipPolicyInEffect": { + "message": "Bir təşkilat siyasəti, sahiblik seçimlərinizə təsir edir." + }, + "allSends": { + "message": "Bütün \"Send\"lər", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fayl" + }, + "sendTypeText": { + "message": "Mətn" + }, + "searchSends": { + "message": "\"Send\"ləri axtar", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "\"Send\"ə düzəliş et", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Anbarım" + }, + "text": { + "message": "Mətn" + }, + "deletionDate": { + "message": "Silinmə tarixi" + }, + "deletionDateDesc": { + "message": "\"Send\" göstərilən tarix və saatda birdəfəlik silinəcək.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Bitmə tarixi" + }, + "expirationDateDesc": { + "message": "Əgər tənzimlənsə, göstərilən tarix və vaxtda \"Send\"ə müraciət başa çatacaq.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maksimal müraciət sayı" + }, + "maxAccessCountDesc": { + "message": "Əgər tənzimlənsə, istifadəçilər maksimal müraciət sayına çatdıqdan sonra bu \"Send\"ə müraciət edə bilməyəcək.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Hazırkı müraciət sayı" + }, + "disableSend": { + "message": "Heç kimin müraciət edə bilməməsi üçün bu \"Send\"i sıradan çıxart.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "İstəyinizə görə istifadəçilərdən bu \"Send\"ə müraciət edərkən parol tələb edə bilərsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Bu \"Send\" ilə bağlı gizli qeydlər.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "\"Send\" bağlantısı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "\"Send\" bağlantısı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "\"Send\"ə müraciət edəndə ilkin olaraq mətni gizlədin", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send yaradıldı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "\"Send\"ə düzəliş edildi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send silindi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Yeni parol" + }, + "whatTypeOfSend": { + "message": "\"Send\"in növü nədir?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Send yarat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Göndərmək istədiyiniz mətn." + }, + "sendFileDesc": { + "message": "Göndərmək istədiyiniz fayl." + }, + "days": { + "message": "$DAYS$ gün", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 gün" + }, + "custom": { + "message": "Özəl" + }, + "deleteSendConfirmation": { + "message": "Bu \"Send\"i silmək istədiyinizə əminsiniz?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Send bağlantısını lövhəyə kopyala", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Saxladıqdan sonra bu \"Send\"in paylaşma bağlantısını lövhəmə kopyala." + }, + "sendDisabled": { + "message": "Send sıradan çıxarıldı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Müəssisə siyasətinə görə, yalnız mövcud \"Send\"i silə bilərsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Bağlantını kopyala" + }, + "disabled": { + "message": "Sıradan çıxarıldı" + }, + "maxAccessCountReached": { + "message": "Maksimal müraciət sayına çatıldı" + }, + "expired": { + "message": "Müddəti bitib" + }, + "pendingDeletion": { + "message": "Silinməsi gözlənilir" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn təsdiqləmə" + }, + "hideEmail": { + "message": "E-poçt ünvanımı alıcılardan gizlət." + }, + "sendOptionsPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasətləri \"Send\" seçimlərinizə təsir edir." + }, + "emailVerificationRequired": { + "message": "E-poçt təsdiqləməsi tələb olunur" + }, + "emailVerificationRequiredDesc": { + "message": "Bu özəlliyi istifadə etmək üçün e-poçtunuzu təsdiqləməlisiniz." + }, + "passwordPrompt": { + "message": "Ana parolu təkrar soruş" + }, + "passwordConfirmation": { + "message": "Ana şifrə təsdiqi" + }, + "passwordConfirmationDesc": { + "message": "Bu əməliyyat qorumalıdır, davam etmək üçün zəhmət olmasa kimliyinizi təsdiqləmək üçün ana parolunuzu təkrar daxil edin." + }, + "updatedMasterPassword": { + "message": "Yenilənmiş ana parol" + }, + "updateMasterPassword": { + "message": "Ana parolu yenilə" + }, + "updateMasterPasswordWarning": { + "message": "Ana parolunuz təzəlikcə təşkilatınızdakı bir administrator tərəfindən dəyişdirildi. Anbara müraciət üçün indi yeniləməlisiniz. Davam etsəniz, hazırkı seansdan çıxış etmiş və təkrar giriş etməli olacaqsınız. Digər cihazlardakı aktiv seanslar bir saata qədər aktiv qalmağa davam edə bilər." + }, + "hours": { + "message": "Saat" + }, + "minutes": { + "message": "Dəqiqə" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Təşkilatınızın siyasətləri, anbarınızın vaxt bitişinə təsir edir. Anbar vaxt bitişi üçün icazə verilən maksimum vaxt $HOURS$ saat $MINUTES$ dəqiqədir", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Anbar vaxt bitişi, təşkilatınız tərəfindən tənzimlənən məhdudiyyətləri aşır." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Avtomatik qeydiyyat" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Bu təşkilat, sizi \"parol sıfırlama\"da avtomatik olaraq qeydiyyata alan müəssisə siyasətinə sahibdir. Qeydiyyat, təşkilat administratorlarına ana parolunuzu dəyişdirmə icazəsi verəcək." + }, + "vaultExportDisabled": { + "message": "Anbar ixracı sıradan çıxarıldı" + }, + "personalVaultExportPolicyInEffect": { + "message": "Bir və ya daha çox təşkilat siyasəti, fərdi anbarınızı ixrac etməyinizin qarşısını alır." + }, + "addAccount": { + "message": "Hesab əlavə et" + }, + "removeMasterPassword": { + "message": "Ana parolu sil" + }, + "removedMasterPassword": { + "message": "Ana parol silindi." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$, öz-özünə sahiblik edən açar serveri ilə SSO istifadə edir. Bu təşkilatın üzvlərinin giriş etməsi üçün artıq ana parol tələb edilməyəcək.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Təşkilatı tərk et" + }, + "leaveOrganizationConfirmation": { + "message": "Bu təşkilatı tərk etmək istədiyinizə əminsiniz?" + }, + "leftOrganization": { + "message": "Təşkilatı tərk etdiniz." + }, + "ssoKeyConnectorUnavailable": { + "message": "Açar bağlayıcı əlçatan deyil, daha sonra yenidən sınayın." + }, + "lockAllVaults": { + "message": "Bütün anbarları kilidlə" + }, + "accountLimitReached": { + "message": "Eyni vaxtda 5-dən çox hesaba giriş edilə bilməz." + }, + "accountPreferences": { + "message": "Tercihlər" + }, + "appPreferences": { + "message": "Tətbiq tənzimləmələri (Bütün hesablar)" + }, + "accountSwitcherLimitReached": { + "message": "Hesab limiti keçildi. Başqa bir hesab əlavə etmək üçün bir hesabdan çıxış edin." + }, + "settingsTitle": { + "message": "$EMAIL$ üçün tətbiq tənzimləmələri", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Hesabı dəyişdir" + }, + "options": { + "message": "Seçimlər" + }, + "sessionTimeout": { + "message": "Seansınızın vaxtı bitdi. Zəhmət olmasa geri qayıdıb yenidən giriş etməyə cəhd edin." + }, + "exportingPersonalVaultTitle": { + "message": "Şəxsi anbarın ixracı" + }, + "exportingPersonalVaultDescription": { + "message": "Yalnız $EMAIL$ ilə əlaqəli şəxsi anbar elementləri ixrac ediləcək. Təşkilat anbar elementləri daxil edilmir.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Yaradıcı" + }, + "whatWouldYouLikeToGenerate": { + "message": "Nə yaratmaq istəyirsiniz?" + }, + "passwordType": { + "message": "Parol növü" + }, + "regenerateUsername": { + "message": "İstifadəçi adını yenidən yarat" + }, + "generateUsername": { + "message": "İstifadəçi adı yarat" + }, + "usernameType": { + "message": "İstifadəçi adı növü" + }, + "plusAddressedEmail": { + "message": "Plyus ünvanlı e-poçt" + }, + "plusAddressedEmailDesc": { + "message": "E-poçt təchizatçınızın alt ünvan özəlliklərini istifadə et." + }, + "catchallEmail": { + "message": "Catch-all E-poçt" + }, + "catchallEmailDesc": { + "message": "Domeninizin konfiqurasiya edilmiş hamısını yaxalama gələn qutusunu istifadə edin." + }, + "random": { + "message": "Təsadüfi" + }, + "randomWord": { + "message": "Təsadüfi söz" + }, + "websiteName": { + "message": "Veb sayt adı" + }, + "service": { + "message": "Xidmət" + } +} diff --git a/apps/desktop/src/locales/be/messages.json b/apps/desktop/src/locales/be/messages.json new file mode 100644 index 0000000000..39761bc5a6 --- /dev/null +++ b/apps/desktop/src/locales/be/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Фільтры" + }, + "allItems": { + "message": "Усе элементы" + }, + "favorites": { + "message": "Абраныя" + }, + "types": { + "message": "Тыпы" + }, + "typeLogin": { + "message": "Уліковыя даныя" + }, + "typeCard": { + "message": "Картка" + }, + "typeIdentity": { + "message": "Пасведчанне" + }, + "typeSecureNote": { + "message": "Бяспечныя нататкі" + }, + "folders": { + "message": "Папкі" + }, + "collections": { + "message": "Калекцыі" + }, + "searchVault": { + "message": "Пошук у сховішчы" + }, + "addItem": { + "message": "Дадаць элемент" + }, + "shared": { + "message": "Абагуленыя" + }, + "share": { + "message": "Абагуліць" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Далучэнні" + }, + "viewItem": { + "message": "Прагляд элемента" + }, + "name": { + "message": "Назва" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Новы URI" + }, + "username": { + "message": "Імя карыстальніка" + }, + "password": { + "message": "Пароль" + }, + "passphrase": { + "message": "Парольная фраза" + }, + "editItem": { + "message": "Рэдагаванне элемента" + }, + "emailAddress": { + "message": "Адрас эл. пошты" + }, + "verificationCodeTotp": { + "message": "Код праверкі (TOTP)" + }, + "website": { + "message": "Вэб-сайт" + }, + "notes": { + "message": "Нататкі" + }, + "customFields": { + "message": "Карыстальніцкія палі" + }, + "launch": { + "message": "Запусціць" + }, + "copyValue": { + "message": "Капіяваць значэнне", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Згарнуць пасля капіявання ў буфер абмену" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Згортваць пасля капіявання даных з элемента ў буфер абмену." + }, + "toggleVisibility": { + "message": "Пераключыць бачнасць" + }, + "toggleCollapse": { + "message": "Згарнуць/Разгарнуць", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Імя ўладальніка карткі" + }, + "number": { + "message": "Нумар" + }, + "brand": { + "message": "Тып карткі" + }, + "expiration": { + "message": "Тэрмін дзеяння" + }, + "securityCode": { + "message": "Код бяспекі" + }, + "identityName": { + "message": "Імя" + }, + "company": { + "message": "Кампанія" + }, + "ssn": { + "message": "Нумар сацыяльнага страхавання" + }, + "passportNumber": { + "message": "Нумар пашпарта" + }, + "licenseNumber": { + "message": "Нумар ліцэнзіі" + }, + "email": { + "message": "Электронная пошта" + }, + "phone": { + "message": "Тэлефон" + }, + "address": { + "message": "Адрас" + }, + "premiumRequired": { + "message": "Патрабуецца прэміяльны статус" + }, + "premiumRequiredDesc": { + "message": "Для выкарыстання гэтай функцыі патрабуецца прэміяльны статус." + }, + "errorOccurred": { + "message": "Адбылася памылка." + }, + "error": { + "message": "Памылка" + }, + "january": { + "message": "Студзень" + }, + "february": { + "message": "Люты" + }, + "march": { + "message": "Сакавік" + }, + "april": { + "message": "Красавік" + }, + "may": { + "message": "Май" + }, + "june": { + "message": "Чэрвень" + }, + "july": { + "message": "Ліпень" + }, + "august": { + "message": "Жнівень" + }, + "september": { + "message": "Верасень" + }, + "october": { + "message": "Кастрычнік" + }, + "november": { + "message": "Лістапад" + }, + "december": { + "message": "Снежань" + }, + "ex": { + "message": "напр.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Зварот" + }, + "mr": { + "message": "С-р" + }, + "mrs": { + "message": "С-ня" + }, + "ms": { + "message": "Пані" + }, + "dr": { + "message": "Док." + }, + "expirationMonth": { + "message": "Месяц заканчэння" + }, + "expirationYear": { + "message": "Год заканчэння" + }, + "select": { + "message": "Выбраць" + }, + "other": { + "message": "Iншае" + }, + "generatePassword": { + "message": "Згенерыраваць пароль" + }, + "type": { + "message": "Тып" + }, + "firstName": { + "message": "Імя" + }, + "middleName": { + "message": "Імя па бацьку" + }, + "lastName": { + "message": "Прозвішча" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Радок адрасу 1" + }, + "address2": { + "message": "Радок адрасу 2" + }, + "address3": { + "message": "Радок адрасу 3" + }, + "cityTown": { + "message": "Горад / Пасёлак" + }, + "stateProvince": { + "message": "Рэгіён / Вобласць" + }, + "zipPostalCode": { + "message": "Паштовы індэкс" + }, + "country": { + "message": "Краіна" + }, + "save": { + "message": "Захаваць" + }, + "cancel": { + "message": "Скасаваць" + }, + "delete": { + "message": "Выдаліць" + }, + "favorite": { + "message": "Абраны" + }, + "edit": { + "message": "Рэдагаваць" + }, + "authenticatorKeyTotp": { + "message": "Ключ праверкі сапраўднасці (TOTP)" + }, + "folder": { + "message": "Папка" + }, + "newCustomField": { + "message": "Новае карыстальніцкае поле" + }, + "value": { + "message": "Значэнне" + }, + "dragToSort": { + "message": "Перацягніце для сартавання" + }, + "cfTypeText": { + "message": "Тэкст" + }, + "cfTypeHidden": { + "message": "Схавана" + }, + "cfTypeBoolean": { + "message": "Лагічнае" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Выдаліць" + }, + "nameRequired": { + "message": "Патрэбна назва." + }, + "addedItem": { + "message": "Элемент дададзены" + }, + "editedItem": { + "message": "Элемент адрэдагаваны" + }, + "deleteItem": { + "message": "Выдаліць элемент" + }, + "deleteFolder": { + "message": "Выдаліць папку" + }, + "deleteAttachment": { + "message": "Выдаліць далучэнне" + }, + "deleteItemConfirmation": { + "message": "Вы ўпэўнены, што хочаце выдаліць гэты элемент?" + }, + "deletedItem": { + "message": "Выдалены элемент" + }, + "overwritePasswordConfirmation": { + "message": "Вы ўпэўнены, што хочаце перазапісаць бягучы пароль?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Без папкі", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Дадаць папку" + }, + "editFolder": { + "message": "Рэдагаваць папку" + }, + "regeneratePassword": { + "message": "Стварыць новы пароль" + }, + "copyPassword": { + "message": "Капіяваць пароль" + }, + "copyUri": { + "message": "Капіяваць URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Даўжыня" + }, + "numWords": { + "message": "Колькасць слоў" + }, + "wordSeparator": { + "message": "Раздзяляльнік слоў" + }, + "capitalize": { + "message": "З вялікай літары", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Уключыць лічбу" + }, + "close": { + "message": "Закрыць" + }, + "minNumbers": { + "message": "Мін. колькасць лічбаў" + }, + "minSpecial": { + "message": "Мін. колькасць сімвалаў", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Пазбягаць неадназначных сімвалаў" + }, + "searchCollection": { + "message": "Пошук у калекцыі" + }, + "searchFolder": { + "message": "Пошук у папцы" + }, + "searchFavorites": { + "message": "Пошук у абраным" + }, + "searchType": { + "message": "Пошук па тыпу", + "description": "Search item type" + }, + "newAttachment": { + "message": "Дадаць новае далучэнне" + }, + "deletedAttachment": { + "message": "Далучэнне выдалена" + }, + "deleteAttachmentConfirmation": { + "message": "Вы ўпэўнены, што хочаце выдаліць гэта далучэнне?" + }, + "attachmentSaved": { + "message": "Далучэнне захавана." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Выберыце файл." + }, + "maxFileSize": { + "message": "Максімальны памер файла 500 МБ." + }, + "updateKey": { + "message": "Вы не можаце выкарыстоўваць гэту функцыю, пакуль не абнавіце свой ключ шыфравання." + }, + "editedFolder": { + "message": "Папка адрэдагавана" + }, + "addedFolder": { + "message": "Папка дададзена" + }, + "deleteFolderConfirmation": { + "message": "Вы ўпэўнены, што хочаце выдаліць гэту папку?" + }, + "deletedFolder": { + "message": "Папка выдалена" + }, + "loginOrCreateNewAccount": { + "message": "Увайдзіце або стварыце новы ўліковы запіс для доступу да бяспечнага сховішча." + }, + "createAccount": { + "message": "Стварыць уліковы запіс" + }, + "logIn": { + "message": "Увайсці" + }, + "submit": { + "message": "Адправіць" + }, + "masterPass": { + "message": "Асноўны пароль" + }, + "masterPassDesc": { + "message": "Асноўны пароль — ключ да вашага бяспечнага сховішча. Ён вельмі важны, таму не забывайце яго. Аднавіць асноўны пароль немагчыма." + }, + "masterPassHintDesc": { + "message": "Падказка да асноўнага пароля можа дапамагчы вам яго ўспомніць." + }, + "reTypeMasterPass": { + "message": "Увядзіце асноўны пароль паўторна" + }, + "masterPassHint": { + "message": "Падказка да асноўнага пароля (неабавязкова)" + }, + "settings": { + "message": "Налады" + }, + "passwordHint": { + "message": "Падказка да пароля" + }, + "enterEmailToGetHint": { + "message": "Увядзіце адрас электроннай пошты ўліковага запісу для атрымання падказкі для асноўнага пароля." + }, + "getMasterPasswordHint": { + "message": "Атрымаць падказку для асноўнага пароля" + }, + "emailRequired": { + "message": "Патрабуецца адрас электроннай пошты." + }, + "invalidEmail": { + "message": "Памылковы адрас электроннай пошты." + }, + "masterPassRequired": { + "message": "Патрабуецца асноўны пароль." + }, + "masterPassLength": { + "message": "Асноўны пароль павінен быць даўжынёй не менш за 8 сімвалаў." + }, + "masterPassDoesntMatch": { + "message": "Асноўныя паролі не супадаюць." + }, + "newAccountCreated": { + "message": "Ваш уліковы запіс створаны! Вы можаце ўвайсці." + }, + "masterPassSent": { + "message": "Мы адправілі вам на электронную пошту падказку для асноўнага пароля." + }, + "unexpectedError": { + "message": "Адбылася нечаканая памылка." + }, + "itemInformation": { + "message": "Звесткі аб элеменце" + }, + "noItemsInList": { + "message": "Няма элементаў для паказу." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Код праверкі" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Патрабуецца код праверкі." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Працягнуць" + }, + "enterVerificationCodeApp": { + "message": "Увядзіце 6 лічбаў кода праверкі з вашай праграмы праверкі сапраўднасці." + }, + "enterVerificationCodeEmail": { + "message": "Увядзіце 6 лічбаў кода праверкі, які быў адпраўлены на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Адпраўлены ліст для пацвярджэння $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запомніць мяне" + }, + "sendVerificationCodeEmailAgain": { + "message": "Адправіць код пацвярджэння зноў" + }, + "useAnotherTwoStepMethod": { + "message": "Выкарыстоўваць іншы метад двухэтапнага ўваходу" + }, + "insertYubiKey": { + "message": "Устаўце ваш YubiKey ў порт USB вашага камп'ютара, затым націсніце на кнопку." + }, + "insertU2f": { + "message": "Устаўце ваш ключ бяспекі ў порт USB вашага камп'ютара. Калі на ім ёсць кнопка, націсніце на яе." + }, + "recoveryCodeDesc": { + "message": "Згубілі доступ да ўсіх варыянтаў двухэтапнага ўваходу? Скарыстайцеся кодам аднаўлення, каб адключыць двухэтапны ўваход для вашага ўліковага запісу." + }, + "recoveryCodeTitle": { + "message": "Код аднаўлення" + }, + "authenticatorAppTitle": { + "message": "Праграма праверкі сапраўднасці" + }, + "authenticatorAppDesc": { + "message": "Выкарыстоўвайце праграму для праверкі сапраўднасці (напрыклад, Authy або Google Authenticator) для стварэння кодаў праверкі на аснове часу.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Ключ бяспекі YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Выкарыстоўвайце YubiKey для доступу да вашага ўліковага запісу. Працуе з прыладамі YubiKey серый 4, 5 і NEO." + }, + "duoDesc": { + "message": "Пацвярдзіце з дапамогай Duo Security, выкарыстоўваючы праграму Duo Mobile, SMS, тэлефонны выклік або ключ бяспекі.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Пацвярдзіце з дапамогай Duo Security для вашай арганізацыі, выкарыстоўваючы праграму Duo Mobile, SMS, тэлефонны выклік або ключ бяспекі.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Электронная пошта" + }, + "emailDesc": { + "message": "Коды пацвярджэння будуць адпраўлены вам па электроннай пошце." + }, + "loginUnavailable": { + "message": "Уваход недаступны" + }, + "noTwoStepProviders": { + "message": "У гэтага ўліковага запісу ўключаны двухэтапны ўваход, аднак ні адзін з наладжаных варыянтаў не падтрымліваецца гэтай прыладай." + }, + "noTwoStepProviders2": { + "message": "Дадайце дадатковыя варыянты двухэтапнага ўваходу, якія падтрымліваюцца большасцю прылад (напрыклад, праграма праверкі сапраўднасці)." + }, + "twoStepOptions": { + "message": "Параметры двухэтапнага ўваходу" + }, + "selfHostedEnvironment": { + "message": "Асяроддзе ўласнага хостынгу" + }, + "selfHostedEnvironmentFooter": { + "message": "Увядзіце асноўны URL-адрас на вашым серверы." + }, + "customEnvironment": { + "message": "Налады асяроддзя" + }, + "customEnvironmentFooter": { + "message": "Для вопытных карыстальнікаў. Можна ўвесці URL-адрасы асобна для кожнай службы." + }, + "baseUrl": { + "message": "URL-адрас сервера" + }, + "apiUrl": { + "message": "API URL-адраса сервера" + }, + "webVaultUrl": { + "message": "URL-адрас сервера вэб-сховішча" + }, + "identityUrl": { + "message": "URL-адрас сервера ідэнтыфікацыі" + }, + "notificationsUrl": { + "message": "URL-адрас сервера апавяшчэнняў" + }, + "iconsUrl": { + "message": "URL-адрас сервера значкоў" + }, + "environmentSaved": { + "message": "URL-адрас сервера асяроддзя захаваны." + }, + "ok": { + "message": "ОК" + }, + "yes": { + "message": "Так" + }, + "no": { + "message": "Не" + }, + "overwritePassword": { + "message": "Перазапісаць пароль" + }, + "learnMore": { + "message": "Даведацца больш" + }, + "featureUnavailable": { + "message": "Функцыя недаступна" + }, + "loggedOut": { + "message": "Вы выйшлі са сховішча" + }, + "loginExpired": { + "message": "Скончыўся тэрмін дзеяння вашага сеансу." + }, + "logOutConfirmation": { + "message": "Вы ўпэўнены, што хочаце выйсці?" + }, + "logOut": { + "message": "Выйсці" + }, + "addNewLogin": { + "message": "Дадаць новыя ўліковыя даныя" + }, + "addNewItem": { + "message": "Дадаць новы элемент" + }, + "addNewFolder": { + "message": "Дадаць новую папку" + }, + "view": { + "message": "Выгляд" + }, + "account": { + "message": "Уліковы запіс" + }, + "loading": { + "message": "Загрузка..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Генератар пароляў" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Паведаміць аб памылцы" + }, + "blog": { + "message": "Блог" + }, + "followUs": { + "message": "Падпісвайцеся" + }, + "syncVault": { + "message": "Сінхранізаваць сховішча" + }, + "changeMasterPass": { + "message": "Змяніць асноўны пароль" + }, + "changeMasterPasswordConfirmation": { + "message": "Вы можаце змяніць свой асноўны пароль на bitwarden.com. Перайсці на сайт зараз?" + }, + "fingerprintPhrase": { + "message": "Фраза адбітка пальца", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Фраза адбітка пальца вашага ўліковага запісу", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Перайсці ў вэб-сховішча" + }, + "getMobileApp": { + "message": "Атрымаць мабільную праграму" + }, + "getBrowserExtension": { + "message": "Атрымаць пашырэнне для браўзера" + }, + "syncingComplete": { + "message": "Сінхранізацыя завершана" + }, + "syncingFailed": { + "message": "Памылка сінхранізацыі" + }, + "yourVaultIsLocked": { + "message": "Ваша сховішча заблакіравана. Каб працягнуць, увядзіце асноўны пароль." + }, + "unlock": { + "message": "Разблакіраваць" + }, + "loggedInAsOn": { + "message": "Выкананы ўваход на $HOSTNAME$ як $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Памылковы асноўны пароль" + }, + "twoStepLoginConfirmation": { + "message": "Двухэтапны ўваход робіць ваш уліковы запіс больш бяспечным, патрабуючы пацвярджэння ўваходу на іншай прыладзе, напрыклад, ключом бяспекі, праграмай для праверкі бяспекі, SMS, тэлефонным выклікам або электроннай поштай. Двухэтапны ўваход уключаецца на bitwarden.com. Перайсці на сайт зараз?" + }, + "twoStepLogin": { + "message": "Двухэтапны ўваход" + }, + "vaultTimeout": { + "message": "Тайм-аўт сховішча" + }, + "vaultTimeoutDesc": { + "message": "Выберыце тайм-аўт для сховішча і дзеянне, якое неабходна зрабіць." + }, + "immediately": { + "message": "Адразу" + }, + "tenSeconds": { + "message": "10 секунд" + }, + "twentySeconds": { + "message": "20 секунд" + }, + "thirtySeconds": { + "message": "30 секунд" + }, + "oneMinute": { + "message": "1 хвіліна" + }, + "twoMinutes": { + "message": "2 хвіліны" + }, + "fiveMinutes": { + "message": "5 хвілін" + }, + "fifteenMinutes": { + "message": "15 хвілін" + }, + "thirtyMinutes": { + "message": "30 хвілін" + }, + "oneHour": { + "message": "1 гадзіна" + }, + "fourHours": { + "message": "4 гадзіны" + }, + "onIdle": { + "message": "Пры бяздзейнасці" + }, + "onSleep": { + "message": "У рэжыме сну" + }, + "onLocked": { + "message": "Разам з камп'ютарам" + }, + "onRestart": { + "message": "Пры перазапуску" + }, + "never": { + "message": "Ніколі" + }, + "security": { + "message": "Бяспека" + }, + "clearClipboard": { + "message": "Ачыстка буфера абмену", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Аўтаматычна ачышчаць скапіяваныя значэнні з вашага буфера абмену.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Адключыць значкі вэб-сайтаў" + }, + "disableFaviconDesc": { + "message": "Значкі вэб-сайтаў паказваюцца з кожным элементам у вашым сховішчы." + }, + "enableMinToTray": { + "message": "Згарунць у вобласць апавяшчэнняў" + }, + "enableMinToTrayDesc": { + "message": "Пры згортванні акна, будзе паказвацца значок у вообласці апавяшчэнняў." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Закрываць у вобласць апавяшчэнняў" + }, + "enableCloseToTrayDesc": { + "message": "Пры закрыцці акна, будзе паказвацца значок у вообласці апавяшчэнняў." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Уключыць значок у вобласці апавяшчэнняў" + }, + "enableTrayDesc": { + "message": "Заўсёды паказваць значок у вобласці апавяшчэнняў." + }, + "startToTray": { + "message": "Запускаць у згорнутым выглядзе" + }, + "startToTrayDesc": { + "message": "Пры першым запуску праграмы, будзе паказвацца значок у вобласці апавяшчэнняў." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Мова" + }, + "languageDesc": { + "message": "Змена мовы, якая выкарыстоўваецца праграмай. Патрабуецца перазапуск." + }, + "theme": { + "message": "Тэма" + }, + "themeDesc": { + "message": "Змена колеравай тэмы праграмы." + }, + "dark": { + "message": "Цёмная", + "description": "Dark color" + }, + "light": { + "message": "Светлая", + "description": "Light color" + }, + "copy": { + "message": "Капіяваць", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Праверыць абнаўленні" + }, + "version": { + "message": "Версія $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Перазапуск для абнаўлення" + }, + "restartToUpdateDesc": { + "message": "Версія $VERSION_NUM$ гатовая да ўсталявання. Вы павінны перазапусціць праграму, каб завершыць усталяванне. Вы хочаце перазапусціць і абнавіць зараз?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Даступна абнаўленне" + }, + "updateAvailableDesc": { + "message": "Знойдзена абнаўленне. Спампаваць яго зараз?" + }, + "restart": { + "message": "Перазапусціць" + }, + "later": { + "message": "Пазней" + }, + "noUpdatesAvailable": { + "message": "Абнаўленняў няма. Вы выкарыстоўваеце апошнюю версію." + }, + "updateError": { + "message": "Памылка абнаўлення" + }, + "unknown": { + "message": "Невядома" + }, + "copyUsername": { + "message": "Капіяваць імя карыстальніка" + }, + "copyNumber": { + "message": "Капіяваць нумар", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Капіяваць код бяспекі", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Прэміяльны статус" + }, + "premiumManage": { + "message": "Кіраванне статусам" + }, + "premiumManageAlert": { + "message": "Вы можаце кіраваць сваім статусам на bitwarden.com. Перайсці на сайт зараз?" + }, + "premiumRefresh": { + "message": "Абнавіць статус" + }, + "premiumNotCurrentMember": { + "message": "На дадзены момант у вас не прэміяльны статус." + }, + "premiumSignUpAndGet": { + "message": "Падпішыцеся на прэміяльны статус і атрымайце:" + }, + "premiumSignUpStorage": { + "message": "1 ГБ зашыфраванага сховішча для далучаных файлаў." + }, + "premiumSignUpTwoStep": { + "message": "Дадатковыя варыянты двухэтапнага ўваходу, такія як YubiKey, FIDO U2F і Duo." + }, + "premiumSignUpReports": { + "message": "Гігіена пароляў, здароўе ўліковага запісу і справаздачы аб уцечках даных для забеспячэння бяспекі вашага сховішча." + }, + "premiumSignUpTotp": { + "message": "TOTP-генератар кодаў (2ФА) для ўліковых даных вашага сховішча." + }, + "premiumSignUpSupport": { + "message": "Прыярытэтная падтрымка." + }, + "premiumSignUpFuture": { + "message": "Усе будучыя функцыі прэміяльнага статусу. Іх будзе больш!" + }, + "premiumPurchase": { + "message": "Купіць прэміяльны статус" + }, + "premiumPurchaseAlert": { + "message": "Вы можаце купіць прэміяльны статус на bitwarden.com. Перайсці на сайт зараз?" + }, + "premiumCurrentMember": { + "message": "У вас прэміяльны статус!" + }, + "premiumCurrentMemberThanks": { + "message": "Дзякуем вам за падтрымку Bitwarden." + }, + "premiumPrice": { + "message": "Усяго толькі за $PRICE$ на год!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Абнаўленне завершана" + }, + "passwordHistory": { + "message": "Гісторыя пароляў" + }, + "clear": { + "message": "Ачысціць", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Няма пароляў для паказу." + }, + "undo": { + "message": "Адрабіць" + }, + "redo": { + "message": "Вярнуць" + }, + "cut": { + "message": "Выразаць", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Уставіць", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Выбраць усё" + }, + "zoomIn": { + "message": "Павялічыць" + }, + "zoomOut": { + "message": "Паменшыць" + }, + "resetZoom": { + "message": "Скінуць маштаб" + }, + "toggleFullScreen": { + "message": "Пераключыць поўнаэкранны рэжым" + }, + "reload": { + "message": "Перазагрузка" + }, + "toggleDevTools": { + "message": "Пераключыць інструменты для распрацоўшчыкаў" + }, + "minimize": { + "message": "Згарнуць", + "description": "Minimize window" + }, + "zoom": { + "message": "Маштаб" + }, + "bringAllToFront": { + "message": "На пярэдні план", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Пра Bitwarden" + }, + "services": { + "message": "Службы" + }, + "hideBitwarden": { + "message": "Схаваць Bitwarden" + }, + "hideOthers": { + "message": "Схаваць іншыя" + }, + "showAll": { + "message": "Паказаць усе" + }, + "quitBitwarden": { + "message": "Выйсці з Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ скапіяваны(-а)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Даведка" + }, + "window": { + "message": "Акно" + }, + "checkPassword": { + "message": "Праверце, ці не скампраметаваны пароль." + }, + "passwordExposed": { + "message": "Гэты пароль быў скампраметаваны $VALUE$ раз(-ы/-оў). Вы павінны змяніць яго.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Гэты пароль не быў знойдзены ў вядомых базах уцечак. Можна працягваць яго выкарыстоўваць." + }, + "baseDomain": { + "message": "Асноўны дамен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Хост", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Дакладна" + }, + "startsWith": { + "message": "Пачынаецца з" + }, + "regEx": { + "message": "Рэгулярны выраз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Выяўленне супадзенняў", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Метад выяўлення па змаўчанні", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Пераключыць параметры" + }, + "organization": { + "message": "Арганізацыя", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Па змаўчанні" + }, + "exit": { + "message": "Выхад" + }, + "showHide": { + "message": "Паказаць / Схаваць", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Схаваць у вобласць апавяшчэнняў" + }, + "alwaysOnTop": { + "message": "Па-над усімі вокнамі", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Абноўлена", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Пароль абноўлены", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Экспарт сховішча" + }, + "fileFormat": { + "message": "Фармат файла" + }, + "warning": { + "message": "УВАГА", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "Экспартуемы файл утрымлівае даныя вашага сховішча ў незашыфраваным фармаце. Яго не варта захоўваць ці адпраўляць па небяспечным каналам (напрыклад, па электроннай пошце). Выдаліце яго адразу пасля выкарыстання." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "Вы не з'яўляецеся членам якой-небудзь арганізацыі. Арганізацыі дазваляюць бяспечна абменьвацца элементамі з іншымі карыстальнікамі." + }, + "noCollectionsInList": { + "message": "Няма калекцый для паказу." + }, + "ownership": { + "message": "Уладальнік" + }, + "whoOwnsThisItem": { + "message": "Каму належыць гэты элемент?" + }, + "strong": { + "message": "Моцны", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Добры", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабы", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слабы асноўны пароль" + }, + "weakMasterPasswordDesc": { + "message": "Асноўны пароль, выбраны вамі, з'яўляецца слабым. Для належнай абароны ўліковага запісу Bitwarden, вы павінны выкарыстоўваць моцны асноўны пароль (або парольную фразу). Вы ўпэўнены, што хочаце выкарыстоўваць гэты асноўны пароль?" + }, + "pin": { + "message": "PIN-код", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Разблакіраваць PIN-кодам" + }, + "setYourPinCode": { + "message": "Задайце PIN-код для разблакіроўкі Bitwarden. Налады PIN-кода будуць скінуты, калі вы калі-небудзь цалкам выйдзеце з праграмы." + }, + "pinRequired": { + "message": "Патрабуецца PIN-код." + }, + "invalidPin": { + "message": "Памылковы PIN-код." + }, + "unlockWithWindowsHello": { + "message": "Разблакіраваць з Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Праверыць на Bitwarden." + }, + "unlockWithTouchId": { + "message": "Разблакіраваць з Touch ID" + }, + "touchIdConsentMessage": { + "message": "Праверыць на Bitwarden." + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Блакіраваць асноўным паролем пры перазапуску" + }, + "preferences": { + "message": "Налады" + }, + "enableMenuBar": { + "message": "Уключыць значок у радку меню" + }, + "enableMenuBarDesc": { + "message": "Заўсёды паказваць значок у радку меню." + }, + "hideToMenuBar": { + "message": "Схаваць у радку меню" + }, + "selectOneCollection": { + "message": "Вы павінны выбраць прынамсі адну калекцыю." + }, + "premiumUpdated": { + "message": "Вы абнавіліся да прэміяльнага статусу." + }, + "restore": { + "message": "Аднавіць" + }, + "premiumManageAlertAppStore": { + "message": "Вы можаце кіраваць сваёй падпіскай з App Store. Вы хочаце наведаць App Store?" + }, + "legal": { + "message": "Правы", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Умовы выкарыстання" + }, + "privacyPolicy": { + "message": "Палітыка прыватнасці" + }, + "unsavedChangesConfirmation": { + "message": "Вы ўпэўнены, што хочаце выйсці? У такім выпадку, ваша інфармацыя не будзе захавана." + }, + "unsavedChangesTitle": { + "message": "Незахаваныя змены" + }, + "clone": { + "message": "Кланіраваць" + }, + "passwordGeneratorPolicyInEffect": { + "message": "На налады генератара ўплываюць адна або некалькі палітык арганізацый." + }, + "vaultTimeoutAction": { + "message": "Дзеянне пры тайм-аўце" + }, + "vaultTimeoutActionLockDesc": { + "message": "Для разблакіроўкі сховішча патрабуецца паўторна ўвесці асноўны пароль." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Выхад са сховішча спатрабуе паўторную праверку сапраўднасці для атрымання доступу да яго." + }, + "lock": { + "message": "Заблакіраваць", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Сметніца", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Пошук у сметніцы" + }, + "permanentlyDeleteItem": { + "message": "Выдаліць назаўсёды" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Вы ўпэўнены, што хочаце назаўсёды выдаліць гэты элемент?" + }, + "permanentlyDeletedItem": { + "message": "Выдаленны назаўсёды элемент" + }, + "restoreItem": { + "message": "Аднавіць элемент" + }, + "restoreItemConfirmation": { + "message": "Вы сапраўды жадаеце аднавіць гэты элемент?" + }, + "restoredItem": { + "message": "Элемент адноўлены" + }, + "permanentlyDelete": { + "message": "Выдаліць назаўсёды" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Выхад з сістэмы выдаліць доступ да сховішча і спатрабуе праверку сапраўднасці анлайн па заканчэнні перыяду чакання. Вы сапраўды жадаеце ўключыць гэтую наладу?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Пацвярджэнне дзеяння для тайм-аута" + }, + "enterpriseSingleSignOn": { + "message": "Адзіны ўваход у карпаратыўную сістэму (SSO)" + }, + "setMasterPassword": { + "message": "Задаць асноўны пароль" + }, + "ssoCompleteRegistration": { + "message": "Для завяршэння ўваходу праз SSO, задайце асноўны пароль для доступу і абароны вашаго сховішча." + }, + "newMasterPass": { + "message": "Новы асноўны пароль" + }, + "confirmNewMasterPass": { + "message": "Пацвердзіць новы асноўны пароль" + }, + "masterPasswordPolicyInEffect": { + "message": "Згодна з адной або некалькімі палітыкамі арганізацыі неабходна, каб ваш асноўны пароль адказваў наступным патрабаванням:" + }, + "policyInEffectMinComplexity": { + "message": "Мінімальны ўзровень складанасці $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Мінімальная даўжыня $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Уключыць адну ці больш прапісных літар" + }, + "policyInEffectLowercase": { + "message": "Уключыць адну ці больш малых літар" + }, + "policyInEffectNumbers": { + "message": "Уключыць адну ці больш лічбаў" + }, + "policyInEffectSpecial": { + "message": "Уключаць хаця б адзін з наступных спецыяльных сімвалаў $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваш новы асноўны пароль не адпавядае патрабаванням палітыкі арганізацыі." + }, + "acceptPolicies": { + "message": "Ставячы гэты сцяжок вы пагаджаецеся з наступным:" + }, + "acceptPoliciesError": { + "message": "Умовы выкарыстання і Палітыка прыватнасці не былі пацверджаны." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "Усе адпраўленні", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Файл" + }, + "sendTypeText": { + "message": "Тэкст" + }, + "searchSends": { + "message": "Пошук адпраўленняў", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Рэдагаваць адпраўленне", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Маё сховішча" + }, + "text": { + "message": "Тэкст" + }, + "deletionDate": { + "message": "Дата выдалення" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Дата завяршэння" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Даслаць спасылку", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Новы пароль" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Стварыць адпраўленне", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Тэкст, які вы хочаце адправіць." + }, + "sendFileDesc": { + "message": "Файл, які вы хочаце адправіць." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Адвольны" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Скапіяваць спасылку адпраўлення ў буфер абмену", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Капіяваць спасылку" + }, + "disabled": { + "message": "Адключана" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Пацвярджэнне асноўнага пароля" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/bg/messages.json b/apps/desktop/src/locales/bg/messages.json new file mode 100644 index 0000000000..9a044a3c8d --- /dev/null +++ b/apps/desktop/src/locales/bg/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Филтри" + }, + "allItems": { + "message": "Всички елементи" + }, + "favorites": { + "message": "Любими" + }, + "types": { + "message": "Видове" + }, + "typeLogin": { + "message": "Запис" + }, + "typeCard": { + "message": "Карта" + }, + "typeIdentity": { + "message": "Самоличност" + }, + "typeSecureNote": { + "message": "Защитена бележка" + }, + "folders": { + "message": "Папки" + }, + "collections": { + "message": "Колекции" + }, + "searchVault": { + "message": "Търсене в трезора" + }, + "addItem": { + "message": "Добавяне на елемент" + }, + "shared": { + "message": "Споделено" + }, + "share": { + "message": "Споделяне" + }, + "moveToOrganization": { + "message": "Преместване в организация" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ се премести в $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Изберете организацията, в която искате да преместите записа. Преместването прехвърля собствеността му към новата организация. След това няма вече директно да го притежавате." + }, + "attachments": { + "message": "Прикачени файлове" + }, + "viewItem": { + "message": "Преглед на елемента" + }, + "name": { + "message": "Наименование" + }, + "uri": { + "message": "Адрес" + }, + "uriPosition": { + "message": "Адрес $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Нов адрес" + }, + "username": { + "message": "Потребителско име" + }, + "password": { + "message": "Парола" + }, + "passphrase": { + "message": "Парола-фраза" + }, + "editItem": { + "message": "Редактиране на елемента" + }, + "emailAddress": { + "message": "Е-поща" + }, + "verificationCodeTotp": { + "message": "Код за потвърждаване (TOTP)" + }, + "website": { + "message": "Сайт" + }, + "notes": { + "message": "Бележки" + }, + "customFields": { + "message": "Допълнителни полета" + }, + "launch": { + "message": "Пускане" + }, + "copyValue": { + "message": "Копиране на стойността", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Минимизиране при копиране" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Минимизиране при копиране на данните на записа." + }, + "toggleVisibility": { + "message": "Превключване на видимостта" + }, + "toggleCollapse": { + "message": "Превключване на свиването", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Име на притежателя на картата" + }, + "number": { + "message": "Номер" + }, + "brand": { + "message": "Вид" + }, + "expiration": { + "message": "Изтичане" + }, + "securityCode": { + "message": "Код за сигурност" + }, + "identityName": { + "message": "Име на самоличността" + }, + "company": { + "message": "Фирма" + }, + "ssn": { + "message": "№ на осигуровката" + }, + "passportNumber": { + "message": "№ на паспорта" + }, + "licenseNumber": { + "message": "№ на лиценза" + }, + "email": { + "message": "Е-поща" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адрес" + }, + "premiumRequired": { + "message": "Изисква се платен абонамент" + }, + "premiumRequiredDesc": { + "message": "За да се възползвате от тази възможност, трябва да ползвате платен абонамент." + }, + "errorOccurred": { + "message": "Възникна грешка." + }, + "error": { + "message": "Грешка" + }, + "january": { + "message": "януари" + }, + "february": { + "message": "февруари" + }, + "march": { + "message": "март" + }, + "april": { + "message": "април" + }, + "may": { + "message": "май" + }, + "june": { + "message": "юни" + }, + "july": { + "message": "юли" + }, + "august": { + "message": "август" + }, + "september": { + "message": "септември" + }, + "october": { + "message": "октомври" + }, + "november": { + "message": "ноември" + }, + "december": { + "message": "декември" + }, + "ex": { + "message": "напр.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Обръщение" + }, + "mr": { + "message": "Г-н" + }, + "mrs": { + "message": "Г-жа" + }, + "ms": { + "message": "Г-жа" + }, + "dr": { + "message": "Д-р" + }, + "expirationMonth": { + "message": "Месец на изтичане" + }, + "expirationYear": { + "message": "Година на изтичане" + }, + "select": { + "message": "Избор" + }, + "other": { + "message": "Други" + }, + "generatePassword": { + "message": "Нова парола" + }, + "type": { + "message": "Вид" + }, + "firstName": { + "message": "Собствено име" + }, + "middleName": { + "message": "Презиме" + }, + "lastName": { + "message": "Фамилно име" + }, + "fullName": { + "message": "Пълно име" + }, + "address1": { + "message": "Адрес 1" + }, + "address2": { + "message": "Адрес 2" + }, + "address3": { + "message": "Адрес 3" + }, + "cityTown": { + "message": "Населено място" + }, + "stateProvince": { + "message": "Област" + }, + "zipPostalCode": { + "message": "Пощенски код" + }, + "country": { + "message": "Държава" + }, + "save": { + "message": "Запазване" + }, + "cancel": { + "message": "Отказ" + }, + "delete": { + "message": "Изтриване" + }, + "favorite": { + "message": "Любими" + }, + "edit": { + "message": "Редактиране" + }, + "authenticatorKeyTotp": { + "message": "Удостоверителен ключ (TOTP)" + }, + "folder": { + "message": "Папка" + }, + "newCustomField": { + "message": "Ново допълнително поле" + }, + "value": { + "message": "Стойност" + }, + "dragToSort": { + "message": "Подредба чрез влачене" + }, + "cfTypeText": { + "message": "Текст" + }, + "cfTypeHidden": { + "message": "Скрито" + }, + "cfTypeBoolean": { + "message": "Булево" + }, + "cfTypeLinked": { + "message": "Свързано", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Свързана стойност", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Премахване" + }, + "nameRequired": { + "message": "Името е задължително." + }, + "addedItem": { + "message": "Елементът е добавен" + }, + "editedItem": { + "message": "Елементът е редактиран" + }, + "deleteItem": { + "message": "Изтриване на елемента" + }, + "deleteFolder": { + "message": "Изтриване на папка" + }, + "deleteAttachment": { + "message": "Изтриване на прикачения файл" + }, + "deleteItemConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете елемента?" + }, + "deletedItem": { + "message": "Елементът е изтрит" + }, + "overwritePasswordConfirmation": { + "message": "Сигурни ли сте, че искате да обновите текущата парола?" + }, + "overwriteUsername": { + "message": "Замяна на потребителското име" + }, + "overwriteUsernameConfirmation": { + "message": "Наостина ли искате да замените текущото потребителско име?" + }, + "noneFolder": { + "message": "Няма папка", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Добавяне на папка" + }, + "editFolder": { + "message": "Редактиране на папка" + }, + "regeneratePassword": { + "message": "Пресъздаване на паролата" + }, + "copyPassword": { + "message": "Копиране на паролата" + }, + "copyUri": { + "message": "Копиране на адреса" + }, + "copyVerificationCodeTotp": { + "message": "Код за потвърждаване (TOTP)" + }, + "length": { + "message": "Дължина" + }, + "numWords": { + "message": "Брой думи" + }, + "wordSeparator": { + "message": "Разделител за думи" + }, + "capitalize": { + "message": "Главни букви", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "И цифри" + }, + "close": { + "message": "Затваряне" + }, + "minNumbers": { + "message": "Минимален брой цифри" + }, + "minSpecial": { + "message": "Минимален брой специални знаци", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Без нееднозначни знаци" + }, + "searchCollection": { + "message": "Търсене в колекцията" + }, + "searchFolder": { + "message": "Търсене в папката" + }, + "searchFavorites": { + "message": "Търсене в любими" + }, + "searchType": { + "message": "Търсене по вид", + "description": "Search item type" + }, + "newAttachment": { + "message": "Прикачване на файл" + }, + "deletedAttachment": { + "message": "Прикаченият файл е изтрит" + }, + "deleteAttachmentConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете прикачения файл?" + }, + "attachmentSaved": { + "message": "Прикаченият файл е запазен." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Избор на файл." + }, + "maxFileSize": { + "message": "Големината на файла е най-много 500 MB." + }, + "updateKey": { + "message": "Трябва да обновите шифриращия си ключ, за да използвате тази възможност." + }, + "editedFolder": { + "message": "Редактирана папка" + }, + "addedFolder": { + "message": "Добавена папка" + }, + "deleteFolderConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете тази папка?" + }, + "deletedFolder": { + "message": "Изтрита папка" + }, + "loginOrCreateNewAccount": { + "message": "Впишете се или създайте нов абонамент, за да достъпите защитен трезор." + }, + "createAccount": { + "message": "Създаване на абонамент" + }, + "logIn": { + "message": "Вписване" + }, + "submit": { + "message": "Подаване" + }, + "masterPass": { + "message": "Главна парола" + }, + "masterPassDesc": { + "message": "Главната парола се използва за достъп до трезора ви. Запомнете я добре, защото възстановяването ѝ е абсолютно невъзможно." + }, + "masterPassHintDesc": { + "message": "Ако сте забравили главната парола, то подсказването може да ви помогне да си я припомните." + }, + "reTypeMasterPass": { + "message": "Повторно въвеждане на главната парола" + }, + "masterPassHint": { + "message": "Подсказване за главната парола (по избор)" + }, + "settings": { + "message": "Настройки" + }, + "passwordHint": { + "message": "Подсказка за паролата" + }, + "enterEmailToGetHint": { + "message": "Въведете адреса на е-пощата си, за да получите подсказка за главната парола." + }, + "getMasterPasswordHint": { + "message": "Получете подсказване за главната парола" + }, + "emailRequired": { + "message": "Електронната поща е задължителна." + }, + "invalidEmail": { + "message": "Грешен адрес на е-поща." + }, + "masterPassRequired": { + "message": "Главната парола е задължителна." + }, + "masterPassLength": { + "message": "Главната парола трябва да съдържа поне 8 знака." + }, + "masterPassDoesntMatch": { + "message": "Главната парола и потвърждението ѝ не съвпадат." + }, + "newAccountCreated": { + "message": "Абонаментът ви бе създаден. Вече можете да се впишете." + }, + "masterPassSent": { + "message": "Изпратили сме ви е-писмо с подсказка за главната ви парола." + }, + "unexpectedError": { + "message": "Неочаквана грешка." + }, + "itemInformation": { + "message": "Сведения за елемента" + }, + "noItemsInList": { + "message": "Няма елементи за показване." + }, + "sendVerificationCode": { + "message": "Изпращане на код за потвърждаване до Вашата ел. поща" + }, + "sendCode": { + "message": "Изпращане на кода" + }, + "codeSent": { + "message": "Кодът е изпратен" + }, + "verificationCode": { + "message": "Код за потвърждаване" + }, + "confirmIdentity": { + "message": "Потвърдете самоличността си, за да продължите." + }, + "verificationCodeRequired": { + "message": "Кодът за потвърждение е задължителен." + }, + "invalidVerificationCode": { + "message": "Грешен код за потвърждаване" + }, + "continue": { + "message": "Продължаване" + }, + "enterVerificationCodeApp": { + "message": "Въведете шестцифрения код за потвърждение от приложението за удостоверяване." + }, + "enterVerificationCodeEmail": { + "message": "Въведете шестцифрения код за потвърждение, който е бил изпратен на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Писмото за потвърждение е изпратено на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запомняне" + }, + "sendVerificationCodeEmailAgain": { + "message": "Повторно изпращане на писмото за потвърждение" + }, + "useAnotherTwoStepMethod": { + "message": "Използвайте друг начин на двустепенно удостоверяване" + }, + "insertYubiKey": { + "message": "Поставете устройството на YubiKey в USB порт на компютъра и натиснете бутона на устройството." + }, + "insertU2f": { + "message": "Поставете устройството за удостоверяване в USB порт на компютъра. Ако на устройството има бутон, натиснете го." + }, + "recoveryCodeDesc": { + "message": "Ако сте загубили достъп до двустепенното удостоверяване, може да използвате код за възстановяване, за да изключите двустепенното удостоверяване в абонамента си." + }, + "recoveryCodeTitle": { + "message": "Код за възстановяване" + }, + "authenticatorAppTitle": { + "message": "Приложение за удостоверяване" + }, + "authenticatorAppDesc": { + "message": "Използвайте приложение за удостоверяване (като Authy или Google Authenticator) за генерирането на временни кодове за потвърждение.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Устройство YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Използвайте устройство на YubiKey, за да влезете в абонамента си. Поддържат се моделите YubiKey 4, 4 Nano, 4C и NEO." + }, + "duoDesc": { + "message": "Удостоверяване чрез Duo Security, с ползване на приложението Duo Mobile, SMS, телефонен разговор или устройство U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Удостоверяване чрез Duo Security за организацията ви, с ползване на приложението Duo Mobile, SMS, телефонен разговор или устройство U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Използвайте всяко устройство, поддържащо WebAuthn, за да влезете в абонамента си." + }, + "emailTitle": { + "message": "Електронна поща" + }, + "emailDesc": { + "message": "Кодовете за потвърждение ще ви бъдат пратени по е-поща." + }, + "loginUnavailable": { + "message": "Записът липсва" + }, + "noTwoStepProviders": { + "message": "Регистрацията е защитена с двустепенно удостоверяване, но никой от настроените доставчици на удостоверяване не се поддържа от тази система." + }, + "noTwoStepProviders2": { + "message": "Пробвайте с други доставчици на удостоверяване, които се поддържат от повече системи (като специални програми за удостоверяване)." + }, + "twoStepOptions": { + "message": "Настройки на двустепенното удостоверяване" + }, + "selfHostedEnvironment": { + "message": "Собствена среда" + }, + "selfHostedEnvironmentFooter": { + "message": "Укажете базовия адрес за собствената ви инсталирана среда на Bitwarden." + }, + "customEnvironment": { + "message": "Специална среда" + }, + "customEnvironmentFooter": { + "message": "За специални случаи. Може да укажете основните адреси на всяка ползвана услуга поотделно." + }, + "baseUrl": { + "message": "Адрес на сървъра" + }, + "apiUrl": { + "message": "Адрес на ППИ-сървъра" + }, + "webVaultUrl": { + "message": "Адрес на сървъра с трезора в уеб" + }, + "identityUrl": { + "message": "Адрес на сървъра със самоличности" + }, + "notificationsUrl": { + "message": "Адрес на сървъра за уведомления" + }, + "iconsUrl": { + "message": "Адрес на сървъра с иконки" + }, + "environmentSaved": { + "message": "Средата с адресите е запазена." + }, + "ok": { + "message": "Добре" + }, + "yes": { + "message": "Да" + }, + "no": { + "message": "Не" + }, + "overwritePassword": { + "message": "Обновяване на паролата" + }, + "learnMore": { + "message": "Научете повече" + }, + "featureUnavailable": { + "message": "Функцията е недостъпна" + }, + "loggedOut": { + "message": "Бяхте отписани" + }, + "loginExpired": { + "message": "Сесията ви изтече." + }, + "logOutConfirmation": { + "message": "Сигурни ли сте, че искате да се отпишете?" + }, + "logOut": { + "message": "Отписване" + }, + "addNewLogin": { + "message": "Добавяне на нов запис" + }, + "addNewItem": { + "message": "Добавяне на нов елемент" + }, + "addNewFolder": { + "message": "Добавяне на нова папка" + }, + "view": { + "message": "Преглед" + }, + "account": { + "message": "Регистрация" + }, + "loading": { + "message": "Зареждане…" + }, + "lockVault": { + "message": "Заключване на трезора" + }, + "passwordGenerator": { + "message": "Създаване на пароли" + }, + "contactUs": { + "message": "Свържете се с нас" + }, + "getHelp": { + "message": "Помощ" + }, + "fileBugReport": { + "message": "Съобщаване за грешка" + }, + "blog": { + "message": "Блог" + }, + "followUs": { + "message": "Следвайте ни" + }, + "syncVault": { + "message": "Синхронизиране" + }, + "changeMasterPass": { + "message": "Промяна на главната парола" + }, + "changeMasterPasswordConfirmation": { + "message": "Главната парола на трезор може да се промени чрез сайта bitwarden.com. Искате ли да го посетите?" + }, + "fingerprintPhrase": { + "message": "Уникална фраза", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Уникална фраза, идентифицираща абонамента ви", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Към трезора по уеб" + }, + "getMobileApp": { + "message": "Изтегляне на мобилно приложение" + }, + "getBrowserExtension": { + "message": "Изтегляне на разширение за браузъра" + }, + "syncingComplete": { + "message": "Синхронизацията завърши" + }, + "syncingFailed": { + "message": "Неуспешна синхронизация" + }, + "yourVaultIsLocked": { + "message": "Трезорът е заключен — въведете главната си парола, за да продължите." + }, + "unlock": { + "message": "Отключване" + }, + "loggedInAsOn": { + "message": "Влезли сте като $EMAIL$ в $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Грешна главна парола" + }, + "twoStepLoginConfirmation": { + "message": "Двустепенното вписване защищава регистрацията ви като ви кара да потвърдите влизането си чрез устройство-ключ, приложение за идентификация, мобилно съобщение, телефонно обаждане или е-поща. Двустепенното вписване може да се включи чрез сайта bitwarden.com. Искате ли да го посетите?" + }, + "twoStepLogin": { + "message": "Двустепенно удостоверяване" + }, + "vaultTimeout": { + "message": "Време за достъп" + }, + "vaultTimeoutDesc": { + "message": "Изберете колко да е времето за достъп и какво ще е действието след това." + }, + "immediately": { + "message": "Незабавно" + }, + "tenSeconds": { + "message": "10 сек." + }, + "twentySeconds": { + "message": "20 сек." + }, + "thirtySeconds": { + "message": "30 сек." + }, + "oneMinute": { + "message": "1 мин." + }, + "twoMinutes": { + "message": "2 мин." + }, + "fiveMinutes": { + "message": "5 мин." + }, + "fifteenMinutes": { + "message": "15 мин." + }, + "thirtyMinutes": { + "message": "30 мин." + }, + "oneHour": { + "message": "1 час" + }, + "fourHours": { + "message": "4 ча̀са" + }, + "onIdle": { + "message": "При бездействие на системата" + }, + "onSleep": { + "message": "При заспиване на системата" + }, + "onLocked": { + "message": "При заключване на системата" + }, + "onRestart": { + "message": "При повторно пускане на системата" + }, + "never": { + "message": "Никога" + }, + "security": { + "message": "Сигурност" + }, + "clearClipboard": { + "message": "Изчистване на буфера", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Автоматично изчистване на буфера след поставяне на стойността.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Без иконки на сайтовете" + }, + "disableFaviconDesc": { + "message": "Иконките на сайтовете са разпознаваемо изображение за всеки запис в трезора." + }, + "enableMinToTray": { + "message": "Смаляване в областта за уведомяване" + }, + "enableMinToTrayDesc": { + "message": "При смаляване на прозореца да се показва иконка в областта за уведомяване." + }, + "enableMinToMenuBar": { + "message": "Минимизиране в лентата за меню" + }, + "enableMinToMenuBarDesc": { + "message": "При минимизиране на прозореца да се показва иконка в лентата за меню." + }, + "enableCloseToTray": { + "message": "Затваряне в областта за уведомяване" + }, + "enableCloseToTrayDesc": { + "message": "При затваряне на прозореца да се показва иконка в областта за уведомяване." + }, + "enableCloseToMenuBar": { + "message": "Затваряне в лентата за меню" + }, + "enableCloseToMenuBarDesc": { + "message": "При затваряне на прозореца да се показва иконка в лентата за меню." + }, + "enableTray": { + "message": "Включване на иконката в областта за уведомяване" + }, + "enableTrayDesc": { + "message": "Постоянно показване на иконка в областта за уведомяване." + }, + "startToTray": { + "message": "Пускане с иконка в областта за уведомяване" + }, + "startToTrayDesc": { + "message": "При пускането на програмата да се показва само иконка в областта за уведомяване." + }, + "startToMenuBar": { + "message": "Стартиране в лентата за меню" + }, + "startToMenuBarDesc": { + "message": "При пускането на програмата да се показва само иконка в лентата за меню." + }, + "openAtLogin": { + "message": "Автоматично стартиране със системата" + }, + "openAtLoginDesc": { + "message": "Автоматично стартиране на самостоятелното приложение на Битуорден при вписване в системата." + }, + "alwaysShowDock": { + "message": "Винаги да се показва в дока" + }, + "alwaysShowDockDesc": { + "message": "Показване на иконата на Битуорден в дока, дори когато е минимизиран в лентата за меню." + }, + "confirmTrayTitle": { + "message": "Потвърждаване на изключване на областта за уведомяванията" + }, + "confirmTrayDesc": { + "message": "Изключването на настройката изключва всички други настройки за областта за уведомяванията." + }, + "language": { + "message": "Език" + }, + "languageDesc": { + "message": "Смяна на езика на интерфейса. Ще трябва да пуснете програмата повторно." + }, + "theme": { + "message": "Облик" + }, + "themeDesc": { + "message": "Промяна на цветовия облик на програмата." + }, + "dark": { + "message": "Тъмен", + "description": "Dark color" + }, + "light": { + "message": "Светъл", + "description": "Light color" + }, + "copy": { + "message": "Копиране", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Проверка за обновления" + }, + "version": { + "message": "Версия: $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Повторно пускане за обновяване" + }, + "restartToUpdateDesc": { + "message": "Версия: $VERSION_NUM$ вече може да се инсталира. За да завършите инсталацията, ще трябва да пуснете Bitwarden наново. Искате ли това да се извърши автоматично сега?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Има налично обновление" + }, + "updateAvailableDesc": { + "message": "Има налично обновление. Искате ли да се изтегли?" + }, + "restart": { + "message": "Повторно пускане" + }, + "later": { + "message": "По-късно" + }, + "noUpdatesAvailable": { + "message": "Няма обновления — ползвате последната версия!" + }, + "updateError": { + "message": "Грешка при обновяване" + }, + "unknown": { + "message": "Неизвестно" + }, + "copyUsername": { + "message": "Копиране на потребителското име" + }, + "copyNumber": { + "message": "Копиране на но̀мера", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Копиране на кода за сигурност", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Платен абонамент" + }, + "premiumManage": { + "message": "Управление на абонамента" + }, + "premiumManageAlert": { + "message": "Можете да управлявате своя абонамент през уеб сайта bitwarden.com. Искате ли да се отвори?" + }, + "premiumRefresh": { + "message": "Опресняване на абонамента" + }, + "premiumNotCurrentMember": { + "message": "В момента ползвате безплатен абонамент." + }, + "premiumSignUpAndGet": { + "message": "Платеният абонамент дава следните предимства:" + }, + "premiumSignUpStorage": { + "message": "1 ГБ пространство за файлове, които се шифроват." + }, + "premiumSignUpTwoStep": { + "message": "Двустепенно удостоверяване чрез YubiKey, FIDO U2F и Duo." + }, + "premiumSignUpReports": { + "message": "Проверки в списъците с публикувани пароли, проверка на регистрациите и доклади за пробивите в сигурността, което спомага трезорът ви да е допълнително защитен." + }, + "premiumSignUpTotp": { + "message": "Генериране на временни, еднократни кодове за двустепенно удостоверяване за регистрациите в трезора." + }, + "premiumSignUpSupport": { + "message": "Приоритетна поддръжка." + }, + "premiumSignUpFuture": { + "message": "Всички бъдещи ползи! Предстои въвеждането на още!" + }, + "premiumPurchase": { + "message": "Покупка на платен абонамент" + }, + "premiumPurchaseAlert": { + "message": "Може да платите абонамента си през сайта bitwarden.com. Искате ли да го посетите сега?" + }, + "premiumCurrentMember": { + "message": "Честито, ползвате платен абонамент!" + }, + "premiumCurrentMemberThanks": { + "message": "Благодарим ви за подкрепата на Bitwarden." + }, + "premiumPrice": { + "message": "И това само за $PRICE$ на година!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Абонаментът е опреснен" + }, + "passwordHistory": { + "message": "Хронология на паролата" + }, + "clear": { + "message": "Изчистване", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Няма пароли за показване." + }, + "undo": { + "message": "Отмяна" + }, + "redo": { + "message": "Връщане" + }, + "cut": { + "message": "Изрязване", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Поставяне", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Избиране на всичко" + }, + "zoomIn": { + "message": "Увеличаване" + }, + "zoomOut": { + "message": "Смаляване" + }, + "resetZoom": { + "message": "Стандартен мащаб" + }, + "toggleFullScreen": { + "message": "Превключване на цял екран" + }, + "reload": { + "message": "Презареждане" + }, + "toggleDevTools": { + "message": "Превключване на инструментите за разработчици" + }, + "minimize": { + "message": "Смаляване", + "description": "Minimize window" + }, + "zoom": { + "message": "Мащаб" + }, + "bringAllToFront": { + "message": "Всичко на преден план", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Относно" + }, + "services": { + "message": "Услуги" + }, + "hideBitwarden": { + "message": "Скриване на Bitwarden" + }, + "hideOthers": { + "message": "Скриване на другите" + }, + "showAll": { + "message": "Показване на всички" + }, + "quitBitwarden": { + "message": "Изход" + }, + "valueCopied": { + "message": "$VALUE$ — копирано", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Помощ" + }, + "window": { + "message": "Прозорец" + }, + "checkPassword": { + "message": "Проверка дали паролата е разкрита." + }, + "passwordExposed": { + "message": "Паролата е била разкрита поне $VALUE$ път/и в пробиви. Непременно я сменете.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Паролата не е била разкрита в известните пробиви. Засега ползването ѝ изглежда безопасно." + }, + "baseDomain": { + "message": "Основен домейн", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Име на домейн", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Сървър", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Точно" + }, + "startsWith": { + "message": "Започва с" + }, + "regEx": { + "message": "Регулярен израз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Откриване на съвпадения", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Стандартно откриване на съвпадения", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Настройки на превключване" + }, + "organization": { + "message": "Организация", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Стандартно" + }, + "exit": { + "message": "Изход" + }, + "showHide": { + "message": "Показване / Скриване", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Скриване в областта за уведомяване" + }, + "alwaysOnTop": { + "message": "Винаги отгоре", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Обновено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Обновена парола", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Изнасяне на трезора" + }, + "fileFormat": { + "message": "Формат на файла" + }, + "warning": { + "message": "ВНИМАНИЕ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Потвърждаване на изнасянето на трезора" + }, + "exportWarningDesc": { + "message": "Данните от трезора ви ще се изнесат в незащитен формат. Не го пращайте по незащитени канали като е-поща. Изтрийте файла незабавно след като свършите работата си с него." + }, + "encExportKeyWarningDesc": { + "message": "При изнасяне данните се шифрират с ключа ви. Ако го смените, ще трябва наново да ги изнесете, защото няма да може да дешифрирате настоящия файл." + }, + "encExportAccountWarningDesc": { + "message": "Ключовете за шифриране са уникални за всеки потребител, затова не може да внесете шифрирани данни от един потребител в регистрацията на друг." + }, + "noOrganizationsList": { + "message": "Не сте член на никоя организация. Организациите позволяват да споделяте записи с други потребители по защитен начин." + }, + "noCollectionsInList": { + "message": "Няма колекции за показване." + }, + "ownership": { + "message": "Собственост" + }, + "whoOwnsThisItem": { + "message": "Кой притежава този запис?" + }, + "strong": { + "message": "Силна", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Добра", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слаба", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слаба главна парола" + }, + "weakMasterPasswordDesc": { + "message": "Зададената главна парола е твърде слаба. Главната парола трябва да е силна. Добре е да ползвате цяла фраза за парола, за да защитите данните в трезора в Bitwarden. Уверени ли сте, че искате да ползвате слаба парола?" + }, + "pin": { + "message": "ПИН", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Отключване с ПИН" + }, + "setYourPinCode": { + "message": "Задайте ПИН за отключване на Bitwarden. Настройките за ПИН се изчистват при всяко пълно излизане от програмата." + }, + "pinRequired": { + "message": "Необходим е ПИН." + }, + "invalidPin": { + "message": "Неправилен ПИН." + }, + "unlockWithWindowsHello": { + "message": "Отключване с Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Потвърждаване за Битуорден." + }, + "unlockWithTouchId": { + "message": "Отключване с Touch ID" + }, + "touchIdConsentMessage": { + "message": "Потвърждаване за Битуорден." + }, + "noAutoPromptWindowsHello": { + "message": "Да не се изисква Windows Hello при стартиране." + }, + "noAutoPromptTouchId": { + "message": "Да не се изисква Touch ID при стартиране." + }, + "lockWithMasterPassOnRestart": { + "message": "Заключване с главната парола при повторно пускане" + }, + "preferences": { + "message": "Настройки" + }, + "enableMenuBar": { + "message": "Икона в лентата с менюта" + }, + "enableMenuBarDesc": { + "message": "Винаги да се показва икона в лентата с менюта." + }, + "hideToMenuBar": { + "message": "Скриване в лентата с менюта" + }, + "selectOneCollection": { + "message": "Изберете поне една колекция." + }, + "premiumUpdated": { + "message": "Вече ползвате платен абонамент." + }, + "restore": { + "message": "Възстановяване" + }, + "premiumManageAlertAppStore": { + "message": "Можете да управлявате абонамента си от уеб магазина „App Store“. Искате ли да го посетите сега?" + }, + "legal": { + "message": "Правни въпроси", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Общи условия" + }, + "privacyPolicy": { + "message": "Политика за поверителност" + }, + "unsavedChangesConfirmation": { + "message": "Сигурни ли сте, че искате да напуснете? Текущата ви информация няма да бъде запазена." + }, + "unsavedChangesTitle": { + "message": "Незапазени промени" + }, + "clone": { + "message": "Дублиране" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Поне една политика на организация влияе на настройките на генерирането на паролите." + }, + "vaultTimeoutAction": { + "message": "Действие при изтичане на времето" + }, + "vaultTimeoutActionLockDesc": { + "message": "При заключване на трезора ще ви се наложи отново да въведете паролата си, за да го достъпите." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "При изход от трезора ще ви се наложи отново да се идентифицирате, за да го достъпите." + }, + "lock": { + "message": "Заключване", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Кошче", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Търсене в кошчето" + }, + "permanentlyDeleteItem": { + "message": "Окончателно изтриване на запис" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете записа окончателно?" + }, + "permanentlyDeletedItem": { + "message": "Записът е изтрит окончателно" + }, + "restoreItem": { + "message": "Възстановяване на запис" + }, + "restoreItemConfirmation": { + "message": "Сигурни ли сте, че искате да възстановите записа?" + }, + "restoredItem": { + "message": "Записът е възстановен" + }, + "permanentlyDelete": { + "message": "Окончателно изтриване" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Излизането от трезора изцяло спира достъпа до него след изтичане на времето. Ще ви се наложи отново да се идентифицирате, за да го достъпите. Сигурни ли сте, че искате това действие?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Потвърждаване на действието" + }, + "enterpriseSingleSignOn": { + "message": "Еднократна идентификация (SSO)" + }, + "setMasterPassword": { + "message": "Задаване на главна парола" + }, + "ssoCompleteRegistration": { + "message": "За да завършите настройките за еднократна идентификация, трябва да зададете главна парола за трезора." + }, + "newMasterPass": { + "message": "Нова главна парола" + }, + "confirmNewMasterPass": { + "message": "Потвърждаване на новата главна парола" + }, + "masterPasswordPolicyInEffect": { + "message": "Поне една политика на организация има следните изисквания към главната ви парола:" + }, + "policyInEffectMinComplexity": { + "message": "Минимална сложност от $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Минимална дължина: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Поне една главна буква" + }, + "policyInEffectLowercase": { + "message": "Поне една малка буква" + }, + "policyInEffectNumbers": { + "message": "Поне една цифра" + }, + "policyInEffectSpecial": { + "message": "Поне един от следните специални знаци: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Паролата ви не отговаря на политиките." + }, + "acceptPolicies": { + "message": "Чрез тази отметка вие се съгласявате със следното:" + }, + "acceptPoliciesError": { + "message": "Условията за използване и политиката за поверителност не бяха приети." + }, + "enableBrowserIntegration": { + "message": "Включване на интеграцията с браузър" + }, + "enableBrowserIntegrationDesc": { + "message": "За потвърждаване с биометрични данни е необходима интеграция с браузъра." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Интеграцията с браузър не се поддържа" + }, + "browserIntegrationMasOnlyDesc": { + "message": "За жалост в момента интеграцията с браузър не се поддържа във версията за магазина на Mac." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Интеграцията с браузър не се поддържа" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "За жалост в момента интеграцията с браузър не се поддържа във версията за магазина на Windows." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Потвърждаване на интеграцията с браузър" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Допълнително ниво на сигурност, чрез изискване на потвърждаване на биометричните данни при създаване на връзка между самостоятелното приложение и браузъра. При включваното му потребителят трябва да потвърждава всяко установяване на връзка." + }, + "approve": { + "message": "Одобряване" + }, + "verifyBrowserTitle": { + "message": "Проверка на връзката с браузъра" + }, + "verifyBrowserDesc": { + "message": "Уверете се, че идентификаторът в разширението съвпада с показания." + }, + "biometricsNotEnabledTitle": { + "message": "Потвърждаването с биометрични данни не е включено" + }, + "biometricsNotEnabledDesc": { + "message": "Потвърждаването с биометрични данни в браузъра изисква включването включването им в настройките за самостоятелното приложение." + }, + "personalOwnershipSubmitError": { + "message": "Заради някоя политика за голяма организация не може да запазвате елементи в собствения си трезор. Променете собствеността да е на организация и изберете от наличните колекции." + }, + "hintEqualsPassword": { + "message": "Подсказването за паролата не може да съвпада с нея." + }, + "personalOwnershipPolicyInEffect": { + "message": "Политика от някоя организация влияе на вариантите за собственост." + }, + "allSends": { + "message": "Всички изпращания", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Файл" + }, + "sendTypeText": { + "message": "Текст" + }, + "searchSends": { + "message": "Търсене в изпратените", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Редактиране на изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Моят трезор" + }, + "text": { + "message": "Текст" + }, + "deletionDate": { + "message": "Дата на изтриване" + }, + "deletionDateDesc": { + "message": "Изпращането ще бъде окончателно изтрито на зададената дата и време.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Срок на валидност" + }, + "expirationDateDesc": { + "message": "При задаване — това изпращане ще се изключи на зададената дата и време.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Максимален брой достъпвания" + }, + "maxAccessCountDesc": { + "message": "При задаване — това изпращане ще се изключи след определен брой достъпвания.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Текущ брой на достъпванията" + }, + "disableSend": { + "message": "Пълно спиране на това изпращане — никой няма да има достъп.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Изискване на парола за достъп до това изпращане.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Скрити бележки за това изпращане.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Изпращане на връзката", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Изпращане на връзката", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "При достъп до изпращането стандартно текстът да се скрива", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Създадено изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Редактиране на изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Изтрито изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Нова парола" + }, + "whatTypeOfSend": { + "message": "Вид на изпратеното", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Създаване на изпращане", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст за изпращане." + }, + "sendFileDesc": { + "message": "Файл за изпращане." + }, + "days": { + "message": "$DAYS$ ден/дни", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 ден" + }, + "custom": { + "message": "По избор" + }, + "deleteSendConfirmation": { + "message": "Сигурни ли сте, че искате да изтриете това изпращане?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Копиране на връзката към изпращането", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Копиране на връзката към изпращането при запазването му за лесно споделяне." + }, + "sendDisabled": { + "message": "Изпращането е изключено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Поради политика на организация, може само да изтривате съществуващи изпращания.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Копиране на връзката" + }, + "disabled": { + "message": "Изключено" + }, + "maxAccessCountReached": { + "message": "Достигнат е максималният брой достъпвания" + }, + "expired": { + "message": "Изтекъл" + }, + "pendingDeletion": { + "message": "Предстои изтриване" + }, + "webAuthnAuthenticate": { + "message": "Идентификация WebAuthn" + }, + "hideEmail": { + "message": "Скриване на е-пощата ми от получателите." + }, + "sendOptionsPolicyInEffect": { + "message": "Поне една политика на организация влияе на настройките за изпращане." + }, + "emailVerificationRequired": { + "message": "Изисква се потвърждение на е-пощата" + }, + "emailVerificationRequiredDesc": { + "message": "Трябва да потвърдите е-пощата си, за да можете да използвате тази функционалност." + }, + "passwordPrompt": { + "message": "Повторно запитване за главната парола" + }, + "passwordConfirmation": { + "message": "Потвърждение на главната парола" + }, + "passwordConfirmationDesc": { + "message": "Това действие е защитено. За да продължите, въведете отново главната си парола, за да потвърдите самоличността си." + }, + "updatedMasterPassword": { + "message": "Главната парола е променена" + }, + "updateMasterPassword": { + "message": "Промяна на главната парола" + }, + "updateMasterPasswordWarning": { + "message": "Вашата главна парола наскоро е била сменена от администратор в организацията Ви. За да получите достъп до трезора, трябва първо да я промените. Това означава, че ще бъдете отписан(а) от текущата си сесия и ще трябва да се впишете отново. Активните сесии на други устройства може да продължат да бъдат активни още един час." + }, + "hours": { + "message": "Часа" + }, + "minutes": { + "message": "Минути" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Настройките на организацията Ви влияят върху времето за достъп до трезора Ви. Максималното разрешено време за достъп е $HOURS$ час(а) и $MINUTES$ минути", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Времето за достъп до трезора Ви превишава ограничението, определено от организацията Ви." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Автоматично включване" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Тази организация включва автоматично новите си потребители в смяната на пароли. Това означава, че администраторите на организацията ще могат да променят главната Ви парола." + }, + "vaultExportDisabled": { + "message": "Изнасянето на трезора е изключено" + }, + "personalVaultExportPolicyInEffect": { + "message": "Една или повече от настройките на организацията Ви не позволяват да изнасяте личния си трезор." + }, + "addAccount": { + "message": "Добавяне на регистрация" + }, + "removeMasterPassword": { + "message": "Премахване на главната парола" + }, + "removedMasterPassword": { + "message": "Главната парола е премахната." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ използва еднократно удостоверяване със собствен сървър за ключове. Членовете на тази организация вече нямат нужда от главна парола за вписване.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Напускане на организацията" + }, + "leaveOrganizationConfirmation": { + "message": "Наистина ли искате да напуснете тази организация?" + }, + "leftOrganization": { + "message": "Напуснахте организацията." + }, + "ssoKeyConnectorUnavailable": { + "message": "Конекторът за ключове е недостъпен. Опитайте отново по-късно." + }, + "lockAllVaults": { + "message": "Заключване на всички трезори" + }, + "accountLimitReached": { + "message": "Не може едновременно да са вписани повече от 5 регистрации." + }, + "accountPreferences": { + "message": "Настройки" + }, + "appPreferences": { + "message": "Настройки на приложението (за всички регистрирани)" + }, + "accountSwitcherLimitReached": { + "message": "Достигнато е ограничението на броя регистрации. Излезте от някоя, за да добавите друга." + }, + "settingsTitle": { + "message": "Настройки на приложението за $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Превключване на потребителя" + }, + "options": { + "message": "Настройки" + }, + "sessionTimeout": { + "message": "Сесията Ви изтече. Моля, върнете се назад и се опитайте да влезете отново." + }, + "exportingPersonalVaultTitle": { + "message": "Изнасяне на личния трезор" + }, + "exportingPersonalVaultDescription": { + "message": "Ще бъдат изнесени само записите от личния трезор свързан с $EMAIL$. Записите в трезора на организацията няма да бъдат включени.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Генератор" + }, + "whatWouldYouLikeToGenerate": { + "message": "Какво бихте искали да генерирате?" + }, + "passwordType": { + "message": "Тип парола" + }, + "regenerateUsername": { + "message": "Повторно генериране на потр. име" + }, + "generateUsername": { + "message": "Генериране на потр. име" + }, + "usernameType": { + "message": "Тип потребителско име" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Използвайте възможностите за под-адресиране на е-поща на своя доставчик." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Произволно" + }, + "randomWord": { + "message": "Произволна дума" + }, + "websiteName": { + "message": "Име на уеб сайт" + }, + "service": { + "message": "Услуга" + } +} diff --git a/apps/desktop/src/locales/bn/messages.json b/apps/desktop/src/locales/bn/messages.json new file mode 100644 index 0000000000..4b6395ce3f --- /dev/null +++ b/apps/desktop/src/locales/bn/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "ফিল্টার" + }, + "allItems": { + "message": "সকল বস্তু" + }, + "favorites": { + "message": "প্রিয়গুলো" + }, + "types": { + "message": "প্রকার" + }, + "typeLogin": { + "message": "লগইন" + }, + "typeCard": { + "message": "কার্ড" + }, + "typeIdentity": { + "message": "পরিচয়" + }, + "typeSecureNote": { + "message": "সুরক্ষিত নোট" + }, + "folders": { + "message": "ফোল্ডারসমূহ" + }, + "collections": { + "message": "সংগ্রহ" + }, + "searchVault": { + "message": "ভল্ট খুঁজুন" + }, + "addItem": { + "message": "বস্তু জুড়ুন" + }, + "shared": { + "message": "ভাগকৃত" + }, + "share": { + "message": "ভাগ করুন" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "সংযুক্তি" + }, + "viewItem": { + "message": "বস্তু দেখুন" + }, + "name": { + "message": "নাম" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "নতুন URI" + }, + "username": { + "message": "ব্যবহারকারীর নাম" + }, + "password": { + "message": "পাসওয়ার্ড" + }, + "passphrase": { + "message": "পাসফ্রেজ" + }, + "editItem": { + "message": "বস্তু সম্পাদনা" + }, + "emailAddress": { + "message": "ইমেইল ঠিকানা" + }, + "verificationCodeTotp": { + "message": "যাচাইকরণ কোড (TOTP)" + }, + "website": { + "message": "ওয়েবসাইট" + }, + "notes": { + "message": "মন্তব্য" + }, + "customFields": { + "message": "পছন্দসই ক্ষেত্র" + }, + "launch": { + "message": "শুরু" + }, + "copyValue": { + "message": "মান অনুলিপিত করুন", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "দৃশ্যমানতা টগল করুন" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "কার্ডধারীর নাম" + }, + "number": { + "message": "নম্বর" + }, + "brand": { + "message": "ব্র্যান্ড" + }, + "expiration": { + "message": "মেয়াদোত্তীর্ণতা" + }, + "securityCode": { + "message": "নিরাপত্তা কোড" + }, + "identityName": { + "message": "পরিচয়ের নাম" + }, + "company": { + "message": "প্রতিষ্ঠান" + }, + "ssn": { + "message": "সামাজিক সুরক্ষা নম্বর" + }, + "passportNumber": { + "message": "পাসপোর্ট নম্বর" + }, + "licenseNumber": { + "message": "লাইসেন্স নম্বর" + }, + "email": { + "message": "ইমেইল" + }, + "phone": { + "message": "ফোন" + }, + "address": { + "message": "ঠিকানা" + }, + "premiumRequired": { + "message": "প্রিমিয়াম আবশ্যক" + }, + "premiumRequiredDesc": { + "message": "এই বৈশিষ্ট্যটি ব্যবহার করতে একটি প্রিমিয়াম সদস্যতার প্রয়োজন।" + }, + "errorOccurred": { + "message": "একটি ত্রুটি উৎপন্ন হয়েছে।" + }, + "error": { + "message": "ত্রুটি" + }, + "january": { + "message": "জানুয়ারী" + }, + "february": { + "message": "ফেব্রুয়ারী" + }, + "march": { + "message": "মার্চ" + }, + "april": { + "message": "এপ্রিল" + }, + "may": { + "message": "মে" + }, + "june": { + "message": "জুন" + }, + "july": { + "message": "জুলাই" + }, + "august": { + "message": "আগস্ট" + }, + "september": { + "message": "সেপ্টেম্বর" + }, + "october": { + "message": "অক্টোবর" + }, + "november": { + "message": "নভেম্বর" + }, + "december": { + "message": "ডিসেম্বর" + }, + "ex": { + "message": "উদাহরণ", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "শিরোনাম" + }, + "mr": { + "message": "জনাব" + }, + "mrs": { + "message": "জনাবা" + }, + "ms": { + "message": "জনাবা" + }, + "dr": { + "message": "ডাঃ" + }, + "expirationMonth": { + "message": "মেয়াদোত্তীর্ণ মাস" + }, + "expirationYear": { + "message": "মেয়াদোত্তীর্ণ বছর" + }, + "select": { + "message": "নির্বাচন করুন" + }, + "other": { + "message": "অন্যান্য" + }, + "generatePassword": { + "message": "পাসওয়ার্ড তৈরি করুন" + }, + "type": { + "message": "ধরন" + }, + "firstName": { + "message": "নামের প্রথমাংশ" + }, + "middleName": { + "message": "নামের মধ্যাংশ" + }, + "lastName": { + "message": "নামের শেষাংশ" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "ঠিকানা ১" + }, + "address2": { + "message": "ঠিকানা ২" + }, + "address3": { + "message": "ঠিকানা ৩" + }, + "cityTown": { + "message": "শহর" + }, + "stateProvince": { + "message": "রাজ্য / প্রদেশ" + }, + "zipPostalCode": { + "message": "জিপ / ডাক কোড" + }, + "country": { + "message": "দেশ" + }, + "save": { + "message": "সংরক্ষণ" + }, + "cancel": { + "message": "বাতিল" + }, + "delete": { + "message": "মুছুন" + }, + "favorite": { + "message": "প্রিয়" + }, + "edit": { + "message": "সম্পাদনা" + }, + "authenticatorKeyTotp": { + "message": "প্রমাণীকরণকারী কী (TOTP)" + }, + "folder": { + "message": "ফোল্ডার" + }, + "newCustomField": { + "message": "নতুন পছন্দসই ক্ষেত্র" + }, + "value": { + "message": "মান" + }, + "dragToSort": { + "message": "বাছাই করতে টানুন" + }, + "cfTypeText": { + "message": "পাঠ্য" + }, + "cfTypeHidden": { + "message": "লুকায়িত" + }, + "cfTypeBoolean": { + "message": "বুলিয়ান" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "সরান" + }, + "nameRequired": { + "message": "নাম প্রয়োজন।" + }, + "addedItem": { + "message": "বস্তু যোগ করা হয়েছে" + }, + "editedItem": { + "message": "সম্পাদিত বস্তু" + }, + "deleteItem": { + "message": "বস্তু মুছুন" + }, + "deleteFolder": { + "message": "ফোল্ডার মুছুন" + }, + "deleteAttachment": { + "message": "সংযুক্তি মুছুন" + }, + "deleteItemConfirmation": { + "message": "আপনি কি সত্যিই আবর্জনাতে পাঠাতে চান?" + }, + "deletedItem": { + "message": "বস্তুতটি আবর্জনাতে পাঠানো হয়েছে" + }, + "overwritePasswordConfirmation": { + "message": "আপনি কি নিশ্চিত যে আপনি বর্তমান পাসওয়ার্ডটি ওভাররাইট করতে চান?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "কোন ফোল্ডার নেই", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "ফোল্ডার জুড়ুন" + }, + "editFolder": { + "message": "ফোল্ডার সম্পাদনা" + }, + "regeneratePassword": { + "message": "পাসওয়ার্ড পুনঃতৈরি করুন" + }, + "copyPassword": { + "message": "পাসওয়ার্ড অনুলিপিত করুন" + }, + "copyUri": { + "message": "URI অনুলিপিত করুন" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "দৈর্ঘ্য" + }, + "numWords": { + "message": "শব্দের সংখ্যা" + }, + "wordSeparator": { + "message": "শব্দ বিভাজক" + }, + "capitalize": { + "message": "বড় হাতের করুন", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "নম্বর অন্তর্ভুক্ত করুন" + }, + "close": { + "message": "বন্ধ করুন" + }, + "minNumbers": { + "message": "সর্বনিম্ন সংখ্যা" + }, + "minSpecial": { + "message": "ন্যূনতম বিশেষ", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "অস্পষ্ট বর্ণগুলি এড়িয়ে চলুন" + }, + "searchCollection": { + "message": "সংগ্রহ অনুসন্ধান" + }, + "searchFolder": { + "message": "ফোল্ডার অনুসন্ধান" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "অনুসন্ধানের ধরন", + "description": "Search item type" + }, + "newAttachment": { + "message": "নতুন সংযুক্তি জুড়ুন" + }, + "deletedAttachment": { + "message": "সংযুক্তি মোছা হয়েছে" + }, + "deleteAttachmentConfirmation": { + "message": "আপনি কি এই সংযুক্তিটি মোছার বিষয়ে নিশ্চিত?" + }, + "attachmentSaved": { + "message": "সংযুক্তিটি সংরক্ষণ করা হয়েছে।" + }, + "file": { + "message": "ফাইল" + }, + "selectFile": { + "message": "একটি ফাইল নির্বাচন করুন।" + }, + "maxFileSize": { + "message": "সর্বোচ্চ ফাইলের আকার ১০০ এমবি।" + }, + "updateKey": { + "message": "আপনি আপনার এনক্রিপশন কী হালনাগাদ না করা পর্যন্ত এই বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না।" + }, + "editedFolder": { + "message": "ফোল্ডার সম্পাদিত" + }, + "addedFolder": { + "message": "ফোল্ডার জোড়া হয়েছে" + }, + "deleteFolderConfirmation": { + "message": "আপনি কি নিশ্চিত যে এই ফোল্ডারটি মুছতে চান?" + }, + "deletedFolder": { + "message": "ফোল্ডার মোছা হয়েছে" + }, + "loginOrCreateNewAccount": { + "message": "আপনার সুরক্ষিত ভল্টে প্রবেশ করতে লগ ইন করুন অথবা একটি নতুন অ্যাকাউন্ট তৈরি করুন।" + }, + "createAccount": { + "message": "অ্যাকাউন্ট তৈরি করুন" + }, + "logIn": { + "message": "প্রবেশ করুন" + }, + "submit": { + "message": "জমা দিন" + }, + "masterPass": { + "message": "মূল পাসওয়ার্ড" + }, + "masterPassDesc": { + "message": "মূল পাসওয়ার্ড হল সেই পাসওয়ার্ডটি যা আপনি নিজের ভল্ট ব্যাবহার করতে ব্যবহার করেন। এটি খুব গুরুত্বপূর্ণ যে আপনি নিজের মূল পাসওয়ার্ডটি ভুলে যাবেন না। আপনি যদি ভুলে গিয়ে থাকেন তবে পাসওয়ার্ডটি পুনরুদ্ধার করার কোনও উপায় নেই।" + }, + "masterPassHintDesc": { + "message": "যদি আপনি আপনার পাসওয়ার্ড ভুলে যান তাহলে একটি মূল পাসওয়ার্ডের ইঙ্গিতটি আপনাকে মনে করাতে সাহায্য করতে পারে।" + }, + "reTypeMasterPass": { + "message": "পুনরায় মূল পাসওয়ার্ডটি লিখুন" + }, + "masterPassHint": { + "message": "মূল পাসওয়ার্ড ইঙ্গিত (ঐচ্ছিক)" + }, + "settings": { + "message": "সেটিংস" + }, + "passwordHint": { + "message": "পাসওয়ার্ড ইঙ্গিত" + }, + "enterEmailToGetHint": { + "message": "আপনার মূল পাসওয়ার্ডের ইঙ্গিতটি পেতে আপনার অ্যাকাউন্টের ইমেল ঠিকানা প্রবেশ করুন।" + }, + "getMasterPasswordHint": { + "message": "মূল পাসওয়ার্ডের ইঙ্গিত পান" + }, + "emailRequired": { + "message": "ইমেইল ঠিকানা প্রয়োজন।" + }, + "invalidEmail": { + "message": "অকার্যকর ইমেইল ঠিকানা।" + }, + "masterPassRequired": { + "message": "মূল পাসওয়ার্ড প্রয়োজন।" + }, + "masterPassLength": { + "message": "মূল পাসওয়ার্ড কমপক্ষে ৮ অক্ষর দীর্ঘ হওয়া উচিত।" + }, + "masterPassDoesntMatch": { + "message": "মূল পাসওয়ার্ড নিশ্চিতকরণ মেলেনি।" + }, + "newAccountCreated": { + "message": "আপনার নতুন অ্যাকাউন্ট তৈরি করা হয়েছে! আপনি এখন প্রবেশ করতে পারেন।" + }, + "masterPassSent": { + "message": "আমরা আপনাকে আপনার মূল পাসওয়ার্ডের ইঙ্গিতসহ একটি ইমেল প্রেরণ করেছি।" + }, + "unexpectedError": { + "message": "একটি অপ্রত্যাশিত ত্রুটি ঘটেছে।" + }, + "itemInformation": { + "message": "বস্তু তথ্য" + }, + "noItemsInList": { + "message": "তালিকার জন্য কোনও বস্তু নেই।" + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "যাচাইকরণ কোড" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "যাচাইকরণ কোড প্রয়োজন।" + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "অবিরত" + }, + "enterVerificationCodeApp": { + "message": "আপনার প্রমাণীকরণকারী অ্যাপ থেকে ৬ সংখ্যার যাচাইকরণ কোডটি প্রবেশ করুন।" + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ এ ইমেইল করা ৬ সংখ্যার যাচাই কোডটি প্রবেশ করুন।", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "$EMAIL$ এ যাচাইকরণ ইমেইল প্রেরণ করা হয়েছে।", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "আমাকে মনে রাখবেন" + }, + "sendVerificationCodeEmailAgain": { + "message": "আবার যাচাইকরণ কোড ইমেইলে প্রেরণ করুন" + }, + "useAnotherTwoStepMethod": { + "message": "অন্য দ্বি-পদক্ষেপ প্রবেশ পদ্ধতি ব্যবহার করুন" + }, + "insertYubiKey": { + "message": "আপনার কম্পিউটারের ইউএসবি পোর্টে আপনার YubiKey ঢোকান, তারপরে তার বোতামটি স্পর্শ করুন।" + }, + "insertU2f": { + "message": "আপনার কম্পিউটারের ইউএসবি পোর্টে আপনার সুরক্ষা কী ঢোকান। এটিতে যদি একটি বোতাম থাকে তবে তা স্পর্শ করুন।" + }, + "recoveryCodeDesc": { + "message": "আপনার সমস্ত দ্বি-গুণক সরবরাহকারীদের অ্যাক্সেস হারিয়েছেন? আপনার অ্যাকাউন্ট থেকে সমস্ত দ্বি-গুণক সরবরাহকারীদের অক্ষম করতে আপনার পুনরুদ্ধার কোডটি ব্যবহার করুন।" + }, + "recoveryCodeTitle": { + "message": "পুনরুদ্ধার কোড" + }, + "authenticatorAppTitle": { + "message": "প্রমাণীকরণকারী অ্যাপ" + }, + "authenticatorAppDesc": { + "message": "সময় ভিত্তিক যাচাইকরণ কোড উৎপন্ন করতে একটি প্রমাণীকরণকারী অ্যাপ্লিকেশন (যেমন Authy বা Google Authenticator) ব্যবহার করুন।", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP সুরক্ষা কী" + }, + "yubiKeyDesc": { + "message": "আপনার অ্যাকাউন্ট ব্যাবহার করতে একটি YubiKey ব্যবহার করুন। YubiKey 4, 4 Nano, 4C, এবং NEO ডিভাইসগুলির সাথে কাজ করে।" + }, + "duoDesc": { + "message": "Duo Mobile app, এসএমএস, ফোন কল, বা U2F সুরক্ষা কী ব্যবহার করে Duo Security এর মাধ্যমে যাচাই করুন।", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo Mobile app, এসএমএস, ফোন কল, বা U2F সুরক্ষা কী ব্যবহার করে আপনার সংস্থার জন্য Duo Security এর মাধ্যমে যাচাই করুন।", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "ইমেইল" + }, + "emailDesc": { + "message": "যাচাই কোডগুলি আপনাকে ই-মেইল করা হবে।" + }, + "loginUnavailable": { + "message": "লগইন অনুপলব্ধ" + }, + "noTwoStepProviders": { + "message": "এই অ্যাকাউন্টে দ্বি-পদক্ষেপ লগইন সক্ষম রয়েছে, তবে কনফিগারকৃত দ্বি-পদক্ষেপ সরবরাহকারীদের কোনওটিই এই ডিভাইস দ্বারা সমর্থিত নয়।" + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "দ্বি-পদক্ষেপ লগইন বিকল্প" + }, + "selfHostedEnvironment": { + "message": "স্ব-হোস্টকৃত পরিবেশ" + }, + "selfHostedEnvironmentFooter": { + "message": "আপনার অন-প্রাঙ্গনে হোস্টকৃত Bitwarden ইনস্টলেশনটির বেস URL উল্লেখ করুন।" + }, + "customEnvironment": { + "message": "পছন্দসই পরিবেশ" + }, + "customEnvironmentFooter": { + "message": "উন্নত ব্যবহারকারীদের জন্য। আপনি স্বতন্ত্রভাবে প্রতিটি পরিষেবার মূল URL নির্দিষ্ট করতে পারেন।" + }, + "baseUrl": { + "message": "সার্ভার URL" + }, + "apiUrl": { + "message": "এপিআই সার্ভার URL" + }, + "webVaultUrl": { + "message": "ওয়েব ভল্ট সার্ভার URL" + }, + "identityUrl": { + "message": "পরিচয় সার্ভার URL" + }, + "notificationsUrl": { + "message": "বিজ্ঞপ্তি সার্ভার URL" + }, + "iconsUrl": { + "message": "আইকন সার্ভার URL" + }, + "environmentSaved": { + "message": "পরিবেশের URL গুলি সংরক্ষণ করা হয়েছে।" + }, + "ok": { + "message": "ঠিক আছে" + }, + "yes": { + "message": "হ্যাঁ" + }, + "no": { + "message": "না" + }, + "overwritePassword": { + "message": "ওভাররাইট পাসওয়ার্ড" + }, + "learnMore": { + "message": "আরও জানুন" + }, + "featureUnavailable": { + "message": "বৈশিষ্ট্য অনুপলব্ধ" + }, + "loggedOut": { + "message": "প্রস্থানকৃত" + }, + "loginExpired": { + "message": "আপনার লগইন মাত্রকালটির মেয়াদ শেষ হয়ে গেছে।" + }, + "logOutConfirmation": { + "message": "আপনি লগ আউট করতে চান?" + }, + "logOut": { + "message": "লগ আউট" + }, + "addNewLogin": { + "message": "নতুন লগইন জুড়ুন" + }, + "addNewItem": { + "message": "নতুন বস্তু জুড়ুন" + }, + "addNewFolder": { + "message": "নতুন ফোল্ডার জুড়ুন" + }, + "view": { + "message": "দেখুন" + }, + "account": { + "message": "অ্যাকাউন্ট" + }, + "loading": { + "message": "লোড হচ্ছে..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "পাসওয়ার্ড উৎপাদক" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "ভল্ট সিঙ্ক করুন" + }, + "changeMasterPass": { + "message": "মূল পাসওয়ার্ড পরিবর্তন" + }, + "changeMasterPasswordConfirmation": { + "message": "আপনি bitwarden.com ওয়েব ভল্ট থেকে মূল পাসওয়ার্ডটি পরিবর্তন করতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "fingerprintPhrase": { + "message": "ফিঙ্গারপ্রিন্ট ফ্রেজ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "আপনার অ্যাকাউন্টের ফিঙ্গারপ্রিন্ট ফ্রেজ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "ব্রাউজার এক্সটেনশন পান" + }, + "syncingComplete": { + "message": "সিঙ্কিং সম্পন্ন" + }, + "syncingFailed": { + "message": "সিঙ্কিঙ্গে ব্যর্থ" + }, + "yourVaultIsLocked": { + "message": "আপনার ভল্ট লক করা আছে। চালিয়ে যেতে আপনার মূল পাসওয়ার্ডটি যাচাই করান।" + }, + "unlock": { + "message": "আনলক" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ এ $EMAIL$ হিসাবে লগ ইনকৃত।", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "অবৈধ মূল পাসওয়ার্ড" + }, + "twoStepLoginConfirmation": { + "message": "দ্বি-পদক্ষেপ লগইন অন্য ডিভাইসে আপনার লগইনটি যাচাই করার জন্য সিকিউরিটি কী, প্রমাণীকরণকারী অ্যাপ্লিকেশন, এসএমএস, ফোন কল বা ই-মেইল ব্যাবহারের মাধ্যমে আপনার অ্যাকাউন্টকে আরও সুরক্ষিত করে। bitwarden.com ওয়েব ভল্টে দ্বি-পদক্ষেপের লগইন সক্ষম করা যাবে। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "twoStepLogin": { + "message": "দ্বি-পদক্ষেপের লগইন" + }, + "vaultTimeout": { + "message": "ভল্টের সময়সীমা" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "সঙ্গে সঙ্গে" + }, + "tenSeconds": { + "message": "১০ সেকেন্ড" + }, + "twentySeconds": { + "message": "২০ সেকেন্ড" + }, + "thirtySeconds": { + "message": "৩০ সেকেন্ড" + }, + "oneMinute": { + "message": "১ মিনিট" + }, + "twoMinutes": { + "message": "২ মিনিট" + }, + "fiveMinutes": { + "message": "৫ মিনিট" + }, + "fifteenMinutes": { + "message": "১৫ মিনিট" + }, + "thirtyMinutes": { + "message": "৩০ মিনিট" + }, + "oneHour": { + "message": "১ ঘণ্টা" + }, + "fourHours": { + "message": "৪ ঘন্টা" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "সিস্টেম লকে" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "ক্লিপবোর্ড পরিষ্কার", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "আপনার ক্লিপবোর্ড থেকে অনুলিপিত মানগুলি স্বয়ংক্রিয়ভাবে সাফ করে।", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "ওয়েবসাইট আইকন অক্ষম করুন" + }, + "disableFaviconDesc": { + "message": "ওয়েবসাইট আইকনগুলি আপনার ভল্টের প্রতিটি লগইন বস্তুর পাশে একটি পরিচয়যোগ্য চিত্র সরবরাহ করে।" + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "ভাষা" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "অ্যাপ্লিকেশনটির রং থিম পরিবর্তন।" + }, + "dark": { + "message": "অন্ধকার", + "description": "Dark color" + }, + "light": { + "message": "উজ্জ্বল", + "description": "Light color" + }, + "copy": { + "message": "অনুলিপি", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "হালনাগাদের জন্য পরীক্ষা করুন" + }, + "version": { + "message": "সংস্করণ $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "হালনাগাদ করতে রিস্টার্ট করুন" + }, + "restartToUpdateDesc": { + "message": "সংস্করণ $VERSION_NUM$ ইন্সটল করার জন্য প্রস্তুত। ইনস্টলেশনটি শেষ করতে আপনাকে অবশ্যই অ্যাপ্লিকেশনটি পুনরায় চালু করতে হবে। আপনি কি এখনই পুনরায় চালু এবং আপডেট করতে চান?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "হালনাগাদ উপলব্ধ" + }, + "updateAvailableDesc": { + "message": "একটি হালনাগাদপাওয়া গেছে। আপনি কি এখনই এটি ডাউনলোড করতে চান?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "পরে" + }, + "noUpdatesAvailable": { + "message": "বর্তমানে কোন হালনাগাদ নেই। আপনি সর্বশেষতম সংস্করণ ব্যবহার করছেন।" + }, + "updateError": { + "message": "আপডেট ত্রুটি" + }, + "unknown": { + "message": "অজানা" + }, + "copyUsername": { + "message": "ব্যবহারকারীর নাম অনুলিপিত করুন" + }, + "copyNumber": { + "message": "নম্বর অনুলিপিত করুন", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "সুরক্ষা কোড অনুলিপিত করুন", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "প্রিমিয়াম সদস্যতা" + }, + "premiumManage": { + "message": "সদস্যতা পরিচালনা" + }, + "premiumManageAlert": { + "message": "আপনি bitwarden.com ওয়েব ভল্টে আপনার সদস্যপদ পরিচালনা করতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "premiumRefresh": { + "message": "সদস্যতা সতেজ করুন" + }, + "premiumNotCurrentMember": { + "message": "আপনি বর্তমানে প্রিমিয়াম সদস্য নন।" + }, + "premiumSignUpAndGet": { + "message": "প্রিমিয়াম সদস্যতার জন্য সাইন আপ করুন এবং পান:" + }, + "premiumSignUpStorage": { + "message": "ফাইল সংযুক্তির জন্য ১ জিবি এনক্রিপ্টেড স্থান।" + }, + "premiumSignUpTwoStep": { + "message": "YubiKey, FIDO U2F, ও Duo এর মতো অতিরিক্ত দ্বি-পদক্ষেপ লগইন বিকল্পগুলি।" + }, + "premiumSignUpReports": { + "message": "আপনার ভল্টটি সুরক্ষিত রাখতে পাসওয়ার্ড স্বাস্থ্যকরন, অ্যাকাউন্ট স্বাস্থ্য এবং ডেটা লঙ্ঘনের প্রতিবেদন।" + }, + "premiumSignUpTotp": { + "message": "আপনার ভল্টে লগইনগুলির জন্য TOTP যাচাইকরণ কোড (2FA) উৎপাদক।" + }, + "premiumSignUpSupport": { + "message": "অগ্রাধিকার গ্রাহক সমর্থন।" + }, + "premiumSignUpFuture": { + "message": "ভবিষ্যতের সমস্ত প্রিমিয়াম বৈশিষ্ট্য। আরও শীঘ্রই আসছে!" + }, + "premiumPurchase": { + "message": "প্রিমিয়াম কিনুন" + }, + "premiumPurchaseAlert": { + "message": "আপনি bitwarden.com ওয়েব ভল্টে প্রিমিয়াম সদস্যতা কিনতে পারেন। আপনি কি এখনই ওয়েবসাইটটি দেখতে চান?" + }, + "premiumCurrentMember": { + "message": "আপনি প্রিমিয়াম সদস্য!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden কে সমর্থন করার জন্য আপনাকে ধন্যবাদ।" + }, + "premiumPrice": { + "message": "সমস্ত মাত্র $PRICE$ / বছরের জন্য!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "পুনঃসতেজ সম্পূর্ণ" + }, + "passwordHistory": { + "message": "পাসওয়ার্ড ইতিহাস" + }, + "clear": { + "message": "পরিষ্কার", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "তালিকার জন্য কোনও পাসওয়ার্ড নেই।" + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ অনুলিপিত", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "সাহায্য" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "পাসওয়ার্ড উন্মুক্ত হয়েছে কিনা তা পরীক্ষা করুন।" + }, + "passwordExposed": { + "message": "ডেটা লঙ্ঘনে এই পাসওয়ার্ডটি $VALUE$ সময় (গুলি) উন্মুক্ত করা হয়েছে। আপনার এটি পরিবর্তন করা উচিত।", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "এই পাসওয়ার্ডটি কোনও পরিচিত তথ্য লঙ্ঘনে পাওয়া যায় নি। এটি ব্যবহার করা নিরাপদ হওয়া উচিত।" + }, + "baseDomain": { + "message": "ভিত্তি ডোমেইন", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "নিয়ন্ত্রণকর্তা", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "হুবহু" + }, + "startsWith": { + "message": "শুরু করুন" + }, + "regEx": { + "message": "নিয়মিত অভিব্যাক্তি", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "মিল সনাক্তকরণ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "পূর্ব-নির্ধারিত মিল সনাক্তকরণ", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "বিকল্পগুলি টগল করুন" + }, + "organization": { + "message": "সংগঠন", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "পূর্ব-নির্ধারিত" + }, + "exit": { + "message": "প্রস্থান" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "হালনাগাদকৃত", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "পাসওয়ার্ড হালনাগাদকৃত", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "ভল্ট রফতানি" + }, + "fileFormat": { + "message": "ফাইলের ধরণ" + }, + "warning": { + "message": "সতর্কতা", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "ভল্ট রফতানির নিশ্চয়তা দিন" + }, + "exportWarningDesc": { + "message": "এই রফতানীতে একটি বিনা-এনক্রিপ্টেড করা বিন্যাসে আপনার ভল্ট তথ্য রয়েছে। আপনার রফতানিকৃত হওয়া ফাইল নিরাপত্তাহীন চ্যানেলগুলির মাধ্যমে (যেমন ইমেল) সংরক্ষণ বা প্রেরণ করা উচিত নয়। আপনি এটি ব্যবহার করে কাজ শেষ করার পর সাথে সাথে মুছে ফেলুন।" + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "আপনি কোনও সংস্থার অন্তর্ভুক্ত নন। সংগঠনগুলি আপনাকে নিরাপদে অন্য ব্যবহারকারীর সাথে বস্তুসমূহ ভাগ করে নেওয়ার অনুমতি দেয়।" + }, + "noCollectionsInList": { + "message": "তালিকার জন্য কোনও সংগ্রহ নেই।" + }, + "ownership": { + "message": "মালিকানা" + }, + "whoOwnsThisItem": { + "message": "এই বস্তুটির মালিক কে?" + }, + "strong": { + "message": "শক্তিশালী", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "ভাল", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "দুর্বল", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "দুর্বল মূল পাসওয়ার্ড" + }, + "weakMasterPasswordDesc": { + "message": "আপনার চয়নকৃত মূল পাসওয়ার্ডটি দুর্বল। আপনার Bitwarden অ্যাকাউন্টটি সঠিকভাবে সুরক্ষিত করার জন্য আপনার একটি শক্তিশালী মূল পাসওয়ার্ড (বা একটি পাসফ্রেজ) ব্যবহার করা উচিত। আপনি কি নিশ্চিত যে এই মূল পাসওয়ার্ডটি ব্যবহার করতে চান?" + }, + "pin": { + "message": "পিন", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "পিন দিয়ে আনলক" + }, + "setYourPinCode": { + "message": "Bitwarden আনলক করার জন্য আপনার পিন কোডটি সেট করুন। আপনি যদি অ্যাপ্লিকেশনটি থেকে পুরোপুরি লগ আউট করেন তবে আপনার পিন সেটিংস রিসেট করা হবে।" + }, + "pinRequired": { + "message": "পিন কোড প্রয়োজন।" + }, + "invalidPin": { + "message": "অবৈধ পিন কোড।" + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "কমপক্ষে একটি সংগ্রহ নির্বাচন করুন।" + }, + "premiumUpdated": { + "message": "আপনি প্রিমিয়ামে আপগ্রেড করেছেন।" + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "সেবা পাবার শর্ত" + }, + "privacyPolicy": { + "message": "গোপনীয়তা নীতি" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "নকল" + }, + "passwordGeneratorPolicyInEffect": { + "message": "এক বা একাধিক সংস্থার নীতিগুলি আপনার উৎপাদকের সেটিংসকে প্রভাবিত করছে।" + }, + "vaultTimeoutAction": { + "message": "ভল্টের সময়সীমা কর্ম" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "আবর্জনা", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "আবর্জনাতে খুঁজুন" + }, + "permanentlyDeleteItem": { + "message": "স্থায়ীভাবে বস্তু মুছুন" + }, + "permanentlyDeleteItemConfirmation": { + "message": "আপনি কি নিশ্চিত এই বস্তুটি স্থায়ীভাবে মুছতে চান?" + }, + "permanentlyDeletedItem": { + "message": "বস্তুটি স্থায়ীভাবে মুছে ফেলা হয়েছে" + }, + "restoreItem": { + "message": "বস্তু পুনরুদ্ধার" + }, + "restoreItemConfirmation": { + "message": "আপনি কি নিশ্চিত যে আপনি এই বস্তুটি পুনরুদ্ধার করতে চান?" + }, + "restoredItem": { + "message": "বস্তু পুনরুদ্ধারকৃত" + }, + "permanentlyDelete": { + "message": "স্থায়ীভাবে বস্তু মুছুন" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "লগ আউট করা আপনার ভল্টের সমস্ত অ্যাক্সেস সরিয়ে ফেলবে এবং সময়সীমার পরে অনলাইন প্রমাণীকরণের প্রয়োজন। আপনি কি নিশ্চিত যে এই সেটিংটি ব্যবহার করবেন?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "সময়সীমা কর্ম নিশ্চিতকরণ" + }, + "enterpriseSingleSignOn": { + "message": "এন্টারপ্রাইজ একক সাইন-অন" + }, + "setMasterPassword": { + "message": "মূল পাসওয়ার্ড ধার্য করুন" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "নতুন মূল পাসওয়ার্ড" + }, + "confirmNewMasterPass": { + "message": "নতুন মূল পাসওয়ার্ড নিশ্চিত করুন" + }, + "masterPasswordPolicyInEffect": { + "message": "এক বা একাধিক সংস্থার নীতিগুলির কারণে নিম্নলিখিত প্রয়োজনসমূহ মূল পাসওয়ার্ডের পূরণ করা প্রয়োজন:" + }, + "policyInEffectMinComplexity": { + "message": "$SCORE$ এর সর্বনিম্ন জটিলতার স্কোর", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "$LENGTH$ এর সর্বনিম্ন দৈর্ঘ্য", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "এক বা একাধিক বড় হাতের অক্ষর রয়েছে" + }, + "policyInEffectLowercase": { + "message": "এক বা একাধিক ছোট হাতের অক্ষর রয়েছে" + }, + "policyInEffectNumbers": { + "message": "এক বা একাধিক সংখ্যা রয়েছে" + }, + "policyInEffectSpecial": { + "message": "নিম্নলিখিত বিশেষ অক্ষরগুলির একটি বা একাধিক রয়েছে $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "আপনার নতুন মূল পাসওয়ার্ড নীতির প্রয়োজনীয়তা পূরণ করে না।" + }, + "acceptPolicies": { + "message": "এই বাক্সটি টিক করে আপনি নিম্নলিখিতগুলিতে সম্মত হন:" + }, + "acceptPoliciesError": { + "message": "পরিষেবার শর্তাদি এবং গোপনীয়তা নীতি স্বীকার করা হয়নি।" + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "বায়োমেট্রিকস সক্ষম নেই" + }, + "biometricsNotEnabledDesc": { + "message": "ব্রাউজার বায়োমেট্রিক্সের জন্য প্রথমে সেটিংসে ডেস্কটপ বায়োমেট্রিক সক্ষম করা প্রয়োজন।" + }, + "personalOwnershipSubmitError": { + "message": "একটি এন্টারপ্রাইজ নীতির কারণে, আপনি আপনার ব্যক্তিগত ভল্টে বস্তুসমূহ সংরক্ষণ করা থেকে সীমাবদ্ধ। একটি প্রতিষ্ঠানের মালিকানা বিকল্পটি পরিবর্তন করুন এবং উপলভ্য সংগ্রহগুলি থেকে চয়ন করুন।" + }, + "hintEqualsPassword": { + "message": "আপনার পাসওয়ার্ডের ইঙ্গিতটি আপনার পাসওয়ার্ড হতে পারবে না।" + }, + "personalOwnershipPolicyInEffect": { + "message": "একটি প্রতিষ্ঠানের নীতি আপনার মালিকানা বিকল্পগুলিকে প্রভাবিত করছে।" + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/bs/messages.json b/apps/desktop/src/locales/bs/messages.json new file mode 100644 index 0000000000..be70aeb5a4 --- /dev/null +++ b/apps/desktop/src/locales/bs/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filteri" + }, + "allItems": { + "message": "Sve spremljene lozinke" + }, + "favorites": { + "message": "Omiljene stavke" + }, + "types": { + "message": "Vrste" + }, + "typeLogin": { + "message": "Prijava" + }, + "typeCard": { + "message": "Kartica" + }, + "typeIdentity": { + "message": "Identitet" + }, + "typeSecureNote": { + "message": "Sigurna bilješka" + }, + "folders": { + "message": "Folderi" + }, + "collections": { + "message": "Kolekcije lozinki" + }, + "searchVault": { + "message": "Pretraživanje trezora" + }, + "addItem": { + "message": "Dodaj stavku" + }, + "shared": { + "message": "Podijeljeno" + }, + "share": { + "message": "Podijeli" + }, + "moveToOrganization": { + "message": "Premjesti u organizaciju" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ premješteno u $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Odaberi organizaciju u koju želiš premjestiti ovu stavku. Premještanje prenosi vlasništvo stavke na organizaciju. Nakon premještanja više nećeš biti direktni vlasnik ove stavke." + }, + "attachments": { + "message": "Prilozi" + }, + "viewItem": { + "message": "Prikaz stavke" + }, + "name": { + "message": "Naziv" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novi URI" + }, + "username": { + "message": "Korisničko ime" + }, + "password": { + "message": "Lozinka" + }, + "passphrase": { + "message": "Fraza/izrazna lozinka" + }, + "editItem": { + "message": "Uredi stavku" + }, + "emailAddress": { + "message": "E-Mail adresa" + }, + "verificationCodeTotp": { + "message": "Verifikacioni kod (TOTP)" + }, + "website": { + "message": "Web stranica" + }, + "notes": { + "message": "Bilješke" + }, + "customFields": { + "message": "Prilagođena polja" + }, + "launch": { + "message": "Pokreni" + }, + "copyValue": { + "message": "Kopiraj vrijednost", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimiziraj pri kopiranju u privremenu memoriju" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimiziraj pri kopiranju stavke u privremenu memoriju." + }, + "toggleVisibility": { + "message": "Prikaži/Sakrij" + }, + "toggleCollapse": { + "message": "Sažmi/Proširi", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Ime vlasnika kartice" + }, + "number": { + "message": "Broj" + }, + "brand": { + "message": "Vrsta kartice" + }, + "expiration": { + "message": "Datum isteka" + }, + "securityCode": { + "message": "Sigurnosni kod" + }, + "identityName": { + "message": "Ime identiteta" + }, + "company": { + "message": "Kompanija" + }, + "ssn": { + "message": "Broj socijalnog osiguranja / Jmbg" + }, + "passportNumber": { + "message": "Broj pasoša" + }, + "licenseNumber": { + "message": "Broj vozačke dozvole" + }, + "email": { + "message": "E Mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresa" + }, + "premiumRequired": { + "message": "Potrebno premium članstvo" + }, + "premiumRequiredDesc": { + "message": "Za korištenje ove funkcije potrebno je premium članstvo." + }, + "errorOccurred": { + "message": "Došlo je do greške." + }, + "error": { + "message": "Greška" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "Septembar" + }, + "october": { + "message": "Oktobar" + }, + "november": { + "message": "Novembar" + }, + "december": { + "message": "Decembar" + }, + "ex": { + "message": "npr.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Naslov" + }, + "mr": { + "message": "G-din" + }, + "mrs": { + "message": "G-đa" + }, + "ms": { + "message": "G-đica" + }, + "dr": { + "message": "dr." + }, + "expirationMonth": { + "message": "Mjesec isteka" + }, + "expirationYear": { + "message": "Godina isteka" + }, + "select": { + "message": "Odaberi" + }, + "other": { + "message": "Ostalo" + }, + "generatePassword": { + "message": "Generiraj lozinku" + }, + "type": { + "message": "Vrsta" + }, + "firstName": { + "message": "Ime" + }, + "middleName": { + "message": "Srednje ime" + }, + "lastName": { + "message": "Prezime" + }, + "fullName": { + "message": "Ime i prezime" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Grad" + }, + "stateProvince": { + "message": "Država / Pokrajina" + }, + "zipPostalCode": { + "message": "Poštanski broj" + }, + "country": { + "message": "Država" + }, + "save": { + "message": "Spremi" + }, + "cancel": { + "message": "Otkaži" + }, + "delete": { + "message": "Izbriši" + }, + "favorite": { + "message": "Omiljene stavke" + }, + "edit": { + "message": "Uredi" + }, + "authenticatorKeyTotp": { + "message": "Ključ autentifikatora (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "Novo prilagođeno polje" + }, + "value": { + "message": "Vrijednost" + }, + "dragToSort": { + "message": "Prevucite za sortiranje" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Sakriveno" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Povezano sa", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Povezana vrijednost", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Ukloni" + }, + "nameRequired": { + "message": "Ime je obavezno." + }, + "addedItem": { + "message": "Stavka dodana" + }, + "editedItem": { + "message": "Stavka izmijenjena" + }, + "deleteItem": { + "message": "Izbriši stavku" + }, + "deleteFolder": { + "message": "Izbriši foldere" + }, + "deleteAttachment": { + "message": "Izbriši priložene fajlove" + }, + "deleteItemConfirmation": { + "message": "Želite li zaista obrisati?" + }, + "deletedItem": { + "message": "Stavka obrisana" + }, + "overwritePasswordConfirmation": { + "message": "Da li ste sigurni da želite da zamijenite trenutnu lozinku?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Nema foldera", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Dodaj folder" + }, + "editFolder": { + "message": "Uredite folder" + }, + "regeneratePassword": { + "message": "Ponovno generiraj lozinku" + }, + "copyPassword": { + "message": "Kopirajte lozinku" + }, + "copyUri": { + "message": "Kopiraj URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopira Verifikacioni kod (TOTP)" + }, + "length": { + "message": "Dužina" + }, + "numWords": { + "message": "Broj riječi" + }, + "wordSeparator": { + "message": "Odvajač riječi" + }, + "capitalize": { + "message": "Prva slova velika", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Uključi broj" + }, + "close": { + "message": "Zatvori" + }, + "minNumbers": { + "message": "Minimalno brojeva" + }, + "minSpecial": { + "message": "Minimalno posebnih znakova", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Izbjegavaj dvosmislene znakove" + }, + "searchCollection": { + "message": "Pretraži kolekciju" + }, + "searchFolder": { + "message": "Pretraži folder" + }, + "searchFavorites": { + "message": "Pretraživanje favorita" + }, + "searchType": { + "message": "Tip pretrage", + "description": "Search item type" + }, + "newAttachment": { + "message": "Priloži novu datoteku" + }, + "deletedAttachment": { + "message": "Izbrisani priloženi fajl/ovi" + }, + "deleteAttachmentConfirmation": { + "message": "Da li ste sigurni da želite obrisati priloženu datoteku?" + }, + "attachmentSaved": { + "message": "Priložena datoteka je spremljena." + }, + "file": { + "message": "Datoteka" + }, + "selectFile": { + "message": "Odaberite datoteku." + }, + "maxFileSize": { + "message": "Maksimalna veličina datoteke je 500 MB." + }, + "updateKey": { + "message": "Ovu funkciju ne možete koristiti dok ne ažurirate ključ za šifrovanje." + }, + "editedFolder": { + "message": "Uređen folder" + }, + "addedFolder": { + "message": "Folder dodan" + }, + "deleteFolderConfirmation": { + "message": "Sigurno želiš izbrisati ovaj Folder?" + }, + "deletedFolder": { + "message": "Folder izbrisan" + }, + "loginOrCreateNewAccount": { + "message": "Prijavite se ili napravite novi račun da biste pristupili svom sigurnom trezoru." + }, + "createAccount": { + "message": "Napravi račun" + }, + "logIn": { + "message": "Prijavite se" + }, + "submit": { + "message": "Potvrdi" + }, + "masterPass": { + "message": "Master/glavna šifra" + }, + "masterPassDesc": { + "message": "Glavna lozinka je lozinka koju koristite za pristup Vašem trezoru. Veoma je važno da ne zaboravite glavnu lozinku. Ne postoji način da povratite lozinku u slučaju da je zaboravite." + }, + "masterPassHintDesc": { + "message": "Nagoveštaj glavne lozinke može Vam pomoći da zapamtite lozinku ako je zaboravite." + }, + "reTypeMasterPass": { + "message": "Ponovo unesite glavnu lozinku" + }, + "masterPassHint": { + "message": "Nagovještaj za glavnu lozinku (opcionalno)" + }, + "settings": { + "message": "Postavke" + }, + "passwordHint": { + "message": "Nagovještaj lozinke" + }, + "enterEmailToGetHint": { + "message": "Unesite E-Mail adresu Vašeg računa da biste dobili nagovještaj o mogućoj glavnoj lozinki." + }, + "getMasterPasswordHint": { + "message": "Dobijte nagovještaj glavne lozinke" + }, + "emailRequired": { + "message": "Potrebna je email adresa." + }, + "invalidEmail": { + "message": "Neispravna email adresa." + }, + "masterPassRequired": { + "message": "Potrebna je glavna lozinka." + }, + "masterPassLength": { + "message": "Glavna lozinka mora imati najmanje 8 znakova." + }, + "masterPassDoesntMatch": { + "message": "Potvrda glavne lozinke se ne podudara." + }, + "newAccountCreated": { + "message": "Tvoj novi račun je kreiran! Sada se možeš prijaviti." + }, + "masterPassSent": { + "message": "Poslali smo vam e-mail sa podsjetnikom za glavnu lozinku." + }, + "unexpectedError": { + "message": "Neočekivana greška se dogodila." + }, + "itemInformation": { + "message": "Informacije o stavki" + }, + "noItemsInList": { + "message": "Nema podataka za prikazati." + }, + "sendVerificationCode": { + "message": "Pošalji verifikacijski kod na E-Mail" + }, + "sendCode": { + "message": "Pošalji kod" + }, + "codeSent": { + "message": "Kod poslan" + }, + "verificationCode": { + "message": "Verifikacioni kod" + }, + "confirmIdentity": { + "message": "Potvrdite lozinku za nastavak." + }, + "verificationCodeRequired": { + "message": "Verifikacijski kod je neophodan." + }, + "invalidVerificationCode": { + "message": "Neispravan verifikacijski kod" + }, + "continue": { + "message": "Nastavi" + }, + "enterVerificationCodeApp": { + "message": "Unesite 6-ocifreni verifikacioni kod iz Vaše aplikacije za potvrdu autentičnosti." + }, + "enterVerificationCodeEmail": { + "message": "Unesite 6-ocifreni verifikacioni kod koji je E-Mailom poslan na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verifikacijski E-Mail poslan je na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamti me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Ponovo pošaljite E-Mail sa verifikacionim kodom" + }, + "useAnotherTwoStepMethod": { + "message": "Koristite drugi način prijavljivanja u dva koraka" + }, + "insertYubiKey": { + "message": "Ubaci svoj YubiKey u USB slot računara, a zatim dodirni njegovu tipku." + }, + "insertU2f": { + "message": "Ubaci svoj sigurnosni ključ u USB slot kompjutera. Ako ima tipku, dodirni je." + }, + "recoveryCodeDesc": { + "message": "Izgubljen je pristup uređaju za dvostruku autentifikaciju? Koristi svoj kôd za oporavak za onemogućavanje svih pružatelja usluga dvostruke autentifikacije na tvom računu." + }, + "recoveryCodeTitle": { + "message": "Kod za oporavak" + }, + "authenticatorAppTitle": { + "message": "Aplikacija za autentifikaciju" + }, + "authenticatorAppDesc": { + "message": "Koristi aplikaciju za autentifikaciju (npr. Authy ili Google Authentifikator) za generiranje kontrolnih kodova.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP sigurnosni ključ" + }, + "yubiKeyDesc": { + "message": "Koristi YubiKey za pristup svom računu. Radi s YubiKey 4, 4 Nano, 4C i NEO uređajima." + }, + "duoDesc": { + "message": "Potvrdi sa Duo Security pomoću aplikacije Duo Mobile, SMS-om, telefonskim pozivom ili U2F sigurnosnim ključem.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Potvrdi sa Duo Security za svoju organizaciju pomoću aplikacije Duo Mobile, SMS-om, telefonskim pozivom ili U2F sigurnosnim ključem.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Koristi bilo koji WebAuthn omogućeni sigurnosni ključ za pristup svojem računu." + }, + "emailTitle": { + "message": "E-Mail " + }, + "emailDesc": { + "message": "Verifikacijski kodovi će biti poslani E-Mailom." + }, + "loginUnavailable": { + "message": "Prijava nije moguća" + }, + "noTwoStepProviders": { + "message": "Ovaj račun ima omogućenu prijavu u dva koraka, međutim, niti jedan od konfiguriranih pružatelja prijave u dva koraka ne podržava ovaj uređaj." + }, + "noTwoStepProviders2": { + "message": "Dodaj dodatne pružatelje koji su bolje podržani na uređajima (npr. aplikacija Autentifikator)." + }, + "twoStepOptions": { + "message": "Opcije prijave u dva koraka" + }, + "selfHostedEnvironment": { + "message": "Vlastito hosting okruženje" + }, + "selfHostedEnvironmentFooter": { + "message": "Navedite osnovni URL vaše lokalne Bitwarden instalacije." + }, + "customEnvironment": { + "message": "Prilagođeno okruženje" + }, + "customEnvironmentFooter": { + "message": "Za napredne korisnike. Samostalno možeš odrediti osnovni URL svake usluge." + }, + "baseUrl": { + "message": "URL servera" + }, + "apiUrl": { + "message": "URL API servera" + }, + "webVaultUrl": { + "message": "URL servera web trezora" + }, + "identityUrl": { + "message": "URL identitet servera" + }, + "notificationsUrl": { + "message": "URL servera obavijesti" + }, + "iconsUrl": { + "message": "URL adresa servera ikona" + }, + "environmentSaved": { + "message": "URL adrese okruženja su spremljene." + }, + "ok": { + "message": "Uredu" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Ne" + }, + "overwritePassword": { + "message": "Prebriši lozinku" + }, + "learnMore": { + "message": "Saznajte više" + }, + "featureUnavailable": { + "message": "Funkcija nije dostupna" + }, + "loggedOut": { + "message": "Odjavljen" + }, + "loginExpired": { + "message": "Sesija je istekla." + }, + "logOutConfirmation": { + "message": "Da li ste sigurni da želite da se odjavite?" + }, + "logOut": { + "message": "Odjavi se" + }, + "addNewLogin": { + "message": "Dodaj novu prijavu" + }, + "addNewItem": { + "message": "Dodaj novu stavku" + }, + "addNewFolder": { + "message": "Dodajte novi folder" + }, + "view": { + "message": "Prikaz" + }, + "account": { + "message": "Račun" + }, + "loading": { + "message": "Učitavanje..." + }, + "lockVault": { + "message": "Zaključaj trezor" + }, + "passwordGenerator": { + "message": "Generator lozinki" + }, + "contactUs": { + "message": "Kontaktirajte nas" + }, + "getHelp": { + "message": "Potraži pomoć" + }, + "fileBugReport": { + "message": "Podnesite izvještaj o greški" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Pratite nas" + }, + "syncVault": { + "message": "Sinhronizujte trezor sada" + }, + "changeMasterPass": { + "message": "Promijenite glavnu lozinku" + }, + "changeMasterPasswordConfirmation": { + "message": "Možete da promjenite svoju glavnu lozinku na bitwarden.com web trezoru. Da li želite da posjetite web stranicu sada?" + }, + "fingerprintPhrase": { + "message": "Jedinstvena fraza", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Jedinstvena fraza tvog računa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Idi na web trezor" + }, + "getMobileApp": { + "message": "Preuzmi mobilnu aplikaciju" + }, + "getBrowserExtension": { + "message": "Preuzmi proširenje za preglednik" + }, + "syncingComplete": { + "message": "Sinhronizacija je završena" + }, + "syncingFailed": { + "message": "Sinhronizacija nije uspjela" + }, + "yourVaultIsLocked": { + "message": "Vaš trezor je zaključan. Potvrdite glavnu lozinku da nastavite." + }, + "unlock": { + "message": "Otključaj" + }, + "loggedInAsOn": { + "message": "Prijavljen kao $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Neispravna glavna lozinka" + }, + "twoStepLoginConfirmation": { + "message": "Prijava u dva koraka čini Vaš račun sigurnijim tako što zahtjeva da verifikujete svoje podatke pomoću drugog uređaja, kao što su sigurnosni ključ, aplikacija za autentifikaciju, SMS, telefonski poziv ili E-Mail. Prijavljivanje u dva koraka može se omogućiti na bitwarden.com web trezoru. Da li želite da posjetite web stranicu sada?" + }, + "twoStepLogin": { + "message": "Prijava u dva koraka" + }, + "vaultTimeout": { + "message": "Vremensko ograničenje trezora" + }, + "vaultTimeoutDesc": { + "message": "Odaberi kada će za koliko vremena će isteći aktivnost trezora i biti izvršena odabrana radnja." + }, + "immediately": { + "message": "Odmah" + }, + "tenSeconds": { + "message": "10 sekundi" + }, + "twentySeconds": { + "message": "20 sekundi" + }, + "thirtySeconds": { + "message": "30 sekundi" + }, + "oneMinute": { + "message": "1 minuta" + }, + "twoMinutes": { + "message": "2 minute" + }, + "fiveMinutes": { + "message": "5 minuta" + }, + "fifteenMinutes": { + "message": "15 minuta" + }, + "thirtyMinutes": { + "message": "30 minuta" + }, + "oneHour": { + "message": "1 sat" + }, + "fourHours": { + "message": "4 sata" + }, + "onIdle": { + "message": "Na sistemskoj pripravnosti" + }, + "onSleep": { + "message": "Na sistemskom mirovanju" + }, + "onLocked": { + "message": "Na sistemskom zaključavanju" + }, + "onRestart": { + "message": "Kod ponovnog pokretanja" + }, + "never": { + "message": "Nikad" + }, + "security": { + "message": "Sigurnost" + }, + "clearClipboard": { + "message": "Očisti međumemoriju", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatski očistiti kopirane vrijednosti iz vaše međumemorije.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Onemogućite ikone web lokacije" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "Kada se aplikacija prvi put pokrene, prikaži samo ikonu u sistemskoj traci." + }, + "startToMenuBar": { + "message": "Pokreni u traci menija" + }, + "startToMenuBarDesc": { + "message": "Kada se aplikacija prvi put pokrene, prikaži samo ikonu u sistemskoj traci." + }, + "openAtLogin": { + "message": "Automatsko pokretanje prilikom prijavljivanja" + }, + "openAtLoginDesc": { + "message": "Automatski pokreni Bitwarden desktop aplikaciju kod prijave." + }, + "alwaysShowDock": { + "message": "Uvijek prikaži u Dock-u" + }, + "alwaysShowDockDesc": { + "message": "Prikaži Bitwareden ikonu u Docku čak i kada je minimiziran u traku s izbornicima." + }, + "confirmTrayTitle": { + "message": "Potvrdi onemogućavanje trake" + }, + "confirmTrayDesc": { + "message": "Ako onemogućite ovo podešavanje sva ostala podešavanja vezana za sistemsku traku će također biti onemogućena." + }, + "language": { + "message": "Jezik" + }, + "languageDesc": { + "message": "Promijeni jezik aplikacije. Potrebno je ponovno pokretanje." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Promjeni boju teme u aplikaciji." + }, + "dark": { + "message": "Tamno", + "description": "Dark color" + }, + "light": { + "message": "Svijetlo", + "description": "Light color" + }, + "copy": { + "message": "Kopiraj", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Provjeri ima li ažuriranja" + }, + "version": { + "message": "Verzija $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Ponovo pokreni za ažuriranje" + }, + "restartToUpdateDesc": { + "message": "Verzija $VERSION_NUM$ je spremna za instalaciju. Moraš ponovno pokrenuti Bitwarden za dovršetak instalacije. Želiš li ponovo pokrenuti i ažurirati?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Dostupna su ažuriranja" + }, + "updateAvailableDesc": { + "message": "Pronađeno je ažuriranje. Želiš li ga sada preuzeti?" + }, + "restart": { + "message": "Ponovno pokreni" + }, + "later": { + "message": "Kasnije" + }, + "noUpdatesAvailable": { + "message": "Trenutno nema ažuriranja. Već koristiš najnoviju verziju." + }, + "updateError": { + "message": "Greška pri ažuriranju" + }, + "unknown": { + "message": "Nepoznato" + }, + "copyUsername": { + "message": "Kopiraj korisničko ime" + }, + "copyNumber": { + "message": "Kopiraj broj", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopirajte sigurnosni kod", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium članstvo" + }, + "premiumManage": { + "message": "Upravljaj članstvom" + }, + "premiumManageAlert": { + "message": "Svojim članstvom možeš upravljati na bitwarden.com web trezoru. Želiš li sada posjetiti web stranicu?" + }, + "premiumRefresh": { + "message": "Osvježi status članstva" + }, + "premiumNotCurrentMember": { + "message": "Trenutno nisi premium član." + }, + "premiumSignUpAndGet": { + "message": "Prijavi se za premium članstvo, čime dobijaš:" + }, + "premiumSignUpStorage": { + "message": "1 GB šifriranog prostora za pohranu podataka." + }, + "premiumSignUpTwoStep": { + "message": "Dodatne mogućnosti za prijavu u dva koraka kao što su YubiKey, FIDO U2F i Duo." + }, + "premiumSignUpReports": { + "message": "Higijenu lozinki, zdravlje računa i izvještaje o krađi podataka radi zaštite svojeg trezora." + }, + "premiumSignUpTotp": { + "message": "Generator TOTP kontrolnog koda (2FA) za prijave u tvom trezoru." + }, + "premiumSignUpSupport": { + "message": "Prioritetnu korisničku podršku." + }, + "premiumSignUpFuture": { + "message": "Sve buduće premium značajke. Uskoro više!" + }, + "premiumPurchase": { + "message": "Kupi premium članstvo" + }, + "premiumPurchaseAlert": { + "message": "Svojim članstvom možeš upravljati na bitwarden.com web trezoru. Želiš li sada posjetiti web stranicu?" + }, + "premiumCurrentMember": { + "message": "Ti si premium član!" + }, + "premiumCurrentMemberThanks": { + "message": "Hvala ti što podupireš Bitwarden." + }, + "premiumPrice": { + "message": "Sve za samo $PRICE$ /godišnje!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Osvježavanje završeno" + }, + "passwordHistory": { + "message": "Historija uređivanja lozinke" + }, + "clear": { + "message": "Obriši", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "Ne pripadaš niti jednoj organizaciji. Organizacije omogućuju sigurno dijeljenje stavki s drugim korisnicima." + }, + "noCollectionsInList": { + "message": "Nema kolekcija za prikazati." + }, + "ownership": { + "message": "Vlasništvo" + }, + "whoOwnsThisItem": { + "message": "Ko je vlasnik ove stavke?" + }, + "strong": { + "message": "Jaka", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobra", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slaba", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slaba glavna lozinka" + }, + "weakMasterPasswordDesc": { + "message": "Odabrana glavna lozinka je slaba. Trebaš koristiti jaču glavnu lozinku (ili frazu) kako bi tvoj Bitwarden račun bio pravilno zaštićen. Sigurno želiš koristiti ovakvu, slabu glavnu lozinku?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/ca/messages.json b/apps/desktop/src/locales/ca/messages.json new file mode 100644 index 0000000000..dccdbd97e1 --- /dev/null +++ b/apps/desktop/src/locales/ca/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtres" + }, + "allItems": { + "message": "Tots els elements" + }, + "favorites": { + "message": "Preferits" + }, + "types": { + "message": "Tipus" + }, + "typeLogin": { + "message": "Inici de sessió" + }, + "typeCard": { + "message": "Targeta" + }, + "typeIdentity": { + "message": "Identitat" + }, + "typeSecureNote": { + "message": "Nota segura" + }, + "folders": { + "message": "Carpetes" + }, + "collections": { + "message": "Col·leccions" + }, + "searchVault": { + "message": "Cerca en la caixa forta" + }, + "addItem": { + "message": "Afegeix element" + }, + "shared": { + "message": "Compartit" + }, + "share": { + "message": "Comparteix" + }, + "moveToOrganization": { + "message": "Desplaça a l'organització" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ desplaçat a $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Trieu una organització a la qual vulgueu desplaçar aquest element. El trasllat a una organització transfereix la propietat de l'element a aquesta organització. Ja no sereu el propietari directe d'aquest element una vegada s'haja mogut." + }, + "attachments": { + "message": "Adjunts" + }, + "viewItem": { + "message": "Visualitza l'element" + }, + "name": { + "message": "Nom" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nova URI" + }, + "username": { + "message": "Nom d'usuari" + }, + "password": { + "message": "Contrasenya" + }, + "passphrase": { + "message": "Frase de pas" + }, + "editItem": { + "message": "Edita l'element" + }, + "emailAddress": { + "message": "Adreça electrònica" + }, + "verificationCodeTotp": { + "message": "Codi de verificació (TOTP)" + }, + "website": { + "message": "Lloc web" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Camps personalitzats" + }, + "launch": { + "message": "Inicia" + }, + "copyValue": { + "message": "Copia el valor", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimitzeu quan feu una còpia al porta-retalls" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimitzeu quan copieu dades d'un element al porta-retalls." + }, + "toggleVisibility": { + "message": "Commuta la visibilitat" + }, + "toggleCollapse": { + "message": "Redueix/Amplia", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Nom del titular de la targeta" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Marca" + }, + "expiration": { + "message": "Caducitat" + }, + "securityCode": { + "message": "Codi de seguretat" + }, + "identityName": { + "message": "Nom d'identitat" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Número de la Seguretat Social" + }, + "passportNumber": { + "message": "Número de passaport" + }, + "licenseNumber": { + "message": "Número de llicència" + }, + "email": { + "message": "Correu electrònic" + }, + "phone": { + "message": "Telèfon" + }, + "address": { + "message": "Adreça" + }, + "premiumRequired": { + "message": "Premium requerit" + }, + "premiumRequiredDesc": { + "message": "Cal una subscripció premium per utilitzar aquesta característica." + }, + "errorOccurred": { + "message": "S'ha produït un error." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "Gener" + }, + "february": { + "message": "Febrer" + }, + "march": { + "message": "Març" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Maig" + }, + "june": { + "message": "Juny" + }, + "july": { + "message": "Juliol" + }, + "august": { + "message": "Agost" + }, + "september": { + "message": "Setembre" + }, + "october": { + "message": "Octubre" + }, + "november": { + "message": "Novembre" + }, + "december": { + "message": "Desembre" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Títol" + }, + "mr": { + "message": "Sr." + }, + "mrs": { + "message": "Sra." + }, + "ms": { + "message": "Srta." + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Mes de venciment" + }, + "expirationYear": { + "message": "Any de venciment" + }, + "select": { + "message": "Selecciona" + }, + "other": { + "message": "Altres" + }, + "generatePassword": { + "message": "Genera contrasenya" + }, + "type": { + "message": "Tipus" + }, + "firstName": { + "message": "Nom" + }, + "middleName": { + "message": "Segon nom" + }, + "lastName": { + "message": "Cognoms" + }, + "fullName": { + "message": "Nom complet" + }, + "address1": { + "message": "Adreça 1" + }, + "address2": { + "message": "Adreça 2" + }, + "address3": { + "message": "Adreça 3" + }, + "cityTown": { + "message": "Localitat" + }, + "stateProvince": { + "message": "Estat/província" + }, + "zipPostalCode": { + "message": "Codi postal" + }, + "country": { + "message": "País" + }, + "save": { + "message": "Guarda" + }, + "cancel": { + "message": "Cancel·la" + }, + "delete": { + "message": "Suprimeix" + }, + "favorite": { + "message": "Preferit" + }, + "edit": { + "message": "Edita" + }, + "authenticatorKeyTotp": { + "message": "Clau d'autenticació (TOTP)" + }, + "folder": { + "message": "Carpeta" + }, + "newCustomField": { + "message": "Nou camp personalitzat" + }, + "value": { + "message": "Valor" + }, + "dragToSort": { + "message": "Arrossega per ordenar" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Amagat" + }, + "cfTypeBoolean": { + "message": "Booleà" + }, + "cfTypeLinked": { + "message": "Enllaçat", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Valor enllaçat", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Suprimeix" + }, + "nameRequired": { + "message": "El nom és obligatori." + }, + "addedItem": { + "message": "Element afegit" + }, + "editedItem": { + "message": "Element editat" + }, + "deleteItem": { + "message": "Suprimeix element" + }, + "deleteFolder": { + "message": "Suprimeix carpeta" + }, + "deleteAttachment": { + "message": "Suprimeix adjunt" + }, + "deleteItemConfirmation": { + "message": "Esteu segur que voleu suprimir aquest element?" + }, + "deletedItem": { + "message": "S'ha enviat l'element a la paperera" + }, + "overwritePasswordConfirmation": { + "message": "Esteu segur que voleu sobreescriure la contrasenya actual?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Cap carpeta", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Afegeix carpeta" + }, + "editFolder": { + "message": "Edita la carpeta" + }, + "regeneratePassword": { + "message": "Regenera contrasenya" + }, + "copyPassword": { + "message": "Copia contrasenya" + }, + "copyUri": { + "message": "Copia URI" + }, + "copyVerificationCodeTotp": { + "message": "Copia codi de verificació (TOTP)" + }, + "length": { + "message": "Longitud" + }, + "numWords": { + "message": "Nombre de paraules" + }, + "wordSeparator": { + "message": "Separador de paraules" + }, + "capitalize": { + "message": "Majúscules inicials", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inclou número" + }, + "close": { + "message": "Tanca" + }, + "minNumbers": { + "message": "Mínim de caràcters númerics" + }, + "minSpecial": { + "message": "Mínim de caràcters especials", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Eviteu caràcters ambigus" + }, + "searchCollection": { + "message": "Cerca en la col·lecció" + }, + "searchFolder": { + "message": "Cerca en la carpeta" + }, + "searchFavorites": { + "message": "Cerca als preferits" + }, + "searchType": { + "message": "Tipus de Cerca", + "description": "Search item type" + }, + "newAttachment": { + "message": "Afegeix un adjunt nou" + }, + "deletedAttachment": { + "message": "Adjunt suprimit" + }, + "deleteAttachmentConfirmation": { + "message": "Esteu segur que voleu suprimir aquest adjunt?" + }, + "attachmentSaved": { + "message": "S'ha guardat el fitxer adjunt." + }, + "file": { + "message": "Fitxer" + }, + "selectFile": { + "message": "Seleccioneu un fitxer." + }, + "maxFileSize": { + "message": "La mida màxima del fitxer és de 500 MB." + }, + "updateKey": { + "message": "No podeu utilitzar aquesta característica fins que no actualitzeu la vostra clau de xifratge." + }, + "editedFolder": { + "message": "Carpeta editada" + }, + "addedFolder": { + "message": "Carpeta afegida" + }, + "deleteFolderConfirmation": { + "message": "Esteu segur que voleu suprimir aquesta carpeta?" + }, + "deletedFolder": { + "message": "Carpeta suprimida" + }, + "loginOrCreateNewAccount": { + "message": "Inicieu sessió o creeu un compte nou per accedir a la caixa forta." + }, + "createAccount": { + "message": "Crea un compte" + }, + "logIn": { + "message": "Inicia sessió" + }, + "submit": { + "message": "Envia" + }, + "masterPass": { + "message": "Contrasenya mestra" + }, + "masterPassDesc": { + "message": "La contrasenya mestra és la clau que utilitzeu per accedir a la vostra caixa forta. És molt important que no la oblideu. No hi ha manera de recuperar-la en cas que la oblideu." + }, + "masterPassHintDesc": { + "message": "Una pista de contrasenya mestra us pot ajudar a recordar-la si l'oblideu." + }, + "reTypeMasterPass": { + "message": "Torneu a escriure la contrasenya mestra" + }, + "masterPassHint": { + "message": "Pista de la contrasenya mestra (opcional)" + }, + "settings": { + "message": "Configuració" + }, + "passwordHint": { + "message": "Pista per a la contrasenya" + }, + "enterEmailToGetHint": { + "message": "Introduïu l'adreça electrònica del vostre compte per rebre la contrasenya mestra." + }, + "getMasterPasswordHint": { + "message": "Obteniu la pista de contrasenya mestra" + }, + "emailRequired": { + "message": "L'adreça de correu electrònic és obligatòria." + }, + "invalidEmail": { + "message": "L’adreça electrònica no és vàlida." + }, + "masterPassRequired": { + "message": "La contrasenya és obligatòria." + }, + "masterPassLength": { + "message": "La contrasenya ha de contenir almenys 8 caràcters." + }, + "masterPassDoesntMatch": { + "message": "La confirmació de la contrasenya mestra no coincideix." + }, + "newAccountCreated": { + "message": "El vostre compte s'ha creat correctament. Ara ja podeu iniciar sessió." + }, + "masterPassSent": { + "message": "Hem enviat un correu electrònic amb la vostra contrasenya mestra." + }, + "unexpectedError": { + "message": "S'ha produït un error inesperat." + }, + "itemInformation": { + "message": "Informació de l'element" + }, + "noItemsInList": { + "message": "No hi ha cap element a llistar." + }, + "sendVerificationCode": { + "message": "Envia un codi de verificació al correu electrònic" + }, + "sendCode": { + "message": "Envia codi" + }, + "codeSent": { + "message": "Codi enviat" + }, + "verificationCode": { + "message": "Codi de verificació" + }, + "confirmIdentity": { + "message": "Confirmeu la vostra contrasenya per continuar." + }, + "verificationCodeRequired": { + "message": "El codi de verificació és obligatori." + }, + "invalidVerificationCode": { + "message": "Codi de verificació no vàlid" + }, + "continue": { + "message": "Continua" + }, + "enterVerificationCodeApp": { + "message": "Introduïu el codi de verificació de 6 dígits de l'aplicació autenticadora." + }, + "enterVerificationCodeEmail": { + "message": "Introduïu el codi de verificació de 6 dígits que s'ha enviat per correu electrònic a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Correu electrònic de verificació enviat a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Recorda'm" + }, + "sendVerificationCodeEmailAgain": { + "message": "Envia el codi de verificació altra vegada" + }, + "useAnotherTwoStepMethod": { + "message": "Utilitzeu un altre mètode d'inici de sessió en dues passes" + }, + "insertYubiKey": { + "message": "Introduïu la vostra YubiKey al port USB de l'ordinador i, a continuació, premeu el seu botó." + }, + "insertU2f": { + "message": "Introduïu la vostra clau de seguretat al port USB de l'ordinador. Si té un botó, premeu-lo." + }, + "recoveryCodeDesc": { + "message": "Heu perdut l'accés a tots els vostres proveïdors de dos factors? Utilitzeu el codi de recuperació per inhabilitar tots els proveïdors de dos factors del vostre compte." + }, + "recoveryCodeTitle": { + "message": "Codi de recuperació" + }, + "authenticatorAppTitle": { + "message": "Aplicació autenticadora" + }, + "authenticatorAppDesc": { + "message": "Utilitzeu una aplicació autenticadora (com Authy o Google Authenticator) per generar codis de verificació basats en el temps.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Clau de seguretat OTP de YubiKey" + }, + "yubiKeyDesc": { + "message": "Utilitzeu una YubiKey per accedir al vostre compte. Funciona amb els dispositius YubiKey 4, 4 Nano, 4C i NEO." + }, + "duoDesc": { + "message": "Verifiqueu amb Duo Security mitjançant l'aplicació Duo Mobile, SMS, trucada telefònica o clau de seguretat U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifiqueu amb Duo Security per a la vostra organització mitjançant l'aplicació Duo Mobile, SMS, trucada telefònica o clau de seguretat U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Utilitzeu qualsevol clau de seguretat habilitada per WebAuthn per accedir al vostre compte." + }, + "emailTitle": { + "message": "Correu electrònic" + }, + "emailDesc": { + "message": "Els codis de verificació els rebreu per correu electrònic." + }, + "loginUnavailable": { + "message": "Inici de sessió no disponible" + }, + "noTwoStepProviders": { + "message": "Aquest compte té habilitat l'inici de sessió en dues passes, però aquest navegador web no admet cap dels dos proveïdors configurats." + }, + "noTwoStepProviders2": { + "message": "Afegiu proveïdors addicionals que s'adapten millor als dispositius (com ara una aplicació d'autenticació)." + }, + "twoStepOptions": { + "message": "Opcions d'inici de sessió en dues passes" + }, + "selfHostedEnvironment": { + "message": "Entorn d'allotjament propi" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifiqueu l'URL base de la vostra instal·lació Bitwarden allotjada en un entorn propi." + }, + "customEnvironment": { + "message": "Entorn personalitzat" + }, + "customEnvironmentFooter": { + "message": "Per a usuaris avançats. Podeu especificar l'URL base de cada servei independentment." + }, + "baseUrl": { + "message": "URL del servidor" + }, + "apiUrl": { + "message": "URL del servidor API" + }, + "webVaultUrl": { + "message": "URL del servidor de la caixa forta web" + }, + "identityUrl": { + "message": "URL del servidor d'identitat" + }, + "notificationsUrl": { + "message": "URL del servidor de notificacions" + }, + "iconsUrl": { + "message": "URL del servidor d'icones" + }, + "environmentSaved": { + "message": "S'han guardat les URL de l'entorn." + }, + "ok": { + "message": "D’acord" + }, + "yes": { + "message": "Sí" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Sobreescriu la contrasenya" + }, + "learnMore": { + "message": "Més informació" + }, + "featureUnavailable": { + "message": "Característica no disponible" + }, + "loggedOut": { + "message": "Desconnectat" + }, + "loginExpired": { + "message": "La vostra sessió ha caducat." + }, + "logOutConfirmation": { + "message": "Segur que voleu tancar la sessió?" + }, + "logOut": { + "message": "Tanca la sessió" + }, + "addNewLogin": { + "message": "Afegeix un inici de sessió nou" + }, + "addNewItem": { + "message": "Afegeix un element nou" + }, + "addNewFolder": { + "message": "Afegeix una carpeta nova" + }, + "view": { + "message": "Mostra" + }, + "account": { + "message": "Compte" + }, + "loading": { + "message": "S'està carregant..." + }, + "lockVault": { + "message": "Bloqueja caixa forta" + }, + "passwordGenerator": { + "message": "Generador de contrasenyes" + }, + "contactUs": { + "message": "Contacta'ns" + }, + "getHelp": { + "message": "Obteniu ajuda" + }, + "fileBugReport": { + "message": "Presenta un informe d'error" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Seguiu-nos" + }, + "syncVault": { + "message": "Sincronitza la caixa forta" + }, + "changeMasterPass": { + "message": "Canvia la contrasenya mestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Podeu canviar la contrasenya mestra a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "fingerprintPhrase": { + "message": "Frase d'empremta digital", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frase d'empremta digital del vostre compte", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Vés a la caixa forta web" + }, + "getMobileApp": { + "message": "Obteniu l'aplicació per a mòbil" + }, + "getBrowserExtension": { + "message": "Obteniu l'extensió del navegador" + }, + "syncingComplete": { + "message": "S'ha completat la sincronització" + }, + "syncingFailed": { + "message": "Ha fallat la sincronització" + }, + "yourVaultIsLocked": { + "message": "La caixa forta està bloquejada. Comproveu la contrasenya mestra per continuar." + }, + "unlock": { + "message": "Desbloqueja" + }, + "loggedInAsOn": { + "message": "Heu iniciat sessió com a $EMAIL$ en $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Contrasenya mestra no vàlida" + }, + "twoStepLoginConfirmation": { + "message": "L'inici de sessió en dues passes fa que el vostre compte siga més segur, ja que obliga a comprovar el vostre inici de sessió amb un altre dispositiu, com ara una clau de seguretat, una aplicació autenticadora, un SMS, una trucada telefònica o un correu electrònic. Es pot habilitar l'inici de sessió en dues passes a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "twoStepLogin": { + "message": "Inici de sessió en dues passes" + }, + "vaultTimeout": { + "message": "Temps d'espera de la caixa forta" + }, + "vaultTimeoutDesc": { + "message": "Trieu quan es tancarà la vostra caixa forta i feu l'acció seleccionada." + }, + "immediately": { + "message": "Immediatament" + }, + "tenSeconds": { + "message": "10 segons" + }, + "twentySeconds": { + "message": "20 segons" + }, + "thirtySeconds": { + "message": "30 segons" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minuts" + }, + "fiveMinutes": { + "message": "5 Minuts" + }, + "fifteenMinutes": { + "message": "15 minuts" + }, + "thirtyMinutes": { + "message": "30 minuts" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 hores" + }, + "onIdle": { + "message": "En inactivitat del sistema" + }, + "onSleep": { + "message": "En aturada temporal del sistema" + }, + "onLocked": { + "message": "En bloquejar el sistema" + }, + "onRestart": { + "message": "En reiniciar" + }, + "never": { + "message": "Mai" + }, + "security": { + "message": "Seguretat" + }, + "clearClipboard": { + "message": "Neteja el porta-retalls", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Esborra automàticament els valors copiats del porta-retalls.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Inhabilita icones del lloc web" + }, + "disableFaviconDesc": { + "message": "Les icones del lloc web proporcionen una imatge que es pot reconèixer al costat de cada element d'inici de sessió a la vostra caixa forta." + }, + "enableMinToTray": { + "message": "Minimitza a icona en la safata" + }, + "enableMinToTrayDesc": { + "message": "En minimitzar la finestra, mostra una icona a la safata del sistema." + }, + "enableMinToMenuBar": { + "message": "Minimitza a la barra de menú" + }, + "enableMinToMenuBarDesc": { + "message": "En minimitzar la finestra, mostra una icona a la safata del sistema." + }, + "enableCloseToTray": { + "message": "Tanca a la icona de safata" + }, + "enableCloseToTrayDesc": { + "message": "En tancar la finestra, mostra una icona a la safata del sistema." + }, + "enableCloseToMenuBar": { + "message": "Tanca a la barra de menú" + }, + "enableCloseToMenuBarDesc": { + "message": "En minimitzar la finestra, mostra una icona a la safata del sistema." + }, + "enableTray": { + "message": "Habilita la icona de safata" + }, + "enableTrayDesc": { + "message": "Mostra sempre una icona a la safata de sistema." + }, + "startToTray": { + "message": "Inicia a la icona de safata" + }, + "startToTrayDesc": { + "message": "Quan l'aplicació s’inicia, mostra només una icona a la safata de sistema." + }, + "startToMenuBar": { + "message": "Inicia a la barra de menú" + }, + "startToMenuBarDesc": { + "message": "Quan l'aplicació s’inicia, mostra només una icona a la safata de sistema." + }, + "openAtLogin": { + "message": "Comença automàticament en iniciar la sessió" + }, + "openAtLoginDesc": { + "message": "Inicia l'aplicació Bitwarden Desktop automàticament en iniciar la sessió." + }, + "alwaysShowDock": { + "message": "Mostra sempre al Dock" + }, + "alwaysShowDockDesc": { + "message": "Mostra la icona Bitwarden al Dock fins i tot quan es minimitza a la barra de menú." + }, + "confirmTrayTitle": { + "message": "Confirma la desactivació a la safata" + }, + "confirmTrayDesc": { + "message": "Si deshabiliteu aquesta configuració, també es deshabilitaran tots els altres paràmetres relacionats amb la safata." + }, + "language": { + "message": "Idioma" + }, + "languageDesc": { + "message": "Canvia l'idioma que utilitza l'aplicació. Es requereix un reinici." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Canvia el color del tema de l'aplicació." + }, + "dark": { + "message": "Fosc", + "description": "Dark color" + }, + "light": { + "message": "Clar", + "description": "Light color" + }, + "copy": { + "message": "Copia", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Cerca actualitzacions" + }, + "version": { + "message": "Versió $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Reinicia per actualitzar" + }, + "restartToUpdateDesc": { + "message": "La versió $VERSION_NUM$ està a punt per instal·lar-se. Heu de reiniciar l'aplicació per completar la instal·lació. Voleu reiniciar i actualitzar ara?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Actualització disponible" + }, + "updateAvailableDesc": { + "message": "S'ha trobat una actualització. Voleu descarregar-la ara?" + }, + "restart": { + "message": "Reinicia" + }, + "later": { + "message": "Més tard" + }, + "noUpdatesAvailable": { + "message": "No hi ha actualitzacions disponibles actualment. Esteu utilitzant l'última versió." + }, + "updateError": { + "message": "Error d'actualizació" + }, + "unknown": { + "message": "Desconegut" + }, + "copyUsername": { + "message": "Copia el nom d'usuari" + }, + "copyNumber": { + "message": "Copia el número", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copia el codi de seguretat", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Subscripció Premium" + }, + "premiumManage": { + "message": "Administra la subscripció" + }, + "premiumManageAlert": { + "message": "Podeu gestionar la vostra subscripció a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "premiumRefresh": { + "message": "Actualitza la subscripció" + }, + "premiumNotCurrentMember": { + "message": "No sou actualment un membre premium." + }, + "premiumSignUpAndGet": { + "message": "Inscriviu-vos per una subscripció premium i obteniu:" + }, + "premiumSignUpStorage": { + "message": "1 GB d'emmagatzematge xifrat per als fitxers adjunts." + }, + "premiumSignUpTwoStep": { + "message": "Opcions addicionals d'inici de sessió en dues passes com ara YubiKey, FIDO U2F i Duo." + }, + "premiumSignUpReports": { + "message": "Requisits d'higiene de la contrasenya, salut del compte i informe d'infraccions de dades per mantenir la seguretat de la vostra caixa forta." + }, + "premiumSignUpTotp": { + "message": "Generador de codi de verificació TOTP (2FA) per a inici de sessió a la vostra caixa forta." + }, + "premiumSignUpSupport": { + "message": "Prioritat d'atenció al client." + }, + "premiumSignUpFuture": { + "message": "Totes les funcions premium futures. Aviat, més!" + }, + "premiumPurchase": { + "message": "Compra Premium" + }, + "premiumPurchaseAlert": { + "message": "Podeu comprar la vostra subscripció a la caixa forta web de bitwarden.com. Voleu visitar el lloc web ara?" + }, + "premiumCurrentMember": { + "message": "Sou un membre premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Gràcies per donar suport a Bitwarden." + }, + "premiumPrice": { + "message": "Tot per només $PRICE$/any!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Actualització completa" + }, + "passwordHistory": { + "message": "Historial de les contrasenyes" + }, + "clear": { + "message": "Esborra", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "No hi ha cap contrasenya a llistar." + }, + "undo": { + "message": "Desfés" + }, + "redo": { + "message": "Refés" + }, + "cut": { + "message": "Retalla", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Enganxa", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Selecciona-ho tot" + }, + "zoomIn": { + "message": "Amplia" + }, + "zoomOut": { + "message": "Allunya" + }, + "resetZoom": { + "message": "Restableix el zoom" + }, + "toggleFullScreen": { + "message": "Commuta pantalla completa" + }, + "reload": { + "message": "Torna a carregar" + }, + "toggleDevTools": { + "message": "Commuta eines de desenvolupadors" + }, + "minimize": { + "message": "Minimitza", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Porta-ho tot al davant", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Quant a Bitwarden" + }, + "services": { + "message": "Serveis" + }, + "hideBitwarden": { + "message": "Amaga Bitwarden" + }, + "hideOthers": { + "message": "Amaga els altres" + }, + "showAll": { + "message": "Mostra-ho tot" + }, + "quitBitwarden": { + "message": "Tanca Bitwarden" + }, + "valueCopied": { + "message": "S'ha copiat $VALUE$", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Ajuda" + }, + "window": { + "message": "Finestra" + }, + "checkPassword": { + "message": "Comprova si la contrasenya ha estat exposada." + }, + "passwordExposed": { + "message": "Aquesta contrasenya ha estat exposada $VALUE$ vegades en errors de seguretat de dades. Heu de canviar-la.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Aquesta contrasenya no s'ha trobat en cap filtració de dades coneguda. Hauries de poder utilitzar-la de manera segura." + }, + "baseDomain": { + "message": "Domini base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Amfitrió", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exacte" + }, + "startsWith": { + "message": "Comença amb" + }, + "regEx": { + "message": "Expressió regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Detecció de coincidències", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detecció de coincidències per defecte", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Commuta opcions" + }, + "organization": { + "message": "Organització", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Per defecte" + }, + "exit": { + "message": "Tanca" + }, + "showHide": { + "message": "Mostra/Amaga", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Amaga a la safata" + }, + "alwaysOnTop": { + "message": "Sempre visible", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Actualitzat", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Contrasenya actualitzada", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Exporta caixa forta" + }, + "fileFormat": { + "message": "Format de fitxer" + }, + "warning": { + "message": "ADVERTIMENT", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirma l'exportació de la Caixa forta" + }, + "exportWarningDesc": { + "message": "Aquesta exportació conté les dades de la vostra caixa forta en un format no xifrat. No hauríeu d'emmagatzemar o enviar el fitxer exportat a través de canals no segurs (com ara el correu electrònic). Elimineu-lo immediatament després d'haver acabat d'usar-lo." + }, + "encExportKeyWarningDesc": { + "message": "Aquesta exportació xifra les vostres dades mitjançant la clau de xifratge del vostre compte. Si alguna vegada gireu eixa clau, hauríeu d'exportar de nou, ja que no podreu desxifrar aquest fitxer d'exportació." + }, + "encExportAccountWarningDesc": { + "message": "Les claus de xifratge són exclusives de cada compte d'usuari Bitwarden, de manera que no podeu importar una exportació xifrada a un compte diferent." + }, + "noOrganizationsList": { + "message": "No pertanyeu a cap organització. Les organitzacions permeten compartir elements amb seguretat amb altres usuaris." + }, + "noCollectionsInList": { + "message": "No hi ha cap col·lecció a llistar." + }, + "ownership": { + "message": "Propietat" + }, + "whoOwnsThisItem": { + "message": "Qui és propietari d'aquest element?" + }, + "strong": { + "message": "Forta", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bona", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Poc segura", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Contrasenya mestra poc segura" + }, + "weakMasterPasswordDesc": { + "message": "La contrasenya mestra que heu triat és poc segura. Heu d'utilitzar una contrasenya mestra segura (o una frase de pas) per protegir correctament el vostre compte de Bitwarden. Esteu segur que voleu utilitzar aquesta contrasenya mestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloqueja amb codi PIN" + }, + "setYourPinCode": { + "message": "Configureu el vostre codi PIN per desbloquejar Bitwarden. La configuració del PIN es restablirà si tanqueu la sessió definitivament." + }, + "pinRequired": { + "message": "Es necessita el codi PIN." + }, + "invalidPin": { + "message": "El codi PIN no és vàlid." + }, + "unlockWithWindowsHello": { + "message": "Desbloqueja amb Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verifica per Bitwarden." + }, + "unlockWithTouchId": { + "message": "Desbloqueja amb Touch ID" + }, + "touchIdConsentMessage": { + "message": "desbloqueja la teva caixa forta" + }, + "noAutoPromptWindowsHello": { + "message": "No demaneu que Windows Hello en iniciar." + }, + "noAutoPromptTouchId": { + "message": "No sol·liciteu Touch ID en iniciar." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloqueja amb la contrasenya mestra en reiniciar" + }, + "preferences": { + "message": "Preferències" + }, + "enableMenuBar": { + "message": "Habilita la icona de la barra de menús" + }, + "enableMenuBarDesc": { + "message": "Mostra sempre una icona a la barra de menú." + }, + "hideToMenuBar": { + "message": "Amaga la barra de menú" + }, + "selectOneCollection": { + "message": "Heu d'escollir com a mínim una col·lecció." + }, + "premiumUpdated": { + "message": "Heu actualitzat a la versió premium." + }, + "restore": { + "message": "Restaura" + }, + "premiumManageAlertAppStore": { + "message": "Podeu gestionar la vostra subscripció des de l'App Store. \nVoleu visitar l'App Store ara?" + }, + "legal": { + "message": "Informació legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Condicions del servei" + }, + "privacyPolicy": { + "message": "Política de privacitat" + }, + "unsavedChangesConfirmation": { + "message": "Segur que voleu marxar? Si marxeu ara, la vostra informació actual no es guardarà." + }, + "unsavedChangesTitle": { + "message": "Hi ha canvis sense guardar" + }, + "clone": { + "message": "Clona" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una o més polítiques d’organització afecten la configuració del generador." + }, + "vaultTimeoutAction": { + "message": "Acció del temps d'espera de la caixa forta" + }, + "vaultTimeoutActionLockDesc": { + "message": "Una caixa forta bloquejada requereix que torneu a introduir la contrasenya principal per accedir-ne de nou." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Una caixa forta desconnectada requereix que torneu a autentificar-vos per accedir-hi de nou." + }, + "lock": { + "message": "Bloqueja", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Paperera", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Cerca a la paperera" + }, + "permanentlyDeleteItem": { + "message": "Element suprimit definitivament" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Esteu segur que voleu suprimir aquest element definitivament?" + }, + "permanentlyDeletedItem": { + "message": "Element suprimit definitivament" + }, + "restoreItem": { + "message": "Restaura l'element" + }, + "restoreItemConfirmation": { + "message": "Esteu segur que voleu restaurar aquest element?" + }, + "restoredItem": { + "message": "Element restaurat" + }, + "permanentlyDelete": { + "message": "Suprimeix definitivament" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "En tancar la sessió s'eliminarà tot l'accés a la vostra caixa forta i es requerirà una autenticació en línia després del període de temps d'espera. Esteu segur que voleu utilitzar aquesta configuració?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmació de l’acció de temps d'espera de la caixa forta" + }, + "enterpriseSingleSignOn": { + "message": "Inici de sessió únic d'empresa" + }, + "setMasterPassword": { + "message": "Estableix la contrasenya mestra" + }, + "ssoCompleteRegistration": { + "message": "Per completar la sessió amb SSO, configureu una contrasenya mestra per accedir i protegir la vostra caixa forta." + }, + "newMasterPass": { + "message": "Contrasenya mestra nova" + }, + "confirmNewMasterPass": { + "message": "Confirma la contrasenya mestra nova" + }, + "masterPasswordPolicyInEffect": { + "message": "Una o més polítiques d’organització requereixen que la vostra contrasenya principal complisca els requisits següents:" + }, + "policyInEffectMinComplexity": { + "message": "Puntuació mínima de complexitat de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Longitud mínima de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Conté un o més caràcters en majúscula" + }, + "policyInEffectLowercase": { + "message": "Conté un o més caràcters en minúscula" + }, + "policyInEffectNumbers": { + "message": "Conté un o més números" + }, + "policyInEffectSpecial": { + "message": "Conté un o més dels següents caràcters especials $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "La nova contrasenya principal no compleix els requisits de la política." + }, + "acceptPolicies": { + "message": "Si activeu aquesta casella, indiqueu que esteu d’acord amb el següent:" + }, + "acceptPoliciesError": { + "message": "No s’han reconegut les condicions del servei i la declaració de privadesa." + }, + "enableBrowserIntegration": { + "message": "Habilita la integració amb el navegador" + }, + "enableBrowserIntegrationDesc": { + "message": "La integració al navegador s’utilitza per a la biometria en aquest." + }, + "browserIntegrationMasOnlyTitle": { + "message": "La integració en el navegador no és compatible" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Malauradament, la integració del navegador només és compatible amb la versió de Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "La integració en el navegador no és compatible" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Malauradament, la integració del navegador només és compatible amb la versió de Microsoft Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Requereix verificació per a la integració del navegador" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Habilita una capa de seguretat addicional mitjançant la validació de frases d'empremtes dactilars quan estableix un enllaç entre l'escriptori i el navegador. Quan està habilitat, requereix la intervenció i verificació de l'usuari cada vegada que s'estableix una connexió." + }, + "approve": { + "message": "Aprova" + }, + "verifyBrowserTitle": { + "message": "Verifiqueu la connexió del navegador" + }, + "verifyBrowserDesc": { + "message": "Assegureu-vos que l’empremta digital que es mostra és idèntica a la que es mostra a l’extensió del navegador." + }, + "biometricsNotEnabledTitle": { + "message": "La biomètrica no està habilitada" + }, + "biometricsNotEnabledDesc": { + "message": "La biometria del navegador primer necessita habilitar la biomètrica d’escriptori a la configuració." + }, + "personalOwnershipSubmitError": { + "message": "A causa d'una política empresarial, no podeu guardar elements a la vostra caixa forta personal. Canvieu l'opció Propietat en organització i trieu entre les col·leccions disponibles." + }, + "hintEqualsPassword": { + "message": "El vostre suggeriment de contrasenya no pot ser el mateix que la vostra contrasenya." + }, + "personalOwnershipPolicyInEffect": { + "message": "Una política d’organització afecta les vostres opcions de propietat." + }, + "allSends": { + "message": "Tots els Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fitxer" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Cerca Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edita Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "La meua caixa forta" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Data de supressió" + }, + "deletionDateDesc": { + "message": "El Send se suprimirà permanentment a la data i hora especificades.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data de caducitat" + }, + "expirationDateDesc": { + "message": "Si s'estableix, l'accés a aquest Send caducarà en la data i hora especificades.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Recompte màxim d'accessos" + }, + "maxAccessCountDesc": { + "message": "Si s’estableix, els usuaris ja no podran accedir a aquest Send una vegada s’assolisca el nombre màxim d’accessos.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Recompte d’accessos actual" + }, + "disableSend": { + "message": "Deshabiliteu aquest Send perquè ningú no hi puga accedir.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcionalment, necessiteu una contrasenya perquè els usuaris accedisquen a aquest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notes privades sobre aquest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Enllaç Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Enllaç Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Quan accediu a Send, amaga el text per defecte", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send creat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send editat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send suprimit", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Contrasenya nova" + }, + "whatTypeOfSend": { + "message": "Quin tipus de Send és aquest?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Crea Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "El text que voleu enviar." + }, + "sendFileDesc": { + "message": "El fitxer que voleu enviar." + }, + "days": { + "message": "$DAYS$ dies", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dia" + }, + "custom": { + "message": "Personalitzat" + }, + "deleteSendConfirmation": { + "message": "Esteu segur que voleu suprimir aquest Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copia l'enllaç Send al porta-retalls", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copie l'enllaç per compartir aquest Send al meu porta-retalls després de guardar-lo." + }, + "sendDisabled": { + "message": "Send desactivat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "A causa d'una política empresarial, només podeu suprimir un Send existent.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copia l'enllaç" + }, + "disabled": { + "message": "Deshabilitat" + }, + "maxAccessCountReached": { + "message": "S'ha assolit el recompte màxim d'accesos" + }, + "expired": { + "message": "Caducat" + }, + "pendingDeletion": { + "message": "Pendent de supressió" + }, + "webAuthnAuthenticate": { + "message": "Autenticar WebAuthn" + }, + "hideEmail": { + "message": "Amagueu la meua adreça de correu electrònic als destinataris." + }, + "sendOptionsPolicyInEffect": { + "message": "Una o més polítiques d'organització afecten les vostres opcions del Send." + }, + "emailVerificationRequired": { + "message": "Es requereix verificació per correu electrònic" + }, + "emailVerificationRequiredDesc": { + "message": "Heu de verificar el vostre correu electrònic per utilitzar aquesta característica." + }, + "passwordPrompt": { + "message": "Sol·licitud de la contrasenya mestra" + }, + "passwordConfirmation": { + "message": "Confirmació de la contrasenya mestra" + }, + "passwordConfirmationDesc": { + "message": "Aquesta acció està protegida. Per continuar, torneu a introduir la contrasenya principal per verificar la vostra identitat." + }, + "updatedMasterPassword": { + "message": "Contrasenya mestra actualitzada" + }, + "updateMasterPassword": { + "message": "Actualitza contrasenya mestra" + }, + "updateMasterPasswordWarning": { + "message": "Un administrador de l'organització ha canviat recentment la contrasenya principal. Per accedir a la caixa forta, heu d'actualitzar-la ara. Si continueu, es tancarà la sessió actual i heu de tornar a iniciar-la. És possible que les sessions obertes en altres dispositius continuen actives fins a una hora." + }, + "hours": { + "message": "Hores" + }, + "minutes": { + "message": "Minuts" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Les polítiques de l'organització afecten el temps d'espera de la caixa forta. El temps d'espera màxim permès d'aquesta és de $HOURS$ hores i $MINUTES$ minuts", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "El temps d'espera de la caixa forta supera les restriccions establertes per la vostra organització." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscripció automàtica" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Aquesta organització té una política empresarial que us inscriurà automàticament al restabliment de la contrasenya. La inscripció permetrà als administradors de l’organització canviar la vostra contrasenya mestra." + }, + "vaultExportDisabled": { + "message": "L'exportació de la caixa forta està desactivada" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una o més polítiques d'organització us impedeixen exportar la vostra caixa forta." + }, + "addAccount": { + "message": "Afig compte" + }, + "removeMasterPassword": { + "message": "Suprimiu la contrasenya mestra" + }, + "removedMasterPassword": { + "message": "S'ha suprimit la contrasenya mestra." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ està utilitzant SSO amb un servidor autoallotjat de claus. Ja no es requereix una contrasenya mestra d'inici de sessió per als membres d'aquesta organització.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Abandona l'organització" + }, + "leaveOrganizationConfirmation": { + "message": "Esteu segur que voleu eixir d'aquesta organització?" + }, + "leftOrganization": { + "message": "Heu deixat l'organització." + }, + "ssoKeyConnectorUnavailable": { + "message": "No es pot arribar al connector de claus, torneu-ho a provar més tard." + }, + "lockAllVaults": { + "message": "Bloqueja totes les caixes fortes" + }, + "accountLimitReached": { + "message": "No es pot iniciar sessió a més de 5 comptes al mateix temps." + }, + "accountPreferences": { + "message": "Preferències" + }, + "appPreferences": { + "message": "Configuració de l'aplicació (tots els comptes)" + }, + "accountSwitcherLimitReached": { + "message": "S'ha arribat al límit del compte. Tanqueu la sessió d'un compte per afegir-ne un altre." + }, + "settingsTitle": { + "message": "Configuració de l'aplicació per a $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Canvia de compte" + }, + "options": { + "message": "Opcions" + }, + "sessionTimeout": { + "message": "La sessió ha expirat. Torneu arrere i proveu d'iniciar sessió de nou." + }, + "exportingPersonalVaultTitle": { + "message": "S'està exportant la caixa forta personal" + }, + "exportingPersonalVaultDescription": { + "message": "Només s'exportaran els elements personals de la caixa forta associats a $EMAIL$. Els elements de la caixa forta de l'organització no s'inclouran.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/cs/messages.json b/apps/desktop/src/locales/cs/messages.json new file mode 100644 index 0000000000..d008e78ba3 --- /dev/null +++ b/apps/desktop/src/locales/cs/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtry" + }, + "allItems": { + "message": "Všechny položky" + }, + "favorites": { + "message": "Oblíbené" + }, + "types": { + "message": "Typy" + }, + "typeLogin": { + "message": "Přihlašovací údaje" + }, + "typeCard": { + "message": "Karta" + }, + "typeIdentity": { + "message": "Identita" + }, + "typeSecureNote": { + "message": "Poznámka" + }, + "folders": { + "message": "Složky" + }, + "collections": { + "message": "Kolekce" + }, + "searchVault": { + "message": "Vyhledat v trezoru" + }, + "addItem": { + "message": "Přidat položku" + }, + "shared": { + "message": "Sdílené" + }, + "share": { + "message": "Sdílet" + }, + "moveToOrganization": { + "message": "Přesunout do organizace" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ přesunut do $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vyberte organizaci, do které chcete tuto položku přesunout. Přesun do organizace převede vlastnictví položky této organizaci. Po přesunutí této položky již nebudete přímým vlastníkem této položky." + }, + "attachments": { + "message": "Přílohy" + }, + "viewItem": { + "message": "Zobrazit položku" + }, + "name": { + "message": "Název" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nová URI" + }, + "username": { + "message": "Uživatelské jméno" + }, + "password": { + "message": "Heslo" + }, + "passphrase": { + "message": "Heslová fráze" + }, + "editItem": { + "message": "Upravit položku" + }, + "emailAddress": { + "message": "E-mailová adresa" + }, + "verificationCodeTotp": { + "message": "Ověřovací kód (TOTP)" + }, + "website": { + "message": "Webová stránka" + }, + "notes": { + "message": "Poznámky" + }, + "customFields": { + "message": "Vlastní pole" + }, + "launch": { + "message": "Spustit" + }, + "copyValue": { + "message": "Zkopírovat hodnotu", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimalizovat při kopírování do schránky" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimalizovat při kopírování údajů položky do schránky." + }, + "toggleVisibility": { + "message": "Přepnout viditelnost" + }, + "toggleCollapse": { + "message": "Přepnout sbalení", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Jméno držitele karty" + }, + "number": { + "message": "Číslo" + }, + "brand": { + "message": "Značka" + }, + "expiration": { + "message": "Expirace" + }, + "securityCode": { + "message": "Bezpečnostní kód" + }, + "identityName": { + "message": "Název identity" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Číslo sociálního pojištění" + }, + "passportNumber": { + "message": "Číslo cestovního pasu" + }, + "licenseNumber": { + "message": "Číslo dokladu totožnosti" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresa" + }, + "premiumRequired": { + "message": "Vyžaduje prémiové členství" + }, + "premiumRequiredDesc": { + "message": "Pro použití této funkce je potřebné prémiové členství." + }, + "errorOccurred": { + "message": "Došlo k chybě." + }, + "error": { + "message": "Chyba" + }, + "january": { + "message": "Leden" + }, + "february": { + "message": "Únor" + }, + "march": { + "message": "Březen" + }, + "april": { + "message": "Duben" + }, + "may": { + "message": "Květen" + }, + "june": { + "message": "Červen" + }, + "july": { + "message": "Červenec" + }, + "august": { + "message": "Srpen" + }, + "september": { + "message": "Září" + }, + "october": { + "message": "Říjen" + }, + "november": { + "message": "Listopad" + }, + "december": { + "message": "Prosinec" + }, + "ex": { + "message": "např.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Oslovení" + }, + "mr": { + "message": "Pan" + }, + "mrs": { + "message": "Paní" + }, + "ms": { + "message": "Slečna" + }, + "dr": { + "message": "MUDr" + }, + "expirationMonth": { + "message": "Měsíc expirace" + }, + "expirationYear": { + "message": "Rok expirace" + }, + "select": { + "message": "Vybrat" + }, + "other": { + "message": "Ostatní" + }, + "generatePassword": { + "message": "Vygenerovat heslo" + }, + "type": { + "message": "Typ" + }, + "firstName": { + "message": "Jméno" + }, + "middleName": { + "message": "Druhé jméno" + }, + "lastName": { + "message": "Příjmení" + }, + "fullName": { + "message": "Celé jméno" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Město" + }, + "stateProvince": { + "message": "Kraj / Provincie" + }, + "zipPostalCode": { + "message": "PSČ" + }, + "country": { + "message": "Stát" + }, + "save": { + "message": "Uložit" + }, + "cancel": { + "message": "Zrušit" + }, + "delete": { + "message": "Smazat" + }, + "favorite": { + "message": "Oblíbené" + }, + "edit": { + "message": "Upravit" + }, + "authenticatorKeyTotp": { + "message": "Autentizační klíč (TOTP)" + }, + "folder": { + "message": "Složka" + }, + "newCustomField": { + "message": "Nové vlastní pole" + }, + "value": { + "message": "Hodnota" + }, + "dragToSort": { + "message": "Přetáhnutím seřadíte" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Skryté" + }, + "cfTypeBoolean": { + "message": "Ano/Ne" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Smazat" + }, + "nameRequired": { + "message": "Název je povinný." + }, + "addedItem": { + "message": "Položka byla přidána" + }, + "editedItem": { + "message": "Položka byla upravena" + }, + "deleteItem": { + "message": "Smazat položku" + }, + "deleteFolder": { + "message": "Smazat složku" + }, + "deleteAttachment": { + "message": "Smazat přílohu" + }, + "deleteItemConfirmation": { + "message": "Opravdu chcete tuto položku smazat?" + }, + "deletedItem": { + "message": "Položka byla smazána" + }, + "overwritePasswordConfirmation": { + "message": "Opravdu chcete přepsat aktuální heslo?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Žádná složka", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Přidat složku" + }, + "editFolder": { + "message": "Upravit složku" + }, + "regeneratePassword": { + "message": "Vygenerovat další heslo" + }, + "copyPassword": { + "message": "Kopírovat heslo" + }, + "copyUri": { + "message": "Kopírovat URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopírovat ověřovací kód (TOTP)" + }, + "length": { + "message": "Délka" + }, + "numWords": { + "message": "Počet slov" + }, + "wordSeparator": { + "message": "Oddělovač slov" + }, + "capitalize": { + "message": "Velká písmena na začátku slova", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Zahrnout číslo" + }, + "close": { + "message": "Zavřít" + }, + "minNumbers": { + "message": "Minimální počet čísel" + }, + "minSpecial": { + "message": "Minimální počet speciálních znaků", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Použít nezaměnitelné znaky" + }, + "searchCollection": { + "message": "Vyhledat v kolekci" + }, + "searchFolder": { + "message": "Vyhledat ve složce" + }, + "searchFavorites": { + "message": "Vyhledat v oblíbených" + }, + "searchType": { + "message": "Vyhledat v typu", + "description": "Search item type" + }, + "newAttachment": { + "message": "Přidat přílohu" + }, + "deletedAttachment": { + "message": "Příloha byla smazána" + }, + "deleteAttachmentConfirmation": { + "message": "Opravdu chcete tuto přílohu smazat?" + }, + "attachmentSaved": { + "message": "Příloha byla uložena." + }, + "file": { + "message": "Soubor" + }, + "selectFile": { + "message": "Vybrat soubor." + }, + "maxFileSize": { + "message": "Maximální velikost souboru je 500 MB." + }, + "updateKey": { + "message": "Tuto funkci nemůžete použít dokud neaktualizujete svůj šifrovací klíč." + }, + "editedFolder": { + "message": "Složka byla upravena" + }, + "addedFolder": { + "message": "Složka byla přidána" + }, + "deleteFolderConfirmation": { + "message": "Opravdu chcete tuto složku smazat?" + }, + "deletedFolder": { + "message": "Složka byla smazána" + }, + "loginOrCreateNewAccount": { + "message": "Pro přístup do vašeho bezpečného trezoru se přihlaste nebo si vytvořte nový účet." + }, + "createAccount": { + "message": "Vytvořit účet" + }, + "logIn": { + "message": "Přihlásit se" + }, + "submit": { + "message": "Potvrdit" + }, + "masterPass": { + "message": "Hlavní heslo" + }, + "masterPassDesc": { + "message": "Hlavní heslo je heslo, které používáte k přístupu do vašeho trezoru. Je velmi důležité, abyste jej nezapomněli. Neexistuje totiž žádný způsob, jak heslo obnovit v případě, že jste na něj zapomněli." + }, + "masterPassHintDesc": { + "message": "Nápověda k hlavnímu heslu vám pomůže zapamatovat si heslo, pokud ho zapomenete." + }, + "reTypeMasterPass": { + "message": "Znovu zadejte hlavní heslo" + }, + "masterPassHint": { + "message": "Nápověda k hlavnímu heslu (volitelné)" + }, + "settings": { + "message": "Nastavení" + }, + "passwordHint": { + "message": "Nápověda k heslu" + }, + "enterEmailToGetHint": { + "message": "Zadejte e-mailovou adresu pro zaslání nápovědy k hlavnímu heslu." + }, + "getMasterPasswordHint": { + "message": "Zaslat nápovědu k hlavnímu heslu" + }, + "emailRequired": { + "message": "E-mailová adresa je povinná." + }, + "invalidEmail": { + "message": "Neplatná e-mailová adresa." + }, + "masterPassRequired": { + "message": "Hlavní heslo je povinné." + }, + "masterPassLength": { + "message": "Hlavní heslo musí obsahovat alespoň 8 znaků." + }, + "masterPassDoesntMatch": { + "message": "Potvrzení hlavního hesla se neshoduje." + }, + "newAccountCreated": { + "message": "Váš účet byl vytvořen! Můžete se přihlásit." + }, + "masterPassSent": { + "message": "Poslali jsme vám e-mail s nápovědou k hlavnímu heslu." + }, + "unexpectedError": { + "message": "Došlo k neznámé chybě." + }, + "itemInformation": { + "message": "Informace o položce" + }, + "noItemsInList": { + "message": "Žádné položky k zobrazení." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Odeslat kód" + }, + "codeSent": { + "message": "Kód odeslán" + }, + "verificationCode": { + "message": "Ověřovací kód" + }, + "confirmIdentity": { + "message": "Pro pokračování potvrďte svou identitu." + }, + "verificationCodeRequired": { + "message": "Ověřovací kód je povinný." + }, + "invalidVerificationCode": { + "message": "Neplatný ověřovací kód" + }, + "continue": { + "message": "Pokračovat" + }, + "enterVerificationCodeApp": { + "message": "Zadejte 6-místný kód z ověřovací aplikace." + }, + "enterVerificationCodeEmail": { + "message": "Zadejte 6místný kód z e-mailu, který byl zaslán na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Ověřovací e-mail byl zaslán na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Pamatuj si mě" + }, + "sendVerificationCodeEmailAgain": { + "message": "Znovu zaslat ověřovací kód na e-mail" + }, + "useAnotherTwoStepMethod": { + "message": "Použít jinou metodu dvoufázového přihlášení" + }, + "insertYubiKey": { + "message": "Vložte YubiKey do USB portu vašeho počítače a stiskněte jeho tlačítko." + }, + "insertU2f": { + "message": "Vložte svůj bezpečnostní klíč do USB portu vašeho počítače a pokud má tlačítko, tak jej stiskněte." + }, + "recoveryCodeDesc": { + "message": "Ztratili jste přístup ke všem nastaveným poskytovatelům dvoufázového přihlášení? Použijte obnovovací kód pro vypnutí dvoufázového přihlášení." + }, + "recoveryCodeTitle": { + "message": "Kód pro obnovení" + }, + "authenticatorAppTitle": { + "message": "Ověřovací aplikace" + }, + "authenticatorAppDesc": { + "message": "Použijte ověřovací aplikaci (jako je Authy nebo Google Authenticator) pro generování časově omezených kódů.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP bezpečnostní klíč" + }, + "yubiKeyDesc": { + "message": "Použít YubiKey pro přístup k vašemu trezoru. Podporuje YubiKey 4, 4 Nano, 4C a NEO zařízení." + }, + "duoDesc": { + "message": "Ověřit pomocí Duo Security prostřednictvím aplikace Duo Mobile, SMS, telefonního hovoru nebo U2F bezpečnostního kódu.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Ověřit pomocí Duo Security pro vaši organizaci prostřednictvím aplikace Duo Mobile, SMS, telefonního hovoru nebo U2F bezpečnostního kódu.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Použijte jakýkoliv WebAuthn bezpečnostní klíč pro přístup k vašemu účtu." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Ověřovací kódy vám budou zaslány e-mailem." + }, + "loginUnavailable": { + "message": "Přihlášení není dostupné" + }, + "noTwoStepProviders": { + "message": "Tento účet má zapnuté dvoufázové ověřování, ale žádný z nastavených poskytovalů dvoufázového přihlášení není v tomto zařízení podporován." + }, + "noTwoStepProviders2": { + "message": "Přidejte prosím další poskytovatele, kteří jsou lépe podporováni v různých zařízeních (například ověřovací aplikace)." + }, + "twoStepOptions": { + "message": "Možnosti dvoufázového přihlášení" + }, + "selfHostedEnvironment": { + "message": "Vlastnoručně hostované prostředí" + }, + "selfHostedEnvironmentFooter": { + "message": "Zadejte základní URL adresu vlastnoručně hostované aplikace Bitwarden." + }, + "customEnvironment": { + "message": "Vlastní prostředí" + }, + "customEnvironmentFooter": { + "message": "Pro pokročilé uživatele. Můžete zadat základní URL adresu každé služby zvlášť." + }, + "baseUrl": { + "message": "URL serveru" + }, + "apiUrl": { + "message": "URL serveru API" + }, + "webVaultUrl": { + "message": "URL serveru webového trezoru" + }, + "identityUrl": { + "message": "URL serveru identity" + }, + "notificationsUrl": { + "message": "URL serveru pro oznámení" + }, + "iconsUrl": { + "message": "URL serveru ikonek" + }, + "environmentSaved": { + "message": "URL adresy vlastního prostředí byly uloženy" + }, + "ok": { + "message": "OK" + }, + "yes": { + "message": "Ano" + }, + "no": { + "message": "Ne" + }, + "overwritePassword": { + "message": "Přepsat heslo" + }, + "learnMore": { + "message": "Dozvědět se více" + }, + "featureUnavailable": { + "message": "Funkce není dostupná" + }, + "loggedOut": { + "message": "Odhlášení" + }, + "loginExpired": { + "message": "Platnost přihlášení vypršela." + }, + "logOutConfirmation": { + "message": "Opravdu se chcete odhlásit?" + }, + "logOut": { + "message": "Odhlásit se" + }, + "addNewLogin": { + "message": "Přidat nové přihlašovací údaje" + }, + "addNewItem": { + "message": "Přidat novou položku" + }, + "addNewFolder": { + "message": "Přidat novou složku" + }, + "view": { + "message": "Zobrazit" + }, + "account": { + "message": "Účet" + }, + "loading": { + "message": "Načítání..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Generátor hesla" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Nahlásit chybu" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Sledujte nás" + }, + "syncVault": { + "message": "Synchronizovat trezor" + }, + "changeMasterPass": { + "message": "Změnit hlavní heslo" + }, + "changeMasterPasswordConfirmation": { + "message": "Hlavní heslo si můžete změnit na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "fingerprintPhrase": { + "message": "Fráze otisku prstu", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fráze otisku prstu vašeho účtu", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Otevřít webovou aplikaci" + }, + "getMobileApp": { + "message": "Stáhnout mobilní aplikaci" + }, + "getBrowserExtension": { + "message": "Stáhnout rozšíření do prohlížeče" + }, + "syncingComplete": { + "message": "Synchronizace je dokončena" + }, + "syncingFailed": { + "message": "Synchronizace selhala" + }, + "yourVaultIsLocked": { + "message": "Váš trezor je uzamčen. Pro pokračování musíte zadat hlavní heslo." + }, + "unlock": { + "message": "Odemknout" + }, + "loggedInAsOn": { + "message": "Přihlášen jako $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Chybné hlavní heslo" + }, + "twoStepLoginConfirmation": { + "message": "Dvoufázové přihlášení činí váš účet mnohem bezpečnějším díky nutnosti po každém úspěšném přihlášení zadat ověřovací kód získaný z aplikace, SMS, e-mailu nebo telefonního hovoru. Dvoufázové přihlášení lze aktivovat na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "twoStepLogin": { + "message": "Dvoufázové přihlášení" + }, + "vaultTimeout": { + "message": "Časový limit trezoru" + }, + "vaultTimeoutDesc": { + "message": "Vyberte, kdy vyprší bezpečnostní limit trezoru. Poté bude provedena vybraná akce." + }, + "immediately": { + "message": "Okamžitě" + }, + "tenSeconds": { + "message": "10 sekund" + }, + "twentySeconds": { + "message": "20 sekund" + }, + "thirtySeconds": { + "message": "30 sekund" + }, + "oneMinute": { + "message": "Po 1 minutě" + }, + "twoMinutes": { + "message": "2 minuty" + }, + "fiveMinutes": { + "message": "Po 5 minutách" + }, + "fifteenMinutes": { + "message": "Po 15 minutách" + }, + "thirtyMinutes": { + "message": "Po 30 minutách" + }, + "oneHour": { + "message": "Po 1 hodině" + }, + "fourHours": { + "message": "Po 4 hodinách" + }, + "onIdle": { + "message": "Při nečinnosti systému" + }, + "onSleep": { + "message": "Při přechodu do režimu spánku" + }, + "onLocked": { + "message": "Při zamknutí systému" + }, + "onRestart": { + "message": "Při restartu systému" + }, + "never": { + "message": "Nikdy" + }, + "security": { + "message": "Zabezpečení" + }, + "clearClipboard": { + "message": "Vymazat schránku", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automaticky vymazat zkopírované hodnoty z vaší schránky.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Zakázat ikonky webových stránek" + }, + "disableFaviconDesc": { + "message": "Ikonky webových stránek zobrazí snadno rozeznatelný obrázek vedle každé položky ve vašem trezoru." + }, + "enableMinToTray": { + "message": "Minimalizovat do systémové lišty" + }, + "enableMinToTrayDesc": { + "message": "Při minimalizaci okna zobrazit ikonu v systémové liště." + }, + "enableMinToMenuBar": { + "message": "Minimalizovat do panelu nabídek" + }, + "enableMinToMenuBarDesc": { + "message": "Při minimalizaci okna, zobrazit ikonu v panelu nabídek." + }, + "enableCloseToTray": { + "message": "Zavřít do systémové lišty" + }, + "enableCloseToTrayDesc": { + "message": "Při zavírání okna zobrazit ikonu v systémové liště." + }, + "enableCloseToMenuBar": { + "message": "Zavřít do panelu nabídek" + }, + "enableCloseToMenuBarDesc": { + "message": "Při zavření okna, zobrazit ikonu v panelu nabídek." + }, + "enableTray": { + "message": "Povolit ikonu v systémové liště" + }, + "enableTrayDesc": { + "message": "Vždy zobrazovat ikonu v systémové liště." + }, + "startToTray": { + "message": "Spustit do systémové lišty" + }, + "startToTrayDesc": { + "message": "Při prvním spuštění aplikace zobrazit pouze ikonu v systémové liště." + }, + "startToMenuBar": { + "message": "Spustit minimalizované v panelu nabídek" + }, + "startToMenuBarDesc": { + "message": "Při prvním spuštění aplikace zobrazit pouze ikonu v panelu nabídek." + }, + "openAtLogin": { + "message": "Spustit automaticky při přihlášení" + }, + "openAtLoginDesc": { + "message": "Při přihlášení automaticky spustit aplikaci Bitwarden." + }, + "alwaysShowDock": { + "message": "Vždy zobrazovat v Docku" + }, + "alwaysShowDockDesc": { + "message": "Zobrazit ikonu Bitwarden v Docku, i když je minimalizován na liště nabídky." + }, + "confirmTrayTitle": { + "message": "Potvrdit zakázání lišty" + }, + "confirmTrayDesc": { + "message": "Zakázáním tohoto nastavení zakážete také všechna ostatní nastavení související s lištami." + }, + "language": { + "message": "Jazyk" + }, + "languageDesc": { + "message": "Změna jazyku používaného aplikací. Je vyžadován restart." + }, + "theme": { + "message": "Motiv" + }, + "themeDesc": { + "message": "Změna barevného motivu aplikace." + }, + "dark": { + "message": "Tmavý", + "description": "Dark color" + }, + "light": { + "message": "Světlý", + "description": "Light color" + }, + "copy": { + "message": "Kopírovat", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Zkontrolovat aktualizace" + }, + "version": { + "message": "Verze $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restartovat pro aktualizaci" + }, + "restartToUpdateDesc": { + "message": "Verze $VERSION_NUM$ je připravena k instalaci. Pro dokončení je ovšem potřeba restartovat aplikaci Bitwarden. Chcete nyní provést restart a aktualizaci?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Aktualizace je dostupná" + }, + "updateAvailableDesc": { + "message": "Byla nalezena aktualizace. Chcete ji nyní stáhnout?" + }, + "restart": { + "message": "Restartovat" + }, + "later": { + "message": "Později" + }, + "noUpdatesAvailable": { + "message": "Nejsou k dispozici žádné aktualizace. Používáte nejnovější verzi." + }, + "updateError": { + "message": "Chyba aktualizace" + }, + "unknown": { + "message": "Neznámá" + }, + "copyUsername": { + "message": "Kopírovat uživatelské jméno" + }, + "copyNumber": { + "message": "Kopírovat číslo", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopírovat bezpečnostní kód", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Prémiové členství" + }, + "premiumManage": { + "message": "Spravovat členství" + }, + "premiumManageAlert": { + "message": "Své členství můžete spravovat na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "premiumRefresh": { + "message": "Obnovit členství" + }, + "premiumNotCurrentMember": { + "message": "Momentálně nejste prémiovým členem." + }, + "premiumSignUpAndGet": { + "message": "Přihlaste se k prémiovému členství a získejte:" + }, + "premiumSignUpStorage": { + "message": "1 GB šifrovaného uložiště pro přílohy." + }, + "premiumSignUpTwoStep": { + "message": "Další možnosti dvoufázového přihlášení, jako je například YubiKey, FIDO U2F a Duo." + }, + "premiumSignUpReports": { + "message": "Reporty o hygieně vašich hesel, zdraví účtu a narušeních bezpečnosti." + }, + "premiumSignUpTotp": { + "message": "Generátor TOTP kódu dvoufázového přihlašování (2FA) pro přihlašovací údaje ve vašem trezoru." + }, + "premiumSignUpSupport": { + "message": "Prioritní zákaznickou podporu." + }, + "premiumSignUpFuture": { + "message": "Všechny budoucí prémiové funkce. Více již brzy!" + }, + "premiumPurchase": { + "message": "Zakoupit prémiové členství" + }, + "premiumPurchaseAlert": { + "message": "Prémiové členství můžete zakoupit na webové stránce bitwarden.com. Chcete tuto stránku nyní otevřít?" + }, + "premiumCurrentMember": { + "message": "Jste prémiovým členem!" + }, + "premiumCurrentMemberThanks": { + "message": "Děkujeme za podporu Bitwarden." + }, + "premiumPrice": { + "message": "Vše jen za $PRICE$ ročně!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Obnova je dokončena" + }, + "passwordHistory": { + "message": "Historie hesel" + }, + "clear": { + "message": "Vymazat", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Nejsou k dispozici žádná hesla." + }, + "undo": { + "message": "Zpět" + }, + "redo": { + "message": "Znovu" + }, + "cut": { + "message": "Vyjmout", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Vložit", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Vybrat vše" + }, + "zoomIn": { + "message": "Přiblížit" + }, + "zoomOut": { + "message": "Oddálit" + }, + "resetZoom": { + "message": "Obnovit přiblížení" + }, + "toggleFullScreen": { + "message": "Režim celé obrazovky" + }, + "reload": { + "message": "Obnovit" + }, + "toggleDevTools": { + "message": "Nástroje pro vývojáře" + }, + "minimize": { + "message": "Minimalizovat", + "description": "Minimize window" + }, + "zoom": { + "message": "Přiblížení" + }, + "bringAllToFront": { + "message": "Přenést vše do popředí", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "O Bitwarden" + }, + "services": { + "message": "Služby" + }, + "hideBitwarden": { + "message": "Skrýt Bitwarden" + }, + "hideOthers": { + "message": "Skrýt ostatní" + }, + "showAll": { + "message": "Zobrazit vše" + }, + "quitBitwarden": { + "message": "Ukončit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ zkopírováno", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Nápověda" + }, + "window": { + "message": "Okno" + }, + "checkPassword": { + "message": "Zkontrolujte, zda nedošlo k úniku hesla." + }, + "passwordExposed": { + "message": "K úniku tohoto hesla došlo celkem $VALUE$x. Měli byste jej změnit.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": " V žádném ze známých případů nedošlo k úniku tohoto hesla. Mělo by být bezpečné používat jej i nadále." + }, + "baseDomain": { + "message": "Základní doména", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Přesně" + }, + "startsWith": { + "message": "Začíná na" + }, + "regEx": { + "message": "Regulární výraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Zjišťování shody", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Výchozí", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Přepnout možnosti" + }, + "organization": { + "message": "Organizace", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Výchozí" + }, + "exit": { + "message": "Ukončit" + }, + "showHide": { + "message": "Zobrazit / skrýt", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Skrýt do systémové lišty" + }, + "alwaysOnTop": { + "message": "Vždy navrchu", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Změněno", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Heslo bylo změněno", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Exportovat trezor" + }, + "fileFormat": { + "message": "Formát souboru" + }, + "warning": { + "message": "VAROVÁNÍ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potvrdit export trezoru" + }, + "exportWarningDesc": { + "message": "Tento export obsahuje data vašeho trezoru v nezašifrovaném formátu. Soubor exportu byste neměli ukládat ani odesílat přes nezabezpečené kanály (např. e-mailem). Odstraňte jej okamžitě po jeho použití." + }, + "encExportKeyWarningDesc": { + "message": "Tento export zašifruje vaše data pomocí šifrovacího klíče vašeho účtu. Pokud někdy změníte šifrovací klíč vašeho účtu, měli by jste vyexportovat data znovu, protože tento exportovaný soubor nebudete moci dešifrovat." + }, + "encExportAccountWarningDesc": { + "message": "Šifrovací klíče účtů jsou jedinečné pro každý Bitwarden uživatelský účet, takže nelze importovat šifrovaný export do jiného účtu." + }, + "noOrganizationsList": { + "message": "Nepatříte do žádné organizace. Organizace umožňují bezpečné sdílení položek s ostatními uživateli." + }, + "noCollectionsInList": { + "message": "Žádné kolekce k zobrazení." + }, + "ownership": { + "message": "Vlastnictví" + }, + "whoOwnsThisItem": { + "message": "Kdo vlastní tuto položku?" + }, + "strong": { + "message": "Silné", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobré", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slabé", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slabé hlavní heslo" + }, + "weakMasterPasswordDesc": { + "message": "Hlavní heslo, které jste si vybrali, je slabé. Pro správnou ochranu účtu Bitwarden byste měli použít silné hlavní heslo (nebo heslovou frázi). Opravdu chcete toto heslo použít?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Odemknout pomocí PIN" + }, + "setYourPinCode": { + "message": "Nastavte svůj PIN kód pro odemknutí trezoru. Pokud se zcela odhlásíte z aplikace bude váš současný PIN bude resetován." + }, + "pinRequired": { + "message": "PIN kód je vyžadován." + }, + "invalidPin": { + "message": "Neplatný PIN kód." + }, + "unlockWithWindowsHello": { + "message": "Odemknout pomocí Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Ověřte se pro Bitwarden." + }, + "unlockWithTouchId": { + "message": "Odemknout pomocí Touch ID" + }, + "touchIdConsentMessage": { + "message": "odemknout váš trezor" + }, + "noAutoPromptWindowsHello": { + "message": "Neptat se na Windows Hello při spuštění." + }, + "noAutoPromptTouchId": { + "message": "Neptat se na Touch ID při spuštění." + }, + "lockWithMasterPassOnRestart": { + "message": "Zamknout trezor při restartu pomocí hlavního hesla" + }, + "preferences": { + "message": "Nastavení" + }, + "enableMenuBar": { + "message": "Povolit ikonu panelu nabídek" + }, + "enableMenuBarDesc": { + "message": "Vždy zobrazit ikonu v panelu nabídek." + }, + "hideToMenuBar": { + "message": "Schovat do panelu nabídek" + }, + "selectOneCollection": { + "message": "Musíte vybrat alespoň jednu kolekci." + }, + "premiumUpdated": { + "message": "Povýšili jste na premium." + }, + "restore": { + "message": "Obnovit" + }, + "premiumManageAlertAppStore": { + "message": "Své předplatné můžete spravovat z App Store. Chcete nyní přejít do App Store?" + }, + "legal": { + "message": "Právní předpisy", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Podmínky použití" + }, + "privacyPolicy": { + "message": "Zásady ochrany osobních údajů" + }, + "unsavedChangesConfirmation": { + "message": "Jste si jisti, že chcete odejít? Pokud nyní odejdete, vaše zadané údaje nebudou uloženy." + }, + "unsavedChangesTitle": { + "message": "Neuložené změny" + }, + "clone": { + "message": "Duplikovat" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Jedna nebo více zásad organizace ovlivňuje nastavení generátoru." + }, + "vaultTimeoutAction": { + "message": "Akce při vypršení časového limitu" + }, + "vaultTimeoutActionLockDesc": { + "message": "Trezor bude uzamčen. Pro opětovný přístup k trezoru bude vyžadováno hlavní heslo." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Budete odhlášeni. Pro opětovný přístup k trezoru bude vyžadováno ověření." + }, + "lock": { + "message": "Zamknout", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Koš", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Hledat v koši" + }, + "permanentlyDeleteItem": { + "message": "Trvale smazat položku" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Opravdu chcete tuto položku trvale smazat?" + }, + "permanentlyDeletedItem": { + "message": "Trvale smazaná položka" + }, + "restoreItem": { + "message": "Obnovit položku" + }, + "restoreItemConfirmation": { + "message": "Opravdu chcete tuto položku obnovit?" + }, + "restoredItem": { + "message": "Obnovená položka" + }, + "permanentlyDelete": { + "message": "Trvale smazat" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Po vypršení časového limitu dojde k odhlášení. Přístup k trezoru bude odebrán a pro opětovné přihlášení bude vyžadováno online ověření. Opravdu chcete použít toto nastavení?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potvrzení akce při vypršení časového limitu" + }, + "enterpriseSingleSignOn": { + "message": "Jednotné podnikové přihlášení" + }, + "setMasterPassword": { + "message": "Nastavení hlavního hesla" + }, + "ssoCompleteRegistration": { + "message": "Chcete-li dokončit přihlášení pomocí SSO, nastavte prosím hlavní heslo pro přístup a ochranu vašeho trezoru." + }, + "newMasterPass": { + "message": "Nové hlavní heslo" + }, + "confirmNewMasterPass": { + "message": "Potvrďte nové heslo" + }, + "masterPasswordPolicyInEffect": { + "message": "Jedna nebo více zásad organizace vyžaduje, aby hlavní heslo splňovalo následující požadavky:" + }, + "policyInEffectMinComplexity": { + "message": "Minimální skóre složitosti $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimální délka $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Obsahuje jedno nebo více velkých písmen" + }, + "policyInEffectLowercase": { + "message": "Obsahuje jedno nebo více malých písmen" + }, + "policyInEffectNumbers": { + "message": "Obsahuje jednu nebo více číslic" + }, + "policyInEffectSpecial": { + "message": "Obsahuje jeden nebo více následujících speciálních znaků: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Vaše nové hlavní heslo nesplňuje požadavky zásad." + }, + "acceptPolicies": { + "message": "Zaškrtnutím tohoto políčka souhlasím s následujícím:" + }, + "acceptPoliciesError": { + "message": "Podmínky služby a zásady ochrany osobních údajů nebyly uznány." + }, + "enableBrowserIntegration": { + "message": "Povolit integraci prohlížeče" + }, + "enableBrowserIntegrationDesc": { + "message": "Integrace prohlížeče se používá pro biometriku v prohlížeči." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Integrace prohlížeče není podporována" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Integrace prohlížeče je bohužel podporována pouze v Mac App Store verzi." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Integrace prohlížeče není podporována" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Integrace prohlížeče bohužel není ve verzi Windows Store podporována." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Vyžadovat ověření pro integraci prohlížeče" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Povolte další vrstvu zabezpečení vyžadováním ověření frází otisků prstů při vytvoření propojení mezi plochou a prohlížečem. Pokud je povoleno, vyžaduje to zásah uživatele a ověření pokaždé, když je navázáno spojení." + }, + "approve": { + "message": "Schválit" + }, + "verifyBrowserTitle": { + "message": "Ověřit připojení prohlížeče" + }, + "verifyBrowserDesc": { + "message": "Zkontrolujte, zda je zobrazený otisk totožný s otiskem zobrazeným v rozšíření prohlížeče." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrie není povolena" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrické prvky v prohlížeči vyžadují, aby v nastavení počítačové aplikace byla povolena biometrie." + }, + "personalOwnershipSubmitError": { + "message": "Z důvodu zásad organizace nemůžete ukládat položky do svého osobního trezoru. Změňte vlastnictví položky na organizaci a poté si vyberte z dostupných kolekcí." + }, + "hintEqualsPassword": { + "message": "Nápověda k vašemu heslu nemůže být stejná jako vaše heslo." + }, + "personalOwnershipPolicyInEffect": { + "message": "Zásady organizace ovlivňují možnosti vlastnictví." + }, + "allSends": { + "message": "Všechny Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Soubor" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Hledat Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Upravit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Můj trezor" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Datum smazání" + }, + "deletionDateDesc": { + "message": "Tento Send bude trvale smazán v určený datum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Datum expirace" + }, + "expirationDateDesc": { + "message": "Je-li nastaveno, přístup k tomuto Send vyprší v daný datum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximální počet přístupů" + }, + "maxAccessCountDesc": { + "message": "Je-li nastaveno, uživatelé již nebudou mít přístup k tomuto Send, jakmile bude dosaženo maximálního počtu přístupů.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Počet aktuálních přístupů" + }, + "disableSend": { + "message": "Deaktivujte tento Send, aby k němu nikdo neměl přístup.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Volitelně vyžadovat heslo pro přístup k tomuto Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Soukromé poznámky o tomto Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Odkaz tohoto Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Odkaz tohoto Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Při přístupu k tomuto Send, ve výchozím nastavení skrýt text", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send vytvořen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send upraven", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send smazán", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nové heslo" + }, + "whatTypeOfSend": { + "message": "Jakého typu je tento Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Vytvořit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Text, který chcete odeslat." + }, + "sendFileDesc": { + "message": "Soubor, který chcete odeslat." + }, + "days": { + "message": "$DAYS$ dní", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 den" + }, + "custom": { + "message": "Vlastní" + }, + "deleteSendConfirmation": { + "message": "Jste si jisti, že chcete odstranit tento Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Zkopírovat odkaz Send do schránky", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Zkopírovat odkaz tohoto Send do mé schránky při uložení." + }, + "sendDisabled": { + "message": "Send deaktivován", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Kvůli zásadám podniku můžete odstranit pouze existující Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopírovat odkaz" + }, + "disabled": { + "message": "Zakázáno" + }, + "maxAccessCountReached": { + "message": "Dosažen maximální počet přístupů" + }, + "expired": { + "message": "Vypršela platnost" + }, + "pendingDeletion": { + "message": "Čeká na smazání" + }, + "webAuthnAuthenticate": { + "message": "Ověřit WebAuthn" + }, + "hideEmail": { + "message": "Skrýt moji e-mailovou adresu před příjemci." + }, + "sendOptionsPolicyInEffect": { + "message": "Jedna nebo více zásad organizace ovlivňuje nastavení Send." + }, + "emailVerificationRequired": { + "message": "Je vyžadováno ověření emailu" + }, + "emailVerificationRequiredDesc": { + "message": "K použití této funkce je zapotřebí ověření vašeho e-mailu." + }, + "passwordPrompt": { + "message": "Zeptat se znovu na hlavní heslo" + }, + "passwordConfirmation": { + "message": "Potvrzení hlavního hesla" + }, + "passwordConfirmationDesc": { + "message": "Tato akce je chráněna. Chcete-li pokračovat, zadejte znovu vaše hlavní heslo, abychom ověřili vaší totožnost." + }, + "updatedMasterPassword": { + "message": "Hlavní heslo aktualizováno" + }, + "updateMasterPassword": { + "message": "Aktualizovat hlavní heslo" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hodin" + }, + "minutes": { + "message": "Minut" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Přidat účet" + }, + "removeMasterPassword": { + "message": "Odstranit hlavní heslo" + }, + "removedMasterPassword": { + "message": "Hlavní heslo bylo odstraněno." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Opustit organizaci" + }, + "leaveOrganizationConfirmation": { + "message": "Opravdu chcete opustit tuto organizaci?" + }, + "leftOrganization": { + "message": "Opustili jste organizaci." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Nastavení" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Přepnout účet" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/da/messages.json b/apps/desktop/src/locales/da/messages.json new file mode 100644 index 0000000000..d623d782c7 --- /dev/null +++ b/apps/desktop/src/locales/da/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtre" + }, + "allItems": { + "message": "Alle elementer" + }, + "favorites": { + "message": "Favoritter" + }, + "types": { + "message": "Typer" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Kort" + }, + "typeIdentity": { + "message": "Identitet" + }, + "typeSecureNote": { + "message": "Sikret notat" + }, + "folders": { + "message": "Mapper" + }, + "collections": { + "message": "Samlinger" + }, + "searchVault": { + "message": "Søg i boks" + }, + "addItem": { + "message": "Tilføj element" + }, + "shared": { + "message": "Delt" + }, + "share": { + "message": "Del" + }, + "moveToOrganization": { + "message": "Flyt til organisation" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ flyttet til $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vælg den organisation, som du vil flytte dette emne til. Flytning overfører ejerskab af emnet til organisationen, og du vil efter flytningen ikke længere være den direkte ejer af emnet." + }, + "attachments": { + "message": "Vedhæftninger" + }, + "viewItem": { + "message": "Vis element" + }, + "name": { + "message": "Navn" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Ny URI" + }, + "username": { + "message": "Brugernavn" + }, + "password": { + "message": "Kodeord" + }, + "passphrase": { + "message": "Adgangssætning" + }, + "editItem": { + "message": "Redigér element" + }, + "emailAddress": { + "message": "E-mailadresse" + }, + "verificationCodeTotp": { + "message": "Verifikationskode (TOTP)" + }, + "website": { + "message": "Hjemmeside" + }, + "notes": { + "message": "Notater" + }, + "customFields": { + "message": "Brugerdefinerede felter" + }, + "launch": { + "message": "Kør" + }, + "copyValue": { + "message": "Kopiér værdi", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimér, når du kopierer til udklipsholder" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimér, når du kopierer et elements data til udklipsholderen." + }, + "toggleVisibility": { + "message": "Slå synlighed til/fra" + }, + "toggleCollapse": { + "message": "Fold sammen/fold ud", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kortindehaverens navn" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Mærke" + }, + "expiration": { + "message": "Udløb" + }, + "securityCode": { + "message": "Sikkerhedskode" + }, + "identityName": { + "message": "Identitetsnavn" + }, + "company": { + "message": "Virksomhed" + }, + "ssn": { + "message": "CPR-nummer" + }, + "passportNumber": { + "message": "Pasnummer" + }, + "licenseNumber": { + "message": "Kørekortnummer" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresse" + }, + "premiumRequired": { + "message": "Premium kræves" + }, + "premiumRequiredDesc": { + "message": "Premium-medlemskab kræves for at anvende denne funktion." + }, + "errorOccurred": { + "message": "En fejl er opstået." + }, + "error": { + "message": "Fejl" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Marts" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "eks.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titel" + }, + "mr": { + "message": "Hr" + }, + "mrs": { + "message": "Fru" + }, + "ms": { + "message": "Frøken" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Udløbsmåned" + }, + "expirationYear": { + "message": "Udløbsår" + }, + "select": { + "message": "Vælg" + }, + "other": { + "message": "Andet" + }, + "generatePassword": { + "message": "Generér adgangskode" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "Fornavn" + }, + "middleName": { + "message": "Mellemnavn" + }, + "lastName": { + "message": "Efternavn" + }, + "fullName": { + "message": "Fulde navn" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "By" + }, + "stateProvince": { + "message": "Region" + }, + "zipPostalCode": { + "message": "Postnummer" + }, + "country": { + "message": "Land" + }, + "save": { + "message": "Gem" + }, + "cancel": { + "message": "Annullér" + }, + "delete": { + "message": "Slet" + }, + "favorite": { + "message": "Favorit" + }, + "edit": { + "message": "Redigér" + }, + "authenticatorKeyTotp": { + "message": "Autentificeringsnøgle (TOTP)" + }, + "folder": { + "message": "Mappe" + }, + "newCustomField": { + "message": "Nyt brugerdefineret felt" + }, + "value": { + "message": "Værdi" + }, + "dragToSort": { + "message": "Træk for at sortere" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Skjult" + }, + "cfTypeBoolean": { + "message": "Boolsk" + }, + "cfTypeLinked": { + "message": "Forbundet", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Forbundet værdi", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Fjern" + }, + "nameRequired": { + "message": "Navn er påkrævet." + }, + "addedItem": { + "message": "Tilføjede element" + }, + "editedItem": { + "message": "Redigerede element" + }, + "deleteItem": { + "message": "Slet element" + }, + "deleteFolder": { + "message": "Slet mappe" + }, + "deleteAttachment": { + "message": "Slet vedhæftning" + }, + "deleteItemConfirmation": { + "message": "Er du sikker på, at du sende til papirkurven?" + }, + "deletedItem": { + "message": "Element sendt til papirkurven" + }, + "overwritePasswordConfirmation": { + "message": "Er du sikker på, at du vil overskrive den aktuelle adgangskode?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Ingen mappe", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Tilføj mappe" + }, + "editFolder": { + "message": "Redigér mappe" + }, + "regeneratePassword": { + "message": "Regenerér adgangskode" + }, + "copyPassword": { + "message": "Kopiér kodeord" + }, + "copyUri": { + "message": "Kopiér URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopiér bekræftelseskode (TOTP)" + }, + "length": { + "message": "Længde" + }, + "numWords": { + "message": "Antal ord" + }, + "wordSeparator": { + "message": "Ordseparator" + }, + "capitalize": { + "message": "Stort begyndelsesbogstav", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inkludér ciffer" + }, + "close": { + "message": "Luk" + }, + "minNumbers": { + "message": "Mindste antal cifre" + }, + "minSpecial": { + "message": "Mindste antal specialtegn", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Undgå tvetydige tegn" + }, + "searchCollection": { + "message": "Søg i samling" + }, + "searchFolder": { + "message": "Søg i mappe" + }, + "searchFavorites": { + "message": "Søg i favoritter" + }, + "searchType": { + "message": "Søg type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Tilføj ny vedhæftning" + }, + "deletedAttachment": { + "message": "Slettet vedhæftning" + }, + "deleteAttachmentConfirmation": { + "message": "Er du sikker på du vil slette denne vedhæftning?" + }, + "attachmentSaved": { + "message": "Den vedhæftede fil er blevet gemt." + }, + "file": { + "message": "Fil" + }, + "selectFile": { + "message": "Vælg en fil." + }, + "maxFileSize": { + "message": "Maksimum filstørrelse er 500 MB." + }, + "updateKey": { + "message": "Du kan ikke bruge denne funktion, før du opdaterer din krypteringsnøgle." + }, + "editedFolder": { + "message": "Redigerede mappe" + }, + "addedFolder": { + "message": "Tilføjede mappe" + }, + "deleteFolderConfirmation": { + "message": "Er du sikker på du vil slette denne mappe?" + }, + "deletedFolder": { + "message": "Slettede mappe" + }, + "loginOrCreateNewAccount": { + "message": "Log ind eller opret en ny konto for at få adgang til din sikre boks." + }, + "createAccount": { + "message": "Opret konto" + }, + "logIn": { + "message": "Log ind" + }, + "submit": { + "message": "Indsend" + }, + "masterPass": { + "message": "Hovedadgangskode" + }, + "masterPassDesc": { + "message": "Hovedadgangskoden er den adgangskode, du bruger til at få adgang til din boks. Det er meget vigtigt, at du ikke glemmer din hovedadgangskode. Der er ingen måde hvorpå koden kan genoprettes, i tilfælde af at du glemmer den." + }, + "masterPassHintDesc": { + "message": "Et tip til hovedadgangskoden kan hjælpe dig med at huske din adgangskode, hvis du glemmer den." + }, + "reTypeMasterPass": { + "message": "Gentast hovedadgangskode" + }, + "masterPassHint": { + "message": "Hovedadgangskodetip (valgfri)" + }, + "settings": { + "message": "Indstillinger" + }, + "passwordHint": { + "message": "Adgangskodetip" + }, + "enterEmailToGetHint": { + "message": "Indtast din kontos e-mailadresse for at modtage dit hovedadgangskodetip." + }, + "getMasterPasswordHint": { + "message": "Få hovedadgangskodetip" + }, + "emailRequired": { + "message": "E-mailadresse er påkrævet." + }, + "invalidEmail": { + "message": "Ugyldig e-mailadresse." + }, + "masterPassRequired": { + "message": "Hovedadgangskode er påkrævet." + }, + "masterPassLength": { + "message": "Hovedadgangskoden skal være på mindst 8 tegn." + }, + "masterPassDoesntMatch": { + "message": "De to adgangskoder matcher ikke." + }, + "newAccountCreated": { + "message": "Din nye konto er oprettet! Du kan nu logge ind." + }, + "masterPassSent": { + "message": "Vi har sendt dig en e-mail med dit hovedadgangskodetip." + }, + "unexpectedError": { + "message": "Der opstod en uventet fejl." + }, + "itemInformation": { + "message": "Elementinformation" + }, + "noItemsInList": { + "message": "Der er ingen elementer at vise." + }, + "sendVerificationCode": { + "message": "Send en bekræftelseskode til din e-mail" + }, + "sendCode": { + "message": "Send kode" + }, + "codeSent": { + "message": "Kode sendt" + }, + "verificationCode": { + "message": "Bekræftelseskode" + }, + "confirmIdentity": { + "message": "Bekræft din identitet for at fortsætte." + }, + "verificationCodeRequired": { + "message": "Bekræftelseskode er påkrævet." + }, + "invalidVerificationCode": { + "message": "Ugyldig bekræftelseskode" + }, + "continue": { + "message": "Fortsæt" + }, + "enterVerificationCodeApp": { + "message": "Indtast den 6-cifrede verifikationskode fra din autentificeringsapp." + }, + "enterVerificationCodeEmail": { + "message": "Indtast den 6-cifrede verifikationskode, der blev sendt til $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Bekræftelses-email sendt til $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Husk mig" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verifikationskode-email igen" + }, + "useAnotherTwoStepMethod": { + "message": "Brug en anden to-trins-loginmetode" + }, + "insertYubiKey": { + "message": "Indsæt din YubiKey i din computers USB-port og tryk derefter på dens knap." + }, + "insertU2f": { + "message": "Indsæt din sikkerhedsnøgle i din computers USB-port. Hvis den har en knap, tryk på den." + }, + "recoveryCodeDesc": { + "message": "Mistet adgang til alle dine to-faktor-udbydere? Brug din genoprettelseskode til at deaktivere alle to-faktor udbydere på din konto." + }, + "recoveryCodeTitle": { + "message": "Gendannelseskode" + }, + "authenticatorAppTitle": { + "message": "Autentificeringsapp" + }, + "authenticatorAppDesc": { + "message": "Brug en autentificeringsapp (f.eks. Authy eller Google Autentificering) til at generere tidsbaserede bekræftelseskoder.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP sikkerhedsnøgle" + }, + "yubiKeyDesc": { + "message": "Brug en YubiKey til at få adgang til din konto. Virker med YubiKey 4, 4 Nano, 4C og NEO enheder." + }, + "duoDesc": { + "message": "Bekræft med Duo sikkerhed ved hjælp af Duo Mobile app, SMS, telefonopkald eller U2F sikkerhedsnøgle.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Bekræft med Duo Security for din organisation ved hjælp af Duo Mobile app, SMS, telefonopkald eller U2F-sikkerhedsnøgle.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Brug en hvilken som helst WebAuthn-aktiveret sikkerhedsnøgle til at få adgang til din konto." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Bekræftelseskoder vil blive e-mailet til dig." + }, + "loginUnavailable": { + "message": "Login utilgængelig" + }, + "noTwoStepProviders": { + "message": "Denne konto har to-trins login aktiveret, men ingen af de konfigurerede to-trinsudbydere understøttes af denne enhed." + }, + "noTwoStepProviders2": { + "message": "Tilføj venligst yderligere udbydere, der understøttes bedre på tværs af enheder (såsom en autentificeringsapp)." + }, + "twoStepOptions": { + "message": "To-trins-login indstillinger" + }, + "selfHostedEnvironment": { + "message": "Selv-hostet miljø" + }, + "selfHostedEnvironmentFooter": { + "message": "Angiv grund-URL'en i din lokal-hostede Bitwarden-installation." + }, + "customEnvironment": { + "message": "Brugerdefineret miljø" + }, + "customEnvironmentFooter": { + "message": "Til avancerede brugere. Du kan angive grund URL'en for hver tjeneste uafhængigt." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API server URL" + }, + "webVaultUrl": { + "message": "Web-boks server URL" + }, + "identityUrl": { + "message": "Identitetsserver URL" + }, + "notificationsUrl": { + "message": "Meddelelsesserver URL" + }, + "iconsUrl": { + "message": "Ikonserver URL" + }, + "environmentSaved": { + "message": "Miljøets URLs er blevet gemt." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nej" + }, + "overwritePassword": { + "message": "Overskriv adgangskode" + }, + "learnMore": { + "message": "Lær mere" + }, + "featureUnavailable": { + "message": "Funktion utilgængelig" + }, + "loggedOut": { + "message": "Logget ud" + }, + "loginExpired": { + "message": "Din login-session er udløbet." + }, + "logOutConfirmation": { + "message": "Er du sikker på, at du vil logge ud?" + }, + "logOut": { + "message": "Log ud" + }, + "addNewLogin": { + "message": "Tilføj nyt login" + }, + "addNewItem": { + "message": "Tilføj nyt element" + }, + "addNewFolder": { + "message": "Tilføj ny mappe" + }, + "view": { + "message": "Vis" + }, + "account": { + "message": "Konto" + }, + "loading": { + "message": "Indlæser..." + }, + "lockVault": { + "message": "Lås boks" + }, + "passwordGenerator": { + "message": "Adgangskodegenerator" + }, + "contactUs": { + "message": "Kontakt os" + }, + "getHelp": { + "message": "Få hjælp" + }, + "fileBugReport": { + "message": "Indsend en fejlrapport" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Følg os" + }, + "syncVault": { + "message": "Synkronisér boks" + }, + "changeMasterPass": { + "message": "Skift hovedadgangskode" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kan ændre din hovedadgangskode i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "fingerprintPhrase": { + "message": "Fingeraftrykssætning", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Din kontos fingeraftrykssætning", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Gå til web-boks" + }, + "getMobileApp": { + "message": "Hent mobilapp" + }, + "getBrowserExtension": { + "message": "Hent browserudvidelse" + }, + "syncingComplete": { + "message": "Synkronisering fuldført" + }, + "syncingFailed": { + "message": "Synkronisering mislykkedes" + }, + "yourVaultIsLocked": { + "message": "Din boks er låst. Bekræft din identitet for at fortsætte." + }, + "unlock": { + "message": "Lås op" + }, + "loggedInAsOn": { + "message": "Logget ind som $EMAIL$ på $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ugyldig hovedadgangskode" + }, + "twoStepLoginConfirmation": { + "message": "To-trins login gør din konto mere sikker ved at kræve, at du verificerer dit login med en anden enhed, med en sikkerhedsnøgle, autentificerings app, SMS, telefonopkald eller e-mail. To-trins login kan aktiveres i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "twoStepLogin": { + "message": "To-trins login" + }, + "vaultTimeout": { + "message": "Boks timeout" + }, + "vaultTimeoutDesc": { + "message": "Vælg timeout for din boks, hvorefter den vil udføre den valgte handling." + }, + "immediately": { + "message": "Straks" + }, + "tenSeconds": { + "message": "10 sekunder" + }, + "twentySeconds": { + "message": "20 sekunder" + }, + "thirtySeconds": { + "message": "30 sekunder" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minutter" + }, + "fiveMinutes": { + "message": "5 minutter" + }, + "fifteenMinutes": { + "message": "15 minutter" + }, + "thirtyMinutes": { + "message": "30 minutter" + }, + "oneHour": { + "message": "1 time" + }, + "fourHours": { + "message": "4 timer" + }, + "onIdle": { + "message": "Når systemet er inaktivt" + }, + "onSleep": { + "message": "Når systemet sover" + }, + "onLocked": { + "message": "Når systemet låses" + }, + "onRestart": { + "message": "Ved genstart" + }, + "never": { + "message": "Aldrig" + }, + "security": { + "message": "Sikkerhed" + }, + "clearClipboard": { + "message": "Ryd udklipsholder", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Fjern automatisk kopierede data fra din udklipsholder.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Slå webikoner fra" + }, + "disableFaviconDesc": { + "message": "Webikoner vises som et genkendeligt billede ved siden af hvert loginelement i din boks." + }, + "enableMinToTray": { + "message": "Minimer til bakkeikon" + }, + "enableMinToTrayDesc": { + "message": "Når vinduet minimeres, vis i stedet et ikon i meddelelsesområdet." + }, + "enableMinToMenuBar": { + "message": "Minimér til menulinjen" + }, + "enableMinToMenuBarDesc": { + "message": "Når vinduet minimeres, vis i stedet et ikon på menulinjen." + }, + "enableCloseToTray": { + "message": "Luk til ikon i meddelelsesområdet" + }, + "enableCloseToTrayDesc": { + "message": "Når vinduet lukkes, vis i stedet et ikon i meddelelsesområdet." + }, + "enableCloseToMenuBar": { + "message": "Luk til menulinjen" + }, + "enableCloseToMenuBarDesc": { + "message": "Når vinduet lukkes, vis i stedet et ikon på menulinjen." + }, + "enableTray": { + "message": "Aktivér bakkeikon" + }, + "enableTrayDesc": { + "message": "Vis altid et ikon i meddelelsesområdet." + }, + "startToTray": { + "message": "Start som ikon i meddelelsesområdet" + }, + "startToTrayDesc": { + "message": "Når applikationen startes første gang, skal der kun vises et ikon i meddelelsesområdet." + }, + "startToMenuBar": { + "message": "Start på menulinjen" + }, + "startToMenuBarDesc": { + "message": "Når applikationen startes første gang, skal der kun vises et ikon på menulinjen." + }, + "openAtLogin": { + "message": "Start automatisk ved login" + }, + "openAtLoginDesc": { + "message": "Start Bitwarden skrivebordsapplikationen automatisk ved login." + }, + "alwaysShowDock": { + "message": "Vis altid i Dock" + }, + "alwaysShowDockDesc": { + "message": "Vis Bitwarden-ikonet i Dock, selv når det er minimeret til menulinjen." + }, + "confirmTrayTitle": { + "message": "Bekræft deaktivering af bakke" + }, + "confirmTrayDesc": { + "message": "Deaktivering af denne indstilling vil også deaktivere alle andre indstillinger relateret til bakken." + }, + "language": { + "message": "Sprog" + }, + "languageDesc": { + "message": "Skift det sprog, der bruges af applikationen. Genstart er påkrævet." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Skift applikationens farvetema." + }, + "dark": { + "message": "Mørk", + "description": "Dark color" + }, + "light": { + "message": "Lys", + "description": "Light color" + }, + "copy": { + "message": "Kopiér", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Søg efter opdateringer" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Genstart for at opdatere" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ er klar til at installere. Du skal genstarte applikationen for at færdiggøre installationen. Vil du genstarte og opdatere nu?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Opdatering tilgængelig" + }, + "updateAvailableDesc": { + "message": "En opdatering blev fundet. Vil du hente den nu?" + }, + "restart": { + "message": "Genstart" + }, + "later": { + "message": "Senere" + }, + "noUpdatesAvailable": { + "message": "Ingen opdateringer er tilgængelige i øjeblikket. Du anvender den nyeste version." + }, + "updateError": { + "message": "Opdateringsfejl" + }, + "unknown": { + "message": "Ukendt" + }, + "copyUsername": { + "message": "Kopiér brugernavn" + }, + "copyNumber": { + "message": "Kopiér nummer", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopiér kortverifikationskode", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium-medlemskab" + }, + "premiumManage": { + "message": "Håndtér medlemsskab" + }, + "premiumManageAlert": { + "message": "Du kan håndtere dit medlemskab i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "premiumRefresh": { + "message": "Opdatér medlemskab" + }, + "premiumNotCurrentMember": { + "message": "Du er i øjeblikket ikke premium-medlem." + }, + "premiumSignUpAndGet": { + "message": "Tilmeld dig et premium medlemskab og få:" + }, + "premiumSignUpStorage": { + "message": "1 GB krypteret lager til vedhæftede filer." + }, + "premiumSignUpTwoStep": { + "message": "Yderligere to-trins-loginmuligheder såsom YubiKey, FIDO U2F og Duo." + }, + "premiumSignUpReports": { + "message": "Adgangskodehygiejne, kontosundhed og rapporter om datalæk til at holde din boks sikker." + }, + "premiumSignUpTotp": { + "message": "TOTP verifikationskode (2FA) generator til logins i din boks." + }, + "premiumSignUpSupport": { + "message": "Prioriteret kundeservice." + }, + "premiumSignUpFuture": { + "message": "Alle fremtidige premium-funktioner. Mere kommer snart!" + }, + "premiumPurchase": { + "message": "Køb premium" + }, + "premiumPurchaseAlert": { + "message": "Du kan købe premium-medlemskab i bitwarden.com web-boksen. Vil du besøge hjemmesiden nu?" + }, + "premiumCurrentMember": { + "message": "Du er premium-medlem!" + }, + "premiumCurrentMemberThanks": { + "message": "Tak fordi du støtter Bitwarden." + }, + "premiumPrice": { + "message": "Alt dette for kun $PRICE$ /år!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Opdatering færdig" + }, + "passwordHistory": { + "message": "Adgangskodehistorik" + }, + "clear": { + "message": "Ryd", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Der er ingen kodeord at vise." + }, + "undo": { + "message": "Fortryd" + }, + "redo": { + "message": "Annullér fortryd" + }, + "cut": { + "message": "Klip", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Indsæt", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Markér alt" + }, + "zoomIn": { + "message": "Zoom ind" + }, + "zoomOut": { + "message": "Zoom ud" + }, + "resetZoom": { + "message": "Nulstil zoom" + }, + "toggleFullScreen": { + "message": "Aktivér/deaktivér fuld skærm" + }, + "reload": { + "message": "Genindlæs" + }, + "toggleDevTools": { + "message": "Udviklingsværktøjer til/fra" + }, + "minimize": { + "message": "Minimér", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Placér alle forrest", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Om Bitwarden" + }, + "services": { + "message": "Tjenester" + }, + "hideBitwarden": { + "message": "Skjul Bitwarden" + }, + "hideOthers": { + "message": "Skjul øvrige" + }, + "showAll": { + "message": "Vis alle" + }, + "quitBitwarden": { + "message": "Afslut Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ kopieret", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Hjælp" + }, + "window": { + "message": "Vindue" + }, + "checkPassword": { + "message": "Undersøg om adgangskoden er blevet afsløret." + }, + "passwordExposed": { + "message": "Denne adgangskode er blevet afsløret $VALUE$ gang(e) i datalæk. Du burde skifte den.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Denne adgangskode er ikke fundet i nogen kendte datalæk. Den burde være sikker at bruge." + }, + "baseDomain": { + "message": "Grund-domæne", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Vært", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Nøjagtig" + }, + "startsWith": { + "message": "Begynder med" + }, + "regEx": { + "message": "Regulært udtryk", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Matchmetode", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standard matchmetode", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Skift indstillinger" + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Standard" + }, + "exit": { + "message": "Afslut" + }, + "showHide": { + "message": "Vis / skjul", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Skjul til bakke" + }, + "alwaysOnTop": { + "message": "Altid øverst", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Opdateret", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Adgangskode opdateret", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Eksportér boks" + }, + "fileFormat": { + "message": "Filformat" + }, + "warning": { + "message": "ADVARSEL", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Bekræft eksport af boks" + }, + "exportWarningDesc": { + "message": "Denne eksport indeholder dine boksdata i ukrypteret form. Du bør ikke gemme eller sende den eksporterede fil over usikre kanaler (f.eks. e-mail). Slet den straks efter at du er færdig med at bruge den." + }, + "encExportKeyWarningDesc": { + "message": "Denne eksport krypterer dine data vha. din kontos krypteringsnøgle. Roterer du på et tidspunkt denne kontokrypteringsnøgle, skal du eksportere igen, da du ikke vil kunne dekryptere denne eksportfil." + }, + "encExportAccountWarningDesc": { + "message": "Kontokrypteringsnøgler er unikke for hver Bitwarden-brugerkonto, så du kan ikke importere en krypteret eksport til en anden konto." + }, + "noOrganizationsList": { + "message": "Du tilhører ikke nogen organisationer. Organisationer giver dig mulighed for at dele elementer med andre brugere på en sikker måde." + }, + "noCollectionsInList": { + "message": "Der er ingen samlinger at vise." + }, + "ownership": { + "message": "Ejerskab" + }, + "whoOwnsThisItem": { + "message": "Hvem ejer dette element?" + }, + "strong": { + "message": "Stærk", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "God", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Svag", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Svag hovedadgangskode" + }, + "weakMasterPasswordDesc": { + "message": "Hovedadgangskoden du har valgt er svag. Du skal bruge en stærk hovedadgangskode (eller en adgangssætning) for at beskytte din Bitwarden-konto korrekt. Er du sikker på, at du vil bruge denne hovedadgangskode?" + }, + "pin": { + "message": "Pinkode", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Lås op med pinkode" + }, + "setYourPinCode": { + "message": "Indstil din pinkode til at låse Bitwarden op. Dine pin-indstillinger nulstilles, hvis du nogensinde logger helt ud af programmet." + }, + "pinRequired": { + "message": "Pinkode er påkrævet." + }, + "invalidPin": { + "message": "Ugyldig pinkode." + }, + "unlockWithWindowsHello": { + "message": "Lås op med Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Bekræft for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Lås op med Touch ID" + }, + "touchIdConsentMessage": { + "message": "lås din boks op" + }, + "noAutoPromptWindowsHello": { + "message": "Bed ikke om Windows Hello ved start." + }, + "noAutoPromptTouchId": { + "message": "Bed ikke om Touch ID ved start." + }, + "lockWithMasterPassOnRestart": { + "message": "Lås med hovedadgangskode ved genstart" + }, + "preferences": { + "message": "Indstillinger" + }, + "enableMenuBar": { + "message": "Aktivér menulinjeikon" + }, + "enableMenuBarDesc": { + "message": "Vis altid et ikon på menulinjen." + }, + "hideToMenuBar": { + "message": "Skjul på menulinjen" + }, + "selectOneCollection": { + "message": "Du skal vælge minimum én samling." + }, + "premiumUpdated": { + "message": "Du har opgraderet til premium." + }, + "restore": { + "message": "Gendan" + }, + "premiumManageAlertAppStore": { + "message": "Du kan administrere dit abonnement fra app butikken. Vil du besøge app butikken nu?" + }, + "legal": { + "message": "Juridisk", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Servicevilkår" + }, + "privacyPolicy": { + "message": "Fortrolighedspolitik" + }, + "unsavedChangesConfirmation": { + "message": "Er du sikker på, at du vil lukke? Hvis du lukker nu, gemmes dine nuværende oplysninger ikke." + }, + "unsavedChangesTitle": { + "message": "Ikke-gemte ændringer" + }, + "clone": { + "message": "Klon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Én eller flere organisationspolitikker påvirker dine generatorindstillinger." + }, + "vaultTimeoutAction": { + "message": "Boks timeout-handling" + }, + "vaultTimeoutActionLockDesc": { + "message": "En låst boks kræver at du gentaster din hovedadgangskode for at tilgå den igen." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "En boks der er logget ud kræver, at du godkender igen for at få adgang til den." + }, + "lock": { + "message": "Lås", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papirkurv", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Søg i papirkurven" + }, + "permanentlyDeleteItem": { + "message": "Slet element permanent" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Er du sikker på, at du vil slette dette element permanent?" + }, + "permanentlyDeletedItem": { + "message": "Element slettet permanent" + }, + "restoreItem": { + "message": "Gendan element" + }, + "restoreItemConfirmation": { + "message": "Er du sikker på, at du vil gendanne dette element?" + }, + "restoredItem": { + "message": "Element gendannet" + }, + "permanentlyDelete": { + "message": "Slette permanent" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Ved at logge ud fjernes al adgang til din boks og kræver online-godkendelse efter timeout-perioden. Er du sikker på, at du vil bruge denne indstilling?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bekræft timeout-handling" + }, + "enterpriseSingleSignOn": { + "message": "Virksomheds Single Sign On" + }, + "setMasterPassword": { + "message": "Indstil hovedadgangskode" + }, + "ssoCompleteRegistration": { + "message": "For at fuldføre indlogning vha. SSO skal en hovedadgangskode opsættes for at tilgå og beskytte din boks." + }, + "newMasterPass": { + "message": "Ny hovedadgangskode" + }, + "confirmNewMasterPass": { + "message": "Bekræft ny hovedadgangskode" + }, + "masterPasswordPolicyInEffect": { + "message": "Én eller flere organisationspolitikker kræver, at din hovedadgangskode opfylder flg. krav:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum kompleksitetsscore på $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimumslængde på $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Indeholder ét eller flere store bogstaver" + }, + "policyInEffectLowercase": { + "message": "Indeholder ét eller flere små bogstaver" + }, + "policyInEffectNumbers": { + "message": "Indeholder ét eller flere cifre" + }, + "policyInEffectSpecial": { + "message": "Indeholder ét eller flere af følgende specialtegn $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Din nye hovedadgangskode opfylder ikke politikkravene." + }, + "acceptPolicies": { + "message": "Ved at markere dette felt accepterer du følgende:" + }, + "acceptPoliciesError": { + "message": "Servicevilkår og fortrolighedspolitik er ikke blevet bekræftet." + }, + "enableBrowserIntegration": { + "message": "Aktiver browserintegration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browserintegration bruges til biometri i browseren." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browserintegration understøttes ikke" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Desværre understøttes browserintegration kun i Mac App Store-versionen indtil videre." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browserintegration understøttes ikke" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Desværre understøttes browserintegration i øjeblikket ikke i Windows Store-versionen." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Kræv verifikation for browserintegration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Aktivér et ekstra sikkerhedslag ved at kræve validering af fingeraftrykssætning, når du opretter en forbindelse mellem dit skrivebord og din browser. Når det er aktiveret, kræver dette brugerintervention og verifikation hver gang en forbindelse oprettes." + }, + "approve": { + "message": "Godkend" + }, + "verifyBrowserTitle": { + "message": "Verificér browserforbindelse" + }, + "verifyBrowserDesc": { + "message": "Sørg for, at det viste fingeraftryk er identisk med det fingeraftryk, der vises i browserudvidelsen." + }, + "biometricsNotEnabledTitle": { + "message": "Biometri ikke aktiveret" + }, + "biometricsNotEnabledDesc": { + "message": "Browserbiometri kræver, at desktop-biometri er aktiveret i indstillingerne først." + }, + "personalOwnershipSubmitError": { + "message": "På grund af en virksomhedspolitik er du begrænset til at gemme elementer i din personlige boks. Skift ejerskabsindstillingen til en organisation, og vælg blandt de tilgængelige samlinger." + }, + "hintEqualsPassword": { + "message": "Dit adgangskodetip kan ikke være det samme som din adgangskode." + }, + "personalOwnershipPolicyInEffect": { + "message": "En organisationspolitik påvirker dine ejerskabsmuligheder." + }, + "allSends": { + "message": "Alle Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fil" + }, + "sendTypeText": { + "message": "Tekst" + }, + "searchSends": { + "message": "Søg i Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Redigér Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Min boks" + }, + "text": { + "message": "Tekst" + }, + "deletionDate": { + "message": "Sletningsdato" + }, + "deletionDateDesc": { + "message": "Send'en slettes permanent på den angivne dato og tid.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Udløbsdato" + }, + "expirationDateDesc": { + "message": "Hvis angivet, vil adgangen til denne Send udløbe på den angivne dato og tidspunkt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maksimalt antal tilgange" + }, + "maxAccessCountDesc": { + "message": "Hvis opsat, vil brugere ikke længere kunne tilgå denne Send, når det maksimale adgangsantal er nået.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Aktuelt antal tilgange" + }, + "disableSend": { + "message": "Deaktivér denne Send, så ingen kan tilgå den.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Valgfrit brugeradgangskodekrav for at tilgå denne Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notater om denne Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Når Send tilgås, skjul som standard teksten", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send oprettet", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send opdateret", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send slettet", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nyt kodeord" + }, + "whatTypeOfSend": { + "message": "Hvilken type Send er dette?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Opret Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Den tekst, du vil sende." + }, + "sendFileDesc": { + "message": "Den fil, du vil sende." + }, + "days": { + "message": "$DAYS$ dage", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dag" + }, + "custom": { + "message": "Tilpasset" + }, + "deleteSendConfirmation": { + "message": "Er du sikker på, at du vil slette denne Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopiér Send link til udklipsholder", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kopier linket for at dele denne Send til min udklipsholder ved gem." + }, + "sendDisabled": { + "message": "Send deaktiveret", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Du kan grundet en virksomhedspolitik kun slette en eksisterende Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopiér link" + }, + "disabled": { + "message": "Deaktiveret" + }, + "maxAccessCountReached": { + "message": "Maksimalt adgangsantal nået" + }, + "expired": { + "message": "Udløbet" + }, + "pendingDeletion": { + "message": "Afventer sletning" + }, + "webAuthnAuthenticate": { + "message": "Godkend WebAuthn" + }, + "hideEmail": { + "message": "Skjul min e-mailadresse for modtagere." + }, + "sendOptionsPolicyInEffect": { + "message": "Én eller flere organisationspolitikker påvirker dine Send-valgmuligheder." + }, + "emailVerificationRequired": { + "message": "E-mailbekræftelse kræves" + }, + "emailVerificationRequiredDesc": { + "message": "Du skal bekræfte din mailadresse for at bruge denne funktion." + }, + "passwordPrompt": { + "message": "Genanmodning om hovedadgangskode" + }, + "passwordConfirmation": { + "message": "Bekræftelse af hovedadgangskode" + }, + "passwordConfirmationDesc": { + "message": "Denne handling er beskyttet. For at fortsætte, indtast venligst din hovedadgangskode igen for at bekræfte din identitet." + }, + "updatedMasterPassword": { + "message": "Hovedadgangskode opdateret" + }, + "updateMasterPassword": { + "message": "Opdatér hovedadgangskode" + }, + "updateMasterPasswordWarning": { + "message": "Dit hovedadgangskode blev for nylig ændret af en administrator i din organisation. For at få adgang til boksen skal du opdatere din hovedadgangskode nu. Hvis du fortsætter, logges du ud af din nuværende session, hvilket kræver, at du logger ind igen. Aktive sessioner på andre enheder kan fortsætte med at være aktive i op til én time." + }, + "hours": { + "message": "Timer" + }, + "minutes": { + "message": "Minutter" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Din organisations politikker påvirker din boks-timeout. Maksimalt tilladt boks-timeout er $HOURS$ time(r) og $MINUTES$ minut(ter)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Din boks-timeout overskrider de begrænsninger, der er fastsat af din organisation." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Auto-indrullering" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Denne organisation har en virksomhedspolitik, der automatisk tilmelder dig til nulstilling af adgangskode. Tilmelding giver organisationsadministratorer mulighed for at skifte din hovedadgangskode." + }, + "vaultExportDisabled": { + "message": "Bokseksport deaktiveret" + }, + "personalVaultExportPolicyInEffect": { + "message": "En eller flere organisationspolitikker forhindrer dig i at eksportere din personlige boks." + }, + "addAccount": { + "message": "Tilføj konto" + }, + "removeMasterPassword": { + "message": "Fjern hovedadgangskode" + }, + "removedMasterPassword": { + "message": "Hovedadgangskode fjernet." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ bruger SSO med en selv-hostet nøgleserver. En hovedadgangskode er ikke længere påkrævet for at logge ind for medlemmer af denne organisation.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Forlad organisation" + }, + "leaveOrganizationConfirmation": { + "message": "Er du sikker på, at du vil forlade denne organisation?" + }, + "leftOrganization": { + "message": "Du har forladt organisationen." + }, + "ssoKeyConnectorUnavailable": { + "message": "Kan ikke kontakte key connector, forsøg igen senere." + }, + "lockAllVaults": { + "message": "Lås alle bokse" + }, + "accountLimitReached": { + "message": "Der må ikke være logget på mere end 5 konti på samme tid." + }, + "accountPreferences": { + "message": "Indstillinger" + }, + "appPreferences": { + "message": "Appindstillinger (alle konti)" + }, + "accountSwitcherLimitReached": { + "message": "Kontogrænsen er nået. Log ud af en konto for at tilføje en anden." + }, + "settingsTitle": { + "message": "Appindstillinger for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Skift konto" + }, + "options": { + "message": "Indstillinger" + }, + "sessionTimeout": { + "message": "Din session er udløbet. Gå tilbage og prøv at logge ind igen." + }, + "exportingPersonalVaultTitle": { + "message": "Eksporterer personlig boks" + }, + "exportingPersonalVaultDescription": { + "message": "Kun de personlige bokselementer tilknyttet $EMAIL$ eksporteres. Organisationsbokseelementer medtages ikke.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/de/messages.json b/apps/desktop/src/locales/de/messages.json new file mode 100644 index 0000000000..9be83ce5ba --- /dev/null +++ b/apps/desktop/src/locales/de/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filter" + }, + "allItems": { + "message": "Alle Einträge" + }, + "favorites": { + "message": "Favoriten" + }, + "types": { + "message": "Typen" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Karte" + }, + "typeIdentity": { + "message": "Identität" + }, + "typeSecureNote": { + "message": "Sichere Notiz" + }, + "folders": { + "message": "Ordner" + }, + "collections": { + "message": "Sammlungen" + }, + "searchVault": { + "message": "Tresor durchsuchen" + }, + "addItem": { + "message": "Neuer Eintrag" + }, + "shared": { + "message": "Freigegeben" + }, + "share": { + "message": "Teilen" + }, + "moveToOrganization": { + "message": "In Organisation verschieben" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ verschoben nach $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Wähle eine Organisation aus, in die du diesen Eintrag verschieben möchtest. Das Verschieben in eine Organisation überträgt das Eigentum an diese Organisation. Du bist nicht mehr der direkte Besitzer dieses Eintrags, sobald er verschoben wurde." + }, + "attachments": { + "message": "Anhänge" + }, + "viewItem": { + "message": "Eintrag anzeigen" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Neue URL" + }, + "username": { + "message": "Nutzername" + }, + "password": { + "message": "Passwort" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Eintrag editieren" + }, + "emailAddress": { + "message": "E-Mail-Adresse" + }, + "verificationCodeTotp": { + "message": "Verifizierungscode (TOTP)" + }, + "website": { + "message": "Webseite" + }, + "notes": { + "message": "Notizen" + }, + "customFields": { + "message": "Benutzerdefinierte Felder" + }, + "launch": { + "message": "Öffnen" + }, + "copyValue": { + "message": "Wert kopieren", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimieren beim Kopieren in die Zwischenablage" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimieren, wenn Daten eines Eintrags in die Zwischenablage kopiert werden." + }, + "toggleVisibility": { + "message": "Sichtbarkeit umschalten" + }, + "toggleCollapse": { + "message": "Ein- und ausklappen", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Name des Karteninhabers" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Marke" + }, + "expiration": { + "message": "Gültig bis" + }, + "securityCode": { + "message": "Sicherheitscode" + }, + "identityName": { + "message": "Identitätsname" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Sozialversicherungsnummer" + }, + "passportNumber": { + "message": "Reisepassnummer" + }, + "licenseNumber": { + "message": "Führerscheinnummer" + }, + "email": { + "message": "E-Mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresse" + }, + "premiumRequired": { + "message": "Premium notwendig" + }, + "premiumRequiredDesc": { + "message": "Für diese Funktion ist eine Premium-Mitgliedschaft notwendig." + }, + "errorOccurred": { + "message": "Ein Fehler ist aufgetreten." + }, + "error": { + "message": "Fehler" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "März" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Dezember" + }, + "ex": { + "message": "Bsp.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titel" + }, + "mr": { + "message": "Herr" + }, + "mrs": { + "message": "Frau" + }, + "ms": { + "message": "Frau" + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Ablaufmonat" + }, + "expirationYear": { + "message": "Ablaufjahr" + }, + "select": { + "message": "Auswählen" + }, + "other": { + "message": "Sonstige" + }, + "generatePassword": { + "message": "Passwort generieren" + }, + "type": { + "message": "Typ" + }, + "firstName": { + "message": "Vorname" + }, + "middleName": { + "message": "Zweiter Vorname" + }, + "lastName": { + "message": "Nachname" + }, + "fullName": { + "message": "Vollständiger Name" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "Stadt" + }, + "stateProvince": { + "message": "Bundesland" + }, + "zipPostalCode": { + "message": "Postleitzahl" + }, + "country": { + "message": "Land" + }, + "save": { + "message": "Speichern" + }, + "cancel": { + "message": "Abbrechen" + }, + "delete": { + "message": "Löschen" + }, + "favorite": { + "message": "Favorit" + }, + "edit": { + "message": "Bearbeiten" + }, + "authenticatorKeyTotp": { + "message": "Authentifizierungsschlüssel (TOTP)" + }, + "folder": { + "message": "Ordner" + }, + "newCustomField": { + "message": "Neues benutzerdefiniertes Feld" + }, + "value": { + "message": "Wert" + }, + "dragToSort": { + "message": "Zum Sortieren ziehen" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Versteckt" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Verknüpft", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Verknüpfter Wert", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Entfernen" + }, + "nameRequired": { + "message": "Name ist erforderlich." + }, + "addedItem": { + "message": "Eintrag hinzugefügt" + }, + "editedItem": { + "message": "Eintrag bearbeitet" + }, + "deleteItem": { + "message": "Eintrag löschen" + }, + "deleteFolder": { + "message": "Ordner löschen" + }, + "deleteAttachment": { + "message": "Anhang löschen" + }, + "deleteItemConfirmation": { + "message": "Soll dieser Eintrag wirklich in den Papierkorb verschoben werden?" + }, + "deletedItem": { + "message": "Eintrag in Papierkorb verschoben" + }, + "overwritePasswordConfirmation": { + "message": "Bist du sicher, dass du das Passwort überschreiben möchtest?" + }, + "overwriteUsername": { + "message": "Benutzername überschreiben" + }, + "overwriteUsernameConfirmation": { + "message": "Bist du sicher, dass du den aktuellen Benutzernamen überschreiben möchtest?" + }, + "noneFolder": { + "message": "Kein Ordner", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Ordner hinzufügen" + }, + "editFolder": { + "message": "Ordner bearbeiten" + }, + "regeneratePassword": { + "message": "Password neu generieren" + }, + "copyPassword": { + "message": "Passwort kopieren" + }, + "copyUri": { + "message": "URI kopieren" + }, + "copyVerificationCodeTotp": { + "message": "Verifizierungscode (TOTP) kopieren" + }, + "length": { + "message": "Länge" + }, + "numWords": { + "message": "Anzahl der Wörter" + }, + "wordSeparator": { + "message": "Worttrennzeichen" + }, + "capitalize": { + "message": "Großschreiben", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Ziffer hinzufügen" + }, + "close": { + "message": "Schließen" + }, + "minNumbers": { + "message": "Mindestanzahl Zahlen" + }, + "minSpecial": { + "message": "Mindestanzahl Sonderzeichen", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Mehrdeutige Zeichen vermeiden" + }, + "searchCollection": { + "message": "Sammlung durchsuchen" + }, + "searchFolder": { + "message": "Ordner durchsuchen" + }, + "searchFavorites": { + "message": "Favoriten durchsuchen" + }, + "searchType": { + "message": "Suchmodus", + "description": "Search item type" + }, + "newAttachment": { + "message": "Anhang hinzufügen" + }, + "deletedAttachment": { + "message": "Anhang gelöscht" + }, + "deleteAttachmentConfirmation": { + "message": "Bist du sicher, dass du diesen Anhang löschen möchtest?" + }, + "attachmentSaved": { + "message": "Die Datei wurde gespeichert." + }, + "file": { + "message": "Datei" + }, + "selectFile": { + "message": "Wähle eine Datei." + }, + "maxFileSize": { + "message": "Die maximale Dateigröße beträgt 500 MB." + }, + "updateKey": { + "message": "Du kannst diese Funktion nicht nutzen, bevor du deinen Verschlüsselungsschlüssel aktualisiert hast." + }, + "editedFolder": { + "message": "Ordner bearbeitet" + }, + "addedFolder": { + "message": "Ordner hinzugefügt" + }, + "deleteFolderConfirmation": { + "message": "Bist du sicher, dass du diesen Ordner löschen möchtest?" + }, + "deletedFolder": { + "message": "Ordner gelöscht" + }, + "loginOrCreateNewAccount": { + "message": "Einloggen oder einen neuen Account erstellen, um auf den Tresor zuzugreifen." + }, + "createAccount": { + "message": "Account erstellen" + }, + "logIn": { + "message": "Anmelden" + }, + "submit": { + "message": "Absenden" + }, + "masterPass": { + "message": "Master-Passwort" + }, + "masterPassDesc": { + "message": "Das Master-Passwort wird verwendet, um den Tresor zu öffnen. Es ist sehr wichtig, dass du das Passwort nicht vergisst, da es keine Möglichkeit gibt, es zurückzusetzen." + }, + "masterPassHintDesc": { + "message": "Ein Master-Passwort-Hinweis kann dir helfen, dich an das Passwort zu erinnern, solltest du es vergessen." + }, + "reTypeMasterPass": { + "message": "Master-Passwort wiederholen" + }, + "masterPassHint": { + "message": "Master-Passwort-Hinweis (optional)" + }, + "settings": { + "message": "Einstellungen" + }, + "passwordHint": { + "message": "Passwort-Hinweis" + }, + "enterEmailToGetHint": { + "message": "Gib die E-Mail-Adresse deines Kontos ein, um den Hinweis für dein Master-Passwort zu erhalten." + }, + "getMasterPasswordHint": { + "message": "Hinweis zum Master-Passwort zusenden" + }, + "emailRequired": { + "message": "Die E-Mail-Adresse ist erforderlich." + }, + "invalidEmail": { + "message": "Ungültige E-Mail-Adresse." + }, + "masterPassRequired": { + "message": "Das Master-Passwort ist erforderlich." + }, + "masterPassLength": { + "message": "Das Master-Passwort muss mindestens 8 Zeichen lang sein." + }, + "masterPassDoesntMatch": { + "message": "Die Passwortbestätigung stimmt nicht mit dem Passwort überein." + }, + "newAccountCreated": { + "message": "Dein neues Konto wurde erstellt! Du kannst dich jetzt anmelden." + }, + "masterPassSent": { + "message": "Wir haben dir eine E-Mail mit dem Master-Passwort-Hinweis gesendet." + }, + "unexpectedError": { + "message": "Ein unerwarteter Fehler ist aufgetreten." + }, + "itemInformation": { + "message": "Eintrags-Information" + }, + "noItemsInList": { + "message": "Keine Einträge vorhanden." + }, + "sendVerificationCode": { + "message": "Einen Bestätigungscode an deine E-Mail senden" + }, + "sendCode": { + "message": "Code senden" + }, + "codeSent": { + "message": "Code gesendet" + }, + "verificationCode": { + "message": "Verifizierungscode" + }, + "confirmIdentity": { + "message": "Bestätige deine Identität, um fortzufahren." + }, + "verificationCodeRequired": { + "message": "Verifizierungscode wird benötigt." + }, + "invalidVerificationCode": { + "message": "Ungültiger Verifizierungscode" + }, + "continue": { + "message": "Weiter" + }, + "enterVerificationCodeApp": { + "message": "Gib den 6-stelligen Verifizierungscode aus deiner Authentifizierungs-App ein." + }, + "enterVerificationCodeEmail": { + "message": "Gib den 6-stelligen Bestätigungscode ein, der an $EMAIL$ gesendet wurde.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verifizierungsmail wurde an $EMAIL$ gesendet.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Eingeloggt bleiben" + }, + "sendVerificationCodeEmailAgain": { + "message": "E-Mail mit Bestätigungscode erneut versenden" + }, + "useAnotherTwoStepMethod": { + "message": "Eine andere Zwei-Faktor-Login-Methode verwenden" + }, + "insertYubiKey": { + "message": "Stecke deinen YubiKey in einen USB-Anschluss deines Computers, dann berühre den Button." + }, + "insertU2f": { + "message": "Stecke deinen Sicherheitsschlüssel in einen USB-Anschluss deines Computers. Falls er einen Knopf hat, drücke diesen." + }, + "recoveryCodeDesc": { + "message": "Zugang zu allen Zwei-Faktor-Anbietern verloren? Benutze deinen Wiederherstellungscode, um alle Zwei-Faktor-Anbieter in deinem Konto zu deaktivieren." + }, + "recoveryCodeTitle": { + "message": "Wiederherstellungscode" + }, + "authenticatorAppTitle": { + "message": "Authentifizierungs-App" + }, + "authenticatorAppDesc": { + "message": "Verwende eine Authentifizierungs-App (wie zum Beispiel Authy oder Google Authenticator), um zeitbasierte Verifizierungscodes zu generieren.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey-OTP-Sicherheitsschlüssel" + }, + "yubiKeyDesc": { + "message": "Verwende einen YubiKey, um auf dein Konto zuzugreifen. Funktioniert mit den Geräten YubiKey 4, Nano 4, 4C und NEO." + }, + "duoDesc": { + "message": "Verifiziere mit Duo Security, indem du die Duo-Mobile-App, SMS, Anrufe oder U2F-Sicherheitsschlüssel benutzt.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Nutze Duo Security, um dich mit der Duo-Mobile-App, SMS, per Anruf oder U2F-Sicherheitsschlüssel bei deiner Organisation zu verifizieren.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Benutze einen WebAuthn-kompatiblen Sicherheitsschlüssel um auf dein Konto zuzugreifen." + }, + "emailTitle": { + "message": "E-Mail" + }, + "emailDesc": { + "message": "Bestätigungscodes werden dir per E-Mail zugesandt." + }, + "loginUnavailable": { + "message": "Login nicht verfügbar" + }, + "noTwoStepProviders": { + "message": "Dieses Konto hat eine aktive Zwei-Faktor-Authentifizierung, allerdings wird keiner der konfigurierten Zwei-Faktor-Anbieter von diesem Gerät unterstützt." + }, + "noTwoStepProviders2": { + "message": "Bitte wähle zusätzliche Dienste, die über mehrere Geräte funktionieren (zum Beispiel eine Authentifizierungs-App)." + }, + "twoStepOptions": { + "message": "Optionen für Zwei-Faktor-Authentifizierung" + }, + "selfHostedEnvironment": { + "message": "Selbstgehostete Anwendung" + }, + "selfHostedEnvironmentFooter": { + "message": "Bitte gib die Basis-URL deiner selbst gehosteten Bitwarden-Installation an." + }, + "customEnvironment": { + "message": "Benutzerdefinierte Umgebung" + }, + "customEnvironmentFooter": { + "message": "Für fortgeschrittene Benutzer. Du kannst die Basis-URL der jeweiligen Dienste unabhängig voneinander festlegen." + }, + "baseUrl": { + "message": "Server-URL" + }, + "apiUrl": { + "message": "API-Server-URL" + }, + "webVaultUrl": { + "message": "Web-Tresor-Server-URL" + }, + "identityUrl": { + "message": "Identitätsserver-URL" + }, + "notificationsUrl": { + "message": "URL des Benachrichtigungsservers" + }, + "iconsUrl": { + "message": "Icons-Server-URL" + }, + "environmentSaved": { + "message": "Die URLs der Umgebung wurden gespeichert." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nein" + }, + "overwritePassword": { + "message": "Passwort ersetzen" + }, + "learnMore": { + "message": "Mehr erfahren" + }, + "featureUnavailable": { + "message": "Funktion nicht verfügbar" + }, + "loggedOut": { + "message": "Abgemeldet" + }, + "loginExpired": { + "message": "Deine Sitzung ist abgelaufen." + }, + "logOutConfirmation": { + "message": "Bist du sicher, dass du dich abmelden willst?" + }, + "logOut": { + "message": "Abmelden" + }, + "addNewLogin": { + "message": "Login hinzufügen" + }, + "addNewItem": { + "message": "Neuen Eintrag hinzufügen" + }, + "addNewFolder": { + "message": "Neuen Ordner hinzufügen" + }, + "view": { + "message": "Ansicht" + }, + "account": { + "message": "Konto" + }, + "loading": { + "message": "Lade …" + }, + "lockVault": { + "message": "Tresor sperren" + }, + "passwordGenerator": { + "message": "Passwort-Generator" + }, + "contactUs": { + "message": "Kontakt" + }, + "getHelp": { + "message": "Hilfe erhalten" + }, + "fileBugReport": { + "message": "Einen Fehler melden" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Folge uns" + }, + "syncVault": { + "message": "Tresor jetzt synchronisieren" + }, + "changeMasterPass": { + "message": "Master-Passwort ändern" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kannst dein Master-Passwort im bitwarden.com-Web-Tresor ändern. Möchtest du die Seite jetzt öffnen?" + }, + "fingerprintPhrase": { + "message": "Prüfschlüssel", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Prüfschlüssel für deinen Account", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Web-Tresor öffnen" + }, + "getMobileApp": { + "message": "Hole dir die mobile App" + }, + "getBrowserExtension": { + "message": "Browser-Erweiterung installieren" + }, + "syncingComplete": { + "message": "Synchronisierung abgeschlossen" + }, + "syncingFailed": { + "message": "Synchronisierung fehlgeschlagen" + }, + "yourVaultIsLocked": { + "message": "Ihr Tresor ist gesperrt. Überprüfen Sie Ihr Master-Passwort, um fortzufahren." + }, + "unlock": { + "message": "Entsperren" + }, + "loggedInAsOn": { + "message": "Eingeloggt als $EMAIL$ auf $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ungültiges Master-Passwort" + }, + "twoStepLoginConfirmation": { + "message": "Mit Zwei-Faktor-Authentifizierung wird dein Account zusätzlich abgesichert, da jede Anmeldung durch einen Sicherheitscode, eine Authentifizierungs-App, SMS, einen Anruf oder eine E-Mail verifiziert werden muss. Zwei-Faktor-Authentifizierung kann im bitwarden.com-Web-Tresor aktiviert werden. Möchtest du die Seite jetzt öffnen?" + }, + "twoStepLogin": { + "message": "Zwei-Faktor-Authentifizierung" + }, + "vaultTimeout": { + "message": "Tresor-Timeout" + }, + "vaultTimeoutDesc": { + "message": "Wähle, wann der Timeout deines Tresors aktiviert werden soll und welche Aktion er bewirken soll." + }, + "immediately": { + "message": "Sofort" + }, + "tenSeconds": { + "message": "10 Sekunden" + }, + "twentySeconds": { + "message": "20 Sekunden" + }, + "thirtySeconds": { + "message": "30 Sekunden" + }, + "oneMinute": { + "message": "1 Minute" + }, + "twoMinutes": { + "message": "2 Minuten" + }, + "fiveMinutes": { + "message": "5 Minuten" + }, + "fifteenMinutes": { + "message": "15 Minuten" + }, + "thirtyMinutes": { + "message": "30 Minuten" + }, + "oneHour": { + "message": "1 Stunde" + }, + "fourHours": { + "message": "4 Stunden" + }, + "onIdle": { + "message": "Im Leerlauf" + }, + "onSleep": { + "message": "Im Standby" + }, + "onLocked": { + "message": "Wenn System gesperrt" + }, + "onRestart": { + "message": "Bei Neustart" + }, + "never": { + "message": "Niemals" + }, + "security": { + "message": "Sicherheit" + }, + "clearClipboard": { + "message": "Zwischenablage leeren", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Kopierten Inhalt automatisch aus der Zwischenablage löschen.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Website-Icons deaktivieren" + }, + "disableFaviconDesc": { + "message": "Website-Icons zeigen ein wiedererkennbares Bild neben jedem Login in deinem Tresor." + }, + "enableMinToTray": { + "message": "Minimieren und in der Taskleiste anzeigen" + }, + "enableMinToTrayDesc": { + "message": "Zeige ein Symbol in der Taskleiste, wenn das Fenster minimiert wird." + }, + "enableMinToMenuBar": { + "message": "In Menüleiste minimieren" + }, + "enableMinToMenuBarDesc": { + "message": "Bei minimiertem Fenster stattdessen ein Symbol in der Menüleiste anzeigen." + }, + "enableCloseToTray": { + "message": "In Taskleiste minimieren" + }, + "enableCloseToTrayDesc": { + "message": "Zeige ein Symbol in der Taskleiste, wenn das Fenster geschlossen wird." + }, + "enableCloseToMenuBar": { + "message": "In Menüleiste schließen" + }, + "enableCloseToMenuBarDesc": { + "message": "Beim Schließen des Fensters stattdessen ein Symbol in der Menüleiste anzeigen." + }, + "enableTray": { + "message": "Taskleisten-Symbol einschalten" + }, + "enableTrayDesc": { + "message": "Dauerhaft ein Symbol in der Taskleiste anzeigen." + }, + "startToTray": { + "message": "Minimiert in Taskleiste starten" + }, + "startToTrayDesc": { + "message": "Beim ersten Start der Anwendung nur minimiert in der Taskleiste anzeigen." + }, + "startToMenuBar": { + "message": "In der Menüleiste starten" + }, + "startToMenuBarDesc": { + "message": "Beim ersten Start der Anwendung nur ein Symbol in der Menüleiste anzeigen." + }, + "openAtLogin": { + "message": "Automatisch bei der Anmeldung starten" + }, + "openAtLoginDesc": { + "message": "Die Bitwarden Desktop-Anwendung automatisch bei der Anmeldung starten." + }, + "alwaysShowDock": { + "message": "Immer im Dock anzeigen" + }, + "alwaysShowDockDesc": { + "message": "Das Bitwarden-Symbol im Dock anzeigen, auch wenn es in die Menüleiste minimiert wird." + }, + "confirmTrayTitle": { + "message": "Tray deaktivieren bestätigen" + }, + "confirmTrayDesc": { + "message": "Das Deaktivieren dieser Einstellung wird auch alle anderen Taskleisten-Einstellungen deaktivieren." + }, + "language": { + "message": "Sprache" + }, + "languageDesc": { + "message": "Ändere die Sprache der Anwendung. Ein Neustart ist erforderlich." + }, + "theme": { + "message": "Design" + }, + "themeDesc": { + "message": "Ändere das Farbschema der Anwendung." + }, + "dark": { + "message": "Dunkel", + "description": "Dark color" + }, + "light": { + "message": "Hell", + "description": "Light color" + }, + "copy": { + "message": "Kopieren", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Auf Updates prüfen" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Neu starten, um zu updaten" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ steht zur Installation bereit. Du musst Bitwarden neustarten, um die Installation abzuschließen. Möchtest du jetzt neustarten und updaten?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Aktualisierung verfügbar" + }, + "updateAvailableDesc": { + "message": "Ein Update wurde gefunden. Möchtest du es jetzt herunterladen?" + }, + "restart": { + "message": "Neustarten" + }, + "later": { + "message": "Später" + }, + "noUpdatesAvailable": { + "message": "Derzeit gibt es keine Updates. Du verwendest die neueste Version." + }, + "updateError": { + "message": "Update-Fehler" + }, + "unknown": { + "message": "Unbekannt" + }, + "copyUsername": { + "message": "Nutzernamen kopieren" + }, + "copyNumber": { + "message": "Nummer kopieren", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Sicherheitscode kopieren", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium-Mitgliedschaft" + }, + "premiumManage": { + "message": "Mitgliedschaft verwalten" + }, + "premiumManageAlert": { + "message": "Du kannst deine Mitgliedschaft im bitwarden.com Webtresor verwalten. Möchtest du die Seite jetzt aufrufen?" + }, + "premiumRefresh": { + "message": "Mitgliedschaft erneuern" + }, + "premiumNotCurrentMember": { + "message": "Du hast derzeit keine Premium-Mitgliedschaft." + }, + "premiumSignUpAndGet": { + "message": "Werde Premium-Mitglied und erhalte dafür:" + }, + "premiumSignUpStorage": { + "message": "1 GB verschlüsselter Speicherplatz für Dateianhänge." + }, + "premiumSignUpTwoStep": { + "message": "Zusätzliche Zwei-Faktor-Anmeldung über YubiKey, FIDO U2F, und Duo." + }, + "premiumSignUpReports": { + "message": "Berichte über Kennworthygiene, Kontostatus und Datenschutzverletzungen, um Ihren Tresor sicher zu halten." + }, + "premiumSignUpTotp": { + "message": "TOTP Prüfcode (2FA) Generator für Anmeldungen in deinem Tresor." + }, + "premiumSignUpSupport": { + "message": "Vorrangiger Kunden-Support." + }, + "premiumSignUpFuture": { + "message": "Alle zukünftigen Premium-Features. Mehr in Kürze!" + }, + "premiumPurchase": { + "message": "Premium-Mitgliedschaft kaufen" + }, + "premiumPurchaseAlert": { + "message": "Du kannst deine Premium-Mitgliedschaft im bitwarden.com Web-Tresor kaufen. Möchtest du die Webseite jetzt besuchen?" + }, + "premiumCurrentMember": { + "message": "Du bist ein Premium-Mitglied!" + }, + "premiumCurrentMemberThanks": { + "message": "Vielen Dank, dass du Bitwarden unterstützt." + }, + "premiumPrice": { + "message": "Das alles für $PRICE$ pro Jahr!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Aktualisierung abgeschlossen" + }, + "passwordHistory": { + "message": "Kennwort-Historie" + }, + "clear": { + "message": "Leeren", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Keine Einträge zum Anzeigen vorhanden." + }, + "undo": { + "message": "Rückgängig" + }, + "redo": { + "message": "Wiederherstellen" + }, + "cut": { + "message": "Ausschneiden", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Einfügen", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Alles auswählen" + }, + "zoomIn": { + "message": "Vergrößern" + }, + "zoomOut": { + "message": "Verkleinern" + }, + "resetZoom": { + "message": "Zoom zurücksetzen" + }, + "toggleFullScreen": { + "message": "Vollbildmodus umschalten" + }, + "reload": { + "message": "Neu laden" + }, + "toggleDevTools": { + "message": "Entwickler-Werkzeuge ein/aus" + }, + "minimize": { + "message": "Minimieren", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoomen" + }, + "bringAllToFront": { + "message": "Alle in den Vordergrund", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Über Bitwarden" + }, + "services": { + "message": "Dienste" + }, + "hideBitwarden": { + "message": "Bitwarden ausblenden" + }, + "hideOthers": { + "message": "Andere ausblenden" + }, + "showAll": { + "message": "Alles anzeigen" + }, + "quitBitwarden": { + "message": "Bitwarden beenden" + }, + "valueCopied": { + "message": "$VALUE$ kopiert", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Hilfe" + }, + "window": { + "message": "Fenster" + }, + "checkPassword": { + "message": "Überprüfe ob dein Kennwort kompromittiert ist." + }, + "passwordExposed": { + "message": "Dieses Kennwort wurde $VALUE$ in öffentlichen Passwortdatenbanken gefunden. Du solltest es ändern.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Dieses Kennwort wurde in keinen bekannten Datensätzen gefunden. Es sollte sicher sein." + }, + "baseDomain": { + "message": "Basis-Domäne", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain-Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Server", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exakt" + }, + "startsWith": { + "message": "Beginnt mit" + }, + "regEx": { + "message": "Regulärer Ausdruck", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match-Erkennung", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standard-Match-Erkennung", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Umschaltoptionen" + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Standard" + }, + "exit": { + "message": "Beenden" + }, + "showHide": { + "message": "Zeigen / Verbergen", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Nur in der Taskleiste anzeigen" + }, + "alwaysOnTop": { + "message": "Immer im Vordergrund", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Aktualisiert", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Passwort aktualisiert", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Tresor exportieren" + }, + "fileFormat": { + "message": "Dateiformat" + }, + "warning": { + "message": "WARNUNG", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Tresor-Export bestätigen" + }, + "exportWarningDesc": { + "message": "Dieser Export enthält deine Tresordaten in einem unverschlüsseltem Format. Du solltest sie nicht speichern oder über unsichere Kanäle (z. B. E-Mail) senden. Lösche sie sofort nach ihrer Verwendung." + }, + "encExportKeyWarningDesc": { + "message": "Dieser Export verschlüsselt deine Daten mit dem Verschlüsselungscode deines Kontos. Falls du deinen Verschlüsselungscode erneuerst, solltest du den Export erneut durchführen, da du die zuvor erstellte Datei ansonsten nicht mehr entschlüsseln kannst." + }, + "encExportAccountWarningDesc": { + "message": "Die Verschlüsselungscodes eines Kontos sind für jedes Bitwarden-Benutzerkonto einzigartig, deshalb kannst du keinen verschlüsselten Export in ein anderes Konto importieren." + }, + "noOrganizationsList": { + "message": "Du bist kein Mitglied einer Organisation. Organisationen erlauben es dir Passwörter sicher mit anderen Nutzern zu teilen." + }, + "noCollectionsInList": { + "message": "Keine Sammlungen vorhanden." + }, + "ownership": { + "message": "Besitzer" + }, + "whoOwnsThisItem": { + "message": "Wem gehört dieser Eintrag?" + }, + "strong": { + "message": "Stark", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Gut", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Schwach", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Schwaches Master-Passwort" + }, + "weakMasterPasswordDesc": { + "message": "Das Master-Passwort, das du gewählt hast, ist schwach. Du solltest ein starkes Master-Passwort (oder eine Passphrase) auswählen, um dein Bitwarden-Konto richtig zu schützen. Bist du sicher, dass du dieses Master-Passwort verwenden willst?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Mit PIN-Code entsperren" + }, + "setYourPinCode": { + "message": "Gebe deinen PIN-Code für das Entsperren von Bitwarden ein. Deine PIN-Einstellungen werden zurückgesetzt, wenn du dich vollständig von der Anwendung abmeldest." + }, + "pinRequired": { + "message": "PIN-Code ist erforderlich." + }, + "invalidPin": { + "message": "Ungültiger PIN-Code." + }, + "unlockWithWindowsHello": { + "message": "Mit Windows Hello entsperren" + }, + "windowsHelloConsentMessage": { + "message": "Für Bitwarden verifizieren." + }, + "unlockWithTouchId": { + "message": "Mit Touch ID entsperren" + }, + "touchIdConsentMessage": { + "message": "Deinen Tresor entsperren" + }, + "noAutoPromptWindowsHello": { + "message": "Beim Start nicht nach Windows Hello fragen." + }, + "noAutoPromptTouchId": { + "message": "Beim Start nicht nach Touch ID fragen." + }, + "lockWithMasterPassOnRestart": { + "message": "Beim Neustart mit Master-Passwort sperren" + }, + "preferences": { + "message": "Einstellungen" + }, + "enableMenuBar": { + "message": "Menüleisten-Symbol aktivieren" + }, + "enableMenuBarDesc": { + "message": "Immer ein Symbol in der Menüleiste anzeigen." + }, + "hideToMenuBar": { + "message": "In Menüleiste ausblenden" + }, + "selectOneCollection": { + "message": "Du musst mindestens eine Sammlung auswählen." + }, + "premiumUpdated": { + "message": "Du hast ein Premium-Abo aktiviert." + }, + "restore": { + "message": "Wiederherstellen" + }, + "premiumManageAlertAppStore": { + "message": "Du kannst dein Abonnement über den App Store verwalten. Willst du jetzt den App Store öffnen?" + }, + "legal": { + "message": "Rechtliches", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Nutzungsbedingungen" + }, + "privacyPolicy": { + "message": "Datenschutzbestimmungen" + }, + "unsavedChangesConfirmation": { + "message": "Willst du wirklich aufhören? Wenn du jetzt aufhörst, werden deine aktuellen Eingaben nicht gespeichert." + }, + "unsavedChangesTitle": { + "message": "Nicht gespeicherte Änderungen" + }, + "clone": { + "message": "Duplizieren" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Eine oder mehrere Organisationsrichtlinien beeinflussen deine Generator-Einstellungen." + }, + "vaultTimeoutAction": { + "message": "Aktion bei Tresor-Timeout" + }, + "vaultTimeoutActionLockDesc": { + "message": "Ein gesperrter Tresor erfordert die erneute Eingabe des Master-Passworts, um abermals darauf zugreifen zu können." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Ein ausgeloggter Tresor erfordert eine Neu-Authentifizierung, um erneut darauf zugreifen zu können." + }, + "lock": { + "message": "Sperren", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papierkorb", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Papierkorb durchsuchen" + }, + "permanentlyDeleteItem": { + "message": "Eintrag dauerhaft löschen" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Soll dieser Eintrag wirklich dauerhaft gelöscht werden?" + }, + "permanentlyDeletedItem": { + "message": "Eintrag dauerhaft gelöscht" + }, + "restoreItem": { + "message": "Eintrag wiederherstellen" + }, + "restoreItemConfirmation": { + "message": "Soll dieser Eintrag wirklich wiederhergestellt werden?" + }, + "restoredItem": { + "message": "Eintrag wiederhergestellt" + }, + "permanentlyDelete": { + "message": "Dauerhaft löschen" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Nach dem Ausloggen verlierest du jeglichen Zugriff auf deinen Tresor und es ist nach Ablauf der Timeout-Zeit eine Online-Authentifizierung erforderlich. Bist du sicher, dass du diese Einstellung nutzen möchtest?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bestätigung der Timeout-Aktion" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Masterpasswort festlegen" + }, + "ssoCompleteRegistration": { + "message": "Bitte lege ein Masterpasswort für den Schutz deines Tresors fest, um die Anmeldung über SSO abzuschließen." + }, + "newMasterPass": { + "message": "Neues Master-Passwort" + }, + "confirmNewMasterPass": { + "message": "Neues Master-Passwort bestätigen" + }, + "masterPasswordPolicyInEffect": { + "message": "Eine oder mehrere Organisationsrichtlinien erfordern, dass dein Masterpasswort die folgenden Anforderungen erfüllt:" + }, + "policyInEffectMinComplexity": { + "message": "Kleinster Komplexitätsgrad von $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Mindestlänge von $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Enthält einen oder mehrere Großbuchstaben" + }, + "policyInEffectLowercase": { + "message": "Enthält einen oder mehrere Kleinbuchstaben" + }, + "policyInEffectNumbers": { + "message": "Enthält eine oder mehrere Zahlen" + }, + "policyInEffectSpecial": { + "message": "Enthält eines oder mehrere der folgenden Sonderzeichen $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Dein neues Masterpasswort entspricht nicht den Anforderungen der Richtlinie." + }, + "acceptPolicies": { + "message": "Durch Anwählen dieses Kästchens erklärst du dich mit folgendem einverstanden:" + }, + "acceptPoliciesError": { + "message": "Die Nutzungsbedingungen und die Datenschutzerklärung wurden nicht akzeptiert." + }, + "enableBrowserIntegration": { + "message": "Browser-Integration aktivieren" + }, + "enableBrowserIntegrationDesc": { + "message": "Die Browser-Integration wird für Biometrie im Browser verwendet." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser-Integration wird nicht unterstützt" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Leider wird die Browser-Integration derzeit nur in der Mac App Store Version unterstützt." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser-Integration wird nicht unterstützt" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Leider wird die Browser-Integration derzeit nicht in der Windows Store Version unterstützt." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Überprüfung für Browser-Integration verlangen" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Eine zusätzliche Sicherheitsebene aktivieren, indem eine Prüfschlüssel-Validierung verlangt wird, wenn eine Verbindung zwischen deiner Desktop-Anwendung und dem Browser aufgebaut wird. Nach Aktivierung ist bei jedem Verbindungsaufbau ein Benutzer-Eingriff erforderlich." + }, + "approve": { + "message": "Genehmigen" + }, + "verifyBrowserTitle": { + "message": "Browser Verbindung bestätigen" + }, + "verifyBrowserDesc": { + "message": "Bitte stelle sicher, dass der angezeigte Prüfschlüssel identisch mit dem Prüfschlüssel in der Browser-Erweiterung ist." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrie ist nicht aktiviert" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrie im Browser setzt voraus, dass Biometrie zuerst in den Einstellungen der Desktop-Anwendung aktiviert ist." + }, + "personalOwnershipSubmitError": { + "message": "Aufgrund einer Unternehmensrichtlinie darfst du keine Einträge in deinem persönlichen Tresor speichern. Ändere die Eigentümer-Option in eine Organisation und wähle aus den verfügbaren Sammlungen." + }, + "hintEqualsPassword": { + "message": "Dein Passwort-Hinweis darf nicht identisch mit deinem Passwort sein." + }, + "personalOwnershipPolicyInEffect": { + "message": "Eine Organisationsrichtlinie beeinflusst deine Eigentümer-Optionen." + }, + "allSends": { + "message": "Alle Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Datei" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Sends suchen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send bearbeiten", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mein Tresor" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Löschdatum" + }, + "deletionDateDesc": { + "message": "Das Send wird am angegebenen Datum zur angegebenen Uhrzeit dauerhaft gelöscht.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Ablaufdatum" + }, + "expirationDateDesc": { + "message": "Wenn aktiviert, verfällt der Zugriff auf dieses Send am angegebenen Datum zur angegebenen Uhrzeit.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximale Zugriffsanzahl" + }, + "maxAccessCountDesc": { + "message": "Falls aktiviert, können Benutzer nicht mehr auf dieses Send zugreifen, sobald die maximale Zugriffsanzahl erreicht ist.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Aktuelle Zugriffsanzahl" + }, + "disableSend": { + "message": "Dieses Send deaktivieren, damit niemand darauf zugreifen kann.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optional ein Passwort verlangen, damit Benutzer auf dieses Send zugreifen können.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private Notizen zu diesem Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send-Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Beim Zugriff auf dieses Send den Text standardmäßig ausblenden", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send erstellt", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send bearbeitet", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Gelöschtes Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Neues Passwort" + }, + "whatTypeOfSend": { + "message": "Welche Art von Send ist das?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Send erstellen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Der Text, den du senden möchtest." + }, + "sendFileDesc": { + "message": "Die Datei, die du senden möchtest." + }, + "days": { + "message": "$DAYS$ Tage", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 Tag" + }, + "custom": { + "message": "Benutzerdefiniert" + }, + "deleteSendConfirmation": { + "message": "Bist du sicher, dass du dieses Send löschen möchtest?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Send-Link in Zwischenablage kopieren", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Den Link zum Teilen dieses Sends beim Speichern in meine Zwischenablage kopieren." + }, + "sendDisabled": { + "message": "Send deaktiviert", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Aufgrund einer Unternehmensrichtlinie kannst du nur ein bestehendes Send löschen.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Link kopieren" + }, + "disabled": { + "message": "Deaktiviert" + }, + "maxAccessCountReached": { + "message": "Maximale Zugriffsanzahl erreicht" + }, + "expired": { + "message": "Abgelaufen" + }, + "pendingDeletion": { + "message": "Ausstehende Löschung" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn authentifizieren" + }, + "hideEmail": { + "message": "Meine E-Mail-Adresse vor den Empfängern ausblenden." + }, + "sendOptionsPolicyInEffect": { + "message": "Eine oder mehrere Organisationsrichtlinien beeinflussen deine Send Einstellungen." + }, + "emailVerificationRequired": { + "message": "E-Mail-Verifizierung erforderlich" + }, + "emailVerificationRequiredDesc": { + "message": "Du musst deine E-Mail verifizieren, um diese Funktion nutzen zu können." + }, + "passwordPrompt": { + "message": "Master-Passwort erneut abfragen" + }, + "passwordConfirmation": { + "message": "Master-Passwort bestätigen" + }, + "passwordConfirmationDesc": { + "message": "Diese Aktion ist geschützt. Um fortzufahren, gib bitte dein Master-Passwort erneut ein, um deine Identität zu bestätigen." + }, + "updatedMasterPassword": { + "message": "Master-Passwort aktualisiert" + }, + "updateMasterPassword": { + "message": "Master-Passwort aktualisieren" + }, + "updateMasterPasswordWarning": { + "message": "Dein Master-Passwort wurde kürzlich von einem Administrator deiner Organisation geändert. Um auf den Tresor zuzugreifen, musst du es jetzt aktualisieren. Wenn Du fortfährst, wirst du aus der aktuellen Sitzung abgemeldet und eine erneute Anmeldung ist erforderlich. Aktive Sitzungen auf anderen Geräten können bis zu einer Stunde weiterhin aktiv bleiben." + }, + "hours": { + "message": "Stunden" + }, + "minutes": { + "message": "Minuten" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Deine Unternehmensrichtlinien beeinflussen dein Tresor-Timeout. Das maximal zulässige Tresor-Timeout ist $HOURS$ Stunde(n) und $MINUTES$ Minute(n)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Dein Tresor-Timeout überschreitet die von deinem Unternehmen festgelegten Beschränkungen." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatische Registrierung" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Diese Organisation hat eine Unternehmensrichtlinie, die dich automatisch für die Passwort Zurücksetzung registriert. Die Registrierung wird es Administratoren der Organisation erlauben, dein Master-Passwort zu ändern." + }, + "vaultExportDisabled": { + "message": "Tresor-Export deaktiviert" + }, + "personalVaultExportPolicyInEffect": { + "message": "Eine oder mehrere Unternehmensrichtlinien verhindern es, dass du deinen persönlichen Tresor exportieren kannst." + }, + "addAccount": { + "message": "Konto hinzufügen" + }, + "removeMasterPassword": { + "message": "Master-Passwort entfernen" + }, + "removedMasterPassword": { + "message": "Master-Passwort entfernt." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ verwendet SSO mit einem selbst gehosteten Schlüsselserver. Ein Master-Passwort ist nicht mehr erforderlich, damit sich Mitglieder dieser Organisation anmelden können.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Organisation verlassen" + }, + "leaveOrganizationConfirmation": { + "message": "Bist du sicher, dass du diese Organisation verlassen möchtest?" + }, + "leftOrganization": { + "message": "Du hast die Organisation verlassen." + }, + "ssoKeyConnectorUnavailable": { + "message": "Der Key Connector konnte nicht erreicht werden. Versuche es später erneut." + }, + "lockAllVaults": { + "message": "Alle Tresore sperren" + }, + "accountLimitReached": { + "message": "Es dürfen nicht mehr als 5 Konten gleichzeitig angemeldet sein." + }, + "accountPreferences": { + "message": "Einstellungen" + }, + "appPreferences": { + "message": "App-Einstellungen (Alle Konten)" + }, + "accountSwitcherLimitReached": { + "message": "Kontolimit erreicht. Abmelden von einem Konto, um ein anderes hinzuzufügen." + }, + "settingsTitle": { + "message": "App-Einstellungen für $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch to Other Account" + }, + "options": { + "message": "Optionen" + }, + "sessionTimeout": { + "message": "Deine Sitzung ist abgelaufen. Bitte gehe zurück und versuche dich erneut einzuloggen." + }, + "exportingPersonalVaultTitle": { + "message": "Persönlichen Tresor exportieren" + }, + "exportingPersonalVaultDescription": { + "message": "Nur die persönlichen Tresoreinträge, die mit $EMAIL$ verbunden sind, werden exportiert. Tresoreinträge der Organisation werden nicht berücksichtigt.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "Was möchtest du generieren?" + }, + "passwordType": { + "message": "Passworttyp" + }, + "regenerateUsername": { + "message": "Benutzername neu generieren" + }, + "generateUsername": { + "message": "Benutzernamen generieren" + }, + "usernameType": { + "message": "Benutzernamentyp" + }, + "plusAddressedEmail": { + "message": "Mit Plus adressierte E-Mail" + }, + "plusAddressedEmailDesc": { + "message": "Verwende die Unteradressierungsmöglichkeiten deines E-Mail-Providers." + }, + "catchallEmail": { + "message": "Catch-All E-Mail-Adresse" + }, + "catchallEmailDesc": { + "message": "Verwende den konfigurierten Catch-All-Posteingang deiner Domain." + }, + "random": { + "message": "Zufällig" + }, + "randomWord": { + "message": "Zufälliges Wort" + }, + "websiteName": { + "message": "Webseiten-Name" + }, + "service": { + "message": "Dienst" + } +} diff --git a/apps/desktop/src/locales/el/messages.json b/apps/desktop/src/locales/el/messages.json new file mode 100644 index 0000000000..0ef81c9904 --- /dev/null +++ b/apps/desktop/src/locales/el/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Φίλτρα" + }, + "allItems": { + "message": "Όλα τα στοιχεία" + }, + "favorites": { + "message": "Αγαπημένα" + }, + "types": { + "message": "Τύποι" + }, + "typeLogin": { + "message": "Είσοδος" + }, + "typeCard": { + "message": "Κάρτα" + }, + "typeIdentity": { + "message": "Ταυτότητα" + }, + "typeSecureNote": { + "message": "Ασφαλής Σημείωση" + }, + "folders": { + "message": "Φάκελοι" + }, + "collections": { + "message": "Συλλογές" + }, + "searchVault": { + "message": "Αναζήτηση στο vault" + }, + "addItem": { + "message": "Προσθήκη Στοιχείου" + }, + "shared": { + "message": "Κοινοποιήθηκε" + }, + "share": { + "message": "Κοινοποίηση" + }, + "moveToOrganization": { + "message": "Μετακίνηση στον Οργανισμό" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ μετακινήθηκε στο $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Επιλέξτε έναν οργανισμό στον οποίο θέλετε να μετακινήσετε αυτό το στοιχείο. Η μετακίνηση σε έναν οργανισμό μεταβιβάζει την ιδιοκτησία του στοιχείου σε αυτό τον οργανισμό. Δεν θα είστε πλέον ο άμεσος ιδιοκτήτης αυτού του στοιχείου μόλις το μετακινήσετε." + }, + "attachments": { + "message": "Συνημμένα" + }, + "viewItem": { + "message": "Προβολή Στοιχείου" + }, + "name": { + "message": "Όνομα" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Νέο URI" + }, + "username": { + "message": "Όνομα χρήστη" + }, + "password": { + "message": "Κωδικός" + }, + "passphrase": { + "message": "Συνθηματικό" + }, + "editItem": { + "message": "Επεξεργασία Στοιχείου" + }, + "emailAddress": { + "message": "Διεύθυνση Email" + }, + "verificationCodeTotp": { + "message": "Κωδικός Επαλήθευσης (TOTP)" + }, + "website": { + "message": "Ιστοσελίδα" + }, + "notes": { + "message": "Σημειώσεις" + }, + "customFields": { + "message": "Προσαρμοσμένα Πεδία" + }, + "launch": { + "message": "Εκκίνηση" + }, + "copyValue": { + "message": "Αντιγραφή Τιμής", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Ελαχιστοποίηση κατά την αντιγραφή στο πρόχειρο" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Ελαχιστοποίηση κατά την αντιγραφή των δεδομένων ενός στοιχείου στο πρόχειρο." + }, + "toggleVisibility": { + "message": "Εναλλαγή Ορατότητας" + }, + "toggleCollapse": { + "message": "Εναλλαγή Σύμπτυξης", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Όνομα κατόχου της κάρτας" + }, + "number": { + "message": "Αριθμός" + }, + "brand": { + "message": "Επωνυμία" + }, + "expiration": { + "message": "Λήξη" + }, + "securityCode": { + "message": "Κωδικός Ασφαλείας" + }, + "identityName": { + "message": "Όνομα Ταυτότητας" + }, + "company": { + "message": "Εταιρεία" + }, + "ssn": { + "message": "ΑΜΚΑ" + }, + "passportNumber": { + "message": "Αριθμός Διαβατηρίου" + }, + "licenseNumber": { + "message": "Αριθμός Άδειας" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Τηλέφωνο" + }, + "address": { + "message": "Διεύθυνση" + }, + "premiumRequired": { + "message": "Απαιτείται Έκδοση Premium" + }, + "premiumRequiredDesc": { + "message": "Για να χρησιμοποιήσετε αυτή τη λειτουργία, απαιτείται η έκδοση premium." + }, + "errorOccurred": { + "message": "Παρουσιάστηκε σφάλμα." + }, + "error": { + "message": "Σφάλμα" + }, + "january": { + "message": "Ιανουάριος" + }, + "february": { + "message": "Φεβρουάριος" + }, + "march": { + "message": "Μάρτιος" + }, + "april": { + "message": "Απρίλιος" + }, + "may": { + "message": "Μάιος" + }, + "june": { + "message": "Ιούνιος" + }, + "july": { + "message": "Ιούλιος" + }, + "august": { + "message": "Αύγουστος" + }, + "september": { + "message": "Σεπτέμβριος" + }, + "october": { + "message": "Οκτώβριος" + }, + "november": { + "message": "Νοέμβριος" + }, + "december": { + "message": "Δεκέμβριος" + }, + "ex": { + "message": "π.χ.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Τίτλος" + }, + "mr": { + "message": "Κος" + }, + "mrs": { + "message": "Κα" + }, + "ms": { + "message": "Κα" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Μήνας λήξης" + }, + "expirationYear": { + "message": "Έτος λήξης" + }, + "select": { + "message": "Επιλογή" + }, + "other": { + "message": "Άλλες" + }, + "generatePassword": { + "message": "Δημιουργία Κωδικού" + }, + "type": { + "message": "Τύπος" + }, + "firstName": { + "message": "Όνομα" + }, + "middleName": { + "message": "Μεσαίο Όνομα" + }, + "lastName": { + "message": "Επώνυμο" + }, + "fullName": { + "message": "Ονοματεπώνυμο" + }, + "address1": { + "message": "Διεύθυνση 1" + }, + "address2": { + "message": "Διεύθυνση 2" + }, + "address3": { + "message": "Διεύθυνση 3" + }, + "cityTown": { + "message": "Πόλη / Κωμόπολη" + }, + "stateProvince": { + "message": "Περιοχή / Νομός" + }, + "zipPostalCode": { + "message": "Ταχυδρομικός Κώδικας" + }, + "country": { + "message": "Χώρα" + }, + "save": { + "message": "Αποθήκευση" + }, + "cancel": { + "message": "Ακύρωση" + }, + "delete": { + "message": "Διαγραφή" + }, + "favorite": { + "message": "Αγαπημένο" + }, + "edit": { + "message": "Επεξεργασία" + }, + "authenticatorKeyTotp": { + "message": "Κλειδί επαλήθευσης (TOTP)" + }, + "folder": { + "message": "Φάκελος" + }, + "newCustomField": { + "message": "Νέο Προσαρμοσμένο Πεδίο" + }, + "value": { + "message": "Τιμή" + }, + "dragToSort": { + "message": "Σύρετε για ταξινόμηση" + }, + "cfTypeText": { + "message": "Κείμενο" + }, + "cfTypeHidden": { + "message": "Κρυφό" + }, + "cfTypeBoolean": { + "message": "Δυαδικό" + }, + "cfTypeLinked": { + "message": "Συνδεδεμένο", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Συνδεδεμένη τιμή", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Αφαίρεση" + }, + "nameRequired": { + "message": "Απαιτείται όνομα." + }, + "addedItem": { + "message": "Προστέθηκε στοιχείο" + }, + "editedItem": { + "message": "Επεξεργασμένο στοιχείο" + }, + "deleteItem": { + "message": "Διαγραφή Στοιχείου" + }, + "deleteFolder": { + "message": "Διαγραφή Φακέλου" + }, + "deleteAttachment": { + "message": "Διαγραφή Συνημμένου" + }, + "deleteItemConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το στοιχείο;" + }, + "deletedItem": { + "message": "Διαγραμμένο στοιχείο" + }, + "overwritePasswordConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να αντικαταστήσετε τον τρέχον κωδικό πρόσβασης;" + }, + "overwriteUsername": { + "message": "Αντικατάσταση Username" + }, + "overwriteUsernameConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να αντικαταστήσετε το τρέχον username;" + }, + "noneFolder": { + "message": "Χωρίς Φάκελο", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Προσθήκη Φακέλου" + }, + "editFolder": { + "message": "Επεξεργασία Φακέλου" + }, + "regeneratePassword": { + "message": "Επαναδημιουργία Κωδικού" + }, + "copyPassword": { + "message": "Αντιγραφή Κωδικού" + }, + "copyUri": { + "message": "Αντιγραφή URI" + }, + "copyVerificationCodeTotp": { + "message": "Αντιγραφή κωδικού επαλήθευσης (TOTP)" + }, + "length": { + "message": "Μήκος" + }, + "numWords": { + "message": "Αριθμός Λέξεων" + }, + "wordSeparator": { + "message": "Διαχωριστής Λέξεων" + }, + "capitalize": { + "message": "Κεφαλαιοποίηση", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Συμπερίληψη Αριθμών" + }, + "close": { + "message": "Κλείσιμο" + }, + "minNumbers": { + "message": "Ελάχιστα Αριθμητικά Ψηφία" + }, + "minSpecial": { + "message": "Ελάχιστο Ειδικών Χαρακτήρων", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Αποφυγή Αμφιλεγόμενων Χαρακτήρων" + }, + "searchCollection": { + "message": "Αναζήτηση στη Συλλογή" + }, + "searchFolder": { + "message": "Αναζήτηση στον Φάκελο" + }, + "searchFavorites": { + "message": "Αναζήτηση στα Αγαπημένα" + }, + "searchType": { + "message": "Τύπος Αναζήτησης", + "description": "Search item type" + }, + "newAttachment": { + "message": "Προσθήκη Νέου Συνημμένου" + }, + "deletedAttachment": { + "message": "Το συνημμένο διαγράφηκε" + }, + "deleteAttachmentConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό το συνημμένο;" + }, + "attachmentSaved": { + "message": "Το συννημένο έχει αποθηκευτεί." + }, + "file": { + "message": "Αρχείο" + }, + "selectFile": { + "message": "Επιλέξτε ένα αρχείο." + }, + "maxFileSize": { + "message": "Το μέγιστο μέγεθος αρχείου είναι 500 MB." + }, + "updateKey": { + "message": "Δεν μπορείτε να χρησιμοποιήσετε αυτήν τη λειτουργία μέχρι να ενημερώσετε το κλειδί κρυπτογράφησης." + }, + "editedFolder": { + "message": "Επεξεργασμένος φάκελος" + }, + "addedFolder": { + "message": "Προστέθηκε φάκελος" + }, + "deleteFolderConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτό τον φάκελο;" + }, + "deletedFolder": { + "message": "Διεγραμμένος φάκελος" + }, + "loginOrCreateNewAccount": { + "message": "Συνδεθείτε ή δημιουργήστε ένα νέο λογαριασμό για να αποκτήσετε πρόσβαση στο ασφαλές vault σας." + }, + "createAccount": { + "message": "Δημιουργία Λογαριασμού" + }, + "logIn": { + "message": "Είσοδος" + }, + "submit": { + "message": "Υποβολή" + }, + "masterPass": { + "message": "Κύριος Κωδικός" + }, + "masterPassDesc": { + "message": "Ο κύριος κωδικός είναι ο κωδικός που χρησιμοποιείτε για την πρόσβαση στο vault σας. Είναι πολύ σημαντικό να μην ξεχάσετε τον κύριο κωδικό. Δεν υπάρχει τρόπος να ανακτήσετε τον κωδικό σε περίπτωση που τον ξεχάσετε." + }, + "masterPassHintDesc": { + "message": "Η υπόδειξη κύριου κωδικού μπορεί να σας βοηθήσει να θυμηθείτε τον κωδικό σας αν τον ξεχάσετε." + }, + "reTypeMasterPass": { + "message": "Επαλήθευση Κύριου Κωδικού" + }, + "masterPassHint": { + "message": "Υπόδειξη Κύριου Κωδικού (προαιρετικό)" + }, + "settings": { + "message": "Ρυθμίσεις" + }, + "passwordHint": { + "message": "Υπόδειξη Κωδικού" + }, + "enterEmailToGetHint": { + "message": "Εισαγάγετε τη διεύθυνση email του λογαριασμού σας για να λάβετε την υπόδειξη του κύριου κωδικού." + }, + "getMasterPasswordHint": { + "message": "Λήψη υπόδειξης κύριου κωδικού" + }, + "emailRequired": { + "message": "Απαιτείται διεύθυνση e-mail." + }, + "invalidEmail": { + "message": "Μη έγκυρη διεύθυνση e-mail." + }, + "masterPassRequired": { + "message": "Απαιτείται κύριος κωδικός πρόσβασης." + }, + "masterPassLength": { + "message": "Ο κύριος κωδικός πρέπει να έχει μήκος τουλάχιστον 8 χαρακτήρες." + }, + "masterPassDoesntMatch": { + "message": "Η επιβεβαίωση κύριου κωδικού δεν ταιριάζει." + }, + "newAccountCreated": { + "message": "Ο λογαριασμός σας έχει δημιουργηθεί! Τώρα μπορείτε να συνδεθείτε." + }, + "masterPassSent": { + "message": "Σας στείλαμε ένα email με την υπόδειξη του κύριου κωδικού." + }, + "unexpectedError": { + "message": "Παρουσιάστηκε ένα μη αναμενόμενο σφάλμα." + }, + "itemInformation": { + "message": "Πληροφορίες Στοιχείου" + }, + "noItemsInList": { + "message": "Δεν υπάρχουν στοιχεία στη λίστα." + }, + "sendVerificationCode": { + "message": "Στείλτε έναν κωδικό επαλήθευσης στο email σας" + }, + "sendCode": { + "message": "Αποστολή Κωδικού" + }, + "codeSent": { + "message": "Ο Κωδικός Στάλθηκε" + }, + "verificationCode": { + "message": "Κωδικός Επαλήθευσης" + }, + "confirmIdentity": { + "message": "Επιβεβαιώστε την ταυτότητα σας για να συνεχίσετε." + }, + "verificationCodeRequired": { + "message": "Απαιτείται ο κωδικός επαλήθευσης." + }, + "invalidVerificationCode": { + "message": "Μη έγκυρος κωδικός επαλήθευσης" + }, + "continue": { + "message": "Συνέχεια" + }, + "enterVerificationCodeApp": { + "message": "Εισάγετε τον 6ψήφιο κωδικό από την εφαρμογή επαλήθευσης." + }, + "enterVerificationCodeEmail": { + "message": "Εισάγετε τον 6ψήφιο κωδικό επαλήθευσης τον οποίο λάβατε στο $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Εστάλη email επαλήθευσης στο $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Να με θυμάσαι" + }, + "sendVerificationCodeEmailAgain": { + "message": "Επανάληψη αποστολής κωδικού επαλήθευσης στο e-mail" + }, + "useAnotherTwoStepMethod": { + "message": "Χρήση άλλης μεθόδου εισόδου δύο παραγόντων" + }, + "insertYubiKey": { + "message": "Τοποθετήστε το YubiKey στη θύρα USB του υπολογιστή σας και έπειτα κάντε κλικ στο κουμπί του." + }, + "insertU2f": { + "message": "Εισάγετε το κλειδί ασφαλείας στη θύρα USB του υπολογιστή σας. Αν έχει κουμπί, πατήστε το." + }, + "recoveryCodeDesc": { + "message": "Έχετε χάσει την πρόσβαση σε όλους τους παρόχους δύο παραγόντων; Χρησιμοποιήστε τον κωδικό ανάκτησης για να απενεργοποιήσετε όλους τους παρόχους δύο παραγόντων από το λογαριασμό σας." + }, + "recoveryCodeTitle": { + "message": "Κωδικός Ανάκτησης" + }, + "authenticatorAppTitle": { + "message": "Εφαρμογή Επαλήθευσης" + }, + "authenticatorAppDesc": { + "message": "Χρησιμοποιήστε μια εφαρμογή επαλήθευσης (όπως το Authy ή Google Authenticator) για να δημιουργήσετε κωδικούς επαλήθευσης με βάση το χρόνο.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Κλειδί ασφαλείας YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Χρησιμοποιήστε ένα YubiKey για να αποκτήσετε πρόσβαση στο λογαριασμό σας. Λειτουργεί με συσκευές σειράς YubiKey 4, 4 Nano, 4C και συσκευές NEO." + }, + "duoDesc": { + "message": "Επαληθεύστε με το Duo Security χρησιμοποιώντας την εφαρμογή Duo Mobile, SMS, τηλεφωνική κλήση ή κλειδί ασφαλείας U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Επαληθεύστε με το Duo Security για τον οργανισμό σας χρησιμοποιώντας την εφαρμογή Duo Mobile, μήνυμα SMS, τηλεφωνική κλήση ή κλειδί ασφαλείας U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Χρησιμοποιήστε οποιοδήποτε κλειδί ασφαλείας WebAuthn για να αποκτήσετε πρόσβαση στο λογαριασμό σας." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Οι κωδικοί επαλήθευσης θα σας αποσταλούν μέσω ηλεκτρονικού ταχυδρομείου." + }, + "loginUnavailable": { + "message": "Σύνδεση μη διαθέσιμη" + }, + "noTwoStepProviders": { + "message": "Αυτός ο λογαριασμός έχει δυνατότητα σύνδεσης σε δύο βήματα, ωστόσο, από αυτήν τη συσκευή δεν υποστηρίζεται κανένας από τους διαμορφωμένους παροχείς δύο βημάτων." + }, + "noTwoStepProviders2": { + "message": "Προσθέστε επιπλέον παρόχους που υποστηρίζονται καλύτερα σε όλες τις συσκευές (όπως μια εφαρμογή επαλήθευσης)." + }, + "twoStepOptions": { + "message": "Επιλογές Σύνδεσης Δύο Παραγόντων" + }, + "selfHostedEnvironment": { + "message": "Αυτο-Φιλοξενούμενο Περιβάλλον" + }, + "selfHostedEnvironmentFooter": { + "message": "Καθορίστε τη βασική διεύθυνση URL, της εγκατάστασης του Bitwarden που φιλοξενείται στο χώρο σας." + }, + "customEnvironment": { + "message": "Προσαρμοσμένο περιβάλλον" + }, + "customEnvironmentFooter": { + "message": "Για προχωρημένους χρήστες. Μπορείτε να ορίσετε ανεξάρτητα τη βασική διεύθυνση URL κάθε υπηρεσίας." + }, + "baseUrl": { + "message": "URL Διακομιστή" + }, + "apiUrl": { + "message": "URL Διακομιστή API" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "URL Ταυτότητας Διακομιστή" + }, + "notificationsUrl": { + "message": "Ειδοποιήσεις Διεύθυνσης URL Διακομιστή" + }, + "iconsUrl": { + "message": "Εικονίδια διακομιστή URL" + }, + "environmentSaved": { + "message": "Οι διευθύνσεις URL περιβάλλοντος έχουν αποθηκευτεί." + }, + "ok": { + "message": "Οκ" + }, + "yes": { + "message": "Ναι" + }, + "no": { + "message": "Όχι" + }, + "overwritePassword": { + "message": "Αντικατάσταση Κωδικού Πρόσβασης" + }, + "learnMore": { + "message": "Μάθετε περισσότερα" + }, + "featureUnavailable": { + "message": "Μη Διαθέσιμο Χαρακτηριστικό" + }, + "loggedOut": { + "message": "Αποσύνδεση" + }, + "loginExpired": { + "message": "Η περίοδος σύνδεσης σας έχει λήξει." + }, + "logOutConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να αποσυνδεθείτε;" + }, + "logOut": { + "message": "Αποσύνδεση" + }, + "addNewLogin": { + "message": "Προσθήκη Νέας Σύνδεσης" + }, + "addNewItem": { + "message": "Προσθήκη Νέου Στοιχείου" + }, + "addNewFolder": { + "message": "Προσθήκη Νέου Φακέλου" + }, + "view": { + "message": "Προβολή" + }, + "account": { + "message": "Λογαριασμός" + }, + "loading": { + "message": "Φόρτωση..." + }, + "lockVault": { + "message": "Κλείδωμα Vault" + }, + "passwordGenerator": { + "message": "Γεννήτρια Κωδικού" + }, + "contactUs": { + "message": "Επικοινωνία" + }, + "getHelp": { + "message": "Ζητήστε Βοήθεια" + }, + "fileBugReport": { + "message": "Υποβολή Αναφοράς Σφάλματος" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Ακολουθήστε μας" + }, + "syncVault": { + "message": "Συγχρονισμός Vault" + }, + "changeMasterPass": { + "message": "Αλλαγή Κύριου Κωδικού" + }, + "changeMasterPasswordConfirmation": { + "message": "Μπορείτε να αλλάξετε τον κύριο κωδικό στο bitwarden.com. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "fingerprintPhrase": { + "message": "Φράση Δακτυλικών Αποτυπωμάτων", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Η Φράση δακτυλικών αποτυπωμάτων του λογαριασμού σας", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Πηγαίνετε στο Web Vault" + }, + "getMobileApp": { + "message": "Λάβετε την Εφαρμογή Κινητού" + }, + "getBrowserExtension": { + "message": "Λάβετε την Επέκταση Browser" + }, + "syncingComplete": { + "message": "Ο συγχρονισμός ολοκληρώθηκε" + }, + "syncingFailed": { + "message": "Ο συγχρονισμός απέτυχε" + }, + "yourVaultIsLocked": { + "message": "Το vault σας είναι κλειδωμένο. Επαληθεύστε τον κύριο κωδικό πρόσβασης για να συνεχίσετε." + }, + "unlock": { + "message": "Ξεκλείδωμα" + }, + "loggedInAsOn": { + "message": "Συνδεθήκατε ως $EMAIL$ στο $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Μη έγκυρος κύριος κωδικός πρόσβασης" + }, + "twoStepLoginConfirmation": { + "message": "Η σύνδεση σε δύο βήματα καθιστά ασφαλέστερο τον λογαριασμό σας, απαιτώντας να επαληθεύσετε τα στοιχεία σας με μια άλλη συσκευή, όπως κλειδί ασφαλείας, εφαρμογή επαλήθευσης ταυτότητας, μήνυμα SMS, τηλεφωνική κλήση ή email. Μπορείτε να ενεργοποιήσετε τη σύνδεση σε δύο βήματα στο bitwarden.com. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "twoStepLogin": { + "message": "Σύνδεση σε δύο βήματα" + }, + "vaultTimeout": { + "message": "Χρόνος Λήξης Vault" + }, + "vaultTimeoutDesc": { + "message": "Επιλέξτε πότε θα λήξει το vault και πραγματοποιήστε την επιλεγμένη ενέργεια." + }, + "immediately": { + "message": "Άμεσα" + }, + "tenSeconds": { + "message": "10 δευτερόλεπτα" + }, + "twentySeconds": { + "message": "20 δευτερόλεπτα" + }, + "thirtySeconds": { + "message": "30 δευτερόλεπτα" + }, + "oneMinute": { + "message": "1 λεπτό" + }, + "twoMinutes": { + "message": "2 λεπτά" + }, + "fiveMinutes": { + "message": "5 λεπτά" + }, + "fifteenMinutes": { + "message": "15 λεπτά" + }, + "thirtyMinutes": { + "message": "30 λεπτά" + }, + "oneHour": { + "message": "1 ώρα" + }, + "fourHours": { + "message": "4 ώρες" + }, + "onIdle": { + "message": "Κατά την Αδράνεια Συστήματος" + }, + "onSleep": { + "message": "Κατά την Αναμονή Συστήματος" + }, + "onLocked": { + "message": "Κατά το Κλείδωμα Συστήματος" + }, + "onRestart": { + "message": "Κατά την Επανεκκίνηση" + }, + "never": { + "message": "Ποτέ" + }, + "security": { + "message": "Ασφάλεια" + }, + "clearClipboard": { + "message": "Εκκαθάριση Πρόχειρου", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Αυτόματη εκκαθάριση αντιγραμμένων τιμών προχείρου.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Απενεργοποίηση Εικονιδίων Ιστοσελίδας" + }, + "disableFaviconDesc": { + "message": "Τα εικονίδια ιστοσελίδων παρέχουν μια αναγνωρίσιμη εικόνα δίπλα σε κάθε στοιχείο σύνδεσης της λίστας σας." + }, + "enableMinToTray": { + "message": "Ελαχιστοποίηση σε Εικονίδιο Δίσκου" + }, + "enableMinToTrayDesc": { + "message": "Όταν ελαχιστοποιείτε το παράθυρο, εμφανίζεται ένα εικονίδιο στο δίσκο συστήματος αντί αυτού." + }, + "enableMinToMenuBar": { + "message": "Ελαχιστοποίηση στη γραμμή μενού" + }, + "enableMinToMenuBarDesc": { + "message": "Όταν ελαχιστοποιείται το παράθυρο, εμφανίζεται ένα εικονίδιο στη γραμμή μενού." + }, + "enableCloseToTray": { + "message": "Κλείσιμο στο Εικονίδιο Δίσκου" + }, + "enableCloseToTrayDesc": { + "message": "Όταν κλείνετε το παράθυρο, εμφανίζεται ένα εικονίδιο στο δίσκο συστήματος αντί αυτού." + }, + "enableCloseToMenuBar": { + "message": "Κλείσιμο στη γραμμή μενού" + }, + "enableCloseToMenuBarDesc": { + "message": "Κατά το κλείσιμο του παραθύρου, εμφανίζεται ένα εικονίδιο στη γραμμή μενού." + }, + "enableTray": { + "message": "Ενεργοποίηση Εικονιδίου Δίσκου" + }, + "enableTrayDesc": { + "message": "Να εμφανίζεται πάντα ένα εικονίδιο στο δίσκο συστήματος." + }, + "startToTray": { + "message": "Έναρξη στο εικονίδιο δίσκου" + }, + "startToTrayDesc": { + "message": "Όταν ξεκινήσει η εφαρμογή, εμφανίζεται μόνο ένα εικονίδιο στο δίσκο συστήματος." + }, + "startToMenuBar": { + "message": "Έναρξη στη γραμμή μενού" + }, + "startToMenuBarDesc": { + "message": "Όταν ξεκινήσει η εφαρμογή, εμφανίζεται μόνο ένα εικονίδιο στη γραμμή μενού." + }, + "openAtLogin": { + "message": "Εκκίνηση αυτόματα κατά τη σύνδεση" + }, + "openAtLoginDesc": { + "message": "Εκκίνηση της εφαρμογής Bitwarden Desktop αυτόματα κατά τη σύνδεση." + }, + "alwaysShowDock": { + "message": "Να εμφανίζεται πάντα στο Dock" + }, + "alwaysShowDockDesc": { + "message": "Εμφάνιση του εικονιδίου Bitwarden στο Dock ακόμα και όταν ελαχιστοποιείται στη γραμμή μενού." + }, + "confirmTrayTitle": { + "message": "Επιβεβαίωση απενεργοποίησης συστήματος" + }, + "confirmTrayDesc": { + "message": "Η απενεργοποίηση αυτής της ρύθμισης θα απενεργοποιήσει επίσης όλες τις άλλες ρυθμίσεις που σχετίζονται με το δίσκο." + }, + "language": { + "message": "Γλώσσα" + }, + "languageDesc": { + "message": "Αλλάξτε τη γλώσσα που χρησιμοποιείται από την εφαρμογή. Απαιτείται επανεκκίνηση." + }, + "theme": { + "message": "Θέμα" + }, + "themeDesc": { + "message": "Αλλαγή χρώματος θέματος εφαρμογής." + }, + "dark": { + "message": "Σκοτεινό", + "description": "Dark color" + }, + "light": { + "message": "Φωτεινό", + "description": "Light color" + }, + "copy": { + "message": "Αντιγραφή", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Έλεγχος Για Ενημερώσεις" + }, + "version": { + "message": "Έκδοση $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Κάντε επανεκκίνηση για ενημέρωση" + }, + "restartToUpdateDesc": { + "message": "Η έκδοση $VERSION_NUM$ είναι έτοιμη για εγκατάσταση. Θα πρέπει να επανεκκινήσετε την εφαρμογή για να ολοκληρωθεί η εγκατάσταση. Θέλετε να κάνετε επανεκκίνηση και ενημέρωση τώρα;", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Διαθέσιμη Ενημέρωση" + }, + "updateAvailableDesc": { + "message": "Βρέθηκε μια ενημέρωση. Θέλετε να την κατεβάσετε τώρα;" + }, + "restart": { + "message": "Επανεκκίνηση" + }, + "later": { + "message": "Αργότερα" + }, + "noUpdatesAvailable": { + "message": "Δεν υπάρχουν προς το παρόν διαθέσιμες ενημερώσεις. Χρησιμοποιείτε την τελευταία έκδοση." + }, + "updateError": { + "message": "Σφάλμα Ενημέρωσης" + }, + "unknown": { + "message": "Άγνωστο" + }, + "copyUsername": { + "message": "Αντιγραφή Ονόματος Χρήστη" + }, + "copyNumber": { + "message": "Αντιγραφή Αριθμού", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Αντιγραφή Κωδικού Ασφαλείας", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Συνδρομή Premium" + }, + "premiumManage": { + "message": "Διαχείριση Συνδρομής" + }, + "premiumManageAlert": { + "message": "Μπορείτε να διαχειριστείτε την ιδιότητά σας ως μέλος στο bitwarden.com web vault. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "premiumRefresh": { + "message": "Ανανέωση Συνδρομής" + }, + "premiumNotCurrentMember": { + "message": "Δεν είστε premium μέλος." + }, + "premiumSignUpAndGet": { + "message": "Εγγραφείτε για μια premium συνδρομή και λάβετε:" + }, + "premiumSignUpStorage": { + "message": "1 GB κρυπτογραφημένο αποθηκευτικό χώρο για συνημμένα αρχεία." + }, + "premiumSignUpTwoStep": { + "message": "Πρόσθετες επιλογές σύνδεσης δύο βημάτων, όπως το YubiKey, το FIDO U2F και το Duo." + }, + "premiumSignUpReports": { + "message": "Ασφάλεια κωδικών, υγιής λογαριασμός και αναφορές παραβίασης δεδομένων για να διατηρήσετε ασφαλή τη λίστα σας." + }, + "premiumSignUpTotp": { + "message": "TOTP κωδικός επαλήθευσης (2FA) για συνδέσεις στη λίστα σας." + }, + "premiumSignUpSupport": { + "message": "Προτεραιότητα υποστήριξης πελατών." + }, + "premiumSignUpFuture": { + "message": "Όλα τα μελλοντικά χαρακτηριστικά premium. Περισσότερα σύντομα!" + }, + "premiumPurchase": { + "message": "Αγορά Premium έκδοσης" + }, + "premiumPurchaseAlert": { + "message": "Μπορείτε να αγοράσετε συνδρομή premium στο bitwarden.com web vault. Θέλετε να επισκεφθείτε την ιστοσελίδα τώρα;" + }, + "premiumCurrentMember": { + "message": "Είστε ένα premium μέλος!" + }, + "premiumCurrentMemberThanks": { + "message": "Ευχαριστούμε που υποστηρίζετε το Bitwarden." + }, + "premiumPrice": { + "message": "Όλα για μόνο $PRICE$ /έτος!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Επιτυχής ανανέωση" + }, + "passwordHistory": { + "message": "Ιστορικό Κωδικού" + }, + "clear": { + "message": "Εκκαθάριση", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Δεν υπάρχουν κωδικοί στη λίστα." + }, + "undo": { + "message": "Αναίρεση" + }, + "redo": { + "message": "Ακύρωση αναίρεσης" + }, + "cut": { + "message": "Αποκοπή", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Επικόλληση", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Επιλογή Όλων" + }, + "zoomIn": { + "message": "Μεγέθυνση" + }, + "zoomOut": { + "message": "Σμίκρυνση" + }, + "resetZoom": { + "message": "Επαναφορά Μεγέθυνσης" + }, + "toggleFullScreen": { + "message": "Εναλλαγή σε Πλήρη Οθόνη" + }, + "reload": { + "message": "Επαναφόρτωση" + }, + "toggleDevTools": { + "message": "Εναλλαγή σε Εργαλεία Προγραμματιστή" + }, + "minimize": { + "message": "Ελαχιστοποίηση", + "description": "Minimize window" + }, + "zoom": { + "message": "Μεγέθυνση" + }, + "bringAllToFront": { + "message": "Φέρτε τα όλα σε πρώτο πλάνο", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Σχετικά με Birwarden" + }, + "services": { + "message": "Υπηρεσίες" + }, + "hideBitwarden": { + "message": "Απόκρυψη Bitwarden" + }, + "hideOthers": { + "message": "Απόκρυψη Άλλων" + }, + "showAll": { + "message": "Εμφάνιση Όλων" + }, + "quitBitwarden": { + "message": "Έξοδος Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ αντιγράφηκε", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Βοήθεια" + }, + "window": { + "message": "Παράθυρο" + }, + "checkPassword": { + "message": "Ελέγξτε εάν ο κωδικός έχει εκτεθεί." + }, + "passwordExposed": { + "message": "Αυτός ο κωδικός πρόσβασης έχει εκτεθεί $VALUE$ φορά (ές) σε παραβιάσεις δεδομένων. Πρέπει να τον αλλάξετε.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Αυτός ο κωδικός δεν βρέθηκε σε κάποια γνωστή διαρροή δεδομένων. Θα πρέπει να είναι ασφαλής για χρήση." + }, + "baseDomain": { + "message": "Βασικός τομέας", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Όνομα τομέα", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Ακριβής" + }, + "startsWith": { + "message": "Έναρξη με" + }, + "regEx": { + "message": "Κανονική έκφραση", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Εντοπισμός Αντιστοίχισης", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Προεπιλεγμένος εντοπισμός αντιστοίχισης", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Επιλογές Εναλλαγής" + }, + "organization": { + "message": "Οργανισμός", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Προεπιλογή" + }, + "exit": { + "message": "Έξοδος" + }, + "showHide": { + "message": "Εμφάνιση / Απόκρυψη", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Απόκρυψη στο Δίσκο" + }, + "alwaysOnTop": { + "message": "Πάντα στη Κορυφή", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Ενημερώθηκε", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Ο Κωδικός Ενημερώθηκε", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Εξαγωγή Vault" + }, + "fileFormat": { + "message": "Μορφή Αρχείου" + }, + "warning": { + "message": "ΠΡΟΕΙΔΟΠΟΙΗΣΗ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Επιβεβαίωση εξαγωγής Vault" + }, + "exportWarningDesc": { + "message": "Αυτή η εξαγωγή περιέχει τα δεδομένα σε μη κρυπτογραφημένη μορφή. Δεν πρέπει να αποθηκεύετε ή να στείλετε το εξαγόμενο αρχείο μέσω μη ασφαλών τρόπων (όπως μέσω email). Διαγράψτε το αμέσως μόλις τελειώσετε με τη χρήση του." + }, + "encExportKeyWarningDesc": { + "message": "Αυτή η εξαγωγή κρυπτογραφεί τα δεδομένα σας χρησιμοποιώντας το κλειδί κρυπτογράφησης του λογαριασμού σας. Εάν ποτέ περιστρέψετε το κλειδί κρυπτογράφησης του λογαριασμού σας, θα πρέπει να κάνετε εξαγωγή ξανά, καθώς δεν θα μπορείτε να αποκρυπτογραφήσετε αυτό το αρχείο εξαγωγής." + }, + "encExportAccountWarningDesc": { + "message": "Τα κλειδιά κρυπτογράφησης λογαριασμού είναι μοναδικά για κάθε λογαριασμό χρήστη Bitwarden, οπότε δεν μπορείτε να εισάγετε μια κρυπτογραφημένη εξαγωγή σε διαφορετικό λογαριασμό." + }, + "noOrganizationsList": { + "message": "Δεν συμμετέχετε σε κάποιον οργανισμό. Οι οργανισμοί επιτρέπουν την ασφαλή κοινοποίηση στοιχείων με άλλους χρήστες." + }, + "noCollectionsInList": { + "message": "Δεν υπάρχουν στοιχεία για εμφάνιση." + }, + "ownership": { + "message": "Ιδιοκτησία" + }, + "whoOwnsThisItem": { + "message": "Ποιος κατέχει αυτό το στοιχείο;" + }, + "strong": { + "message": "Ισχυρός", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Καλός", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Αδύναμος", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Αδύναμος Κύριος Κωδικός" + }, + "weakMasterPasswordDesc": { + "message": "Ο κύριος κωδικός που έχετε επιλέξει είναι αδύναμος. Θα πρέπει να χρησιμοποιήσετε έναν ισχυρό κύριο κωδικό (ή μια φράση) για την κατάλληλη προστασία του λογαριασμού Bitwarden. Είστε βέβαιοι ότι θέλετε να χρησιμοποιήσετε αυτόν τον κύριο κωδικό;" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Ξεκλείδωμα με PIN" + }, + "setYourPinCode": { + "message": "Ορίστε τον κωδικό PIN για να ξεκλειδώσετε το Bitwarden. Οι ρυθμίσεις PIN θα επαναρυθμιστούν αν αποσυνδεθείτε πλήρως από την εφαρμογή." + }, + "pinRequired": { + "message": "Απαιτείται κωδικός PIN." + }, + "invalidPin": { + "message": "Μη έγκυρος κωδικός PIN." + }, + "unlockWithWindowsHello": { + "message": "Ξεκλειδώστε με το Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Επαληθεύστε για το Bitwarden." + }, + "unlockWithTouchId": { + "message": "Ξεκλείδωμα με Touch ID" + }, + "touchIdConsentMessage": { + "message": "Ξεκλειδώστε το vault σας" + }, + "noAutoPromptWindowsHello": { + "message": "Μην προτρέξετε για τα Windows Hello κατά την εκκίνηση." + }, + "noAutoPromptTouchId": { + "message": "Να μην ζητηθεί το Touch ID κατά την εκκίνηση." + }, + "lockWithMasterPassOnRestart": { + "message": "Κλείδωμα με τον κύριο κωδικό πρόσβασης κατά την επανεκκίνηση" + }, + "preferences": { + "message": "Προτιμήσεις" + }, + "enableMenuBar": { + "message": "Ενεργοποίηση Εικονιδίου Μπάρας Μενού" + }, + "enableMenuBarDesc": { + "message": "Να εμφανίζεται πάντα το εικονίδιο στη μπάρα μενού." + }, + "hideToMenuBar": { + "message": "Απόκρυψη στη Μπάρα Μενού" + }, + "selectOneCollection": { + "message": "Πρέπει να επιλέξετε τουλάχιστον μία συλλογή." + }, + "premiumUpdated": { + "message": "Έχετε αναβαθμίσει σε premium." + }, + "restore": { + "message": "Επαναφορά" + }, + "premiumManageAlertAppStore": { + "message": "Μπορείτε να διαχειριστείτε τη συνδρομή σας από το App Store. Θέλετε να επισκεφθείτε το App Store τώρα;" + }, + "legal": { + "message": "Νομικά", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Όροι Χρήσης" + }, + "privacyPolicy": { + "message": "Πολιτική Απορρήτου" + }, + "unsavedChangesConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να φύγετε; Εάν φύγετε τώρα, οι τρέχουσες πληροφορίες σας δεν θα αποθηκευτούν." + }, + "unsavedChangesTitle": { + "message": "Μη αποθηκευμένες αλλαγές" + }, + "clone": { + "message": "Κλώνος" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Μία ή περισσότερες πολιτικές του οργανισμού επηρεάζουν τις ρυθμίσεις της γεννήτριας." + }, + "vaultTimeoutAction": { + "message": "Ενέργεια Χρόνου Λήξης Vault" + }, + "vaultTimeoutActionLockDesc": { + "message": "Ένα κλειδωμένο vault απαιτεί να εισάγετε ξανά τον κύριο κωδικό για να αποκτήσετε ξανά πρόσβαση σε αυτόν." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Ένα αποσυνδεδεμένο vault απαιτεί να κάνετε ξανά έλεγχο ταυτότητας για να αποκτήσετε πρόσβαση σε αυτό." + }, + "lock": { + "message": "Κλείδωμα", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Κάδος Απορριμάτων", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Αναζήτηση Κάδου" + }, + "permanentlyDeleteItem": { + "message": "Μόνιμη Διαγραφή Αντικειμένου" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε μόνιμα αυτό το στοιχείο;" + }, + "permanentlyDeletedItem": { + "message": "Μόνιμα Διεγραμμένο Στοιχείο" + }, + "restoreItem": { + "message": "Ανάκτηση Στοιχείου" + }, + "restoreItemConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να ανακτήσετε αυτό το στοιχείο;" + }, + "restoredItem": { + "message": "Στοιχείο που έχει Ανακτηθεί" + }, + "permanentlyDelete": { + "message": "Μόνιμη Διαγραφή" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Η αποσύνδεση θα καταργήσει όλη την πρόσβαση στο vault σας και απαιτεί online έλεγχο ταυτότητας μετά το χρονικό όριο λήξης. Είστε βέβαιοι ότι θέλετε να χρησιμοποιήσετε αυτήν τη ρύθμιση;" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Επιβεβαίωση Ενέργειας Χρονικού Ορίου" + }, + "enterpriseSingleSignOn": { + "message": "Ενιαία είσοδος για επιχειρήσεις" + }, + "setMasterPassword": { + "message": "Ορισμός Κύριου Κωδικού" + }, + "ssoCompleteRegistration": { + "message": "Για να ολοκληρώσετε τη σύνδεση με SSO, ορίστε έναν κύριο κωδικό πρόσβασης για πρόσβαση και προστασία του vault σας." + }, + "newMasterPass": { + "message": "Νέος Κύριος Κωδικός" + }, + "confirmNewMasterPass": { + "message": "Επιβεβαίωση Νέου Κύριου Κωδικού" + }, + "masterPasswordPolicyInEffect": { + "message": "Σε μία ή περισσότερες πολιτικές του οργανισμού απαιτείται ο κύριος κωδικός να πληρεί τις ακόλουθες απαιτήσεις:" + }, + "policyInEffectMinComplexity": { + "message": "Ελάχιστος βαθμός πολυπλοκότητας: $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Ελάχιστο μήκος: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Να περιέχει έναν ή περισσότερους κεφαλαίους χαρακτήρες" + }, + "policyInEffectLowercase": { + "message": "Να περιέχει έναν ή περισσότερους πεζούς χαρακτήρες" + }, + "policyInEffectNumbers": { + "message": "Να περιέχει έναν ή περισσότερους αριθμούς" + }, + "policyInEffectSpecial": { + "message": "Να περιέχει έναν ή περισσότερους από τους ακόλουθους ειδικούς χαρακτήρες $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ο νέος κύριος κωδικός δεν πληροί τις απαιτήσεις πολιτικής." + }, + "acceptPolicies": { + "message": "Επιλέγοντας αυτό το πλαίσιο, συμφωνείτε με τα εξής:" + }, + "acceptPoliciesError": { + "message": "Οι Όροι Παροχής Υπηρεσιών και η Πολιτική Απορρήτου δεν έχουν αναγνωριστεί." + }, + "enableBrowserIntegration": { + "message": "Ενεργοποίηση ενσωμάτωσης περιηγητή" + }, + "enableBrowserIntegrationDesc": { + "message": "Η ενσωμάτωση του προγράμματος περιήγησης χρησιμοποιείται για βιομετρικά στοιχεία στο πρόγραμμα περιήγησης." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Η ενσωμάτωση του περιηγητή δεν υποστηρίζεται" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Δυστυχώς η ενσωμάτωση του προγράμματος περιήγησης υποστηρίζεται μόνο στην έκδοση Mac App Store για τώρα." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Η ενσωμάτωση του περιηγητή δεν υποστηρίζεται" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Δυστυχώς η ενσωμάτωση του προγράμματος περιήγησης, δεν υποστηρίζεται στην έκδοση Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Απαιτείται επαλήθευση για ολοκλήρωση περιηγητή" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Ενεργοποιήστε ένα πρόσθετο επίπεδο ασφάλειας απαιτώντας επικύρωση φράσης δακτυλικών αποτυπωμάτων κατά τη δημιουργία μιας σύνδεσης μεταξύ της επιφάνειας εργασίας σας και του προγράμματος περιήγησης. Όταν ενεργοποιηθεί, αυτό απαιτεί παρέμβαση χρήστη και επαλήθευση κάθε φορά που δημιουργείται σύνδεση." + }, + "approve": { + "message": "Έγκριση" + }, + "verifyBrowserTitle": { + "message": "Επαλήθευση σύνδεσης περιηγητή" + }, + "verifyBrowserDesc": { + "message": "Βεβαιωθείτε ότι το εμφανιζόμενο δακτυλικό αποτύπωμα είναι ταυτόσημο με το δακτυλικό αποτύπωμα που εμφανίζεται στην επέκταση του προγράμματος περιήγησης." + }, + "biometricsNotEnabledTitle": { + "message": "Η βιομετρική δεν είναι ενεργοποιημένη" + }, + "biometricsNotEnabledDesc": { + "message": "Η βιομετρική περιήγηση απαιτεί την ενεργοποίηση των βιομετρικών στοιχείων επιφάνειας εργασίας στις ρυθμίσεις πρώτα." + }, + "personalOwnershipSubmitError": { + "message": "Λόγω μιας Πολιτικής Επιχειρήσεων, δεν επιτρέπεται η αποθήκευση στοιχείων στο προσωπικό σας vault. Αλλάξτε την επιλογή Ιδιοκτησίας σε έναν οργανισμό και επιλέξτε από τις διαθέσιμες Συλλογές." + }, + "hintEqualsPassword": { + "message": "Η υπόδειξη κωδικού πρόσβασης, δεν μπορεί να είναι η ίδια με τον κωδικό πρόσβασης σας." + }, + "personalOwnershipPolicyInEffect": { + "message": "Μια πολιτική του οργανισμού, επηρεάζει τις επιλογές ιδιοκτησίας σας." + }, + "allSends": { + "message": "Όλα τα Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Αρχείο" + }, + "sendTypeText": { + "message": "Κείμενο" + }, + "searchSends": { + "message": "Αναζήτηση Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Επεξεργασία Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Το Vault μου" + }, + "text": { + "message": "Κείμενο" + }, + "deletionDate": { + "message": "Ημερομηνία διαγραφής" + }, + "deletionDateDesc": { + "message": "Το Send θα διαγραφεί οριστικά την καθορισμένη ημερομηνία και ώρα.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Ημερομηνία Λήξης" + }, + "expirationDateDesc": { + "message": "Εάν οριστεί, η πρόσβαση σε αυτό το Send θα λήξει την καθορισμένη ημερομηνία και ώρα.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Μέγιστος Αριθμός Πρόσβασης" + }, + "maxAccessCountDesc": { + "message": "Εάν οριστεί, οι χρήστες δεν θα μπορούν πλέον να έχουν πρόσβαση σε αυτό το send μόλις επιτευχθεί ο μέγιστος αριθμός πρόσβασης.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Τρέχων Αριθμός Πρόσβασης" + }, + "disableSend": { + "message": "Απενεργοποιήστε αυτό το Send έτσι ώστε κανείς να μην μπορεί να έχει πρόσβαση σε αυτό.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Προαιρετικά απαιτείται κωδικός πρόσβασης για τους χρήστες για να έχουν πρόσβαση σε αυτό το Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Ιδιωτικές σημειώσεις σχετικά με αυτό το Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Σύνδεσμος Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Αποστολή Συνδέσμου", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Κατά την πρόσβαση στην αποστολή, απόκρυψη του κειμένου από προεπιλογή", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Το Send Δημιουργήθηκε", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Το Send Επεξεργάστηκε", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Το Send Διαγράφηκε", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Νέος Κωδικός" + }, + "whatTypeOfSend": { + "message": "Τι είδους Send είναι αυτό;", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Δημιουργήστε Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Το κείμενο που θέλετε να στείλετε." + }, + "sendFileDesc": { + "message": "Το αρχείο που θέλετε να στείλετε." + }, + "days": { + "message": "$DAYS$ ημέρες", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 ημέρα" + }, + "custom": { + "message": "Προσαρμοσμένο" + }, + "deleteSendConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το Send;", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Αντιγραφή συνδέσμου Send στο πρόχειρο", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Αντιγράψτε το σύνδεσμο, για να μοιραστείτε αυτό το Send στο πρόχειρο μου, κατά την αποθήκευση." + }, + "sendDisabled": { + "message": "Send Απενεργοποιημένο", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Λόγω μιας επιχειρηματικής πολιτικής, είστε σε θέση να διαγράψετε μόνο ένα υπάρχον Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Αντιγραφή συνδέσμου" + }, + "disabled": { + "message": "Απενεργοποιημένο" + }, + "maxAccessCountReached": { + "message": "Φτάσατε στον μέγιστο αριθμό πρόσβασης" + }, + "expired": { + "message": "Έληξε" + }, + "pendingDeletion": { + "message": "Εκκρεμεί διαγραφή" + }, + "webAuthnAuthenticate": { + "message": "Ταυτοποίηση WebAutn" + }, + "hideEmail": { + "message": "Απόκρυψη της διεύθυνσης email μου από τους παραλήπτες." + }, + "sendOptionsPolicyInEffect": { + "message": "Μία ή περισσότερες οργανωτικές πολιτικές επηρεάζουν τις επιλογές send σας." + }, + "emailVerificationRequired": { + "message": "Απαιτείται Επαλήθευση Email" + }, + "emailVerificationRequiredDesc": { + "message": "Πρέπει να επαληθεύσετε το email σας για να χρησιμοποιήσετε αυτή τη δυνατότητα." + }, + "passwordPrompt": { + "message": "Προτροπή νέου κωδικού πρόσβασης" + }, + "passwordConfirmation": { + "message": "Επιβεβαίωση κύριου κωδικού πρόσβασης" + }, + "passwordConfirmationDesc": { + "message": "Αυτή η ενέργεια προστατεύεται. Για να συνεχίσετε, πληκτρολογήστε ξανά τον κύριο κωδικό πρόσβασης για να επαληθεύσετε την ταυτότητά σας." + }, + "updatedMasterPassword": { + "message": "Ενημερώθηκε ο κύριος κωδικός πρόσβασης" + }, + "updateMasterPassword": { + "message": "Ενημερώστε τον κύριο κωδικό πρόσβασης" + }, + "updateMasterPasswordWarning": { + "message": "Ο Κύριος Κωδικός Πρόσβασής σας άλλαξε πρόσφατα από διαχειριστή στον οργανισμό σας. Για να αποκτήσετε πρόσβαση στο vault, πρέπει να τον ενημερώσετε τώρα. Η διαδικασία θα σας αποσυνδέσει από την τρέχουσα συνεδρία σας, απαιτώντας από εσάς να συνδεθείτε ξανά. Οι ενεργές συνεδρίες σε άλλες συσκευές ενδέχεται να συνεχίσουν να είναι ενεργές για μία ώρα." + }, + "hours": { + "message": "Ώρες" + }, + "minutes": { + "message": "Λεπτά" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Οι πολιτικές του οργανισμού σας επηρεάζουν το χρονικό όριο vault σας. Το μέγιστο επιτρεπόμενο Χρονικό όριο Vault είναι $HOURS$ ώρα(ες) και $MINUTES$ λεπτό(ά)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Το χρονικό όριο του vault σας υπερβαίνει τους περιορισμούς που έχει ορίσει ο οργανισμός σας." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Αυτόματη Εγγραφή" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Αυτός ο οργανισμός έχει μια επιχειρηματική πολιτική που θα σας εγγράψει αυτόματα στην επαναφορά κωδικού. Η εγγραφή θα επιτρέψει στους διαχειριστές του οργανισμού να αλλάξουν τον κύριο κωδικό πρόσβασης σας." + }, + "vaultExportDisabled": { + "message": "Εξαγωγή vault Απενεργοποιημένη" + }, + "personalVaultExportPolicyInEffect": { + "message": "Μία ή περισσότερες οργανωτικές πολιτικές σας αποτρέπει από την εξαγωγή του προσωπικού vault." + }, + "addAccount": { + "message": "Προσθήκη Λογαριασμού" + }, + "removeMasterPassword": { + "message": "Αφαίρεση Κύριου Κωδικού Πρόσβασης" + }, + "removedMasterPassword": { + "message": "Ο κύριος κωδικός αφαιρέθηκε." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ χρησιμοποιεί SSO με έναν αυτοεξυπηρετητή κλειδιών. Ένας κύριος κωδικός πρόσβασης δεν απαιτείται πλέον για να συνδεθείτε για τα μέλη αυτού του οργανισμού.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Αποχώρηση από τον οργανισμό" + }, + "leaveOrganizationConfirmation": { + "message": "Είστε βέβαιοι ότι θέλετε να φύγετε από αυτόν τον οργανισμό;" + }, + "leftOrganization": { + "message": "Έχετε φύγει από τον οργανισμό." + }, + "ssoKeyConnectorUnavailable": { + "message": "Δεν είναι δυνατή η πρόσβαση στον σύνδεσμο κλειδιού, προσπαθήστε ξανά αργότερα." + }, + "lockAllVaults": { + "message": "Κλείδωμα Όλων Των Vault" + }, + "accountLimitReached": { + "message": "Δεν μπορούν να συνδεθούν περισσότεροι από 5 λογαριασμοί ταυτόχρονα." + }, + "accountPreferences": { + "message": "Προτιμήσεις" + }, + "appPreferences": { + "message": "Ρυθμίσεις Εφαρμογής (Όλοι Οι Λογαριασμοί)" + }, + "accountSwitcherLimitReached": { + "message": "Συμπληρώθηκε το όριο λογαριασμού. Αποσυνδεθείτε από έναν λογαριασμό για να προσθέσετε έναν άλλο." + }, + "settingsTitle": { + "message": "Ρυθμίσεις εφαρμογής για $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Εναλλαγή λογαριασμού" + }, + "options": { + "message": "Ρυθμίσεις" + }, + "sessionTimeout": { + "message": "Έχει λήξει το χρονικό όριο. Παρακαλώ επιστρέψτε και προσπαθήστε να συνδεθείτε ξανά." + }, + "exportingPersonalVaultTitle": { + "message": "Εξαγωγή Προσωπικού Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Θα εξαχθούν μόνο τα προσωπικά αντικείμενα Vault που σχετίζονται με το $EMAIL$. Τα αντικείμενα Vault οργανισμού δεν θα συμπεριληφθούν.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Γεννήτρια" + }, + "whatWouldYouLikeToGenerate": { + "message": "Τι θα θέλατε να δημιουργήσετε;" + }, + "passwordType": { + "message": "Τύπος Κωδικού" + }, + "regenerateUsername": { + "message": "Επαναδημιουργία Ονόματος Χρήστη" + }, + "generateUsername": { + "message": "Δημιουργία Ονόματος Χρήστη" + }, + "usernameType": { + "message": "Τύπος Ονόματος Χρήστη" + }, + "plusAddressedEmail": { + "message": "Συν Διεύθυνση Email" + }, + "plusAddressedEmailDesc": { + "message": "Χρησιμοποιήστε τις δυνατότητες δευτερεύουσας διεύθυνσης του παρόχου email σας." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Χρησιμοποιήστε τα διαμορφωμένα εισερχόμενα catch-all του domain σας." + }, + "random": { + "message": "Τυχαίο" + }, + "randomWord": { + "message": "Τυχαία Λέξη" + }, + "websiteName": { + "message": "Όνομα Ιστοσελίδας" + }, + "service": { + "message": "Υπηρεσία" + } +} diff --git a/apps/desktop/src/locales/en/messages.json b/apps/desktop/src/locales/en/messages.json new file mode 100644 index 0000000000..590e3743f2 --- /dev/null +++ b/apps/desktop/src/locales/en/messages.json @@ -0,0 +1,1930 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "Favorites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Email Address" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy Value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security Code" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favorite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "uppercase": { + "message": "Uppercase (A-Z)" + }, + "lowercase": { + "message": "Lowercase (a-z)" + }, + "numbers": { + "message": "Numbers (0-9)" + }, + "specialCharacters": { + "message": "Special Characters (!@#$%^&*)" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "Search Folder" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "Add New Folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go to Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check for Updates…" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart to Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search Trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationUnsupportedTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "browserIntegrationLinuxDesc": { + "message": "Unfortunately browser integration is currently not supported in the linux version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count", + "description": "This text will be displayed after a Send has been accessed the maximum amount of times." + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorError": { + "message": "Key Connector error: make sure Key Connector is available and working correctly." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "locked": { + "message": "Locked" + }, + "unlocked": { + "message": "Unlocked" + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email", + "description": "Username generator option that appends a random sub-address to the username. For example: address+subaddress@email.com" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + }, + "allVaults": { + "message": "All Vaults" + }, + "searchOrganization": { + "message": "Search Organization" + }, + "searchMyVault": { + "message": "Search My Vault" + }, + "forwardedEmail": { + "message": "Forwarded Email Alias" + }, + "forwardedEmailDesc": { + "message": "Generate an email alias with an external forwarding service." + }, + "hostname": { + "message": "Hostname", + "description": "Part of a URL." + }, + "apiAccessToken": { + "message": "API Access Token" + }, + "apiKey": { + "message": "API Key" + } +} diff --git a/apps/desktop/src/locales/en_GB/messages.json b/apps/desktop/src/locales/en_GB/messages.json new file mode 100644 index 0000000000..ae918f7eb1 --- /dev/null +++ b/apps/desktop/src/locales/en_GB/messages.json @@ -0,0 +1,1740 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All items" + }, + "favorites": { + "message": "Favourites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search vault" + }, + "addItem": { + "message": "Add item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organisation" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organisation that you wish to move this item to. Moving to an organisation transfers ownership of the item to that organisation. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit item" + }, + "emailAddress": { + "message": "Email address" + }, + "verificationCodeTotp": { + "message": "Verification code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimise when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimise when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle visibility" + }, + "toggleCollapse": { + "message": "Toggle collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security code" + }, + "identityName": { + "message": "Identity name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "National Insurance number" + }, + "passportNumber": { + "message": "Passport number" + }, + "licenseNumber": { + "message": "Licence number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "e.g.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration month" + }, + "expirationYear": { + "message": "Expiration year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First name" + }, + "middleName": { + "message": "Middle name" + }, + "lastName": { + "message": "Last name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / town" + }, + "stateProvince": { + "message": "County" + }, + "zipPostalCode": { + "message": "Postcode" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favourite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New custom field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete item" + }, + "deleteFolder": { + "message": "Delete folder" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the bin?" + }, + "deletedItem": { + "message": "Sent item to bin" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "noneFolder": { + "message": "No folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add folder" + }, + "editFolder": { + "message": "Edit folder" + }, + "regeneratePassword": { + "message": "Regenerate password" + }, + "copyPassword": { + "message": "Copy password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of words" + }, + "wordSeparator": { + "message": "Word separator" + }, + "capitalize": { + "message": "Capitalise", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum numbers" + }, + "minSpecial": { + "message": "Minimum special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid ambiguous characters" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchFavorites": { + "message": "Search favourites" + }, + "searchType": { + "message": "Search type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add new attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "options": { + "message": "Options" + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create account" + }, + "logIn": { + "message": "Log in" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type master password" + }, + "masterPassHint": { + "message": "Master password hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "verificationCode": { + "message": "Verification code" + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery code" + }, + "authenticatorAppTitle": { + "message": "Authenticator app" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP security key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organisation using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled. However, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step login options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API server URL" + }, + "webVaultUrl": { + "message": "Web vault server URL" + }, + "identityUrl": { + "message": "Identity server URL" + }, + "notificationsUrl": { + "message": "Notifications server URL" + }, + "iconsUrl": { + "message": "Icons server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "OK" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log out" + }, + "addNewLogin": { + "message": "Add new login" + }, + "addNewItem": { + "message": "Add new item" + }, + "addNewFolder": { + "message": "Add new folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockNow": { + "message": "Lock now" + }, + "passwordGenerator": { + "message": "Password generator" + }, + "emailUs": { + "message": "Email us" + }, + "visitOurWebsite": { + "message": "Visit our website" + }, + "fileBugReport": { + "message": "File a bug report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow us" + }, + "syncVault": { + "message": "Sync vault" + }, + "changeMasterPass": { + "message": "Change master password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go to web vault" + }, + "getMobileApp": { + "message": "Get mobile app" + }, + "getBrowserExtension": { + "message": "Get browser extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your master password to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step login" + }, + "vaultTimeout": { + "message": "Vault timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On system idle" + }, + "onSleep": { + "message": "On system sleep" + }, + "onLocked": { + "message": "On system lock" + }, + "onRestart": { + "message": "On restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable website icons" + }, + "disableFaviconDesc": { + "message": "Website icons provide a recognisable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimise to tray icon" + }, + "enableMinToTrayDesc": { + "message": "When minimising the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimise to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimising the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to tray icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable tray icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start to tray icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimised to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's colour theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check for updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart to update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy username" + }, + "copyNumber": { + "message": "Copy number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy security code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium membership" + }, + "premiumManage": { + "message": "Manage membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password history" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select all" + }, + "zoomIn": { + "message": "Zoom in" + }, + "zoomOut": { + "message": "Zoom out" + }, + "resetZoom": { + "message": "Reset zoom" + }, + "toggleFullScreen": { + "message": "Toggle full screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle developer tools" + }, + "minimize": { + "message": "Minimise", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring all to front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide others" + }, + "showAll": { + "message": "Show all" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle options" + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to tray" + }, + "alwaysOnTop": { + "message": "Always on top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export vault" + }, + "fileFormat": { + "message": "File format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over insecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Enter your master password to export your vault data." + }, + "noOrganizationsList": { + "message": "You do not belong to any organisations. Organisations allow you to share items securely with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak master password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "yourVaultIsLockedPinCode": { + "message": "Your vault is locked. Verify your PIN code to continue." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable menu bar icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to menu bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of service" + }, + "privacyPolicy": { + "message": "Privacy policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now, your current information won't be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organisation policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault timeout action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Bin", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search bin" + }, + "permanentlyDeleteItem": { + "message": "Permanently delete item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently deleted item" + }, + "restoreItem": { + "message": "Restore item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored item" + }, + "permanentlyDelete": { + "message": "Permanently delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout action confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise single sign-on" + }, + "setMasterPassword": { + "message": "Set master password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New master password" + }, + "confirmNewMasterPass": { + "message": "Confirm new master password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organisation policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of service and privacy policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint shown in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organisation and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organisation policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organisation policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + } +} diff --git a/apps/desktop/src/locales/en_IN/messages.json b/apps/desktop/src/locales/en_IN/messages.json new file mode 100644 index 0000000000..6f1ef49942 --- /dev/null +++ b/apps/desktop/src/locales/en_IN/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All items" + }, + "favorites": { + "message": "Favourites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search vault" + }, + "addItem": { + "message": "Add item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organisation" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organisation that you wish to move this item to. Moving to an organisation transfers ownership of the item to that organisation. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit item" + }, + "emailAddress": { + "message": "Email address" + }, + "verificationCodeTotp": { + "message": "Verification code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimise when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimise when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle visibility" + }, + "toggleCollapse": { + "message": "Toggle collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security code" + }, + "identityName": { + "message": "Identity name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "National Insurance number" + }, + "passportNumber": { + "message": "Passport number" + }, + "licenseNumber": { + "message": "Licence number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "e.g.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration month" + }, + "expirationYear": { + "message": "Expiration year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First name" + }, + "middleName": { + "message": "Middle name" + }, + "lastName": { + "message": "Last name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / town" + }, + "stateProvince": { + "message": "County" + }, + "zipPostalCode": { + "message": "Postcode" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favourite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New custom field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete item" + }, + "deleteFolder": { + "message": "Delete folder" + }, + "deleteAttachment": { + "message": "Delete attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the bin?" + }, + "deletedItem": { + "message": "Sent item to bin" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add folder" + }, + "editFolder": { + "message": "Edit folder" + }, + "regeneratePassword": { + "message": "Regenerate password" + }, + "copyPassword": { + "message": "Copy password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of words" + }, + "wordSeparator": { + "message": "Word separator" + }, + "capitalize": { + "message": "Capitalise", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum numbers" + }, + "minSpecial": { + "message": "Minimum special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid ambiguous characters" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchFavorites": { + "message": "Search favourites" + }, + "searchType": { + "message": "Search type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add new attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create account" + }, + "logIn": { + "message": "Log in" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type master password" + }, + "masterPassHint": { + "message": "Master password hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery code" + }, + "authenticatorAppTitle": { + "message": "Authenticator app" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP security key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organisation using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled. However, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step login options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API server URL" + }, + "webVaultUrl": { + "message": "Web vault server URL" + }, + "identityUrl": { + "message": "Identity server URL" + }, + "notificationsUrl": { + "message": "Notifications server URL" + }, + "iconsUrl": { + "message": "Icons server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "OK" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log out" + }, + "addNewLogin": { + "message": "Add new login" + }, + "addNewItem": { + "message": "Add new item" + }, + "addNewFolder": { + "message": "Add new folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a bug report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow us" + }, + "syncVault": { + "message": "Sync vault" + }, + "changeMasterPass": { + "message": "Change master password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go to web vault" + }, + "getMobileApp": { + "message": "Get mobile app" + }, + "getBrowserExtension": { + "message": "Get browser extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your master password to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step login" + }, + "vaultTimeout": { + "message": "Vault timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On system idle" + }, + "onSleep": { + "message": "On system sleep" + }, + "onLocked": { + "message": "On system lock" + }, + "onRestart": { + "message": "On restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable website icons" + }, + "disableFaviconDesc": { + "message": "Website icons provide a recognisable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimise to tray icon" + }, + "enableMinToTrayDesc": { + "message": "When minimising the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimise to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimising the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to tray icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable tray icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start to tray icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimised to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's colour theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check for updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart to update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy username" + }, + "copyNumber": { + "message": "Copy number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy security code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium membership" + }, + "premiumManage": { + "message": "Manage membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password history" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select all" + }, + "zoomIn": { + "message": "Zoom in" + }, + "zoomOut": { + "message": "Zoom out" + }, + "resetZoom": { + "message": "Reset zoom" + }, + "toggleFullScreen": { + "message": "Toggle full screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle developer tools" + }, + "minimize": { + "message": "Minimise", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring all to front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide others" + }, + "showAll": { + "message": "Show all" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle options" + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to tray" + }, + "alwaysOnTop": { + "message": "Always on top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export vault" + }, + "fileFormat": { + "message": "File format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over insecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organisations. Organisations allow you to share items securely with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak master password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable menu bar icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to menu bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of service" + }, + "privacyPolicy": { + "message": "Privacy policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now, your current information won't be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organisation policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault timeout action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Bin", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search bin" + }, + "permanentlyDeleteItem": { + "message": "Permanently delete item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently deleted item" + }, + "restoreItem": { + "message": "Restore item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored item" + }, + "permanentlyDelete": { + "message": "Permanently delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout action confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise single sign-on" + }, + "setMasterPassword": { + "message": "Set master password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New master password" + }, + "confirmNewMasterPass": { + "message": "Confirm new master password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organisation policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of service and privacy policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint shown in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organisation and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organisation policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organisation policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organisation. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organisation policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organisation." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organisation has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organisation administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organisation policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organisation.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organisation" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organisation?" + }, + "leftOrganization": { + "message": "You have left the organisation." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organisation vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/eo/messages.json b/apps/desktop/src/locales/eo/messages.json new file mode 100644 index 0000000000..1b909d5de4 --- /dev/null +++ b/apps/desktop/src/locales/eo/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "Favorites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Email Address" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy Value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security Code" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favorite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "Search Folder" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "Add New Folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check For Updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/es/messages.json b/apps/desktop/src/locales/es/messages.json new file mode 100644 index 0000000000..df85edfab1 --- /dev/null +++ b/apps/desktop/src/locales/es/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtros" + }, + "allItems": { + "message": "Todos los elementos" + }, + "favorites": { + "message": "Favoritos" + }, + "types": { + "message": "Tipos" + }, + "typeLogin": { + "message": "Entrada" + }, + "typeCard": { + "message": "Tarjeta" + }, + "typeIdentity": { + "message": "Identidad" + }, + "typeSecureNote": { + "message": "Nota segura" + }, + "folders": { + "message": "Carpetas" + }, + "collections": { + "message": "Colecciones" + }, + "searchVault": { + "message": "Buscar en caja fuerte" + }, + "addItem": { + "message": "Añadir elemento" + }, + "shared": { + "message": "Compartido" + }, + "share": { + "message": "Compartir" + }, + "moveToOrganization": { + "message": "Mover a la organización" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ se desplazó a $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Elige una organización a la que deseas mover este objeto. Moviendo a una organización transfiere la propiedad del objeto a esa organización. Ya no serás el dueño directo de este objeto una vez que haya sido movido." + }, + "attachments": { + "message": "Adjuntos" + }, + "viewItem": { + "message": "Ver elemento" + }, + "name": { + "message": "Nombre" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nueva URI" + }, + "username": { + "message": "Usuario" + }, + "password": { + "message": "Contraseña" + }, + "passphrase": { + "message": "Frase de contraseña" + }, + "editItem": { + "message": "Editar elemento" + }, + "emailAddress": { + "message": "Correo electrónico" + }, + "verificationCodeTotp": { + "message": "Código de verificación (TOTP)" + }, + "website": { + "message": "Web" + }, + "notes": { + "message": "Notas" + }, + "customFields": { + "message": "Campos personalizados" + }, + "launch": { + "message": "Iniciar" + }, + "copyValue": { + "message": "Copiar valor", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimizar al copiar al portapapeles" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimizar al copiar los datos de un elemento al portapapeles." + }, + "toggleVisibility": { + "message": "Alternar visibilidad" + }, + "toggleCollapse": { + "message": "Colapsar/Expandir", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Nombre del propietario de la tarjeta" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Marca" + }, + "expiration": { + "message": "Expiración" + }, + "securityCode": { + "message": "Código de seguridad" + }, + "identityName": { + "message": "Nombre de la identidad" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Nº de la seguridad social" + }, + "passportNumber": { + "message": "Nº de pasaporte" + }, + "licenseNumber": { + "message": "Número de licencia" + }, + "email": { + "message": "Correo electrónico" + }, + "phone": { + "message": "Teléfono" + }, + "address": { + "message": "Dirección" + }, + "premiumRequired": { + "message": "Premium requerido" + }, + "premiumRequiredDesc": { + "message": "Se quiere membrasía Premium para poder utilizar esta característica." + }, + "errorOccurred": { + "message": "Ha ocurrido un error." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "Enero" + }, + "february": { + "message": "Febrero" + }, + "march": { + "message": "Marzo" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Mayo" + }, + "june": { + "message": "Junio" + }, + "july": { + "message": "Julio" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Septiembre" + }, + "october": { + "message": "Octubre" + }, + "november": { + "message": "Noviembre" + }, + "december": { + "message": "Diciembre" + }, + "ex": { + "message": "ej.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Título" + }, + "mr": { + "message": "Sr" + }, + "mrs": { + "message": "Sra" + }, + "ms": { + "message": "Srta" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Mes de expiración" + }, + "expirationYear": { + "message": "Año de expiración" + }, + "select": { + "message": "Seleccionar" + }, + "other": { + "message": "Otro" + }, + "generatePassword": { + "message": "Generar contraseña" + }, + "type": { + "message": "Tipo" + }, + "firstName": { + "message": "Nombre" + }, + "middleName": { + "message": "2º nombre" + }, + "lastName": { + "message": "Apellido" + }, + "fullName": { + "message": "Nombre" + }, + "address1": { + "message": "Dirección 1" + }, + "address2": { + "message": "Dirección 2" + }, + "address3": { + "message": "Dirección 3" + }, + "cityTown": { + "message": "Ciudad / Pueblo" + }, + "stateProvince": { + "message": "Estado / Provincia" + }, + "zipPostalCode": { + "message": "Código postal" + }, + "country": { + "message": "País" + }, + "save": { + "message": "Guardar" + }, + "cancel": { + "message": "Cancelar" + }, + "delete": { + "message": "Eliminar" + }, + "favorite": { + "message": "Favorito" + }, + "edit": { + "message": "Editar" + }, + "authenticatorKeyTotp": { + "message": "Clave de autenticación (TOTP)" + }, + "folder": { + "message": "Carpeta" + }, + "newCustomField": { + "message": "Nuevo campo personalizado" + }, + "value": { + "message": "Valor" + }, + "dragToSort": { + "message": "Arrastre para ordenar" + }, + "cfTypeText": { + "message": "Texto" + }, + "cfTypeHidden": { + "message": "Oculto" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "cfTypeLinked": { + "message": "Conectado", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Valor vinculado", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Eliminar" + }, + "nameRequired": { + "message": "Nombre requerido." + }, + "addedItem": { + "message": "Elemento añadido" + }, + "editedItem": { + "message": "Elemento editado" + }, + "deleteItem": { + "message": "Eliminar elemento" + }, + "deleteFolder": { + "message": "Borrar carpeta" + }, + "deleteAttachment": { + "message": "Eliminar archivo adjunto" + }, + "deleteItemConfirmation": { + "message": "¿Estás seguro de que quieres eliminar este elemento?" + }, + "deletedItem": { + "message": "Elemento eliminado" + }, + "overwritePasswordConfirmation": { + "message": "¿Estás seguro de que quieres sobreescribir la contraseña actual?" + }, + "overwriteUsername": { + "message": "Reemplazar nombre de usuario" + }, + "overwriteUsernameConfirmation": { + "message": "¿Esta seguro que desea reemplazar el nombre de usuario?" + }, + "noneFolder": { + "message": "Sin carpeta", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Añadir carpeta" + }, + "editFolder": { + "message": "Editar carpeta" + }, + "regeneratePassword": { + "message": "Regenerar contraseña" + }, + "copyPassword": { + "message": "Copiar contraseña" + }, + "copyUri": { + "message": "Copiar URI" + }, + "copyVerificationCodeTotp": { + "message": "Copiar código de verificación (TOTP)" + }, + "length": { + "message": "Longitud" + }, + "numWords": { + "message": "Número de palabras" + }, + "wordSeparator": { + "message": "Separador de palabras" + }, + "capitalize": { + "message": "Mayúsculas iniciales", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Incluir número" + }, + "close": { + "message": "Cerrar" + }, + "minNumbers": { + "message": "Mínimo de caracteres numéricos" + }, + "minSpecial": { + "message": "Mínimo de caracteres especiales", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Evitar caracteres ambiguos" + }, + "searchCollection": { + "message": "Buscar en colección" + }, + "searchFolder": { + "message": "Buscar en carpeta" + }, + "searchFavorites": { + "message": "Buscar en favoritos" + }, + "searchType": { + "message": "Buscar en tipo", + "description": "Search item type" + }, + "newAttachment": { + "message": "Añadir nuevo adjunto" + }, + "deletedAttachment": { + "message": "Adjunto eliminado" + }, + "deleteAttachmentConfirmation": { + "message": "¿Estás seguro de querer eliminar este adjunto?" + }, + "attachmentSaved": { + "message": "El adjunto se ha guardado." + }, + "file": { + "message": "Archivo" + }, + "selectFile": { + "message": "Selecciona un archivo." + }, + "maxFileSize": { + "message": "El tamaño máximo de archivo es de 500MB." + }, + "updateKey": { + "message": "No puedes usar esta característica hasta que actualices tu clave de cifrado." + }, + "editedFolder": { + "message": "Carpeta editada" + }, + "addedFolder": { + "message": "Carpeta añadida" + }, + "deleteFolderConfirmation": { + "message": "¿Estás seguro de querer eliminar esta carpeta?" + }, + "deletedFolder": { + "message": "Carpeta eliminada" + }, + "loginOrCreateNewAccount": { + "message": "Identifícate o crea una nueva cuenta para acceder a tu caja fuerte." + }, + "createAccount": { + "message": "Crear cuenta" + }, + "logIn": { + "message": "Identificarse" + }, + "submit": { + "message": "Enviar" + }, + "masterPass": { + "message": "Contraseña maestra" + }, + "masterPassDesc": { + "message": "La contraseña maestra es la clave que utilizas para acceder a tu caja fuerte. Es muy importante que no olvides tu contraseña maestra. No hay forma de recuperarla si la olvidas." + }, + "masterPassHintDesc": { + "message": "Una pista de tu contraseña maestra puede ayudarte a recordarla en caso de que la olvides." + }, + "reTypeMasterPass": { + "message": "Vuelve a escribir tu contraseña maestra" + }, + "masterPassHint": { + "message": "Pista de contraseña maestra (opcional)" + }, + "settings": { + "message": "Ajustes" + }, + "passwordHint": { + "message": "Pista de contraseña" + }, + "enterEmailToGetHint": { + "message": "Introduce el correo electrónico de tu cuenta para recibir la pista de tu contraseña maestra." + }, + "getMasterPasswordHint": { + "message": "Obtener pista de la contraseña maestra" + }, + "emailRequired": { + "message": "Correo electrónico requerido." + }, + "invalidEmail": { + "message": "Correo electrónico no válido." + }, + "masterPassRequired": { + "message": "Contraseña maestra requerida." + }, + "masterPassLength": { + "message": "La contraseña maestra debe tener al menos 8 caracteres." + }, + "masterPassDoesntMatch": { + "message": "La confirmación de contraseña maestra no coincide." + }, + "newAccountCreated": { + "message": "¡Tu nueva cuenta ha sido creada! Ahora puedes acceder." + }, + "masterPassSent": { + "message": "Te hemos enviado un correo electrónico con la pista de tu contraseña maestra." + }, + "unexpectedError": { + "message": "Ha ocurrido un error inesperado." + }, + "itemInformation": { + "message": "Información del elemento" + }, + "noItemsInList": { + "message": "No hay elementos que listar." + }, + "sendVerificationCode": { + "message": "Envía un código de verificación a tu correo electrónico" + }, + "sendCode": { + "message": "Enviar código" + }, + "codeSent": { + "message": "Código enviado" + }, + "verificationCode": { + "message": "Código de verificación" + }, + "confirmIdentity": { + "message": "Confirma tu identidad para continuar." + }, + "verificationCodeRequired": { + "message": "Código de verificación requerido." + }, + "invalidVerificationCode": { + "message": "Código de verificación incorrecto" + }, + "continue": { + "message": "Continuar" + }, + "enterVerificationCodeApp": { + "message": "Introduce el código de verificación de 6 dígitos de tu aplicación autenticadora." + }, + "enterVerificationCodeEmail": { + "message": "Introduce el código de verificación de 6 dígitos que fue enviado a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Correo de verificación enviado a $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Recordarme" + }, + "sendVerificationCodeEmailAgain": { + "message": "Reenviar código de verificación por correo electrónico" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizar otro método de autenticación en dos pasos" + }, + "insertYubiKey": { + "message": "Inserta tu YubiKey en el puerto USB de tu equipo y posteriormente pulsa su botón." + }, + "insertU2f": { + "message": "Inserta tu llave de seguridad en el puerto USB de tu equipo. Si tiene un botón, púlsalo." + }, + "recoveryCodeDesc": { + "message": "¿Has perdido el acceso a todos tus métodos de autenticación en dos pasos? Utiliza tu código de recuperación para deshabilitar todos los métodos de autenticación en dos pasos de tu cuenta." + }, + "recoveryCodeTitle": { + "message": "Código de recuperación" + }, + "authenticatorAppTitle": { + "message": "Aplicación de autenticación" + }, + "authenticatorAppDesc": { + "message": "Utiliza una aplicación de autenticación (como Authy o Google Authenticator) para generar código de verificación basados en tiempo.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Llave de seguridad YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Usa un Yubikey para acceder a tu cuenta. Funciona con YubiKey 4, 4 Nano, 4C y dispositivos NEO." + }, + "duoDesc": { + "message": "Verificar con Duo Security usando la aplicación Duo Mobile, SMS, llamada telefónica o llave de seguridad U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verificar con Duo Security para tu organización usando la aplicación Duo Mobile, SMS, llamada telefónica o llave de seguridad U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Utilice cualquier clave de seguridad WebAuthn habilitada para acceder a su cuenta." + }, + "emailTitle": { + "message": "Correo electrónico" + }, + "emailDesc": { + "message": "Los códigos de verificación te serán enviados por correo electrónico." + }, + "loginUnavailable": { + "message": "Entrada no disponible" + }, + "noTwoStepProviders": { + "message": "Esta cuenta tiene autenticación en dos pasos habilitada, pero ninguno de los métodos configurados son soportados por este dispositivo." + }, + "noTwoStepProviders2": { + "message": "Por favor, añade proveedores que estén mejor soportados entre dispositivos (como una aplicación autenticadora)." + }, + "twoStepOptions": { + "message": "Opciones de la autenticación en dos pasos" + }, + "selfHostedEnvironment": { + "message": "Entorno de alojamiento propio" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifica la URL base de tu instalación de Bitwarden de alojamiento propio." + }, + "customEnvironment": { + "message": "Entorno personalizado" + }, + "customEnvironmentFooter": { + "message": "Para usuarios avanzados. Puedes especificar la URL base de cada servicio de forma independiente." + }, + "baseUrl": { + "message": "URL del servidor" + }, + "apiUrl": { + "message": "URL del servidor de la API" + }, + "webVaultUrl": { + "message": "URL del servidor de la caja fuerte web" + }, + "identityUrl": { + "message": "URL del servidor de identidad" + }, + "notificationsUrl": { + "message": "URL del servidor de notificaciones" + }, + "iconsUrl": { + "message": "URL del servidor de iconos" + }, + "environmentSaved": { + "message": "Las URLs del entorno han sido guardadas." + }, + "ok": { + "message": "Aceptar" + }, + "yes": { + "message": "Si" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Sobreescribir contraseña" + }, + "learnMore": { + "message": "Más información" + }, + "featureUnavailable": { + "message": "Característica no disponible" + }, + "loggedOut": { + "message": "Sesión terminada" + }, + "loginExpired": { + "message": "Tu sesión ha expirado." + }, + "logOutConfirmation": { + "message": "¿Estás seguro de querer cerrar sesión?" + }, + "logOut": { + "message": "Cerrar sesión" + }, + "addNewLogin": { + "message": "Añadir nueva entrada" + }, + "addNewItem": { + "message": "Añadir nuevo elemento" + }, + "addNewFolder": { + "message": "Añadir nueva carpeta" + }, + "view": { + "message": "Ver" + }, + "account": { + "message": "Cuenta" + }, + "loading": { + "message": "Cargando..." + }, + "lockVault": { + "message": "Bloquear caja fuerte" + }, + "passwordGenerator": { + "message": "Generador de contraseñas" + }, + "contactUs": { + "message": "Contáctenos" + }, + "getHelp": { + "message": "Obtener ayuda" + }, + "fileBugReport": { + "message": "Reportar un fallo" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Síguenos" + }, + "syncVault": { + "message": "Sincronizar caja fuerte" + }, + "changeMasterPass": { + "message": "Cambiar contraseña maestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Puedes cambiar tu contraseña maestra en la caja fuerte web de bitwarden.com. ¿Quieres visitar ahora el sitio web?" + }, + "fingerprintPhrase": { + "message": "Frase de huella digital", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frase de la huella digital de su cuenta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Ir a la caja fuerte web" + }, + "getMobileApp": { + "message": "Obtener la aplicación móvil" + }, + "getBrowserExtension": { + "message": "Obtener extensión de navegador" + }, + "syncingComplete": { + "message": "Sincronización completada" + }, + "syncingFailed": { + "message": "Sincronización fallida" + }, + "yourVaultIsLocked": { + "message": "Tu caja fuerte está bloqueada. Verifica tu contraseña maestra para continuar." + }, + "unlock": { + "message": "Desbloquear" + }, + "loggedInAsOn": { + "message": "Conectado como $EMAIL$ en $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Contraseña maestra no válida" + }, + "twoStepLoginConfirmation": { + "message": "La autenticación en dos pasos hace que tu cuenta sea mucho más segura, requiriendo que introduzcas un código de seguridad de una aplicación de autenticación cada vez que accedes. La autenticación en dos pasos puede ser habilitada en la caja fuerte web de bitwarden.com. ¿Quieres visitar ahora el sitio web?" + }, + "twoStepLogin": { + "message": "Autenticación en dos pasos" + }, + "vaultTimeout": { + "message": "Tiempo de espera de la caja fuerte" + }, + "vaultTimeoutDesc": { + "message": "Elije cuando se agotará el tiempo de espera de tu caja fuerte y se ejecutará la acción seleccionada." + }, + "immediately": { + "message": "Inmediatamente" + }, + "tenSeconds": { + "message": "10 segundos" + }, + "twentySeconds": { + "message": "20 segundos" + }, + "thirtySeconds": { + "message": "30 segundos" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minutos" + }, + "fiveMinutes": { + "message": "5 minutos" + }, + "fifteenMinutes": { + "message": "15 minutos" + }, + "thirtyMinutes": { + "message": "30 minutos" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 horas" + }, + "onIdle": { + "message": "En inactividad del sistema" + }, + "onSleep": { + "message": "Al suspender el sistema" + }, + "onLocked": { + "message": "Al bloquear el sistema" + }, + "onRestart": { + "message": "Al reiniciar" + }, + "never": { + "message": "Nunca" + }, + "security": { + "message": "Seguridad" + }, + "clearClipboard": { + "message": "Limpiar el Portapapeles", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Borrar automáticamente los valores copiados de su portapapeles.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Deshabilitar iconos de sitio web" + }, + "disableFaviconDesc": { + "message": "Los iconos de sitio web añaden una imagen reconocible al lado de cada entrada de tu caja fuerte." + }, + "enableMinToTray": { + "message": "Minimizar a icono en la bandeja" + }, + "enableMinToTrayDesc": { + "message": "Cuando se minimiza la ventana, se muestra un icono en la bandeja del sistema." + }, + "enableMinToMenuBar": { + "message": "Minimizar a la barra de menú" + }, + "enableMinToMenuBarDesc": { + "message": "Al minimizar la ventana, muestra un icono en la barra de menú." + }, + "enableCloseToTray": { + "message": "Cerrar a icono de la bandeja" + }, + "enableCloseToTrayDesc": { + "message": "Cuando se cierre la ventana, mostrar un icono en la bandeja de sistema." + }, + "enableCloseToMenuBar": { + "message": "Cerrar a la barra de menú" + }, + "enableCloseToMenuBarDesc": { + "message": "Al cerrar la ventana, muestra un icono en la barra de menú." + }, + "enableTray": { + "message": "Activar icono en bandeja" + }, + "enableTrayDesc": { + "message": "Mostrar siempre el icono de la bandeja del sistema." + }, + "startToTray": { + "message": "Iniciar como icono de bandeja del sistema" + }, + "startToTrayDesc": { + "message": "Cuando la aplicación se inicia por primera vez, sólo muestra un icono en la bandeja del sistema." + }, + "startToMenuBar": { + "message": "Inicia a la barra de menú" + }, + "startToMenuBarDesc": { + "message": "Cuando la aplicación se inicia por primera vez, mostrar únicamente un icono en la barra de menú." + }, + "openAtLogin": { + "message": "Arranca automáticamente al iniciar sesión" + }, + "openAtLoginDesc": { + "message": "Arranca la aplicación Bitwarden Desktop automáticamente tras iniciar sesión." + }, + "alwaysShowDock": { + "message": "Mostrar siempre en el Dock" + }, + "alwaysShowDockDesc": { + "message": "Muestra el icono de Bitwarden en el Dock incluso cuando se minimiza a la barra de menú." + }, + "confirmTrayTitle": { + "message": "Confirmar deshabilitar en bandeja del sistema" + }, + "confirmTrayDesc": { + "message": "Deshabilitar esta opción también desactivará todas las demás opciones relacionadas con la bandeja." + }, + "language": { + "message": "Idioma" + }, + "languageDesc": { + "message": "Cambiar el idioma usado por la aplicación. Es necesario reiniciar." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Cambiar el tema de la aplicación." + }, + "dark": { + "message": "Oscuro", + "description": "Dark color" + }, + "light": { + "message": "Claro", + "description": "Light color" + }, + "copy": { + "message": "Copiar", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Buscar actualizaciones" + }, + "version": { + "message": "Versión $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Reiniciar para actualizar" + }, + "restartToUpdateDesc": { + "message": "La versión $VERSION_NUM$ está lista para instalar. Debes reiniciar Bitwarden para completar la instalación. ¿Quieres reiniciar y actualizar ahora?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Actualización disponible" + }, + "updateAvailableDesc": { + "message": "Se ha encontrado una actualización. ¿Quieres descargarla ahora?" + }, + "restart": { + "message": "Reiniciar" + }, + "later": { + "message": "Más tarde" + }, + "noUpdatesAvailable": { + "message": "No hay actualizaciones disponibles. Estás utilizando la última versión." + }, + "updateError": { + "message": "Error de actualización" + }, + "unknown": { + "message": "Desconocido" + }, + "copyUsername": { + "message": "Copiar usuario" + }, + "copyNumber": { + "message": "Copiar número", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copiar código de seguridad", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Membresía Premium" + }, + "premiumManage": { + "message": "Gestionar membresía" + }, + "premiumManageAlert": { + "message": "Puedes gestionar tu membresía en la caja fuerte web de bitwarden.com. ¿Quieres visitar el sitio web ahora?" + }, + "premiumRefresh": { + "message": "Actualizar membresía" + }, + "premiumNotCurrentMember": { + "message": "Actualmente no eres un miembro premium." + }, + "premiumSignUpAndGet": { + "message": "Registrate como miembro Premium y obtén:" + }, + "premiumSignUpStorage": { + "message": "1GB de espacio en disco cifrado." + }, + "premiumSignUpTwoStep": { + "message": "Métodos de autenticación en dos pasos adicionales como YubiKey, FIDO U2F y Duo." + }, + "premiumSignUpReports": { + "message": "Higiene de contraseña, salud de la cuenta e informes de violaciones de datos para mantener tu caja fuerte segura." + }, + "premiumSignUpTotp": { + "message": "Generación de códigos TOTP (2FA) para registros de tu caja fuerte." + }, + "premiumSignUpSupport": { + "message": "Soporte prioritario." + }, + "premiumSignUpFuture": { + "message": "Acceso a nuevas características premium en el futuro. ¡Hay más en camino!" + }, + "premiumPurchase": { + "message": "Comprar Premium" + }, + "premiumPurchaseAlert": { + "message": "Puedes comprar la membresía Premium en la caja fuerte web de bitwarden.com. ¿Quieres visitar el sitio web ahora?" + }, + "premiumCurrentMember": { + "message": "¡Eres un miembro Premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Gracias por apoyar el desarrollo de Bitwarden." + }, + "premiumPrice": { + "message": "¡Todo por sólo $PRICE$/año!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Actualización completada" + }, + "passwordHistory": { + "message": "Historial de contraseñas" + }, + "clear": { + "message": "Limpiar", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "No hay contraseñas que listar." + }, + "undo": { + "message": "Deshacer" + }, + "redo": { + "message": "Rehacer" + }, + "cut": { + "message": "Cortar", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Pegar", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Seleccionar todo" + }, + "zoomIn": { + "message": "Zoom +" + }, + "zoomOut": { + "message": "Zoom -" + }, + "resetZoom": { + "message": "Reestablecer zoom" + }, + "toggleFullScreen": { + "message": "Alternar pantalla completa" + }, + "reload": { + "message": "Recargar" + }, + "toggleDevTools": { + "message": "Herramientas de desarrollo" + }, + "minimize": { + "message": "Minimizar", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Traer todo al frente", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Acerca de Bitwarden" + }, + "services": { + "message": "Servicios" + }, + "hideBitwarden": { + "message": "Ocultar Bitwarden" + }, + "hideOthers": { + "message": "Ocultar otros" + }, + "showAll": { + "message": "Mostrar todo" + }, + "quitBitwarden": { + "message": "Salir de Bitwarden" + }, + "valueCopied": { + "message": "Valor de $VALUE$ copiado", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Ayuda" + }, + "window": { + "message": "Ventana" + }, + "checkPassword": { + "message": "Comprobar si la contraseña está comprometida." + }, + "passwordExposed": { + "message": "Esta contraseña fue encontrada $VALUE$ vez/veces en filtraciones de datos. Deberías cambiarla.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Esta contraseña no fue encontrada en ninguna filtración de datos conocida. Deberías poder utilizarla de forma segura." + }, + "baseDomain": { + "message": "Dominio base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nombre de dominio", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Servidor", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exacta" + }, + "startsWith": { + "message": "Empieza con" + }, + "regEx": { + "message": "Expresión regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Tipo de detección", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detección por defecto", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Alternar opciones" + }, + "organization": { + "message": "Organización", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Por defecto" + }, + "exit": { + "message": "Salir" + }, + "showHide": { + "message": "Mostrar / Ocultar", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Ocultar en bandeja" + }, + "alwaysOnTop": { + "message": "Siempre por encima", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Actualizada", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Contraseña actualizada", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Exportar caja fuerte" + }, + "fileFormat": { + "message": "Formato de archivo" + }, + "warning": { + "message": "ADVERTENCIA", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirmar la exportación de la bóveda" + }, + "exportWarningDesc": { + "message": "Esta exportación contiene tus datos de la caja fuerte en un formato no cifrado. No deberías almacenar o enviar el archivo exportado por canales no seguros (como el correo electrónico). Elimínalo inmediatamente cuando termines de utilizarlo." + }, + "encExportKeyWarningDesc": { + "message": "Esta exportación encripta tus datos utilizando la clave de encriptación de tu cuenta. Si alguna vez renueva la clave de cifrado de su cuenta, deberá exportar de nuevo, ya que no podrá descifrar este archivo de exportación." + }, + "encExportAccountWarningDesc": { + "message": "Las claves de encriptación de las cuentas son únicas para cada cuenta de usuario de Bitwarden, por lo que no se puede importar una exportación encriptada a una cuenta diferente." + }, + "noOrganizationsList": { + "message": "No perteneces a ninguna organización. Las organizaciones te permiten compartir elementos con otros usuarios de forma segura." + }, + "noCollectionsInList": { + "message": "No hay colecciones que listar." + }, + "ownership": { + "message": "Propiedad" + }, + "whoOwnsThisItem": { + "message": "¿Quién posee este elemento?" + }, + "strong": { + "message": "Fuerte", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Buena", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Débil", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Contraseña maestra débil" + }, + "weakMasterPasswordDesc": { + "message": "La contraseña maestra que ha elegido es débil. Debe usar una contraseña maestra fuerte (o una frase de contraseña) para proteger adecuadamente su cuenta de Bitwarden. ¿Está seguro de que desea utilizar esta contraseña maestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloquear con PIN" + }, + "setYourPinCode": { + "message": "Establece tu código PIN para desbloquear Bitwarden. Tus ajustes de PIN se reiniciarán si alguna vez se desloguea completamente de la aplicación." + }, + "pinRequired": { + "message": "Código PIN requerido." + }, + "invalidPin": { + "message": "Código PIN inválido." + }, + "unlockWithWindowsHello": { + "message": "Desbloquear con Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verificar para Bitwarden." + }, + "unlockWithTouchId": { + "message": "Desbloquear con Touch ID" + }, + "touchIdConsentMessage": { + "message": "Verificar para Bitwarden." + }, + "noAutoPromptWindowsHello": { + "message": "No solicite Windows Hello al empezar." + }, + "noAutoPromptTouchId": { + "message": "No solicite Touch ID al empezar." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloquear con contraseña maestra al reiniciar" + }, + "preferences": { + "message": "Preferencias" + }, + "enableMenuBar": { + "message": "Activar ícono de barra de menú" + }, + "enableMenuBarDesc": { + "message": "Mostrar siempre un ícono en la barra de menú." + }, + "hideToMenuBar": { + "message": "Ocultar en la barra de menú" + }, + "selectOneCollection": { + "message": "Debes seleccionar al menos una colección." + }, + "premiumUpdated": { + "message": "Has actualizado a premium." + }, + "restore": { + "message": "Restaurar" + }, + "premiumManageAlertAppStore": { + "message": "Puedes administrar tu suscripción desde la App Store. ¿Quieres visitar la App Store ahora?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Términos y condiciones del servicio" + }, + "privacyPolicy": { + "message": "Política de privacidad" + }, + "unsavedChangesConfirmation": { + "message": "¿Estás seguro que deseas salir? Si sales ahora, tu información actual no será guardada" + }, + "unsavedChangesTitle": { + "message": "Hay cambios sin guardar" + }, + "clone": { + "message": "Clonar" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una o más políticas de la organización están afectando la configuración del generador." + }, + "vaultTimeoutAction": { + "message": "Tiempo de espera de la caja fuerte" + }, + "vaultTimeoutActionLockDesc": { + "message": "Una caja fuerte bloqueada requiere que introduzcas de nuevo tu contraseña maestra para acceder nuevamente." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Cerrar sesión en la caja fuerte requiere que vuelvas a autenticarte para acceder nuevamente a ella." + }, + "lock": { + "message": "Bloquear", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papelera", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Buscar en la Papelera" + }, + "permanentlyDeleteItem": { + "message": "Eliminar elemento de forma permanente" + }, + "permanentlyDeleteItemConfirmation": { + "message": "¿Estás seguro de eliminar de forma permanente este elemento?" + }, + "permanentlyDeletedItem": { + "message": "Elemento eliminado de forma permanente" + }, + "restoreItem": { + "message": "Restaurar elemento" + }, + "restoreItemConfirmation": { + "message": "¿Estás seguro de que quieres restaurar este elemento?" + }, + "restoredItem": { + "message": "Elemento restaurado" + }, + "permanentlyDelete": { + "message": "Eliminar de forma permanente" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Si cierras sesión, tu caja fuerte se bloqueará después del tiempo de espera seleccionado hasta que vuelvas a autenticarte. Utiliza esta opción sólo si este es el efecto deseado." + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmación de acción del tiempo de espera de la caja fuerte" + }, + "enterpriseSingleSignOn": { + "message": "Inicio de sesión único empresarial" + }, + "setMasterPassword": { + "message": "Establecer contraseña maestra" + }, + "ssoCompleteRegistration": { + "message": "Para completar el inicio de sesión con SSO, por favor establezca una contraseña maestra para acceder y proteger su caja fuerte." + }, + "newMasterPass": { + "message": "Nueva contraseña maestra" + }, + "confirmNewMasterPass": { + "message": "Confirma la nueva contraseña maestra" + }, + "masterPasswordPolicyInEffect": { + "message": "Una o más políticas de la organización requieren que su contraseña maestra cumpla con los siguientes requisitos:" + }, + "policyInEffectMinComplexity": { + "message": "Puntuación de complejidad mínima $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Longitud mínima $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contenga uno o más caracteres en mayúsculas" + }, + "policyInEffectLowercase": { + "message": "Contenga uno o más caracteres en minúsculas" + }, + "policyInEffectNumbers": { + "message": "Contenga uno o más números" + }, + "policyInEffectSpecial": { + "message": "Contenga uno o más de los siguientes caracteres especiales $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Su nueva contraseña maestra no cumple con los requisitos de la política." + }, + "acceptPolicies": { + "message": "Al seleccionar esta casilla, acepto lo siguiente:" + }, + "acceptPoliciesError": { + "message": "Todavía no has aceptado los términos del servicio y la política de privacidad." + }, + "enableBrowserIntegration": { + "message": "Habilitar integración con el navegador" + }, + "enableBrowserIntegrationDesc": { + "message": "La integración del navegador se usa para la biometría en el mismo." + }, + "browserIntegrationMasOnlyTitle": { + "message": "La integración del navegador no está soportada" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Por desgracia la integración del navegador sólo está soportada por ahora en la versión de la Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "La integración del navegador no está soportada" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Por desgracia la integración del navegador sólo está soportada por ahora en la versión de Microsoft Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Requiere verificación para la integración del navegador" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Requiere una capa adicional de seguridad mediante el solicitar la frase de validación de huella dactilar al establecer un enlace entre el escritorio y el navegador. Cuando se activa, requiere intervención del usuario y verificación cada vez que se establece una conexión." + }, + "approve": { + "message": "Aprobar" + }, + "verifyBrowserTitle": { + "message": "Verificar la conexión del navegador" + }, + "verifyBrowserDesc": { + "message": "Por favor, asegúrese de que la huella digital mostrada es idéntica a la huella que aparece en la extensión del navegador." + }, + "biometricsNotEnabledTitle": { + "message": "Biometría no habilitada" + }, + "biometricsNotEnabledDesc": { + "message": "La biometría del navegador requiere habilitar primero la biometría de escritorio en los ajustes." + }, + "personalOwnershipSubmitError": { + "message": "Debido a una política de organización, tiene restringido el guardar elementos a su bóveda personal. Cambie la configuración de propietario a organización y elija entre las colecciones disponibles." + }, + "hintEqualsPassword": { + "message": "La pista para la contraseña no puede ser igual que la contraseña." + }, + "personalOwnershipPolicyInEffect": { + "message": "Una política de organización está afectando a sus opciones de propiedad." + }, + "allSends": { + "message": "Todos los Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Archivo" + }, + "sendTypeText": { + "message": "Texto" + }, + "searchSends": { + "message": "Búsqueda de Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Editar Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mi bóveda" + }, + "text": { + "message": "Texto" + }, + "deletionDate": { + "message": "Fecha de eliminación" + }, + "deletionDateDesc": { + "message": "El Send se borrará definitivamente en la fecha y hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Fecha de caducidad" + }, + "expirationDateDesc": { + "message": "Si se establece, el acceso a este Send expirará en la fecha y hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Número máximo de accesos" + }, + "maxAccessCountDesc": { + "message": "Si se establece, los usuarios ya no podrán acceder a este Send una vez que se alcance el número máximo de accesos.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Conteo actual de accesos" + }, + "disableSend": { + "message": "Desactive este Send para que nadie pueda acceder a él.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcionalmente, se requiere una contraseña para que los usuarios accedan a este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notas privadas sobre este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send enlace", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send enlace", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Cuando se accede al Envío, se oculta el texto por defecto", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send creado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send editado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send eliminado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nueva contraseña" + }, + "whatTypeOfSend": { + "message": "¿Qué tipo de Send es éste?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Crear Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "El texto que quieres enviar." + }, + "sendFileDesc": { + "message": "El archivo que quieres enviar." + }, + "days": { + "message": "$DAYS$ días", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 día" + }, + "custom": { + "message": "Personalizado" + }, + "deleteSendConfirmation": { + "message": "¿Está seguro de que quiere eliminar este envío?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copiar el enlace del Send al portapapeles", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copiar el enlace para compartir esto Enviar a mi portapapeles al guardar." + }, + "sendDisabled": { + "message": "Enviar desactivado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Debido a una política de la empresa, sólo puede eliminar un Envío existente.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copiar enlace" + }, + "disabled": { + "message": "Deshabilitado" + }, + "maxAccessCountReached": { + "message": "Se ha alcanzado el número máximo de accesos" + }, + "expired": { + "message": "Expirado" + }, + "pendingDeletion": { + "message": "Pendiente de eliminación" + }, + "webAuthnAuthenticate": { + "message": "Autenticar WebAuthn" + }, + "hideEmail": { + "message": "Ocultar mi dirección de correo electrónico a los destinatarios." + }, + "sendOptionsPolicyInEffect": { + "message": "Una o más políticas de organización están afectando sus opciones del Send." + }, + "emailVerificationRequired": { + "message": "Verificación de correo electrónico requerida" + }, + "emailVerificationRequiredDesc": { + "message": "Debes verificar tu correo electrónico para usar esta característica." + }, + "passwordPrompt": { + "message": "Volver a preguntar contraseña maestra" + }, + "passwordConfirmation": { + "message": "Confirmación de contraseña maestra" + }, + "passwordConfirmationDesc": { + "message": "Esta acción está protegida. Para continuar, vuelva a introducir su contraseña maestra para verificar su identidad." + }, + "updatedMasterPassword": { + "message": "Contraseña maestra actualizada" + }, + "updateMasterPassword": { + "message": "Actualizar contraseña maestra" + }, + "updateMasterPasswordWarning": { + "message": "Su contraseña maestra ha sido cambiada recientemente por un administrador de su organización. Para acceder a la caja fuerte, debe actualizarla ahora. Proceder le desconectará de su sesión actual, requiriendo que vuelva a iniciar sesión. Las sesiones activas en otros dispositivos pueden seguir estando activas durante una hora." + }, + "hours": { + "message": "Horas" + }, + "minutes": { + "message": "Minutos" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Las políticas de tu organización están afectando el tiempo de espera de tu caja fuerte. El máximo permitido de espera es de $HOURS$ hora(s) y de $MINUTES$ minuto(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "El tiempo de espera de tu caja fuerte excede las restricciones establecidas por tu organización." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscripción automática" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Esta organización tiene una política empresarial que lo inscribirá automáticamente en el restablecimiento de contraseña. La inscripción permitirá a los administradores de la organización cambiar su contraseña maestra." + }, + "vaultExportDisabled": { + "message": "Exportación de caja fuerte desactivada" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una o más políticas de organización le impiden exportar su caja fuerte personal." + }, + "addAccount": { + "message": "Añadir cuenta" + }, + "removeMasterPassword": { + "message": "Eliminar contraseña maestra" + }, + "removedMasterPassword": { + "message": "Contraseña maestra eliminada." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ está usando SSO con un servidor de claves autoalojado. Los miembros de esta organización ya no necesitarán una contraseña maestra para iniciar sesión.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Abandonar organización" + }, + "leaveOrganizationConfirmation": { + "message": "¿Estás seguro de que quieres dejar esta organización?" + }, + "leftOrganization": { + "message": "Has abandonado la organización." + }, + "ssoKeyConnectorUnavailable": { + "message": "No se puede acceder al conector de clave. Inténtalo de nuevo más tarde." + }, + "lockAllVaults": { + "message": "Bloquear todas las cajas fuertes" + }, + "accountLimitReached": { + "message": "No se puede iniciar sesión en más de 5 cuentas al mismo tiempo." + }, + "accountPreferences": { + "message": "Preferencias" + }, + "appPreferences": { + "message": "Ajustes de la aplicación (todas las cuentas)" + }, + "accountSwitcherLimitReached": { + "message": "Límite de cuentas alcanzado. Cierre sesión de una cuenta para añadir otra." + }, + "settingsTitle": { + "message": "Ajustes de la aplicación para $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Cambiar cuenta" + }, + "options": { + "message": "Opciones" + }, + "sessionTimeout": { + "message": "Su sesión ha expirado. Por favor, vuelva e intente iniciar sesión de nuevo." + }, + "exportingPersonalVaultTitle": { + "message": "Exportando bóveda personal" + }, + "exportingPersonalVaultDescription": { + "message": "Solo se exportarán los elementos de la bóveda personal asociados con $EMAIL$. Los elementos de la bóveda de la organización no se incluirán.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generador" + }, + "whatWouldYouLikeToGenerate": { + "message": "¿Qué deseas generar?" + }, + "passwordType": { + "message": "Tipo de contraseña" + }, + "regenerateUsername": { + "message": "Regenerar nombre de usuario" + }, + "generateUsername": { + "message": "Generar nombre de usuario" + }, + "usernameType": { + "message": "Tipo de nombre de usuario" + }, + "plusAddressedEmail": { + "message": "Dirección adicional de correo electrónico" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Aleatorio" + }, + "randomWord": { + "message": "Palabra aleatoria" + }, + "websiteName": { + "message": "Nombre del sitio web" + }, + "service": { + "message": "Servicio" + } +} diff --git a/apps/desktop/src/locales/et/messages.json b/apps/desktop/src/locales/et/messages.json new file mode 100644 index 0000000000..97ace1cc68 --- /dev/null +++ b/apps/desktop/src/locales/et/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtrid" + }, + "allItems": { + "message": "Kõik kirjed" + }, + "favorites": { + "message": "Lemmikud" + }, + "types": { + "message": "Tüübid" + }, + "typeLogin": { + "message": "Kasutajakonto andmed" + }, + "typeCard": { + "message": "Pangakaart" + }, + "typeIdentity": { + "message": "Identiteet" + }, + "typeSecureNote": { + "message": "Turvaline märkus" + }, + "folders": { + "message": "Kaustad" + }, + "collections": { + "message": "Kogumikud" + }, + "searchVault": { + "message": "Otsi hoidlast" + }, + "addItem": { + "message": "Lisa kirje" + }, + "shared": { + "message": "Jagatud" + }, + "share": { + "message": "Jaga" + }, + "moveToOrganization": { + "message": "Teisalda organisatsiooni" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ teisaldati $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vali organisatsioon, kuhu soovid seda kirjet teisaldada. Teisaldamisega saab kirje omanikuks organisatsioon. Pärast kirje teisaldamist ei ole sa enam selle otsene omanik." + }, + "attachments": { + "message": "Manused" + }, + "viewItem": { + "message": "Kirje vaatamine" + }, + "name": { + "message": "Nimi" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Uus URI" + }, + "username": { + "message": "Kasutajanimi" + }, + "password": { + "message": "Parool" + }, + "passphrase": { + "message": "Paroolifraas" + }, + "editItem": { + "message": "Kirje muutmine" + }, + "emailAddress": { + "message": "E-posti aadress" + }, + "verificationCodeTotp": { + "message": "Kinnituskood (TOTP)" + }, + "website": { + "message": "Veebileht" + }, + "notes": { + "message": "Märkmed" + }, + "customFields": { + "message": "Kohandatud väljad" + }, + "launch": { + "message": "Käivita" + }, + "copyValue": { + "message": "Kopeeri kirje", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimeeri programm pärast sisu kopeerimist" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimeerib programmi pärast kirje kopeerimist." + }, + "toggleVisibility": { + "message": "Näita sisu" + }, + "toggleCollapse": { + "message": "Ava", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kaardiomaniku nimi" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Väljastaja" + }, + "expiration": { + "message": "Aegumine" + }, + "securityCode": { + "message": "Turvakood" + }, + "identityName": { + "message": "identityName" + }, + "company": { + "message": "Ettevõte" + }, + "ssn": { + "message": "Isikukood" + }, + "passportNumber": { + "message": "Passi number" + }, + "licenseNumber": { + "message": "Litsentsi number" + }, + "email": { + "message": "E-post" + }, + "phone": { + "message": "Telefoninumber" + }, + "address": { + "message": "Aadress" + }, + "premiumRequired": { + "message": "Vajalik on Preemium versioon" + }, + "premiumRequiredDesc": { + "message": "Selle funktsiooni kasutamiseks on vajalik tasulist kontot omada." + }, + "errorOccurred": { + "message": "Ilmnes tõrge." + }, + "error": { + "message": "Viga" + }, + "january": { + "message": "Jaanuar" + }, + "february": { + "message": "Veebruar" + }, + "march": { + "message": "Märts" + }, + "april": { + "message": "Aprill" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juuni" + }, + "july": { + "message": "Juuli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktoober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Detsember" + }, + "ex": { + "message": "nt.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Pealkiri" + }, + "mr": { + "message": "Hr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Pr" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Aegumise kuu" + }, + "expirationYear": { + "message": "Aegumise aasta" + }, + "select": { + "message": "Vali" + }, + "other": { + "message": "Muu" + }, + "generatePassword": { + "message": "Loo parool" + }, + "type": { + "message": "Tüüp" + }, + "firstName": { + "message": "Eesnimi" + }, + "middleName": { + "message": "Teine eesnimi" + }, + "lastName": { + "message": "Perekonnanimi" + }, + "fullName": { + "message": "Täisnimi" + }, + "address1": { + "message": "Aadress 1" + }, + "address2": { + "message": "Aadress 2" + }, + "address3": { + "message": "Aadress 3" + }, + "cityTown": { + "message": "Linn / asula" + }, + "stateProvince": { + "message": "Maakond / vald" + }, + "zipPostalCode": { + "message": "Postiindeks" + }, + "country": { + "message": "Riik" + }, + "save": { + "message": "Salvesta" + }, + "cancel": { + "message": "Tühista" + }, + "delete": { + "message": "Kustuta" + }, + "favorite": { + "message": "Lemmik" + }, + "edit": { + "message": "Muuda" + }, + "authenticatorKeyTotp": { + "message": "Autentimise võti (TOTP)" + }, + "folder": { + "message": "Kaust" + }, + "newCustomField": { + "message": "Uus kohandatud väli" + }, + "value": { + "message": "Väärtus" + }, + "dragToSort": { + "message": "Lohista sorteerimiseks" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Peidetud" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Ühenduses", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Ühendatud väärtus", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Eemalda" + }, + "nameRequired": { + "message": "Nimi on kohustuslik." + }, + "addedItem": { + "message": "Kirje on lisatud" + }, + "editedItem": { + "message": "Kirje on muudetud" + }, + "deleteItem": { + "message": "Kustuta kirje" + }, + "deleteFolder": { + "message": "Kustuta Kaust" + }, + "deleteAttachment": { + "message": "Kustuta manus" + }, + "deleteItemConfirmation": { + "message": "Soovid tõesti selle kirje kustutada?" + }, + "deletedItem": { + "message": "Kirje on kustutatud" + }, + "overwritePasswordConfirmation": { + "message": "Oled kindel, et soovid olemasolevat parooli üle kirjutada?" + }, + "overwriteUsername": { + "message": "Kasutajanime ülekirjutamine" + }, + "overwriteUsernameConfirmation": { + "message": "Oled kindel, et soovid praegust kasutajanime üle kirjutada?" + }, + "noneFolder": { + "message": "Kaust puudub", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Kausta lisamine" + }, + "editFolder": { + "message": "Muuda kausta" + }, + "regeneratePassword": { + "message": "Genereeri parool uuesti" + }, + "copyPassword": { + "message": "Kopeeri parool" + }, + "copyUri": { + "message": "Kopeeri URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopeeri Kinnituskood (TOTP)" + }, + "length": { + "message": "Pikkus" + }, + "numWords": { + "message": "Sõnade arv" + }, + "wordSeparator": { + "message": "Sõna eraldaja" + }, + "capitalize": { + "message": "Suurtäht", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Lisa number" + }, + "close": { + "message": "Sulge" + }, + "minNumbers": { + "message": "Vähim arv numbreid" + }, + "minSpecial": { + "message": "Vähim arv spetsiaalmärke", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Väldi ebamääraseid kirjamärke" + }, + "searchCollection": { + "message": "Otsi kogumikku" + }, + "searchFolder": { + "message": "Otsi kausta" + }, + "searchFavorites": { + "message": "Otsi lemmikute hulgast" + }, + "searchType": { + "message": "Otsingu tüüp", + "description": "Search item type" + }, + "newAttachment": { + "message": "Lisa uus manus" + }, + "deletedAttachment": { + "message": "Manus on kustutatud" + }, + "deleteAttachmentConfirmation": { + "message": "Oled kindel, et soovid manuse kustutada?" + }, + "attachmentSaved": { + "message": "Manus on salvestatud." + }, + "file": { + "message": "Fail" + }, + "selectFile": { + "message": "Vali fail." + }, + "maxFileSize": { + "message": "Maksimaalne faili suurus on 500 MB." + }, + "updateKey": { + "message": "Seda funktsiooni ei saa enne krüpteerimise võtme uuendamist kasutada." + }, + "editedFolder": { + "message": "Kaust on muudetud" + }, + "addedFolder": { + "message": "Kaust on lisatud" + }, + "deleteFolderConfirmation": { + "message": "Oled kindel, et soovid seda kausta kustutada?" + }, + "deletedFolder": { + "message": "Kaust on kustutatud" + }, + "loginOrCreateNewAccount": { + "message": "Logi oma olemasolevasse kontosse sisse või loo uus konto." + }, + "createAccount": { + "message": "Konto loomine" + }, + "logIn": { + "message": "Logi sisse" + }, + "submit": { + "message": "Kinnita" + }, + "masterPass": { + "message": "Ülemparool" + }, + "masterPassDesc": { + "message": "Ülemparool on parool, millega pääsed oma kontole ligi. On äärmiselt tähtis, et ülemparool ei ununeks. Selle parooli taastamine ei ole mingil moel võimalik." + }, + "masterPassHintDesc": { + "message": "Vihje võib abiks olla olukorras, kui oled ülemparooli unustanud." + }, + "reTypeMasterPass": { + "message": "Sisesta ülemparool uuesti" + }, + "masterPassHint": { + "message": "Ülemparooli vihje (ei ole kohustuslik)" + }, + "settings": { + "message": "Seaded" + }, + "passwordHint": { + "message": "Parooli vihje" + }, + "enterEmailToGetHint": { + "message": "Ülemparooli vihje saamiseks sisesta oma konto e-posti aadress." + }, + "getMasterPasswordHint": { + "message": "Tuleta ülemparooli vihjega meelde" + }, + "emailRequired": { + "message": "E-posti aadress on nõutud." + }, + "invalidEmail": { + "message": "Vigane e-posti aadress." + }, + "masterPassRequired": { + "message": "Vajalik on ülemparooli sisestamine." + }, + "masterPassLength": { + "message": "Ülemparool peab olema vähemalt 8 tähemärgi pikkune." + }, + "masterPassDoesntMatch": { + "message": "Ülemparoolid ei ühti." + }, + "newAccountCreated": { + "message": "Sinu konto on loodud! Võid nüüd sisse logida." + }, + "masterPassSent": { + "message": "Ülemparooli vihje saadeti Sinu e-postile." + }, + "unexpectedError": { + "message": "Tekkis ootamatu viga." + }, + "itemInformation": { + "message": "Kirje andmed" + }, + "noItemsInList": { + "message": "Puuduvad kirjed, mida kuvada." + }, + "sendVerificationCode": { + "message": "Saada kinnituskood oma e-postile" + }, + "sendCode": { + "message": "Saada kood" + }, + "codeSent": { + "message": "Kood on saadetud" + }, + "verificationCode": { + "message": "Kinnituskood" + }, + "confirmIdentity": { + "message": "Jätkamiseks kinnita oma identiteet." + }, + "verificationCodeRequired": { + "message": "Nõutav on kinnituskood." + }, + "invalidVerificationCode": { + "message": "Vale kinnituskood" + }, + "continue": { + "message": "Jätka" + }, + "enterVerificationCodeApp": { + "message": "Sisesta autentimise rakendusest 6 kohaline number." + }, + "enterVerificationCodeEmail": { + "message": "Sisesta 6 kohaline number, mis saadeti e-posti aadressile $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Kinnituskood saadeti e-posti aadressile $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Jäta mind meelde" + }, + "sendVerificationCodeEmailAgain": { + "message": "Saada kinnituskood uuesti e-postile" + }, + "useAnotherTwoStepMethod": { + "message": "Kasuta teist kaheastmelist sisselogimise meetodit" + }, + "insertYubiKey": { + "message": "Sisesta oma YubiKey arvuti USB porti ja kliki sellele nupule." + }, + "insertU2f": { + "message": "Sisesta oma turvaline võti arvuti USB porti. Kui sellel on nupp, siis vajuta seda." + }, + "recoveryCodeDesc": { + "message": "Puudub ligipääs kaheastmelise kinnitamise teenusele? Kasuta Taastamise koodi, et kaheastmeline kinnitamine oma kontol välja lülitada." + }, + "recoveryCodeTitle": { + "message": "Taastamise kood" + }, + "authenticatorAppTitle": { + "message": "Autentimise rakendus" + }, + "authenticatorAppDesc": { + "message": "Kausta autentimise rakendust (näiteks Authy või Google Authenticator), et luua ajal baseeruvaid kinnituskoode.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Turvaline võti" + }, + "yubiKeyDesc": { + "message": "Kasuta kontole ligipääsemiseks YubiKey-d. See töötab YubiKey 4, 4 Nano, 4C ja NEO seadmetega." + }, + "duoDesc": { + "message": "Kinnita Duo Security abil, kasutades selleks Duo Mobile rakendust, SMS-i, telefonikõnet või U2F turvavõtit.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Kinnita organisatsiooni jaoks Duo Security abil, kasutades selleks Duo Mobile rakendust, SMS-i, telefonikõnet või U2F turvavõtit.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Kasuta mistahes WebAuthn toetavat turvalist võtit, et oma kontole ligi pääseda." + }, + "emailTitle": { + "message": "E-post" + }, + "emailDesc": { + "message": "Kinnituskoodid saadetakse e-postiga." + }, + "loginUnavailable": { + "message": "Sisselogimine ei ole saadaval" + }, + "noTwoStepProviders": { + "message": "Sellel kontol on aktiveeritud kaheastmeline kinnitus. Siiski ei toeta käesolev seade ühtegi aktiveeritud kaheastmelise kinnitamise teenust." + }, + "noTwoStepProviders2": { + "message": "Palun lisa täiendavaid kaheastmelise kinnitamise teenuse pakkujaid, mis toetavad rohkem seadmeid (näiteks mõni autentimisrakendus)." + }, + "twoStepOptions": { + "message": "Kaheastmelise sisselogimise valikud" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted bitwarden installation." + }, + "customEnvironment": { + "message": "Kohandatud keskkond" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Serveri URL" + }, + "apiUrl": { + "message": "API serveri URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Teavitus serveri URL" + }, + "iconsUrl": { + "message": "Ikoonide serveri URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Jah" + }, + "no": { + "message": "Ei" + }, + "overwritePassword": { + "message": "Kirjuta parool üle" + }, + "learnMore": { + "message": "Loe edasi" + }, + "featureUnavailable": { + "message": "Funktsioon pole saadaval" + }, + "loggedOut": { + "message": "Välja logitud" + }, + "loginExpired": { + "message": "Sessioon on aegunud." + }, + "logOutConfirmation": { + "message": "Oled kindel, et soovid välja logida?" + }, + "logOut": { + "message": "Logi välja" + }, + "addNewLogin": { + "message": "Lisa konto andmed" + }, + "addNewItem": { + "message": "Lisa uus kirje" + }, + "addNewFolder": { + "message": "Lisa uus kaust" + }, + "view": { + "message": "Vaata" + }, + "account": { + "message": "Konto" + }, + "loading": { + "message": "Laadimine..." + }, + "lockVault": { + "message": "Lukusta hoidla" + }, + "passwordGenerator": { + "message": "Parooli genereerimine" + }, + "contactUs": { + "message": "Võta ühendust" + }, + "getHelp": { + "message": "Klienditugi" + }, + "fileBugReport": { + "message": "Esita tarkvaraviga" + }, + "blog": { + "message": "Blogi" + }, + "followUs": { + "message": "Jälgi meid" + }, + "syncVault": { + "message": "Sünkroniseeri hoidla" + }, + "changeMasterPass": { + "message": "Muuda ülemparooli" + }, + "changeMasterPasswordConfirmation": { + "message": "Saad oma ülemparooli muuta bitwarden.com veebihoidlas. Soovid seda kohe teha?" + }, + "fingerprintPhrase": { + "message": "Sõrmejälje fraas", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Konto sõrmejälje fraas", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Ava Veebihoidla" + }, + "getMobileApp": { + "message": "Hangi mobiilirakendus" + }, + "getBrowserExtension": { + "message": "Hangi brauseri lisa" + }, + "syncingComplete": { + "message": "Sünkroniseerimine on lõpetatud" + }, + "syncingFailed": { + "message": "Sünkroniseerimine nurjus" + }, + "yourVaultIsLocked": { + "message": "Hoidla on lukus. Jätkamiseks sisesta ülemparool." + }, + "unlock": { + "message": "Lukusta lahti" + }, + "loggedInAsOn": { + "message": "Sisse logitud kontoga $EMAIL$ aadressil $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Vale ülemparool" + }, + "twoStepLoginConfirmation": { + "message": "Kaheastmeline kinnitamine aitab konto turvalisust tõsta. Lisaks paroolile pead kontole ligipääsemiseks kinnitama sisselogimise päringu SMS-ga, telefonikõnega, autentimise rakendusega või e-postiga. Kaheastmelist kinnitust saab sisse lülitada bitwarden.com veebihoidlas. Soovid seda kohe avada?" + }, + "twoStepLogin": { + "message": "Kaheastmeline kinnitamine" + }, + "vaultTimeout": { + "message": "Hoidla ajalõpp" + }, + "vaultTimeoutDesc": { + "message": "Vali millal saabub hoidla ajalõpp ning sooritatakse valitud tegevus." + }, + "immediately": { + "message": "Koheselt" + }, + "tenSeconds": { + "message": "10 sekundi pärast" + }, + "twentySeconds": { + "message": "20 sekundi pärast" + }, + "thirtySeconds": { + "message": "30 sekundi pärast" + }, + "oneMinute": { + "message": "1 minuti pärast" + }, + "twoMinutes": { + "message": "2 minuti pärast" + }, + "fiveMinutes": { + "message": "5 minuti pärast" + }, + "fifteenMinutes": { + "message": "15 minuti pärast" + }, + "thirtyMinutes": { + "message": "30 minuti pärast" + }, + "oneHour": { + "message": "1 tunni pärast" + }, + "fourHours": { + "message": "4 tunni pärast" + }, + "onIdle": { + "message": "Kui arvuti on kasutuseta" + }, + "onSleep": { + "message": "Kui arvuti läheb unerežiimi" + }, + "onLocked": { + "message": "Kui arvuti lukustatakse" + }, + "onRestart": { + "message": "Arvuti taaskäivitamisel" + }, + "never": { + "message": "Mitte kunagi" + }, + "security": { + "message": "Turvalisus" + }, + "clearClipboard": { + "message": "Lõikelaua puhastamine", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Puhastab automaatselt lõikelauale kopeeritud sisu.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Keela veebilehel ikoonid" + }, + "disableFaviconDesc": { + "message": "Ikoonid aitavad hoidlas olevaid veebilehti paremini ära tunda." + }, + "enableMinToTray": { + "message": "Minimeeri tegumiribale" + }, + "enableMinToTrayDesc": { + "message": "Akna minimeerimisel kuvatakse rakendus süsteemisalve ikoonina." + }, + "enableMinToMenuBar": { + "message": "Minimeeri menüüribale" + }, + "enableMinToMenuBarDesc": { + "message": "Akna minimeerimisel kuvatakse rakendus menüüriba ikoonina." + }, + "enableCloseToTray": { + "message": "Minimeeri süsteemisalvele" + }, + "enableCloseToTrayDesc": { + "message": "Akna sulgemisel kuvatakse rakendus süsteemisalve ikoonina." + }, + "enableCloseToMenuBar": { + "message": "Sulge menüüribale" + }, + "enableCloseToMenuBarDesc": { + "message": "Akna sulgemisel kuva rakendus menüüriba ikoonina." + }, + "enableTray": { + "message": "Näita süsteemisalve ikooni" + }, + "enableTrayDesc": { + "message": "Kuva süsteemisalve ikoon alati." + }, + "startToTray": { + "message": "Käivita süsteemisalves" + }, + "startToTrayDesc": { + "message": "Rakenduse esmasel käivitusel kuvatakse seda ainult süsteemisalve ikoonina." + }, + "startToMenuBar": { + "message": "Käivita menüüribal" + }, + "startToMenuBarDesc": { + "message": "Rakenduse esmasel käivitusel kuvatakse selle ikooni ainult menüüribal." + }, + "openAtLogin": { + "message": "Käivita koos arvutiga" + }, + "openAtLoginDesc": { + "message": "Bitwardeni töölaua rakendus käivitatakse automaatselt koos arvutiga." + }, + "alwaysShowDock": { + "message": "Kuva alati Dockis" + }, + "alwaysShowDockDesc": { + "message": "Bitwardeni ikooni kuvatakse alati Dockis, isegi kui see on minimeeritud menüüribale." + }, + "confirmTrayTitle": { + "message": "Kinnita süsteemisalve ikooni keelamine" + }, + "confirmTrayDesc": { + "message": "Selle seadistuse keelamine lülitab välja ka teised süsteemisalve ikooniga seonduvad võimalused." + }, + "language": { + "message": "Keel" + }, + "languageDesc": { + "message": "Rakenduse poolt kasutatava keele muutmine. Vajalik on programmi taaskäivitus." + }, + "theme": { + "message": "Teema" + }, + "themeDesc": { + "message": "Muudab rakenduse värvikujundust." + }, + "dark": { + "message": "Tume", + "description": "Dark color" + }, + "light": { + "message": "Hele", + "description": "Light color" + }, + "copy": { + "message": "Kopeeri", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Otsi värskendusi" + }, + "version": { + "message": "Versioon $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Vajalik on rakenduse taaskäivitamine" + }, + "restartToUpdateDesc": { + "message": "Versioon $VERSION_NUM$ on paigaldamiseks valmis. Paigaldamise lõpetamiseks on vajalik Bitwarden taaskäivitada. Soovid seda kohe teha?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Saadaval on värskendus" + }, + "updateAvailableDesc": { + "message": "Soovid selle kohe alla laadida?" + }, + "restart": { + "message": "Taaskäivita" + }, + "later": { + "message": "Hiljem" + }, + "noUpdatesAvailable": { + "message": "Värskendusi ei ole saadaval. Kasutusel on viimane versioon." + }, + "updateError": { + "message": "Viga uuendamisel" + }, + "unknown": { + "message": "Tundmatu" + }, + "copyUsername": { + "message": "Kopeeri kasutajanimi" + }, + "copyNumber": { + "message": "Kopeeri number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopeeri turvakood", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Preemium versioon" + }, + "premiumManage": { + "message": "Halda Preemium versiooni" + }, + "premiumManageAlert": { + "message": "Saad Preemium versiooni hallata bitwarden.com veebihoidlas. Soovid seda kohe teha?" + }, + "premiumRefresh": { + "message": "Uuenda staatust" + }, + "premiumNotCurrentMember": { + "message": "Sa ei ole hetkel preemium versiooni kasutaja." + }, + "premiumSignUpAndGet": { + "message": "Preemium versiooni lisab järgmised eelised:" + }, + "premiumSignUpStorage": { + "message": "1 GB ulatuses krüpteeritud salvestusruum." + }, + "premiumSignUpTwoStep": { + "message": "Lisavõimalused kaheastmeliseks kinnitamiseks, näiteks YubiKey, FIDO U2F ja Duo." + }, + "premiumSignUpReports": { + "message": "Parooli hügieen, konto seisukord ja andmelekete raportid aitavad hoidlat turvalisena hoida." + }, + "premiumSignUpTotp": { + "message": "TOTP kinnituskoodide (2FA) genereerija hoidlas olevatele kasutajakontodele." + }, + "premiumSignUpSupport": { + "message": "Kiirema kasutajatoe." + }, + "premiumSignUpFuture": { + "message": "Tulevased preemium funktsioonid - tasuta!" + }, + "premiumPurchase": { + "message": "Osta Preemium" + }, + "premiumPurchaseAlert": { + "message": "Saad Preemium versiooni osta bitwarden.com veebihoidlas. Soovid seda kohe teha?" + }, + "premiumCurrentMember": { + "message": "Oled preemium kasutaja!" + }, + "premiumCurrentMemberThanks": { + "message": "Täname, et toetad bitwardenit." + }, + "premiumPrice": { + "message": "Kõik see ainult $PRICE$ / aastas!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Värskendamine lõpetatud" + }, + "passwordHistory": { + "message": "Paroolide ajalugu" + }, + "clear": { + "message": "Tühjenda", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Puuduvad paroolid, mida kuvada." + }, + "undo": { + "message": "Võta tagasi" + }, + "redo": { + "message": "Tee uuesti" + }, + "cut": { + "message": "Lõika", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Kleebi", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Vali kõik" + }, + "zoomIn": { + "message": "Suumi sisse" + }, + "zoomOut": { + "message": "Suumi välja" + }, + "resetZoom": { + "message": "Taasta suurendus" + }, + "toggleFullScreen": { + "message": "Lülita täisekraanile" + }, + "reload": { + "message": "Lae uuesti" + }, + "toggleDevTools": { + "message": "Lülita Arendaja tööriistad sisse" + }, + "minimize": { + "message": "Minimeeri", + "description": "Minimize window" + }, + "zoom": { + "message": "Suurenda" + }, + "bringAllToFront": { + "message": "Too kõik ette", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Rohkem infot" + }, + "services": { + "message": "Teenused" + }, + "hideBitwarden": { + "message": "Peida Bitwarden" + }, + "hideOthers": { + "message": "Peida teised" + }, + "showAll": { + "message": "Näita kõiki" + }, + "quitBitwarden": { + "message": "Välju Bitwardenist" + }, + "valueCopied": { + "message": "$VALUE$ on kopeeritud", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Abi" + }, + "window": { + "message": "Aken" + }, + "checkPassword": { + "message": "Vaata, kas parool on lekkinud." + }, + "passwordExposed": { + "message": "See parool on erinevates andmeleketes kokku $VALUE$ korda lekkinud. Peaksid selle ära muutma.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Seda parooli ei õnnestu andmeleketest leida. Parooli edasi kasutamine peaks olema turvaline." + }, + "baseDomain": { + "message": "Baasdomeen", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domeeni nimi", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Täpne" + }, + "startsWith": { + "message": "Algab" + }, + "regEx": { + "message": "RegEx", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Sobivuse tuvastamine", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Vaike sobivuse tuvastamine", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Valik sisse" + }, + "organization": { + "message": "Organisatsioon", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Vaikimisi" + }, + "exit": { + "message": "Välju" + }, + "showHide": { + "message": "Kuva / peida", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Peida süsteemisalve" + }, + "alwaysOnTop": { + "message": "Alati kõige peal", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Uuendatud", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parool on uuendatud", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Ekspordi hoidla" + }, + "fileFormat": { + "message": "Failivorming" + }, + "warning": { + "message": "HOIATUS", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Hoidla eksportimise kinnitamine" + }, + "exportWarningDesc": { + "message": "Eksporditav fail sisaldab hoidla sisu, mis on krüpteeringuta. Seda faili ei tohiks kaua käidelda ning mitte mingil juhul ebaturvaliselt saata (näiteks e-postiga). Kustuta see koheselt pärast kasutamist." + }, + "encExportKeyWarningDesc": { + "message": "Eksporditavate andmete krüpteerimiseks kasutatakse kontol olevat krüpteerimisvõtit. Kui sa peaksid seda krüpteerimise võtit roteerima, ei saa sa järgnevalt eksporditavaid andmeid enam dekrüpteerida." + }, + "encExportAccountWarningDesc": { + "message": "Iga Bitwardeni kasutaja krüpteerimisvõti on unikaalne. Eksporditud andmeid ei saa importida teise Bitwardeni kasutajakontosse." + }, + "noOrganizationsList": { + "message": "Sa ei kuulu ühessegi organisatsiooni. Organisatsioonid võimaldavad sul kirjeid turvaliselt teiste kasutajatega jagada." + }, + "noCollectionsInList": { + "message": "Puuduvad kollektsioonid, mida kuvada." + }, + "ownership": { + "message": "Omanik" + }, + "whoOwnsThisItem": { + "message": "Kes on selle kirje omanik?" + }, + "strong": { + "message": "Tugev", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Hea", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Nõrk", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Nõrk ülemparool" + }, + "weakMasterPasswordDesc": { + "message": "Valitud ülemparool on nõrk. Oma Bitwardeni konto paremaks kaitsmiseks peaksid kasutama tugevat parooli. Oled kindel, et soovid seda parooli ülemparoolina kasutada?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Ava PIN-iga" + }, + "setYourPinCode": { + "message": "Määra Bitwardeni lahtilukustamiseks PIN kood. Rakendusest täielikult välja logides nullitakse ka PIN koodi seaded." + }, + "pinRequired": { + "message": "Nõutakse PIN koodi." + }, + "invalidPin": { + "message": "Vale PIN kood." + }, + "unlockWithWindowsHello": { + "message": "Lukusta lahti Windows Helloga" + }, + "windowsHelloConsentMessage": { + "message": "Kinnita Bitwardenisse sisselogimine." + }, + "unlockWithTouchId": { + "message": "Lukusta lahti Touch ID-ga" + }, + "touchIdConsentMessage": { + "message": "Kinnita Bitwardenisse sisselogimine." + }, + "noAutoPromptWindowsHello": { + "message": "Ära küsi käivitudes Windows Hello't." + }, + "noAutoPromptTouchId": { + "message": "Ära küsi käivitudes Touch ID'd." + }, + "lockWithMasterPassOnRestart": { + "message": "Lukusta ülemparooliga, kui rakendus taaskäivitatakse" + }, + "preferences": { + "message": "Eelistused" + }, + "enableMenuBar": { + "message": "Lülita menüüriba ikoon sisse" + }, + "enableMenuBarDesc": { + "message": "Sisselülitatuna kuvatakse süsteemisalve ikooni alati." + }, + "hideToMenuBar": { + "message": "Peida süsteemisalve ikoon" + }, + "selectOneCollection": { + "message": "Pead valima vähemalt ühe kogumiku." + }, + "premiumUpdated": { + "message": "Oled nüüd Premium konto omanik." + }, + "restore": { + "message": "Taasta" + }, + "premiumManageAlertAppStore": { + "message": "Saad oma tellimust hallata App Store kaudu. Avan App Store?" + }, + "legal": { + "message": "Juriidiline info", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Kasutustingimused" + }, + "privacyPolicy": { + "message": "Privaatsuspoliitika" + }, + "unsavedChangesConfirmation": { + "message": "Oled kindel, et soovid lahkuda? Kui sa praegu lahkud, ei salvestata sisestatud või muudetud andmeid" + }, + "unsavedChangesTitle": { + "message": "Salvestamata muudatused" + }, + "clone": { + "message": "Klooni" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Organisatsiooni seaded mõjutavad parooli genereerija sätteid." + }, + "vaultTimeoutAction": { + "message": "Hoidla ajalõpu tegevus" + }, + "vaultTimeoutActionLockDesc": { + "message": "Lukustatud hoidla nõuab taaskordseks ligipääsuks ülemparooli uuesti sisestamist." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Hoidlast väljalogimine nõuab taaskordseks ligipääsuks uut autentimist." + }, + "lock": { + "message": "Lukusta", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Prügikast", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Otsi prügikastist" + }, + "permanentlyDeleteItem": { + "message": "Kustuta kirje jäädavalt" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Oled kindel, et soovid selle kirje jäädavalt kustutada?" + }, + "permanentlyDeletedItem": { + "message": "Kirje on jäädavalt kustutatud" + }, + "restoreItem": { + "message": "Taasta kirje" + }, + "restoreItemConfirmation": { + "message": "Oled kindel, et soovid selle kirje taastada?" + }, + "restoredItem": { + "message": "Kirje on taastatud" + }, + "permanentlyDelete": { + "message": "Kustuta kirje jäädavalt" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Väljalogimine eemaldab hoidlale ligipääsu ning nõuab pärast ajalõpu perioodi uuesti autentimist. Oled kindel, et soovid seda valikut kasutada?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Ajalõpu tegevuse kinnitamine" + }, + "enterpriseSingleSignOn": { + "message": "Ettevõtte Single Sign-On" + }, + "setMasterPassword": { + "message": "Määra ülemparool" + }, + "ssoCompleteRegistration": { + "message": "SSO-ga sisselogimise kinnitamiseks tuleb määrata ülemparool. See kaitseb sinu hoidlat ning võimaldab sellele ligi pääseda." + }, + "newMasterPass": { + "message": "Uus ülemparool" + }, + "confirmNewMasterPass": { + "message": "Kinnita uus ülemparool" + }, + "masterPasswordPolicyInEffect": { + "message": "Üks või enam organisatsiooni eeskirja nõuavad, et ülemparool vastaks nendele nõudmistele:" + }, + "policyInEffectMinComplexity": { + "message": "Minimaalne keerulisuse skoor peab olema $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimaalne pikkus peab olema $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Sisaldab üht või enamat suurtähte" + }, + "policyInEffectLowercase": { + "message": "Sisaldab üht või enamat väiketähte" + }, + "policyInEffectNumbers": { + "message": "Sisaldab üht või rohkem numbreid" + }, + "policyInEffectSpecial": { + "message": "Sisaldab üht või enamat järgnevatest märkidest: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Uus ülemparool ei vasta eeskirjades väljatoodud tingimustele." + }, + "acceptPolicies": { + "message": "Märkeruudu markeerimisel nõustud järgnevaga:" + }, + "acceptPoliciesError": { + "message": "Kasutustingimuste ja Privaatsuspoliitikaga pole nõustutud." + }, + "enableBrowserIntegration": { + "message": "Lülita sisse brauseri integratsioon" + }, + "enableBrowserIntegrationDesc": { + "message": "Brauseri integratsioon on vajalik biomeetria kasutamiseks brauseris." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Brauseri integratsioon ei ole toetatud" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Paraku on brauseri integratsioon hetkel toetatud ainult Mac App Store'i versioonis." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Brauseri integratsioon ei ole toetatud" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Paraku ei ole brauseri integratsioon hetkel Microsoft Store versioonis toetatud." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Nõua brauseri integratsiooni ülekinnitamist" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "See seadistus võimaldab täiendavat kaitset, küsides brauseriga liidestamisel sõrmejälje fraasi. Sisselülitamisel nõuab see seadistus igakordset kasutaja sekkumist, kui luuakse ühendus brauseri ja töölaua rakenduse vahel." + }, + "approve": { + "message": "Kinnita" + }, + "verifyBrowserTitle": { + "message": "Brauseri ühendamise kinnitamine" + }, + "verifyBrowserDesc": { + "message": "Veendu, et kuvatav sõrmejälje fraas on identne sellega, mida kuvatakse brauseri lisas." + }, + "biometricsNotEnabledTitle": { + "message": "Biomeetria ei ole sisse lülitatud" + }, + "biometricsNotEnabledDesc": { + "message": "Selleks, et kasutada biomeetriat brauseris, peab selle esmalt Bitwardeni töölaua rakenduse seadetes sisse lülitama." + }, + "personalOwnershipSubmitError": { + "message": "Ettevõtte poliitika tõttu ei saa sa andmeid oma personaalsesse Hoidlasse salvestada. Vali Omanikuks organisatsioon ja vali mõni saadavaolevatest Kogumikest." + }, + "hintEqualsPassword": { + "message": "Parooli vihje ei saa olla sama mis parool ise." + }, + "personalOwnershipPolicyInEffect": { + "message": "Organisatsiooni poliitika on seadnud omaniku valikutele piirangu." + }, + "allSends": { + "message": "Kõik Sendid", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fail" + }, + "sendTypeText": { + "message": "Tekst" + }, + "searchSends": { + "message": "Otsi Sende", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Muuda Sendi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Minu hoidla" + }, + "text": { + "message": "Tekst" + }, + "deletionDate": { + "message": "Kustutamise kuupäev" + }, + "deletionDateDesc": { + "message": "Send kustutatakse määratud kuupäeval ja kellaajal jäädavalt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Aegumiskuupäev" + }, + "expirationDateDesc": { + "message": "Selle valimisel ei pääse sellele Sendile enam pärast määratud kuupäeva ligi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maksimaalne ligipääsude arv" + }, + "maxAccessCountDesc": { + "message": "Selle valimisel ei saa kasutajad pärast maksimaalse ligipääsude arvu saavutamist sellele Sendile enam ligi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Hetkeline ligipääsude arv" + }, + "disableSend": { + "message": "Keela see Send, et keegi ei pääseks sellele ligi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Soovi korral nõua parooli, millega Sendile ligi pääseb.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privaatne märkus selle Sendi kohta.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Sendi link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Sendi link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Sendi avamisel peida tekst automaatselt", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send on loodud", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Muudetud", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send on kustutatud", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Uus Parool" + }, + "whatTypeOfSend": { + "message": "Mis tüüpi Send see on?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Loo Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Tekst, mida soovid saata." + }, + "sendFileDesc": { + "message": "Fail, mida soovid saata." + }, + "days": { + "message": "$DAYS$ päeva", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 päev" + }, + "custom": { + "message": "Kohandatud" + }, + "deleteSendConfirmation": { + "message": "Soovid tõesti selle Sendi kustutada?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopeeri Sendi link lõikelauale", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Salvestamisel kopeeri Sendi jagamise link lõikepuhvrisse." + }, + "sendDisabled": { + "message": "Send on väljalülitatud", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Ettevõtte poliitika kohaselt saad ainult olemasolevat Sendi kustutada.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopeeri link" + }, + "disabled": { + "message": "Keelatud" + }, + "maxAccessCountReached": { + "message": "Maksimaalne ligipääsude arv on saavutatud" + }, + "expired": { + "message": "Aegunud" + }, + "pendingDeletion": { + "message": "Kustutamise ootel" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn kinnitamine" + }, + "hideEmail": { + "message": "Ära näita saajatele minu e-posti aadressi." + }, + "sendOptionsPolicyInEffect": { + "message": "Organisatsiooni seaded mõjutavad sinu Sendi sätteid." + }, + "emailVerificationRequired": { + "message": "Vajalik on e-posti kinnitamine" + }, + "emailVerificationRequiredDesc": { + "message": "Enne selle funktsiooni kasutamist pead oma e-posti kinnitama." + }, + "passwordPrompt": { + "message": "Nõutav on ülemparool" + }, + "passwordConfirmation": { + "message": "Ülemparooli kinnitamine" + }, + "passwordConfirmationDesc": { + "message": "See tegevus on kaitstud. Jätkamiseks sisesta oma ülemparool." + }, + "updatedMasterPassword": { + "message": "Uuendas ülemparooli" + }, + "updateMasterPassword": { + "message": "Ülemparooli uuendamine" + }, + "updateMasterPasswordWarning": { + "message": "Organisatsiooni administraator muutis hiljuti sinu ülemparooli. Hoidlale ligi pääsemiseks pead seda nüüd uuendama. Jätkates logitakse sind käimasolevast sessioonist välja, misjärel nõutakse uuesti sisselogimist. Teistes seadmetes olevad aktiivsed sessioonid jäävad aktiivseks kuni üheks tunniks." + }, + "hours": { + "message": "Tundi" + }, + "minutes": { + "message": "Minutit" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Organisatsiooni poliitikad mõjutavad sinu hoidla ajalõppu. Maksimaalne lubatud hoidla ajalõpp on $HOURS$ tund(i) ja $MINUTES$ minut(it)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Valitud hoidla ajalõpp ei ole organisatsiooni poolt määratud reeglitega kooskõlas." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automaatne liitumine" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Selle organisatsiooni poliitika kohaselt liidetakse sind automaatselt ülemparooli lähtestamise funktsiooniga. Liitumisel saavad organisatsiooni administraatorid sinu ülemparooli muuta." + }, + "vaultExportDisabled": { + "message": "Hoidla eksportimine on väljalülitatud" + }, + "personalVaultExportPolicyInEffect": { + "message": "Üks või enam organisatsiooni poliitikat ei võimalda sul oma personaalset hoidlat eksportida." + }, + "addAccount": { + "message": "Lisa konto" + }, + "removeMasterPassword": { + "message": "Eemalda ülemparool" + }, + "removedMasterPassword": { + "message": "Ülemparool on eemaldatud." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ kasutab SSO-d koos enda majutatud võtmeserveriga. Selle organisatsiooni liikmed ei pea sisselogimisel enam ülemparooli kasutama.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Lahku organisatsioonist" + }, + "leaveOrganizationConfirmation": { + "message": "Kas oled kindel, et soovid sellest organisatsioonist lahkuda?" + }, + "leftOrganization": { + "message": "Oled organisatsioonist lahkunud." + }, + "ssoKeyConnectorUnavailable": { + "message": "Ühenduse loomine ebaõnnestus. Proovi hiljem uuesti." + }, + "lockAllVaults": { + "message": "Lukusta kõik hoidlad" + }, + "accountLimitReached": { + "message": "Korraga ei tohi olla sisse logitud rohkem kui 5 kontot." + }, + "accountPreferences": { + "message": "Eelistused" + }, + "appPreferences": { + "message": "Rakenduse seaded (kõik kontod)" + }, + "accountSwitcherLimitReached": { + "message": "Kontode limiit on saavutatud. Teise konto lisamiseks pead esmalt välja logima." + }, + "settingsTitle": { + "message": "Rakenduse seaded e-postile $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Vaheta kontot" + }, + "options": { + "message": "Valikud" + }, + "sessionTimeout": { + "message": "Sessioon on aegunud. Palun mine tagasi ja proovi uuesti sisse logida." + }, + "exportingPersonalVaultTitle": { + "message": "Personaalse hoidla eksportimine" + }, + "exportingPersonalVaultDescription": { + "message": "Ainult personaalsed $EMAIL$ alla kuuluvad kirjed eksportidakse. Organisatsiooni kirjeid ei ekspordita.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Genereerija" + }, + "whatWouldYouLikeToGenerate": { + "message": "Mida sa soovid genereerida?" + }, + "passwordType": { + "message": "Parooli tüüp" + }, + "regenerateUsername": { + "message": "Genereeri kasutajanimi uuesti" + }, + "generateUsername": { + "message": "Genereeri kasutajanimi" + }, + "usernameType": { + "message": "Kasutajanime tüüp" + }, + "plusAddressedEmail": { + "message": "Lisaks e-post" + }, + "plusAddressedEmailDesc": { + "message": "Kasuta e-posti teenuspakkuja alamadressimise võimalusi." + }, + "catchallEmail": { + "message": "Kogumisaadress" + }, + "catchallEmailDesc": { + "message": "Kasuta domeenipõhist kogumisaadressi." + }, + "random": { + "message": "Juhuslik" + }, + "randomWord": { + "message": "Juhuslik sõna" + }, + "websiteName": { + "message": "Veebilehe nimi" + }, + "service": { + "message": "Teenus" + } +} diff --git a/apps/desktop/src/locales/fa/messages.json b/apps/desktop/src/locales/fa/messages.json new file mode 100644 index 0000000000..8642c5b04e --- /dev/null +++ b/apps/desktop/src/locales/fa/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "فیلترها" + }, + "allItems": { + "message": "تمام موارد" + }, + "favorites": { + "message": "مورد علاقه" + }, + "types": { + "message": "انواع" + }, + "typeLogin": { + "message": "ورود" + }, + "typeCard": { + "message": "کارت" + }, + "typeIdentity": { + "message": "مشخصات" + }, + "typeSecureNote": { + "message": "یادداشت امن" + }, + "folders": { + "message": "پوشه‌ها" + }, + "collections": { + "message": "مجموعه‌ها" + }, + "searchVault": { + "message": "جستجوی گاوصندوق" + }, + "addItem": { + "message": "افزودن مورد" + }, + "shared": { + "message": "اشتراک گذاری شد" + }, + "share": { + "message": "اشتراک‌گذاری" + }, + "moveToOrganization": { + "message": "انتقال به سازمان" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ منتقل شد به $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "سازمانی را انتخاب کنید که می خواهید این مورد را به آن منتقل کنید. انتقال به یک سازمان، مالکیت مورد را به آن سازمان منتقل می کند. پس از انتقال این مورد، دیگر مالک مستقیم آن نخواهید بود." + }, + "attachments": { + "message": "پیوست‌ها" + }, + "viewItem": { + "message": "مشاهده مورد" + }, + "name": { + "message": "نام" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "URI جدید" + }, + "username": { + "message": "نام کاربری" + }, + "password": { + "message": "کلمه عبور" + }, + "passphrase": { + "message": "عبارت عبور" + }, + "editItem": { + "message": "ویرایش مورد" + }, + "emailAddress": { + "message": "نشانی رایانامه" + }, + "verificationCodeTotp": { + "message": "کد تایید (TOTP)" + }, + "website": { + "message": "وب سایت" + }, + "notes": { + "message": "یادداشت‌ها" + }, + "customFields": { + "message": "فیلدهای سفارشی" + }, + "launch": { + "message": "راه اندازی" + }, + "copyValue": { + "message": "رونوشت مقدار", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "پایین کشیدن پنجره موقع کپی کردن در کلیپ بورد" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "پایین کشیدن پنجره موقع کپی کردن اطلاعات یک مورد در کلیپ بورد." + }, + "toggleVisibility": { + "message": "نمایش" + }, + "toggleCollapse": { + "message": "باز و بسته کردن", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "نام صاحب کارت" + }, + "number": { + "message": "شماره" + }, + "brand": { + "message": "نام تجاری" + }, + "expiration": { + "message": "انقضاء" + }, + "securityCode": { + "message": "کد امنیتی" + }, + "identityName": { + "message": "نام شناسایی" + }, + "company": { + "message": "شرکت" + }, + "ssn": { + "message": "شماره امنیتی اجتماعی" + }, + "passportNumber": { + "message": "شماره پاسپورت" + }, + "licenseNumber": { + "message": "شماره مجوز" + }, + "email": { + "message": "رایانامه" + }, + "phone": { + "message": "تلفن" + }, + "address": { + "message": "نشانی" + }, + "premiumRequired": { + "message": "در نسخه پرمیوم کار می‌کند" + }, + "premiumRequiredDesc": { + "message": "برای استفاده از این ویژگی عضویت پرمیوم لازم است." + }, + "errorOccurred": { + "message": "خطایی رخ داده است." + }, + "error": { + "message": "خطا" + }, + "january": { + "message": "ژانویه" + }, + "february": { + "message": "فوریه" + }, + "march": { + "message": "مارس" + }, + "april": { + "message": "آوریل" + }, + "may": { + "message": "مِی" + }, + "june": { + "message": "ژوئن" + }, + "july": { + "message": "جولای" + }, + "august": { + "message": "آگوست‌" + }, + "september": { + "message": "سپتامبر" + }, + "october": { + "message": "اکتبر" + }, + "november": { + "message": "نوامبر" + }, + "december": { + "message": "دسامبر" + }, + "ex": { + "message": "مثال.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "عنوان" + }, + "mr": { + "message": "آقا" + }, + "mrs": { + "message": "بانو" + }, + "ms": { + "message": "خانم" + }, + "dr": { + "message": "دکتر" + }, + "expirationMonth": { + "message": "ماه انقضاء" + }, + "expirationYear": { + "message": "سال انقضاء" + }, + "select": { + "message": "انتخاب" + }, + "other": { + "message": "ساير" + }, + "generatePassword": { + "message": "تولید کلمه عبور" + }, + "type": { + "message": "نوع" + }, + "firstName": { + "message": "نام" + }, + "middleName": { + "message": "نام میانی" + }, + "lastName": { + "message": "نام خانوادگی" + }, + "fullName": { + "message": "نام کامل" + }, + "address1": { + "message": "نشانی ۱" + }, + "address2": { + "message": "نشانی ۲" + }, + "address3": { + "message": "نشانی ۳" + }, + "cityTown": { + "message": "شهر / شهرک" + }, + "stateProvince": { + "message": "ایالت / استان" + }, + "zipPostalCode": { + "message": "کد پستی" + }, + "country": { + "message": "کشور" + }, + "save": { + "message": "ذخیره" + }, + "cancel": { + "message": "انصراف" + }, + "delete": { + "message": "حذف" + }, + "favorite": { + "message": "مورد علاقه" + }, + "edit": { + "message": "ویرایش" + }, + "authenticatorKeyTotp": { + "message": "کلید تاییدکننده (TOTP)" + }, + "folder": { + "message": "پوشه" + }, + "newCustomField": { + "message": "فیلد سفارشی جدید" + }, + "value": { + "message": "مقدار" + }, + "dragToSort": { + "message": "برای مرتب کردن بکشید" + }, + "cfTypeText": { + "message": "متن" + }, + "cfTypeHidden": { + "message": "مخفی" + }, + "cfTypeBoolean": { + "message": "بولی" + }, + "cfTypeLinked": { + "message": "لینک شده", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "ارزش لینک شده", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "حذف" + }, + "nameRequired": { + "message": "نام ضروری است." + }, + "addedItem": { + "message": "مورد افزوده شد" + }, + "editedItem": { + "message": "مورد ویرایش شد" + }, + "deleteItem": { + "message": "حذف مورد" + }, + "deleteFolder": { + "message": "حذف پوشه" + }, + "deleteAttachment": { + "message": "حذف پیوست" + }, + "deleteItemConfirmation": { + "message": "آیا مطمئن هستید که می‌خواهید این مورد را حذف کنید؟" + }, + "deletedItem": { + "message": "مورد حذف شد" + }, + "overwritePasswordConfirmation": { + "message": "آیا از بازنویسی بر روی پسورد فعلی مطمئن هستید؟" + }, + "overwriteUsername": { + "message": "بازنویسی نام کاربری" + }, + "overwriteUsernameConfirmation": { + "message": "آیا از بازنویسی نام کاربری فعلی مطمئن هستید؟" + }, + "noneFolder": { + "message": "بدون پوشه", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "افزودن پوشه" + }, + "editFolder": { + "message": "ويرايش پوشه" + }, + "regeneratePassword": { + "message": "تولید دوباره کلمه عبور" + }, + "copyPassword": { + "message": "رونوشت کلمه عبور" + }, + "copyUri": { + "message": "رونوشت URI" + }, + "copyVerificationCodeTotp": { + "message": "کپی کد تأیید (TOTP)" + }, + "length": { + "message": "طول" + }, + "numWords": { + "message": "تعداد کلمات" + }, + "wordSeparator": { + "message": "جداکننده کلمات" + }, + "capitalize": { + "message": "بزرگ نوشتن حرف اول", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "شامل عدد" + }, + "close": { + "message": "بستن" + }, + "minNumbers": { + "message": "حداقل اعداد" + }, + "minSpecial": { + "message": "حداقل حرف خاص", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "از کاراکترهای مبهم اجتناب شود" + }, + "searchCollection": { + "message": "جستجوی مجموعه" + }, + "searchFolder": { + "message": "جستجوی پوشه" + }, + "searchFavorites": { + "message": "جستجوی مورد علاقه‌ها" + }, + "searchType": { + "message": "نوع جستجو", + "description": "Search item type" + }, + "newAttachment": { + "message": "افزودن پیوست جدید" + }, + "deletedAttachment": { + "message": "پیوست حذف شد" + }, + "deleteAttachmentConfirmation": { + "message": "آیا از پاک کردن این پیوست مطمئن هستید؟" + }, + "attachmentSaved": { + "message": "پیوست ذخیره شد." + }, + "file": { + "message": "پرونده" + }, + "selectFile": { + "message": "ﺍﻧﺘﺨﺎﺏ یک ﭘﺮﻭﻧﺪﻩ." + }, + "maxFileSize": { + "message": "بیشترین حجم فایل ۱۰۰ مگابایت است." + }, + "updateKey": { + "message": "تا زمانی که کد رمزنگاری را بروز نکنید نمی‌توانید از این قابلیت استفاده کنید." + }, + "editedFolder": { + "message": "پوشه ویرایش شد" + }, + "addedFolder": { + "message": "پوشه اضافه شد" + }, + "deleteFolderConfirmation": { + "message": "آیا از حذف این پوشه اطمینان دارید؟" + }, + "deletedFolder": { + "message": "پوشه حذف شد" + }, + "loginOrCreateNewAccount": { + "message": "وارد شوید یا یک حساب کاربری بسازید تا به گاوصندوق امنتان دسترسی یابید." + }, + "createAccount": { + "message": "ایجاد حساب کاربری" + }, + "logIn": { + "message": "ورود" + }, + "submit": { + "message": "ثبت" + }, + "masterPass": { + "message": "کلمه عبور اصلی" + }, + "masterPassDesc": { + "message": "کلمه عبور اصلی کلمه عبوری است که شما برای دسترسی به گاوصندوق خود استفاده می‌کنید. بیاد داشتن کلمه عبور اصلی بسیار اهمیت دارد. اگر آن را فراموش کنید هیچ راهی برای بازگردانی آن وجود ندارد." + }, + "masterPassHintDesc": { + "message": "راهنمای کلمه عبور اصلی می تواند کمک کند تا در صورت فراموشی آن را بیاد بیاورید." + }, + "reTypeMasterPass": { + "message": "نوشتن دوباره کلمه عبور اصلی" + }, + "masterPassHint": { + "message": "راهنمای کلمه عبور اصلی (اختیاری)" + }, + "settings": { + "message": "تنظیمات" + }, + "passwordHint": { + "message": "راهنمای کلمه عبور" + }, + "enterEmailToGetHint": { + "message": "برای دریافت راهنمای کلمه عبور اصلی خود آدرس رایانامه‌تان را وارد کنید." + }, + "getMasterPasswordHint": { + "message": "دریافت راهنمای کلمه عبور اصلی" + }, + "emailRequired": { + "message": "نشانی رایانامه ضروری است." + }, + "invalidEmail": { + "message": "نشانی رایانامه نامعتبر است." + }, + "masterPassRequired": { + "message": "کلمه عبور اصلی ضروری است." + }, + "masterPassLength": { + "message": "طول کلمه عبور اصلی باید حداقل ۸ کاراکتر باشد." + }, + "masterPassDoesntMatch": { + "message": "کلمه عبور اصلی با تکرار آن مطابقت ندارد." + }, + "newAccountCreated": { + "message": "حساب جدید شما ساخته شد! حالا می‌توانید وارد شوید." + }, + "masterPassSent": { + "message": "ما یک رایانامه همراه با راهنمای کلمه عبور اصلی برایتان ارسال کردیم." + }, + "unexpectedError": { + "message": "یک خطای غیر منتظره رخ داده است." + }, + "itemInformation": { + "message": "اطلاعات مورد" + }, + "noItemsInList": { + "message": "هیچ موردی برای نمایش وجود ندارد." + }, + "sendVerificationCode": { + "message": "ارسال یک کد تأیید به ایمیل شما" + }, + "sendCode": { + "message": "ارسال کد" + }, + "codeSent": { + "message": "کد ارسال شد" + }, + "verificationCode": { + "message": "کد تایید" + }, + "confirmIdentity": { + "message": "برای ادامه هویت خود را تأیید کنید." + }, + "verificationCodeRequired": { + "message": "کد تایید مورد نیاز است." + }, + "invalidVerificationCode": { + "message": "کد تایید نامعتبر" + }, + "continue": { + "message": "ادامه" + }, + "enterVerificationCodeApp": { + "message": "کد تایید ۶ رقمی را از برنامه تایید کننده‌تان وارد کنید." + }, + "enterVerificationCodeEmail": { + "message": "کد تایید ۶ رقمی که به $EMAIL$ ارسال شد را وارد کنید.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "رایانامه تایید به $EMAIL$ ارسال شد.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "مرا به خاطر بسپار" + }, + "sendVerificationCodeEmailAgain": { + "message": "ارسال دوباره رایانامه کد تایید" + }, + "useAnotherTwoStepMethod": { + "message": "استفاده از روش ورود دو مرحله‌ای دیگر" + }, + "insertYubiKey": { + "message": "YubiKey خود را وارد پورت USB رایانه کنید، بعد دکمه آن را بفشارید." + }, + "insertU2f": { + "message": "کلید امنیتی خود را وارد پورت USB رایانه کنید، اگر دکمه‌ای دارد آن را بفشارید." + }, + "recoveryCodeDesc": { + "message": "دسترسی به تمامی ارائه‌دهندگان دو مرحله‌ای را از دست داده‌اید؟ از کد بازیابی خود برای غیرفعال‌سازی ارائه‌دهندگان دو مرحله‌ای حسابتان استفاده کنید." + }, + "recoveryCodeTitle": { + "message": "کد بازیابی" + }, + "authenticatorAppTitle": { + "message": "برنامه تاییدکننده" + }, + "authenticatorAppDesc": { + "message": "از یک برنامه تاییدکننده (همانند Authy یا Google Authenticator) استفاده کنید تا کدهای تایید بر پایه زمان تولید کنید.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "کلید امنیتی YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "از یک YubiKey برای دسترسی به حسابتان استفاده کنید. همراه با دستگاه‌های YubiKey 4،4 Nano، NEO کار میکند." + }, + "duoDesc": { + "message": "با Duo Security با استفاده از برنامه تلفن همراه، پیامک، تماس تلفنی، یا کلید امنیتی U2F تایید کنید.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "از Duo Security با استفاده از برنامه تلفن همراه، پیامک، تماس تلفنی یا کلید امنیتی U2F برای تایید سازمان خود استفاده کنید.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "برای دسترسی به حساب خود از هر کلید امنیتی فعال شده WebAuthn استفاده کنید." + }, + "emailTitle": { + "message": "رایانامه" + }, + "emailDesc": { + "message": "کد تایید برایتان ارسال می‌شود." + }, + "loginUnavailable": { + "message": "ورود به سیستم موجود نیست" + }, + "noTwoStepProviders": { + "message": "ورود دو مرحله‌ای برای این حساب فعال است، با این حال، هیچ یک از ارائه‌دهندگان دو مرحله‌ای پیکربندی شده توسط این دستگاه پشتیبانی‌نمی شوند." + }, + "noTwoStepProviders2": { + "message": "لطفا ارائه‌دهندگان دیگری را که بهتر در سایر دستگاه‌ها پشتیبانی می‌شوند اضافه کنید (همانند یک برنامه تاییدکننده)." + }, + "twoStepOptions": { + "message": "گزینه‌های ورود دو مرحله‌ای" + }, + "selfHostedEnvironment": { + "message": "محیط خود میزبان" + }, + "selfHostedEnvironmentFooter": { + "message": "آدرس اینترنتی پایه نصب Bitwarden میزبانی شده را مشخص کنید." + }, + "customEnvironment": { + "message": "محیط سفارشی" + }, + "customEnvironmentFooter": { + "message": "برای کاربران پیشرفته. شما می‌توانید آدرس پایه هر سرویس را به صورت مستقل تعیین کنید." + }, + "baseUrl": { + "message": "نشانی سرور" + }, + "apiUrl": { + "message": "نشانی API سرور" + }, + "webVaultUrl": { + "message": "نشانی سرور گاوصندوق وب" + }, + "identityUrl": { + "message": "نشانی سرور شناسایی" + }, + "notificationsUrl": { + "message": "نشانی سرور اعلان‌ها" + }, + "iconsUrl": { + "message": "نشانی سرور آیکون‌ها" + }, + "environmentSaved": { + "message": "نشانی‌های اینترنتی محیط ذخیره شدند." + }, + "ok": { + "message": "تایید" + }, + "yes": { + "message": "بله" + }, + "no": { + "message": "خیر" + }, + "overwritePassword": { + "message": "بازنویسی کلمه عبور" + }, + "learnMore": { + "message": "بیشتر بدانید" + }, + "featureUnavailable": { + "message": "ویژگی موجود نیست" + }, + "loggedOut": { + "message": "خارج شد" + }, + "loginExpired": { + "message": "نشست ورود شما منقضی شده است." + }, + "logOutConfirmation": { + "message": "آیا مطمئنید که می‌خواهید خارج شوید؟" + }, + "logOut": { + "message": "خروج" + }, + "addNewLogin": { + "message": "افزودن ورود جدید" + }, + "addNewItem": { + "message": "افزودن مورد جدید" + }, + "addNewFolder": { + "message": "افزودن پوشه جدید" + }, + "view": { + "message": "مشاهده" + }, + "account": { + "message": "حساب" + }, + "loading": { + "message": "درحال بارگذاری..." + }, + "lockVault": { + "message": "قفل کردن گاوصندوق" + }, + "passwordGenerator": { + "message": "تولید کننده کلمه عبور" + }, + "contactUs": { + "message": "تماس با ما" + }, + "getHelp": { + "message": "کمک گرفتن" + }, + "fileBugReport": { + "message": "گزارش یک مشکل" + }, + "blog": { + "message": "وبلاگ" + }, + "followUs": { + "message": "ﻣﺎ ﺭﺍ ﺩﻧﺒﺎﻝ ﮐﻨﻴﺪ" + }, + "syncVault": { + "message": "همگام سازی گاوصندوق" + }, + "changeMasterPass": { + "message": "تغییر کلمه عبور اصلی" + }, + "changeMasterPasswordConfirmation": { + "message": "شما می‌توانید کلمه عبور اصلی خود را در bitwarden.com تغییر دهید. آیا می‌خواهید از سایت بازدید کنید؟" + }, + "fingerprintPhrase": { + "message": "عبارت اثر انگشت", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "عبارت اثر انگشت حساب شما", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "برو به گاوصندق وب" + }, + "getMobileApp": { + "message": "دریافت برنامه تلفن همراه" + }, + "getBrowserExtension": { + "message": "دریافت افزونه مرورگر" + }, + "syncingComplete": { + "message": "همگام سازی کامل شد" + }, + "syncingFailed": { + "message": "همگام سازی ناموفق بود" + }, + "yourVaultIsLocked": { + "message": "گاوصندوق شما فقل شد. برای ادامه کلمه عبور اصلی را وارد کنید." + }, + "unlock": { + "message": "باز کردن قفل" + }, + "loggedInAsOn": { + "message": "وارد شده با $EMAIL$ در $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "کلمه عبور اصلی نامعتبر است" + }, + "twoStepLoginConfirmation": { + "message": "ورودی دو مرحله‌ای باعث می‌شود که حساب کاربری شما با استفاده از یک دستگاه دیگر مانند کلید امنیتی، برنامه تایید هویت، پیامک، تماس تلفنی و یا رایانامه، اعتبار خود را با ایمنی بیشتر ثابت کند. ورود دو مرحله‌ای می‌تواند در bitwarden.com فعال شود. آیا می‌خواهید از سایت بازدید کنید؟" + }, + "twoStepLogin": { + "message": "ورود دو مرحله‌ای" + }, + "vaultTimeout": { + "message": "متوقف شدن گاو‌صندوق" + }, + "vaultTimeoutDesc": { + "message": "انتخاب کنید که گاو‌صندوق شما چه موقع متوقف شود و عملکرد انتخاب شده را انجام دهد." + }, + "immediately": { + "message": "بلافاصله" + }, + "tenSeconds": { + "message": "۱۰ ثانیه" + }, + "twentySeconds": { + "message": "۲۰ ثانیه" + }, + "thirtySeconds": { + "message": "۳۰ ثانیه" + }, + "oneMinute": { + "message": "۱ دقیقه" + }, + "twoMinutes": { + "message": "۲ دقیقه" + }, + "fiveMinutes": { + "message": "۵ دقیقه" + }, + "fifteenMinutes": { + "message": "۱۵ دقیقه" + }, + "thirtyMinutes": { + "message": "۳۰ دقیقه" + }, + "oneHour": { + "message": "۱ ساعت" + }, + "fourHours": { + "message": "۴ ساعت" + }, + "onIdle": { + "message": "هنگام بیکاری سیستم" + }, + "onSleep": { + "message": "هنگام خواب سیستم" + }, + "onLocked": { + "message": "هنگام قفل سیستم" + }, + "onRestart": { + "message": "هنگام راه اندازی مجدد" + }, + "never": { + "message": "هرگز" + }, + "security": { + "message": "امنیت" + }, + "clearClipboard": { + "message": "پاک‌سازی کلیپ‌برد", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "به صورت خودکار، مقادیر رونوشت شده را از کلیپ‌برد پاک کن.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "غیرفعال‌سازی آیکون‌های وبسایت" + }, + "disableFaviconDesc": { + "message": "آیکون‌های وبسایت یک تصویر قابل تشخیص در کنار هر داده ورودی ارائه می‌دهد." + }, + "enableMinToTray": { + "message": "کوچک کردن به نماد Tray" + }, + "enableMinToTrayDesc": { + "message": "هنگام کوچک‌کردن پنچره، یک نماد در قسمت نمادهای سیستم بجای آن نشان بده." + }, + "enableMinToMenuBar": { + "message": "به نوار منو کوچک کنید" + }, + "enableMinToMenuBarDesc": { + "message": "هنگام کوچک کردن پنجره، به جای آن یک نماد در نوار منو نشان بده." + }, + "enableCloseToTray": { + "message": "بستن به نماد Tray" + }, + "enableCloseToTrayDesc": { + "message": "هنگام بستن پنچره، یک نماد در قسمت نمادهای سیستم بجای آن نشان بده." + }, + "enableCloseToMenuBar": { + "message": "بستن به نوار منو" + }, + "enableCloseToMenuBarDesc": { + "message": "هنگام بستن پنجره، به جای آن یک نماد در نوار منو نشان دهید." + }, + "enableTray": { + "message": "فعال کردن نماد Tray" + }, + "enableTrayDesc": { + "message": "همیشه یک نماد در قسمت نمادهای سیستم نشان بده." + }, + "startToTray": { + "message": "در زمان شروع، به نماد Tray برو" + }, + "startToTrayDesc": { + "message": "زمانی که برنامه برای بار اول شروع می‌شود، فقط یک نماد در نمادهای سیستم نشان بده." + }, + "startToMenuBar": { + "message": "شروع به نوار منو" + }, + "startToMenuBarDesc": { + "message": "زمانی که برنامه برای بار اول شروع می‌شود، فقط یک نماد در نوار منو نشان بده." + }, + "openAtLogin": { + "message": "هنگام ورود به سیستم به طور خودکار شروع کنید" + }, + "openAtLoginDesc": { + "message": "برنامه دستکتاپ Bitwarden را به طور خودکار هنگام ورود به سیستم شروع کنید." + }, + "alwaysShowDock": { + "message": "همیشه در داک نشان بده" + }, + "alwaysShowDockDesc": { + "message": "نماد Bitwarden را در داک نمایش بده حتی زمانی که به نوار منو کوچک شود." + }, + "confirmTrayTitle": { + "message": "غیرفعال کردن tray را تأیید کنید" + }, + "confirmTrayDesc": { + "message": "غیرفعال کردن این تنظیم تمام تنظیمات مربوط به tray را غیرفعال می کند." + }, + "language": { + "message": "زبان" + }, + "languageDesc": { + "message": "تغییر زبان مورد استفاده برنامه انجام شد. نیاز به راه اندازی مجدد." + }, + "theme": { + "message": "پوسته" + }, + "themeDesc": { + "message": "تغییر رنگ پوسته برنامه." + }, + "dark": { + "message": "تیره", + "description": "Dark color" + }, + "light": { + "message": "روشن", + "description": "Light color" + }, + "copy": { + "message": "رونوشت", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "بررسی برای بروزرسانی‌ها" + }, + "version": { + "message": "نسخه $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "برای بروزرسانی راه اندازی مجدد کنید" + }, + "restartToUpdateDesc": { + "message": "نسخه $VERSION_NUM$ آماده نصب است. برای تکمیل نصب باید Bitwarden را مجددا راه اندازی کنید. آیا تمایل به راه اندازی مجدد و بروزرسانی دارید؟", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "بروزرسانی موجود است" + }, + "updateAvailableDesc": { + "message": "یک بروزرسانی یافت شد. مایل به دانلود و نصب آن هستید؟" + }, + "restart": { + "message": "راه اندازی مجدد" + }, + "later": { + "message": "بعدا" + }, + "noUpdatesAvailable": { + "message": "در حال حاظر هیچ بروزرسانی در دسترس نمی‌باشد. شما در در حال استفاده از آخرین نسخه هستید." + }, + "updateError": { + "message": "خطا در بروزرسانی" + }, + "unknown": { + "message": "ناشناخته" + }, + "copyUsername": { + "message": "رونوشت نام کاربری" + }, + "copyNumber": { + "message": "رونوشت شماره", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "رونوشت کد امنیتی", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "عضویت پریمیوم" + }, + "premiumManage": { + "message": "مدیریت عضویت" + }, + "premiumManageAlert": { + "message": "شما می‌توانید عضویت خود را در نسخه وب گاوصندوق در bitwarden.com مدیریت کنید. آیا مایل به دیدن وبسایت هستید؟" + }, + "premiumRefresh": { + "message": "نوسازی عضویت" + }, + "premiumNotCurrentMember": { + "message": "شما در حال حاظر کاربر پریمیوم نیستید." + }, + "premiumSignUpAndGet": { + "message": "ثبت نام برای عضویت پرمیوم و گرفتن:" + }, + "premiumSignUpStorage": { + "message": "۱ گیگابایت فضای ذخیره‌سازی رمزنگاری شده برای پرونده‌های پیوست." + }, + "premiumSignUpTwoStep": { + "message": "گزینه‌های ورود دو مرحله‌ای اضافی مانند YubiKey, FIDO U2F و Duo." + }, + "premiumSignUpReports": { + "message": "دانش کلمه عبور، سلامت حساب کاربری و گزارش‌های نقص اطلاعات، برای حفظ امنیت گاوصندوق شما." + }, + "premiumSignUpTotp": { + "message": "تولید کننده کد تایید (2FA) از نوع TOTP برای ورودهای موجود در گاوصندوقتان." + }, + "premiumSignUpSupport": { + "message": "پشتیبانی از مشتری با اولویت." + }, + "premiumSignUpFuture": { + "message": "تمام ویژگی‌های پریمیوم آینده. به زودی بیشتر!" + }, + "premiumPurchase": { + "message": "خرید پریمیوم" + }, + "premiumPurchaseAlert": { + "message": "شما می‌توانید عضویت پریمیوم را از گاوصندوق وب bitwarden.com خریداری کنید. آیا مایلید اکنون از وبسایت بازید کنید؟" + }, + "premiumCurrentMember": { + "message": "شما یک عضو پریمیوم هستید!" + }, + "premiumCurrentMemberThanks": { + "message": "برای حمایتتان از Bitwarden سپاسگزاریم." + }, + "premiumPrice": { + "message": "تمامش فقط $PRICE$ در سال!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "نوسازی کامل شد" + }, + "passwordHistory": { + "message": "تاریخچه کلمه عبور" + }, + "clear": { + "message": "پاک کردن", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "هیچ کلمه عبوری در لیست وجود ندارد." + }, + "undo": { + "message": "بازگرداندن" + }, + "redo": { + "message": "انجام مجدد" + }, + "cut": { + "message": "بریدن", + "description": "Cut to clipboard" + }, + "paste": { + "message": "جای‌گذاری", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "انتخاب همه" + }, + "zoomIn": { + "message": "بزرگ‌نمایی" + }, + "zoomOut": { + "message": "کوچک‌نمایی" + }, + "resetZoom": { + "message": "بازگردانی بزرگ‌نمایی" + }, + "toggleFullScreen": { + "message": "تغییر به حالت تمام صفحه" + }, + "reload": { + "message": "بارگذاری مجدد" + }, + "toggleDevTools": { + "message": "تغییر وضعیت ابزارهای توسعه دهنده" + }, + "minimize": { + "message": "کوچک کردن", + "description": "Minimize window" + }, + "zoom": { + "message": "بزرگ‌نمایی" + }, + "bringAllToFront": { + "message": "آوردن همه به جلو", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "درباره Bitwarden" + }, + "services": { + "message": "خدمات" + }, + "hideBitwarden": { + "message": "پنهان‌سازی Bitwarden" + }, + "hideOthers": { + "message": "پنهان‌سازی بقیه" + }, + "showAll": { + "message": "نمایش همه" + }, + "quitBitwarden": { + "message": "خروج از Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ رونوشت شد", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "راهنما" + }, + "window": { + "message": "پنجره" + }, + "checkPassword": { + "message": "بررسی اینکه که آیا کلمه عبور افشا شده است." + }, + "passwordExposed": { + "message": "این کلمه عبور $VALUE$ بار در رخنه داده‌ها افشا شده است. باید آن را تغییر دهید.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "این کلمه عبور در هیچ رخنه داده‌ای شناخته نشده است. باید برای استفاده امن باشد." + }, + "baseDomain": { + "message": "دامنه پایه", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "نام دامنه", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "میزبان", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "دقیق" + }, + "startsWith": { + "message": "شروع می شود با" + }, + "regEx": { + "message": "عبارت منظم", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "تشخیص تطابق", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "تشخیص تطابق پیشفرض", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "گزینه های تبدیل" + }, + "organization": { + "message": "سازمان", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "پیش فرض" + }, + "exit": { + "message": "خروج" + }, + "showHide": { + "message": "نمایش / پنهان‌سازی", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "پنهان‌سازی در قسمت نمادهای سیستم" + }, + "alwaysOnTop": { + "message": "همشه در بالا", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "بروزرسانی شد", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "کلمه عبور بروزرسانی شد", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "خروجی گرفتن از گاوصندوق" + }, + "fileFormat": { + "message": "فرمت پرونده" + }, + "warning": { + "message": "اخطار", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "صادرات گاوصندوق را تأیید کنید" + }, + "exportWarningDesc": { + "message": "این خروجی شامل داده‌های گاوصندوق در یک قالب رمزنگاری نشده است. شما نباید آن را از طریق یک راه ارتباطی ناامن (مثل ایمیل) ذخیره یا ارسال کنید. به محض اینکه استفاده‌تان از آن تمام شد، آن را حذف کنید." + }, + "encExportKeyWarningDesc": { + "message": "این صادرات با استفاده از کلید رمزگذاری حساب شما ، اطلاعات شما را رمزگذاری می کند. اگر حتی کلید رمزگذاری حساب خود را بچرخانید ، باید دوباره صادر کنید چون قادر به رمزگشایی این پرونده صادراتی نخواهید بود." + }, + "encExportAccountWarningDesc": { + "message": "کلیدهای رمزگذاری حساب برای هر حساب کاربری Bitwarden منحصر به فرد است ، بنابراین نمی توانید صادرات رمزگذاری شده را به حساب دیگری وارد کنید." + }, + "noOrganizationsList": { + "message": "شما به هیچ سازمانی تعلق ندارید. سازمان‌ها به شما اجازه می‌دهند تا داده‌های خود را را با کاربران دیگر به صورت امن به اشتراک بگذارید." + }, + "noCollectionsInList": { + "message": "هیچ مجموعه‌ای برای نمایش وجود ندارد." + }, + "ownership": { + "message": "مالکیت" + }, + "whoOwnsThisItem": { + "message": "چه کسی مالک این مورد است؟" + }, + "strong": { + "message": "قوی", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "خوب", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "ضعیف", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "کلمه عبور اصلی ضعیف" + }, + "weakMasterPasswordDesc": { + "message": "کلمه عبور اصلی که انتخاب کرده‌اید، ضعیف است. شما باید از کلمه عبور (یا عبارت عبور) قوی استفاده کنید تا از حساب کاربری Bitwarden خود به خوبی محافظت کنید. آیا مطمئنید که می‌خواهید این کلمه عبور را استفاده کنید؟" + }, + "pin": { + "message": "پین", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "بازکردن با پین" + }, + "setYourPinCode": { + "message": "کد پین خود را برای باز کردن Bitwarden تنظیم کنید. اگر به طور کامل از برنامه خارج شوید (Log out)، تنظیمات پین شما از بین می‌رود." + }, + "pinRequired": { + "message": "کد پین الزامیست." + }, + "invalidPin": { + "message": "کد پین غیر معتبر است." + }, + "unlockWithWindowsHello": { + "message": "باز کردن با Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "تایید برای Bitwarden." + }, + "unlockWithTouchId": { + "message": "باز کردن با اثر انگشت" + }, + "touchIdConsentMessage": { + "message": "تایید برای Bitwarden." + }, + "noAutoPromptWindowsHello": { + "message": "در هنگام راه اندازی ، درخواست Windows Hello نکنید." + }, + "noAutoPromptTouchId": { + "message": "در هنگام راه اندازی ، درخواست Touch ID نکنید." + }, + "lockWithMasterPassOnRestart": { + "message": "در زمان شروع مجدد، با کلمه عبور اصلی قفل کن" + }, + "preferences": { + "message": "تنظیمات" + }, + "enableMenuBar": { + "message": "فعال کردن نماد نوار منو" + }, + "enableMenuBarDesc": { + "message": "همیشه یک نماد در نوار منو نشان بده." + }, + "hideToMenuBar": { + "message": "پنهان‌سازی در نوار منو" + }, + "selectOneCollection": { + "message": "شما باید حداقل یک مجموعه را انتخاب کنید." + }, + "premiumUpdated": { + "message": "شما به پرمیوم ارتقاء یافتید." + }, + "restore": { + "message": "بازیابی" + }, + "premiumManageAlertAppStore": { + "message": "می‌توانید اشتراک خود را از اپ استور مدیریت کنید. آیا می‌خواهید هم اکنون از اپ استور دیدن کنید؟" + }, + "legal": { + "message": "قانونی", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "شرایط استفاده از خدمات" + }, + "privacyPolicy": { + "message": "سیاست حفظ حریم خصوصی" + }, + "unsavedChangesConfirmation": { + "message": "آیا مطمئن هستید که می‌خواهید خارج شوید؟ اگر الان خارج شوید اطلاعات فعلی ذخیره نخواهند شد" + }, + "unsavedChangesTitle": { + "message": "تغییرات ذخیره نشده وجود دارند" + }, + "clone": { + "message": "شبیه سازی" + }, + "passwordGeneratorPolicyInEffect": { + "message": "یک یا چند خط مشی سازمان بر تنظیمات تولیدکننده شما تأثیر می گذارد." + }, + "vaultTimeoutAction": { + "message": "عمل متوقف شدن گاو‌صندوق" + }, + "vaultTimeoutActionLockDesc": { + "message": "یک گاوصندوق قفل شده درخواست وارد کردن مجدد کلمه عبور اصلی را برای دسترسی میدهد." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "یک گاوصندوق خارج شده درخواست احراز هویت مجدد را برای دسترسی آن میدهد." + }, + "lock": { + "message": "قفل", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "زباله‌ها", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "جستجوی زباله‌ها" + }, + "permanentlyDeleteItem": { + "message": "حذف دائمی مورد" + }, + "permanentlyDeleteItemConfirmation": { + "message": "آیا مطمئن هستید که می خواهید این مورد را برای همیشه حذف کنید؟" + }, + "permanentlyDeletedItem": { + "message": "مورد برای همیشه حذف شد" + }, + "restoreItem": { + "message": "بازیابی مورد" + }, + "restoreItemConfirmation": { + "message": "آیا مطمئن هستید می خواهید این مورد را بازیابی کنید؟" + }, + "restoredItem": { + "message": "مورد بازیابی شد" + }, + "permanentlyDelete": { + "message": "حذف دائمی" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "خروج از سیستم تمام دسترسی ها به گاو‌صندوق شما را از بین می برد و نیاز به احراز هویت آنلاین پس از مدت زمان توقف دارد. آیا مطمئن هستید که می خواهید از این تنظیمات استفاده کنید؟" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "تایید عمل توقف" + }, + "enterpriseSingleSignOn": { + "message": "ورود به سیستم پروژه" + }, + "setMasterPassword": { + "message": "تنظیم کلمه عبور اصلی" + }, + "ssoCompleteRegistration": { + "message": "برای تکمیل ورود به سیستم با SSO ، لطفاً یک کلمه عبور اصلی برای دسترسی و محافظت از گاوصندوق خود تنظیم کنید." + }, + "newMasterPass": { + "message": "کلمه عبور اصلی جدید" + }, + "confirmNewMasterPass": { + "message": "تایید کلمه عبور اصلی جدید" + }, + "masterPasswordPolicyInEffect": { + "message": "یک یا چند سیاست سازمانی برای تأمین شرایط زیر به گذرواژه اصلی شما احتیاج دارد:" + }, + "policyInEffectMinComplexity": { + "message": "حداقل نمره پیچیدگی $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "حداقل طول $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "حاوی یک یا چند کاراکتر بزرگ" + }, + "policyInEffectLowercase": { + "message": "حاوی یک یا چند کاراکتر کوچک" + }, + "policyInEffectNumbers": { + "message": "حاوی یک یا چند عدد بیشتر" + }, + "policyInEffectSpecial": { + "message": "حاوی یک یا چند کاراکتر خاص زیر است $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "کلمه عبور اصلی جدید شما از شرایط سیاست پپیروی نمی کند." + }, + "acceptPolicies": { + "message": "با علامت زدن این کادر با موارد زیر موافقت می کنید:" + }, + "acceptPoliciesError": { + "message": "شرایط خدمات و سیاست حفظ حریم خصوصی تأیید نشده است." + }, + "enableBrowserIntegration": { + "message": "فعال کردن ادغام مرورگر" + }, + "enableBrowserIntegrationDesc": { + "message": "یکپارچه سازی مرورگر برای بیومتریک در مرورگر استفاده می شود." + }, + "browserIntegrationMasOnlyTitle": { + "message": "ادغام مرورگر پشتیبانی نمی شود" + }, + "browserIntegrationMasOnlyDesc": { + "message": "متأسفانه در حال حاضر ادغام مرورگر فقط در نسخه Mac App Store پشتیبانی می شود." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "ادغام مرورگر پشتیبانی نمی شود" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "متأسفانه در حال حاضر ادغام مرورگر در نسخه فروشگاه ویندوز پشتیبانی نمی شود." + }, + "enableBrowserIntegrationFingerprint": { + "message": "برای ادغام مرورگر نیاز به تأیید است" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "هنگام ایجاد پیوند بین دسکتاپ و مرورگر خود، با تأیید اعتبار اثر انگشت، یک لایه امنیتی دیگر را فعال کنید. درصورت فعال بودن، این امر مستلزم مداخله و تأیید کاربر در هر بار برقراری ارتباط است." + }, + "approve": { + "message": "تایید" + }, + "verifyBrowserTitle": { + "message": "اتصال مرورگر را تأیید کنید" + }, + "verifyBrowserDesc": { + "message": "لطفاً اطمینان حاصل کنید که اثر انگشت نشان داده شده با اثر انگشت نشان داده شده در افزونه مرورگر یکسان است." + }, + "biometricsNotEnabledTitle": { + "message": "بیومتریک فعال نیست" + }, + "biometricsNotEnabledDesc": { + "message": "بیومتریک مرورگر ابتدا نیاز به فعالسازی بیومتریک دسکتاپ در تنظیمات دارد." + }, + "personalOwnershipSubmitError": { + "message": "به دلیل خط مشی Enterprise ، برای ذخیره موارد در گاوصندوق شخصی خود محدود شده اید. گزینه مالکیت را به یک سازمان تغییر دهید و مجموعه های موجود را انتخاب کنید." + }, + "hintEqualsPassword": { + "message": "نکته کلمه عبور شما نمی تواند همان کلمه عبور شما باشد." + }, + "personalOwnershipPolicyInEffect": { + "message": "خط مشی سازمانی بر تنظیمات مالکیت شما تأثیر می گذارد." + }, + "allSends": { + "message": "همه ارسال ها", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "فایل" + }, + "sendTypeText": { + "message": "متن" + }, + "searchSends": { + "message": "ارسال ها را جستجو کن", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "ویرایش ارسال", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "گاوصندوق من" + }, + "text": { + "message": "متن" + }, + "deletionDate": { + "message": "تاریخ حذف" + }, + "deletionDateDesc": { + "message": "ارسال در تاریخ و ساعت مشخص شده برای همیشه حذف خواهد شد.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "تاريخ انقضاء" + }, + "expirationDateDesc": { + "message": "در صورت تنظیم، دسترسی به این ارسال در تاریخ و ساعت مشخص شده منقضی می شود.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "تعداد دسترسی حداکثر" + }, + "maxAccessCountDesc": { + "message": "در صورت تنظیم، با رسیدن به حداکثر تعداد دسترسی، کاربران دیگر نمی توانند به این ارسال دسترسی پیدا کنند.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "تعداد دسترسی فعلی" + }, + "disableSend": { + "message": "این ارسال را غیرفعال کنید تا کسی نتواند به آن دسترسی پیدا کند.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "به صورت اختیاری برای دسترسی کاربران به این ارسال به یک کلمه عبور نیاز دارید.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "یادداشت های خصوصی در مورد این ارسال.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "ارسال پیوند", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "ارسال پیوند", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "هنگام دسترسی به ارسال، متن را به طور پیش فرض پنهان کن", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "ارسال جدید ساخته شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "ارسال جدید ویرایش شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "ارسال پاک شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "کلمه عبور جدید" + }, + "whatTypeOfSend": { + "message": "این چه نوع ارسالی است؟", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "ساختن ارسال", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "متنی که می خواهید ارسال کنید." + }, + "sendFileDesc": { + "message": "فایلی که می خواهید ارسال کنید." + }, + "days": { + "message": "$DAYS$ روز", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "۱ روز" + }, + "custom": { + "message": "سفارشی" + }, + "deleteSendConfirmation": { + "message": "آیا مطمئن هستید می خواهید این ارسال را حذف کنید؟", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "کپی لینک ارسال به حافظه موقت", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "این پیوند را برای به اشتراک گذاری ارسال بعد از ارسال کپی کن." + }, + "sendDisabled": { + "message": "ارسال غیرفعال شد", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "به دلیل خط مشی سازمانی، شما فقط می توانید ارسال موجود را حذف کنید.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "کپی پیوند" + }, + "disabled": { + "message": "غیرفعال شد" + }, + "maxAccessCountReached": { + "message": "به حداکثر تعداد دسترسی رسیده است" + }, + "expired": { + "message": "منقضی شده" + }, + "pendingDeletion": { + "message": "در انتظار حذف" + }, + "webAuthnAuthenticate": { + "message": "تأیید اعتبار در WebAuthn" + }, + "hideEmail": { + "message": "آدرس ایمیلم را از گیرندگان مخفی کن." + }, + "sendOptionsPolicyInEffect": { + "message": "یک یا چند سیاست سازمان بر گزینه های ارسال شما تأثیر می گذارد." + }, + "emailVerificationRequired": { + "message": "تایید ایمیل لازم است" + }, + "emailVerificationRequiredDesc": { + "message": "برای استفاده از این ویژگی باید ایمیل خود را تأیید کنید." + }, + "passwordPrompt": { + "message": "کلمه عبور اصلی دوباره تولید می شود" + }, + "passwordConfirmation": { + "message": "تأیید کلمه عبور اصلی" + }, + "passwordConfirmationDesc": { + "message": "این عمل محافظت می شود. برای ادامه، لطفاً کلمه ورود اصلی خود را دوباره وارد کنید تا هویتان را تأیید کنید." + }, + "updatedMasterPassword": { + "message": "کلمه عبور اصلی بروز شد" + }, + "updateMasterPassword": { + "message": "بروزرسانی کلمه عبور اصلی" + }, + "updateMasterPasswordWarning": { + "message": "کلمه عبور اصلی شما اخیراً توسط سرپرست سازمانتان تغییر کرده است. برای دسترسی به گاوصندوق، باید همین حالا کلمه عبور اصلی خود را به روز کنید. در صورت ادامه، شما از نشست فعلی خود خارج می شوید و باید دوباره وارد سیستم شوید. نشست فعال در دستگاه های دیگر ممکن است تا یک ساعت همچنان فعال باقی بمانند." + }, + "hours": { + "message": "ساعت" + }, + "minutes": { + "message": "دقیقه" + }, + "vaultTimeoutPolicyInEffect": { + "message": "خط مشی های سازمانتان بر مهلت زمانی گاوصندوق شما تأثیر می گذارد. حداکثر زمان مجاز گاوصندوق $HOURS$ ساعت و $MINUTES$ دقیقه است", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "مهلت زمانی شما بیش از محدودیت های تعیین شده توسط سازمانتان است." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "ثبت نام خودکار" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "این سازمان دارای خط مشی سازمانی ای است که به طور خودکار شما را در بازنشانی کلمه عبور ثبت نام می کند. این ثبت نام به مدیران سازمان اجازه می دهد تا کلمه عبور اصلی شما را تغییر دهند." + }, + "vaultExportDisabled": { + "message": "صادرات گاوصندوق غیرفعال شده است" + }, + "personalVaultExportPolicyInEffect": { + "message": "یک یا چند خط مشی سازمان از صادرات گاوصندوق شخصی شما جلوگیری می کند." + }, + "addAccount": { + "message": "افزودن حساب کاربری" + }, + "removeMasterPassword": { + "message": "پاک کردن کلمه عبور اصلی" + }, + "removedMasterPassword": { + "message": "کلمه عبور اصلی پاک شد." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ در حال استفاده از SSO با یک سرور کلید خود میزبان است. برای ورود اعضای این سازمان دیگر نیازی به کلمه عبور اصلی نیست.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "ترک سازمان" + }, + "leaveOrganizationConfirmation": { + "message": "آيا مطمئن هستيد که می خواهيد سازمان های انتخاب شده را ترک کنيد؟" + }, + "leftOrganization": { + "message": "شما از سازمان ها خارج شده اید." + }, + "ssoKeyConnectorUnavailable": { + "message": "دسترسی به رابط کلید ممکن نیست، بعداً دوباره امتحان کنید." + }, + "lockAllVaults": { + "message": "قفل کردن تمام گاوصندوق ها" + }, + "accountLimitReached": { + "message": "بیش از 5 حساب را نمی توان همزمان وارد کرد." + }, + "accountPreferences": { + "message": "تنظیمات" + }, + "appPreferences": { + "message": "تنظیمات اپ (تمام حسابها)" + }, + "accountSwitcherLimitReached": { + "message": "محدودیت حساب تکمیل شد. برای افزودن حساب دیگر، از یک حساب خارج شوید." + }, + "settingsTitle": { + "message": "تنظیمات اپ برای $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "تعویض حساب کاربری" + }, + "options": { + "message": "گزینه‌ها" + }, + "sessionTimeout": { + "message": "زمان نشست شما به پایان رسید. لطفاً برگردید و دوباره وارد سیستم شوید." + }, + "exportingPersonalVaultTitle": { + "message": "صادرات گاو‌صندوق شخصی" + }, + "exportingPersonalVaultDescription": { + "message": "فقط موارد گاو‌صندوق شخصی مرتبط با $EMAIL$ صادر خواهد شد. موارد گاو‌صندوق سازمان شامل نخواهد شد.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "تولید کننده" + }, + "whatWouldYouLikeToGenerate": { + "message": "چه چیزی دوست دارید تولید کنید؟" + }, + "passwordType": { + "message": "نوع گذرواژه" + }, + "regenerateUsername": { + "message": "ایجاد مجدد نام کاربری" + }, + "generateUsername": { + "message": "ایجاد نام کاربری" + }, + "usernameType": { + "message": "نوع نام کاربری" + }, + "plusAddressedEmail": { + "message": "به علاوه ایمیل آدرس داده شده" + }, + "plusAddressedEmailDesc": { + "message": "از قابلیت های آدرس دهی فرعی ارائه دهنده ایمیل خود استفاده کنید." + }, + "catchallEmail": { + "message": "رایانامه همه‌گیر" + }, + "catchallEmailDesc": { + "message": "از صندوق ورودی پیکربندی شده دامنه خود استفاده کنید." + }, + "random": { + "message": "تصادفی" + }, + "randomWord": { + "message": "کلمه تصادفی" + }, + "websiteName": { + "message": "نام وب سایت" + }, + "service": { + "message": "خدمت" + } +} diff --git a/apps/desktop/src/locales/fi/messages.json b/apps/desktop/src/locales/fi/messages.json new file mode 100644 index 0000000000..48d7a015b4 --- /dev/null +++ b/apps/desktop/src/locales/fi/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Suodattimet" + }, + "allItems": { + "message": "Kaikki kohteet" + }, + "favorites": { + "message": "Suosikit" + }, + "types": { + "message": "Tyypit" + }, + "typeLogin": { + "message": "Kirjautumistieto" + }, + "typeCard": { + "message": "Kortti" + }, + "typeIdentity": { + "message": "Henkilöllisyys" + }, + "typeSecureNote": { + "message": "Salattu muistio" + }, + "folders": { + "message": "Kansiot" + }, + "collections": { + "message": "Kokoelmat" + }, + "searchVault": { + "message": "Hae holvista" + }, + "addItem": { + "message": "Lisää kohde" + }, + "shared": { + "message": "Jaettu" + }, + "share": { + "message": "Jaa" + }, + "moveToOrganization": { + "message": "Siirrä organisaatiolle" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ siirrettiin organisaatioon $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Valitse organisaatio, jolle haluat siirtää kohteen. Tämä siirtää kohteen organisaation omistukseen, etkä tämän jälkeen ole enää sen suora omistaja." + }, + "attachments": { + "message": "Liitteet" + }, + "viewItem": { + "message": "Näytä kohde" + }, + "name": { + "message": "Nimi" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Uusi URI" + }, + "username": { + "message": "Käyttäjätunnus" + }, + "password": { + "message": "Salasana" + }, + "passphrase": { + "message": "Salauslauseke" + }, + "editItem": { + "message": "Muokkaa kohdetta" + }, + "emailAddress": { + "message": "Sähköpostiosoite" + }, + "verificationCodeTotp": { + "message": "Todennuskoodi (TOTP)" + }, + "website": { + "message": "Verkkosivusto" + }, + "notes": { + "message": "Merkinnät" + }, + "customFields": { + "message": "Lisäkentät" + }, + "launch": { + "message": "Avaa" + }, + "copyValue": { + "message": "Kopioi arvo", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Pienennä kopioitaessa leikepöydälle" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Pienennä kun kohteen tietoja kopioidaan leikepöydälle." + }, + "toggleVisibility": { + "message": "Näytä tai piilota" + }, + "toggleCollapse": { + "message": "Laajenna tai pienennä", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kortinhaltijan nimi" + }, + "number": { + "message": "Numero" + }, + "brand": { + "message": "Merkki" + }, + "expiration": { + "message": "Erääntymisaika" + }, + "securityCode": { + "message": "Turvakoodi (CVC/CVV)" + }, + "identityName": { + "message": "Henkilöllisyyden nimi" + }, + "company": { + "message": "Yritys" + }, + "ssn": { + "message": "Henkilötunnus" + }, + "passportNumber": { + "message": "Passin numero" + }, + "licenseNumber": { + "message": "Ajokortin numero" + }, + "email": { + "message": "Sähköposti" + }, + "phone": { + "message": "Puhelinnumero" + }, + "address": { + "message": "Osoite" + }, + "premiumRequired": { + "message": "Premium vaaditaan" + }, + "premiumRequiredDesc": { + "message": "Käyttääksesi tätä toimintoa tarvitset Premium-jäsenyyden." + }, + "errorOccurred": { + "message": "Tapahtui virhe." + }, + "error": { + "message": "Virhe" + }, + "january": { + "message": "Tammikuu" + }, + "february": { + "message": "Helmikuu" + }, + "march": { + "message": "Maaliskuu" + }, + "april": { + "message": "Huhtikuu" + }, + "may": { + "message": "Toukokuu" + }, + "june": { + "message": "Kesäkuu" + }, + "july": { + "message": "Heinäkuu" + }, + "august": { + "message": "Elokuu" + }, + "september": { + "message": "Syyskuu" + }, + "october": { + "message": "Lokakuu" + }, + "november": { + "message": "Marraskuu" + }, + "december": { + "message": "Joulukuu" + }, + "ex": { + "message": "esim.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titteli" + }, + "mr": { + "message": "Hra" + }, + "mrs": { + "message": "Rva" + }, + "ms": { + "message": "Nti" + }, + "dr": { + "message": "Tri" + }, + "expirationMonth": { + "message": "Erääntymiskuukausi" + }, + "expirationYear": { + "message": "Erääntymisvuosi" + }, + "select": { + "message": "Valitse" + }, + "other": { + "message": "Muut" + }, + "generatePassword": { + "message": "Luo salasana" + }, + "type": { + "message": "Tyyppi" + }, + "firstName": { + "message": "Etunimi" + }, + "middleName": { + "message": "Toinen nimi" + }, + "lastName": { + "message": "Sukunimi" + }, + "fullName": { + "message": "Koko nimi" + }, + "address1": { + "message": "Osoite 1" + }, + "address2": { + "message": "Osoite 2" + }, + "address3": { + "message": "Osoite 3" + }, + "cityTown": { + "message": "Paikkakunta" + }, + "stateProvince": { + "message": "Osavaltio/maakunta" + }, + "zipPostalCode": { + "message": "Postinumero" + }, + "country": { + "message": "Maa" + }, + "save": { + "message": "Tallenna" + }, + "cancel": { + "message": "Peruuta" + }, + "delete": { + "message": "Poista" + }, + "favorite": { + "message": "Suosikki" + }, + "edit": { + "message": "Muokkaa" + }, + "authenticatorKeyTotp": { + "message": "Todennusmenetelmän avain (TOTP)" + }, + "folder": { + "message": "Kansio" + }, + "newCustomField": { + "message": "Uusi lisäkenttä" + }, + "value": { + "message": "Arvo" + }, + "dragToSort": { + "message": "Järjestä raahaamalla" + }, + "cfTypeText": { + "message": "Teksti" + }, + "cfTypeHidden": { + "message": "Piilotettu" + }, + "cfTypeBoolean": { + "message": "Totuusarvo" + }, + "cfTypeLinked": { + "message": "Linkitetty", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linkitetty arvo", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Poista" + }, + "nameRequired": { + "message": "Nimi vaaditaan." + }, + "addedItem": { + "message": "Kohde lisätty" + }, + "editedItem": { + "message": "Kohdetta muokattu" + }, + "deleteItem": { + "message": "Poista kohde" + }, + "deleteFolder": { + "message": "Poista kansio" + }, + "deleteAttachment": { + "message": "Poista tiedostoliite" + }, + "deleteItemConfirmation": { + "message": "Haluatko varmasti siirtää roskakoriin?" + }, + "deletedItem": { + "message": "Kohde siirretty roskakoriin" + }, + "overwritePasswordConfirmation": { + "message": "Haluatko varmasti korvata nykyisen salasanan?" + }, + "overwriteUsername": { + "message": "Korvaa käyttäjätunnus" + }, + "overwriteUsernameConfirmation": { + "message": "Haluatko varmasti korvata nykyisen käyttäjätunnuksen?" + }, + "noneFolder": { + "message": "Ei kansiota", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Lisää kansio" + }, + "editFolder": { + "message": "Muokkaa kansiota" + }, + "regeneratePassword": { + "message": "Luo uusi salasana" + }, + "copyPassword": { + "message": "Kopioi salasana" + }, + "copyUri": { + "message": "Kopioi URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopioi todennuskoodi (TOTP)" + }, + "length": { + "message": "Pituus" + }, + "numWords": { + "message": "Sanojen määrä" + }, + "wordSeparator": { + "message": "Sanojen erotin" + }, + "capitalize": { + "message": "Sanat isoilla alkukirjaimilla", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Sisällytä numero" + }, + "close": { + "message": "Sulje" + }, + "minNumbers": { + "message": "Numeroita vähintään" + }, + "minSpecial": { + "message": "Erikoismerkkejä vähintään", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Vältä epäselviä merkkejä" + }, + "searchCollection": { + "message": "Hae kokoelmasta" + }, + "searchFolder": { + "message": "Hae kansiosta" + }, + "searchFavorites": { + "message": "Hae suosikeista" + }, + "searchType": { + "message": "Hae tyypeistä", + "description": "Search item type" + }, + "newAttachment": { + "message": "Lisää uusi tiedostoliite" + }, + "deletedAttachment": { + "message": "Tiedostoliite poistettu" + }, + "deleteAttachmentConfirmation": { + "message": "Haluatko varmasti poistaa liitteen?" + }, + "attachmentSaved": { + "message": "Tiedostoliite tallennettu." + }, + "file": { + "message": "Tiedosto" + }, + "selectFile": { + "message": "Valitse tiedosto." + }, + "maxFileSize": { + "message": "Tiedoston enimmäiskoko on 500 Mt." + }, + "updateKey": { + "message": "Et voi käyttää tätä toimintoa ennen kuin päivität salausavaimesi." + }, + "editedFolder": { + "message": "Kansiota muokattu" + }, + "addedFolder": { + "message": "Kansio lisätty" + }, + "deleteFolderConfirmation": { + "message": "Haluatko varmasti poistaa kansion?" + }, + "deletedFolder": { + "message": "Kansio poistettu" + }, + "loginOrCreateNewAccount": { + "message": "Kirjaudu sisään tai luo uusi tili päästäksesi salattuun holviisi." + }, + "createAccount": { + "message": "Luo tili" + }, + "logIn": { + "message": "Kirjaudu" + }, + "submit": { + "message": "Jatka" + }, + "masterPass": { + "message": "Pääsalasana" + }, + "masterPassDesc": { + "message": "Pääsalasanalla pääset käsiksi holviisi. On erittäin tärkeää, että muistat pääsalasanasi, koska sen palautus ei ole mahdollista, jos unohdat sen." + }, + "masterPassHintDesc": { + "message": "Pääsalasanan vihje voi auttaa sinua muistamaan unohtamasi salasanan." + }, + "reTypeMasterPass": { + "message": "Syötä pääsalasana uudelleen" + }, + "masterPassHint": { + "message": "Pääsalasanan vihje (valinnainen)" + }, + "settings": { + "message": "Asetukset" + }, + "passwordHint": { + "message": "Salasanavihje" + }, + "enterEmailToGetHint": { + "message": "Syötä tilisi sähköpostiosoite saadaksesi pääsalasanan vihjeen." + }, + "getMasterPasswordHint": { + "message": "Pyydä pääsalasanan vihjettä" + }, + "emailRequired": { + "message": "Sähköpostiosoite vaaditaan." + }, + "invalidEmail": { + "message": "Virheellinen sähköpostiosoite." + }, + "masterPassRequired": { + "message": "Pääsalasana vaaditaan." + }, + "masterPassLength": { + "message": "Pääsalasanan on oltava vähintään 8 merkkiä pitkä." + }, + "masterPassDoesntMatch": { + "message": "Pääsalasanan vahvistus ei täsmää." + }, + "newAccountCreated": { + "message": "Uusi käyttäjätilisi on luotu! Voit nyt kirjautua sisään." + }, + "masterPassSent": { + "message": "Lähetimme pääsalasanasi vihjeen sinulle sähköpostitse." + }, + "unexpectedError": { + "message": "Tapahtui odottamaton virhe." + }, + "itemInformation": { + "message": "Kohteen tiedot" + }, + "noItemsInList": { + "message": "Ei näytettäviä kohteita." + }, + "sendVerificationCode": { + "message": "Lähetä vahvistuskoodi sähköpostiisi" + }, + "sendCode": { + "message": "Lähetä koodi" + }, + "codeSent": { + "message": "Koodi lähetetty" + }, + "verificationCode": { + "message": "Todennuskoodi" + }, + "confirmIdentity": { + "message": "Vahvista henkilöllisyytesi jatkaaksesi." + }, + "verificationCodeRequired": { + "message": "Todennuskoodi vaaditaan." + }, + "invalidVerificationCode": { + "message": "Virheellinen vahvistuskoodi" + }, + "continue": { + "message": "Jatka" + }, + "enterVerificationCodeApp": { + "message": "Syötä 6-numeroinen todennuskoodi todennussovelluksestasi." + }, + "enterVerificationCodeEmail": { + "message": "Syötä 6-numeroinen todennuskoodi, joka lähetettiin sähköpostitse osoitteeseen $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Todennussähköposti lähetettiin osoitteeseen $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Muista minut" + }, + "sendVerificationCodeEmailAgain": { + "message": "Lähetä todennuskoodi sähköpostitse uudelleen" + }, + "useAnotherTwoStepMethod": { + "message": "Käytä eri kaksivaiheisen kirjautumisen todennusmenetelmää" + }, + "insertYubiKey": { + "message": "Kytke YubiKey-todennuslaitteesi tietokoneen USB-porttiin ja paina sen painiketta." + }, + "insertU2f": { + "message": "Kytke todennuslaitteesi tietokoneen USB-porttiin ja jos laitteessa on painike, paina sitä." + }, + "recoveryCodeDesc": { + "message": "Etkö pysty käyttämään kaksivaiheisen kirjautumisen todentajiasi? Poista kaikki tilisi todentajat käytöstä palautuskoodillasi." + }, + "recoveryCodeTitle": { + "message": "Palautuskoodi" + }, + "authenticatorAppTitle": { + "message": "Todennussovellus" + }, + "authenticatorAppDesc": { + "message": "Käytä todennussovellusta (kuten Authy tai Google Authenticator) luodaksesi aikarajallisia todennuskoodeja.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP -todennuslaite" + }, + "yubiKeyDesc": { + "message": "Käytä YubiKey-todennuslaitetta tilisi avaukseen. Toimii YubiKey 4, 4 Nano, 4C sekä NEO -laitteiden kanssa." + }, + "duoDesc": { + "message": "Vahvista Duo Securityn avulla käyttäen Duo Mobile ‑sovellusta, tekstiviestiä, puhelua tai U2F-todennuslaitetta.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Vahvista organisaatiollesi Duo Securityn avulla käyttäen Duo Mobile ‑sovellusta, tekstiviestiä, puhelua tai U2F-todennuslaitetta.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Käytä mitä tahansa WebAuthn‑yhteensopivaa todennuslaitetta päästäksesi käsiksi tiliisi." + }, + "emailTitle": { + "message": "Sähköposti" + }, + "emailDesc": { + "message": "Todennuskoodit lähetetään sinulle sähköpostitse." + }, + "loginUnavailable": { + "message": "Kirjautuminen ei ole käytettävissä" + }, + "noTwoStepProviders": { + "message": "Tilillä on käytössä kaksivaiheinen kirjautuminen, mutta tämä laite ei tue käytettävissä olevia todentajia." + }, + "noTwoStepProviders2": { + "message": "Lisää muita todentajia, joita tuetaan laajemmin eri laitteilla (kuten todennussovellus)." + }, + "twoStepOptions": { + "message": "Kaksivaiheisen kirjautumisen asetukset" + }, + "selfHostedEnvironment": { + "message": "Oma palvelinympäristö" + }, + "selfHostedEnvironmentFooter": { + "message": "Määritä omassa palvelinympäristössäsi suoritettavan Bitwarden-asennuksen pääverkkotunnus." + }, + "customEnvironment": { + "message": "Mukautettu palvelinympäristö" + }, + "customEnvironmentFooter": { + "message": "Edistyneille käyttäjille. Voit määrittää jokaiselle palvelulle oman pääverkkotunnuksen." + }, + "baseUrl": { + "message": "Palvelimen URL" + }, + "apiUrl": { + "message": "API-palvelimen URL" + }, + "webVaultUrl": { + "message": "Verkkoholvipalvelimen URL" + }, + "identityUrl": { + "message": "Henkilöllisyyspalvelimen URL" + }, + "notificationsUrl": { + "message": "Ilmoituspalvelimen URL" + }, + "iconsUrl": { + "message": "Kuvakepalvelimen URL" + }, + "environmentSaved": { + "message": "Palvelinten URL-osoitteet tallennettiin." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Kyllä" + }, + "no": { + "message": "En" + }, + "overwritePassword": { + "message": "Korvaa salasana" + }, + "learnMore": { + "message": "Lue lisää" + }, + "featureUnavailable": { + "message": "Toiminto ei ole käytettävissä" + }, + "loggedOut": { + "message": "Kirjauduttu ulos" + }, + "loginExpired": { + "message": "Kirjautumisistuntosi on erääntynyt." + }, + "logOutConfirmation": { + "message": "Haluatko varmasti kirjautua ulos?" + }, + "logOut": { + "message": "Kirjaudu ulos" + }, + "addNewLogin": { + "message": "Lisää uusi kirjautumistieto" + }, + "addNewItem": { + "message": "Lisää uusi kohde" + }, + "addNewFolder": { + "message": "Lisää uusi kansio" + }, + "view": { + "message": "Näytä" + }, + "account": { + "message": "Käyttäjätili" + }, + "loading": { + "message": "Ladataan…" + }, + "lockVault": { + "message": "Lukitse holvi" + }, + "passwordGenerator": { + "message": "Salasanageneraattori" + }, + "contactUs": { + "message": "Ota yhteyttä" + }, + "getHelp": { + "message": "Hanki apua" + }, + "fileBugReport": { + "message": "Jätä virheilmoitus" + }, + "blog": { + "message": "Blogi" + }, + "followUs": { + "message": "Seuraa meitä" + }, + "syncVault": { + "message": "Synkronoi holvi" + }, + "changeMasterPass": { + "message": "Vaihda pääsalasana" + }, + "changeMasterPasswordConfirmation": { + "message": "Voit vaihtaa pääsalasanasi bitwarden.com-verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "fingerprintPhrase": { + "message": "Tunnistelauseke", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Tilisi tunnistelauseke", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Siirry verkkoholviin" + }, + "getMobileApp": { + "message": "Hanki mobiilisovellus" + }, + "getBrowserExtension": { + "message": "Hanki selainlaajennus" + }, + "syncingComplete": { + "message": "Synkronointi on valmis" + }, + "syncingFailed": { + "message": "Synkronointi epäonnistui" + }, + "yourVaultIsLocked": { + "message": "Holvisi on lukittu. Vahvista henkilöllisyytesi jatkaaksesi." + }, + "unlock": { + "message": "Avaa" + }, + "loggedInAsOn": { + "message": "Kirjautuneena tunnuksella $EMAIL$ palveluun $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Virheellinen pääsalasana" + }, + "twoStepLoginConfirmation": { + "message": "Kaksivaiheinen kirjautuminen tekee tilistäsi turvallisemman edellyttämällä salasanan lisäksi kirjautumisen lisätodennusta todennuslaitteen, ‑sovelluksen, tekstiviestin, puhelun tai sähköpostin avulla. Voit ottaa kaksivaiheisen kirjautumisen käyttöön bitwarden.com‑verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "twoStepLogin": { + "message": "Kaksivaiheinen kirjautuminen" + }, + "vaultTimeout": { + "message": "Holvin aikakatkaisu" + }, + "vaultTimeoutDesc": { + "message": "Valitse milloin holvin aikakatkaisu tapahtuu ja suorita valittu toiminto." + }, + "immediately": { + "message": "Välittömästi" + }, + "tenSeconds": { + "message": "10 sekuntia" + }, + "twentySeconds": { + "message": "20 sekuntia" + }, + "thirtySeconds": { + "message": "30 sekuntia" + }, + "oneMinute": { + "message": "1 minuutti" + }, + "twoMinutes": { + "message": "2 minuuttia" + }, + "fiveMinutes": { + "message": "5 minuuttia" + }, + "fifteenMinutes": { + "message": "15 minuuttia" + }, + "thirtyMinutes": { + "message": "30 minuuttia" + }, + "oneHour": { + "message": "1 tunti" + }, + "fourHours": { + "message": "4 tuntia" + }, + "onIdle": { + "message": "Kun järjetelmä on käyttämättömänä" + }, + "onSleep": { + "message": "Kun järjestelmän siirtyy lepotilaan" + }, + "onLocked": { + "message": "Kun järjestelmän lukitaan" + }, + "onRestart": { + "message": "Kun käynnistetään uudelleen" + }, + "never": { + "message": "Ei koskaan" + }, + "security": { + "message": "Suojaus" + }, + "clearClipboard": { + "message": "Tyhjennä leikepöytä", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Poista kopioidut arvot leikepöydältä automaattisesti.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Älä näytä sivustojen kuvakkeita" + }, + "disableFaviconDesc": { + "message": "Kirjautumistietojen vieressä näytettävät sivustojen kuvakkeet helpottavat kohteiden tunnistusta." + }, + "enableMinToTray": { + "message": "Pienennä ilmoitusalueelle" + }, + "enableMinToTrayDesc": { + "message": "Pienennä ikkuna kuvakkeeksi järjestelmän ilmoitusalueelle." + }, + "enableMinToMenuBar": { + "message": "Pienennä valikkoriville" + }, + "enableMinToMenuBarDesc": { + "message": "Kun ikkuna pienennetään, näytä se kuvakkeena valikkorivillä." + }, + "enableCloseToTray": { + "message": "Sulje ilmoitusalueelle" + }, + "enableCloseToTrayDesc": { + "message": "Sulje ikkuna kuvakkeeksi järjestelmän ilmoitusalueelle." + }, + "enableCloseToMenuBar": { + "message": "Sulje valikkoriville" + }, + "enableCloseToMenuBarDesc": { + "message": "Kun ikkuna suljetaan, näytä se sulun sijaan kuvakkeena valikkorivillä." + }, + "enableTray": { + "message": "Näytä ilmoitusalueen kuvake" + }, + "enableTrayDesc": { + "message": "Näytä ilmoitusalueen kuvake aina." + }, + "startToTray": { + "message": "Käynnistä ilmoitusalueelle" + }, + "startToTrayDesc": { + "message": "Kun sovellus käynnistetään, näytä vain kuvake ilmoitusalueella." + }, + "startToMenuBar": { + "message": "Avaa valikkoriville" + }, + "startToMenuBarDesc": { + "message": "Kun sovellus avataan ensimmäisen kerran, näytä se kuvakkeena valikkorivillä." + }, + "openAtLogin": { + "message": "Käynnistä automaattisesti kirjauduttaessa" + }, + "openAtLoginDesc": { + "message": "Käynnistä Bitwardenin työpöytäsovellus automaattisesti kirjautumisen yhteydessä." + }, + "alwaysShowDock": { + "message": "Näytä aina Dockissa" + }, + "alwaysShowDockDesc": { + "message": "Näytä Bitwardenin kuvake Dockissa myös sen ollessa pienennettynä valikkoriville." + }, + "confirmTrayTitle": { + "message": "Vahvista ilmoitusalueen käytöstä poisto" + }, + "confirmTrayDesc": { + "message": "Asetuksen käytöstä poisto kytkee myös kaikki muut ilmoitusalueeseen liittyvät asetukset pois käytöstä." + }, + "language": { + "message": "Kieli" + }, + "languageDesc": { + "message": "Vaihda sovelluksen kieli. Vaatii uudelleenkäynnistyksen." + }, + "theme": { + "message": "Teema" + }, + "themeDesc": { + "message": "Muuta sovelluksen väriteemaa." + }, + "dark": { + "message": "Tumma", + "description": "Dark color" + }, + "light": { + "message": "Vaalea", + "description": "Light color" + }, + "copy": { + "message": "Kopioi", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Tarkista päivitykset" + }, + "version": { + "message": "Versio $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Käynnistä Bitwarden uudelleen päivittääksesi" + }, + "restartToUpdateDesc": { + "message": "Versio $VERSION_NUM$ on valmis asennettavaksi. Sovellus tulee käynnistää uudelleen, jotta asennus voidaan suorittaa loppuun. Haluatko käynnistää sovelluksen uudelleen ja päivittää nyt?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Päivitys on saatavilla" + }, + "updateAvailableDesc": { + "message": "Päivitys löydetty. Haluatko ladata sen nyt?" + }, + "restart": { + "message": "Käynnistä sovellus uudelleen" + }, + "later": { + "message": "Myöhemmin" + }, + "noUpdatesAvailable": { + "message": "Päivityksiä ei ole saatavilla. Käytät viimeisintä versiota." + }, + "updateError": { + "message": "Päivitysvirhe" + }, + "unknown": { + "message": "Tuntematon" + }, + "copyUsername": { + "message": "Kopioi käyttäjätunnus" + }, + "copyNumber": { + "message": "Kopioi numero", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopioi turvakoodi", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium-jäsenyys" + }, + "premiumManage": { + "message": "Hallitse jäsenyyttä" + }, + "premiumManageAlert": { + "message": "Voit hallita jäsenyyttäsi bitwarden.com-verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "premiumRefresh": { + "message": "Päivitä jäsenyys" + }, + "premiumNotCurrentMember": { + "message": "Et ole tällä hetkellä Premium-jäsen." + }, + "premiumSignUpAndGet": { + "message": "Ryhdy Premium-jäseneksi saadaksesi:" + }, + "premiumSignUpStorage": { + "message": "1 Gt salattua tallennustilaa tiedostoliitteille." + }, + "premiumSignUpTwoStep": { + "message": "Muita kaksivaiheisen kirjautumisen todennusmenetelmiä kuten YubiKey, FIDO U2F ja Duo Security." + }, + "premiumSignUpReports": { + "message": "Salasanahygienian, tilin terveyden ja tietovuotojen raportointitoiminnot pitävät holvisi turvassa." + }, + "premiumSignUpTotp": { + "message": "Kaksivaiheisen kirjautumisen (2FA) TOTP-todennuskoodien generaattori holvisi kirjautumistiedoille." + }, + "premiumSignUpSupport": { + "message": "Ensisijainen asiakastuki." + }, + "premiumSignUpFuture": { + "message": "Kaikki tulossa olevat Premium-toiminnot. Lisää tulossa pian!" + }, + "premiumPurchase": { + "message": "Osta Premium" + }, + "premiumPurchaseAlert": { + "message": "Voit ostaa Premium-jäsenyyden bitwarden.com-verkkoholvissa. Haluatko käydä sivustolla nyt?" + }, + "premiumCurrentMember": { + "message": "Olet Premium-jäsen!" + }, + "premiumCurrentMemberThanks": { + "message": "Kiitos kun tuet Bitwardenia." + }, + "premiumPrice": { + "message": "Kaikki tämä vain $PRICE$/vuosi!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Päivitys on valmis" + }, + "passwordHistory": { + "message": "Salasanahistoria" + }, + "clear": { + "message": "Tyhjennä", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Ei näytettäviä salasanoja." + }, + "undo": { + "message": "Kumoa" + }, + "redo": { + "message": "Tee uudelleen" + }, + "cut": { + "message": "Leikkaa", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Liitä", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Valitse kaikki" + }, + "zoomIn": { + "message": "Lähennä" + }, + "zoomOut": { + "message": "Loitonna" + }, + "resetZoom": { + "message": "Palauta zoomaus" + }, + "toggleFullScreen": { + "message": "Kytke koko näytön tila" + }, + "reload": { + "message": "Lataa uudelleen" + }, + "toggleDevTools": { + "message": "Kytke kehittäjätyökalut" + }, + "minimize": { + "message": "Pienennä", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoomaus" + }, + "bringAllToFront": { + "message": "Tuo kaikki eteen", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Tietoja Bitwardenista" + }, + "services": { + "message": "Palvelut" + }, + "hideBitwarden": { + "message": "Piilota Bitwarden" + }, + "hideOthers": { + "message": "Piilota muut" + }, + "showAll": { + "message": "Näytä kaikki" + }, + "quitBitwarden": { + "message": "Sulje Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ kopioitu", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Ohje" + }, + "window": { + "message": "Ikkuna" + }, + "checkPassword": { + "message": "Tarkasta, onko salasana vuotanut." + }, + "passwordExposed": { + "message": "Salasana on paljastunut $VALUE$ tietovuodossa. Se tulisi vaihtaa.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Salasanaa ei löytynyt tunnetuista tietovuodoista. Sen pitäisi olla turvallinen." + }, + "baseDomain": { + "message": "Pääverkkotunnus", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Verkkotunnus", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Isäntä", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tarkka" + }, + "startsWith": { + "message": "Alkaa" + }, + "regEx": { + "message": "Säännöllinen lauseke", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Tunnistustapa", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Tunnistuksen oletustapa", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Näytä tai piilota asetukset" + }, + "organization": { + "message": "Organisaatio", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Oletus" + }, + "exit": { + "message": "Poistu" + }, + "showHide": { + "message": "Näytä tai piilota", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Piilota ilmoitusalueelle" + }, + "alwaysOnTop": { + "message": "Aina päällimmäisenä", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Päivitetty", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Salasana päivitetty", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Vie holvi" + }, + "fileFormat": { + "message": "Tiedostomuoto" + }, + "warning": { + "message": "VAROITUS", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Vahvista holvin vienti" + }, + "exportWarningDesc": { + "message": "Tämä vienti sisältää holvisi tiedot salaamattomassa muodossa. Sinun ei tulisi säilyttää tai lähettää vietyä tiedostoa suojaamattomien kanavien (kuten sähköpostin) välityksellä. Poista se välittömästi kun sille ei enää ole käyttöä." + }, + "encExportKeyWarningDesc": { + "message": "Tämä vienti salaa tietosi käyttäen käyttäjätilisi salausavaimella. Jos joskus uudistat tilisi salausavaimen, tulee sinun viedä tiedot uudelleen, koska et voi enää purkaa nyt viedyn tiedoston salausta." + }, + "encExportAccountWarningDesc": { + "message": "Tilin salausavaimet ovat ainutlaatuisia jokaiselle Bitwarden-käyttäjätilille, joten et voi tuoda salattua vientitiedostoa toiselle tilille." + }, + "noOrganizationsList": { + "message": "Et kuulu mihinkään organisaatioon. Organisaatioiden avulla voit jakaa kohteita turvallisesti muiden käyttäjien kanssa." + }, + "noCollectionsInList": { + "message": "Ei näytettäviä kokoelmia." + }, + "ownership": { + "message": "Omistus" + }, + "whoOwnsThisItem": { + "message": "Kuka omistaa tämän kohteen?" + }, + "strong": { + "message": "Vahva", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Hyvä", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Heikko", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Heikko pääsalasana" + }, + "weakMasterPasswordDesc": { + "message": "Valitsemasi pääsalasana on heikko. Sinun tulisi käyttää vahvaa pääsalasanaa (tai salauslauseketta) suojataksesi Bitwarden-tilisi kunnolla. Haluatko varmasti käyttää tätä pääsalasanaa?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Avaa PIN-koodilla" + }, + "setYourPinCode": { + "message": "Aseta PIN-koodi Bitwardenin avaukselle. PIN-asetukset tyhjentyvät, jos kirjaudut kokonaan ulos sovelluksesta." + }, + "pinRequired": { + "message": "PIN-koodi vaaditaan." + }, + "invalidPin": { + "message": "Virheellinen PIN-koodi." + }, + "unlockWithWindowsHello": { + "message": "Avaa Windows Hellolla" + }, + "windowsHelloConsentMessage": { + "message": "Vahvista Bitwarden." + }, + "unlockWithTouchId": { + "message": "Avaa Touch ID:llä" + }, + "touchIdConsentMessage": { + "message": "avaa holvisi" + }, + "noAutoPromptWindowsHello": { + "message": "Älä pyydä Windows Hello -kirjautumista käynnistettäessä." + }, + "noAutoPromptTouchId": { + "message": "Älä pyydä Touch ID -kirjautumista käynnistettäessä." + }, + "lockWithMasterPassOnRestart": { + "message": "Lukitse pääsalasanalla uudelleenkäynnistyksen yhteydessä" + }, + "preferences": { + "message": "Asetukset" + }, + "enableMenuBar": { + "message": "Käytä tehtäväpalkin kuvaketta" + }, + "enableMenuBarDesc": { + "message": "Näytä tehtäväpalkin kuvake aina." + }, + "hideToMenuBar": { + "message": "Piilota tehtäväpalkkiin" + }, + "selectOneCollection": { + "message": "Valitse ainakin yksi kokoelma." + }, + "premiumUpdated": { + "message": "Olet päivittänyt Premiumiin." + }, + "restore": { + "message": "Palauta" + }, + "premiumManageAlertAppStore": { + "message": "Voit hallita tilaustasi App Storessa. Haluatko siirtyä App Storeen nyt?" + }, + "legal": { + "message": "Oikeudelliset tiedot", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Käyttöehdot" + }, + "privacyPolicy": { + "message": "Tietosuojakäytäntö" + }, + "unsavedChangesConfirmation": { + "message": "Haluatko varmasti poistua? Jos poistut nyt, nykyisiä tietoja ei tallenneta." + }, + "unsavedChangesTitle": { + "message": "Tallentamattomia muutoksia" + }, + "clone": { + "message": "Kloonaa" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Yksi tai useampi organisaatiokäytäntö vaikuttaa generaattorisi asetuksiin." + }, + "vaultTimeoutAction": { + "message": "Holvin aikakatkaisun toiminto" + }, + "vaultTimeoutActionLockDesc": { + "message": "Lukittu holvi vaatii pääsalasanan syötön sen käyttämiseksi." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Uloskirjattu holvi vaatii uuden todennuksen sen käyttämiseksi." + }, + "lock": { + "message": "Lukitse", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Roskakori", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Hae roskakorista" + }, + "permanentlyDeleteItem": { + "message": "Poista kohde pysyvästi" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Haluatko varmasti poistaa kohteen pysyvästi?" + }, + "permanentlyDeletedItem": { + "message": "Kohde poistettu pysyvästi" + }, + "restoreItem": { + "message": "Palauta kohde" + }, + "restoreItemConfirmation": { + "message": "Haluatko varmasti palauttaa kohteen?" + }, + "restoredItem": { + "message": "Kohde palautettu" + }, + "permanentlyDelete": { + "message": "Poista pysyvästi" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Uloskirjautuminen estää pääsyn holviisi ja vaatii ajan umpeuduttua todennuksen internet-yhteyden välityksellä. Haluatko varmasti käyttää asetusta?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Aikakatkaisun toiminnon vahvistus" + }, + "enterpriseSingleSignOn": { + "message": "Yrityksen kertakirjautuminen (SSO)" + }, + "setMasterPassword": { + "message": "Aseta pääsalasana" + }, + "ssoCompleteRegistration": { + "message": "Kirjautuaksesi sisään käyttäen kertakirjautumista (SSO), ole hyvä ja aseta holvillesi pääsalasana." + }, + "newMasterPass": { + "message": "Uusi pääsalasana" + }, + "confirmNewMasterPass": { + "message": "Vahvista uusi pääsalasana" + }, + "masterPasswordPolicyInEffect": { + "message": "Yksi tai useampi organisaatiokäytäntö edellyttää, että pääsalasanasi täyttää seuraavat vaatimukset:" + }, + "policyInEffectMinComplexity": { + "message": "Monimutkaisuuden vähimmäispistemäärä on $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Vähimmäispituus on $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Sisältää yhden tai useamman ison kirjaimen" + }, + "policyInEffectLowercase": { + "message": "Sisältää yhden tai useamman pienen kirjaimen" + }, + "policyInEffectNumbers": { + "message": "Sisältää yhden tai useamman numeron" + }, + "policyInEffectSpecial": { + "message": "Sisältää yhden tai useamman seuraavista erikoismerkeistä $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Uusi pääsalasanasi ei täytä käytännön määrittämiä vaatimuksia." + }, + "acceptPolicies": { + "message": "Valitsemalla tämän ruudun hyväksyt seuraavat:" + }, + "acceptPoliciesError": { + "message": "Käyttöehtoja ja tietosuojakäytäntöä ei ole vahvistettu." + }, + "enableBrowserIntegration": { + "message": "Käytä selainintegrointia" + }, + "enableBrowserIntegrationDesc": { + "message": "Selainintegrointia käytetään selaimessa biometriaa varten." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Selainintegrointia ei tueta" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Valitettavasti selainintegrointia tukee toistaiseksi vain Mac App Store -versio." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Selainintegrointia ei tueta" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Valitettavasti selainintegrointia ei toistaiseksi tueta sovelluksen Microsoft Store -versiossa." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Vaadi selainintegroinnin vahvistus" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Käytä ylimääräistä tietoturvakerrosta ja vaadi todennus tunnistelausekkeen avulla kun luot linkin työpöytäsi ja selaimesi välille. Kun käytössä, edellyttää käyttäjältä manuaalista todennusta aina yhteyden muodostuessa." + }, + "approve": { + "message": "Salli" + }, + "verifyBrowserTitle": { + "message": "Varmista yhteys selaimeen" + }, + "verifyBrowserDesc": { + "message": "Varmista, että näytetty tunnistelauseke on identtinen selainlaajennuksessa näkyvän lausekkeen kanssa." + }, + "biometricsNotEnabledTitle": { + "message": "Biometria ei ole käytössä" + }, + "biometricsNotEnabledDesc": { + "message": "Käyttääksesi biometriaa selaimessa, on biometria otettava käyttöön työpöytäsovelluksen asetuksista." + }, + "personalOwnershipSubmitError": { + "message": "Yrityksen asettaman käytännön johdosta kohteiden tallennus omaan holviisi ei ole mahdollista. Muuta omistusasetus organisaatiolle ja valitse käytettävissä olevista kokoelmista." + }, + "hintEqualsPassword": { + "message": "Salasanavihjeesi ei voi olla sama kuin salasanasi." + }, + "personalOwnershipPolicyInEffect": { + "message": "Organisaatiokäytäntö vaikuttaa omistajuusvalintoihisi." + }, + "allSends": { + "message": "Kaikki Sendit", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Tiedosto" + }, + "sendTypeText": { + "message": "Teksti" + }, + "searchSends": { + "message": "Hae Sendeistä", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Muokkaa Sendiä", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Oma holvi" + }, + "text": { + "message": "Teksti" + }, + "deletionDate": { + "message": "Poistoajankohta" + }, + "deletionDateDesc": { + "message": "Send poistuu pysyvästi määritettynä ajankohtana.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Erääntymisajankohta" + }, + "expirationDateDesc": { + "message": "Send erääntyy määritettynä ajankohtana.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Käyttöoikeuksien enimmäismäärä" + }, + "maxAccessCountDesc": { + "message": "Jos määritetty, käyttäjät eivät voi avata Sendiä käyttökertojen enimmäismäärän täytyttyä.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Nykyinen käyttökertojen määrä" + }, + "disableSend": { + "message": "Poista Send käytöstä, jottei kukaan voi avata sitä.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Halutessasi, vaadi käyttäjiä syöttämään salasana Sendin avaamiseksi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Yksityisiä merkintöjä tästä Sendistä.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send-linkki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send-linkki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Piilota teksti oletuksena kun Send avataan", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send luotu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Sendiä muokattu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send poistettu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Uusi salasana" + }, + "whatTypeOfSend": { + "message": "Minkä tyyppinen Send tämä on?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Send luotu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teksti, jonka haluat lähettää." + }, + "sendFileDesc": { + "message": "Tiedosto, jonka haluat lähettää." + }, + "days": { + "message": "$DAYS$ päivää", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 päivä" + }, + "custom": { + "message": "Mukautettu" + }, + "deleteSendConfirmation": { + "message": "Haluatko varmasti poistaa Sendin?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopioi Sendin linkki leikepöydälle", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kopioi Sendin linkki leikepöydälle tallennettaessa." + }, + "sendDisabled": { + "message": "Send on poistettu käytöstä", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Yrityksen käytännön vuoksi voit poistaa vain olemassa olevan Sendin.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopioi linkki" + }, + "disabled": { + "message": "Poistettu käytöstä" + }, + "maxAccessCountReached": { + "message": "Käyttökertojen enimmäismäärä saavutettu" + }, + "expired": { + "message": "Erääntynyt" + }, + "pendingDeletion": { + "message": "Odottaa poistoa" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn-todennus" + }, + "hideEmail": { + "message": "Piilota sähköpostiosoitteeni vastaanottajilta." + }, + "sendOptionsPolicyInEffect": { + "message": "Yksi tai useampi organisaatiokäytäntö vaikuttaa Send-asetuksiisi." + }, + "emailVerificationRequired": { + "message": "Sähköpostiosoitteen vahvistus vaaditaan" + }, + "emailVerificationRequiredDesc": { + "message": "Sinun on vahvistettava sähköpostiosoitteesi käyttääksesi tätä ominaisuutta." + }, + "passwordPrompt": { + "message": "Pääsalasanan uudelleenkysely" + }, + "passwordConfirmation": { + "message": "Pääsalasanan vahvistus" + }, + "passwordConfirmationDesc": { + "message": "Toiminto on suojattu. Jatkaaksesi, syötä pääsalasanasi uudelleen vahvistaaksesi henkilöllisyytesi." + }, + "updatedMasterPassword": { + "message": "Pääsalasana on päivitetty" + }, + "updateMasterPassword": { + "message": "Päivitä pääsalasana" + }, + "updateMasterPasswordWarning": { + "message": "Organisaatiosi ylläpito on hiljattain vaihtanut pääsalasanasi. Käyttääksesi holvia, on sinun päivitettävä se nyt. Tämä uloskirjaa kaikki nykyiset istunnot pakottaen uudelleenkirjautumisen. Muiden laitteiden aktiiviset istunnot saattavat toimia vielä tunnin ajan." + }, + "hours": { + "message": "Tuntia" + }, + "minutes": { + "message": "Minuuttia" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Organisaatiosi käytännöt vaikuttavat holvisi aikakatkaisuun. Suurin sallittu viive on $HOURS$ tunti(a) ja $MINUTES$ minuutti(a)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Holvisi aikakatkaisuviive ylittää organisaatiosi asettamat rajoitukset." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automaattinen liitos" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Organisaatiolla on käytäntö, joka liittää tilisi automaattisesti salasanan palautusapuun. Liitos sallii organisaation ylläpitäjien vaihtaa pääsalasanasi." + }, + "vaultExportDisabled": { + "message": "Holvin vienti on poistettu käytöstä" + }, + "personalVaultExportPolicyInEffect": { + "message": "Yksi tai useampi organisaation käytäntö estää henkilökohtaisen holvisi viennin." + }, + "addAccount": { + "message": "Lisää tili" + }, + "removeMasterPassword": { + "message": "Poista pääsalasana" + }, + "removedMasterPassword": { + "message": "Pääsalasana on poistettu." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ käyttää kertakirjautumista (SSO) oman avainpalvelimensa kanssa. Organisaation jäsenet eivät enää tarvitse pääsalasanaa kirjautumiseen.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Poistu organisaatiosta" + }, + "leaveOrganizationConfirmation": { + "message": "Haluatko varmasti poistua tästä organisaatiosta?" + }, + "leftOrganization": { + "message": "Olet poistunut organisaatiosta." + }, + "ssoKeyConnectorUnavailable": { + "message": "Avainyhdistäjää ei tavoiteta. Yritä myöhemmin uudelleen." + }, + "lockAllVaults": { + "message": "Lukitse kaikki holvit" + }, + "accountLimitReached": { + "message": "Enintään 5 tiliä voi olla samanaikaisesti kirjautuneena." + }, + "accountPreferences": { + "message": "Asetukset" + }, + "appPreferences": { + "message": "Sovellusasetukset (kaikki tilit)" + }, + "accountSwitcherLimitReached": { + "message": "Tilien enimmäismäärä on saavutettu. Kirjaa jokin niistä ulos lisätäksesi tilin." + }, + "settingsTitle": { + "message": "Sovellusasetukset tunnukselle $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Vaihda tiliä" + }, + "options": { + "message": "Valinnat" + }, + "sessionTimeout": { + "message": "Istuntosi on aikakatkaistu. Palaa takaisin ja yritä kirjautua uudelleen." + }, + "exportingPersonalVaultTitle": { + "message": "Henkilökohtaisen holvin vienti" + }, + "exportingPersonalVaultDescription": { + "message": "Vain tunnukseen $EMAIL$ liitetyt henkilökohtaiset holvin kohteet viedään. Organisaation kohteet eivät sisälly tähän.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generaattori" + }, + "whatWouldYouLikeToGenerate": { + "message": "Mitä haluat luoda?" + }, + "passwordType": { + "message": "Salasanan tyyppi" + }, + "regenerateUsername": { + "message": "Luo uusi käyttäjätunnus" + }, + "generateUsername": { + "message": "Luo käyttäjätunnus" + }, + "usernameType": { + "message": "Käyttäjätunnuksen tyyppi" + }, + "plusAddressedEmail": { + "message": "Plus-osoitteinen sähköposti" + }, + "plusAddressedEmailDesc": { + "message": "Käytä sähköpostipalvelusi aliosoiteominaisuuksia." + }, + "catchallEmail": { + "message": "Catch-all-sähköpostiosoite" + }, + "catchallEmailDesc": { + "message": "Käytä verkkotunnuksellesi määritettyä catch-all-postilaatikkoa." + }, + "random": { + "message": "Satunnainen" + }, + "randomWord": { + "message": "Satunnainen sana" + }, + "websiteName": { + "message": "Verkkosivuston nimi" + }, + "service": { + "message": "Palvelu" + } +} diff --git a/apps/desktop/src/locales/fil/messages.json b/apps/desktop/src/locales/fil/messages.json new file mode 100644 index 0000000000..1b909d5de4 --- /dev/null +++ b/apps/desktop/src/locales/fil/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "Favorites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Email Address" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy Value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security Code" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favorite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "Search Folder" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "Add New Folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check For Updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/fr/messages.json b/apps/desktop/src/locales/fr/messages.json new file mode 100644 index 0000000000..9e45fc97fd --- /dev/null +++ b/apps/desktop/src/locales/fr/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtres" + }, + "allItems": { + "message": "Tous les éléments" + }, + "favorites": { + "message": "Favoris" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Identifiant" + }, + "typeCard": { + "message": "Carte de paiement" + }, + "typeIdentity": { + "message": "Identité" + }, + "typeSecureNote": { + "message": "Note sécurisée" + }, + "folders": { + "message": "Dossiers" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Rechercher dans le coffre" + }, + "addItem": { + "message": "Ajouter un élément" + }, + "shared": { + "message": "Partagé" + }, + "share": { + "message": "Partager" + }, + "moveToOrganization": { + "message": "Déplacer vers l'organisation" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ a été déplacé vers $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choisissez une organisation vers laquelle vous souhaitez déplacer cet élément. Déplacer un élément vers une organisation transfère la propriété de l'élément à cette organisation. Vous ne serez plus le propriétaire direct de cet élément une fois qu'il aura été déplacé." + }, + "attachments": { + "message": "Pièces jointes" + }, + "viewItem": { + "message": "Afficher l'élément" + }, + "name": { + "message": "Nom" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nouvel URI" + }, + "username": { + "message": "Nom d'utilisateur" + }, + "password": { + "message": "Mot de passe" + }, + "passphrase": { + "message": "Phrase de passe" + }, + "editItem": { + "message": "Modifier l'élément" + }, + "emailAddress": { + "message": "Adresse e-mail" + }, + "verificationCodeTotp": { + "message": "Code de vérification (TOTP)" + }, + "website": { + "message": "Site web" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Champs personnalisés" + }, + "launch": { + "message": "Ouvrir" + }, + "copyValue": { + "message": "Copier la valeur", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Réduire lors de la copie dans le presse-papiers" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Réduire lors de la copie des données d'un élément dans le presse-papiers." + }, + "toggleVisibility": { + "message": "Afficher/Masquer" + }, + "toggleCollapse": { + "message": "Déplier ou replier", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Nom du titulaire de la carte" + }, + "number": { + "message": "Numéro" + }, + "brand": { + "message": "Réseau de paiement" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Code de sécurité" + }, + "identityName": { + "message": "Identité" + }, + "company": { + "message": "Société" + }, + "ssn": { + "message": "Numéro de sécurité sociale" + }, + "passportNumber": { + "message": "Numéro de passeport" + }, + "licenseNumber": { + "message": "Numéro de permis" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Téléphone" + }, + "address": { + "message": "Adresse" + }, + "premiumRequired": { + "message": "Adhésion Premium requise" + }, + "premiumRequiredDesc": { + "message": "Une adhésion premium est requise pour utiliser cette fonctionnalité." + }, + "errorOccurred": { + "message": "Une erreur est survenue." + }, + "error": { + "message": "Erreur" + }, + "january": { + "message": "Janvier" + }, + "february": { + "message": "Février" + }, + "march": { + "message": "Mars" + }, + "april": { + "message": "Avril" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juin" + }, + "july": { + "message": "Juillet" + }, + "august": { + "message": "Août" + }, + "september": { + "message": "Septembre" + }, + "october": { + "message": "Octobre" + }, + "november": { + "message": "Novembre" + }, + "december": { + "message": "Décembre" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titre" + }, + "mr": { + "message": "M." + }, + "mrs": { + "message": "Mme" + }, + "ms": { + "message": "Mlle" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Mois d'expiration" + }, + "expirationYear": { + "message": "Année d'expiration" + }, + "select": { + "message": "Sélectionner" + }, + "other": { + "message": "Autre" + }, + "generatePassword": { + "message": "Générer un mot de passe" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "Prénom" + }, + "middleName": { + "message": "Deuxième prénom" + }, + "lastName": { + "message": "Nom" + }, + "fullName": { + "message": "Nom et prénom" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "Ville" + }, + "stateProvince": { + "message": "État / Région" + }, + "zipPostalCode": { + "message": "Code postal" + }, + "country": { + "message": "Pays" + }, + "save": { + "message": "Enregistrer" + }, + "cancel": { + "message": "Annuler" + }, + "delete": { + "message": "Supprimer" + }, + "favorite": { + "message": "Favori" + }, + "edit": { + "message": "Modifier" + }, + "authenticatorKeyTotp": { + "message": "Clé d'authentification (TOTP)" + }, + "folder": { + "message": "Dossier" + }, + "newCustomField": { + "message": "Nouveau champ personnalisé" + }, + "value": { + "message": "Valeur" + }, + "dragToSort": { + "message": "Glissez pour trier" + }, + "cfTypeText": { + "message": "Texte" + }, + "cfTypeHidden": { + "message": "Masqué" + }, + "cfTypeBoolean": { + "message": "Booléen" + }, + "cfTypeLinked": { + "message": "Lié", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Valeur liée", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Supprimer" + }, + "nameRequired": { + "message": "Le nom est requis." + }, + "addedItem": { + "message": "Élément ajouté" + }, + "editedItem": { + "message": "Élément modifié" + }, + "deleteItem": { + "message": "Supprimer l'élément" + }, + "deleteFolder": { + "message": "Supprimer le dossier" + }, + "deleteAttachment": { + "message": "Supprimer la pièce jointe" + }, + "deleteItemConfirmation": { + "message": "Êtes-vous sûr de vouloir envoyer cet élément vers la corbeille ?" + }, + "deletedItem": { + "message": "L'élément a été envoyé à la corbeille" + }, + "overwritePasswordConfirmation": { + "message": "Êtes-vous sûr de vouloir écraser le mot de passe actuel ?" + }, + "overwriteUsername": { + "message": "Remplacer le nom d'utilisateur" + }, + "overwriteUsernameConfirmation": { + "message": "Êtes-vous sûr(e) de vouloir remplacer le mot de passe actuel ?" + }, + "noneFolder": { + "message": "Aucun dossier", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Ajouter un dossier" + }, + "editFolder": { + "message": "Modifier le dossier" + }, + "regeneratePassword": { + "message": "Générer un nouveau mot de passe" + }, + "copyPassword": { + "message": "Copier le mot de passe" + }, + "copyUri": { + "message": "Copier l'URI" + }, + "copyVerificationCodeTotp": { + "message": "Copier le code de vérification (TOTP)" + }, + "length": { + "message": "Longueur" + }, + "numWords": { + "message": "Nombre de mots" + }, + "wordSeparator": { + "message": "Séparateur de mots" + }, + "capitalize": { + "message": "Mettre la première lettre de chaque mot en majuscule", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inclure un chiffre" + }, + "close": { + "message": "Fermer" + }, + "minNumbers": { + "message": "Nombre minimum de chiffres" + }, + "minSpecial": { + "message": "Nombre minimum de caractères spéciaux", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Éviter les caractères ambigus" + }, + "searchCollection": { + "message": "Rechercher dans la collection" + }, + "searchFolder": { + "message": "Rechercher dans le dossier" + }, + "searchFavorites": { + "message": "Rechercher dans les favoris" + }, + "searchType": { + "message": "Rechercher dans le type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Ajouter une nouvelle pièce jointe" + }, + "deletedAttachment": { + "message": "Pièce jointe supprimée" + }, + "deleteAttachmentConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer cette pièce jointe ?" + }, + "attachmentSaved": { + "message": "La pièce jointe a été enregistrée." + }, + "file": { + "message": "Fichier" + }, + "selectFile": { + "message": "Sélectionnez un fichier." + }, + "maxFileSize": { + "message": "La taille maximale du fichier est de 500 Mo." + }, + "updateKey": { + "message": "Vous ne pouvez pas utiliser cette fonctionnalité tant que vous ne mettez pas à jour votre clé de chiffrement." + }, + "editedFolder": { + "message": "Dossier modifié" + }, + "addedFolder": { + "message": "Dossier ajouté" + }, + "deleteFolderConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer ce dossier ?" + }, + "deletedFolder": { + "message": "Dossier supprimé" + }, + "loginOrCreateNewAccount": { + "message": "Identifiez-vous ou créez un nouveau compte pour accéder à votre coffre sécurisé." + }, + "createAccount": { + "message": "Créer un compte" + }, + "logIn": { + "message": "S'identifier" + }, + "submit": { + "message": "Soumettre" + }, + "masterPass": { + "message": "Mot de passe maître" + }, + "masterPassDesc": { + "message": "Le mot de passe maître est le mot de passe que vous utilisez pour accéder à votre coffre. Il est très important de ne pas l'oublier. Il n'existe aucun moyen de le récupérer si vous le perdez." + }, + "masterPassHintDesc": { + "message": "Un indice de mot de passe maître peut vous aider à vous rappeler de votre mot de passe en cas d'oubli." + }, + "reTypeMasterPass": { + "message": "Saisissez à nouveau le mot de passe maître" + }, + "masterPassHint": { + "message": "Indice du mot de passe maître (facultatif)" + }, + "settings": { + "message": "Paramètres" + }, + "passwordHint": { + "message": "Indice du mot de passe" + }, + "enterEmailToGetHint": { + "message": "Saisissez l'adresse e-mail de votre compte pour recevoir l'indice de votre mot de passe maître." + }, + "getMasterPasswordHint": { + "message": "Obtenir l'indice du mot de passe maître" + }, + "emailRequired": { + "message": "L'adresse e-mail est requise." + }, + "invalidEmail": { + "message": "Adresse e-mail invalide." + }, + "masterPassRequired": { + "message": "Le mot de passe maître est requis." + }, + "masterPassLength": { + "message": "Le mot de passe maître doit au moins contenir 8 caractères." + }, + "masterPassDoesntMatch": { + "message": "La confirmation du mot de passe maître ne correspond pas." + }, + "newAccountCreated": { + "message": "Votre nouveau compte a été créé ! Vous pouvez maintenant vous authentifier." + }, + "masterPassSent": { + "message": "Nous vous avons envoyé un e-mail contenant votre indice de mot de passe maître." + }, + "unexpectedError": { + "message": "Une erreur inattendue est survenue." + }, + "itemInformation": { + "message": "Informations sur l'élément" + }, + "noItemsInList": { + "message": "Aucun élément à afficher." + }, + "sendVerificationCode": { + "message": "Envoyer un code de vérification à votre adresse email" + }, + "sendCode": { + "message": "Envoyer le code" + }, + "codeSent": { + "message": "Code envoyé" + }, + "verificationCode": { + "message": "Code de vérification" + }, + "confirmIdentity": { + "message": "Confirmez votre identité pour continuer." + }, + "verificationCodeRequired": { + "message": "Le code de vérification est requis." + }, + "invalidVerificationCode": { + "message": "Code de vérification invalide" + }, + "continue": { + "message": "Continuer" + }, + "enterVerificationCodeApp": { + "message": "Saisissez le code de vérification à 6 chiffres depuis votre application d'authentification." + }, + "enterVerificationCodeEmail": { + "message": "Saisissez le code de vérification à 6 chiffres qui vous a été envoyé par e-mail à $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mail de vérification envoyé à $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Rester connecté" + }, + "sendVerificationCodeEmailAgain": { + "message": "Envoyer à nouveau l'e-mail du code de vérification" + }, + "useAnotherTwoStepMethod": { + "message": "Utiliser une autre méthode de connexion en deux étapes" + }, + "insertYubiKey": { + "message": "Insérez votre YubiKey dans le port USB de votre ordinateur puis appuyez sur son bouton." + }, + "insertU2f": { + "message": "Insérez votre clé de sécurité dans le port USB de votre ordinateur. S'il dispose d'un bouton, appuyez dessus." + }, + "recoveryCodeDesc": { + "message": "Accès perdu à tous vos services d'authentification à double facteurs ? Utilisez votre code de récupération pour désactiver tous les services de double authentifications sur votre compte." + }, + "recoveryCodeTitle": { + "message": "Code de récupération" + }, + "authenticatorAppTitle": { + "message": "Application d'authentification" + }, + "authenticatorAppDesc": { + "message": "Utiliser une application d'authentification (comme Authy ou Google Authenticator) pour générer des codes de vérification basés sur le temps.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Clé de sécurité YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utiliser une YubiKey pour accéder à votre compte. Fonctionne avec les appareils YubiKey 4, 4 Nano, 4C et NEO." + }, + "duoDesc": { + "message": "S'authentifier avec Duo Security via l'application Duo Mobile, un SMS, un appel téléphonique, ou une clé de sécurité U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Sécurisez votre organisation avec Duo Security à l'aide de l'application Duo Mobile, l'envoi d'un SMS, un appel vocal ou une clé de sécurité U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "WebAuthn FIDO2" + }, + "webAuthnDesc": { + "message": "Utilisez n'importe quelle clé de sécurité compatible WebAuthn pour accéder à votre compte." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Les codes de vérification vont vous être envoyés par e-mail." + }, + "loginUnavailable": { + "message": "Connexion impossible" + }, + "noTwoStepProviders": { + "message": "Ce compte dispose d'une authentification en deux étapes, cependant aucun de vos services d'authentification en deux étapes n'est supporté par cet appareil." + }, + "noTwoStepProviders2": { + "message": "Veuillez ajouter des services additionnels qui supportent une utilisation sur plusieurs appareils (comme une application d'authentification)." + }, + "twoStepOptions": { + "message": "Options d'identification en deux étapes" + }, + "selfHostedEnvironment": { + "message": "Environnement auto-hébergé" + }, + "selfHostedEnvironmentFooter": { + "message": "Spécifiez l'URL de base de votre installation Bitwarden auto-hébergée." + }, + "customEnvironment": { + "message": "Environnement personnalisé" + }, + "customEnvironmentFooter": { + "message": "Pour utilisateurs avancés. Vous pouvez spécifier une URL de base indépendante pour chaque service." + }, + "baseUrl": { + "message": "URL du serveur" + }, + "apiUrl": { + "message": "URL du serveur de l'API" + }, + "webVaultUrl": { + "message": "URL du serveur du coffre web" + }, + "identityUrl": { + "message": "URL du serveur d'identification" + }, + "notificationsUrl": { + "message": "URL du serveur de notifications" + }, + "iconsUrl": { + "message": "URL du serveur d’icônes" + }, + "environmentSaved": { + "message": "Les URLs d'environnement ont été enregistrées." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Oui" + }, + "no": { + "message": "Non" + }, + "overwritePassword": { + "message": "Écraser le mot de passe" + }, + "learnMore": { + "message": "En savoir plus" + }, + "featureUnavailable": { + "message": "Fonctionnalité non disponible" + }, + "loggedOut": { + "message": "Déconnecté" + }, + "loginExpired": { + "message": "Votre session a expiré." + }, + "logOutConfirmation": { + "message": "Êtes-vous sûr de vouloir vous déconnecter ?" + }, + "logOut": { + "message": "Déconnexion" + }, + "addNewLogin": { + "message": "Ajouter un nouvel identifiant" + }, + "addNewItem": { + "message": "Ajouter un nouvel élément" + }, + "addNewFolder": { + "message": "Ajouter un nouveau dossier" + }, + "view": { + "message": "Voir" + }, + "account": { + "message": "Compte" + }, + "loading": { + "message": "Chargement ..." + }, + "lockVault": { + "message": "Verrouiller le coffre" + }, + "passwordGenerator": { + "message": "Générateur de mot de passe" + }, + "contactUs": { + "message": "Nous contacter" + }, + "getHelp": { + "message": "Obtenir de l'aide" + }, + "fileBugReport": { + "message": "Envoyer un rapport de bug" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Suivez-nous" + }, + "syncVault": { + "message": "Synchroniser le coffre" + }, + "changeMasterPass": { + "message": "Modifier le mot de passe maître" + }, + "changeMasterPasswordConfirmation": { + "message": "Vous pouvez modifier votre mot de passe maître depuis le coffre web sur bitwarden.com. Souhaitez-vous visiter le site maintenant ?" + }, + "fingerprintPhrase": { + "message": "Phrase d'empreinte", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "La phrase d'empreinte de votre compte", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Aller au coffre web" + }, + "getMobileApp": { + "message": "Télécharger l'application mobile" + }, + "getBrowserExtension": { + "message": "Télécharger l'extension de navigateur" + }, + "syncingComplete": { + "message": "Synchronisation terminée" + }, + "syncingFailed": { + "message": "Échec de la synchronisation" + }, + "yourVaultIsLocked": { + "message": "Votre coffre est verrouillé. Vérifiez votre identité pour continuer." + }, + "unlock": { + "message": "Déverrouiller" + }, + "loggedInAsOn": { + "message": "Connecté en tant que $EMAIL$ sur $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Mot de passe maître invalide" + }, + "twoStepLoginConfirmation": { + "message": "L'identification en deux étapes sécurise davantage votre compte en vous demandant à chaque connexion de saisir un code de sécurité obtenu depuis un autre appareil, via une clé de sécurité, une application d'authentification, un SMS, un appel téléphonique, ou un e-mail. L'identification en deux étapes peut être activée depuis le coffre web sur bitwarden.com. Voulez-vous vous visiter le site web maintenant ?" + }, + "twoStepLogin": { + "message": "Identification en deux étapes" + }, + "vaultTimeout": { + "message": "Délai d'expiration du coffre" + }, + "vaultTimeoutDesc": { + "message": "Choisissez quand votre coffre expirera et effectuera l'action sélectionnée." + }, + "immediately": { + "message": "Immédiatement" + }, + "tenSeconds": { + "message": "10 secondes" + }, + "twentySeconds": { + "message": "20 secondes" + }, + "thirtySeconds": { + "message": "30 secondes" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 heure" + }, + "fourHours": { + "message": "4 heures" + }, + "onIdle": { + "message": "À l'inactivité du système" + }, + "onSleep": { + "message": "À la mise en veille du système" + }, + "onLocked": { + "message": "Au verrouillage du système" + }, + "onRestart": { + "message": "Au redémarrage" + }, + "never": { + "message": "Jamais" + }, + "security": { + "message": "Sécurité" + }, + "clearClipboard": { + "message": "Effacer le presse-papiers", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Effacer automatiquement de votre presse-papiers les valeurs copiées.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Désactiver les icônes des sites web" + }, + "disableFaviconDesc": { + "message": "Les icônes des sites web permettent d'avoir une icône reconnaissable à côté de chaque identifiant dans votre coffre." + }, + "enableMinToTray": { + "message": "Réduire dans la zone de notification" + }, + "enableMinToTrayDesc": { + "message": "Lorsque la fenêtre est réduite, afficher une icône dans la zone de notification à la place." + }, + "enableMinToMenuBar": { + "message": "Réduire dans la barre de menu" + }, + "enableMinToMenuBarDesc": { + "message": "Lorsque la fenêtre est réduite, privilégier l'affichage d'une icône dans la barre de menu." + }, + "enableCloseToTray": { + "message": "Fermer dans la zone de notification" + }, + "enableCloseToTrayDesc": { + "message": "Lorsque la fenêtre est fermée, afficher une icône dans la zone de notification." + }, + "enableCloseToMenuBar": { + "message": "Fermer vers la barre de menu" + }, + "enableCloseToMenuBarDesc": { + "message": "Lorsque la fenêtre est fermée, privilégier l'affichage d'une icône dans la barre de menu." + }, + "enableTray": { + "message": "Activer le raccourci dans la zone de notification" + }, + "enableTrayDesc": { + "message": "Toujours afficher une icône dans la zone de notification." + }, + "startToTray": { + "message": "Démarrer dans la zone de notification" + }, + "startToTrayDesc": { + "message": "Au premier démarrage de l'application, afficher uniquement une icône dans la zone de notification." + }, + "startToMenuBar": { + "message": "Démarrer dans la barre de menu" + }, + "startToMenuBarDesc": { + "message": "Au premier démarrage de l'application, afficher uniquement une icône dans la barre de menu." + }, + "openAtLogin": { + "message": "Démarrer automatiquement à la connexion" + }, + "openAtLoginDesc": { + "message": "Démarrer l'application Bitwarden automatiquement à la connexion." + }, + "alwaysShowDock": { + "message": "Toujours afficher dans le Dock" + }, + "alwaysShowDockDesc": { + "message": "Afficher l'icône Bitwarden dans le Dock même si l'application est réduite dans la barre de menus." + }, + "confirmTrayTitle": { + "message": "Confirmer la désactivation de la zone de notification" + }, + "confirmTrayDesc": { + "message": "Désactiver cette option désactivera également tous les autres paramètres liés à la zone de notifications." + }, + "language": { + "message": "Langue" + }, + "languageDesc": { + "message": "Modifier la langue utilisée par l'application. Un redémarrage est requis." + }, + "theme": { + "message": "Thème" + }, + "themeDesc": { + "message": "Modifier la couleur du thème de l'application." + }, + "dark": { + "message": "Sombre", + "description": "Dark color" + }, + "light": { + "message": "Clair", + "description": "Light color" + }, + "copy": { + "message": "Copier", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Vérifier les mises à jour" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Redémarrer pour mettre à jour" + }, + "restartToUpdateDesc": { + "message": "La version $VERSION_NUM$ est prête à être installée. Vous devez redémarrer Bitwarden pour terminer l'installation. Souhaitez-vous redémarrer et mettre à jour maintenant ?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Mise à jour disponible" + }, + "updateAvailableDesc": { + "message": "Une mise à jour a été trouvée. Souhaitez-vous la télécharger maintenant ?" + }, + "restart": { + "message": "Redémarrer" + }, + "later": { + "message": "Plus tard" + }, + "noUpdatesAvailable": { + "message": "Aucune mise à jour n'est actuellement disponible. Vous utilisez la dernière version." + }, + "updateError": { + "message": "Erreur de mise à jour" + }, + "unknown": { + "message": "Inconnu" + }, + "copyUsername": { + "message": "Copier le nom d'utilisateur" + }, + "copyNumber": { + "message": "Copier le numéro", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copier le code de sécurité", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Adhésion Premium" + }, + "premiumManage": { + "message": "Gérer l'adhésion" + }, + "premiumManageAlert": { + "message": "Vous pouvez gérer votre adhésion depuis le coffre web sur bitwarden.com. Souhaitez-vous visiter le site web maintenant ?" + }, + "premiumRefresh": { + "message": "Actualiser l'adhésion" + }, + "premiumNotCurrentMember": { + "message": "Vous n'êtes actuellement pas un membre premium." + }, + "premiumSignUpAndGet": { + "message": "Devenez un membre premium et obtenez :" + }, + "premiumSignUpStorage": { + "message": "1 Go de stockage de fichiers chiffrés." + }, + "premiumSignUpTwoStep": { + "message": "Options d'identification en deux étapes additionnelles comme YubiKey, FIDO U2F et Duo." + }, + "premiumSignUpReports": { + "message": "Rapports sur l'hygiène des mots de passe, la santé des comptes et les fuites de données pour assurer la sécurité de votre coffre." + }, + "premiumSignUpTotp": { + "message": "Génération d'un code de vérification TOTP (2FA) pour les identifiants de votre coffre." + }, + "premiumSignUpSupport": { + "message": "Support client prioritaire." + }, + "premiumSignUpFuture": { + "message": "Toutes les futures options premium. D'autres suivront prochainement !" + }, + "premiumPurchase": { + "message": "Acheter Premium" + }, + "premiumPurchaseAlert": { + "message": "Vous pouvez opter pour une adhésion premium depuis le coffre web sur bitwarden.com. Souhaitez-vous visiter le site web maintenant ?" + }, + "premiumCurrentMember": { + "message": "Vous êtes un adhérent premium !" + }, + "premiumCurrentMemberThanks": { + "message": "Merci de supporter Bitwarden." + }, + "premiumPrice": { + "message": "Tout pour seulement $PRICE$ /an !", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Actualisation terminée" + }, + "passwordHistory": { + "message": "Historique des mots de passe" + }, + "clear": { + "message": "Effacer", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Aucun mot de passe à afficher." + }, + "undo": { + "message": "Annuler" + }, + "redo": { + "message": "Rétablir" + }, + "cut": { + "message": "Couper", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Coller", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Tout sélectionner" + }, + "zoomIn": { + "message": "Zoom avant" + }, + "zoomOut": { + "message": "Zoom arrière" + }, + "resetZoom": { + "message": "Réinitialiser le zoom" + }, + "toggleFullScreen": { + "message": "Afficher en plein écran" + }, + "reload": { + "message": "Recharger" + }, + "toggleDevTools": { + "message": "Afficher/cacher les outils de développement" + }, + "minimize": { + "message": "Réduire", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Tout ramener au premier plan", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "À propos de Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Masquer Bitwarden" + }, + "hideOthers": { + "message": "Masquer les autres" + }, + "showAll": { + "message": "Tout afficher" + }, + "quitBitwarden": { + "message": "Quitter Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copié", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Aide" + }, + "window": { + "message": "Fenêtre" + }, + "checkPassword": { + "message": "Vérifier si le mot de passe a été exposé." + }, + "passwordExposed": { + "message": "Ce mot de passe a été exposé $VALUE$ fois dans des fuites de données. Vous devriez le changer.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Ce mot de passe n'a été trouvé dans aucune fuite de données connue. Il semble sécurisé." + }, + "baseDomain": { + "message": "Domaine de base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nom du domaine", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Hôte", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Commence par" + }, + "regEx": { + "message": "Expression régulière", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Détection de correspondance", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Détection de correspondance par défaut", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Afficher/masquer les options" + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Par défaut" + }, + "exit": { + "message": "Quitter" + }, + "showHide": { + "message": "Afficher/Masquer", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Masquer" + }, + "alwaysOnTop": { + "message": "Toujours au premier plan", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Mis à jour ", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Mot de passe mis à jour", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Exporter le coffre" + }, + "fileFormat": { + "message": "Format de fichier" + }, + "warning": { + "message": "AVERTISSEMENT", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirmer l'export du coffre" + }, + "exportWarningDesc": { + "message": "Cet export contient les données de votre coffre dans un format non chiffré. Vous ne devriez ni le stocker ni l'envoyer via des canaux non sécurisés (tel que par e-mail). Supprimez-le immédiatement après l'avoir utilisé." + }, + "encExportKeyWarningDesc": { + "message": "Cet export chiffre vos données en utilisant la clé de chiffrement de votre compte. Si jamais vous modifiez la clé de chiffrement de votre compte, vous devriez exporter à nouveau car vous ne pourrez pas déchiffrer ce fichier." + }, + "encExportAccountWarningDesc": { + "message": "Les clés de chiffrement du compte sont spécifiques à chaque utilisateur Bitwarden. Vous ne pouvez donc pas importer d'export chiffré dans un compte différent." + }, + "noOrganizationsList": { + "message": "Vous ne faites partie d'aucune organisation. Les organisations vous permettent de partager des éléments de façon sécurisée avec d'autres utilisateurs." + }, + "noCollectionsInList": { + "message": "Aucune collection à afficher." + }, + "ownership": { + "message": "Propriété" + }, + "whoOwnsThisItem": { + "message": "À qui appartient cet élément ?" + }, + "strong": { + "message": "Fort", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Suffisant", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Faible", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Mot de passe maître faible" + }, + "weakMasterPasswordDesc": { + "message": "Le mot de passe maître que vous avez choisi est faible. Vous devriez utiliser un mot de passe (ou une phrase secrète) fort(e) pour protéger correctement votre compte Bitwarden. Êtes-vous sûr de vouloir utiliser ce mot de passe maître ?" + }, + "pin": { + "message": "Code PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Déverrouiller avec un code PIN" + }, + "setYourPinCode": { + "message": "Définissez votre code PIN pour déverrouiller Bitwarden. Les paramètres relatifs à votre code PIN seront réinitialisés si vous vous déconnectez complètement de l'application." + }, + "pinRequired": { + "message": "Le code PIN est requis." + }, + "invalidPin": { + "message": "Code PIN invalide." + }, + "unlockWithWindowsHello": { + "message": "Déverrouiller avec Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Vérifier pour Bitwarden." + }, + "unlockWithTouchId": { + "message": "Déverrouiller avec Touch ID" + }, + "touchIdConsentMessage": { + "message": "déverouiller votre coffre" + }, + "noAutoPromptWindowsHello": { + "message": "Ne pas proposer Windows Hello au lancement." + }, + "noAutoPromptTouchId": { + "message": "Ne pas proposer Touch ID au lancement." + }, + "lockWithMasterPassOnRestart": { + "message": "Verrouiller avec le mot de passe maître lors du redémarrage" + }, + "preferences": { + "message": "Préférences" + }, + "enableMenuBar": { + "message": "Activer l'icône dans la barre de menu" + }, + "enableMenuBarDesc": { + "message": "Toujours afficher une icône dans la barre de menu." + }, + "hideToMenuBar": { + "message": "Masquer dans la barre de menu" + }, + "selectOneCollection": { + "message": "Vous devez sélectionner au moins une collection." + }, + "premiumUpdated": { + "message": "Vous venez de passer à un compte Premium." + }, + "restore": { + "message": "Restaurer" + }, + "premiumManageAlertAppStore": { + "message": "Vous pouvez gérer votre abonnement depuis l'App Store. Voulez-vous visiter l'App Store maintenant ?" + }, + "legal": { + "message": "Légal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Conditions d'utilisation" + }, + "privacyPolicy": { + "message": "Politique de confidentialité" + }, + "unsavedChangesConfirmation": { + "message": "Êtes-vous sûr de vouloir quitter ? Si vous le faites maintenant, vos informations actuelles ne seront pas sauvegardées." + }, + "unsavedChangesTitle": { + "message": "Modifications non sauvegardées" + }, + "clone": { + "message": "Cloner" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Une ou plusieurs politiques d'organisation affectent les paramètres de votre générateur." + }, + "vaultTimeoutAction": { + "message": "Action lors de l'expiration du délai du coffre" + }, + "vaultTimeoutActionLockDesc": { + "message": "Un coffre verrouillé requiert la saisie de votre mot de passe maître pour y avoir à nouveau accès." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Un coffre déconnecté nécessite que vous vous ré-authentifiez pour y accéder de nouveau." + }, + "lock": { + "message": "Verrouiller", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Corbeille", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Rechercher dans la corbeille" + }, + "permanentlyDeleteItem": { + "message": "Supprimer définitivement l'élément" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer définitivement cet élément ?" + }, + "permanentlyDeletedItem": { + "message": "Élément supprimé définitivement" + }, + "restoreItem": { + "message": "Restaurer l'élément" + }, + "restoreItemConfirmation": { + "message": "Êtes-vous sûr de vouloir restaurer cet élément ?" + }, + "restoredItem": { + "message": "Élément restauré" + }, + "permanentlyDelete": { + "message": "Supprimer définitivement" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "La déconnexion supprimera tous les accès à votre coffre et nécessite une authentification en ligne après la période d'expiration. Êtes-vous sûr de vouloir utiliser ce paramètre?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmation de l'action lors de l'expiration du délai" + }, + "enterpriseSingleSignOn": { + "message": "Portail de connexion unique d'entreprise" + }, + "setMasterPassword": { + "message": "Définir le mot de passe maître" + }, + "ssoCompleteRegistration": { + "message": "Afin de terminer la connexion avec SSO, veuillez définir un mot de passe maître pour accéder à votre coffre et le protéger." + }, + "newMasterPass": { + "message": "Nouveau mot de passe maître" + }, + "confirmNewMasterPass": { + "message": "Confirmer le nouveau mot de passe maître" + }, + "masterPasswordPolicyInEffect": { + "message": "Une ou plusieurs politiques de l'organisation exigent que votre mot de passe maître réponde aux exigences suivantes :" + }, + "policyInEffectMinComplexity": { + "message": "Score de complexité minimum de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Longueur minimale de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contenir une ou plusieurs majuscules" + }, + "policyInEffectLowercase": { + "message": "Contenir une ou plusieurs minuscules" + }, + "policyInEffectNumbers": { + "message": "Contenir un ou plusieurs chiffres" + }, + "policyInEffectSpecial": { + "message": "Contenir un ou plusieurs des caractères spéciaux suivants $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Votre nouveau mot de passe maître ne répond pas aux exigences de la politique." + }, + "acceptPolicies": { + "message": "En cochant cette case, vous acceptez les éléments suivants :" + }, + "acceptPoliciesError": { + "message": "Les conditions d'utilisation et la politique de confidentialité n'ont pas été acceptées." + }, + "enableBrowserIntegration": { + "message": "Activer l'intégration avec le navigateur" + }, + "enableBrowserIntegrationDesc": { + "message": "L'intégration avec le navigateur est utilisée pour le déverrouillage biométrique dans le navigateur." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Intégration avec le navigateur non supportée" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Malheureusement l'intégration avec le navigateur est uniquement supportée dans la version Mac App Store pour le moment." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Intégration avec le navigateur non supportée" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Malheureusement l'intégration avec le navigateur n'est pas supportée dans la version Windows Store pour le moment." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Exiger une vérification pour l'intégration avec le navigateur" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Activez une couche de sécurité supplémentaire en exigeant la validation de la phrase d'empreinte du compte lors de l'établissement d'un lien entre l'application et votre navigateur. Lorsque cette option est activée, cela nécessite une intervention et une vérification de l'utilisateur à chaque fois qu'une connexion est établie." + }, + "approve": { + "message": "Accepter" + }, + "verifyBrowserTitle": { + "message": "Vérifier la connexion au navigateur" + }, + "verifyBrowserDesc": { + "message": "Veuillez vous assurer que la phrase d'empreinte affichée est identique à celle affichée dans l'extension de navigateur." + }, + "biometricsNotEnabledTitle": { + "message": "Le déverrouillage biométrique n'est pas activé" + }, + "biometricsNotEnabledDesc": { + "message": "Les options de biométrie dans le navigateur nécessitent au préalable l'activation des options de biométrie dans l'application de bureau." + }, + "personalOwnershipSubmitError": { + "message": "En raison d'une politique d'entreprise, il vous est interdit d'enregistrer des éléments dans votre coffre personnel. Sélectionnez une organisation dans l'option Propriété et choisissez parmi les collections disponibles." + }, + "hintEqualsPassword": { + "message": "Votre indice de mot de passe ne peut pas être identique à votre nom d'utilisateur." + }, + "personalOwnershipPolicyInEffect": { + "message": "Une politique d'organisation affecte vos options de propriété." + }, + "allSends": { + "message": "Tous les Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fichier" + }, + "sendTypeText": { + "message": "Texte" + }, + "searchSends": { + "message": "Rechercher dans les Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Modifier le Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mon Coffre" + }, + "text": { + "message": "Texte" + }, + "deletionDate": { + "message": "Date de suppression" + }, + "deletionDateDesc": { + "message": "Le Send sera définitivement supprimé à la date et heure spécifiées.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Date d'expiration" + }, + "expirationDateDesc": { + "message": "Si défini, l'accès à ce Send expirera à la date et heure spécifiées.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Nombre maximum d'accès" + }, + "maxAccessCountDesc": { + "message": "Si défini, les utilisateurs ne seront plus en mesure d'accéder à ce Send une fois que le nombre maximum d'accès sera atteint.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Nombre d'accès actuel" + }, + "disableSend": { + "message": "Désactiver ce Send pour que personne ne puisse y accéder.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Vous pouvez, si vous le souhaitez, exiger un mot de passe pour accéder à ce Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notes privées à propos de ce Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Lien du Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Lien du Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Lors de l'accès à ce Send, masquer le texte par défaut", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send créé", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send modifié", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send supprimé", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nouveau mot de passe" + }, + "whatTypeOfSend": { + "message": "De quel type de Send s'agit-il ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Créer un Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Le texte que vous voulez envoyer." + }, + "sendFileDesc": { + "message": "Le fichier que vous voulez envoyer." + }, + "days": { + "message": "$DAYS$ jours", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 jour" + }, + "custom": { + "message": "Personnalisé" + }, + "deleteSendConfirmation": { + "message": "Êtes-vous sûr de vouloir supprimer ce Send ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copier le lien du Send dans le presse-papier", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copier le lien de ce Send dans mon presse-papiers lors de l'enregistrement." + }, + "sendDisabled": { + "message": "Send désactivé", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "En raison d'une politique d'entreprise, vous ne pouvez que supprimer un Send existant.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copier le lien" + }, + "disabled": { + "message": "Désactivé" + }, + "maxAccessCountReached": { + "message": "Nombre maximum d'accès atteint" + }, + "expired": { + "message": "Expiré" + }, + "pendingDeletion": { + "message": "En attente de suppression" + }, + "webAuthnAuthenticate": { + "message": "Authentifier WebAuthn" + }, + "hideEmail": { + "message": "Cacher mon adresse e-mail aux destinataires." + }, + "sendOptionsPolicyInEffect": { + "message": "Une ou plusieurs politiques d'organisation affectent vos options Send." + }, + "emailVerificationRequired": { + "message": "Vérification de l'adresse e-mail nécessaire" + }, + "emailVerificationRequiredDesc": { + "message": "Vous devez vérifier votre adresse e-mail pour utiliser cette fonctionnalité." + }, + "passwordPrompt": { + "message": "Ressaisie du mot de passe maître" + }, + "passwordConfirmation": { + "message": "Confirmation du mot de passe maître" + }, + "passwordConfirmationDesc": { + "message": "Cette action est protégée. Pour continuer, veuillez ressaisir votre mot de passe maître pour vérifier votre identité." + }, + "updatedMasterPassword": { + "message": "Mot de passe maître mis à jour" + }, + "updateMasterPassword": { + "message": "Mettre à jour le mot de passe maître" + }, + "updateMasterPasswordWarning": { + "message": "Votre mot de passe maître a récemment été modifié par un administrateur de votre organisation. Pour pouvoir accéder au coffre-fort, vous devez mettre à jour votre mot de passe maître maintenant. Poursuivre vous déconnectera de votre session actuelle, vous obligeant à vous reconnecter. Les sessions actives sur d'autres appareils peuvent rester actives jusqu'à une heure." + }, + "hours": { + "message": "Heures" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Les politiques de votre organisation affectent le délai d'expiration de votre coffre. Le délai d'expiration maximal autorisé est de $HOURS$ heure(s) et $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Le délai d'expiration de votre coffre-fort dépasse les restrictions définies par votre organisation." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscription automatique" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Cette organisation a une politique d'entreprise qui vous inscrira automatiquement à la réinitialisation du mot de passe. L'inscription permettra aux administrateurs de l'organisation de changer votre mot de passe maître." + }, + "vaultExportDisabled": { + "message": "Export du coffre désactivé" + }, + "personalVaultExportPolicyInEffect": { + "message": "Une ou plusieurs politiques d'organisation vous empêchent d'exporter votre coffre personnel." + }, + "addAccount": { + "message": "Ajouter un compte" + }, + "removeMasterPassword": { + "message": "Supprimer le mot de passe maître" + }, + "removedMasterPassword": { + "message": "Mot de passe maître supprimé." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ utilise SSO avec un serveur de clés auto-hébergé. Un mot de passe maître n'est plus nécessaire aux membres de cette organisation pour se connecter.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Quitter l'organisation" + }, + "leaveOrganizationConfirmation": { + "message": "Êtes-vous sûr de vouloir quitter cette organisation ?" + }, + "leftOrganization": { + "message": "Vous avez quitté l'organisation." + }, + "ssoKeyConnectorUnavailable": { + "message": "Impossible de contacter Key Connector, réessayez plus tard." + }, + "lockAllVaults": { + "message": "Verrouiller tous les coffres" + }, + "accountLimitReached": { + "message": "Vous ne pouvez pas connecter plus de 5 comptes en même temps." + }, + "accountPreferences": { + "message": "Préférences" + }, + "appPreferences": { + "message": "Paramètres de l'application (tous les comptes)" + }, + "accountSwitcherLimitReached": { + "message": "Limite de comptes atteinte. Déconnectez-vous d'un compte pour en ajouter un nouveau." + }, + "settingsTitle": { + "message": "Paramètres de l'application pour $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Changer de compte" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Votre session a expiré. Veuillez revenir en arrière et essayer de vous connecter à nouveau." + }, + "exportingPersonalVaultTitle": { + "message": "Export du coffre personnel" + }, + "exportingPersonalVaultDescription": { + "message": "Seuls les éléments du coffre personnel associé à l'adresse e-mail $EMAIL$ seront exportés. Les éléments du coffre de l'organisation ne seront pas inclus.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Générateur" + }, + "whatWouldYouLikeToGenerate": { + "message": "Que souhaitez-vous générer ?" + }, + "passwordType": { + "message": "Type de mot de passe" + }, + "regenerateUsername": { + "message": "Régénérer le nom d'utilisateur" + }, + "generateUsername": { + "message": "Générer le nom d'utilisateur" + }, + "usernameType": { + "message": "Type de nom d'utilisateur" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Utilisez les capacités de sous-adressage de votre fournisseur de courriel." + }, + "catchallEmail": { + "message": "Collecteur d'email" + }, + "catchallEmailDesc": { + "message": "Utilisez la boîte de réception du collecteur configurée de votre domaine." + }, + "random": { + "message": "Aléatoire" + }, + "randomWord": { + "message": "Mots aléatoire" + }, + "websiteName": { + "message": "Nom du site Web" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/he/messages.json b/apps/desktop/src/locales/he/messages.json new file mode 100644 index 0000000000..526344dd58 --- /dev/null +++ b/apps/desktop/src/locales/he/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "מסננים" + }, + "allItems": { + "message": "כל הפריטים" + }, + "favorites": { + "message": "מועדפים" + }, + "types": { + "message": "סוגים" + }, + "typeLogin": { + "message": "פרטי התחברות" + }, + "typeCard": { + "message": "כרטיס" + }, + "typeIdentity": { + "message": "זהות" + }, + "typeSecureNote": { + "message": "תזכורת מאובטחת" + }, + "folders": { + "message": "תיקיות" + }, + "collections": { + "message": "אוספים" + }, + "searchVault": { + "message": "חפש כספת" + }, + "addItem": { + "message": "הוסף פריט" + }, + "shared": { + "message": "משותף" + }, + "share": { + "message": "שתף" + }, + "moveToOrganization": { + "message": "העברה לארגון" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ הועבר ל־$ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "בחר ארגון שאליו ברצונך להעביר פריט זה. ההעברה לארגון מעבירה את הבעלות על הפריט לאותו ארגון. לאחר העברת פריט זה לא תוכל עוד לקבוע באופן ישיר הבעלות." + }, + "attachments": { + "message": "קבצים מצורפים" + }, + "viewItem": { + "message": "צפה בפריט" + }, + "name": { + "message": "שם" + }, + "uri": { + "message": "כתובת" + }, + "uriPosition": { + "message": "כתובת $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "כתובת חדשה" + }, + "username": { + "message": "שם משתמש" + }, + "password": { + "message": "סיסמה" + }, + "passphrase": { + "message": "משפט סיסמה" + }, + "editItem": { + "message": "ערוך פריט" + }, + "emailAddress": { + "message": "כתובת אימייל" + }, + "verificationCodeTotp": { + "message": "קוד אימות (TOTP)" + }, + "website": { + "message": "אתר" + }, + "notes": { + "message": "פתקים" + }, + "customFields": { + "message": "שדות מותאמים אישית" + }, + "launch": { + "message": "פתח" + }, + "copyValue": { + "message": "העתק ערך", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "מזעור בעת העתקה ללוח" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "מזער את החלון בזמן העתקה של מידע מפריט ללוח." + }, + "toggleVisibility": { + "message": "הצג או הסתר" + }, + "toggleCollapse": { + "message": "הצג או הסתר", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "שם בעל הכרטיס" + }, + "number": { + "message": "מספר" + }, + "brand": { + "message": "מותג" + }, + "expiration": { + "message": "תוקף" + }, + "securityCode": { + "message": "קוד אבטחה" + }, + "identityName": { + "message": "שם זהות" + }, + "company": { + "message": "חברה" + }, + "ssn": { + "message": "מספר ביטוח לאומי" + }, + "passportNumber": { + "message": "מספר דרכון" + }, + "licenseNumber": { + "message": "מספר רשיון" + }, + "email": { + "message": "אימייל" + }, + "phone": { + "message": "טלפון" + }, + "address": { + "message": "כתובת" + }, + "premiumRequired": { + "message": "נדרש חשבון פרימיום" + }, + "premiumRequiredDesc": { + "message": "בכדי להשתמש ביכולת זו יש צורך בחשבון פרמיום." + }, + "errorOccurred": { + "message": "אירעה שגיאה." + }, + "error": { + "message": "שגיאה" + }, + "january": { + "message": "ינואר" + }, + "february": { + "message": "פברואר" + }, + "march": { + "message": "מרץ" + }, + "april": { + "message": "אפריל" + }, + "may": { + "message": "מאי" + }, + "june": { + "message": "יוני" + }, + "july": { + "message": "יולי" + }, + "august": { + "message": "אוגוסט" + }, + "september": { + "message": "ספטמבר" + }, + "october": { + "message": "אוקטובר" + }, + "november": { + "message": "נובמבר" + }, + "december": { + "message": "דצמבר" + }, + "ex": { + "message": "לדוגמא", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "תואר" + }, + "mr": { + "message": "מר" + }, + "mrs": { + "message": "גברת" + }, + "ms": { + "message": "העלמה" + }, + "dr": { + "message": "דוקטור" + }, + "expirationMonth": { + "message": "תוקף אשראי - חודש" + }, + "expirationYear": { + "message": "תוקף אשראי - שנה" + }, + "select": { + "message": "בחר" + }, + "other": { + "message": "אחר" + }, + "generatePassword": { + "message": "צור סיסמה" + }, + "type": { + "message": "סוג" + }, + "firstName": { + "message": "שם פרטי" + }, + "middleName": { + "message": "שם אמצעי" + }, + "lastName": { + "message": "שם משפחה" + }, + "fullName": { + "message": "שם מלא" + }, + "address1": { + "message": "כתובת 1" + }, + "address2": { + "message": "כתובת 2" + }, + "address3": { + "message": "כתובת 3" + }, + "cityTown": { + "message": "עיר \\ יישוב" + }, + "stateProvince": { + "message": "מדינה \\ מחוז" + }, + "zipPostalCode": { + "message": "מיקוד" + }, + "country": { + "message": "מדינה" + }, + "save": { + "message": "שמור" + }, + "cancel": { + "message": "ביטול" + }, + "delete": { + "message": "מחק" + }, + "favorite": { + "message": "מועדף" + }, + "edit": { + "message": "ערוך" + }, + "authenticatorKeyTotp": { + "message": "מפתח אימות (TOTP)" + }, + "folder": { + "message": "תיקייה" + }, + "newCustomField": { + "message": "שדה מותאם אישית חדש" + }, + "value": { + "message": "ערך" + }, + "dragToSort": { + "message": "גרור כדי למיין" + }, + "cfTypeText": { + "message": "טקסט" + }, + "cfTypeHidden": { + "message": "מוסתר" + }, + "cfTypeBoolean": { + "message": "אמת או שקר" + }, + "cfTypeLinked": { + "message": "מקושר", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "ערך מקושר", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "הסר" + }, + "nameRequired": { + "message": "דרוש שם." + }, + "addedItem": { + "message": "פריט שהתווסף" + }, + "editedItem": { + "message": "פריט שנערך" + }, + "deleteItem": { + "message": "מחק פריט" + }, + "deleteFolder": { + "message": "מחק תיקייה" + }, + "deleteAttachment": { + "message": "מחק קובץ מצורף" + }, + "deleteItemConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק פריט זה?" + }, + "deletedItem": { + "message": "פריט נשלח לסל המחזור" + }, + "overwritePasswordConfirmation": { + "message": "האם אתה בטוח שברצונך לדרוס את הסיסמה הנוכחית?" + }, + "overwriteUsername": { + "message": "כתוב מחדש את שם המשתמש" + }, + "overwriteUsernameConfirmation": { + "message": "האם אתה בטוח שברצונך לדרוס את שם המשתמש הנוכחי?" + }, + "noneFolder": { + "message": "ללא תיקיה", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "הוסף תיקיה" + }, + "editFolder": { + "message": "ערוך תיקייה" + }, + "regeneratePassword": { + "message": "צור סיסמה חדשה" + }, + "copyPassword": { + "message": "העתק סיסמה" + }, + "copyUri": { + "message": "העתק שורת כתובת" + }, + "copyVerificationCodeTotp": { + "message": "העתקת קוד אימות (TOTP)" + }, + "length": { + "message": "אורך" + }, + "numWords": { + "message": "מספר מילים" + }, + "wordSeparator": { + "message": "מפריד מילים" + }, + "capitalize": { + "message": "הפוך אותיות ראשונות לגדולות", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "כלול מספרים" + }, + "close": { + "message": "סגור" + }, + "minNumbers": { + "message": "מינימום ספרות" + }, + "minSpecial": { + "message": "מינימום תווים מיוחדים", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "המנע מאותיות ותווים דומים" + }, + "searchCollection": { + "message": "חפש אוסף" + }, + "searchFolder": { + "message": "חפש תיקייה" + }, + "searchFavorites": { + "message": "חפש מועדפים" + }, + "searchType": { + "message": "חפש סוג", + "description": "Search item type" + }, + "newAttachment": { + "message": "צרף קובץ חדש" + }, + "deletedAttachment": { + "message": "קובץ מצורף שנמחק" + }, + "deleteAttachmentConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק קובץ מצורף זה?" + }, + "attachmentSaved": { + "message": "הקובץ המצורף נשמר." + }, + "file": { + "message": "קובץ" + }, + "selectFile": { + "message": "בחירת קובץ." + }, + "maxFileSize": { + "message": "גודל הקובץ המירבי הוא 500 מגה." + }, + "updateKey": { + "message": "לא ניתן להשתמש ביכולת זו עד שתעדכן את מפתח ההצפנה שלך." + }, + "editedFolder": { + "message": "תיקיה שנערכה" + }, + "addedFolder": { + "message": "תיקיה שנוספה" + }, + "deleteFolderConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק את התיקייה?" + }, + "deletedFolder": { + "message": "תיקיה שנמחקה" + }, + "loginOrCreateNewAccount": { + "message": "היכנס או צור חשבון חדש כדי לגשת לכספת המאובטחת שלך." + }, + "createAccount": { + "message": "צור חשבון" + }, + "logIn": { + "message": "התחבר" + }, + "submit": { + "message": "שלח" + }, + "masterPass": { + "message": "סיסמה ראשית" + }, + "masterPassDesc": { + "message": "הסיסמה הראשית היא הסיסמה שבאמצעותה תיגש לכספת שלך. חשוב מאוד שלא תשכח את הסיסמה הזו. אין שום דרך לשחזר אותה במקרה ושכחת אותה." + }, + "masterPassHintDesc": { + "message": "ניתן להשתמש ברמז לסיסמה הראשית אם שכחת אותה." + }, + "reTypeMasterPass": { + "message": "הקלד שוב סיסמה ראשית" + }, + "masterPassHint": { + "message": "רמז לסיסמה ראשית (אופציונאלי)" + }, + "settings": { + "message": "הגדרות" + }, + "passwordHint": { + "message": "רמז לסיסמה" + }, + "enterEmailToGetHint": { + "message": "הכנס את כתובת האימייל שלך לקבלת רמז עבור הסיסמה הראשית." + }, + "getMasterPasswordHint": { + "message": "הצג את הרמז לסיסמה הראשית" + }, + "emailRequired": { + "message": "נדרשת כתובת אימייל." + }, + "invalidEmail": { + "message": "כתובת אימייל לא תקינה." + }, + "masterPassRequired": { + "message": "יש להזין את הסיסמה הראשית." + }, + "masterPassLength": { + "message": "הסיסמה הראשית חייבת להיות לפחות באורך 8 תווים." + }, + "masterPassDoesntMatch": { + "message": "אימות סיסמה ראשית אינו תואם." + }, + "newAccountCreated": { + "message": "החשבון החדש שלך נוצר בהצלחה! כעת ניתן להתחבר למערכת." + }, + "masterPassSent": { + "message": "שלחנו לך אימייל עם רמז לסיסמה הראשית." + }, + "unexpectedError": { + "message": "אירעה שגיאה לא צפויה." + }, + "itemInformation": { + "message": "מידע על הפריט" + }, + "noItemsInList": { + "message": "אין פריטים להצגה ברשימה." + }, + "sendVerificationCode": { + "message": "שליחת קוד אימות לדוא״ל שלך" + }, + "sendCode": { + "message": "שליחת קוד" + }, + "codeSent": { + "message": "קוד נשלח" + }, + "verificationCode": { + "message": "קוד אימות" + }, + "confirmIdentity": { + "message": "יש לאשר את זהותך כדי להמשיך." + }, + "verificationCodeRequired": { + "message": "נדרש קוד אימות." + }, + "invalidVerificationCode": { + "message": "קוד אימות שגוי" + }, + "continue": { + "message": "המשך" + }, + "enterVerificationCodeApp": { + "message": "הכנס את קוד האימות בן 6 הספרות מאפליקציית האימות שלך." + }, + "enterVerificationCodeEmail": { + "message": "הכנס את קוד האימות בן 6 הספרות שנשלח ל-$EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "מייל אימות נשלח לכתובת $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "זכור אותי" + }, + "sendVerificationCodeEmailAgain": { + "message": "שלח שוב קוד אימות לאימייל" + }, + "useAnotherTwoStepMethod": { + "message": "השתמש בשיטה אחרת עבור כניסה דו שלבית" + }, + "insertYubiKey": { + "message": "הכנס את ה-YubiKey אל כניסת ה-USB במחשבך, ואז גע בכפתור שלו." + }, + "insertU2f": { + "message": "הכנס את מפתח האבטחה שלך אל כניסת ה-USB במחשבך. אם יש לו כפתור, גע בו." + }, + "recoveryCodeDesc": { + "message": "איבדת גישה לכל ספקי האימות הדו-שלבי שלך? השתמש בקוד האימות כדי לבטל את הספקים הקיימים מתוך החשבון שלך." + }, + "recoveryCodeTitle": { + "message": "קוד שחזור" + }, + "authenticatorAppTitle": { + "message": "אפליקציית אימות" + }, + "authenticatorAppDesc": { + "message": "השתמש באפליקצית אימות (כמו לדוגמא Authy או Google Authenticator) לייצור סיסמאות אימות מבוססות זמן.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "מפתח אבטחה OTP של YubiKey" + }, + "yubiKeyDesc": { + "message": "השתמש בYubiKey עבור גישה לחשבון שלך. עובד עם YubiKey בגירסאות 4, 4C, 4Nano, ומכשירי NEO." + }, + "duoDesc": { + "message": "בצע אימות מול Duo Security באמצעות אפליקצית Duo לפלאפון, SMS, שיחת טלפון, או מפתח אבטחה U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "בצע אימות מול Duo Security עבור הארגון שלך באמצעות אפליקצית Duo לפלאפון, SMS, שיחת טלפון, או מפתח אבטחה U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "השתמש בכל מפתח אבטחה המותאם ל- WebAuthn כדי לגשת לחשבונך." + }, + "emailTitle": { + "message": "אימייל" + }, + "emailDesc": { + "message": "קודים לאימות יישלחו אליך באימייל." + }, + "loginUnavailable": { + "message": "פרטי כניסה לא זמינים" + }, + "noTwoStepProviders": { + "message": "כניסה דו-שלבית פעילה בחשבון זה, אך אף אחד מספקי הכניסה הדו-שלבית לא נתמכים במכשיר זה." + }, + "noTwoStepProviders2": { + "message": "אנא הוסף ספקים אחרים שיש להם תמיכה במכשירים נוספים (לדוגמא - אפליקציית אימות)." + }, + "twoStepOptions": { + "message": "אפשרויות כניסה דו שלבית" + }, + "selfHostedEnvironment": { + "message": "סביבה על שרתים מקומיים" + }, + "selfHostedEnvironmentFooter": { + "message": "הזן את כתובת השרת המקומי של Bitwarden." + }, + "customEnvironment": { + "message": "סביבה מותאמת אישית" + }, + "customEnvironmentFooter": { + "message": "למשתמשים מתקדמים. באפשרותך לציין את כתובת השרת עבור כל שירות בנפרד." + }, + "baseUrl": { + "message": "כתובת שרת" + }, + "apiUrl": { + "message": "כתובת שרת הAPI" + }, + "webVaultUrl": { + "message": "כתובת שרת הכספת" + }, + "identityUrl": { + "message": "כתובת שרת הזהות" + }, + "notificationsUrl": { + "message": "כתובת שרת הודעות" + }, + "iconsUrl": { + "message": "כתובת שרת אייקונים" + }, + "environmentSaved": { + "message": "כתובות הסביבה נשמרו." + }, + "ok": { + "message": "אישור" + }, + "yes": { + "message": "כן" + }, + "no": { + "message": "לא" + }, + "overwritePassword": { + "message": "דרוס סיסמה" + }, + "learnMore": { + "message": "למידע נוסף" + }, + "featureUnavailable": { + "message": "יכולת זו לא זמינה" + }, + "loggedOut": { + "message": "בוצעה יציאה" + }, + "loginExpired": { + "message": "תוקף החיבור שלך הסתיים." + }, + "logOutConfirmation": { + "message": "האם אתה בטוח שברצונך להתנתק?" + }, + "logOut": { + "message": "התנתק" + }, + "addNewLogin": { + "message": "הוסף פרטי כניסה חדשה" + }, + "addNewItem": { + "message": "הוספת פריט חדש" + }, + "addNewFolder": { + "message": "הוספת תיקייה חדשה" + }, + "view": { + "message": "הצג" + }, + "account": { + "message": "חשבון" + }, + "loading": { + "message": "טוען..." + }, + "lockVault": { + "message": "נעילת כספת" + }, + "passwordGenerator": { + "message": "יוצר הסיסמאות" + }, + "contactUs": { + "message": "יצירת קשר אתנו" + }, + "getHelp": { + "message": "קבלת עזרה" + }, + "fileBugReport": { + "message": "דווח על באג" + }, + "blog": { + "message": "בלוג" + }, + "followUs": { + "message": "עקוב אחרינו" + }, + "syncVault": { + "message": "סנכרן כספת" + }, + "changeMasterPass": { + "message": "החלף סיסמה ראשית" + }, + "changeMasterPasswordConfirmation": { + "message": "באפשרותך לשנות את הסיסמה הראשית שלך דרך הכספת באתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "fingerprintPhrase": { + "message": "סיסמת טביעת אצבע", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "הסיסמה של טביעת האצבעות בחשבון שלך", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "עבור לכספת באתר" + }, + "getMobileApp": { + "message": "הורד את האפליקציה לפלאפון" + }, + "getBrowserExtension": { + "message": "הורד תוסף לדפדפן" + }, + "syncingComplete": { + "message": "הסינכרון הושלם" + }, + "syncingFailed": { + "message": "הסינכרון נכשל" + }, + "yourVaultIsLocked": { + "message": "הכספת שלך נעולה. הזן את הסיסמה הראשית שלך כדי להמשיך." + }, + "unlock": { + "message": "בטל נעילה" + }, + "loggedInAsOn": { + "message": "מחובר כ $EMAIL$ באתר $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "סיסמה ראשית שגויה" + }, + "twoStepLoginConfirmation": { + "message": "התחברות בשני-שלבים הופכת את החשבון שלך למאובטח יותר בכך שאתה נדרש לוודא בכל כניסה בעזרת מכשיר אחר כדוגמת מפתח אבטחה, תוכנת אימות, SMS, שיחת טלפון, או אימייל. ניתן להפעיל את \"התחברות בשני-שלבים\" בכספת שבאתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "twoStepLogin": { + "message": "התחברות בשני-שלבים" + }, + "vaultTimeout": { + "message": "משך זמן מירבי עבור חיבור לכספת" + }, + "vaultTimeoutDesc": { + "message": "בחר כמה זמן יעבור כדי שהכספת תסגר לאחר חוסר פעילות ותבצע את הפעולה שנבחרה." + }, + "immediately": { + "message": "באופן מיידי" + }, + "tenSeconds": { + "message": "10 שניות" + }, + "twentySeconds": { + "message": "20 שניות" + }, + "thirtySeconds": { + "message": "30 שניות" + }, + "oneMinute": { + "message": "דקה אחת" + }, + "twoMinutes": { + "message": "2 דקות" + }, + "fiveMinutes": { + "message": "5 דקות" + }, + "fifteenMinutes": { + "message": "15 דקות" + }, + "thirtyMinutes": { + "message": "30 דקות" + }, + "oneHour": { + "message": "שעה אחת" + }, + "fourHours": { + "message": "4 שעות" + }, + "onIdle": { + "message": "כשהמערכת מזהה חוסר פעילות" + }, + "onSleep": { + "message": "כשהמערכת נכנסת למצב שינה" + }, + "onLocked": { + "message": "בזמן נעילת המערכת" + }, + "onRestart": { + "message": "בהפעלה מחדש" + }, + "never": { + "message": "לעולם לא" + }, + "security": { + "message": "אבטחה" + }, + "clearClipboard": { + "message": "נקה לוח העתקות", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "נקה אוטומטית ערכים שהועתקו ללוח ההעתקות (clipboard).", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "בטל אייקונים של האתר" + }, + "disableFaviconDesc": { + "message": "יכולת הצג אייקונים-של-האתר מאפשרת הצגה של תמונה או אייקון מוכר ליד פרטי הכניסה שבכספת שלך." + }, + "enableMinToTray": { + "message": "מזער למגש המערכת" + }, + "enableMinToTrayDesc": { + "message": "בלחיצה על מזעור החלון, יופיע אייקון במגש המערכת (לרוב, ליד השעון)." + }, + "enableMinToMenuBar": { + "message": "מזער למגש המערכת" + }, + "enableMinToMenuBarDesc": { + "message": "במזעור חלון, הצג סמל במגש המערכת." + }, + "enableCloseToTray": { + "message": "סגור למגש המערכת" + }, + "enableCloseToTrayDesc": { + "message": "בלחיצה על סגירת החלון, יופיע אייקון במגש המערכת (לרוב, ליד השעון)." + }, + "enableCloseToMenuBar": { + "message": "סגור למגש המערכת" + }, + "enableCloseToMenuBarDesc": { + "message": "בעת סגירת חלון, הצג סמל במגש המערכת." + }, + "enableTray": { + "message": "אפשר אייקון במגש המערכת" + }, + "enableTrayDesc": { + "message": "הצג תמיד אייקון במגש המערכת." + }, + "startToTray": { + "message": "התחל עם אייקון במגש המערכת" + }, + "startToTrayDesc": { + "message": "בהפעלה הראשונה של האפליקציה, הצג אייקון במגש המערכת (מבלי לפתוח את החלון הראשי)." + }, + "startToMenuBar": { + "message": "הפעל במגש המערכת" + }, + "startToMenuBarDesc": { + "message": "בהפעלה הראשונה של האפליקציה, הצג סמל במגש המערכת." + }, + "openAtLogin": { + "message": "הפעלה אוטומטית באתחול המערכת" + }, + "openAtLoginDesc": { + "message": "התחל באופן אוטומטי את אפליקציית שולחן העבודה של Bitwarden בהתחברות." + }, + "alwaysShowDock": { + "message": "הצג תמיד ב-Dock" + }, + "alwaysShowDockDesc": { + "message": "הצג את הסמל של Bitwarden ב-Dock גם כשהתוכנה ממוזערת במגש המערכת." + }, + "confirmTrayTitle": { + "message": "אשר השבתת מגש המערכת" + }, + "confirmTrayDesc": { + "message": "השבתת הגדרה זו תשבית גם את כל ההגדרות האחרות הקשורות למגש." + }, + "language": { + "message": "שפה" + }, + "languageDesc": { + "message": "שנה את שפת האפליקציה. יש להפעיל מחדש את האפליקציה להחלת השינויים." + }, + "theme": { + "message": "ערכת נושא" + }, + "themeDesc": { + "message": "שנה את ערכת הצבע של האפליקציה." + }, + "dark": { + "message": "כהה", + "description": "Dark color" + }, + "light": { + "message": "בהיר", + "description": "Light color" + }, + "copy": { + "message": "העתק", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "חפש עדכונים" + }, + "version": { + "message": "גירסה $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "הפעל מחדש כדי לעדכן" + }, + "restartToUpdateDesc": { + "message": "גירסה מספר $VERSION_NUM$ מוכנה להתקנה. יש להפעיל מחדש את התוכנה כדי להשלים את ההתקנה. האם ברצונך להפעיל מחדש ולעדכן כעת?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "עדכון זמין" + }, + "updateAvailableDesc": { + "message": "עדכון חדש נמצא. האם ברצונך להורידו כעת?" + }, + "restart": { + "message": "הפעל מחדש" + }, + "later": { + "message": "מאוחר יותר" + }, + "noUpdatesAvailable": { + "message": "אין עדכונים חדשים זמינים כעת. הינך משתמש בגירסה האחרונה." + }, + "updateError": { + "message": "שגיאת עדכון" + }, + "unknown": { + "message": "לא ידועה" + }, + "copyUsername": { + "message": "העתק שם משתמש" + }, + "copyNumber": { + "message": "העתק מספר", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "העתק קוד אבטחה", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "חשבון פרימיום" + }, + "premiumManage": { + "message": "נהל חשבון" + }, + "premiumManageAlert": { + "message": "באפשרותך לנהל את החשבון שלך דרך הכספת באתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "premiumRefresh": { + "message": "רענן פרטי חשבון" + }, + "premiumNotCurrentMember": { + "message": "חשבונך אינו חשבון פרמיום כרגע." + }, + "premiumSignUpAndGet": { + "message": "צור חשבון פרמיום לשנה, וקבל:" + }, + "premiumSignUpStorage": { + "message": "1 ג'יגה של מקום אחסון מוצפן עבור קבצים מצורפים." + }, + "premiumSignUpTwoStep": { + "message": "אפשרויות כניסה דו שלבית מתקדמות כמו YubiKey, FIDO U2F, וDuo." + }, + "premiumSignUpReports": { + "message": "היגיינת סיסמאות, מצב בריאות החשבון, ודיווחים מעודכנים על פרצות חדשות בכדי לשמור על הכספת שלך בטוחה." + }, + "premiumSignUpTotp": { + "message": "מייצר קודי אימות TOTP עבור כניסות דו-שלביות (2FA) בכספת שלך." + }, + "premiumSignUpSupport": { + "message": "קדימות בתמיכה הטכנית." + }, + "premiumSignUpFuture": { + "message": "כל יכולות הפרימיום העתידיות שנפתח. עוד יכולות מגיעות בקרוב!" + }, + "premiumPurchase": { + "message": "רכוש פרימיום" + }, + "premiumPurchaseAlert": { + "message": "באפשרותך לרכוש מנוי פרימיום בכספת באתר bitwarden.com. האם ברצונך לפתוח את האתר כעת?" + }, + "premiumCurrentMember": { + "message": "אתה מנוי פרימיום!" + }, + "premiumCurrentMemberThanks": { + "message": "תודה על תמיכתך בBitwarden." + }, + "premiumPrice": { + "message": "הכל רק ב-$PRICE$ לשנה!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "הרענון הושלם" + }, + "passwordHistory": { + "message": "היסטוריית סיסמאות" + }, + "clear": { + "message": "נקה", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "אין סיסמאות להצגה ברשימה." + }, + "undo": { + "message": "בטל" + }, + "redo": { + "message": "בצע שוב" + }, + "cut": { + "message": "גזור", + "description": "Cut to clipboard" + }, + "paste": { + "message": "הדבק", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "בחר הכל" + }, + "zoomIn": { + "message": "הגדל" + }, + "zoomOut": { + "message": "הקטן" + }, + "resetZoom": { + "message": "איפוס זום" + }, + "toggleFullScreen": { + "message": "הפעל/הפסק מצב מסך מלא" + }, + "reload": { + "message": "רענן" + }, + "toggleDevTools": { + "message": "הצג/הסתר כלי פיתוח" + }, + "minimize": { + "message": "מזער", + "description": "Minimize window" + }, + "zoom": { + "message": "זום" + }, + "bringAllToFront": { + "message": "העבר קדימה", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "אודות Bitwarden" + }, + "services": { + "message": "שירותים" + }, + "hideBitwarden": { + "message": "הסתר את Bitwarden" + }, + "hideOthers": { + "message": "הסתר אחרים" + }, + "showAll": { + "message": "הצג הכל" + }, + "quitBitwarden": { + "message": "צא מBitwarden" + }, + "valueCopied": { + "message": "$VALUE$ הועתק", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "עזרה" + }, + "window": { + "message": "חלון" + }, + "checkPassword": { + "message": "בדוק אם הסיסמה נחשפה." + }, + "passwordExposed": { + "message": "הסיסמה הזו נחשפה $VALUE$ פעמים בפריצות אבטחה. כדאי לשנות אותה.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "הסיסמה לא נמצאה בפריצות אבטחה ידועות. היא בטוחה לשימוש." + }, + "baseDomain": { + "message": "שם בסיס הדומיין", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "שם דומיין", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "שרת", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "מדויק" + }, + "startsWith": { + "message": "מתחיל עם" + }, + "regEx": { + "message": "ביטוי רגולרי", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "זיהוי התאמה", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "ברירת מחדל לזיהוי התאמות", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "הצגה\\הסתרה של אפשרויות" + }, + "organization": { + "message": "ארגון", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "ברירת מחדל" + }, + "exit": { + "message": "יציאה" + }, + "showHide": { + "message": "הצג\\הסתר", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "הסתר למגש המערכת" + }, + "alwaysOnTop": { + "message": "תמיד מעל כל החלונות", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "עודכן", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "הסיסמה עודכנה", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "יצוא כספת" + }, + "fileFormat": { + "message": "פורמט קובץ" + }, + "warning": { + "message": "אזהרה", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "אשר ייצוא הכספת" + }, + "exportWarningDesc": { + "message": "הקובץ מכיל את פרטי הכספת שלך בפורמט לא מוצפן. מומלץ להעביר את הקובץ רק בדרכים מוצפנות, ומאוד לא מומלץ לשמור או לשלוח את הקובץ הזה בדרכים לא מוצפנות (כדוגמת סתם אימייל). מחק את הקובץ מיד לאחר שסיימת את השימוש בו." + }, + "encExportKeyWarningDesc": { + "message": "ייצוא זה מצפין את הנתונים שלך באמצעות מפתח ההצפנה של חשבונך. אם אי פעם תחדש את מפתח ההצפנה עבור חשבונך, יהיה עליך לייצא שוב מכיוון שלא תוכל לפענח מקובץ ייצוא זה." + }, + "encExportAccountWarningDesc": { + "message": "מפתחות הצפנת חשבון ייחודיים לכל חשבון משתמש של Bitwarden, כך שלא ניתן לייבא ייצוא מוצפן לחשבון אחר." + }, + "noOrganizationsList": { + "message": "אינך משויך לארגון. ניתן לשתף באופן מאובטח פריטים רק עם משתמשים אחרים בתוך ארגון." + }, + "noCollectionsInList": { + "message": "אין אוספים להצגה ברשימה." + }, + "ownership": { + "message": "בעלות" + }, + "whoOwnsThisItem": { + "message": "מי הבעלים של פריט הזה?" + }, + "strong": { + "message": "חזקה", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "טובה", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "חלשה", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "סיסמה ראשית חלשה" + }, + "weakMasterPasswordDesc": { + "message": "הסיסמה הראשית שבחרת חלשה מאוד. עליך לבחור סיסמה חזקה יותר (או להשתמש במשפט במקום מילה אחת) בכדי לאבטח את החשבון שלך. האם אתה בטוח שברצונך להשתמש בסיסמה ראשית זו?" + }, + "pin": { + "message": "קוד PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "בטל נעילה עם קוד PIN" + }, + "setYourPinCode": { + "message": "קבע קוד PIN לביטול נעילת Bitwarden. הגדרות הPIN יאופסו אם תבצע יציאה מהתוכנה." + }, + "pinRequired": { + "message": "נדרש קוד PIN." + }, + "invalidPin": { + "message": "קוד PIN לא תקין." + }, + "unlockWithWindowsHello": { + "message": "שחרור נעילה עם Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "אימות עבור Bitwarden." + }, + "unlockWithTouchId": { + "message": "שחרור נעילה עם Touch ID" + }, + "touchIdConsentMessage": { + "message": "פתח את הכספת שלך" + }, + "noAutoPromptWindowsHello": { + "message": "אל תבקש גישה ל- Windows Hello בעת ההפעלה." + }, + "noAutoPromptTouchId": { + "message": "אל תבקש גישה ל-Touch ID בעת ההפעלה." + }, + "lockWithMasterPassOnRestart": { + "message": "נעל בעזרת הסיסמה הראשית בהפעלה מחדש" + }, + "preferences": { + "message": "העדפות" + }, + "enableMenuBar": { + "message": "אפשר אייקון בתפריט" + }, + "enableMenuBarDesc": { + "message": "הצג תמיד אייקון בתפריט." + }, + "hideToMenuBar": { + "message": "הסתר לתפריט" + }, + "selectOneCollection": { + "message": "עליך לבחור לפחות אוסף אחד." + }, + "premiumUpdated": { + "message": "שדרגת לפרימיום." + }, + "restore": { + "message": "שחזור" + }, + "premiumManageAlertAppStore": { + "message": "ניתן לנהל את המינוי שלך דרך ה־App Store. האם ברצונך לבקר ב־App Store כעת?" + }, + "legal": { + "message": "משפטי", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "תנאי שירות" + }, + "privacyPolicy": { + "message": "מדיניות הפרטיות" + }, + "unsavedChangesConfirmation": { + "message": "האם אתה בטוח שברצונך לצאת? אם תצא כעת המידע הנוכחי לא ישמר." + }, + "unsavedChangesTitle": { + "message": "שינויים שלא נשמרו" + }, + "clone": { + "message": "שכפול" + }, + "passwordGeneratorPolicyInEffect": { + "message": "מדיניות ארגונית אחת או יותר משפיעה על הגדרות המחולל שלך." + }, + "vaultTimeoutAction": { + "message": "פעולה לביצוע בכספת בתום זמן החיבור" + }, + "vaultTimeoutActionLockDesc": { + "message": "כספת נעולה דורשת שתזין את הסיסמה הראשית בכדי לגשת לפרטים שבתוכה." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "בכדי לקבל גישה לכספת שיצאו ממנה, יש לבצע אימות מחדש." + }, + "lock": { + "message": "נעילה", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "סל המחזור", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "חפש בסל המחזור" + }, + "permanentlyDeleteItem": { + "message": "מחק לצמיתות פריט שנבחר" + }, + "permanentlyDeleteItemConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק את הפריט הזה לצמיתות?" + }, + "permanentlyDeletedItem": { + "message": "פריט שנמחק לצמיתות" + }, + "restoreItem": { + "message": "שחזר פריט" + }, + "restoreItemConfirmation": { + "message": "האם אתה בטוח שברצונך לשחזר פריט זה?" + }, + "restoredItem": { + "message": "פריט ששוחזר" + }, + "permanentlyDelete": { + "message": "מחק לצמיתות" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "יציאה תגרום להסרת כל גישה שיש לך לכספת ודורשת אימות אונליין לאחר משך זמן מסויים. האם אתה בטוח שברצונך להשתמש באפשרות זו?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "אישור פעולת אימות לאחר חוסר פעילות" + }, + "enterpriseSingleSignOn": { + "message": "כניסה אחודה ארגונית" + }, + "setMasterPassword": { + "message": "הגדרת סיסמה ראשית" + }, + "ssoCompleteRegistration": { + "message": "כדי להשלים את הכניסה עם SSO, נא להגדיר סיסמה ראשית כדי לגשת ולהגן על הכספת שלך." + }, + "newMasterPass": { + "message": "סיסמה ראשית חדשה" + }, + "confirmNewMasterPass": { + "message": "אימות סיסמה ראשית חדשה" + }, + "masterPasswordPolicyInEffect": { + "message": "אחד או יותר מאילוצי המדיניות של הארגון דורשים שהסיסמה הראשית שלך תעמוד בדרישות הבאות:" + }, + "policyInEffectMinComplexity": { + "message": "ניקוד מורכבות הסיסמה צריך להיות לפחות {0}", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "אורך מינימלי של $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "מכילה אות גדולה אחת או יותר" + }, + "policyInEffectLowercase": { + "message": "מכילה אות קטנה אחת או יותר" + }, + "policyInEffectNumbers": { + "message": "מכילה ספרה אחת או יותר" + }, + "policyInEffectSpecial": { + "message": "מכילה תו אחד או יותר מהתווים הבאים: {0}", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "הסיסמה הראשית החדשה השלך לא עומדת בדרישות המדיניות." + }, + "acceptPolicies": { + "message": "סימון תיבה זו מהווה את הסכמתך לתנאים הבאים:" + }, + "acceptPoliciesError": { + "message": "לא הסכמת לתנאי השירות ומדיניות הפרטיות." + }, + "enableBrowserIntegration": { + "message": "אפשר אינטגרציה עם הדפדפן" + }, + "enableBrowserIntegrationDesc": { + "message": "אינטגרצייה עם הדפדפן מאפשרת שימוש באמצעיים ביומטריים בדפדפן." + }, + "browserIntegrationMasOnlyTitle": { + "message": "אינטגרצייה עם הדפדפן אינה נמתכמת" + }, + "browserIntegrationMasOnlyDesc": { + "message": "למצער, אינטגרצייה עם הדפדפן בשלב זה נתמכת רק על ידי גרסת חנות האפליקציות של מקינטוש." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "אינטגרצייה עם הדפדפן אינה נמתכמת" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "למרבה הצער שילוב הדפדפן אינו נתמך כרגע בגרסת ה-Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "דרוש אימות לצורך שילוב הדפדפן" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "הפעל שכבת אבטחה נוספת באמצעות בקשת אימות טביעות אצבע בעת יצירת קישור בין שולחן העבודה לדפדפן. כשהוא מופעל, זה דורש התערבות ואימות משתמש בכל פעם שנוצר חיבור." + }, + "approve": { + "message": "לְאַשֵׁר" + }, + "verifyBrowserTitle": { + "message": "אמת את חיבור הדפדפן" + }, + "verifyBrowserDesc": { + "message": "בבקשה, וודא כי חתימת האצבע הדיגיטלית המוצגת זהה לחתימה שמופיע בתוסף הדפדפן." + }, + "biometricsNotEnabledTitle": { + "message": "לא הופעלו אמצעי זיהוי ביומטריים" + }, + "biometricsNotEnabledDesc": { + "message": "בכדי להשתמש באמצעי אימות ביומטריים בדפדפן, אפשר תכונה זו באפליקציה בשולחן העבודה." + }, + "personalOwnershipSubmitError": { + "message": "בשל מדיניות ארגונית, אתה מוגבל לשמירת פריטים בכספת האישית שלך. שנה את ההגדרות בעלות החשבון לחשבון ארגוני ובחר מתוך האוספים הזמינים." + }, + "hintEqualsPassword": { + "message": "הרמז לסיסמה לא יכול להיות זהה לסיסמה." + }, + "personalOwnershipPolicyInEffect": { + "message": "מדיניות ארגון מסויימת משפיעה על אפשרויות הבעלות." + }, + "allSends": { + "message": "כל השליחות", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "קובץ" + }, + "sendTypeText": { + "message": "טקסט" + }, + "searchSends": { + "message": "חיפוש שליחויות", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "ערוך Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "הכספת שלי" + }, + "text": { + "message": "טקסט" + }, + "deletionDate": { + "message": "תאריך מחיקה" + }, + "deletionDateDesc": { + "message": "המשלוח יימחק לצמיתות בתאריך ובשעה שצוינו.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "תאריך תפוגה" + }, + "expirationDateDesc": { + "message": "במדה והגדרת זמן, הגישה לשליחה זו תושבת בתאריך ובשעה שהוגדרו.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "מונה גישה מרבי" + }, + "maxAccessCountDesc": { + "message": "אם תגדיר, משתמשים כבר לא יוכלו לגשת לשליחה זו לאחר שמספר הגישות המרבי יושג.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "מונה גישה נוכחית" + }, + "disableSend": { + "message": "השבת את השליחה הזאת ואל תאפשר גישה אליה.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "לחלופין, דרוש סיסמה לכל המשתמשים כדי לגשת לשליחה זאת.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "הערות אישיות אודות השליחה הזאת.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "שלח קישור", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "שלח קישור", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "בעת גישה לשליחה, הסתר את הטקסט בברירת מחדל", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "ה-Send נוצר", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "שליחה שנערכה", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "השליחה נמחקה", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "סיסמה חדשה" + }, + "whatTypeOfSend": { + "message": "איזה סוג של שליחה הוא זה?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "צור Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "הטקסט שברצונך לשלוח." + }, + "sendFileDesc": { + "message": "הקובץ שברצונך לשלוח." + }, + "days": { + "message": "$DAYS$ יום/ימים", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "יום 1" + }, + "custom": { + "message": "מותאם אישית" + }, + "deleteSendConfirmation": { + "message": "האם אתה בטוח שברצונך למחוק את המשלוח הזה?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "העתק את קישור ה-Send ללוח", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "בשמירה העתק את הקישור ללוח כדי לשתף את ה-Send." + }, + "sendDisabled": { + "message": "ה-Send הושבת", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "בשל מדיניות החברה, אתה יכול למחוק רק משלוח קיים.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "העתק קישור" + }, + "disabled": { + "message": "מושבת" + }, + "maxAccessCountReached": { + "message": "מספר הגישות המרבי הושג" + }, + "expired": { + "message": "פג תוקף" + }, + "pendingDeletion": { + "message": "ממתין להסרה" + }, + "webAuthnAuthenticate": { + "message": "אמת WebAutn" + }, + "hideEmail": { + "message": "הסתר את כתובת הדואר האלקטרוני שלי מהנמענים." + }, + "sendOptionsPolicyInEffect": { + "message": "מדיניות ארגון אחת או יותר משפיעה על אפשרויות השליחה שלך." + }, + "emailVerificationRequired": { + "message": "נדרש כתובת אימייל לאימות" + }, + "emailVerificationRequiredDesc": { + "message": "נדרש אישור אימות בדוא\"ל כדי לאפשר שימוש בתכונה זו." + }, + "passwordPrompt": { + "message": "בקשת חוזרת של סיסמת ראשית" + }, + "passwordConfirmation": { + "message": "אישור סיסמא ראשי" + }, + "passwordConfirmationDesc": { + "message": "פעולה זו מוגנת. כדי להמשיך, הזן מחדש את הסיסמה הראשית שלך כדי לאמת את זהותך." + }, + "updatedMasterPassword": { + "message": "סיסמה ראשית עודכנה" + }, + "updateMasterPassword": { + "message": "עדכון סיסמה ראשית" + }, + "updateMasterPasswordWarning": { + "message": "הסיסמה הראשית שלך שונתה לאחרונה על ידי מנהל הארגון שלך. כדי לגשת לכספת, עליך לעדכן אותה כעת. בהמשך תנותק מההפעלה הנוכחית שלך ותידרש להיכנס שוב. הפעלות אחרות הפתוחות במכשירים שונים ימשיכו להיות פעילים עד משך שעה אחת." + }, + "hours": { + "message": "שעות" + }, + "minutes": { + "message": "דקות" + }, + "vaultTimeoutPolicyInEffect": { + "message": "מדיניות הארגון שלך משפיעה על הזמן הקצוב לכספת שלך. פסק הזמן המרבי המותר לכספת הוא $HOURS$ שע(ה/ות) ו $MINUTES$ דק(ה/ות)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "הזמן הקצוב לכספת שלך חורג מהמגבלות שנקבעו על ידי הארגון שלך." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "רישום אוטומטי" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "לארגון זה יש מדיניות ארגונית שרושמת אותך אוטומטית לאיפוס סיסמה. הרישום יאפשר למנהלי הארגון לשנות את סיסמת האב שלך." + }, + "vaultExportDisabled": { + "message": "ייצוא מהכספת מושבת" + }, + "personalVaultExportPolicyInEffect": { + "message": "מדיניות אחת או יותר של הארגון שלך מונעות ממך לייצא את הכספת האישית שלך." + }, + "addAccount": { + "message": "הוספת חשבון" + }, + "removeMasterPassword": { + "message": "הסרת סיסמה ראשית" + }, + "removedMasterPassword": { + "message": "הסיסמה הראשית הוסרה." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ משתמשים ב־SSO עם שרת מפתחות באירוח עצמי. סיסמה ראשית לא נחוצה יותר לטובת כניסה לחברי הארגון.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "לעזוב את הארגון" + }, + "leaveOrganizationConfirmation": { + "message": "לעזוב את הארגון?" + }, + "leftOrganization": { + "message": "עזבת את הארגון." + }, + "ssoKeyConnectorUnavailable": { + "message": "לא ניתן להגיע למחבר המפתח, נא לנסות שוב." + }, + "lockAllVaults": { + "message": "נעילת כל הכספות" + }, + "accountLimitReached": { + "message": "אפשר להיכנס לעד 5 חשבונות בו־זמנית." + }, + "accountPreferences": { + "message": "העדפות" + }, + "appPreferences": { + "message": "הגדרות היישום (כל החשבונות)" + }, + "accountSwitcherLimitReached": { + "message": "הגעת למגבלת החשבונות. יש לצאת מחשבון כדי להוסיף אחד נוסף." + }, + "settingsTitle": { + "message": "הגדרות היישום עבור $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "החלף חשבון" + }, + "options": { + "message": "אפשרויות" + }, + "sessionTimeout": { + "message": "זמן ההפעלה שלך תם. נא לחזור ולנסות להיכנס שוב." + }, + "exportingPersonalVaultTitle": { + "message": "הכספת האישית מיוצאת" + }, + "exportingPersonalVaultDescription": { + "message": "רק פריטי הכספת האישית שמשויכת עם $EMAIL$ ייוצאו. פריטי הכספת הארגוניים לא יהיו חלק מהייצוא.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "מחולל" + }, + "whatWouldYouLikeToGenerate": { + "message": "מה ברצונך לחולל?" + }, + "passwordType": { + "message": "סוג סיסמה" + }, + "regenerateUsername": { + "message": "חולל מחדש שם משתמש" + }, + "generateUsername": { + "message": "חולל שם משתמש" + }, + "usernameType": { + "message": "סוג שם משתמש" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "אקראי" + }, + "randomWord": { + "message": "מילה אקראית" + }, + "websiteName": { + "message": "שם אתר" + }, + "service": { + "message": "שירות" + } +} diff --git a/apps/desktop/src/locales/hi/messages.json b/apps/desktop/src/locales/hi/messages.json new file mode 100644 index 0000000000..abce23b0f0 --- /dev/null +++ b/apps/desktop/src/locales/hi/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "फ़िल्टर" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "Favorites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "नाम" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Email Address" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy Value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security Code" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favorite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "Search Folder" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "Add New Folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check For Updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/hr/messages.json b/apps/desktop/src/locales/hr/messages.json new file mode 100644 index 0000000000..e8ec3f7124 --- /dev/null +++ b/apps/desktop/src/locales/hr/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtri" + }, + "allItems": { + "message": "Sve stavke" + }, + "favorites": { + "message": "Favoriti" + }, + "types": { + "message": "Vrste" + }, + "typeLogin": { + "message": "Prijava" + }, + "typeCard": { + "message": "Platna kartica" + }, + "typeIdentity": { + "message": "Identitet" + }, + "typeSecureNote": { + "message": "Sigurna bilješka" + }, + "folders": { + "message": "Mape" + }, + "collections": { + "message": "Zbirke" + }, + "searchVault": { + "message": "Pretraživanje trezora" + }, + "addItem": { + "message": "Dodaj stavku" + }, + "shared": { + "message": "Dijeljeno" + }, + "share": { + "message": "Podijeli" + }, + "moveToOrganization": { + "message": "Premjesti u organizaciju" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ premješteno u $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Odaberi organizaciju u koju želiš premjestiti ovu stavku. Premještanje prenosi vlasništvo stavke na organizaciju. Nakon premještanja više nećeš biti izravni vlasnik ove stavke." + }, + "attachments": { + "message": "Privitci" + }, + "viewItem": { + "message": "Prikaz stavke" + }, + "name": { + "message": "Naziv" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novi URI" + }, + "username": { + "message": "Korisničko ime" + }, + "password": { + "message": "Lozinka" + }, + "passphrase": { + "message": "Frazna lozinka" + }, + "editItem": { + "message": "Uredi stavku" + }, + "emailAddress": { + "message": "Adresa e-pošte" + }, + "verificationCodeTotp": { + "message": "Kôd za provjeru (TOTP)" + }, + "website": { + "message": "Web stranica" + }, + "notes": { + "message": "Bilješke" + }, + "customFields": { + "message": "Prilagođena polja" + }, + "launch": { + "message": "Pokreni" + }, + "copyValue": { + "message": "Kopiraj vrijednost", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimiziraj pri kopiranju u međuspremnik" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimiziraj pri kopiranju stavke u međuspremnik." + }, + "toggleVisibility": { + "message": "Prikaži/Sakrij" + }, + "toggleCollapse": { + "message": "Sažmi/Proširi", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Vlasnik kartice" + }, + "number": { + "message": "Broj" + }, + "brand": { + "message": "Vrsta kartice" + }, + "expiration": { + "message": "Istek" + }, + "securityCode": { + "message": "Kontrolni broj" + }, + "identityName": { + "message": "identityName" + }, + "company": { + "message": "Tvrtka" + }, + "ssn": { + "message": "Broj socijalnog osiguranja" + }, + "passportNumber": { + "message": "Broj putovnice" + }, + "licenseNumber": { + "message": "Broj licence" + }, + "email": { + "message": "E-pošta" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresa" + }, + "premiumRequired": { + "message": "Potrebno premium članstvo" + }, + "premiumRequiredDesc": { + "message": "Za korištenje ove značajke potrebno je premium članstvo." + }, + "errorOccurred": { + "message": "Došlo je do pogreške." + }, + "error": { + "message": "Pogreška" + }, + "january": { + "message": "siječanj" + }, + "february": { + "message": "veljača" + }, + "march": { + "message": "ožujak" + }, + "april": { + "message": "travanj" + }, + "may": { + "message": "svibanj" + }, + "june": { + "message": "lipanj" + }, + "july": { + "message": "srpanj" + }, + "august": { + "message": "kolovoz" + }, + "september": { + "message": "rujan" + }, + "october": { + "message": "listopad" + }, + "november": { + "message": "studeni" + }, + "december": { + "message": "prosinac" + }, + "ex": { + "message": "npr.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titula" + }, + "mr": { + "message": "g." + }, + "mrs": { + "message": "gđa." + }, + "ms": { + "message": "gđica." + }, + "dr": { + "message": "dr." + }, + "expirationMonth": { + "message": "Mjesec isteka" + }, + "expirationYear": { + "message": "Godina isteka" + }, + "select": { + "message": "Odaberi" + }, + "other": { + "message": "Ostalo" + }, + "generatePassword": { + "message": "Generiraj lozinku" + }, + "type": { + "message": "Vrsta" + }, + "firstName": { + "message": "Ime" + }, + "middleName": { + "message": "Srednje ime" + }, + "lastName": { + "message": "Prezime" + }, + "fullName": { + "message": "Ime i prezime" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Grad / Mjesto" + }, + "stateProvince": { + "message": "Država / Pokrajina" + }, + "zipPostalCode": { + "message": "Poštanski broj" + }, + "country": { + "message": "Zemlja" + }, + "save": { + "message": "Spremi" + }, + "cancel": { + "message": "Odustani" + }, + "delete": { + "message": "Izbriši" + }, + "favorite": { + "message": "Favorit" + }, + "edit": { + "message": "Uredi" + }, + "authenticatorKeyTotp": { + "message": "Ključ autentifikatora (TOTP)" + }, + "folder": { + "message": "Mapa" + }, + "newCustomField": { + "message": "Novo prilagođeno polje" + }, + "value": { + "message": "Vrijednost" + }, + "dragToSort": { + "message": "Povuci za sortiranje" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Skriveno" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Povezano", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Povezana vrijednost", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Ukloni" + }, + "nameRequired": { + "message": "Ime je obavezno." + }, + "addedItem": { + "message": "Stavka dodana" + }, + "editedItem": { + "message": "Stavka izmijenjena" + }, + "deleteItem": { + "message": "Izbriši stavku" + }, + "deleteFolder": { + "message": "Izbriši mapu" + }, + "deleteAttachment": { + "message": "Izbriši privitak" + }, + "deleteItemConfirmation": { + "message": "Želiš li zaista poslati u smeće?" + }, + "deletedItem": { + "message": "Stavka poslana u smeće" + }, + "overwritePasswordConfirmation": { + "message": "Sigurno želiš prebrisati trenutnu lozinku?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Nema mape", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Dodaj mapu" + }, + "editFolder": { + "message": "Uredi mapu" + }, + "regeneratePassword": { + "message": "Ponovno generiraj lozinku" + }, + "copyPassword": { + "message": "Kopiraj lozinku" + }, + "copyUri": { + "message": "Kopiraj URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopiraj kôd za provjeru (TOTP)" + }, + "length": { + "message": "Duljina" + }, + "numWords": { + "message": "Broj riječi" + }, + "wordSeparator": { + "message": "Razdjelitelj riječi" + }, + "capitalize": { + "message": "Prva slova velika", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Uključi broj" + }, + "close": { + "message": "Zatvori" + }, + "minNumbers": { + "message": "Najmanje brojeva" + }, + "minSpecial": { + "message": "Najmanje specijalnih", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Izbjegavaj dvosmislene znakove" + }, + "searchCollection": { + "message": "Pretraživanje zbirke" + }, + "searchFolder": { + "message": "Pretraživanje mape" + }, + "searchFavorites": { + "message": "Pretraživanje favorita" + }, + "searchType": { + "message": "Tip pretrage", + "description": "Search item type" + }, + "newAttachment": { + "message": "Dodaj novi privitak" + }, + "deletedAttachment": { + "message": "Izbrisani privitak" + }, + "deleteAttachmentConfirmation": { + "message": "Sigurno želiš izbrisati ovaj privitak?" + }, + "attachmentSaved": { + "message": "Privitak je spremljen." + }, + "file": { + "message": "Datoteka" + }, + "selectFile": { + "message": "Odaberi datoteku." + }, + "maxFileSize": { + "message": "Najveća veličina datoteke je 500 MB." + }, + "updateKey": { + "message": "Ne možeš koristiti ovu značajku prije nego ažuriraš ključ za šifriranje." + }, + "editedFolder": { + "message": "Uređena mapa" + }, + "addedFolder": { + "message": "Mapa dodana" + }, + "deleteFolderConfirmation": { + "message": "Sigurno želiš izbrisati ovu mapu?" + }, + "deletedFolder": { + "message": "Mapa izbrisana" + }, + "loginOrCreateNewAccount": { + "message": "Prijavi se ili stvori novi račun za pristup svojem sigurnom trezoru." + }, + "createAccount": { + "message": "Stvori račun" + }, + "logIn": { + "message": "Prijavi se" + }, + "submit": { + "message": "Pošalji" + }, + "masterPass": { + "message": "Glavna lozinka" + }, + "masterPassDesc": { + "message": "Glavnu lozinku koristiš za pristup svom trezoru. Vrlo je važno da ne zaboraviš glavnu lozinku. Ne postoji način za oporavak lozinke u slučaju da ju zaboraviš." + }, + "masterPassHintDesc": { + "message": "Podsjetnik glavne lozinke ti može pomoći da se prisjetiš svoje lozinke ako ju zaboraviš." + }, + "reTypeMasterPass": { + "message": "Ponovno upiši glavnu lozinku" + }, + "masterPassHint": { + "message": "Podsjetnik glavne lozinke (neobavezno)" + }, + "settings": { + "message": "Postavke" + }, + "passwordHint": { + "message": "Podsjetnik za lozinku" + }, + "enterEmailToGetHint": { + "message": "Unesi adresu e-pošte svog računa za primitak podsjetnika glavne lozinke." + }, + "getMasterPasswordHint": { + "message": "Slanje podsjetnika glavne lozinke" + }, + "emailRequired": { + "message": "Adresa e-pošte je obavezna." + }, + "invalidEmail": { + "message": "Nevažeća adresa e-pošte." + }, + "masterPassRequired": { + "message": "Potrebna je glavna lozinka." + }, + "masterPassLength": { + "message": "Glavna lozinka mora imati najmanje 8 znakova." + }, + "masterPassDoesntMatch": { + "message": "Potvrda glavne lozinke se ne podudara." + }, + "newAccountCreated": { + "message": "Tvoj novi račun je kreiran! Sada se možeš prijaviti." + }, + "masterPassSent": { + "message": "Poslali smo e-poštu s podsjetnikom glavne lozinke." + }, + "unexpectedError": { + "message": "Došlo je do neočekivane pogreške." + }, + "itemInformation": { + "message": "Informacije o stavci" + }, + "noItemsInList": { + "message": "Nema stavki za prikaz." + }, + "sendVerificationCode": { + "message": "Slanje verifikacijskog kôda e-poštom" + }, + "sendCode": { + "message": "Pošalji kôd" + }, + "codeSent": { + "message": "Kôd poslan" + }, + "verificationCode": { + "message": "Kôd za provjeru" + }, + "confirmIdentity": { + "message": "Potvrdite lozinku za nastavak." + }, + "verificationCodeRequired": { + "message": "Potvrdni kôd je obavezan." + }, + "invalidVerificationCode": { + "message": "Nevažeći kôd za provjeru" + }, + "continue": { + "message": "Nastavi" + }, + "enterVerificationCodeApp": { + "message": "Unesi 6-znamenkasti kontrolni kôd iz autentifikatorske aplikacije." + }, + "enterVerificationCodeEmail": { + "message": "Unesi 6-znamenkasti kontrolni kôd poslan e-poštom na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-pošta za potvrdu poslana je na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamti me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Ponovno slanje kontrolnog koda e-poštom" + }, + "useAnotherTwoStepMethod": { + "message": "Koristiti drugi način prijave u dva koraka" + }, + "insertYubiKey": { + "message": "Umetni svoj YubiKey u USB priključak računala, a zatim dodirni njegovu tipku." + }, + "insertU2f": { + "message": "Umetni svoj sigurnosni ključ u USB priključak računala. Ako ima tipku, dodirni ju." + }, + "recoveryCodeDesc": { + "message": "Izgubljen je pristup uređaju za dvostruku autentifikaciju? Koristi svoj kôd za oporavak za onemogućavanje svih pružatelja usluga dvostruke autentifikacije na tvojem računu." + }, + "recoveryCodeTitle": { + "message": "Kôd za oporavak" + }, + "authenticatorAppTitle": { + "message": "Autentifikatorska aplikacija" + }, + "authenticatorAppDesc": { + "message": "Koristi autentifikatorsku aplikaciju (npr. Authy ili Google Authentifikator) za generiranje kontrolnih kodova.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP sigurnosni ključ" + }, + "yubiKeyDesc": { + "message": "Koristi YubiKey za pristup svojem računu. Radi s YubiKey 4, 4 Nano, 4C i NEO uređajima." + }, + "duoDesc": { + "message": "Potvrdi s Duo Security pomoću aplikacije Duo Mobile, SMS-om, telefonskim pozivom ili U2F sigurnosnim ključem.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Potvrdi s Duo Security za svoju organizaciju pomoću aplikacije Duo Mobile, SMS-om, telefonskim pozivom ili U2F sigurnosnim ključem.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Koristi bilo koji WebAuthn omogućen sigurnosni ključ za pristup svojem računu." + }, + "emailTitle": { + "message": "E-pošta" + }, + "emailDesc": { + "message": "Verifikacijski kodovi će biti poslani e-poštom." + }, + "loginUnavailable": { + "message": "Prijava nije dostupna" + }, + "noTwoStepProviders": { + "message": "Ovaj račun ima omogućenu prijavu u dva koraka, međutim, niti jedan od konfiguriranih pružatelja prijave u dva koraka ne podržava ovaj uređaj." + }, + "noTwoStepProviders2": { + "message": "Dodaj dodatne pružatelje, bolje podržane na uređajima (npr. aplikacija Autentifikator)." + }, + "twoStepOptions": { + "message": "Mogućnosti prijave u dva koraka" + }, + "selfHostedEnvironment": { + "message": "Vlastito hosting okruženje" + }, + "selfHostedEnvironmentFooter": { + "message": "Navedi osnovni URL svoje lokalno smještene Bitwarden instalacije." + }, + "customEnvironment": { + "message": "Prilagođeno okruženje" + }, + "customEnvironmentFooter": { + "message": "Za napredne korisnike. Samostalno možeš odrediti osnovni URL svake usluge." + }, + "baseUrl": { + "message": "URL poslužitelja" + }, + "apiUrl": { + "message": "URL API poslužitelja" + }, + "webVaultUrl": { + "message": "URL poslužitelja web trezora" + }, + "identityUrl": { + "message": "URL id poslužitelja" + }, + "notificationsUrl": { + "message": "URL poslužitelja obavijesti" + }, + "iconsUrl": { + "message": "URL poslužitelja ikona" + }, + "environmentSaved": { + "message": "URL-ovi okoline su spremljeni." + }, + "ok": { + "message": "U redu" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Ne" + }, + "overwritePassword": { + "message": "Prebriši lozinku" + }, + "learnMore": { + "message": "Saznaj više" + }, + "featureUnavailable": { + "message": "Značajka nije dostupna" + }, + "loggedOut": { + "message": "Odjavljen" + }, + "loginExpired": { + "message": "Sesija je istekla." + }, + "logOutConfirmation": { + "message": "Sigurno se želiš odjaviti?" + }, + "logOut": { + "message": "Odjavi se" + }, + "addNewLogin": { + "message": "Dodaj novu prijavu" + }, + "addNewItem": { + "message": "Dodaj novu stavku" + }, + "addNewFolder": { + "message": "Dodaj novu mapu" + }, + "view": { + "message": "Prikaz" + }, + "account": { + "message": "Račun" + }, + "loading": { + "message": "Učitavanje..." + }, + "lockVault": { + "message": "Zaključaj trezor" + }, + "passwordGenerator": { + "message": "Generator lozinki" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Podnesi izvješće o grešci" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Prati nas" + }, + "syncVault": { + "message": "Odmah sinkroniziraj trezor" + }, + "changeMasterPass": { + "message": "Promjeni glavnu lozinku" + }, + "changeMasterPasswordConfirmation": { + "message": "Svoju glavnu lozinku možeš promijeniti na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "fingerprintPhrase": { + "message": "Jedinstvena fraza", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Jedinstvena fraza tvog računa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Idi na web trezor" + }, + "getMobileApp": { + "message": "Preuzmi mobilnu aplikaciju" + }, + "getBrowserExtension": { + "message": "Preuzmi proširenje za preglednik" + }, + "syncingComplete": { + "message": "Sinkronizacija dovršena" + }, + "syncingFailed": { + "message": "Sinkronizacija nije uspjela" + }, + "yourVaultIsLocked": { + "message": "Tvoj trezor je zaključan. Potvrdi glavnu lozinku za nastavak." + }, + "unlock": { + "message": "Otključaj" + }, + "loggedInAsOn": { + "message": "Prijavljen kao $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Neispravna glavna lozinka" + }, + "twoStepLoginConfirmation": { + "message": "Prijava u dva koraka čini tvoj račun još sigurnijim tako što će zahtijevati da potvrdiš prijavu putem drugog uređaja sigurnosnim ključem, autentifikatorskom aplikacijom, SMS-om, pozivom ili e-poštom. Prijavu u dva koraka možeš omogućiti na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "twoStepLogin": { + "message": "Prijava u dva koraka" + }, + "vaultTimeout": { + "message": "Istek trezora" + }, + "vaultTimeoutDesc": { + "message": "Odaberi kada će isteći trezor i koja će se radnja izvršiti." + }, + "immediately": { + "message": "Odmah" + }, + "tenSeconds": { + "message": "10 sekundi" + }, + "twentySeconds": { + "message": "20 sekundi" + }, + "thirtySeconds": { + "message": "30 sekundi" + }, + "oneMinute": { + "message": "1 minuta" + }, + "twoMinutes": { + "message": "2 minute" + }, + "fiveMinutes": { + "message": "5 minuta" + }, + "fifteenMinutes": { + "message": "15 minuta" + }, + "thirtyMinutes": { + "message": "30 minuta" + }, + "oneHour": { + "message": "1 sat" + }, + "fourHours": { + "message": "4 sata" + }, + "onIdle": { + "message": "Nekativnost sustava" + }, + "onSleep": { + "message": "Stanje mirovanja" + }, + "onLocked": { + "message": "Pri zaključavanju sustava" + }, + "onRestart": { + "message": "Kod ponovnog pokretanja" + }, + "never": { + "message": "Nikad" + }, + "security": { + "message": "Sigurnost" + }, + "clearClipboard": { + "message": "Očisti međuspremnik", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatski očisti kopirane vrijednosti iz međuspremnika.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Onemogući ikone web mjesta" + }, + "disableFaviconDesc": { + "message": "Prepoznatljive ikone web mjesta prikazuju se pored prijava u tvojem trezoru." + }, + "enableMinToTray": { + "message": "Minimiziraj u područje obavijesti" + }, + "enableMinToTrayDesc": { + "message": "Kod minimiziranja, prikazuje se ikona u području obavijesti." + }, + "enableMinToMenuBar": { + "message": "Minimiziraj u programsku traku" + }, + "enableMinToMenuBarDesc": { + "message": "Kod minimiziranja, prikazuje se ikona u programskoj traci." + }, + "enableCloseToTray": { + "message": "Zatvaranje u područje obavijesti" + }, + "enableCloseToTrayDesc": { + "message": "Kod zatvaranja prozora, prikazuje se ikona u području obavijesti." + }, + "enableCloseToMenuBar": { + "message": "Zatvaranje u programsku traku" + }, + "enableCloseToMenuBarDesc": { + "message": "Kod zatvaranja prozora, prikazuje se ikona u programskoj traci." + }, + "enableTray": { + "message": "Omogući ikonu u području obavijesti" + }, + "enableTrayDesc": { + "message": "Uvijek prikaži ikonu u području obavijesti." + }, + "startToTray": { + "message": "Pokreni u područje obavijesti" + }, + "startToTrayDesc": { + "message": "Prilikom pokretanja aplikacije prikazuje se samo ikona u području obavijesti." + }, + "startToMenuBar": { + "message": "Pokreni u programsku traku" + }, + "startToMenuBarDesc": { + "message": "Prilikom pokretanja aplikacije prikazuje se ikona u programskoj traci." + }, + "openAtLogin": { + "message": "Automatsko pokretanje kod prijave" + }, + "openAtLoginDesc": { + "message": "Automatski pokreni Bitwarden desktop aplikaciju kod prijave." + }, + "alwaysShowDock": { + "message": "Uvijek prikaži u Docku" + }, + "alwaysShowDockDesc": { + "message": "Prikaži Bitwareden ikonu u Docku čak i kada je minimiziran u traku s izbornicima." + }, + "confirmTrayTitle": { + "message": "Potvrdi onemogućavanje pladnja" + }, + "confirmTrayDesc": { + "message": "Isključivanjem ove opcije isključiti će se sve druge postavke vezane za pladanj." + }, + "language": { + "message": "Jezik" + }, + "languageDesc": { + "message": "Promijeni jezik aplikacije. Potrebno je ponovno pokretanje." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Promijeni temu boja." + }, + "dark": { + "message": "Tamna", + "description": "Dark color" + }, + "light": { + "message": "Svijetla", + "description": "Light color" + }, + "copy": { + "message": "Kopiraj", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Provjeri ažuriranja" + }, + "version": { + "message": "Verzija $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Ponovo pokreni za ažuriranje" + }, + "restartToUpdateDesc": { + "message": "Verzija $VERSION_NUM$ je spremna za instalaciju. Moraš ponovno pokrenuti Bitwarden za dovršetak instalacije. Želiš li ponovo pokrenuti i ažurirati?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Dostupna su ažuriranja" + }, + "updateAvailableDesc": { + "message": "Pronađeno je ažuriranje. Želiš li ga sada preuzeti?" + }, + "restart": { + "message": "Ponovno pokreni" + }, + "later": { + "message": "Kasnije" + }, + "noUpdatesAvailable": { + "message": "Trenutno nema ažuriranja. Već koristiš najnoviju verziju." + }, + "updateError": { + "message": "Pogreška pri ažuriranju" + }, + "unknown": { + "message": "Nepoznato" + }, + "copyUsername": { + "message": "Kopiraj korisničko ime" + }, + "copyNumber": { + "message": "Kopiraj broj", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopiraj kontrolni broj", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium članstvo" + }, + "premiumManage": { + "message": "Upravljaj članstvom" + }, + "premiumManageAlert": { + "message": "Svojim članstvom možeš upravljati na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "premiumRefresh": { + "message": "Osvježi status članstva" + }, + "premiumNotCurrentMember": { + "message": "Trenutno nisi premium član." + }, + "premiumSignUpAndGet": { + "message": "Prijavi se za premium članstvo, čime dobivaš:" + }, + "premiumSignUpStorage": { + "message": "1 GB šifriranog prostora za pohranu podataka." + }, + "premiumSignUpTwoStep": { + "message": "Dodatne mogućnosti za prijavu u dva koraka kao što su YubiKey, FIDO U2F i Duo." + }, + "premiumSignUpReports": { + "message": "Higijenu lozinki, zdravlje računa i izvještaje o krađi podatak radi zaštite svojeg trezora." + }, + "premiumSignUpTotp": { + "message": "Generator TOTP kontrolnog koda (2FA) za prijave u tvom trezoru." + }, + "premiumSignUpSupport": { + "message": "Prioritetnu korisničku podršku." + }, + "premiumSignUpFuture": { + "message": "Sve buduće premium značajke. Uskoro više!" + }, + "premiumPurchase": { + "message": "Kupi premium članstvo" + }, + "premiumPurchaseAlert": { + "message": "Možeš kupiti premium članstvo na web trezoru. Želiš li sada posjetiti bitwarden.com?" + }, + "premiumCurrentMember": { + "message": "Ti si premium član!" + }, + "premiumCurrentMemberThanks": { + "message": "Hvala ti što podupireš Bitwarden." + }, + "premiumPrice": { + "message": "Sve za samo $PRICE$ /godišnje!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Osvježavanje završeno" + }, + "passwordHistory": { + "message": "Povijest" + }, + "clear": { + "message": "Očisti", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Nema lozinki na popisu." + }, + "undo": { + "message": "Poništi" + }, + "redo": { + "message": "Vrati" + }, + "cut": { + "message": "Izreži", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Zalijepi", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Odaberi sve" + }, + "zoomIn": { + "message": "Povećaj" + }, + "zoomOut": { + "message": "Smanji" + }, + "resetZoom": { + "message": "Poništi zumiranje" + }, + "toggleFullScreen": { + "message": "Uključi/isključi prikaz preko cijelog zaslona" + }, + "reload": { + "message": "Ponovno učitaj" + }, + "toggleDevTools": { + "message": "Uključi/isključi razvojne alate" + }, + "minimize": { + "message": "Minimiziraj", + "description": "Minimize window" + }, + "zoom": { + "message": "Povećaj" + }, + "bringAllToFront": { + "message": "Premjesti sve u prednji plan", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "O aplikaciji Bitwarden" + }, + "services": { + "message": "Usluge" + }, + "hideBitwarden": { + "message": "Sakrij Bitwarden" + }, + "hideOthers": { + "message": "Sakrij ostale" + }, + "showAll": { + "message": "Prikaži sve" + }, + "quitBitwarden": { + "message": "Zatvori Bitwarden" + }, + "valueCopied": { + "message": " kopirano", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Pomoć" + }, + "window": { + "message": "Prozor" + }, + "checkPassword": { + "message": "Provjeri je li lozinka bila ukradena." + }, + "passwordExposed": { + "message": "Ova lozinka je otkrivena $VALUE$ put(a) prilikom krađe podataka. Trebalo bi ju promijeniti.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Lozinka nije pronađena niti u jednoj krađi podataka. Sigurna je za korištenje." + }, + "baseDomain": { + "message": "Primarna domena", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Točno" + }, + "startsWith": { + "message": "Počinje s" + }, + "regEx": { + "message": "Regularni izraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Otkrivanje podudaranja", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Zadano otkrivanje podudaranja", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Uključi/isključi opcije" + }, + "organization": { + "message": "Organizacija", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Zadano" + }, + "exit": { + "message": "Izlaz" + }, + "showHide": { + "message": "Prikaži / sakrij", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Sakrij u područje obavijesti" + }, + "alwaysOnTop": { + "message": "Uvijek na vrhu", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Ažurirano", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Lozinka ažurirana", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Izvezi trezor" + }, + "fileFormat": { + "message": "Format datoteke" + }, + "warning": { + "message": "UPOZORENJE", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potvrdi izvoz trezora" + }, + "exportWarningDesc": { + "message": "Ovaj izvoz sadrži podatke trezora u nešifriranom obliku! Izvezenu datoteku se ne bi smjelo pohranjivati ili slati putem nesigurnih kanala (npr. e-poštom). Izbriši ju odmah nakon završetka korištenja." + }, + "encExportKeyWarningDesc": { + "message": "Ovaj izvoz šifrira tvoje podatke koristeći ključ za šifriranje. Promijeniš li naknadno ključ za šifriranje, potrebno je ponovno napraviti izvoz jer nećeš moći dešifrirati ovu izvezenu datoteku." + }, + "encExportAccountWarningDesc": { + "message": "Ključ za šifriranje jedinstven je za svakog Bitwarden korisnika, kako bi se šifrirani izvoz mogao uvesti u drugi korisnički račun." + }, + "noOrganizationsList": { + "message": "Ne pripadaš niti jednoj organizaciji. Organizacije omogućuju sigurno dijeljenje stavki s drugim korisnicima." + }, + "noCollectionsInList": { + "message": "Nema zbirki za prikaz." + }, + "ownership": { + "message": "Vlasništvo" + }, + "whoOwnsThisItem": { + "message": "Tko je vlasnik ove stavke?" + }, + "strong": { + "message": "Jaka", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobra", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slaba", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slaba glavna lozinka" + }, + "weakMasterPasswordDesc": { + "message": "Odabrana glavna lozinka je slaba. Trebaš koristiti jaču glavnu lozinku (ili frazu) kako bi tvoj Bitwarden račun bio pravilno zaštićen. Sigurno želiš koristiti ovakvu, slabu glavnu lozinku?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Otključaj PIN-om" + }, + "setYourPinCode": { + "message": "Postavi svoj PIN kôd za otključavanje Bitwardena. Postavke PIN-a se resetiraju ako se potpuno odjaviš iz aplikacije." + }, + "pinRequired": { + "message": "Potreban je PIN." + }, + "invalidPin": { + "message": "Nerispravan PIN." + }, + "unlockWithWindowsHello": { + "message": "Otključaj koristeći Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Otključaj trezor." + }, + "unlockWithTouchId": { + "message": "Otključaj koristeći Touch ID" + }, + "touchIdConsentMessage": { + "message": "Otključaj trezor" + }, + "noAutoPromptWindowsHello": { + "message": "Ne traži Windows Hello pri pokretanju." + }, + "noAutoPromptTouchId": { + "message": "Ne traži Touch ID pri pokretanju." + }, + "lockWithMasterPassOnRestart": { + "message": "Zaključaj glavnom lozinkom kod svakog pokretanja" + }, + "preferences": { + "message": "Postavke" + }, + "enableMenuBar": { + "message": "Omogući ikonu u traci s izbornicima" + }, + "enableMenuBarDesc": { + "message": "Uvijek prikaži ikonu u traci s izbornicima." + }, + "hideToMenuBar": { + "message": "Sakrij u traku s izbornicima" + }, + "selectOneCollection": { + "message": "Moraš odabrati barem jednu zbirku." + }, + "premiumUpdated": { + "message": "Premium nadogradnja uspješna." + }, + "restore": { + "message": "Vrati" + }, + "premiumManageAlertAppStore": { + "message": "Svoju pretplatu možeš mijenjati u App Store-u. Želiš li ga sada otvoriti?" + }, + "legal": { + "message": "Pravne informacije", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Uvjeti korištenja" + }, + "privacyPolicy": { + "message": "Pravila privatnosti" + }, + "unsavedChangesConfirmation": { + "message": "Sigurno želiš otići? Svi trenutni podaci neće biti spremljeni." + }, + "unsavedChangesTitle": { + "message": "Nespremljene promjene" + }, + "clone": { + "message": "Kloniraj" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Jedno ili više pravila organizacije utječe na postavke generatora." + }, + "vaultTimeoutAction": { + "message": "Nakon isteka trezora" + }, + "vaultTimeoutActionLockDesc": { + "message": "Zaključani trezor, za ponovni pristup, zahtijeva ponovni unos tvoje glavne lozinke." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Odjavljeni trezor, za ponovni pristup, zahtijeva ponovnu provjeru autentičnosti." + }, + "lock": { + "message": "Zaključaj", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Smeće", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Pretraži smeće" + }, + "permanentlyDeleteItem": { + "message": "Trajno izbriši stavku" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Želiš li zaista trajno izbrisati ovu stavku?" + }, + "permanentlyDeletedItem": { + "message": "Trajno izbirsana stavka" + }, + "restoreItem": { + "message": "Vrati stavku" + }, + "restoreItemConfirmation": { + "message": "Sigurno želiš vratiti ovu stavku?" + }, + "restoredItem": { + "message": "Stavka vraćena" + }, + "permanentlyDelete": { + "message": "Trajno izbriši" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Odjava će ukloniti pristup tvojem trezoru i zahtijeva mrežnu potvrdu identiteta nakon isteka vremenske neaktivnosti. Sigurno želiš koristiti ovu postavku?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potvrda akcije vremenske neaktivnosti" + }, + "enterpriseSingleSignOn": { + "message": "Jedinstvena prijava na razini tvrtke (SSO)" + }, + "setMasterPassword": { + "message": "Postavi glavnu lozinku" + }, + "ssoCompleteRegistration": { + "message": "Za dovršetak jedinstvene prijave na razini tvrtke (SSO), postavi glavnu lozinku za pristup i zaštitu tvog trezora." + }, + "newMasterPass": { + "message": "Nova glavna lozinka" + }, + "confirmNewMasterPass": { + "message": "Potvrdi novu glavnu lozinku" + }, + "masterPasswordPolicyInEffect": { + "message": "Jedno ili više pravila organizacije zahtijeva da tvoja glavna lozinka ispunjava sljedeće uvjete:" + }, + "policyInEffectMinComplexity": { + "message": "Minimalna ocjena složenosti od $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Duljina najmanje $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Sadrži jedno ili više velikih slova" + }, + "policyInEffectLowercase": { + "message": "Sadrži jedno ili više malih slova" + }, + "policyInEffectNumbers": { + "message": "Sadrži jedan ili više brojeva" + }, + "policyInEffectSpecial": { + "message": "Sadrži jedan ili više sljedećih posebnih znakova $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Tvoja nova glavna lozinka ne ispunjava zahtjeve." + }, + "acceptPolicies": { + "message": "Označavanjem ove kućice slažete se sa sljedećim:" + }, + "acceptPoliciesError": { + "message": "Uvjeti korištenja i Pravila privatnosti nisu prihvaćeni." + }, + "enableBrowserIntegration": { + "message": "Uključi integraciju s web preglednikom" + }, + "enableBrowserIntegrationDesc": { + "message": "Integracija s preglednikom koristi se za biometriju u pregledniku." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Integracija s preglednikom nije omogućena" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Nažalost, za sada je integracija s preglednikom podržana samo u Mac App Store verziji aplikacije." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Integracija s preglednikom nije podržana" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Nažalost, integracija s preglednikom nije podržana u Windows Store verziji aplikacije." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Traži verifikaciju za integraciju s preglednikom" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Uključi dodatni sloj sigurnosti tražeći verifikaciju jedinstvenom frazom prilikom povezivanja radne površine i preglednika. Kada je ovo uključeno, potrebno je verificirati prilikom svakog novog povezivanja." + }, + "approve": { + "message": "Odobri" + }, + "verifyBrowserTitle": { + "message": "Verificiraj vezu s preglednikom" + }, + "verifyBrowserDesc": { + "message": "Provjeri da je prikazana jedinstvena fraza identična onoj prikazanoj u proširenju preglednika." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrija nije omogućena" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrija preglednika zahtijeva prethodno omogućenu biometriju u Bitwarden desktop aplikaciji." + }, + "personalOwnershipSubmitError": { + "message": "Pravila tvrtke onemogućuju spremanje stavki u osobni trezor. Promijeni vlasništvo stavke na tvrtku i odaberi dostupnu Zbirku." + }, + "hintEqualsPassword": { + "message": "Podsjetnik za lozinku ne može biti isti kao lozinka." + }, + "personalOwnershipPolicyInEffect": { + "message": "Pravila organizacije utječu na tvoje mogućnosti vlasništva." + }, + "allSends": { + "message": "Svi Sendovi", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Datoteka" + }, + "sendTypeText": { + "message": "Tekst" + }, + "searchSends": { + "message": "Pretraži Sendove", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Uredi Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Moj trezor" + }, + "text": { + "message": "Tekst" + }, + "deletionDate": { + "message": "Obriši za" + }, + "deletionDateDesc": { + "message": "Send će nakon navedenog vremena biti trajno izbrisan.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Vremenski ograničeni pristup" + }, + "expirationDateDesc": { + "message": "Pristup ovom Sendu neće biti moguć nakon navednog roka.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Ograničeni broj pristupanja" + }, + "maxAccessCountDesc": { + "message": "Ako je određen, ovom Sendu će se moći pristupiti samo ograničeni broj puta.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Trenutni broj pristupanja" + }, + "disableSend": { + "message": "Onemogući ovaj Send da mu nitko ne može pristupiti.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Neobavezno zahtijevaj korisnika lozinku za pristup ovom Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privatne bilješke o Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Veza na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Veza na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Zadano sakrij tekst pri pristupanju Sendu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send stvoren", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send uređen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send izbrisan", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nova lozinka" + }, + "whatTypeOfSend": { + "message": "Koja je ovo vrsta Senda?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Stvori Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Tekst kojeg želiš poslati." + }, + "sendFileDesc": { + "message": "Datoteka koju želiš poslati." + }, + "days": { + "message": "$DAYS$ dana", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dan" + }, + "custom": { + "message": "Prilagođeno" + }, + "deleteSendConfirmation": { + "message": "Sigurno želiš izbrisati ovaj Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopiraj vezu na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kopiraj vezu na Send nakon spremanja" + }, + "sendDisabled": { + "message": "Send onemogućen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Pravila tvrtke omogućuju brisanje samo postojećeg Senda.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopiraj vezu" + }, + "disabled": { + "message": "Onemogućeno" + }, + "maxAccessCountReached": { + "message": "Dostignut najveći broj pristupanja" + }, + "expired": { + "message": "Isteklo" + }, + "pendingDeletion": { + "message": "Čeka brisanje" + }, + "webAuthnAuthenticate": { + "message": "Ovjeri WebAuthn" + }, + "hideEmail": { + "message": "Sakrij moju adresu e-pošte od primatelja." + }, + "sendOptionsPolicyInEffect": { + "message": "Jedno ili više pravila organizacije utječe na postavke Senda." + }, + "emailVerificationRequired": { + "message": "Potrebna je potvrda e-pošte" + }, + "emailVerificationRequiredDesc": { + "message": "Za korištenje ove značajke, potrebna je ovjera e-pošte." + }, + "passwordPrompt": { + "message": "Ponovno zatraži glavnu lozinku" + }, + "passwordConfirmation": { + "message": "Potvrda glavne lozinke" + }, + "passwordConfirmationDesc": { + "message": "Ova radnja je zaštićena. Za nastavak i potvrdu identiteta, unesi svoju glavnu lozinku." + }, + "updatedMasterPassword": { + "message": "Glavna lozinka ažurirana" + }, + "updateMasterPassword": { + "message": "Ažuriraj glavnu lozinku" + }, + "updateMasterPasswordWarning": { + "message": "Tvoju glavnu lozinku je nedavno promijenio administrator tvoje organizacije. Za pristup trezoru, potrebno je ažurirati glavnu lozinku, što će te odjaviti iz trenutne sesije, te ćeš se morati ponovno prijaviti. Aktivne sesije na drugim uređajima mogu ostati aktivne još sat vremena." + }, + "hours": { + "message": "sat(i)" + }, + "minutes": { + "message": "minuta" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Pravilo tvoje organizacije utječe na istek trezora. Najveće dozvoljeno vrijeme isteka je $HOURS$:$MINUTES$ h.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Vrijeme isteka premašuje ograničenje koju je postavila tvoja organizacija." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatsko učlanjenje" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Pravilo ove organizacija automatski će te učlaniti u ponovno postavljanje lozinke. Učlanjenje će omogućiti administratorima organizacije promjenu tvoje glavne lozinke." + }, + "vaultExportDisabled": { + "message": "Izvoz trezora onemogućen" + }, + "personalVaultExportPolicyInEffect": { + "message": "Jedno ili više pravila organizacija onemogućuje izvoz osobnog trezora. " + }, + "addAccount": { + "message": "Dodaj račun" + }, + "removeMasterPassword": { + "message": "Ukloni glavnu lozinku" + }, + "removedMasterPassword": { + "message": "Glavna lozinka uklonjena." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ koristi jedinstvenu prijavu SSO s vlastitim poslužiteljem. Članovima organizacije glavna lozinka više nije potrebna.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Napusti organizaciju" + }, + "leaveOrganizationConfirmation": { + "message": "Sigurno želiš napustiti ovu organizaciju?" + }, + "leftOrganization": { + "message": "Organizacija napuštena." + }, + "ssoKeyConnectorUnavailable": { + "message": "Nije moguće spajanje s konektorom za ključ, pokušaj kasnije." + }, + "lockAllVaults": { + "message": "Zaključaj sve trezore" + }, + "accountLimitReached": { + "message": "U isto vrijeme ne smije biti prijavljeno više od 5 računa." + }, + "accountPreferences": { + "message": "Postavke" + }, + "appPreferences": { + "message": "Postavke aplikacije (svi računi)" + }, + "accountSwitcherLimitReached": { + "message": "Dosegnuto je ograničenje računa. Odjavite se s računa da dodate drugi." + }, + "settingsTitle": { + "message": "Postavke aplikacije za $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Promijeni račun" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/hu/messages.json b/apps/desktop/src/locales/hu/messages.json new file mode 100644 index 0000000000..79ab96986b --- /dev/null +++ b/apps/desktop/src/locales/hu/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Szűrők" + }, + "allItems": { + "message": "Összes elem" + }, + "favorites": { + "message": "Kedvencek" + }, + "types": { + "message": "Típusok" + }, + "typeLogin": { + "message": "Bejelentkezés" + }, + "typeCard": { + "message": "Kártya" + }, + "typeIdentity": { + "message": "Személyazonosság" + }, + "typeSecureNote": { + "message": "Biztonságos jegyzet" + }, + "folders": { + "message": "Mappák" + }, + "collections": { + "message": "Gyűjtemények" + }, + "searchVault": { + "message": "Keresés a széfben" + }, + "addItem": { + "message": "Elem hozzáadása" + }, + "shared": { + "message": "Megosztva" + }, + "share": { + "message": "Megosztás" + }, + "moveToOrganization": { + "message": "Áthelyezés szervezethez" + }, + "movedItemToOrg": { + "message": "Példaérték $itemname$: titkos elem változóhoz\nPéldaérték $itemname$: cégnév változóhoz\nFájl: messages.json", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Válasszunk egy szervezetet, ahová áthelyezni szeretnénk ezt az elemet. A szervezetbe áthelyezés átruházza az elem tulajdonjogát az adott szervezetre. Az áthelyezés után többé nem leszünk az elem közvetlen tulajdonosa." + }, + "attachments": { + "message": "Mellékletek" + }, + "viewItem": { + "message": "Elem megtekintése" + }, + "name": { + "message": "Név" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI- $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Új URI" + }, + "username": { + "message": "Felhasználónév" + }, + "password": { + "message": "Jelszó" + }, + "passphrase": { + "message": "Kulcskifejezés" + }, + "editItem": { + "message": "Elem szerkesztése" + }, + "emailAddress": { + "message": "Email cím" + }, + "verificationCodeTotp": { + "message": "Ellenőrző kód (egyszeri-idő alapú)" + }, + "website": { + "message": "Webhely" + }, + "notes": { + "message": "Jegyzetek" + }, + "customFields": { + "message": "Egyedi mezők" + }, + "launch": { + "message": "Megnyitás" + }, + "copyValue": { + "message": "Érték másolása", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimalizálás vágólapra másoláskor" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimalizálás asz összes elemadat vágólapra másolásakor." + }, + "toggleVisibility": { + "message": "Láthatóság váltása" + }, + "toggleCollapse": { + "message": "Összezárás váltása", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kártyatulajdonos neve" + }, + "number": { + "message": "Szám" + }, + "brand": { + "message": "Márka" + }, + "expiration": { + "message": "Lejárat" + }, + "securityCode": { + "message": "Biztonsági kód" + }, + "identityName": { + "message": "Személyazonosság megnevezés" + }, + "company": { + "message": "Cég" + }, + "ssn": { + "message": "Társadalombiztosítási szám" + }, + "passportNumber": { + "message": "Útlevélszám" + }, + "licenseNumber": { + "message": "Vezetői engedély száma" + }, + "email": { + "message": "Email cím" + }, + "phone": { + "message": "Telefonszám" + }, + "address": { + "message": "Postai cím" + }, + "premiumRequired": { + "message": "Prémium verzió szükséges" + }, + "premiumRequiredDesc": { + "message": "A funkció használatához prémium tagság szükséges." + }, + "errorOccurred": { + "message": "Valamilyen hiba történt." + }, + "error": { + "message": "Hiba" + }, + "january": { + "message": "január" + }, + "february": { + "message": "február" + }, + "march": { + "message": "március" + }, + "april": { + "message": "április" + }, + "may": { + "message": "május" + }, + "june": { + "message": "június" + }, + "july": { + "message": "július" + }, + "august": { + "message": "augusztus" + }, + "september": { + "message": "szeptember" + }, + "october": { + "message": "október" + }, + "november": { + "message": "november" + }, + "december": { + "message": "december" + }, + "ex": { + "message": "példa:", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Címzés" + }, + "mr": { + "message": "Úr" + }, + "mrs": { + "message": "Asszony" + }, + "ms": { + "message": "Kisasszony" + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Lejárati hónap" + }, + "expirationYear": { + "message": "Lejárati év" + }, + "select": { + "message": "Kijelölés" + }, + "other": { + "message": "Egyéb" + }, + "generatePassword": { + "message": "Jelszó generálása" + }, + "type": { + "message": "Típus" + }, + "firstName": { + "message": "Személynév" + }, + "middleName": { + "message": "Középső név" + }, + "lastName": { + "message": "Családnév" + }, + "fullName": { + "message": "Teljes név" + }, + "address1": { + "message": "Postai cím 1" + }, + "address2": { + "message": "Postai cím 2" + }, + "address3": { + "message": "Postai cím 3" + }, + "cityTown": { + "message": "Település" + }, + "stateProvince": { + "message": "Állam/Megye" + }, + "zipPostalCode": { + "message": "Irányítószám" + }, + "country": { + "message": "Ország" + }, + "save": { + "message": "Mentés" + }, + "cancel": { + "message": "Mégsem" + }, + "delete": { + "message": "Törlés" + }, + "favorite": { + "message": "Kedvenc" + }, + "edit": { + "message": "Szerkesztés" + }, + "authenticatorKeyTotp": { + "message": "Hitelesítő kulcs (egyszeri-idő alapú)" + }, + "folder": { + "message": "Mappa" + }, + "newCustomField": { + "message": "Új egyedi mező" + }, + "value": { + "message": "Érték" + }, + "dragToSort": { + "message": "Húzás a rendezéshez" + }, + "cfTypeText": { + "message": "Szöveg" + }, + "cfTypeHidden": { + "message": "Rejtett" + }, + "cfTypeBoolean": { + "message": "Logikai" + }, + "cfTypeLinked": { + "message": "Csatolva", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Csatolt érték", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Eltávolítás" + }, + "nameRequired": { + "message": "A név megadása kötelező." + }, + "addedItem": { + "message": "Az elem hozzáadásra került." + }, + "editedItem": { + "message": "Az elem szerkesztésre került." + }, + "deleteItem": { + "message": "Elem törlése" + }, + "deleteFolder": { + "message": "Mappa törlése" + }, + "deleteAttachment": { + "message": "Melléklet törlése" + }, + "deleteItemConfirmation": { + "message": "Biztosan törlésre kerüljön ez az elem?" + }, + "deletedItem": { + "message": "Az elem törlésre került." + }, + "overwritePasswordConfirmation": { + "message": "Biztosan felülírásra kerüljön a jelenlegi jelszó?" + }, + "overwriteUsername": { + "message": "Felhasználónév felülírása" + }, + "overwriteUsernameConfirmation": { + "message": "Biztosan felülírásra kerüljön az aktuális felhasználónév?" + }, + "noneFolder": { + "message": "Nincs mappa", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Mappa hozzáadása" + }, + "editFolder": { + "message": "Mappa szerkesztése" + }, + "regeneratePassword": { + "message": "Jelszó újragenerálása" + }, + "copyPassword": { + "message": "Jelszó másolása" + }, + "copyUri": { + "message": "URI másolása" + }, + "copyVerificationCodeTotp": { + "message": "Ellenőrző kód másolása (TOTP)" + }, + "length": { + "message": "Hossz" + }, + "numWords": { + "message": "Szavak száma" + }, + "wordSeparator": { + "message": "Szó elválasztó" + }, + "capitalize": { + "message": "Nagy kezdőbetű", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Szám is" + }, + "close": { + "message": "Bezárás" + }, + "minNumbers": { + "message": "Minimális szám" + }, + "minSpecial": { + "message": "Minimális speciális", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Félreérthető karakterek mellőzése" + }, + "searchCollection": { + "message": "Gyűjtemény keresése" + }, + "searchFolder": { + "message": "Mappa keresése" + }, + "searchFavorites": { + "message": "Kedvencek keresése" + }, + "searchType": { + "message": "Típus keresése", + "description": "Search item type" + }, + "newAttachment": { + "message": "Új melléklet hozzáadása" + }, + "deletedAttachment": { + "message": "A melléklet törlésre került." + }, + "deleteAttachmentConfirmation": { + "message": "Biztos törlésre kerüljön ez a melléklet?" + }, + "attachmentSaved": { + "message": "A melléklet mentésre került." + }, + "file": { + "message": "Fájl" + }, + "selectFile": { + "message": "Válasszunk egy fájlt." + }, + "maxFileSize": { + "message": "Maximális fájl méret 500 MB." + }, + "updateKey": { + "message": "Ez a funkció nem használható a titkosítási kulcs frissítéséig." + }, + "editedFolder": { + "message": "A mappa szerkesztésre került." + }, + "addedFolder": { + "message": "A mappa hozzáadásra került." + }, + "deleteFolderConfirmation": { + "message": "Biztosan törlésre kerüljön ez a mappa?" + }, + "deletedFolder": { + "message": "A mappa törlésre került." + }, + "loginOrCreateNewAccount": { + "message": "Bejelentkezés vagy új fiók létrehozása a biztonsági széf eléréséhez." + }, + "createAccount": { + "message": "Fiók létrehozása" + }, + "logIn": { + "message": "Bejelentkezés" + }, + "submit": { + "message": "Beküldés" + }, + "masterPass": { + "message": "Mesterjelszó" + }, + "masterPassDesc": { + "message": "A mesterjelszó a jelszó a széf eléréséhez. Nagyon fontos a mesterjelszó ismerete. Nincs mód a jelszó visszaállítására." + }, + "masterPassHintDesc": { + "message": "A mesterjelszó emlékeztető segíthet emlékezni a jelszóra elfelejtés esetén." + }, + "reTypeMasterPass": { + "message": "Mesterjelszó ismételt beírása" + }, + "masterPassHint": { + "message": "Mesterjelszó emlékeztető (nem kötelező)" + }, + "settings": { + "message": "Beállítások" + }, + "passwordHint": { + "message": "Jelszó emlékeztető" + }, + "enterEmailToGetHint": { + "message": "A fiók email címének megadása a mesterjelszó emlékeztető fogadásához." + }, + "getMasterPasswordHint": { + "message": "Mesterjelszó emlékeztető kérése" + }, + "emailRequired": { + "message": "Az email cím megadása kötelező." + }, + "invalidEmail": { + "message": "Az email cím érvénytelen." + }, + "masterPassRequired": { + "message": "A mesterjelszó megadása kötelező." + }, + "masterPassLength": { + "message": "A mesterjelszó legyen legalább 8 karakter hosszú." + }, + "masterPassDoesntMatch": { + "message": "A mesterjelszó megerősítése nem egyezik." + }, + "newAccountCreated": { + "message": "A fiók létrehozásra került. Most már be lehet jelentkezni." + }, + "masterPassSent": { + "message": "Elküldtünk neked egy emailt a mesterjelszó emlékeztetővel." + }, + "unexpectedError": { + "message": "Váratlan hiba történt." + }, + "itemInformation": { + "message": "Elem információ" + }, + "noItemsInList": { + "message": "Nincsenek megjeleníthető elemek." + }, + "sendVerificationCode": { + "message": "Ellenőrző kód elküldése a saját email címre" + }, + "sendCode": { + "message": "Kód küldése" + }, + "codeSent": { + "message": "A kód elküldésre került." + }, + "verificationCode": { + "message": "Ellenőrző kód" + }, + "confirmIdentity": { + "message": "A folytatáshoz meg kell erősíteni a személyazonosságot." + }, + "verificationCodeRequired": { + "message": "Az ellenőrző kód kötelező." + }, + "invalidVerificationCode": { + "message": "Érvénytelen ellenőrző kód" + }, + "continue": { + "message": "Folytatás" + }, + "enterVerificationCodeApp": { + "message": "A 6 számjegyű ellenőrző kód megadása a hitelesítő alkalmazásból." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ email címre elküldött 6 számjegyű ellenőrző kód megadása.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Az ellenőrző kód elküldésre került $EMAIL$ email címre.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Adatok megjegyzése" + }, + "sendVerificationCodeEmailAgain": { + "message": "Megerősítő kód ismételt elküldése emailben" + }, + "useAnotherTwoStepMethod": { + "message": "Másik kétlépcsős bejelentkezési mód használata" + }, + "insertYubiKey": { + "message": "A YubiKey beillesztése a számítógép USB portjába és a rajta levő gomb megnyomása." + }, + "insertU2f": { + "message": "A biztonsági kulcs beillesztése a számítógép USB portjába. Ha van rajta gomb, nyomjuk meg." + }, + "recoveryCodeDesc": { + "message": "Elveszett a hozzáférés az összes kétlépcsős szolgáltatóhoz? A visszaállítókód használatával letilthatók fiókból a kétlépcsős szolgáltatók." + }, + "recoveryCodeTitle": { + "message": "Helyreállító kód" + }, + "authenticatorAppTitle": { + "message": "Hitelesítő alkalmazás" + }, + "authenticatorAppDesc": { + "message": "Hitelesítő alkalmazás használata (mint például az Authy vagy a Google Authenticator) idő alapú ellenőrzőkód generálásához.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP egyszeri időalapú jelszó biztonsági kulcs" + }, + "yubiKeyDesc": { + "message": "YubiKey használata a fiók eléréséhez. Működik a YubiKey 4, 4 Nano, 4C, és NEO eszközökkel." + }, + "duoDesc": { + "message": "Ellenőrzés Duo Security segítségével a Duo Mobile alkalmazás, SMS, telefonhívás vagy U2F biztonsági kulcs használatával.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Ellenőrzés szervezeti Duo Security segítségével a Duo Mobile alkalmazás, SMS, telefonhívás vagy U2F biztonsági kulcs használatával.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Használjunk bármilyen WebAuthn engedélyezett biztonsági kulcsot a saját fiók eléréséhez." + }, + "emailTitle": { + "message": "Email cím" + }, + "emailDesc": { + "message": "Az ellenőrző kódok emailben kerülnek elküldésre." + }, + "loginUnavailable": { + "message": "A bejelentkezés nem érhető el." + }, + "noTwoStepProviders": { + "message": "Ezen a fiókon kétlépcsős bejelentkezés van engedélyezve, de ez az eszköz nem támogatja egyik beállított kétlépcsős szolgáltatót sem." + }, + "noTwoStepProviders2": { + "message": "Az eszközöket jobban támogató további szolgáltatók hozzáadása (például egy hitelesítő alkalmazás)." + }, + "twoStepOptions": { + "message": "Kétlépcsős bejelentkezés opciók" + }, + "selfHostedEnvironment": { + "message": "Saját üzemeltetésű környezet" + }, + "selfHostedEnvironmentFooter": { + "message": "A helyileg üzemeltetett Bitwarden telepítés webcímének megadása." + }, + "customEnvironment": { + "message": "Egyedi környezet" + }, + "customEnvironmentFooter": { + "message": "Haladó felhasználóknak. Minden egyes szolgáltatásnak külön megadható az alap webcím." + }, + "baseUrl": { + "message": "Szerver webcím" + }, + "apiUrl": { + "message": "API szerver webcím" + }, + "webVaultUrl": { + "message": "Webes széf szerver webcím" + }, + "identityUrl": { + "message": "Személyazonosság szerver webcím" + }, + "notificationsUrl": { + "message": "Értesítési szerver webcím" + }, + "iconsUrl": { + "message": "Ikonok szerver webcím" + }, + "environmentSaved": { + "message": "A környezeti webcímek mentésre kerültek." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Igen" + }, + "no": { + "message": "Nem" + }, + "overwritePassword": { + "message": "Jelszó felülírása" + }, + "learnMore": { + "message": "További információ" + }, + "featureUnavailable": { + "message": "Ez a funkció nem érhető el." + }, + "loggedOut": { + "message": "Megtörtént a kijelentkezés." + }, + "loginExpired": { + "message": "A bejelentkezési munkamenet lejárt." + }, + "logOutConfirmation": { + "message": "Biztosan szeretnénk kijelentkezni?" + }, + "logOut": { + "message": "Kijelentkezés" + }, + "addNewLogin": { + "message": "Új bejelentkezés hozzáadása" + }, + "addNewItem": { + "message": "Új elem hozzáadása" + }, + "addNewFolder": { + "message": "Új mappa hozzáadása" + }, + "view": { + "message": "Megtekintés" + }, + "account": { + "message": "Fiók" + }, + "loading": { + "message": "A betöltés folyamatban van..." + }, + "lockVault": { + "message": "Széf lezárása" + }, + "passwordGenerator": { + "message": "Jelszó generátor" + }, + "contactUs": { + "message": "Kapcsolatfelvétel" + }, + "getHelp": { + "message": "Segítségkérés" + }, + "fileBugReport": { + "message": "Hibajelentés" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Követés" + }, + "syncVault": { + "message": "Széf szinkronizálása" + }, + "changeMasterPass": { + "message": "Mesterjelszó módosítása" + }, + "changeMasterPasswordConfirmation": { + "message": "A mesterjelszó megváltoztatható a bitwarden.com webes széfben. Szeretnénk felkeresni a webhelyet mos?" + }, + "fingerprintPhrase": { + "message": "Ujjlenyomat kifejezés", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fiók ujjlenyomat kifejezése", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Ugrás a webes széfhez" + }, + "getMobileApp": { + "message": "Mobil alkalmazás beszerzése" + }, + "getBrowserExtension": { + "message": "Böngésző bővítmény beszerzése" + }, + "syncingComplete": { + "message": "A szinkronizálás befejezésre került." + }, + "syncingFailed": { + "message": "A szinkronizálás meghiúsult." + }, + "yourVaultIsLocked": { + "message": "A széf zárolásra került. A folytatáshoz meg kell adni a mesterjelszót." + }, + "unlock": { + "message": "Feloldás" + }, + "loggedInAsOn": { + "message": "Bejelentkezve mint $EMAIL$ $HOSTNAME$ webhelyen.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "A mesterjelszó érvénytelen." + }, + "twoStepLoginConfirmation": { + "message": "A kétlépcsős bejelentkezés biztonságosabbá teszi a fiókot azzal, hogy meg kell erősíteni a bejelentkezést egy másik olyan eszközzel mint például biztonsági kulcs, hitelesítő alkalmazás, SMS, telefonhívás vagy email. A kétlépcsős bejelentkezést a bitwarden.com webes széfben lehet megváltoztatni. Szeretnénk felkeresni most a webhelyet?" + }, + "twoStepLogin": { + "message": "Kétlépcsős bejelentkezés" + }, + "vaultTimeout": { + "message": "Széf időkifutás" + }, + "vaultTimeoutDesc": { + "message": "Válasszuk ki, hogy a széfnél mikor legyen időkifutás és a kiválasztott művelet végrehajtása." + }, + "immediately": { + "message": "Azonnal" + }, + "tenSeconds": { + "message": "10 másodperc" + }, + "twentySeconds": { + "message": "20 másodperc" + }, + "thirtySeconds": { + "message": "30 másodperc" + }, + "oneMinute": { + "message": "1 perc" + }, + "twoMinutes": { + "message": "2 perc" + }, + "fiveMinutes": { + "message": "5 perc" + }, + "fifteenMinutes": { + "message": "15 perc" + }, + "thirtyMinutes": { + "message": "30 perc" + }, + "oneHour": { + "message": "1 óra" + }, + "fourHours": { + "message": "4 óra" + }, + "onIdle": { + "message": "Rendszer üresjárat esetén" + }, + "onSleep": { + "message": "Rendszer alvó mód esetén" + }, + "onLocked": { + "message": "Rendszer zárolás esetén" + }, + "onRestart": { + "message": "Újraindításkor" + }, + "never": { + "message": "Soha" + }, + "security": { + "message": "Biztonság" + }, + "clearClipboard": { + "message": "Vágólap ürítése", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatikusan törli a vágólapra másolt értékeket.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Webhely ikonok letiltása" + }, + "disableFaviconDesc": { + "message": "A webhelyek ikonjai felismerhető ikonként jelennek meg a széf összes eleme mellett." + }, + "enableMinToTray": { + "message": "Kicsinyítés tálcaikonná" + }, + "enableMinToTrayDesc": { + "message": "Az ablak minimalizálásakor helyette egy ikon jelenik meg a rendszertálcán." + }, + "enableMinToMenuBar": { + "message": "Kicsinyítés a menüsávra" + }, + "enableMinToMenuBarDesc": { + "message": "Az ablak minimalizálásakor helyette egy ikon jelenik meg a rendszertálcán." + }, + "enableCloseToTray": { + "message": "Bezárás tálcaikonba" + }, + "enableCloseToTrayDesc": { + "message": "Az ablak bezárásakor helyette egy ikon jelenik meg a rendszertálcán." + }, + "enableCloseToMenuBar": { + "message": "Befejezés a menüsávnál" + }, + "enableCloseToMenuBarDesc": { + "message": "Az ablak bezárásakor helyette egy ikon jelenik meg a menüsávon." + }, + "enableTray": { + "message": "Tálcaikon engedélyezése" + }, + "enableTrayDesc": { + "message": "Ikon folyamatos megjelenítése a rendszertálcán." + }, + "startToTray": { + "message": "Indítás tálcaikonra" + }, + "startToTrayDesc": { + "message": "Az alkalmazás első indításakor csak egy ikon jelenjen meg a rendszertálcán." + }, + "startToMenuBar": { + "message": "Indítás a menüsávon" + }, + "startToMenuBarDesc": { + "message": "Az alkalmazás első indításakor csak egy ikon jelenjen meg a menüsávon." + }, + "openAtLogin": { + "message": "Automatikus indítás bejelentkezéskor" + }, + "openAtLoginDesc": { + "message": "A Bitwarden asztali alkalmazás automatikus indítása bejelentkezéskor." + }, + "alwaysShowDock": { + "message": "Mindig megjelenik a dokk elemen" + }, + "alwaysShowDockDesc": { + "message": "A Bitwarden ikon megjelenítése a dokk elemben még akkor is, ha a menüsorra van kicsinyítve." + }, + "confirmTrayTitle": { + "message": "Tálca letiltás megerősítése" + }, + "confirmTrayDesc": { + "message": "Ennek a beállításnak a kikapcsolásával az összes többi tálcával kapcsolatos beállítás is letiltásra kerül." + }, + "language": { + "message": "Nyelv" + }, + "languageDesc": { + "message": "Az alkalmazás nyelvének megváltoztatása. Újraindítás szükséges." + }, + "theme": { + "message": "Téma" + }, + "themeDesc": { + "message": "Az alkalmazás színtémájának megváltoztatása." + }, + "dark": { + "message": "Sötét", + "description": "Dark color" + }, + "light": { + "message": "Világos", + "description": "Light color" + }, + "copy": { + "message": "Másolás", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Frissítések ellenőrzése" + }, + "version": { + "message": "Verzió: $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Újraindítás a frissítéshez" + }, + "restartToUpdateDesc": { + "message": "Az új $VERSION_NUM$ verzió készen áll a telepítéshez. A telepítés befejezéséhez újra kell indítani az alkalmazást. Szeretnénk most az újraindítást és a frissítést?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Frissítés érhető el" + }, + "updateAvailableDesc": { + "message": "Egy frissítés jelent meg. Szeretnénk most letölteni?" + }, + "restart": { + "message": "Újraindítás" + }, + "later": { + "message": "Később" + }, + "noUpdatesAvailable": { + "message": "Jelenleg nem található frissítés. A legfrissebb verzió van használatban." + }, + "updateError": { + "message": "Frissítési hiba történt." + }, + "unknown": { + "message": "Ismeretlen" + }, + "copyUsername": { + "message": "Felhasználónév másolása" + }, + "copyNumber": { + "message": "Szám másolása", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Biztonsági kód másolása", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Prémium tagság" + }, + "premiumManage": { + "message": "Tagság kezelése" + }, + "premiumManageAlert": { + "message": "Prémium tagság a bitwarden.com webes széfben kezelhető. Szeretnénk most felkeresni a webhelyet?" + }, + "premiumRefresh": { + "message": "Tagság frissítése" + }, + "premiumNotCurrentMember": { + "message": "Jelenleg nincs prémium tagság." + }, + "premiumSignUpAndGet": { + "message": "Regisztráció a prémium tagságra az alábbi funkciókért:" + }, + "premiumSignUpStorage": { + "message": "1 GB titkosított fájlmelléklet tárhely." + }, + "premiumSignUpTwoStep": { + "message": "További olyan kétlépcsős bejelentkezési opciók mint a YubiKey, FIDO U2F és Duo." + }, + "premiumSignUpReports": { + "message": "Jelszó higiénia, felhasználói fiók biztonsága, és adatszivárgási jelentések a széf biztonsága érdekében." + }, + "premiumSignUpTotp": { + "message": "Egyszeri időalapú TOTP ellenőrző kód (2FA) generátor a széfbe bejelentkezésekhez." + }, + "premiumSignUpSupport": { + "message": "Elsőbbségi ügyfél támogatás." + }, + "premiumSignUpFuture": { + "message": "Minden jövőbeli prémium funkció. Hamarosan jön még több." + }, + "premiumPurchase": { + "message": "Prémium verzió megvásárlása" + }, + "premiumPurchaseAlert": { + "message": "Prémium tagságot a bitwarden.com webes széfben lehet vásárolni. Szeretnénk most felkeresni a webhelyet?" + }, + "premiumCurrentMember": { + "message": "Jelenleg a prémium tagság érvényben van." + }, + "premiumCurrentMemberThanks": { + "message": "Köszönjük a Bitwarden támogatását." + }, + "premiumPrice": { + "message": "Mindez csak $PRICE$ /év.", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "A frissítés befejezésre került." + }, + "passwordHistory": { + "message": "Jelszó előzmények" + }, + "clear": { + "message": "Kiürítés", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Nincsenek listázható jelszavak." + }, + "undo": { + "message": "Visszavonás" + }, + "redo": { + "message": "Megismétlés" + }, + "cut": { + "message": "Kivágás", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Beillesztés", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Összes kijelölése" + }, + "zoomIn": { + "message": "Nagyítás" + }, + "zoomOut": { + "message": "Kicsinyítés" + }, + "resetZoom": { + "message": "Nagyítás alaphelyzetbe" + }, + "toggleFullScreen": { + "message": "Teljes képernyős módra váltás" + }, + "reload": { + "message": "Újratöltés" + }, + "toggleDevTools": { + "message": "Fejlesztőeszközök váltás" + }, + "minimize": { + "message": "Minimalizálás", + "description": "Minimize window" + }, + "zoom": { + "message": "Nagyítás" + }, + "bringAllToFront": { + "message": "Összes előtérbe helyezése", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Bitwarden névjegy" + }, + "services": { + "message": "Szolgáltatások" + }, + "hideBitwarden": { + "message": "Bitwarden elrejtése" + }, + "hideOthers": { + "message": "Többi elrejtése" + }, + "showAll": { + "message": "Összes megjelenítése" + }, + "quitBitwarden": { + "message": "Kilépés a Bitwardenből" + }, + "valueCopied": { + "message": "$VALUE$ másolásra került.", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Súgó" + }, + "window": { + "message": "Ablak" + }, + "checkPassword": { + "message": "A jelszóvédelem ellenőrzése." + }, + "passwordExposed": { + "message": "Ez a jelszó már $VALUE$ alkalommal volt kitéve az adatszivárgásnak. Célszerű megváltoztatni.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Ez a jelszó nem található egyetlen ismert adatszivárgásban sem. Biztonságos a használata." + }, + "baseDomain": { + "message": "Alap domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Tartománynév", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Kiszolgáló", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Pontos" + }, + "startsWith": { + "message": "Ezzel kezdődik:" + }, + "regEx": { + "message": "Reguláris kifejezés", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Találat érzékelés", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Alapértelmezett találat érzékelés", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Opciók váltása" + }, + "organization": { + "message": "Szervezet", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Alapértelmezett" + }, + "exit": { + "message": "Kilépés" + }, + "showHide": { + "message": "Megjelenítés / Elrejtés", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Elrejtés a tálcára" + }, + "alwaysOnTop": { + "message": "Mindig felül", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "A frissítés megtörtént.", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "A jelszó frissítésre került.", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Széf exportálása" + }, + "fileFormat": { + "message": "Fájlformátum" + }, + "warning": { + "message": "FIGYELEM", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Széf exportálás megerősítése" + }, + "exportWarningDesc": { + "message": "Ez az exportálás titkosítás nélkül tartalmazza a széfadatokat.Nem célszerű az exportált fájlt nem biztonságos csatornákon tárolni és továbbküldeni (például emailben). A felhasználás után erősen ajánlott a törlés." + }, + "encExportKeyWarningDesc": { + "message": "Ez az exportálás titkosítja az adatokat a fiók titkosítási kulcsával. Ha a fiók forgatási kulcsa más lesz, akkor újra exportálni kell, mert nem lehet visszafejteni ezt az exportálási fájlt." + }, + "encExportAccountWarningDesc": { + "message": "A fiók titkosítási kulcsai minden Bitwarden felhasználói fiókhoz egyediek, ezért nem importálhatunk titkosított exportálást egy másik fiókba." + }, + "noOrganizationsList": { + "message": "Még nem tartozunk egyik szervezethez sem. A szervezetek lehetővé teszik az elemek megosztását más felhasználókkal." + }, + "noCollectionsInList": { + "message": "Nincsenek megjeleníthető gyűjtemények." + }, + "ownership": { + "message": "Tulajdonjog" + }, + "whoOwnsThisItem": { + "message": "Ki tulajdonolja ezt az elemet?" + }, + "strong": { + "message": "Erős", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Jó", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Gyenge", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Gyenge mesterjelszó" + }, + "weakMasterPasswordDesc": { + "message": "A választott mesterjelszó gyenge. Erős jelszót (vagy kifejezést) kell használni a Bitwarden fiók megfelelő védelme érdekében. Biztosan ezt a mesterjelszót szeretnénk használni?" + }, + "pin": { + "message": "Pinkód", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Felnyitás pinkóddal" + }, + "setYourPinCode": { + "message": "A pinkód beállítása a Bitwarden feloldásához. A pinkód beállítások alaphelyzetbe kerülnek az alkalmazásból történő teljes kijelentkezés után." + }, + "pinRequired": { + "message": "A pinkód szükséges." + }, + "invalidPin": { + "message": "A pinkód érvénytelen." + }, + "unlockWithWindowsHello": { + "message": "Feloldás Windows Hello segítségével" + }, + "windowsHelloConsentMessage": { + "message": "Bitwarden ellenőrzés." + }, + "unlockWithTouchId": { + "message": "Feloldás Touch ID segítségével" + }, + "touchIdConsentMessage": { + "message": "Bitwarden feloldás" + }, + "noAutoPromptWindowsHello": { + "message": "Indításkor ne kérje a Windows Hello alkalmazást." + }, + "noAutoPromptTouchId": { + "message": "Indításkor ne kérje a Touch ID alkalmazást." + }, + "lockWithMasterPassOnRestart": { + "message": "Lezárás mesterjelszóval újraindításkor" + }, + "preferences": { + "message": "Beállítások" + }, + "enableMenuBar": { + "message": "Menüsáv ikon engedélyezése" + }, + "enableMenuBarDesc": { + "message": "Mindig jelenjen meg az ikon a menüsávban." + }, + "hideToMenuBar": { + "message": "Elrejtés a menüsávon" + }, + "selectOneCollection": { + "message": "Legalább egy gyűjteményt ki kell választani." + }, + "premiumUpdated": { + "message": "Megtörtént az áttérés a Prémium verzióra." + }, + "restore": { + "message": "Visszaállítás" + }, + "premiumManageAlertAppStore": { + "message": "A feliratkozás az App Store szolgáltatásból kezelhető Felkeressük az App Store-t most?" + }, + "legal": { + "message": "Jogi információk", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Használati feltételek" + }, + "privacyPolicy": { + "message": "Adatvédelem" + }, + "unsavedChangesConfirmation": { + "message": "Biztos a kilépés? A kilépés esetén az aktuális információ nem kerül mentésre." + }, + "unsavedChangesTitle": { + "message": "Mentetlen változások" + }, + "clone": { + "message": "Klónozás" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Egy vagy több szervezeti szabály érinti a generátor beállításokat." + }, + "vaultTimeoutAction": { + "message": "Széf időkifutás művelet" + }, + "vaultTimeoutActionLockDesc": { + "message": "Egy zárolt széfnél újra meg kell adni a mesterjelszót az ismételt hozzáféréshez." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A lezárt széfnél szükséges az újra hitelesítés az ismételt eléréshez." + }, + "lock": { + "message": "Lezárás", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Lomtár", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Keresés a lomtárban" + }, + "permanentlyDeleteItem": { + "message": "Az elem végleges törlése" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Biztosan véglegesen törlésre kerüljön ez az elem?" + }, + "permanentlyDeletedItem": { + "message": "Elem végleges törlése" + }, + "restoreItem": { + "message": "Elem visszaállítása" + }, + "restoreItemConfirmation": { + "message": "Biztosan visszaállításra kerüljön ezt az elem?" + }, + "restoredItem": { + "message": "Visszaállított elem" + }, + "permanentlyDelete": { + "message": "Végleges törlés" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Kijelentkezve az összes széf elérés eltávolításra kerül és webes hitelesítésre van szükség az időkifutás után. Biztosan szeretnénk használni ezt a beállítást?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Időkifutás művelet megerősítés" + }, + "enterpriseSingleSignOn": { + "message": "Vállalati önálló bejelentkezés" + }, + "setMasterPassword": { + "message": "Mesterjelszó beállítása" + }, + "ssoCompleteRegistration": { + "message": "Az SSO-val történő bejelentkezés befejezéséhez mesterjelszót kell beállítani a széf eléréséhez és védelméhez." + }, + "newMasterPass": { + "message": "Új mesterjelszó" + }, + "confirmNewMasterPass": { + "message": "Új mesterjelszó megerősítése" + }, + "masterPasswordPolicyInEffect": { + "message": "Egy vagy több szervezeti rendszabályhoz mesterjelszó szükséges a következő követelmények megfeleléséhez:" + }, + "policyInEffectMinComplexity": { + "message": "Minimális összetettségi pontszám $SCORE$ értékhez", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimális hossz $LENGTH$ értékből", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Egy vagy több nagybetűs karaktert tartalmaz" + }, + "policyInEffectLowercase": { + "message": "Egy vagy több kisbetűs karaktert tartalmaz" + }, + "policyInEffectNumbers": { + "message": "Egy vagy több számot tartalmaz" + }, + "policyInEffectSpecial": { + "message": "$CHARS$ speciális karakterekből egyet vagy többet tartalmaz", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Az új mesterjelszó nem felel meg a szabály követelményeknek." + }, + "acceptPolicies": { + "message": "A kapcsoló bekapcsolásával egyetértünk a következőkkel:" + }, + "acceptPoliciesError": { + "message": "A szolgáltatási feltételeket és az adatvédelmi irányelveket nem vették figyelembe." + }, + "enableBrowserIntegration": { + "message": "Böngésző integráció engedélyezése" + }, + "enableBrowserIntegrationDesc": { + "message": "A böngésző integrációt a biometrikus adatokhoz használják a böngészőben." + }, + "browserIntegrationMasOnlyTitle": { + "message": "A böngésző integráció nem támogatott." + }, + "browserIntegrationMasOnlyDesc": { + "message": "Sajnos a böngésző integrációt egyelőre csak a Mac App Store verzió támogatja." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "A böngésző integráció nem támogatott." + }, + "browserIntegrationWindowsStoreDesc": { + "message": "A böngésző integrációt egyelőre csak a Windows Store verzió támogatja." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Ellenőrzés kérése a böngésző integrációhoz" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Engedélyezzünk további biztonsági réteget ujjlenyomat kifejezés-hitelesítés kérésével az asztal és a böngésző közötti kapcsolat létrehozásakor. Ha engedélyezve van, ez minden egyes kapcsolat létrehozásakor felhasználói beavatkozást és ellenőrzést igényel." + }, + "approve": { + "message": "Jóváhagyás" + }, + "verifyBrowserTitle": { + "message": "Böngésző kapcsolat ellenőrzése" + }, + "verifyBrowserDesc": { + "message": "Ellenőrizzük, hogy a bemutatott ujjlenyomat megegyezik a böngésző kiterjesztésében megjelenített ujjlenyomattal." + }, + "biometricsNotEnabledTitle": { + "message": "A biometrikus adatok nincsenek engedélyezve." + }, + "biometricsNotEnabledDesc": { + "message": "A böngésző biometrikus adataihoz először az asztali biometrikus adatokat kell engedélyezni a beállításokban." + }, + "personalOwnershipSubmitError": { + "message": "Egy vállalati házirend miatt korlátozásra került az elemek személyes tárolóba történő mentése. Módosítsuk a Tulajdon opciót egy szervezetre és válasszunk az elérhető gyűjtemények közül." + }, + "hintEqualsPassword": { + "message": "A jelszavas tipp nem lehet azonos a jelszóval." + }, + "personalOwnershipPolicyInEffect": { + "message": "A szervezeti házirend befolyásolja a tulajdonosi opciókat." + }, + "allSends": { + "message": "Összes küldés", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fájl" + }, + "sendTypeText": { + "message": "Szöveg" + }, + "searchSends": { + "message": "Küldés keresése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Küldés szerkesztése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Saját széf" + }, + "text": { + "message": "Szöveg" + }, + "deletionDate": { + "message": "Törlési dátum" + }, + "deletionDateDesc": { + "message": "A Send véglegesen törlésre kerül a meghatározott időpontban.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Lejárati dátum" + }, + "expirationDateDesc": { + "message": "Beállítva a hozzáférés ehhez a Küldéshez lejár a meghatározott időpontban.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximális elérési szám" + }, + "maxAccessCountDesc": { + "message": "Beállítva a Küldés elérhetetlen lesz a meghatározott hozzáférések számának elérése után.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Aktuális elérési szám" + }, + "disableSend": { + "message": "A Küldés letiltásával mindenki hozzáférése megvonható.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcionálissan egy jelszó kérhető a felhasználóktól a Küldés eléréséhez.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Személyes megjegyzések erről a Küldésről.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Hivatkozás küldése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Hivatkozás küldése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "A Küldés elérésekor alapértelmezés szerint a szöveg elrejtése", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "A küldés létrejött", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "A küldés szerkesztésre került", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "A küldés törlésre került", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Új jelszó" + }, + "whatTypeOfSend": { + "message": "Milyen típusú ez a küldés?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "A küldés létrejött.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "A küldendő szöveg." + }, + "sendFileDesc": { + "message": "A küldendő fájl." + }, + "days": { + "message": "$DAYS$ nap", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 nap" + }, + "custom": { + "message": "Egyedi" + }, + "deleteSendConfirmation": { + "message": "Biztosan törlésre kerüljön ez a küldés?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Hivatkozás küldése másolás a vágólapra", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "A hivatkozás másolása a Küldés megosztásához a vágólapra mentéskor." + }, + "sendDisabled": { + "message": "A küldés kikapcsolásra került", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "A vállalati házirend miatt csak egy meglévő Küldés törölhető.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Hivatkozás másolása" + }, + "disabled": { + "message": "Letiltva" + }, + "maxAccessCountReached": { + "message": "A maximális hozzáférések száma elérésre került." + }, + "expired": { + "message": "Lejárt" + }, + "pendingDeletion": { + "message": "Függőben lévő törlés" + }, + "webAuthnAuthenticate": { + "message": "WebAutn hitelesítés" + }, + "hideEmail": { + "message": "Saját email cím elrejtése a címzettek elől." + }, + "sendOptionsPolicyInEffect": { + "message": "Egy vagy több szervezeti szabály érinti a Send opciókat." + }, + "emailVerificationRequired": { + "message": "E-mail hitelesítés szükséges" + }, + "emailVerificationRequiredDesc": { + "message": "A funkció használatához ellenőrizni kell az email címet." + }, + "passwordPrompt": { + "message": "Mesterjelszó ismételt megadás" + }, + "passwordConfirmation": { + "message": "Mesterjelszó megerősítése" + }, + "passwordConfirmationDesc": { + "message": "Ez a művelet védett. A folytatásért ismételten meg kell adni a mesterjelszőt az személyazonosság ellenőrzéséhez." + }, + "updatedMasterPassword": { + "message": "A mesterjelszó frisstésre került." + }, + "updateMasterPassword": { + "message": "Mesterjelszó frissítése" + }, + "updateMasterPasswordWarning": { + "message": "A szervezet egyik adminisztrátora nemrég megváltoztatta a mesterjelszót. A széf eléréséhez most frissíteni kell a mesterjelszót. Továbblépéskor kijelentkezés történik a jelenlegi munkamenetből és újra be kell jelentkezni. Ha van aktív munkamenet más eszközön, az még legfeljebb egy óráig aktív maradhat." + }, + "hours": { + "message": "Óra" + }, + "minutes": { + "message": "Perc" + }, + "vaultTimeoutPolicyInEffect": { + "message": "A szervezeti házirendek hatással vannak a széf időkorlátjára. A széf időkorlátja legfeljebb $HOURS$ óra és $MINUTES$ perc lehet.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "A széf időkorlátja túllépi a szervezet által beállított korlátozást." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatikus regisztráció" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ennek a szervezetnek van egy vállalati házirendje, amely automatikusan regisztrál a jelszó alaphelyzetbe állítására. A regisztráció lehetővé teszi a szervezet adminisztrátorainak a mesterjelszó megváltoztatását." + }, + "vaultExportDisabled": { + "message": "A széf exportálás nem engedélyezett." + }, + "personalVaultExportPolicyInEffect": { + "message": "Egy vagy több szervezeti házirend tiltja a személyes széf exportálását." + }, + "addAccount": { + "message": "Fiók hozzáadása" + }, + "removeMasterPassword": { + "message": "Mesterjelszó eltávolítása" + }, + "removedMasterPassword": { + "message": "A mesterjelszó eltávolításra került." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ jelenleg saját tárolású aláíráskulcsú SSO szervert használ. A mesterjelszó a továbbiakban nem szükséges a szervezeti tagsági bejelentkezéshez.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Szervezet elhagyása" + }, + "leaveOrganizationConfirmation": { + "message": "Biztosan kilépünk ebből a szervezetből?" + }, + "leftOrganization": { + "message": "Megtörtént a kilépés a szervezetből." + }, + "ssoKeyConnectorUnavailable": { + "message": "Nem érhető el a kulcskapcsoló. Próbáljuk újra később." + }, + "lockAllVaults": { + "message": "Összes széf lezárása" + }, + "accountLimitReached": { + "message": "Egyszerre legfeljebb 5 fiókba lehet bejelentkezni." + }, + "accountPreferences": { + "message": "Előbeállítások" + }, + "appPreferences": { + "message": "Alkalmazás beállítások (összes fiók)" + }, + "accountSwitcherLimitReached": { + "message": "A fiók korlát elérésre került. Kijelentkezés egy fiókból másik hozzáadásához." + }, + "settingsTitle": { + "message": "Alkalmezás beállítások $EMAIL$ címhez", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Fiók váltása" + }, + "options": { + "message": "Opciók" + }, + "sessionTimeout": { + "message": "A munkamenet lejárt. Lépjünk vissza és próbáljunk újra bejelentkezni." + }, + "exportingPersonalVaultTitle": { + "message": "Személyes széf exportálása" + }, + "exportingPersonalVaultDescription": { + "message": "Csak $EMAIL$ email címmel társított személyes széf elemek kerülnek exportálásra. Ebbe nem kerülnek be a szervezeti széf elemek.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generátor" + }, + "whatWouldYouLikeToGenerate": { + "message": "Mit szeretnénk generálni?" + }, + "passwordType": { + "message": "Jelszótípus" + }, + "regenerateUsername": { + "message": "Felhasználónév ismételt geneálása" + }, + "generateUsername": { + "message": "Felhasználónév generálása" + }, + "usernameType": { + "message": "Felhasználónév típusa" + }, + "plusAddressedEmail": { + "message": "További címzési email cím" + }, + "plusAddressedEmailDesc": { + "message": "Használjuk az email cím szolgáltató alcímzési képességeit." + }, + "catchallEmail": { + "message": "Összes email cím begyűjtése" + }, + "catchallEmailDesc": { + "message": "Használjuk a tartomány konfigurált összes befogási bejövő postaládát." + }, + "random": { + "message": "Véletlen" + }, + "randomWord": { + "message": "Véletlenszerű szó" + }, + "websiteName": { + "message": "Webhelynév" + }, + "service": { + "message": "Szolgáltatás" + } +} diff --git a/apps/desktop/src/locales/id/messages.json b/apps/desktop/src/locales/id/messages.json new file mode 100644 index 0000000000..8fdd59cfd8 --- /dev/null +++ b/apps/desktop/src/locales/id/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Saring" + }, + "allItems": { + "message": "Semua Item" + }, + "favorites": { + "message": "Favorit" + }, + "types": { + "message": "Tipe" + }, + "typeLogin": { + "message": "Masuk" + }, + "typeCard": { + "message": "Kartu" + }, + "typeIdentity": { + "message": "Identitas" + }, + "typeSecureNote": { + "message": "Catatan yang aman" + }, + "folders": { + "message": "Folder" + }, + "collections": { + "message": "Koleksi" + }, + "searchVault": { + "message": "Cari brankas" + }, + "addItem": { + "message": "Tambah Item" + }, + "shared": { + "message": "Dibagikan" + }, + "share": { + "message": "Berbagi" + }, + "moveToOrganization": { + "message": "Pindah ke Organisasi" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ pindah ke $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Pilihlah sebuah organisasi yang Anda ingin memindahkan item ini. Memindahkan berarti memberikan kepemilikan kepada organisasi tersebut. Anda tidak akan lagi menjadi pemilik item ini." + }, + "attachments": { + "message": "Lampiran" + }, + "viewItem": { + "message": "Lihat Item" + }, + "name": { + "message": "Nama" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "URl Baru" + }, + "username": { + "message": "Nama Pengguna" + }, + "password": { + "message": "Kata Sandi" + }, + "passphrase": { + "message": "Frasa sandi" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Alamat Email" + }, + "verificationCodeTotp": { + "message": "Kode Verifikasi (TOTP)" + }, + "website": { + "message": "Situs Web" + }, + "notes": { + "message": "Catatan" + }, + "customFields": { + "message": "Kolom Ubahsuai" + }, + "launch": { + "message": "Meluncurkan" + }, + "copyValue": { + "message": "Salin Nilai", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimalkan saat menyalin ke clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimalkan saat menyalin data item ke clipboard." + }, + "toggleVisibility": { + "message": "Alihkan Visibilitas" + }, + "toggleCollapse": { + "message": "Buka Tutup", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Nama Pemilik Kartu" + }, + "number": { + "message": "Nomor" + }, + "brand": { + "message": "Merek" + }, + "expiration": { + "message": "Masa Berlaku" + }, + "securityCode": { + "message": "Kode Keamanan" + }, + "identityName": { + "message": "Nama Identitas" + }, + "company": { + "message": "Perusahaan" + }, + "ssn": { + "message": "Nomor Jaminan Sosial" + }, + "passportNumber": { + "message": "Nomor Paspor" + }, + "licenseNumber": { + "message": "Nomor Lisensi" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telepon" + }, + "address": { + "message": "Alamat" + }, + "premiumRequired": { + "message": "Memerlukan Keanggotaan Premium" + }, + "premiumRequiredDesc": { + "message": "Keanggotaan premium diperlukan untuk menggunakan fitur ini." + }, + "errorOccurred": { + "message": "Terjadi kesalahan." + }, + "error": { + "message": "Galat" + }, + "january": { + "message": "Januari" + }, + "february": { + "message": "Februari" + }, + "march": { + "message": "Maret" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Mei" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "Agustus" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Desember" + }, + "ex": { + "message": "contoh", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Panggilan" + }, + "mr": { + "message": "Tuan" + }, + "mrs": { + "message": "Nyonya" + }, + "ms": { + "message": "Nona" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Bulan Kedaluwarsa" + }, + "expirationYear": { + "message": "Tahun Kedaluwarsa" + }, + "select": { + "message": "Pilih" + }, + "other": { + "message": "Lainnya" + }, + "generatePassword": { + "message": "Buat Kata Sandi" + }, + "type": { + "message": "Tipe" + }, + "firstName": { + "message": "Nama Depan" + }, + "middleName": { + "message": "Nama Tengah" + }, + "lastName": { + "message": "Nama Belakang" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Alamat 1" + }, + "address2": { + "message": "Alamat 2" + }, + "address3": { + "message": "Alamat 3" + }, + "cityTown": { + "message": "Kota / Kabupaten" + }, + "stateProvince": { + "message": "Negara Bagian / Provinsi" + }, + "zipPostalCode": { + "message": "Kode Pos" + }, + "country": { + "message": "Negara" + }, + "save": { + "message": "Simpan" + }, + "cancel": { + "message": "Batal" + }, + "delete": { + "message": "Hapus" + }, + "favorite": { + "message": "Favorit" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Kunci Autentikasi (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "Kolom Ubahsuai Baru" + }, + "value": { + "message": "Nilai" + }, + "dragToSort": { + "message": "Geser untuk sortir" + }, + "cfTypeText": { + "message": "Teks" + }, + "cfTypeHidden": { + "message": "Tersembunyi" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Hapus" + }, + "nameRequired": { + "message": "Nama diperlukan." + }, + "addedItem": { + "message": "Item yang Ditambahkan" + }, + "editedItem": { + "message": "Item yang Diedit" + }, + "deleteItem": { + "message": "Hapus Item" + }, + "deleteFolder": { + "message": "Hapus Folder" + }, + "deleteAttachment": { + "message": "Hapus Lampiran" + }, + "deleteItemConfirmation": { + "message": "Anda yakin Anda ingin menghapus item ini?" + }, + "deletedItem": { + "message": "Item yang Dihapus" + }, + "overwritePasswordConfirmation": { + "message": "Anda yakin ingin menimpa sandi saat ini?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Tidak Ada Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Tambah Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Buat Ulang Sandi" + }, + "copyPassword": { + "message": "Salin Kata Sandi" + }, + "copyUri": { + "message": "Salin URI" + }, + "copyVerificationCodeTotp": { + "message": "Salin Kode Verifikasi (TOTP)" + }, + "length": { + "message": "Panjang" + }, + "numWords": { + "message": "Jumlah kata" + }, + "wordSeparator": { + "message": "Pemisah Kata" + }, + "capitalize": { + "message": "Gunakan Huruf Besar", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Termasuk angka" + }, + "close": { + "message": "Tutup" + }, + "minNumbers": { + "message": "Angka Minimum" + }, + "minSpecial": { + "message": "Karakter Khusus Minimum", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Hindari Karakter Ambigu" + }, + "searchCollection": { + "message": "Cari koleksi" + }, + "searchFolder": { + "message": "Cari folder" + }, + "searchFavorites": { + "message": "Cari favorit" + }, + "searchType": { + "message": "Search type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Tambah Lampiran Baru" + }, + "deletedAttachment": { + "message": "Lampiran dihapus" + }, + "deleteAttachmentConfirmation": { + "message": "Anda yakin ingin menghapus lampiran ini?" + }, + "attachmentSaved": { + "message": "Lampiran telah disimpan." + }, + "file": { + "message": "Berkas" + }, + "selectFile": { + "message": "Pilih berkas." + }, + "maxFileSize": { + "message": "Ukuran berkas maksimal adalah 500 MB." + }, + "updateKey": { + "message": "Anda tidak dapat menggunakan fitur ini sampai Anda memperbarui kunci enkripsi Anda." + }, + "editedFolder": { + "message": "Folder yang di Edit" + }, + "addedFolder": { + "message": "Tambah Folder" + }, + "deleteFolderConfirmation": { + "message": "Anda yakin Anda ingin menghapus folder ini?" + }, + "deletedFolder": { + "message": "Folder yang terhapus" + }, + "loginOrCreateNewAccount": { + "message": "Masuk atau buat akun baru untuk mengakses brankas Anda." + }, + "createAccount": { + "message": "Buat Akun" + }, + "logIn": { + "message": "Masuk" + }, + "submit": { + "message": "Kirim" + }, + "masterPass": { + "message": "Sandi Utama" + }, + "masterPassDesc": { + "message": "Kata sandi utama adalah kata sandi yang Anda gunakan untuk mengakses brankas Anda. Sangat penting bahwa Anda tidak lupa kata sandi utama Anda. Tidak ada cara untuk memulihkan kata sandi jika Anda melupakannya." + }, + "masterPassHintDesc": { + "message": "Petunjuk kata sandi utama dapat membantu Anda mengingat kata sandi Anda jika Anda melupakannya." + }, + "reTypeMasterPass": { + "message": "Ketik Ulang Sandi Utama" + }, + "masterPassHint": { + "message": "Petunjuk Kata Sandi Utama (pilihan)" + }, + "settings": { + "message": "Setelan" + }, + "passwordHint": { + "message": "Petunjuk Sandi" + }, + "enterEmailToGetHint": { + "message": "Masukkan email akun Anda untuk menerima pentunjuk sandi utama Anda." + }, + "getMasterPasswordHint": { + "message": "Dapatkan petunjuk sandi utama" + }, + "emailRequired": { + "message": "Alamat email diperlukan." + }, + "invalidEmail": { + "message": "Alamat email tidak valid." + }, + "masterPassRequired": { + "message": "Sandi utama diperlukan." + }, + "masterPassLength": { + "message": "Kata sandi utama sedikitnya harus 8 karakter." + }, + "masterPassDoesntMatch": { + "message": "Konfirmasi sandi utama tidak cocok." + }, + "newAccountCreated": { + "message": "Akun baru Anda telah dibuat! Sekarang Anda bisa masuk." + }, + "masterPassSent": { + "message": "Kami telah mengirimi Anda email dengan petunjuk sandi utama Anda." + }, + "unexpectedError": { + "message": "Terjadi kesalahan yang tak diduga." + }, + "itemInformation": { + "message": "Informasi Item" + }, + "noItemsInList": { + "message": "Tidak ada item yang dapat dicantumkan." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Kode Verifikasi" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Kode verifikasi diperlukan." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Lanjutkan" + }, + "enterVerificationCodeApp": { + "message": "Masukkan 6 digit kode verifikasi dari aplikasi autentikasi Anda." + }, + "enterVerificationCodeEmail": { + "message": "Masukkan 6 digit kode verifikasi yang dikirim melalui email ke $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Email verifikasi dikirim ke $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Ingat saya" + }, + "sendVerificationCodeEmailAgain": { + "message": "Kirim ulang email kode verifikasi" + }, + "useAnotherTwoStepMethod": { + "message": "Gunakan metode masuk dua langkah lainnya" + }, + "insertYubiKey": { + "message": "Masukkan YubiKey Anda ke port USB komputer Anda, lalu sentuh tombol nya." + }, + "insertU2f": { + "message": "Masukkan kunci keamanan ke port USB komputer Anda. Jika ada tombolnya, tekanlah." + }, + "recoveryCodeDesc": { + "message": "Kehilangan akses ke semua penyedia dua faktor Anda? Gunakan kode pemulihan untuk menonaktifkan semua penyedia dua faktor dari akun Anda." + }, + "recoveryCodeTitle": { + "message": "Kode Pemulihan" + }, + "authenticatorAppTitle": { + "message": "Aplikasi Autentikasi" + }, + "authenticatorAppDesc": { + "message": "Gunakan aplikasi autentikasi (seperti Authy atau Google Authenticator) untuk menghasilkan kode verifikasi berbasis waktu.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Kunci Keamanan OTP YubiKey" + }, + "yubiKeyDesc": { + "message": "Gunakan YubiKey untuk mengakses akun Anda. Bekerja dengan YubiKey 4, 4 Nano, 4C, dan peranti NEO." + }, + "duoDesc": { + "message": "Verifikasi dengan Duo Security menggunakan aplikasi Duo Mobile, SMS, panggilan telepon, atau kunci keamanan U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifikasi dengan Duo Security untuk organisasi anda dengan menggunakan Aplikasi Duo Mobile, SMS, panggilan telepon atau kunci keamanan U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Gunakan kunci yang mendukung WebAUthn untuk mengakses akun anda." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Kode verifikasi akan dikirim via email kepada Anda." + }, + "loginUnavailable": { + "message": "Info Masuk Tidak Tersedia" + }, + "noTwoStepProviders": { + "message": "Akun ini mengaktifkan info masuk dua langkah, namun, tidak satupun dari penyedia dua langkah yang dikonfigurasi didukung oleh perangkat ini." + }, + "noTwoStepProviders2": { + "message": "Silahkan tambahkan penyedia tambahan yang baik didukung di perangkat (seperti aplikasi authenticator)." + }, + "twoStepOptions": { + "message": "Pilihan Info Masuk Dua Langkah" + }, + "selfHostedEnvironment": { + "message": "Lingkungan Hos-mandiri" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted bitwarden installation." + }, + "customEnvironment": { + "message": "Lingkungan Kustom" + }, + "customEnvironmentFooter": { + "message": "Untuk pengguna lanjutan. Anda dapat menentukan basis dari URL untuk setiap layanan mandiri." + }, + "baseUrl": { + "message": "URL Server" + }, + "apiUrl": { + "message": "URL Server API" + }, + "webVaultUrl": { + "message": "URL Server Brankas Web" + }, + "identityUrl": { + "message": "URL Server Identitas" + }, + "notificationsUrl": { + "message": "Pemberitahuan URL Server" + }, + "iconsUrl": { + "message": "URL Server Ikon" + }, + "environmentSaved": { + "message": "Lingkungan dari URL sudah tersimpan." + }, + "ok": { + "message": "Oke" + }, + "yes": { + "message": "Ya" + }, + "no": { + "message": "Tidak" + }, + "overwritePassword": { + "message": "Timpa Sandi" + }, + "learnMore": { + "message": "Pelajari lebih lanjut" + }, + "featureUnavailable": { + "message": "Fitur Tidak Tersedia" + }, + "loggedOut": { + "message": "Keluar" + }, + "loginExpired": { + "message": "Sesi masuk Anda telah berakhir." + }, + "logOutConfirmation": { + "message": "Anda yakin ingin keluar?" + }, + "logOut": { + "message": "Keluar" + }, + "addNewLogin": { + "message": "Tambahkan Info Masuk Baru" + }, + "addNewItem": { + "message": "Tambahkan Item Baru" + }, + "addNewFolder": { + "message": "Tambahkan Folder Baru" + }, + "view": { + "message": "Tampilan" + }, + "account": { + "message": "Akun" + }, + "loading": { + "message": "Memuat..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Pembuat Kata Sandi" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Buat Laporan Masalah" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Ikuti Kami" + }, + "syncVault": { + "message": "Sinkronisasi Brankas" + }, + "changeMasterPass": { + "message": "Ubah Kata Sandi Utama" + }, + "changeMasterPasswordConfirmation": { + "message": "Anda dapat mengubah kata sandi utama Anda di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" + }, + "fingerprintPhrase": { + "message": "Frase Fingerprint", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frase fingerprint milik Anda", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Buka Brankas Web" + }, + "getMobileApp": { + "message": "Dapatkan Aplikasi Seluler" + }, + "getBrowserExtension": { + "message": "Dapatkan Ekstensi Peramban" + }, + "syncingComplete": { + "message": "Sinkronisasi selesai" + }, + "syncingFailed": { + "message": "Gagal menyinkronkan" + }, + "yourVaultIsLocked": { + "message": "Brankas Anda terkunci. Verifikasi sandi utama Anda untuk melanjutkan." + }, + "unlock": { + "message": "Buka" + }, + "loggedInAsOn": { + "message": "Telah log in sebagai $EMAIL$ di $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Sandi utama tidak valid" + }, + "twoStepLoginConfirmation": { + "message": "Info masuk dua langkah membuat akun Anda lebih aman dengan mengharuskan Anda memverifikasi info masuk Anda dengan peranti lain seperti kode keamanan, aplikasi autentikasi, SMS, panggilan telepon, atau email. Info masuk dua langkah dapat diaktifkan di brankas web bitwarden.com. Anda ingin mengunjungi situs web sekarang?" + }, + "twoStepLogin": { + "message": "Info masuk dua langkah" + }, + "vaultTimeout": { + "message": "Batas Waktu Brankas" + }, + "vaultTimeoutDesc": { + "message": "Pilih kapan brankas Anda akan timeout dan melakukan tindakan yang dipilih." + }, + "immediately": { + "message": "Segera" + }, + "tenSeconds": { + "message": "10 detik" + }, + "twentySeconds": { + "message": "20 detik" + }, + "thirtySeconds": { + "message": "30 detik" + }, + "oneMinute": { + "message": "1 menit" + }, + "twoMinutes": { + "message": "2 menit" + }, + "fiveMinutes": { + "message": "5 menit" + }, + "fifteenMinutes": { + "message": "15 menit" + }, + "thirtyMinutes": { + "message": "30 menit" + }, + "oneHour": { + "message": "1 jam" + }, + "fourHours": { + "message": "4 jam" + }, + "onIdle": { + "message": "Saat sistem menganggur" + }, + "onSleep": { + "message": "Saat sistem tidur" + }, + "onLocked": { + "message": "Sistem kunci" + }, + "onRestart": { + "message": "Pada Mulai Ulang" + }, + "never": { + "message": "Tidak pernah" + }, + "security": { + "message": "Keamanan" + }, + "clearClipboard": { + "message": "Hapus Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Secara otomatis menghapus nilai yang disalin dari clipboard Anda.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Nonaktifkan Ikon Situs Web" + }, + "disableFaviconDesc": { + "message": "Ikon Situs Web menyediakan gambar yang dikenali di sebelah item info masuk di brankas Anda." + }, + "enableMinToTray": { + "message": "Kecilkan ke Ikon Baki" + }, + "enableMinToTrayDesc": { + "message": "Ketika jendela di perkecil, tampilkan ikon di dalam sistem baki sebagai gantinya." + }, + "enableMinToMenuBar": { + "message": "Minimalkan ke bilah menu" + }, + "enableMinToMenuBarDesc": { + "message": "Saat meminimalkan jendela, tampilkan ikon di bilah menu sebagai gantinya." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "Saat menutup jendela, tampilkan ikon di baki sistem sebagai gantinya." + }, + "enableCloseToMenuBar": { + "message": "Dekat dengan bilah menu" + }, + "enableCloseToMenuBarDesc": { + "message": "Saat menutup jendela, tampilkan ikon di bilah menu sebagai gantinya." + }, + "enableTray": { + "message": "Aktifkan Ikon Baki" + }, + "enableTrayDesc": { + "message": "Selalu tampilkan ikon di dalam baki sistem." + }, + "startToTray": { + "message": "Mulai Pada Baki Sistem" + }, + "startToTrayDesc": { + "message": "Saat aplikasi pertama kali dijalankan, hanya tampilkan ikon di baki sistem." + }, + "startToMenuBar": { + "message": "Mulai menu bar" + }, + "startToMenuBarDesc": { + "message": "Saat aplikasi pertama kali dijalankan, hanya tampilkan ikon di bilah menu." + }, + "openAtLogin": { + "message": "Mulai secara otomatis saat login" + }, + "openAtLoginDesc": { + "message": "Jalankan aplikasi Bitwarden Desktop secara otomatis saat login." + }, + "alwaysShowDock": { + "message": "Selalu tampilkan di Dock" + }, + "alwaysShowDockDesc": { + "message": "Tampilkan ikon Bitwarden di Dock bahkan saat diminimalkan ke bilah menu." + }, + "confirmTrayTitle": { + "message": "Konfirmasi nonaktifkan baki" + }, + "confirmTrayDesc": { + "message": "Menonaktifkan pengaturan ini juga akan menonaktifkan semua pengaturan terkait baki lainnya." + }, + "language": { + "message": "Bahasa" + }, + "languageDesc": { + "message": "Ubah bahasa yang di gunakan oleh aplikasi. Mulai Ulang diperlukan." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Ubah tema warna aplikasi." + }, + "dark": { + "message": "Gelap", + "description": "Dark color" + }, + "light": { + "message": "Terang", + "description": "Light color" + }, + "copy": { + "message": "Salin", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Periksa Pembaruan" + }, + "version": { + "message": "Versi $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Mulai ulang untuk Perbarui" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart Bitwarden to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Pembaruan Tersedia" + }, + "updateAvailableDesc": { + "message": "Pembaruan telah di temukan. Apakah anda ingin mengunduhnya sekarang?" + }, + "restart": { + "message": "Mulai Ulang" + }, + "later": { + "message": "Nanti" + }, + "noUpdatesAvailable": { + "message": "Tidak ada update saat ini. Kamu menggunakan versi terbaru." + }, + "updateError": { + "message": "Kesalahan pada Pembaruan" + }, + "unknown": { + "message": "Tidak diketahui" + }, + "copyUsername": { + "message": "Salin Nama Pengguna" + }, + "copyNumber": { + "message": "Salin Nomor", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Salin Kode Keamanan", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Keanggotaan Premium" + }, + "premiumManage": { + "message": "Kelola Keanggotaan" + }, + "premiumManageAlert": { + "message": "Anda dapat mengelola keanggotaan anda di Brankas Web bitwarden.com. Apakah anda ingin mengunjungi situs web itu sekarang?" + }, + "premiumRefresh": { + "message": "Segarkan Keanggotaan" + }, + "premiumNotCurrentMember": { + "message": "Anda saat ini bukanlah pengguna Premium." + }, + "premiumSignUpAndGet": { + "message": "Daftar untuk keanggotaan Premium dan dapatkan:" + }, + "premiumSignUpStorage": { + "message": "1 GB penyimpanan berkas yang dienkripsi." + }, + "premiumSignUpTwoStep": { + "message": "Pilihan info masuk dua langkah tambahan seperti YubiKey, FIDO U2F, dan Duo." + }, + "premiumSignUpReports": { + "message": "Kebersihan kata sandi, kesehatan akun, dan laporan pelanggaran data untuk menjaga brankas Anda tetap aman." + }, + "premiumSignUpTotp": { + "message": "Pembuat kode verifikasi TOTP (2FA) untuk masuk di brankas anda." + }, + "premiumSignUpSupport": { + "message": "Dukungan pelanggan Prioritas." + }, + "premiumSignUpFuture": { + "message": "Semua fitur Premium kedepannya. Selebihnya, akan segera hadir!" + }, + "premiumPurchase": { + "message": "Beli Premium" + }, + "premiumPurchaseAlert": { + "message": "Kamu bisa membeli keanggotaan Premium di Brankas Web bitwarden.com. Apakah kamu ingin mengunjungi situs web itu sekarang?" + }, + "premiumCurrentMember": { + "message": "Anda adalah anggota premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting bitwarden." + }, + "premiumPrice": { + "message": "Semua itu hanya $PRICE$/tahun!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Penyegaran selesai" + }, + "passwordHistory": { + "message": "Riwayat Kata Sandi" + }, + "clear": { + "message": "Bersihkan", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Tidak ada sandi yang dapat dicantumkan." + }, + "undo": { + "message": "Urungkan" + }, + "redo": { + "message": "Mengulangi" + }, + "cut": { + "message": "Potong", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Tempel", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Pilih Semua" + }, + "zoomIn": { + "message": "Perbesar" + }, + "zoomOut": { + "message": "Perkecil" + }, + "resetZoom": { + "message": "Set Ulang Zum" + }, + "toggleFullScreen": { + "message": "Aktif/nonaktifkan Layar Penuh" + }, + "reload": { + "message": "Muat ulang" + }, + "toggleDevTools": { + "message": "Aktif/nonaktifkan Alat Pengembang" + }, + "minimize": { + "message": "Perkecil", + "description": "Minimize window" + }, + "zoom": { + "message": "Zum" + }, + "bringAllToFront": { + "message": "Bawa Semua ke Depan", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Tentang Bitwarden" + }, + "services": { + "message": "Layanan" + }, + "hideBitwarden": { + "message": "Sembunyikan Bitwarden" + }, + "hideOthers": { + "message": "Sembunyikan Lainnya" + }, + "showAll": { + "message": "Tampilkan Semua" + }, + "quitBitwarden": { + "message": "Keluar dari Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ disalin", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Bantuan" + }, + "window": { + "message": "Jendela" + }, + "checkPassword": { + "message": "Periksa jika kata sandi telah terpapar." + }, + "passwordExposed": { + "message": "Kata sandi ini telah terpapar di dalam pelanggaran data selama $VALUE$ kali. Anda harus mengubahnya.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Kata sandi ini tidak di temukan di dalam pelanggaran data yang di kenal. Harusnya aman untuk di gunakan." + }, + "baseDomain": { + "message": "Basis domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tepat" + }, + "startsWith": { + "message": "Mulai dengan" + }, + "regEx": { + "message": "Ekspresi umum", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Deteksi kecocokan", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Deteksi kecocokan standar", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Ubah Opsi" + }, + "organization": { + "message": "Organisasi", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Bawaan" + }, + "exit": { + "message": "Keluar" + }, + "showHide": { + "message": "Tampilkan / Sembunyikan", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Sembunyi ke Tray" + }, + "alwaysOnTop": { + "message": "Selalu di Atas", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Di perbarui", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Kata Sandi telah Diperbarui", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Ekspor Brankas" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "PERINGATAN", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Konfirmasi Ekspor Vault" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "Ekspor ini mengenkripsi data Anda menggunakan kunci enkripsi akun Anda. Jika Anda pernah merotasi kunci enkripsi akun Anda, Anda harus mengekspor lagi karena Anda tidak akan dapat mendekripsi file ekspor ini." + }, + "encExportAccountWarningDesc": { + "message": "Kunci enkripsi akun unik untuk setiap akun pengguna Bitwarden, jadi Anda tidak dapat mengimpor ekspor terenkripsi ke akun lain." + }, + "noOrganizationsList": { + "message": "Anda tidak berada dalam organisasi apapun. Organisasi memungkinkan Anda dengan aman berbagi item dengan pengguna lainnya." + }, + "noCollectionsInList": { + "message": "Tidak ada koleksi yang akan ditampilkan." + }, + "ownership": { + "message": "Kepemilikan" + }, + "whoOwnsThisItem": { + "message": "Pemilik item ini?" + }, + "strong": { + "message": "Kuat", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Baik", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Lemah", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Kata Sandi Utama Lemah" + }, + "weakMasterPasswordDesc": { + "message": "Sandi utama yang Anda pilih itu lemah. Anda harus menggunakan sandi yang kuat (atau sebuah passphrase) untuk melindungi akun Bitwarden Anda. Apakah Anda yakin ingin menggunakan sandi ini?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Buka kunci dengan PIN" + }, + "setYourPinCode": { + "message": "Setel kode PIN Anda untuk membuka kunci Bitwarden. Pengaturan PIN Anda akan diatur ulang jika Anda pernah keluar secara menyeluruh dari aplikasi." + }, + "pinRequired": { + "message": "Diperlukan kode PIN." + }, + "invalidPin": { + "message": "Kode PIN tidak valid." + }, + "unlockWithWindowsHello": { + "message": "Buka dengan Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verifikasi untuk Bitwarden." + }, + "unlockWithTouchId": { + "message": "Buka kunci dengan Touch ID" + }, + "touchIdConsentMessage": { + "message": "Verifikasi untuk Bitwarden." + }, + "noAutoPromptWindowsHello": { + "message": "Jangan meminta Windows Hello waktu baru dinyalakan." + }, + "noAutoPromptTouchId": { + "message": "Jangan meminta Touch ID waktu baru dinyalakan." + }, + "lockWithMasterPassOnRestart": { + "message": "Kunci dengan kata sandi utama saat komputer dihidupkan ulang" + }, + "preferences": { + "message": "Preferensi" + }, + "enableMenuBar": { + "message": "Aktifkan Ikon Menu Bar" + }, + "enableMenuBarDesc": { + "message": "Selalu tampilkan ikon pada menu bar." + }, + "hideToMenuBar": { + "message": "Sembunyikan ke Menu Bar" + }, + "selectOneCollection": { + "message": "Anda harus memilih setidaknya satu koleksi." + }, + "premiumUpdated": { + "message": "Anda telah ditingkatkan ke premium." + }, + "restore": { + "message": "Pulihkan" + }, + "premiumManageAlertAppStore": { + "message": "Anda dapat mengelola langganan Anda di App Store. Apakah Anda ingin mengunjungi App Store sekarang?" + }, + "legal": { + "message": "Hukum", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Persyaratan Layanan" + }, + "privacyPolicy": { + "message": "Kebijakan Privasi" + }, + "unsavedChangesConfirmation": { + "message": "Anda yakin ingin keluar? Jika Anda keluar sekarang maka informasi Anda saat ini tidak akan disimpan." + }, + "unsavedChangesTitle": { + "message": "Perubahan Tidak Disimpan" + }, + "clone": { + "message": "Klon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Satu atau lebih kebijakan organisasi mempengaruhi pengaturan generator anda." + }, + "vaultTimeoutAction": { + "message": "Aksi Batas Waktu Penyimpanan" + }, + "vaultTimeoutActionLockDesc": { + "message": "Brankas yang terkunci membutuhkan Anda untuk memasukkan ulang password utama untuk mengakses kembali." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Brankas akan keluar dan Anda diminta untuk memasukkan password utama untuk mengakses kembali." + }, + "lock": { + "message": "Kunci", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Sampah", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Cari di sampah" + }, + "permanentlyDeleteItem": { + "message": "Hapus Item Permanen" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Apakah Anda yakin ingin menghapus item ini secara permanen?" + }, + "permanentlyDeletedItem": { + "message": "Item Terhapus Permanen" + }, + "restoreItem": { + "message": "Pulihkan Item" + }, + "restoreItemConfirmation": { + "message": "Apakah Anda yakin ingin memulihkan item ini?" + }, + "restoredItem": { + "message": "Item Yang Dipulihkan" + }, + "permanentlyDelete": { + "message": "Hapus Secara Permanen" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Keluar akan menghapus semua akses ke Brankas Anda dan memerlukan otentikasi online setelah batas waktu yang ditentukan. Anda yakin ingin menggunakan pengaturan ini?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Konfirmasi Aksi Batas Waktu" + }, + "enterpriseSingleSignOn": { + "message": "Sistem Masuk Tunggal Perusahaan" + }, + "setMasterPassword": { + "message": "Atur Kata Sandi Utama" + }, + "ssoCompleteRegistration": { + "message": "Untuk menyelesaikan masuk dengan SSO, harap setel kata sandi utama untuk mengakses dan melindungi brankas Anda." + }, + "newMasterPass": { + "message": "Kata Sandi Utama Baru" + }, + "confirmNewMasterPass": { + "message": "Konfirmasi Kata Sandi Baru" + }, + "masterPasswordPolicyInEffect": { + "message": "Satu atau lebih kebijakan organisasi memerlukan kata sandi utama Anda untuk memenuhi persyaratan berikut:" + }, + "policyInEffectMinComplexity": { + "message": "Skor kompleksitas minimum $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Panjang minimum $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Berisi satu atau lebih karakter huruf besar" + }, + "policyInEffectLowercase": { + "message": "Berisi satu atau lebih karakter huruf kecil" + }, + "policyInEffectNumbers": { + "message": "Berisi satu atau lebih angka" + }, + "policyInEffectSpecial": { + "message": "Berisi satu atau lebih karakter khusus berikut $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Kata sandi utama Anda yang baru tidak memenuhi persyaratan kebijakan." + }, + "acceptPolicies": { + "message": "Dengan mencentang kotak ini, anda menyetujui yang berikut:" + }, + "acceptPoliciesError": { + "message": "Persyaratan Layanan dan Kebijakan Privasi belum diakui." + }, + "enableBrowserIntegration": { + "message": "Aktifkan integrasi browser" + }, + "enableBrowserIntegrationDesc": { + "message": "Integrasi browser digunakan untuk biometrik di browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Integrasi browser tidak didukung" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Sayangnya integrasi browser hanya didukung di versi Mac App Store untuk saat ini." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Integrasi browser tidak didukung" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Sayangnya integrasi browser saat ini tidak didukung di versi Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Mewajibkan verifikasi untuk integrasi browser" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Aktifkan lapisan keamanan tambahan dengan meminta validasi frase sidik jari saat membuat tautan antara desktop dan browser Anda. Saat diaktifkan, ini membutuhkan intervensi pengguna dan verifikasi setiap kali koneksi dibuat." + }, + "approve": { + "message": "Menyetujui" + }, + "verifyBrowserTitle": { + "message": "Verifikasi koneksi browser" + }, + "verifyBrowserDesc": { + "message": "Harap pastikan sidik jari yang ditampilkan identik dengan sidik jari yang ditunjukkan di ekstensi browser." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrik tidak diaktifkan" + }, + "biometricsNotEnabledDesc": { + "message": "Biometrik browser mengharuskan biometrik desktop diaktifkan di pengaturan terlebih dahulu." + }, + "personalOwnershipSubmitError": { + "message": "Karena Kebijakan Perusahaan, Anda dilarang menyimpan item ke lemari besi pribadi Anda. Ubah opsi Kepemilikan ke organisasi dan pilih dari Koleksi yang tersedia." + }, + "hintEqualsPassword": { + "message": "Petunjuk kata sandi Anda tidak boleh sama dengan kata sandi Anda." + }, + "personalOwnershipPolicyInEffect": { + "message": "Kebijakan organisasi memengaruhi opsi kepemilikan Anda." + }, + "allSends": { + "message": "Semua Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Berkas" + }, + "sendTypeText": { + "message": "Teks" + }, + "searchSends": { + "message": "Pencarian Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Brankas Saya" + }, + "text": { + "message": "Teks" + }, + "deletionDate": { + "message": "Tanggal Penghapusan" + }, + "deletionDateDesc": { + "message": "Send akan dihapus secara permanen pada tanggal dan waktu yang ditentukan.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Tanggal habis tempo" + }, + "expirationDateDesc": { + "message": "Jika disetel, akses ke Send ini akan berakhir pada tanggal dan waktu yang ditentukan.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Hitungan Akses Maksimum" + }, + "maxAccessCountDesc": { + "message": "Jika disetel, pengguna tidak dapat lagi mengakses Send ini setelah jumlah akses maksimum tercapai.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Hitungan Akses Saat Ini" + }, + "disableSend": { + "message": "Nonaktifkan Send ini sehingga tidak ada yang dapat mengaksesnya.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Secara opsional, minta kata sandi bagi pengguna untuk mengakses Send ini.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Catatan pribadi tentang Send ini.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Tautan Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Tautan Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Saat mengakses Send, sembunyikan teks secara default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send Dibuat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send diedit", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send Dihapus", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Kata Sandi baru" + }, + "whatTypeOfSend": { + "message": "Jenis Send apakah ini?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Buat Send Baru", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teks yang ingin Anda kirim." + }, + "sendFileDesc": { + "message": "File yang ingin Anda kirim." + }, + "days": { + "message": "$DAYS$ hari", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 hari" + }, + "custom": { + "message": "Kustom" + }, + "deleteSendConfirmation": { + "message": "Anda yakin ingin menghapus Send ini?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Salin Send tautan ke papan klip", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Salin tautan untuk membagikan Send ke papan klip saya ini setelah disimpan." + }, + "sendDisabled": { + "message": "Send Dinonaktifkan", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Karena kebijakan perusahaan, Anda hanya dapat menghapus Send yang sudah ada.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Salin tautan" + }, + "disabled": { + "message": "Dinonaktifkan" + }, + "maxAccessCountReached": { + "message": "Jumlah akses maksimum tercapai" + }, + "expired": { + "message": "Kedaluwarsa" + }, + "pendingDeletion": { + "message": "Penghapusan menunggu keputusan" + }, + "webAuthnAuthenticate": { + "message": "Autentikasi dengan WebAuthn" + }, + "hideEmail": { + "message": "Sembunyikan alamat surel saya dari penerima." + }, + "sendOptionsPolicyInEffect": { + "message": "Satu atau lebih kebijakan organisasi mempengaruhi pengaturan feature Send anda." + }, + "emailVerificationRequired": { + "message": "Verifikasi Email Diperlukan" + }, + "emailVerificationRequiredDesc": { + "message": "Anda harus mengkonfirmasi email anda untuk menggunakan fitur ini." + }, + "passwordPrompt": { + "message": "Master password ditanyakan kembali" + }, + "passwordConfirmation": { + "message": "Konfirmasi sandi utama" + }, + "passwordConfirmationDesc": { + "message": "Aksi ini terproteksi. Untuk melanjutkan, masukkan kembali sandi utama Anda untuk verifikasi identitas." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/it/messages.json b/apps/desktop/src/locales/it/messages.json new file mode 100644 index 0000000000..dd8eef1102 --- /dev/null +++ b/apps/desktop/src/locales/it/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtri" + }, + "allItems": { + "message": "Tutti gli elementi" + }, + "favorites": { + "message": "Preferiti" + }, + "types": { + "message": "Tipi" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Carta" + }, + "typeIdentity": { + "message": "Identità" + }, + "typeSecureNote": { + "message": "Nota sicura" + }, + "folders": { + "message": "Cartelle" + }, + "collections": { + "message": "Raccolte" + }, + "searchVault": { + "message": "Cerca nella cassaforte" + }, + "addItem": { + "message": "Aggiungi elemento" + }, + "shared": { + "message": "Condiviso" + }, + "share": { + "message": "Condividi" + }, + "moveToOrganization": { + "message": "Sposta in organizzazione" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ spostato in $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Scegli un'organizzazione in cui desideri spostare questo elemento. Spostare in un'organizzazione trasferisce la proprietà dell'elemento all'organizzazione. Non sarai più il proprietario diretto di questo elemento una volta spostato." + }, + "attachments": { + "message": "Allegati" + }, + "viewItem": { + "message": "Mostra elemento" + }, + "name": { + "message": "Nome" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nuovo URI" + }, + "username": { + "message": "Nome utente" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Frase segreta" + }, + "editItem": { + "message": "Modifica elemento" + }, + "emailAddress": { + "message": "Indirizzo email" + }, + "verificationCodeTotp": { + "message": "Codice di verifica (TOTP)" + }, + "website": { + "message": "Sito web" + }, + "notes": { + "message": "Note" + }, + "customFields": { + "message": "Campi personalizzati" + }, + "launch": { + "message": "Avvia" + }, + "copyValue": { + "message": "Copia valore", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Riduci a icona durante la copia negli appunti" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Riduci a icona durante la copia dei dati dell'elemento negli appunti." + }, + "toggleVisibility": { + "message": "Mostra/Nascondi" + }, + "toggleCollapse": { + "message": "Comprimi/espandi", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Titolare della carta" + }, + "number": { + "message": "Numero" + }, + "brand": { + "message": "Marca" + }, + "expiration": { + "message": "Scadenza" + }, + "securityCode": { + "message": "Codice di sicurezza" + }, + "identityName": { + "message": "Nome dell'identità" + }, + "company": { + "message": "Azienda" + }, + "ssn": { + "message": "Codice fiscale/Previdenza sociale" + }, + "passportNumber": { + "message": "Numero del passaporto" + }, + "licenseNumber": { + "message": "Numero patente" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telefono" + }, + "address": { + "message": "Indirizzo" + }, + "premiumRequired": { + "message": "Abbonamento Premium Richiesto" + }, + "premiumRequiredDesc": { + "message": "Un abbonamento premium è richiesto per utilizzare questa funzionalità." + }, + "errorOccurred": { + "message": "Si è verificato un errore." + }, + "error": { + "message": "Errore" + }, + "january": { + "message": "Gennaio" + }, + "february": { + "message": "Febbraio" + }, + "march": { + "message": "Marzo" + }, + "april": { + "message": "Aprile" + }, + "may": { + "message": "Maggio" + }, + "june": { + "message": "Giugno" + }, + "july": { + "message": "Luglio" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Settembre" + }, + "october": { + "message": "Ottobre" + }, + "november": { + "message": "Novembre" + }, + "december": { + "message": "Dicembre" + }, + "ex": { + "message": "es.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titolo" + }, + "mr": { + "message": "Sig" + }, + "mrs": { + "message": "Sig.ra" + }, + "ms": { + "message": "Sig.na" + }, + "dr": { + "message": "Dott." + }, + "expirationMonth": { + "message": "Mese di scadenza" + }, + "expirationYear": { + "message": "Anno di scadenza" + }, + "select": { + "message": "Seleziona" + }, + "other": { + "message": "Altro" + }, + "generatePassword": { + "message": "Genera password" + }, + "type": { + "message": "Tipo" + }, + "firstName": { + "message": "Nome" + }, + "middleName": { + "message": "Secondo nome" + }, + "lastName": { + "message": "Cognome" + }, + "fullName": { + "message": "Nome completo" + }, + "address1": { + "message": "Indirizzo 1" + }, + "address2": { + "message": "Indirizzo 2" + }, + "address3": { + "message": "Indirizzo 3" + }, + "cityTown": { + "message": "Città / Comune" + }, + "stateProvince": { + "message": "Stato / Provincia" + }, + "zipPostalCode": { + "message": "CAP" + }, + "country": { + "message": "Nazione" + }, + "save": { + "message": "Salva" + }, + "cancel": { + "message": "Annulla" + }, + "delete": { + "message": "Elimina" + }, + "favorite": { + "message": "Preferito" + }, + "edit": { + "message": "Modifica" + }, + "authenticatorKeyTotp": { + "message": "Chiave di autenticazione (TOTP)" + }, + "folder": { + "message": "Cartella" + }, + "newCustomField": { + "message": "Nuovo campo personalizzato" + }, + "value": { + "message": "Valore" + }, + "dragToSort": { + "message": "Trascina per ordinare" + }, + "cfTypeText": { + "message": "Testo" + }, + "cfTypeHidden": { + "message": "Nascosto" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "cfTypeLinked": { + "message": "Collegato", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Valore collegato", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Rimuovi" + }, + "nameRequired": { + "message": "Il nome è obbligatorio." + }, + "addedItem": { + "message": "Elemento aggiunto" + }, + "editedItem": { + "message": "Elemento modificato" + }, + "deleteItem": { + "message": "Elimina elemento" + }, + "deleteFolder": { + "message": "Elimina cartella" + }, + "deleteAttachment": { + "message": "Elimina allegato" + }, + "deleteItemConfirmation": { + "message": "Sei sicuro di voler cestinare questo elemento?" + }, + "deletedItem": { + "message": "Elemento cestinato" + }, + "overwritePasswordConfirmation": { + "message": "Sei sicuro di voler sovrascrivere la password corrente?" + }, + "overwriteUsername": { + "message": "Sovrascrivi nome utente" + }, + "overwriteUsernameConfirmation": { + "message": "Sei sicuro di voler sovrascrivere il nome utente attuale?" + }, + "noneFolder": { + "message": "Nessuna cartella", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Aggiungi cartella" + }, + "editFolder": { + "message": "Modifica cartella" + }, + "regeneratePassword": { + "message": "Rigenera password" + }, + "copyPassword": { + "message": "Copia password" + }, + "copyUri": { + "message": "Copia URI" + }, + "copyVerificationCodeTotp": { + "message": "Copia codice di verifica (TOTP)" + }, + "length": { + "message": "Lunghezza" + }, + "numWords": { + "message": "Numero di parole" + }, + "wordSeparator": { + "message": "Separatore parole" + }, + "capitalize": { + "message": "Rendi maiuscolo", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Includi numero" + }, + "close": { + "message": "Chiudi" + }, + "minNumbers": { + "message": "Minimo di numeri" + }, + "minSpecial": { + "message": "Minimo di speciali", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Evita caratteri ambigui" + }, + "searchCollection": { + "message": "Cerca nella raccolta" + }, + "searchFolder": { + "message": "Cerca nella cartella" + }, + "searchFavorites": { + "message": "Cerca tra i preferiti" + }, + "searchType": { + "message": "Cerca tipo", + "description": "Search item type" + }, + "newAttachment": { + "message": "Aggiungi nuovo allegato" + }, + "deletedAttachment": { + "message": "Allegato eliminato" + }, + "deleteAttachmentConfirmation": { + "message": "Sei sicuro di voler eliminare questo allegato?" + }, + "attachmentSaved": { + "message": "L'allegato è stato salvato." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Seleziona un file." + }, + "maxFileSize": { + "message": "La dimensione massima del file è 500 MB." + }, + "updateKey": { + "message": "Non puoi utilizzare questa funzione finché non aggiorni la tua chiave." + }, + "editedFolder": { + "message": "Cartella modificata" + }, + "addedFolder": { + "message": "Cartella aggiunta" + }, + "deleteFolderConfirmation": { + "message": "Sei sicuro di voler eliminare questa cartella?" + }, + "deletedFolder": { + "message": "Cartella eliminata" + }, + "loginOrCreateNewAccount": { + "message": "Accedi o crea un nuovo account per accedere alla tua cassaforte." + }, + "createAccount": { + "message": "Crea account" + }, + "logIn": { + "message": "Accedi" + }, + "submit": { + "message": "Invia" + }, + "masterPass": { + "message": "Password principale" + }, + "masterPassDesc": { + "message": "La password principale è quella che usi per accedere alla cassaforte. È molto importante che tu non la dimentichi. Non c'è alcun modo di recuperarla nel caso la dimenticassi." + }, + "masterPassHintDesc": { + "message": "Un suggerimento può aiutarti a ricordare la tua password principale nel caso in cui la dimentichi." + }, + "reTypeMasterPass": { + "message": "Digita nuovamente la password principale" + }, + "masterPassHint": { + "message": "Suggerimento password principale (facoltativo)" + }, + "settings": { + "message": "Impostazioni" + }, + "passwordHint": { + "message": "Suggerimento password" + }, + "enterEmailToGetHint": { + "message": "Inserisci l'indirizzo email del tuo account per ricevere il suggerimento della password principale." + }, + "getMasterPasswordHint": { + "message": "Ottieni il suggerimento per la password principale" + }, + "emailRequired": { + "message": "L'indirizzo email è obbligatorio." + }, + "invalidEmail": { + "message": "L'indirizzo email non è valido." + }, + "masterPassRequired": { + "message": "La password principale è obbligatoria." + }, + "masterPassLength": { + "message": "La password principale deve avere almeno 8 caratteri." + }, + "masterPassDoesntMatch": { + "message": "La conferma della password principale non corrisponde." + }, + "newAccountCreated": { + "message": "Il tuo account è stato creato! Ora puoi effettuare l'accesso." + }, + "masterPassSent": { + "message": "Ti abbiamo inviato un'email con il tuo suggerimento per la password principale." + }, + "unexpectedError": { + "message": "Si è verificato un errore imprevisto." + }, + "itemInformation": { + "message": "Informazioni sull'elemento" + }, + "noItemsInList": { + "message": "Non ci sono elementi da elencare." + }, + "sendVerificationCode": { + "message": "Invia un codice di verifica alla tua email" + }, + "sendCode": { + "message": "Invia codice" + }, + "codeSent": { + "message": "Codice inviato" + }, + "verificationCode": { + "message": "Codice di verifica" + }, + "confirmIdentity": { + "message": "Conferma la tua identità per continuare." + }, + "verificationCodeRequired": { + "message": "Il codice di verifica è obbligatorio." + }, + "invalidVerificationCode": { + "message": "Codice di verifica non valido" + }, + "continue": { + "message": "Continua" + }, + "enterVerificationCodeApp": { + "message": "Inserisci il codice di verifica a 6 cifre dalla tua applicazione di autenticazione." + }, + "enterVerificationCodeEmail": { + "message": "Inserisci il codice di verifica a 6 cifre che è stato inviato all'indirizzo $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "L'email di verifica è stata inviata all'indirizzo $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Ricordami" + }, + "sendVerificationCodeEmailAgain": { + "message": "Invia nuovamente l'email con il codice di verifica" + }, + "useAnotherTwoStepMethod": { + "message": "Usa un altro metodo di verifica in due passaggi" + }, + "insertYubiKey": { + "message": "Inserisci la tua YubiKey nella porta USB del computer e poi premi il suo pulsante." + }, + "insertU2f": { + "message": "Inserisci la tua chiave di sicurezza nella porta USB del tuo computer. Se dispone di un pulsante, premilo." + }, + "recoveryCodeDesc": { + "message": "Hai perso l'accesso a tutti i tuoi metodi di verifica in due passaggi? Usa il tuo codice di recupero per disattivare tutti i metodi di verifica in due passaggi sul tuo account." + }, + "recoveryCodeTitle": { + "message": "Codice di recupero" + }, + "authenticatorAppTitle": { + "message": "Applicazione di autenticazione" + }, + "authenticatorAppDesc": { + "message": "Usa un'applicazione di autenticazione (come Authy o Google Authenticator) per generare codici di verifica a tempo.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Chiave di sicurezza YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Usa YubiKey per accedere al tuo account. Compatibile con YubiKey 4, 4 Nano, 4C, e dispositivi NEO." + }, + "duoDesc": { + "message": "Verifica con Duo Security usando l'applicazione Duo Mobile, SMS, chiamata telefonica, o chiave di sicurezza U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifica con Duo Security per la tua azienda usando l'applicazione Duo Mobile, SMS, chiamata telefonica, o chiave di sicurezza U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Usa qualsiasi chiave di sicurezza abilitata WebAuthn per accedere al tuo account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "I codici di verifica ti saranno inviati per email." + }, + "loginUnavailable": { + "message": "Accesso non disponibile" + }, + "noTwoStepProviders": { + "message": "Questo account ha la verifica in due passaggi abilitata, ma nessuno dei provider configurati è supportato da questo browser." + }, + "noTwoStepProviders2": { + "message": "Aggiungi altri metodi che sono supportati meglio su tutti i dispositivi (ad esempio, un'applicazione di autenticazione)." + }, + "twoStepOptions": { + "message": "Opzioni di accesso in due passaggi" + }, + "selfHostedEnvironment": { + "message": "Ambiente self-hosted" + }, + "selfHostedEnvironmentFooter": { + "message": "Specifica l'URL principale della tua installazione Bitwarden locale." + }, + "customEnvironment": { + "message": "Ambiente personalizzato" + }, + "customEnvironmentFooter": { + "message": "Per utenti avanzati. Puoi specificare l'URL principale di ogni servizio indipendentemente." + }, + "baseUrl": { + "message": "URL del server" + }, + "apiUrl": { + "message": "URL del server API" + }, + "webVaultUrl": { + "message": "URL della cassaforte web" + }, + "identityUrl": { + "message": "URL del server di identità" + }, + "notificationsUrl": { + "message": "URL del server delle notifiche" + }, + "iconsUrl": { + "message": "URL del server di icone" + }, + "environmentSaved": { + "message": "Gli URL dell'ambiente sono stati salvati." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Sì" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Sovrascrivi password" + }, + "learnMore": { + "message": "Per saperne di più" + }, + "featureUnavailable": { + "message": "Funzione non disponibile" + }, + "loggedOut": { + "message": "Disconnesso" + }, + "loginExpired": { + "message": "La tua sessione è scaduta." + }, + "logOutConfirmation": { + "message": "Sei sicuro di volerti disconnettere?" + }, + "logOut": { + "message": "Disconnetti" + }, + "addNewLogin": { + "message": "Aggiungi nuovo accesso" + }, + "addNewItem": { + "message": "Aggiungi nuovo elemento" + }, + "addNewFolder": { + "message": "Aggiungi nuova cartella" + }, + "view": { + "message": "Visualizza" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Caricamento in corso..." + }, + "lockVault": { + "message": "Blocca la cassaforte" + }, + "passwordGenerator": { + "message": "Generatore di password" + }, + "contactUs": { + "message": "Contattaci" + }, + "getHelp": { + "message": "Ottieni aiuto" + }, + "fileBugReport": { + "message": "Segnala un bug" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Seguici" + }, + "syncVault": { + "message": "Sincronizza la cassaforte" + }, + "changeMasterPass": { + "message": "Cambia password principale" + }, + "changeMasterPasswordConfirmation": { + "message": "Puoi cambiare la tua password principale su bitwarden.com. Vuoi visitare ora il sito?" + }, + "fingerprintPhrase": { + "message": "Frase impronta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Frase impronta dell'account", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Vai alla cassaforte web" + }, + "getMobileApp": { + "message": "Scarica l'applicazione mobile" + }, + "getBrowserExtension": { + "message": "Scarica l'estensione del browser" + }, + "syncingComplete": { + "message": "Sincronizzazione completata" + }, + "syncingFailed": { + "message": "Sincronizzazione non riuscita" + }, + "yourVaultIsLocked": { + "message": "La tua cassaforte è bloccata. Inserisci la tua password principale per continuare." + }, + "unlock": { + "message": "Sblocca" + }, + "loggedInAsOn": { + "message": "Accesso effettuato come $EMAIL$ su $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Password principale errata" + }, + "twoStepLoginConfirmation": { + "message": "L'autenticazione in due passaggi rende il tuo account più sicuro richiedendo di verificare l'accesso con un altro dispositivo come una chiave di sicurezza, applicazione di autenticazione, SMS, telefonata o email. Può essere abilitata su bitwarden.com. Vuoi visitare il sito ora?" + }, + "twoStepLogin": { + "message": "Verifica in due passaggi" + }, + "vaultTimeout": { + "message": "Timeout cassaforte" + }, + "vaultTimeoutDesc": { + "message": "Scegli quando la tua cassaforte andrà in timeout ed esegui l'azione selezionata." + }, + "immediately": { + "message": "Immediatamente" + }, + "tenSeconds": { + "message": "10 secondi" + }, + "twentySeconds": { + "message": "20 secondi" + }, + "thirtySeconds": { + "message": "30 secondi" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minuti" + }, + "fiveMinutes": { + "message": "5 minuti" + }, + "fifteenMinutes": { + "message": "15 minuti" + }, + "thirtyMinutes": { + "message": "30 minuti" + }, + "oneHour": { + "message": "1 ora" + }, + "fourHours": { + "message": "4 ore" + }, + "onIdle": { + "message": "Quando il sistema è inattivo" + }, + "onSleep": { + "message": "Quando il sistema è sospeso" + }, + "onLocked": { + "message": "Quando il sistema è bloccato" + }, + "onRestart": { + "message": "Al riavvio" + }, + "never": { + "message": "Mai" + }, + "security": { + "message": "Sicurezza" + }, + "clearClipboard": { + "message": "Cancella appunti", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Cancella automaticamente i valori copiati dagli appunti.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disabilita icone dei siti web" + }, + "disableFaviconDesc": { + "message": "Le icone dei siti web forniscono un'immagine riconoscibile accanto ad ogni elemento di login della cassaforte." + }, + "enableMinToTray": { + "message": "Riduci nell'area di notifica" + }, + "enableMinToTrayDesc": { + "message": "Riduci nell'area di notifica invece di ridurre a icona." + }, + "enableMinToMenuBar": { + "message": "Riduci nella barra dei menu" + }, + "enableMinToMenuBarDesc": { + "message": "Mostra un'icona nella barra dei menu quando si minimizza la finestra." + }, + "enableCloseToTray": { + "message": "Chiudi nell'area di notifica" + }, + "enableCloseToTrayDesc": { + "message": "Mostra un'icona nell'area di notifica quando si chiude la finestra." + }, + "enableCloseToMenuBar": { + "message": "Chiudi nella barra dei menu" + }, + "enableCloseToMenuBarDesc": { + "message": "Quando chiudi la finestra, mostra invece un'icona nella barra dei menu." + }, + "enableTray": { + "message": "Icona nell'area di notifica" + }, + "enableTrayDesc": { + "message": "Mostra sempre un'icona nell'area di notifica." + }, + "startToTray": { + "message": "Avvio dall'area di notifica" + }, + "startToTrayDesc": { + "message": "Mostra solo l'icona nell'area di notifica all'avvio dell'applicazione." + }, + "startToMenuBar": { + "message": "Avvia dalla barra dei menu" + }, + "startToMenuBarDesc": { + "message": "Mostra solo l'icona nella barra dei menu all'avvio dell'applicazione." + }, + "openAtLogin": { + "message": "Avvia automaticamente all'accesso" + }, + "openAtLoginDesc": { + "message": "Avvia automaticamente Bitwarden Desktop all'accesso." + }, + "alwaysShowDock": { + "message": "Mostra sempre nel Dock" + }, + "alwaysShowDockDesc": { + "message": "Mostra l'icona di Bitwarden nel Dock anche quando minimizzato nella barra dei menu." + }, + "confirmTrayTitle": { + "message": "Conferma disattivazione icona del vassoio" + }, + "confirmTrayDesc": { + "message": "La disabilitazione di questa impostazione disabiliterà anche tutte le altre impostazioni del vassoio." + }, + "language": { + "message": "Lingua" + }, + "languageDesc": { + "message": "Cambia la lingua dell'applicazione. Riavvio necessario." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Cambia lo schema di colori dell'applicazione." + }, + "dark": { + "message": "Scuro", + "description": "Dark color" + }, + "light": { + "message": "Chiaro", + "description": "Light color" + }, + "copy": { + "message": "Copia", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Controlla aggiornamenti" + }, + "version": { + "message": "Versione $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Riavvia per aggiornare" + }, + "restartToUpdateDesc": { + "message": "Versione $VERSION_NUM$ è pronto per l'installazione. È necessario riavviare Bitwarden per completare l'installazione. Desideri riavviare e aggiornare ora?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Aggiornamento disponibile" + }, + "updateAvailableDesc": { + "message": "Un aggiornamento è stato trovato. Desideri scaricarlo adesso?" + }, + "restart": { + "message": "Riavvia" + }, + "later": { + "message": "Più tardi" + }, + "noUpdatesAvailable": { + "message": "Non sono attualmente disponibili aggiornamenti. Stai utilizzando la versione più recente." + }, + "updateError": { + "message": "Errore di aggiornamento" + }, + "unknown": { + "message": "Sconosciuto" + }, + "copyUsername": { + "message": "Copia nome utente" + }, + "copyNumber": { + "message": "Copia numero", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copia il codice di sicurezza", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Abbonamento Premium" + }, + "premiumManage": { + "message": "Gestisci abbonamento" + }, + "premiumManageAlert": { + "message": "Puoi gestire il tuo abbonamento premium online su bitwarden.com. Vuoi visitare ora il sito?" + }, + "premiumRefresh": { + "message": "Aggiorna abbonamento" + }, + "premiumNotCurrentMember": { + "message": "Al momento non sei un membro premium." + }, + "premiumSignUpAndGet": { + "message": "Iscriviti a un abbonamento premium e ottieni:" + }, + "premiumSignUpStorage": { + "message": "1 GB di spazio di archiviazione cifrato per gli allegati." + }, + "premiumSignUpTwoStep": { + "message": "Opzioni di verifica in due passaggi addizionali come YubiKey, FIDO U2F, e Duo." + }, + "premiumSignUpReports": { + "message": "Sicurezza delle password, integrità dell'account e resoconti sulla violazione dei dati per mantenere sicura la tua cassaforte." + }, + "premiumSignUpTotp": { + "message": "Generatore di codice di verifica TOTP (2FA) per i login nella tua cassaforte." + }, + "premiumSignUpSupport": { + "message": "Supporto clienti prioritario." + }, + "premiumSignUpFuture": { + "message": "Tutte le funzioni premium future. Nuove in arrivo!" + }, + "premiumPurchase": { + "message": "Acquista Premium" + }, + "premiumPurchaseAlert": { + "message": "Puoi acquistare il tuo abbonamento premium online su bitwarden.com. Vuoi visitare ora il sito?" + }, + "premiumCurrentMember": { + "message": "Sei un membro premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Grazie per il tuo supporto a Bitwarden." + }, + "premiumPrice": { + "message": "Il tutto per solo $PRICE$ all'anno!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Aggiornamento completato" + }, + "passwordHistory": { + "message": "Cronologia delle password" + }, + "clear": { + "message": "Cancella", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Non ci sono password da elencare." + }, + "undo": { + "message": "Annulla" + }, + "redo": { + "message": "Rifai" + }, + "cut": { + "message": "Taglia", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Incolla", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Seleziona tutto" + }, + "zoomIn": { + "message": "Ingrandisci" + }, + "zoomOut": { + "message": "Rimpicciolisci" + }, + "resetZoom": { + "message": "Ripristina zoom" + }, + "toggleFullScreen": { + "message": "Attiva/disattiva schermo intero" + }, + "reload": { + "message": "Ricarica" + }, + "toggleDevTools": { + "message": "Attiva/disattiva strumenti di sviluppo" + }, + "minimize": { + "message": "Minimizza", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Porta tutto in primo piano", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Informazioni su Bitwarden" + }, + "services": { + "message": "Servizi" + }, + "hideBitwarden": { + "message": "Nascondi Bitwarden" + }, + "hideOthers": { + "message": "Nascondi altri" + }, + "showAll": { + "message": "Mostra tutto" + }, + "quitBitwarden": { + "message": "Esci da Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copiata", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Aiuto" + }, + "window": { + "message": "Finestra" + }, + "checkPassword": { + "message": "Verifica se la password è stata esposta." + }, + "passwordExposed": { + "message": "Questa password è presente $VALUE$ volta/e in database di violazioni. Dovresti cambiarla.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Questa password non è stata trovata in dati violati noti. Dovrebbe essere sicura da usare." + }, + "baseDomain": { + "message": "Dominio di base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nome dominio", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Esatto" + }, + "startsWith": { + "message": "Inizia con" + }, + "regEx": { + "message": "Espressione regolare", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Rilevamento di corrispondenza", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Rilevamento di corrispondenza predefinito", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Attiva/Disattiva opzioni" + }, + "organization": { + "message": "Organizzazione", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Predefinito" + }, + "exit": { + "message": "Esci" + }, + "showHide": { + "message": "Mostra / Nascondi", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Nascondi nell'area di notifica" + }, + "alwaysOnTop": { + "message": "Sempre in primo piano", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Aggiornato", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password aggiornata", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Esporta cassaforte" + }, + "fileFormat": { + "message": "Formato file" + }, + "warning": { + "message": "ATTENZIONE", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Conferma esportazione della cassaforte" + }, + "exportWarningDesc": { + "message": "Questa esportazione contiene i dati della cassaforte in un formato non cifrato. Non archiviare o inviare il file esportato su canali non protetti (come la posta elettronica). Eliminalo immediatamente dopo aver finito di usarlo." + }, + "encExportKeyWarningDesc": { + "message": "Questa esportazione cifra i tuoi dati utilizzando la chiave di cifratura del tuo account. Se cambi la chiave di cifratura del tuo account, non sarai più in grado di decifrare il file esportato e sarà necessario eseguire una nuova esportazione." + }, + "encExportAccountWarningDesc": { + "message": "Le chiavi di cifratura dell'account sono uniche per ogni account utente Bitwarden, quindi non è possibile importare un'esportazione cifrata in un account diverso." + }, + "noOrganizationsList": { + "message": "Non appartieni ad alcuna organizzazione. Le organizzazioni ti consentono di condividere oggetti in modo sicuro con altri utenti." + }, + "noCollectionsInList": { + "message": "Nessuna raccolta da elencare." + }, + "ownership": { + "message": "Proprietà" + }, + "whoOwnsThisItem": { + "message": "A chi appartiene questo elemento?" + }, + "strong": { + "message": "Robusta", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Buona", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Debole", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Password principale debole" + }, + "weakMasterPasswordDesc": { + "message": "La password principale che hai scelto è debole. È necessario utilizzare una password principale forte (o una frase segreta) per proteggere adeguatamente il tuo account Bitwarden. Sei sicuro di voler utilizzare questa password principale?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Sblocca con PIN" + }, + "setYourPinCode": { + "message": "Imposta il tuo codice PIN per sbloccare Bitwarden. Le impostazioni del PIN saranno reimpostate se ti disconnetti dall'applicazione." + }, + "pinRequired": { + "message": "È richiesto il PIN." + }, + "invalidPin": { + "message": "Codice PIN non valido." + }, + "unlockWithWindowsHello": { + "message": "Sblocca con Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verifica per Bitwarden." + }, + "unlockWithTouchId": { + "message": "Sblocca con Touch ID" + }, + "touchIdConsentMessage": { + "message": "sblocca la cassaforte" + }, + "noAutoPromptWindowsHello": { + "message": "Non richiedere Windows Hello all'avvio." + }, + "noAutoPromptTouchId": { + "message": "Non richiedere Touch ID all'avvio." + }, + "lockWithMasterPassOnRestart": { + "message": "Blocca con la password principale al riavvio" + }, + "preferences": { + "message": "Preferenze" + }, + "enableMenuBar": { + "message": "Abilita icona barra dei menu" + }, + "enableMenuBarDesc": { + "message": "Mostra sempre un'icona nella barra dei menu." + }, + "hideToMenuBar": { + "message": "Nascondi nella barra dei menu" + }, + "selectOneCollection": { + "message": "Devi selezionare almeno una raccolta." + }, + "premiumUpdated": { + "message": "Hai effettuato l'aggiornamento a premium." + }, + "restore": { + "message": "Ripristina" + }, + "premiumManageAlertAppStore": { + "message": "Puoi gestire il tuo abbonamento dall'App Store. Vuoi visitare l'App Store adesso?" + }, + "legal": { + "message": "Informazioni legali", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Termini del servizio" + }, + "privacyPolicy": { + "message": "Informativa sulla privacy" + }, + "unsavedChangesConfirmation": { + "message": "Sei sicuro di voler uscire? Se esci adesso, le informazioni attuali non saranno salvate." + }, + "unsavedChangesTitle": { + "message": "Modifiche non salvate" + }, + "clone": { + "message": "Clona" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una o più policy dell'organizzazione controllano le impostazioni del tuo generatore." + }, + "vaultTimeoutAction": { + "message": "Azione timeout cassaforte" + }, + "vaultTimeoutActionLockDesc": { + "message": "Una cassaforte bloccata richiede l'inserimento della password principale per accedere nuovamente." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "La disconnessione dalla cassaforte richiede l'inserimento della password principale per accedere nuovamente." + }, + "lock": { + "message": "Blocca", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Cestino", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Cerca nel cestino" + }, + "permanentlyDeleteItem": { + "message": "Elimina definitivamente l'elemento" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Sei sicuro di voler eliminare definitivamente questo elemento?" + }, + "permanentlyDeletedItem": { + "message": "Elemento eliminato definitivamente" + }, + "restoreItem": { + "message": "Ripristina elemento" + }, + "restoreItemConfirmation": { + "message": "Sei sicuro di voler ripristinare questo elemento?" + }, + "restoredItem": { + "message": "Elemento ripristinato" + }, + "permanentlyDelete": { + "message": "Elimina definitivamente" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "La disconnessione rimuove tutti gli accessi alla tua cassaforte e richiede l'autenticazione in linea dopo il periodo di timeout. Sei sicuro di voler utilizzare questa impostazione?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Conferma azione di timeout" + }, + "enterpriseSingleSignOn": { + "message": "Single Sign-On aziendale" + }, + "setMasterPassword": { + "message": "Imposta la password principale" + }, + "ssoCompleteRegistration": { + "message": "Per completare l'accesso con SSO, imposta una password principale per accedere e proteggere la cassaforte." + }, + "newMasterPass": { + "message": "Nuova password principale" + }, + "confirmNewMasterPass": { + "message": "Conferma nuova password principale" + }, + "masterPasswordPolicyInEffect": { + "message": "La password principale deve avere i seguenti requisiti, stabiliti da una o più regole dell'organizzazione:" + }, + "policyInEffectMinComplexity": { + "message": "Punteggio minimo di complessità $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Lunghezza minima $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contiene almeno un carattere maiuscolo" + }, + "policyInEffectLowercase": { + "message": "Contiene almeno un carattere minuscolo" + }, + "policyInEffectNumbers": { + "message": "Contiene almeno una cifra" + }, + "policyInEffectSpecial": { + "message": "Contiene almeno uno dei seguenti caratteri speciali $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "La tua nuova password principale non soddisfa i requisiti di sicurezza." + }, + "acceptPolicies": { + "message": "Marcando la casella accetti quanto segue:" + }, + "acceptPoliciesError": { + "message": "I termini di servizio e l'informativa sulla privacy non sono stati accettati." + }, + "enableBrowserIntegration": { + "message": "Abilita l'integrazione del browser" + }, + "enableBrowserIntegrationDesc": { + "message": "L'integrazione del browser è utilizzata per l'autenticazione biometrica." + }, + "browserIntegrationMasOnlyTitle": { + "message": "L'integrazione del browser non è supportata" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Purtroppo l'integrazione del browser è supportata solo nella versione disponibile nel Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "L'integrazione del browser non è supportata" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Purtroppo l'integrazione del browser non è attualmente supportata nella versione disponibile nel Microsoft Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Richiedi verifica per l'integrazione del browser" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Abilita un livello aggiuntivo di sicurezza richiedendo la conferma della frase impronta quando viene stabilito un collegamento fra il desktop e il browser. Quando abilitato, sarà necessario che l'utente esegua la verifica ad ogni nuova connessione." + }, + "approve": { + "message": "Approva" + }, + "verifyBrowserTitle": { + "message": "Verifica connessione browser" + }, + "verifyBrowserDesc": { + "message": "Assicurati che l'impronta digitale mostrata sia identica all'impronta digitale mostrata nell'estensione del browser." + }, + "biometricsNotEnabledTitle": { + "message": "Autenticazione biometrica non abilitata" + }, + "biometricsNotEnabledDesc": { + "message": "L'autenticazione biometrica del browser richiede che l'autenticazione biometrica del desktop sia stata abilitata prima nelle impostazioni." + }, + "personalOwnershipSubmitError": { + "message": "A causa di una policy aziendale, non è possibile salvare elementi nella tua cassaforte personale. Cambia l'opzione Proprietà in un'organizzazione e scegli tra le raccolte disponibili." + }, + "hintEqualsPassword": { + "message": "Il suggerimento della password non può essere uguale alla password." + }, + "personalOwnershipPolicyInEffect": { + "message": "Una policy dell'organizzazione controlla le opzioni di proprietà." + }, + "allSends": { + "message": "Tutti i Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Testo" + }, + "searchSends": { + "message": "Cerca Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Modifica Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "La mia cassaforte" + }, + "text": { + "message": "Testo" + }, + "deletionDate": { + "message": "Data di eliminazione" + }, + "deletionDateDesc": { + "message": "Il Send sarà definitivamente eliminato alla data e all'ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data di scadenza" + }, + "expirationDateDesc": { + "message": "Se impostata, l'accesso a questo Send scadrà alla data e all'ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Numero massimo di accessi" + }, + "maxAccessCountDesc": { + "message": "Se impostata, gli utenti non saranno più in grado di accedere a questo Send una volta raggiunto il numero massimo di accessi.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Conteggio accessi attuale" + }, + "disableSend": { + "message": "Disabilita il Send per renderlo inaccessibile.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Facoltativamente, richiedi una password agli utenti per accedere al Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Note private sul Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Collegamento del Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Collegamento del Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Quando accedi al Send, nascondi il testo in modo predefinito", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send creato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send modificato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send eliminato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nuova password" + }, + "whatTypeOfSend": { + "message": "Di quale tipo di Send si tratta?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Crea Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Il testo che desideri inviare." + }, + "sendFileDesc": { + "message": "Il file che desideri inviare." + }, + "days": { + "message": "$DAYS$ giorni", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 giorno" + }, + "custom": { + "message": "Personalizzato" + }, + "deleteSendConfirmation": { + "message": "Sei sicuro di voler eliminare questo Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copia collegamento Send negli appunti", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copia il collegamento per condividere questo Send nei miei appunti dopo aver salvato." + }, + "sendDisabled": { + "message": "Send disabilitato", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "A causa di una policy aziendale, è possibile eliminare solo un Send esistente.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copia collegamento" + }, + "disabled": { + "message": "Disabilitato" + }, + "maxAccessCountReached": { + "message": "Numero massimo di accessi raggiunto" + }, + "expired": { + "message": "Scaduto" + }, + "pendingDeletion": { + "message": "In attesa di eliminazione" + }, + "webAuthnAuthenticate": { + "message": "Autenticazione WebAuthn" + }, + "hideEmail": { + "message": "Nascondi il mio indirizzo email dai destinatari." + }, + "sendOptionsPolicyInEffect": { + "message": "Una o più policy dell'organizzazione influenzano le opzioni dei Send." + }, + "emailVerificationRequired": { + "message": "Verifica email necessaria" + }, + "emailVerificationRequiredDesc": { + "message": "Devi verificare la tua email per utilizzare questa funzionalità." + }, + "passwordPrompt": { + "message": "Nuova richiesta della password principale" + }, + "passwordConfirmation": { + "message": "Conferma della password principale" + }, + "passwordConfirmationDesc": { + "message": "Questa azione è protetta. Per continuare, inserisci nuovamente la tua password principale per verificare la tua identità." + }, + "updatedMasterPassword": { + "message": "Password principale aggiornata" + }, + "updateMasterPassword": { + "message": "Aggiorna password principale" + }, + "updateMasterPasswordWarning": { + "message": "La tua password principale è stata recentemente modificata da un amministratore nella tua organizzazione. Per accedere alla cassaforte, aggiorna ora la password. Procedendo sarai disconnesso dalla sessione attuale e ti sarà richiesto di effettuare nuovamente l'accesso. Le sessioni attive su altri dispositivi potrebbero continuare a rimanere attive per un massimo di un'ora." + }, + "hours": { + "message": "Ore" + }, + "minutes": { + "message": "Minuti" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Le policy dell'organizzazione stanno influenzando il timeout della tua cassaforte. Il tempo massimo consentito è di $HOURS$ ore e $MINUTES$ minuti", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Il timeout della tua cassaforte supera i limiti impostati dalla tua organizzazione." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Iscrizione automatica" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Questa organizzazione ha una policy aziendale che ti iscriverà automaticamente al ripristino della password. Ciò permetterà agli amministratori dell'organizzazione di cambiare la tua password principale." + }, + "vaultExportDisabled": { + "message": "Esportazione cassaforte disabilitata" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una o più policy dell'organizzazione ti impediscono di esportare la tua cassaforte personale." + }, + "addAccount": { + "message": "Aggiungi account" + }, + "removeMasterPassword": { + "message": "Rimuovi la password principale" + }, + "removedMasterPassword": { + "message": "Password principale rimossa." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ sta usando SSO con un server \"self-hosted\". Non è più richiesta una password principale per accedere per i membri di questa organizzazione.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Lascia l'organizzazione" + }, + "leaveOrganizationConfirmation": { + "message": "Sei sicuro di voler lasciare questa organizzazione?" + }, + "leftOrganization": { + "message": "Hai lasciato l'organizzazione." + }, + "ssoKeyConnectorUnavailable": { + "message": "Impossibile raggiungere il key connector, riprova più tardi." + }, + "lockAllVaults": { + "message": "Blocca tutte le casseforti" + }, + "accountLimitReached": { + "message": "Non possono essere accedere più di 5 account contemporaneamente." + }, + "accountPreferences": { + "message": "Preferenze" + }, + "appPreferences": { + "message": "Impostazioni applicazione (tutti gli account)" + }, + "accountSwitcherLimitReached": { + "message": "Limite di account raggiunto. Disconnetti un account per aggiungerne un altro." + }, + "settingsTitle": { + "message": "Impostazioni applicazione per $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Cambia account" + }, + "options": { + "message": "Opzioni" + }, + "sessionTimeout": { + "message": "La tua sessione è scaduta. Torna indietro e riprova ad accedere." + }, + "exportingPersonalVaultTitle": { + "message": "Esportazione cassaforte personale" + }, + "exportingPersonalVaultDescription": { + "message": "Saranno esportati solo gli oggetti della cassaforte personale associati a $EMAIL$. Gli oggetti della cassaforte dell'organizzazione non saranno inclusi.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generatore" + }, + "whatWouldYouLikeToGenerate": { + "message": "Cosa vorresti generare?" + }, + "passwordType": { + "message": "Tipo di password" + }, + "regenerateUsername": { + "message": "Rigenera nome utente" + }, + "generateUsername": { + "message": "Genera nome utente" + }, + "usernameType": { + "message": "Tipo di nome utente" + }, + "plusAddressedEmail": { + "message": "Indirizzo di posta alternativo" + }, + "plusAddressedEmailDesc": { + "message": "Usa le funzionalità di sub-indirizzamento del tuo fornitore di posta elettronica." + }, + "catchallEmail": { + "message": "Email catch-all" + }, + "catchallEmailDesc": { + "message": "Usa la casella di posta catch-all di dominio." + }, + "random": { + "message": "Casuale" + }, + "randomWord": { + "message": "Parola casuale" + }, + "websiteName": { + "message": "Nome sito web" + }, + "service": { + "message": "Servizio" + } +} diff --git a/apps/desktop/src/locales/ja/messages.json b/apps/desktop/src/locales/ja/messages.json new file mode 100644 index 0000000000..5db3bb7863 --- /dev/null +++ b/apps/desktop/src/locales/ja/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "フィルター" + }, + "allItems": { + "message": "全てのアイテム" + }, + "favorites": { + "message": "お気に入り" + }, + "types": { + "message": "タイプ" + }, + "typeLogin": { + "message": "ログイン" + }, + "typeCard": { + "message": "カード" + }, + "typeIdentity": { + "message": "ID" + }, + "typeSecureNote": { + "message": "セキュアメモ" + }, + "folders": { + "message": "フォルダー" + }, + "collections": { + "message": "コレクション" + }, + "searchVault": { + "message": "保管庫を検索" + }, + "addItem": { + "message": "アイテムの追加" + }, + "shared": { + "message": "共有" + }, + "share": { + "message": "共有" + }, + "moveToOrganization": { + "message": "組織に移動" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ を $ORGNAME$ に移動しました", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "このアイテムを移動する組織を選択してください。組織に移動すると、アイテムの所有権がその組織に移行します。 このアイテムが移動された後、あなたはこのアイテムの直接の所有者にはなりません。" + }, + "attachments": { + "message": "添付ファイル" + }, + "viewItem": { + "message": "アイテムの表示" + }, + "name": { + "message": "名前" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "新しい URI" + }, + "username": { + "message": "ユーザー名" + }, + "password": { + "message": "パスワード" + }, + "passphrase": { + "message": "パスフレーズ" + }, + "editItem": { + "message": "アイテムの編集" + }, + "emailAddress": { + "message": "メールアドレス" + }, + "verificationCodeTotp": { + "message": "認証コード (TOTP)" + }, + "website": { + "message": "ウェブサイト" + }, + "notes": { + "message": "メモ" + }, + "customFields": { + "message": "カスタムフィールド" + }, + "launch": { + "message": "開く" + }, + "copyValue": { + "message": "値のコピー", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "クリップボードへのコピー時に最小化する" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "アイテムデータをクリップボードにコピーしたときに最小化します。" + }, + "toggleVisibility": { + "message": "表示切り替え" + }, + "toggleCollapse": { + "message": "開く/閉じる", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "カードの名義人名" + }, + "number": { + "message": "番号" + }, + "brand": { + "message": "ブランド" + }, + "expiration": { + "message": "有効期限" + }, + "securityCode": { + "message": "セキュリティコード" + }, + "identityName": { + "message": "固有名" + }, + "company": { + "message": "会社名" + }, + "ssn": { + "message": "社会保障番号" + }, + "passportNumber": { + "message": "パスポート番号" + }, + "licenseNumber": { + "message": "免許証番号" + }, + "email": { + "message": "メールアドレス" + }, + "phone": { + "message": "電話番号" + }, + "address": { + "message": "住所" + }, + "premiumRequired": { + "message": "プレミアム会員専用" + }, + "premiumRequiredDesc": { + "message": "この機能はプレミアムメンバー専用です。" + }, + "errorOccurred": { + "message": "エラーが発生しました。" + }, + "error": { + "message": "エラー" + }, + "january": { + "message": "1月" + }, + "february": { + "message": "2月" + }, + "march": { + "message": "3月" + }, + "april": { + "message": "4月" + }, + "may": { + "message": "5月" + }, + "june": { + "message": "6月" + }, + "july": { + "message": "7月" + }, + "august": { + "message": "8月" + }, + "september": { + "message": "9月" + }, + "october": { + "message": "10月" + }, + "november": { + "message": "11月" + }, + "december": { + "message": "12月" + }, + "ex": { + "message": "例:", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "敬称" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "有効期限月" + }, + "expirationYear": { + "message": "有効期限年" + }, + "select": { + "message": "選択" + }, + "other": { + "message": "その他" + }, + "generatePassword": { + "message": "パスワードの自動生成" + }, + "type": { + "message": "タイプ" + }, + "firstName": { + "message": "名" + }, + "middleName": { + "message": "ミドルネーム" + }, + "lastName": { + "message": "姓" + }, + "fullName": { + "message": "フルネーム" + }, + "address1": { + "message": "住所1" + }, + "address2": { + "message": "住所2" + }, + "address3": { + "message": "住所3" + }, + "cityTown": { + "message": "市町村" + }, + "stateProvince": { + "message": "都道府県" + }, + "zipPostalCode": { + "message": "郵便番号" + }, + "country": { + "message": "国" + }, + "save": { + "message": "保存" + }, + "cancel": { + "message": "キャンセル" + }, + "delete": { + "message": "削除" + }, + "favorite": { + "message": "お気に入り" + }, + "edit": { + "message": "編集" + }, + "authenticatorKeyTotp": { + "message": "認証キー (TOTP)" + }, + "folder": { + "message": "フォルダー" + }, + "newCustomField": { + "message": "新規カスタムフィールド" + }, + "value": { + "message": "値" + }, + "dragToSort": { + "message": "ドラッグして並べ替え" + }, + "cfTypeText": { + "message": "テキスト" + }, + "cfTypeHidden": { + "message": "非表示" + }, + "cfTypeBoolean": { + "message": "真偽値" + }, + "cfTypeLinked": { + "message": "リンク済", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "リンクされた値", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "削除" + }, + "nameRequired": { + "message": "名前は必須項目です。" + }, + "addedItem": { + "message": "追加しました" + }, + "editedItem": { + "message": "編集しました" + }, + "deleteItem": { + "message": "アイテムの削除" + }, + "deleteFolder": { + "message": "フォルダーの削除" + }, + "deleteAttachment": { + "message": "添付ファイルの削除" + }, + "deleteItemConfirmation": { + "message": "このアイテムを削除してもよろしいですか?" + }, + "deletedItem": { + "message": "削除しました" + }, + "overwritePasswordConfirmation": { + "message": "現在のパスワードを上書きしてもよろしいですか?" + }, + "overwriteUsername": { + "message": "ユーザー名を上書き" + }, + "overwriteUsernameConfirmation": { + "message": "現在のユーザー名を上書きしてもよろしいですか?" + }, + "noneFolder": { + "message": "フォルダーなし", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "フォルダーの追加" + }, + "editFolder": { + "message": "フォルダーの編集" + }, + "regeneratePassword": { + "message": "パスワードの再生成" + }, + "copyPassword": { + "message": "パスワードのコピー" + }, + "copyUri": { + "message": "URI のコピー" + }, + "copyVerificationCodeTotp": { + "message": "認証コード (TOTP) をコピー" + }, + "length": { + "message": "長さ" + }, + "numWords": { + "message": "単語数" + }, + "wordSeparator": { + "message": "単語の区切り" + }, + "capitalize": { + "message": "先頭を大文字", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "数字を含む" + }, + "close": { + "message": "閉じる" + }, + "minNumbers": { + "message": "数字の最小数" + }, + "minSpecial": { + "message": "記号の最小数", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "あいまいな文字を省く" + }, + "searchCollection": { + "message": "コレクションの検索" + }, + "searchFolder": { + "message": "フォルダーの検索" + }, + "searchFavorites": { + "message": "お気に入りの検索" + }, + "searchType": { + "message": "検索の種類", + "description": "Search item type" + }, + "newAttachment": { + "message": "添付ファイルの追加" + }, + "deletedAttachment": { + "message": "削除された添付ファイル" + }, + "deleteAttachmentConfirmation": { + "message": "この添付ファイルを削除してよろしいですか?" + }, + "attachmentSaved": { + "message": "添付ファイルを保存しました。" + }, + "file": { + "message": "ファイル" + }, + "selectFile": { + "message": "ファイルを選択してください。" + }, + "maxFileSize": { + "message": "最大ファイルサイズは500MBです。" + }, + "updateKey": { + "message": "暗号キーを更新するまでこの機能は使用できません。" + }, + "editedFolder": { + "message": "フォルダーを編集しました" + }, + "addedFolder": { + "message": "フォルダーを追加しました" + }, + "deleteFolderConfirmation": { + "message": "フォルダーを削除しますか?" + }, + "deletedFolder": { + "message": "フォルダーを削除しました" + }, + "loginOrCreateNewAccount": { + "message": "安全なデータ保管庫へアクセスするためにログインまたはアカウントを作成してください。" + }, + "createAccount": { + "message": "アカウントの作成" + }, + "logIn": { + "message": "ログイン" + }, + "submit": { + "message": "送信" + }, + "masterPass": { + "message": "マスターパスワード" + }, + "masterPassDesc": { + "message": "マスターパスワードは、パスワード保管庫へのアクセスに使用するパスワードです。あなたのマスターパスワードを忘れないように注意してください。忘れた場合、パスワードを回復する方法はありません。" + }, + "masterPassHintDesc": { + "message": "マスターパスワードのヒントは、パスワードを忘れた場合に役立ちます。" + }, + "reTypeMasterPass": { + "message": "新しいパスワードを再入力" + }, + "masterPassHint": { + "message": "マスターパスワードのヒント (省略可能)" + }, + "settings": { + "message": "設定" + }, + "passwordHint": { + "message": "パスワードのヒント" + }, + "enterEmailToGetHint": { + "message": "マスターパスワードのヒントを受信するアカウントのメールアドレスを入力してください。" + }, + "getMasterPasswordHint": { + "message": "マスターパスワードのヒントを取得する" + }, + "emailRequired": { + "message": "メールアドレスは必須項目です。" + }, + "invalidEmail": { + "message": "無効なメールアドレスです。" + }, + "masterPassRequired": { + "message": "マスターパスワードは必須です。" + }, + "masterPassLength": { + "message": "マスターパスワードは、少なくとも8文字以上で設定してください。" + }, + "masterPassDoesntMatch": { + "message": "マスターパスワードが一致しません。" + }, + "newAccountCreated": { + "message": "新しいアカウントを作成しました!今すぐログインできます。" + }, + "masterPassSent": { + "message": "あなたのマスターパスワードのヒントを記載したメールを送信しました。" + }, + "unexpectedError": { + "message": "予期せぬエラーが発生しました。" + }, + "itemInformation": { + "message": "アイテム情報" + }, + "noItemsInList": { + "message": "表示するアイテムがありません" + }, + "sendVerificationCode": { + "message": "確認コードをメールに送信" + }, + "sendCode": { + "message": "コードを送信" + }, + "codeSent": { + "message": "確認コードを送信しました。" + }, + "verificationCode": { + "message": "認証コード" + }, + "confirmIdentity": { + "message": "続行するには本人確認を行ってください。" + }, + "verificationCodeRequired": { + "message": "認証コードは必須項目です。" + }, + "invalidVerificationCode": { + "message": "認証コードが間違っています" + }, + "continue": { + "message": "続行" + }, + "enterVerificationCodeApp": { + "message": "認証アプリに表示された6桁の認証コードを入力してください。" + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ に送信された6桁の認証コードを入力してください。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "$EMAIL$ に認証コードを送信しました。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "情報を保存する" + }, + "sendVerificationCodeEmailAgain": { + "message": "確認コードをメールで再送" + }, + "useAnotherTwoStepMethod": { + "message": "他の2段階認証方法を使用" + }, + "insertYubiKey": { + "message": "YubiKey を USB ポートに挿入し、ボタンをタッチしてください。" + }, + "insertU2f": { + "message": "セキュリティキーを USB ポートに挿入し、ボタンがある場合はボタンをタッチしてください。" + }, + "recoveryCodeDesc": { + "message": "すべての2段階認証プロパイダにアクセスできなくなったときは、リカバリーコードを使用するとアカウントの2段階認証を無効化できます。" + }, + "recoveryCodeTitle": { + "message": "リカバリーコード" + }, + "authenticatorAppTitle": { + "message": "認証アプリ" + }, + "authenticatorAppDesc": { + "message": "Authy や Google 認証システムなどの認証アプリで時限式の認証コードを生成してください。", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP セキュリティキー" + }, + "yubiKeyDesc": { + "message": "YubiKey を使ってアカウントにアクセスできます。 YubiKey 4、4 Nano、4C、NEOに対応しています。" + }, + "duoDesc": { + "message": "Duo Mobile アプリや SMS、電話や U2F セキュリティキーを使って Duo Security で認証します。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "組織の Duo Security を Duo Mobile アプリや SMS、電話、U2F セキュリティーキーを使用して認証します。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "アカウントにアクセスするには、WebAuthn 対応のセキュリティキーを使用してください。" + }, + "emailTitle": { + "message": "メールアドレス" + }, + "emailDesc": { + "message": "確認コードをメールにお送りします。" + }, + "loginUnavailable": { + "message": "ログインできません。" + }, + "noTwoStepProviders": { + "message": "このアカウントは2段階認証が有効ですが、このブラウザに対応した2段階認証プロパイダが一つも設定されていません。" + }, + "noTwoStepProviders2": { + "message": "より幅広い端末に対応した認証プロパイダを追加してください。" + }, + "twoStepOptions": { + "message": "2段階認証オプション" + }, + "selfHostedEnvironment": { + "message": "セルフホスティング環境" + }, + "selfHostedEnvironmentFooter": { + "message": "セルフホスティングしている Bitwarden のベース URL を指定してください。" + }, + "customEnvironment": { + "message": "カスタム環境" + }, + "customEnvironmentFooter": { + "message": "上級者向けです。各サービスのベース URL を個別に指定できます。" + }, + "baseUrl": { + "message": "サーバー URL" + }, + "apiUrl": { + "message": "API サーバー URL" + }, + "webVaultUrl": { + "message": "ウェブ保管庫サーバー URL" + }, + "identityUrl": { + "message": "ID サーバー URL" + }, + "notificationsUrl": { + "message": "通知サーバー URL" + }, + "iconsUrl": { + "message": "アイコンサーバー URL" + }, + "environmentSaved": { + "message": "環境 URL を保存しました。" + }, + "ok": { + "message": "OK" + }, + "yes": { + "message": "はい" + }, + "no": { + "message": "いいえ" + }, + "overwritePassword": { + "message": "パスワードを上書き" + }, + "learnMore": { + "message": "詳細情報" + }, + "featureUnavailable": { + "message": "サービスが利用できません" + }, + "loggedOut": { + "message": "ログアウトしました" + }, + "loginExpired": { + "message": "ログインセッションの有効期限が切れています。" + }, + "logOutConfirmation": { + "message": "ログアウトしてもよろしいですか?" + }, + "logOut": { + "message": "ログアウト" + }, + "addNewLogin": { + "message": "新しいログインの追加" + }, + "addNewItem": { + "message": "新しいアイテムの追加" + }, + "addNewFolder": { + "message": "新規フォルダーの追加" + }, + "view": { + "message": "表示" + }, + "account": { + "message": "アカウント" + }, + "loading": { + "message": "読み込み中…" + }, + "lockVault": { + "message": "保管庫をロック" + }, + "passwordGenerator": { + "message": "パスワード生成ツール" + }, + "contactUs": { + "message": "お問い合わせ" + }, + "getHelp": { + "message": "ヘルプ" + }, + "fileBugReport": { + "message": "バグレポートを送信" + }, + "blog": { + "message": "ブログ" + }, + "followUs": { + "message": "フォロー" + }, + "syncVault": { + "message": "保管庫の同期" + }, + "changeMasterPass": { + "message": "マスターパスワードの変更" + }, + "changeMasterPasswordConfirmation": { + "message": "マスターパスワードは bitwarden.com ウェブ保管庫で変更できます。ウェブサイトを開きますか?" + }, + "fingerprintPhrase": { + "message": "パスフレーズ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "アカウントのパスフレーズ", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "ウェブ保管庫を開く" + }, + "getMobileApp": { + "message": "モバイルアプリを取得" + }, + "getBrowserExtension": { + "message": "ブラウザの拡張機能を取得" + }, + "syncingComplete": { + "message": "同期が完了しました" + }, + "syncingFailed": { + "message": "同期に失敗しました" + }, + "yourVaultIsLocked": { + "message": "保管庫がロックされています。開くにはマスターパスワードを入力してください。" + }, + "unlock": { + "message": "ロック解除" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ の $EMAIL$ としてログインしました。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "マスターパスワードが間違っています" + }, + "twoStepLoginConfirmation": { + "message": "2段階認証を使うと、ログイン時にセキュリティキーや認証アプリ、SMS、電話やメールでの認証を必要にすることでアカウントをさらに安全に出来ます。2段階認証は bitwarden.com ウェブ保管庫で有効化できます。ウェブサイトを開きますか?" + }, + "twoStepLogin": { + "message": "2段階認証" + }, + "vaultTimeout": { + "message": "保管庫のタイムアウト" + }, + "vaultTimeoutDesc": { + "message": "保管庫がタイムアウトし、選択したアクションを実行するタイミングを選択します。" + }, + "immediately": { + "message": "すぐに" + }, + "tenSeconds": { + "message": "10秒" + }, + "twentySeconds": { + "message": "20秒" + }, + "thirtySeconds": { + "message": "30秒" + }, + "oneMinute": { + "message": "1分" + }, + "twoMinutes": { + "message": "2分" + }, + "fiveMinutes": { + "message": "5分" + }, + "fifteenMinutes": { + "message": "15分" + }, + "thirtyMinutes": { + "message": "30分" + }, + "oneHour": { + "message": "1時間" + }, + "fourHours": { + "message": "4時間" + }, + "onIdle": { + "message": "アイドル時" + }, + "onSleep": { + "message": "スリープ時" + }, + "onLocked": { + "message": "ロック時" + }, + "onRestart": { + "message": "再起動時" + }, + "never": { + "message": "なし" + }, + "security": { + "message": "セキュリティ" + }, + "clearClipboard": { + "message": "クリップボードの消去", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "選択した時間が経過した後、自動的にクリップボードを消去します。", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "ウェブサイトアイコンの無効化" + }, + "disableFaviconDesc": { + "message": "保管庫のアイテム毎にウェブサイトのアイコンを表示します。" + }, + "enableMinToTray": { + "message": "トレイアイコンに最小化" + }, + "enableMinToTrayDesc": { + "message": "ウインドウを最小化するとき、システムトレイにアイコンを表示するようにします。" + }, + "enableMinToMenuBar": { + "message": "メニューバーに最小化" + }, + "enableMinToMenuBarDesc": { + "message": "ウインドウを最小化するとき、メニューバーにアイコンを表示するようにします。" + }, + "enableCloseToTray": { + "message": "トレイアイコンへ閉じる" + }, + "enableCloseToTrayDesc": { + "message": "ウインドウを閉じたとき、システムトレイにアイコンを表示するようにします。" + }, + "enableCloseToMenuBar": { + "message": "閉じてメニューバーに表示" + }, + "enableCloseToMenuBarDesc": { + "message": "ウインドウを閉じたとき、メニューバーにアイコンを表示するようにします。" + }, + "enableTray": { + "message": "トレイアイコンの有効化" + }, + "enableTrayDesc": { + "message": "システムトレイにアイコンを常に表示します。" + }, + "startToTray": { + "message": "起動時にトレイアイコンのみ表示" + }, + "startToTrayDesc": { + "message": "アプリを初めて起動した際、システムトレイにアイコンを表示するだけにします。" + }, + "startToMenuBar": { + "message": "起動してメニューバーに表示" + }, + "startToMenuBarDesc": { + "message": "アプリを初めて起動した際、メニューバーにアイコンを表示するだけにします。" + }, + "openAtLogin": { + "message": "ログイン時に自動的に起動" + }, + "openAtLoginDesc": { + "message": "Bitwarden デスクトップアプリケーションをログイン時に自動的に起動します。" + }, + "alwaysShowDock": { + "message": "常にドックに表示" + }, + "alwaysShowDockDesc": { + "message": "メニューバーに最小化した場合でも、Bitwarden アイコンを表示します。" + }, + "confirmTrayTitle": { + "message": "トレイの無効化の確認" + }, + "confirmTrayDesc": { + "message": "この設定を無効にすると、他のすべてのトレイ関連設定も無効になります。" + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "アプリで使用する言語を変更します。再起動が必要です。" + }, + "theme": { + "message": "テーマ" + }, + "themeDesc": { + "message": "アプリのテーマカラーを変更します。" + }, + "dark": { + "message": "ダーク", + "description": "Dark color" + }, + "light": { + "message": "ライト", + "description": "Light color" + }, + "copy": { + "message": "コピー", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "更新を確認" + }, + "version": { + "message": "バージョン $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "再起動して更新" + }, + "restartToUpdateDesc": { + "message": "バージョン $VERSION_NUM$ をインストールする準備ができました。インストールを完了するにはアプリを再起動する必要があります。再起動して更新しますか?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "更新があります" + }, + "updateAvailableDesc": { + "message": "更新が見つかりました。今すぐダウンロードしますか?" + }, + "restart": { + "message": "再起動" + }, + "later": { + "message": "後で" + }, + "noUpdatesAvailable": { + "message": "現在更新はありません。最新バージョンを使用しています。" + }, + "updateError": { + "message": "更新エラー" + }, + "unknown": { + "message": "不明" + }, + "copyUsername": { + "message": "ユーザー名のコピー" + }, + "copyNumber": { + "message": "番号のコピー", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "セキュリティコードのコピー", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "プレミアム会員" + }, + "premiumManage": { + "message": "会員情報の管理" + }, + "premiumManageAlert": { + "message": "会員情報は bitwarden.com ウェブ保管庫で管理できます。ウェブサイトを開きますか?" + }, + "premiumRefresh": { + "message": "会員情報の更新" + }, + "premiumNotCurrentMember": { + "message": "あなたは現在プレミアム会員ではありません。" + }, + "premiumSignUpAndGet": { + "message": "プレミアム会員に登録すると以下の特典を得られます:" + }, + "premiumSignUpStorage": { + "message": "1GB の暗号化されたファイルストレージ。" + }, + "premiumSignUpTwoStep": { + "message": "YubiKey、FIDO U2F、Duoなどの追加の2段階認証ログインオプション" + }, + "premiumSignUpReports": { + "message": "保管庫を安全に保つための、パスワードやアカウントの健全性、データ侵害に関するレポート。" + }, + "premiumSignUpTotp": { + "message": "保管庫内での2段階認証コード生成" + }, + "premiumSignUpSupport": { + "message": "優先カスタマーサポート" + }, + "premiumSignUpFuture": { + "message": "将来のプレミアム機能すべて(詳細は近日公開予定!)" + }, + "premiumPurchase": { + "message": "プレミアム会員に加入" + }, + "premiumPurchaseAlert": { + "message": "プレミアム会員権は bitwarden.com ウェブ保管庫で購入できます。ウェブサイトを開きますか?" + }, + "premiumCurrentMember": { + "message": "あなたはプレミアム会員です!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden を支援いただき、ありがとうございます。" + }, + "premiumPrice": { + "message": "全部で年間たった$PRICE$!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "更新完了" + }, + "passwordHistory": { + "message": "パスワードの履歴" + }, + "clear": { + "message": "消去する", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "表示するパスワードがありません" + }, + "undo": { + "message": "元に戻す" + }, + "redo": { + "message": "やり直し" + }, + "cut": { + "message": "切り取り", + "description": "Cut to clipboard" + }, + "paste": { + "message": "貼り付け", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "すべて選択" + }, + "zoomIn": { + "message": "拡大" + }, + "zoomOut": { + "message": "縮小" + }, + "resetZoom": { + "message": "拡大をリセット" + }, + "toggleFullScreen": { + "message": "全画面表示の切り替え" + }, + "reload": { + "message": "再読み込み" + }, + "toggleDevTools": { + "message": "開発者ツールを表示" + }, + "minimize": { + "message": "最小化", + "description": "Minimize window" + }, + "zoom": { + "message": "ズーム" + }, + "bringAllToFront": { + "message": "すべてを手前に移動", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Bitwarden について" + }, + "services": { + "message": "サービス" + }, + "hideBitwarden": { + "message": "Bitwarden を隠す" + }, + "hideOthers": { + "message": "他を隠す" + }, + "showAll": { + "message": "すべて表示" + }, + "quitBitwarden": { + "message": "Bitwarden の終了" + }, + "valueCopied": { + "message": "$VALUE$ をコピーしました", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "ヘルプ" + }, + "window": { + "message": "ウィンドウ" + }, + "checkPassword": { + "message": "パスワードが漏洩していないか確認する" + }, + "passwordExposed": { + "message": "このパスワードは過去に$VALUE$回漏洩したことがあるため、変更するべきです。", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "このパスワードは過去に漏洩したデータ内にはないため、安全であると思われます。" + }, + "baseDomain": { + "message": "ベースドメイン", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "ドメイン名", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "ホスト", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "完全一致" + }, + "startsWith": { + "message": "前方一致" + }, + "regEx": { + "message": "正規表現", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "一致検出方法", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "デフォルトの一致検出方法", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "オプションの切り替え" + }, + "organization": { + "message": "組織", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "デフォルト" + }, + "exit": { + "message": "終了" + }, + "showHide": { + "message": "表示 / 非表示", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "トレイに隠す" + }, + "alwaysOnTop": { + "message": "常に最前面", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "更新日", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "パスワード更新日", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "保管庫のエクスポート" + }, + "fileFormat": { + "message": "ファイル形式" + }, + "warning": { + "message": "警告", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "保管庫のエクスポートの確認" + }, + "exportWarningDesc": { + "message": "このエクスポートデータは暗号化されていない形式の保管庫データを含んでいます。メールなどのセキュリティ保護されていない方法で共有したり保管したりしないでください。使用した後はすぐに削除してください。" + }, + "encExportKeyWarningDesc": { + "message": "このエクスポートは、アカウントの暗号化キーを使用してデータを暗号化します。 暗号化キーをローテーションした場合は、このエクスポートファイルを復号することはできなくなるため、もう一度エクスポートする必要があります。" + }, + "encExportAccountWarningDesc": { + "message": "アカウント暗号化キーは各 Bitwarden ユーザーアカウントに固有であるため、暗号化されたエクスポートを別のアカウントにインポートすることはできません。" + }, + "noOrganizationsList": { + "message": "あなたはどの組織にも属していません。組織では他のユーザーとアイテムを安全に共有できます。" + }, + "noCollectionsInList": { + "message": "表示するコレクションがありません" + }, + "ownership": { + "message": "所有者" + }, + "whoOwnsThisItem": { + "message": "このアイテムは誰が所有していますか?" + }, + "strong": { + "message": "強力", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "良好", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "脆弱", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "脆弱なマスターパスワード" + }, + "weakMasterPasswordDesc": { + "message": "設定されたマスターパスワードの強度は脆弱です。Bitwarden アカウントを適切に保護するために、強力なマスターパスワード(またはパスフレーズ)を使用すべきです。本当にこのマスターパスワードを使用しますか?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "PIN でロック解除" + }, + "setYourPinCode": { + "message": "Bitwarden のロックを解除するための PIN コードを設定します。アプリから完全にログアウトすると、PIN 設定はリセットされます。" + }, + "pinRequired": { + "message": "PIN コードが必要です。" + }, + "invalidPin": { + "message": "PIN コードが間違っています。" + }, + "unlockWithWindowsHello": { + "message": "Windows Hello でロック解除" + }, + "windowsHelloConsentMessage": { + "message": "Bitwarden の認証を行います。" + }, + "unlockWithTouchId": { + "message": "Touch ID でロック解除" + }, + "touchIdConsentMessage": { + "message": "Bitwarden の認証を行います。" + }, + "noAutoPromptWindowsHello": { + "message": "起動時に Windows Hello のプロンプトを表示しない" + }, + "noAutoPromptTouchId": { + "message": "起動時に Touch ID を要求しない" + }, + "lockWithMasterPassOnRestart": { + "message": "再起動時にマスターパスワードでロック" + }, + "preferences": { + "message": "設定" + }, + "enableMenuBar": { + "message": "メニューバーアイコンを有効化" + }, + "enableMenuBarDesc": { + "message": "メニューバーに常にアイコンを表示します。" + }, + "hideToMenuBar": { + "message": "メニューバーに隠す" + }, + "selectOneCollection": { + "message": "最低でも一つのコレクションを選んでください。" + }, + "premiumUpdated": { + "message": "プレミアムにアップグレードしました。" + }, + "restore": { + "message": "リストア" + }, + "premiumManageAlertAppStore": { + "message": "App Store でサブスクリプションを管理できます。今すぐ開きますか?" + }, + "legal": { + "message": "法的事項", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "サービス利用規約" + }, + "privacyPolicy": { + "message": "プライバシーポリシー" + }, + "unsavedChangesConfirmation": { + "message": "本当に閉じますか?今閉じると変更した情報は保存されません。" + }, + "unsavedChangesTitle": { + "message": "変更が保存されていません" + }, + "clone": { + "message": "複製" + }, + "passwordGeneratorPolicyInEffect": { + "message": "一つ以上の組織のポリシーがパスワード生成の設定に影響しています。" + }, + "vaultTimeoutAction": { + "message": "保管庫タイムアウト時のアクション" + }, + "vaultTimeoutActionLockDesc": { + "message": "ロックされた保管庫にアクセスするには、マスターパスワードを再入力してください。" + }, + "vaultTimeoutActionLogOutDesc": { + "message": "ログアウトした保管庫にアクセスするには、再認証してください。" + }, + "lock": { + "message": "ロック", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "ごみ箱", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "ごみ箱を検索" + }, + "permanentlyDeleteItem": { + "message": "アイテムを完全に削除" + }, + "permanentlyDeleteItemConfirmation": { + "message": "このアイテムを完全に削除してもよろしいですか?" + }, + "permanentlyDeletedItem": { + "message": "完全に削除されたアイテム" + }, + "restoreItem": { + "message": "アイテムをリストア" + }, + "restoreItemConfirmation": { + "message": "このアイテムをリストアしますか?" + }, + "restoredItem": { + "message": "リストアされたアイテム" + }, + "permanentlyDelete": { + "message": "完全に削除" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "ログアウトすると保管庫へのすべてのアクセスが制限され、タイムアウト期間後にオンライン認証が必要になります。 この設定を使用してもよろしいですか?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "タイムアウトアクションの確認" + }, + "enterpriseSingleSignOn": { + "message": "組織のシングルサインオン" + }, + "setMasterPassword": { + "message": "マスターパスワードを設定" + }, + "ssoCompleteRegistration": { + "message": "SSO ログインを完了するには、保管庫にアクセス・保護するためのマスターパスワードを設定してください。" + }, + "newMasterPass": { + "message": "新しいマスターパスワード" + }, + "confirmNewMasterPass": { + "message": "新しいマスターパスワードの確認" + }, + "masterPasswordPolicyInEffect": { + "message": "組織が求めるマスターパスワードの要件:" + }, + "policyInEffectMinComplexity": { + "message": "複雑度は最低$SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "長さは最低$LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "大文字が最低1つ必要" + }, + "policyInEffectLowercase": { + "message": "小文字が最低1つ必要" + }, + "policyInEffectNumbers": { + "message": "数字が最低1つ必要" + }, + "policyInEffectSpecial": { + "message": "次の記号から1つ以上:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "新しいマスターパスワードは最低要件を満たしていません。" + }, + "acceptPolicies": { + "message": "以下に同意しチェックします:" + }, + "acceptPoliciesError": { + "message": "利用規約とプライバシーポリシーを確認してください。" + }, + "enableBrowserIntegration": { + "message": "ブラウザ統合を有効にする" + }, + "enableBrowserIntegrationDesc": { + "message": "ブラウザでの生体認証のためにブラウザ統合を使用します。" + }, + "browserIntegrationMasOnlyTitle": { + "message": "ブラウザ統合はサポートされていません" + }, + "browserIntegrationMasOnlyDesc": { + "message": "残念ながら、ブラウザ統合は、Mac App Storeのバージョンでのみサポートされています。" + }, + "browserIntegrationWindowsStoreTitle": { + "message": "ブラウザ統合に対応していません" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "残念ながらお使いの Microsoft Store のバージョンではブラウザの統合に対応していません。" + }, + "enableBrowserIntegrationFingerprint": { + "message": "ブラウザ統合には認証を必要とする。" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "デスクトップとブラウザ間のリンクを確立する際にパスフレーズを要求することで、さらなるセキュリティ層を有効にします。 有効にすると、接続を確立するたびにユーザーによる確認が必要になります。" + }, + "approve": { + "message": "承認" + }, + "verifyBrowserTitle": { + "message": "ブラウザの接続を確認" + }, + "verifyBrowserDesc": { + "message": "表示されているパスフレーズがブラウザ拡張に表示されているものと同じであることを確認してください。" + }, + "biometricsNotEnabledTitle": { + "message": "生体認証が有効になっていません。" + }, + "biometricsNotEnabledDesc": { + "message": "ブラウザで生体認証を利用するには、最初に設定でデスクトップ生体認証を有効にする必要があります。" + }, + "personalOwnershipSubmitError": { + "message": "組織のポリシーにより、個人保管庫へのアイテムの保存が制限されています。 所有権を組織に変更し、利用可能なコレクションから選択してください。" + }, + "hintEqualsPassword": { + "message": "パスワードのヒントをパスワードと同じにすることはできません。" + }, + "personalOwnershipPolicyInEffect": { + "message": "組織のポリシーは、所有者のオプションに影響を与えています。" + }, + "allSends": { + "message": "すべての Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "ファイル" + }, + "sendTypeText": { + "message": "テキスト" + }, + "searchSends": { + "message": "Send を検索", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send を編集", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "保管庫" + }, + "text": { + "message": "テキスト" + }, + "deletionDate": { + "message": "削除日時" + }, + "deletionDateDesc": { + "message": "Send は指定された日時に完全に削除されます。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "有効期限" + }, + "expirationDateDesc": { + "message": "設定されている場合、この Send へのアクセスは指定された日時に失効します。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "最大アクセス数" + }, + "maxAccessCountDesc": { + "message": "設定されている場合、最大アクセス数に達するとユーザーはこの Send にアクセスできなくなります。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "現在のアクセス数" + }, + "disableSend": { + "message": "誰もアクセスできないように、この Send を無効にする", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "必要に応じて、ユーザーがこの Send にアクセスするためのパスワードを要求します。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "この Send に関するプライベートメモ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send リンク", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send リンク", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Send へのアクセス時に既定でテキストを非表示にする", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "作成した Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "編集済みの Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "削除した Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "新しいパスワード" + }, + "whatTypeOfSend": { + "message": "この Send の種類は何ですか?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Send を作成", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "送信するテキスト" + }, + "sendFileDesc": { + "message": "送信するファイル" + }, + "days": { + "message": "$DAYS$日", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1日" + }, + "custom": { + "message": "カスタム" + }, + "deleteSendConfirmation": { + "message": "この Send を削除してもよろしいですか?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Send リンクをクリップボードにコピー", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Send の保存時にクリップボードへリンクをコピーします。" + }, + "sendDisabled": { + "message": "Send 無効", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "組織のポリシーにより、既存の Send のみを削除できます。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "リンクをコピー" + }, + "disabled": { + "message": "無効" + }, + "maxAccessCountReached": { + "message": "最大アクセス数に達しました" + }, + "expired": { + "message": "有効期限切れ" + }, + "pendingDeletion": { + "message": "削除の保留中" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn の認証" + }, + "hideEmail": { + "message": "メールアドレスを受信者に表示しない" + }, + "sendOptionsPolicyInEffect": { + "message": "一つ以上の組織ポリシーが Send の設定に影響しています。" + }, + "emailVerificationRequired": { + "message": "メールアドレスの確認が必要です" + }, + "emailVerificationRequiredDesc": { + "message": "この機能を使用するにはメールアドレスを確認する必要があります。" + }, + "passwordPrompt": { + "message": "マスターパスワードの再要求" + }, + "passwordConfirmation": { + "message": "マスターパスワードの確認" + }, + "passwordConfirmationDesc": { + "message": "この操作は保護されています。続行するには、確認のためにマスターパスワードを再入力してください。" + }, + "updatedMasterPassword": { + "message": "マスターパスワードを更新しました" + }, + "updateMasterPassword": { + "message": "マスターパスワードを更新しました" + }, + "updateMasterPasswordWarning": { + "message": "マスターパスワードは最近組織の管理者によって変更されました。保管庫にアクセスするには、今すぐ更新する必要があります。 続行すると現在のセッションからログアウトし、再度ログインする必要があります。 他のデバイスでのアクティブなセッションは、最大1時間アクティブになり続けることがあります。" + }, + "hours": { + "message": "時間" + }, + "minutes": { + "message": "分" + }, + "vaultTimeoutPolicyInEffect": { + "message": "あなたの組織ポリシーは保管庫のタイムアウトに影響を与えています。最大保管庫のタイムアウト時間は $HOURS$ 時間 $MINUTES$ 分です。", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "保管庫のタイムアウトが組織によって設定された制限を超えています。" + }, + "resetPasswordPolicyAutoEnroll": { + "message": "自動登録" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "この組織には自動的にパスワードリセットに登録するポリシーがあります。登録すると、組織の管理者はマスターパスワードを変更できます。" + }, + "vaultExportDisabled": { + "message": "保管庫のエクスポートは無効です" + }, + "personalVaultExportPolicyInEffect": { + "message": "1 つまたは複数の組織ポリシーにより、個人の保管庫をエクスポートできません。" + }, + "addAccount": { + "message": "アカウントを追加" + }, + "removeMasterPassword": { + "message": "マスターパスワードを削除する" + }, + "removedMasterPassword": { + "message": "マスターパスワードを削除しました。" + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ は自己ホストの鍵サーバで SSO を使用しています。この組織のメンバーのログインにマスターパスワードは必要ありません。", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "組織から脱退する" + }, + "leaveOrganizationConfirmation": { + "message": "本当にこの組織から脱退しますか?" + }, + "leftOrganization": { + "message": "組織から脱退しました。" + }, + "ssoKeyConnectorUnavailable": { + "message": "キーコネクターに到達できません。後でもう一度お試しください。" + }, + "lockAllVaults": { + "message": "すべての保管庫をロック" + }, + "accountLimitReached": { + "message": "5つ以上のアカウントに同時にログインすることはできません。" + }, + "accountPreferences": { + "message": "設定" + }, + "appPreferences": { + "message": "アプリ設定 (すべてのアカウント)" + }, + "accountSwitcherLimitReached": { + "message": "アカウントの制限に達しました。別のアカウントを追加するにはアカウントからログアウトしてください。" + }, + "settingsTitle": { + "message": "$EMAIL$ のアプリ設定", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "アカウント切替" + }, + "options": { + "message": "オプション" + }, + "sessionTimeout": { + "message": "セッションがタイムアウトしました。もう一度ログインしてください。" + }, + "exportingPersonalVaultTitle": { + "message": "個人保管庫のエクスポート" + }, + "exportingPersonalVaultDescription": { + "message": "$EMAIL$ に関連付けられた個人用保管庫アイテムのみがエクスポートされます。組織用保管庫アイテムは含まれません。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "ジェネレーター" + }, + "whatWouldYouLikeToGenerate": { + "message": "何を生成しますか?" + }, + "passwordType": { + "message": "パスワードの種類" + }, + "regenerateUsername": { + "message": "ユーザー名を再生成" + }, + "generateUsername": { + "message": "ユーザー名を生成" + }, + "usernameType": { + "message": "ユーザー名の種類" + }, + "plusAddressedEmail": { + "message": "プラス付きのメールアドレス" + }, + "plusAddressedEmailDesc": { + "message": "メールプロバイダのエイリアス機能を使用します。" + }, + "catchallEmail": { + "message": "キャッチオールメール" + }, + "catchallEmailDesc": { + "message": "ドメインに設定されたキャッチオール受信トレイを使用します。" + }, + "random": { + "message": "ランダム" + }, + "randomWord": { + "message": "ランダムな単語" + }, + "websiteName": { + "message": "ウェブサイト名" + }, + "service": { + "message": "サービス" + } +} diff --git a/apps/desktop/src/locales/ka/messages.json b/apps/desktop/src/locales/ka/messages.json new file mode 100644 index 0000000000..1b909d5de4 --- /dev/null +++ b/apps/desktop/src/locales/ka/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "Favorites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Email Address" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy Value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security Code" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favorite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "Search Folder" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "Add New Folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check For Updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/km/messages.json b/apps/desktop/src/locales/km/messages.json new file mode 100644 index 0000000000..1b909d5de4 --- /dev/null +++ b/apps/desktop/src/locales/km/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "Favorites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Email Address" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy Value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security Code" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favorite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "Search Folder" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "Add New Folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check For Updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/kn/messages.json b/apps/desktop/src/locales/kn/messages.json new file mode 100644 index 0000000000..20e8bc07a9 --- /dev/null +++ b/apps/desktop/src/locales/kn/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "ಬಿಟ್ವಾರ್ಡೆನ್" + }, + "filters": { + "message": "ಶೋಧಕಗಳು" + }, + "allItems": { + "message": "ಎಲ್ಲಾ ವಸ್ತುಗಳು" + }, + "favorites": { + "message": "ಮೆಚ್ಚುಗೆಗಳು" + }, + "types": { + "message": "ರೀತಿಯ" + }, + "typeLogin": { + "message": "ಲಾಗಿನ್" + }, + "typeCard": { + "message": "ಕಾರ್ಡ್" + }, + "typeIdentity": { + "message": "ಗುರುತಿಸುವಿಕೆ" + }, + "typeSecureNote": { + "message": "ಸುರಕ್ಷಿತ ಟಿಪ್ಪಣಿ" + }, + "folders": { + "message": "ಫೋಲ್ಡರ್‌ಗಳು" + }, + "collections": { + "message": "ಸಂಗ್ರಹಣೆಗಳು" + }, + "searchVault": { + "message": "ವಾಲ್ಟ್ ಹುಡುಕಿ" + }, + "addItem": { + "message": "ಐಟಂ ಸೇರಿಸಿ" + }, + "shared": { + "message": "ಹಂಚಿಕೊಳ್ಳಲಾಗಿದೆ" + }, + "share": { + "message": "ಹಂಚಿಕೊಳ್ಳಿ" + }, + "moveToOrganization": { + "message": "ಸಂಸ್ಥೆಗೆ ಸರಿಸಿ" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ ಅನ್ನು $ORGNAME$ ಗೆ ಸರಿಸಲಾಗಿದೆ", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಸರಿಸಲು ನೀವು ಬಯಸುವ ಸಂಸ್ಥೆಯನ್ನು ಆರಿಸಿ. ಸಂಸ್ಥೆಗೆ ಹೋಗುವುದರಿಂದ ವಸ್ತುವಿನ ಮಾಲೀಕತ್ವವನ್ನು ಆ ಸಂಸ್ಥೆಗೆ ವರ್ಗಾಯಿಸುತ್ತದೆ. ಈ ಐಟಂ ಅನ್ನು ಸರಿಸಿದ ನಂತರ ನೀವು ಇನ್ನು ಮುಂದೆ ಅದರ ನೇರ ಮಾಲೀಕರಾಗಿರುವುದಿಲ್ಲ." + }, + "attachments": { + "message": "ಲಗತ್ತುಗಳು" + }, + "viewItem": { + "message": "ಐಟಂ ವೀಕ್ಷಿಸಿ" + }, + "name": { + "message": "ಹೆಸರು" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "ಯುಆರ್ಐ $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "ಹೊಸ ಯುಆರ್ಐ" + }, + "username": { + "message": "ಬಳಕೆದಾರ ಹೆಸರು" + }, + "password": { + "message": "ಪಾಸ್ವರ್ಡ್" + }, + "passphrase": { + "message": "ಪಾಸ್ಫ್ರೇಸ್" + }, + "editItem": { + "message": "ವಸ್ತುಗಳನ್ನು ಸಂಪಾದಿಸಿ" + }, + "emailAddress": { + "message": "ಇಮೇಲ್ ವಿಳಾಸ" + }, + "verificationCodeTotp": { + "message": "ಪರಿಶೀಲನಾ ಕೋಡ್‌ಗಳು (TOTP)" + }, + "website": { + "message": "ಜಾಲತಾಣ" + }, + "notes": { + "message": "ಟಿಪ್ಪಣಿಗಳು" + }, + "customFields": { + "message": "ಕಸ್ಟಮ್ ಕ್ಷೇತ್ರಗಳು" + }, + "launch": { + "message": "ಶುರು" + }, + "copyValue": { + "message": "ಮೌಲ್ಯವನ್ನು ನಕಲಿಸಿ", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "ಕ್ಲಿಪ್ಬೋರ್ಡ್ಗೆ ನಕಲಿಸಿದಾಗ ಕಡಿಮೆ ಮಾಡಿ" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "ಐಟಂನ ಡೇಟಾವನ್ನು ಕ್ಲಿಪ್ಬೋರ್ಡ್ಗೆ ನಕಲಿಸುವಾಗ ಕಡಿಮೆ ಮಾಡಿ." + }, + "toggleVisibility": { + "message": "ಗೋಚರತೆಯನ್ನು ಟಾಗಲ್ ಮಾಡಿ" + }, + "toggleCollapse": { + "message": "ಟಾಗಲ್ ಕುಸಿತ", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "ಕಾರ್ಡುದಾರನ ಹೆಸರು" + }, + "number": { + "message": "ಸಂಖ್ಯೆ" + }, + "brand": { + "message": "ಬ್ರ್ಯಾಂಡ್" + }, + "expiration": { + "message": "ಮುಕ್ತಾಯ" + }, + "securityCode": { + "message": "ಭದ್ರತಾ ಕೋಡ್" + }, + "identityName": { + "message": "ಹೆಸರು ಗುರುತು" + }, + "company": { + "message": "ಕಂಪನಿ" + }, + "ssn": { + "message": "ಸಾಮಾಜಿಕ ಭದ್ರತೆ ಸಂಖ್ಯೆ" + }, + "passportNumber": { + "message": "ಪಾಸ್ಪೋರ್ಟ್ ಸಂಖ್ಯೆ" + }, + "licenseNumber": { + "message": "ಪರವಾನಗಿ ಸಂಖ್ಯೆ" + }, + "email": { + "message": "ಇಮೇಲ್" + }, + "phone": { + "message": "ಫೋನ್‌" + }, + "address": { + "message": "ವಿಳಾಸ" + }, + "premiumRequired": { + "message": "ಪ್ರೀಮಿಯಂ ಅಗತ್ಯವಿದೆ" + }, + "premiumRequiredDesc": { + "message": "ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವ ಅಗತ್ಯವಿದೆ." + }, + "errorOccurred": { + "message": "ದೋಷ ಸಂಭವಿಸಿದೆ." + }, + "error": { + "message": "ದೋಷ" + }, + "january": { + "message": "ಜನವರಿ" + }, + "february": { + "message": "ಫೆಬ್ರವರಿ" + }, + "march": { + "message": "ಮಾರ್ಚ್" + }, + "april": { + "message": "ಏಪ್ರಿಲ್" + }, + "may": { + "message": "ಮೇ" + }, + "june": { + "message": "ಜೂನ್" + }, + "july": { + "message": "ಜುಲೈ" + }, + "august": { + "message": "ಆಗಸ್ಟ್" + }, + "september": { + "message": "ಸೆಪ್ಟೆಂಬರ್" + }, + "october": { + "message": "ಅಕ್ಟೋಬರ್" + }, + "november": { + "message": "ನವೆಂಬರ್" + }, + "december": { + "message": "ಡಿಸೆಂಬರ್" + }, + "ex": { + "message": "ಉದಾಹರಣೆ.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "ಶೀರ್ಷಿಕೆ" + }, + "mr": { + "message": "ಶ್ರೀ" + }, + "mrs": { + "message": "ಶ್ರೀಮತಿ" + }, + "ms": { + "message": "ಎಂ ಎಸ್" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "ಮುಕ್ತಾಯ ತಿಂಗಳು" + }, + "expirationYear": { + "message": "ಮುಕ್ತಾಯ ವರ್ಷ" + }, + "select": { + "message": "ಆಯ್ಕೆಮಾಡಿ" + }, + "other": { + "message": "ಇತರೆ" + }, + "generatePassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ರಚಿಸಿ" + }, + "type": { + "message": "ಪ್ರಕಾರ" + }, + "firstName": { + "message": "ಮೊದಲ ಹೆಸರು" + }, + "middleName": { + "message": "ಮಧ್ಯದ ಹೆಸರು" + }, + "lastName": { + "message": "ಕೊನೆ ಹೆಸರು" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "ವಿಳಾಸ 1" + }, + "address2": { + "message": "ವಿಳಾಸ 2" + }, + "address3": { + "message": "ವಿಳಾಸ 3" + }, + "cityTown": { + "message": "ನಗರ / ಪಟ್ಟಣ" + }, + "stateProvince": { + "message": "ರಾಜ್ಯ / ಪ್ರಾಂತ್ಯ" + }, + "zipPostalCode": { + "message": "ಪಿನ್ / ಅಂಚೆ ಕೋಡ್" + }, + "country": { + "message": "ದೇಶ" + }, + "save": { + "message": "ಉಳಿಸಿ" + }, + "cancel": { + "message": "ರದ್ದು" + }, + "delete": { + "message": "ಅಳಿಸು" + }, + "favorite": { + "message": "ಮೆಚ್ಚಿನ" + }, + "edit": { + "message": "ಎಡಿಟ್" + }, + "authenticatorKeyTotp": { + "message": "ದೃಢೀಕರಣ ಕೀ (TOTP)" + }, + "folder": { + "message": "ಫೋಲ್ಡರ್" + }, + "newCustomField": { + "message": "ಹೊಸ ಕಸ್ಟಮ್ ಕ್ಷೇತ್ರ" + }, + "value": { + "message": "ಮೌಲ್ಯ" + }, + "dragToSort": { + "message": "ವಿಂಗಡಿಸಲು ಎಳೆಯಿರಿ" + }, + "cfTypeText": { + "message": "ಪಠ್ಯ" + }, + "cfTypeHidden": { + "message": "ಮರೆಮಾಡಲಾಗಿದೆ" + }, + "cfTypeBoolean": { + "message": "ಬೂಲಿಯನ್" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "ತೆಗೆ" + }, + "nameRequired": { + "message": "ಹೆಸರೊಂದು ಅಗತ್ಯವಿದೆ." + }, + "addedItem": { + "message": "ಐಟಂ ಸೇರಿಸಲಾಗಿದೆ" + }, + "editedItem": { + "message": "ಐಟಂ ಸಂಪಾದಿಸಲಾಗಿದೆ" + }, + "deleteItem": { + "message": "ಐಟಂ ಅಳಿಸಿ" + }, + "deleteFolder": { + "message": "ಫೋಲ್ಡರ್ ಅಳಿಸಿ" + }, + "deleteAttachment": { + "message": "ಲಗತ್ತನ್ನು ಅಳಿಸಿ" + }, + "deleteItemConfirmation": { + "message": "ನೀವು ನಿಜವಾಗಿಯೂ ಅನುಪಯುಕ್ತಕ್ಕೆ ಕಳುಹಿಸಲು ಬಯಸುವಿರಾ?" + }, + "deletedItem": { + "message": "ಐಟಂ ಅನ್ನು ಅನುಪಯುಕ್ತಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿದೆ" + }, + "overwritePasswordConfirmation": { + "message": "ಪ್ರಸ್ತುತ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ತಿದ್ದಿಬರೆಯಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "ಫೋಲ್ಡರ್ ಇಲ್ಲ", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "ಫೋಲ್ಡರ್ ಸೇರಿಸಿ" + }, + "editFolder": { + "message": "ಫೋಲ್ಡರ್ ಸಂಪಾದಿಸಿ" + }, + "regeneratePassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಪುನರುತ್ಪಾದಿಸಿ" + }, + "copyPassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ನಕಲಿಸಿ" + }, + "copyUri": { + "message": "URI ಅನ್ನು ನಕಲಿಸಿ" + }, + "copyVerificationCodeTotp": { + "message": "ನಕಲಿಸಿ ಪರಿಶೀಲನೆ ಕೋಡ್ (TOTP)" + }, + "length": { + "message": "ಉದ್ದ" + }, + "numWords": { + "message": "ಪದಗಳ ಸಂಖ್ಯೆ" + }, + "wordSeparator": { + "message": "ಪದ ವಿಭಜಕ" + }, + "capitalize": { + "message": "ದೊಡ್ಡಕ್ಷರ ಮಾಡಿ", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ" + }, + "close": { + "message": "ಮುಚ್ಚಿ" + }, + "minNumbers": { + "message": "ಕನಿಷ್ಠ ಸಂಖ್ಯೆಗಳು" + }, + "minSpecial": { + "message": "ಕನಿಷ್ಠ ವಿಶೇಷ", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "ಅಸ್ಪಷ್ಟ ಅಕ್ಷರಗಳನ್ನು ತಪ್ಪಿಸಿ" + }, + "searchCollection": { + "message": "ಸಂಗ್ರಹಣೆ ಹುಡುಕಿ" + }, + "searchFolder": { + "message": "ಫೋಲ್ಡರ್ ಹುಡುಕಿ" + }, + "searchFavorites": { + "message": "ಮೆಚ್ಚುಗೆಗಳಲ್ಲಿ ಶೋಧ" + }, + "searchType": { + "message": "ಹುಡುಕಾಟ ಪ್ರಕಾರ", + "description": "Search item type" + }, + "newAttachment": { + "message": "ಹೊಸ ಲಗತ್ತನ್ನು ಸೇರಿಸಿ" + }, + "deletedAttachment": { + "message": "ಲಗತ್ತು ಅಳಿಸಲಾಗಿದೆ" + }, + "deleteAttachmentConfirmation": { + "message": "ಈ ಲಗತ್ತನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "attachmentSaved": { + "message": "ಲಗತ್ತನ್ನು ಉಳಿಸಲಾಗಿದೆ." + }, + "file": { + "message": "ಫೈಲ್" + }, + "selectFile": { + "message": "ಕಡತವನ್ನು ಆಯ್ಕೆಮಾಡು." + }, + "maxFileSize": { + "message": "ಗರಿಷ್ಠ ಫೈಲ್ ಗಾತ್ರ 500 ಎಂಬಿ." + }, + "updateKey": { + "message": "ನಿಮ್ಮ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಲಿಯನ್ನು ನವೀಕರಿಸುವವರೆಗೆ ನೀವು ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲಾಗುವುದಿಲ್ಲ." + }, + "editedFolder": { + "message": "ಫೋಲ್ಡರ್ ತಿದ್ದಲಾಗಿದೆ" + }, + "addedFolder": { + "message": "ಫೋಲ್ಡರ್ ಸೇರಿಸಿ" + }, + "deleteFolderConfirmation": { + "message": "ನೀವು ಈ ಕಡತಕೋಶವನ್ನು ಖಚಿತವಾಗಿಯೂ ಅಳಿಸಬಯಸುವಿರಾ?" + }, + "deletedFolder": { + "message": "ಫೋಲ್ಡರ್ ಅಳಿಸಿ" + }, + "loginOrCreateNewAccount": { + "message": "ನಿಮ್ಮ ಸುರಕ್ಷಿತ ವಾಲ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಲಾಗ್ ಇನ್ ಮಾಡಿ ಅಥವಾ ಹೊಸ ಖಾತೆಯನ್ನು ರಚಿಸಿ." + }, + "createAccount": { + "message": "ಖಾತೆ ತೆರೆ" + }, + "logIn": { + "message": "ಲಾಗಿನ್" + }, + "submit": { + "message": "ಒಪ್ಪಿಸು" + }, + "masterPass": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್" + }, + "masterPassDesc": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ನೀವು ಬಳಸುವ ಪಾಸ್ವರ್ಡ್ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಆಗಿದೆ. ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನೀವು ಮರೆಯದಿರುವುದು ಬಹಳ ಮುಖ್ಯ. ನೀವು ಅದನ್ನು ಮರೆತ ಸಂದರ್ಭದಲ್ಲಿ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರುಪಡೆಯಲು ಯಾವುದೇ ಮಾರ್ಗವಿಲ್ಲ." + }, + "masterPassHintDesc": { + "message": "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನೀವು ಮರೆತರೆ ಅದನ್ನು ನೆನಪಿಟ್ಟುಕೊಳ್ಳಲು ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಸುಳಿವು ನಿಮಗೆ ಸಹಾಯ ಮಾಡುತ್ತದೆ." + }, + "reTypeMasterPass": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಮರು-ಟೈಪ್ ಮಾಡಿ" + }, + "masterPassHint": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಸುಳಿವು (ಐಚ್ಛಿಕ)" + }, + "settings": { + "message": "ಸೆಟ್ಟಿಂಗ್‍ಗಳು" + }, + "passwordHint": { + "message": "ಪಾಸ್ವರ್ಡ್ ಸುಳಿವು" + }, + "enterEmailToGetHint": { + "message": "ವಿಸ್ತರಣೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಮೆನುವಿನಲ್ಲಿರುವ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಐಕಾನ್ ಟ್ಯಾಪ್ ಮಾಡಿ." + }, + "getMasterPasswordHint": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಸುಳಿವನ್ನು ಪಡೆಯಿರಿ" + }, + "emailRequired": { + "message": "ಇಮೇಲ್ ವಿಳಾಸದ ಅಗತ್ಯವಿದೆ." + }, + "invalidEmail": { + "message": "ಅಮಾನ್ಯ ಇಮೇಲ್ ವಿಳಾಸ." + }, + "masterPassRequired": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಅಗತ್ಯವಿದೆ." + }, + "masterPassLength": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಕನಿಷ್ಠ 8 ಅಕ್ಷರಗಳಷ್ಟು ಉದ್ದವಾಗಿರಬೇಕು." + }, + "masterPassDoesntMatch": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ದೃಢೀಕರಣವು ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ." + }, + "newAccountCreated": { + "message": "ನಿಮ್ಮ ಹೊಸ ಖಾತೆಯನ್ನು ರಚಿಸಲಾಗಿದೆ! ನೀವು ಈಗ ಲಾಗ್ ಇನ್ ಮಾಡಬಹುದು." + }, + "masterPassSent": { + "message": "ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಸುಳಿವಿನೊಂದಿಗೆ ನಾವು ನಿಮಗೆ ಇಮೇಲ್ ಕಳುಹಿಸಿದ್ದೇವೆ." + }, + "unexpectedError": { + "message": "ಅನಿರೀಕ್ಷಿತ ದೋಷ ಸಂಭವಿಸಿದೆ." + }, + "itemInformation": { + "message": "ಐಟಂ ಮಾಹಿತಿ" + }, + "noItemsInList": { + "message": "ಪಟ್ಟಿ ಮಾಡಲು ಯಾವುದೇ ಐಟಂಗಳಿಲ್ಲ." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "ಪರಿಶೀಲನಾ ಕೋಡ್‌ಗಳು" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "ಪರಿಶೀಲನೆ ಕೋಡ್ ಅಗತ್ಯವಿದೆ." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "ಮುಂದುವರಿಸಿ" + }, + "enterVerificationCodeApp": { + "message": "ನಿಮ್ಮ ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ 6 ಅಂಕಿಯ ಪರಿಶೀಲನಾ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ಗೆ ಇಮೇಲ್ ಮಾಡಲಾದ 6 ಅಂಕಿಯ ಪರಿಶೀಲನಾ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "ಪರಿಶೀಲನೆ ಇಮೇಲ್ $EMAIL$ ಗೆ ಕಳುಹಿಸಲಾಗಿದೆ.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "ನನ್ನನ್ನು ನೆನಪಿನಲ್ಲಿ ಇಡು" + }, + "sendVerificationCodeEmailAgain": { + "message": "ಪರಿಶೀಲನೆ ಕೋಡ್ ಇಮೇಲ್ ಅನ್ನು ಮತ್ತೆ ಕಳುಹಿಸಿ" + }, + "useAnotherTwoStepMethod": { + "message": "ಮತ್ತೊಂದು ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ವಿಧಾನವನ್ನು ಬಳಸಿ" + }, + "insertYubiKey": { + "message": "ನಿಮ್ಮ ಯುಬಿಕಿಯನ್ನು ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನ ಯುಎಸ್‌ಬಿ ಪೋರ್ಟ್ಗೆ ಸೇರಿಸಿ, ನಂತರ ಅದರ ಗುಂಡಿಯನ್ನು ಸ್ಪರ್ಶಿಸಿ." + }, + "insertU2f": { + "message": "ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್‌ನ ಯುಎಸ್‌ಬಿ ಪೋರ್ಟ್ಗೆ ನಿಮ್ಮ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಸೇರಿಸಿ. ಅದು ಬಟನ್ ಹೊಂದಿದ್ದರೆ, ಅದನ್ನು ಸ್ಪರ್ಶಿಸಿ." + }, + "recoveryCodeDesc": { + "message": "ನಿಮ್ಮ ಎಲ್ಲಾ ಎರಡು ಅಂಶ ಪೂರೈಕೆದಾರರಿಗೆ ಪ್ರವೇಶವನ್ನು ಕಳೆದುಕೊಂಡಿದ್ದೀರಾ? ನಿಮ್ಮ ಖಾತೆಯಿಂದ ಎಲ್ಲಾ ಎರಡು ಅಂಶ ಪೂರೈಕೆದಾರರನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ನಿಮ್ಮ ಮರುಪಡೆಯುವಿಕೆ ಕೋಡ್ ಬಳಸಿ." + }, + "recoveryCodeTitle": { + "message": "ಮರುಪಡೆಯುವಿಕೆ ಕೋಡ್" + }, + "authenticatorAppTitle": { + "message": "ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್" + }, + "authenticatorAppDesc": { + "message": "ಸಮಯ ಆಧಾರಿತ ಪರಿಶೀಲನಾ ಕೋಡ್‌ಗಳನ್ನು ರಚಿಸಲು ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಬಳಸಿ (ಆಥಿ ಅಥವಾ ಗೂಗಲ್ ಅಥೆಂಟಿಕೇಟರ್).", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "ಯುಬಿಕೆ ಒಟಿಪಿ ಭದ್ರತಾ ಕೀ" + }, + "yubiKeyDesc": { + "message": "ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಯುಬಿಕೆ ಬಳಸಿ. ಯುಬಿಕೆ 4, 4 ನ್ಯಾನೋ, 4 ಸಿ ಮತ್ತು ಎನ್ಇಒ ಸಾಧನಗಳೊಂದಿಗೆ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ." + }, + "duoDesc": { + "message": "ಡ್ಯುಯೊ ಮೊಬೈಲ್ ಅಪ್ಲಿಕೇಶನ್, ಎಸ್‌ಎಂಎಸ್, ಫೋನ್ ಕರೆ ಅಥವಾ ಯು 2 ಎಫ್ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಬಳಸಿಕೊಂಡು ಡ್ಯುಯೊ ಸೆಕ್ಯುರಿಟಿಯೊಂದಿಗೆ ಪರಿಶೀಲಿಸಿ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "ಡ್ಯುಯೊ ಮೊಬೈಲ್ ಅಪ್ಲಿಕೇಶನ್, ಎಸ್‌ಎಂಎಸ್, ಫೋನ್ ಕರೆ ಅಥವಾ ಯು 2 ಎಫ್ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಸಂಸ್ಥೆಗಾಗಿ ಡ್ಯುಯೊ ಸೆಕ್ಯುರಿಟಿಯೊಂದಿಗೆ ಪರಿಶೀಲಿಸಿ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಯಾವುದೇ ವೆಬ್‌ಆಥ್ನ್ ಸಕ್ರಿಯಗೊಳಿಸಿದ ಭದ್ರತಾ ಕೀಲಿಯನ್ನು ಬಳಸಿ." + }, + "emailTitle": { + "message": "ಇಮೇಲ್" + }, + "emailDesc": { + "message": "ಪರಿಶೀಲನೆ ಕೋಡ್‌ಗಳನ್ನು ನಿಮಗೆ ಇಮೇಲ್ ಮಾಡಲಾಗುತ್ತದೆ." + }, + "loginUnavailable": { + "message": "ಲಾಗಿನ್ ಲಭ್ಯವಿಲ್ಲ" + }, + "noTwoStepProviders": { + "message": "ಈ ಖಾತೆಯು ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿದೆ, ಆದಾಗ್ಯೂ, ಕಾನ್ಫಿಗರ್ ಮಾಡಲಾದ ಎರಡು-ಹಂತದ ಪೂರೈಕೆದಾರರಲ್ಲಿ ಯಾರೂ ಈ ವೆಬ್ ಬ್ರೌಸರ್‌ನಿಂದ ಬೆಂಬಲಿತವಾಗಿಲ್ಲ." + }, + "noTwoStepProviders2": { + "message": "ಸಾಧನಗಳಲ್ಲಿ (ಅಥೆಂಟಿಕೇಟರ್ ಅಪ್ಲಿಕೇಶನ್‌ನಂತಹ) ಉತ್ತಮವಾಗಿ ಬೆಂಬಲಿತವಾಗಿರುವ ಹೆಚ್ಚುವರಿ ಪೂರೈಕೆದಾರರನ್ನು ದಯವಿಟ್ಟು ಸೇರಿಸಿ." + }, + "twoStepOptions": { + "message": "ಎರಡು ಹಂತದ ಲಾಗಿನ್ ಆಯ್ಕೆಗಳು" + }, + "selfHostedEnvironment": { + "message": "ಸ್ವಯಂ ಆತಿಥೇಯ ಪರಿಸರ" + }, + "selfHostedEnvironmentFooter": { + "message": "ನಿಮ್ಮ ಆನ್-ಪ್ರಮೇಯ ಹೋಸ್ಟ್ ಮಾಡಿದ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಸ್ಥಾಪನೆಯ ಮೂಲ URL ಅನ್ನು ನಿರ್ದಿಷ್ಟಪಡಿಸಿ." + }, + "customEnvironment": { + "message": "ಕಸ್ಟಮ್ ಪರಿಸರ" + }, + "customEnvironmentFooter": { + "message": "ಸುಧಾರಿತ ಬಳಕೆದಾರರಿಗಾಗಿ. ನೀವು ಪ್ರತಿ ಸೇವೆಯ ಮೂಲ URL ಅನ್ನು ಸ್ವತಂತ್ರವಾಗಿ ನಿರ್ದಿಷ್ಟಪಡಿಸಬಹುದು." + }, + "baseUrl": { + "message": "ಸರ್ವರ್ URL" + }, + "apiUrl": { + "message": "API ಸರ್ವರ್ URL" + }, + "webVaultUrl": { + "message": "ವೆಬ್ ವಾಲ್ಟ್ ಸರ್ವರ್ URL" + }, + "identityUrl": { + "message": "ಗುರುತಿನ ಸರ್ವರ್ URL" + }, + "notificationsUrl": { + "message": "ಅಧಿಸೂಚನೆಗಳು ಸರ್ವರ್ URL" + }, + "iconsUrl": { + "message": "ಚಿಹ್ನೆಗಳು ಸರ್ವರ್ URL" + }, + "environmentSaved": { + "message": "ಪರಿಸರ URL ಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ." + }, + "ok": { + "message": "ಸರಿ" + }, + "yes": { + "message": "ಹೌದು" + }, + "no": { + "message": "ಇಲ್ಲ" + }, + "overwritePassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಬದಲಿಸಿ" + }, + "learnMore": { + "message": "ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ" + }, + "featureUnavailable": { + "message": "ವೈಶಿಷ್ಟ್ಯ ಲಭ್ಯವಿಲ್ಲ" + }, + "loggedOut": { + "message": "ಲಾಗ್ ಔಟ್" + }, + "loginExpired": { + "message": "ನಿಮ್ಮ ಲಾಗಿನ್ ಸೆಷನ್ ಅವಧಿ ಮೀರಿದೆ." + }, + "logOutConfirmation": { + "message": "ಲಾಗ್ ಔಟ್ ಮಾಡಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "logOut": { + "message": "ಲಾಗ್ ಔಟ್" + }, + "addNewLogin": { + "message": "ಹೊಸ ಲಾಗಿನ್ ಸೇರಿಸಿ" + }, + "addNewItem": { + "message": "ಐಟಂ ಸೇರಿಸಿ" + }, + "addNewFolder": { + "message": "ಹೊಸ ಫೋಲ್ಡರ್ ಸೇರಿಸಿ" + }, + "view": { + "message": "ವೀಕ್ಷಣೆ" + }, + "account": { + "message": "ಖಾತೆ" + }, + "loading": { + "message": "ಲೋಡ್‌ಆಗುತ್ತಿದೆ..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "ಪಾಸ್ವರ್ಡ್ ಜನರೇಟರ್" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "ದೋಷ ವರದಿಯನ್ನು ಫೈಲ್ ಮಾಡಿ" + }, + "blog": { + "message": "ಬ್ಲಾಗ್" + }, + "followUs": { + "message": "ನಮ್ಮನ್ನು ಅನುಸರಿಸಿ" + }, + "syncVault": { + "message": "ಸಿಂಕ್ ವಾಲ್ಟ್" + }, + "changeMasterPass": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಬದಲಾಯಿಸಿ" + }, + "changeMasterPasswordConfirmation": { + "message": "ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ನೀವು bitwarden.com ವೆಬ್ ವಾಲ್ಟ್‌ನಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "fingerprintPhrase": { + "message": "ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಫ್ರೇಸ್", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "ನಿಮ್ಮ ಖಾತೆಯ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ನುಡಿಗಟ್ಟು", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "ವೆಬ್ ಚಾವಣಿಗೆ ಹೋಗಿ" + }, + "getMobileApp": { + "message": "ಮೊಬೈಲ್ ಅಪ್ಲಿಕೇಶನ್ ಪಡೆಯಿರಿ" + }, + "getBrowserExtension": { + "message": "ಬ್ರೌಸರ್ ವಿಸ್ತರಣೆ ಪಡೆಯಿರಿ" + }, + "syncingComplete": { + "message": "ಒಡವಾಗುನಂಟು ಪೂರ್ಣಗೊಂಡಿದೆ" + }, + "syncingFailed": { + "message": "ಸಿಂಕ್ ವಿಫಲಗೊಂಡಿದೆ" + }, + "yourVaultIsLocked": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಲಾಕ್ ಆಗಿದೆ. ಮುಂದುವರೆಯಲು ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ." + }, + "unlock": { + "message": "ಅನ್‌ಲಾಕ್ ಮಾಡಿ" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ನಲ್ಲಿ $EMAIL$ಆಗಿ ಲಾಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆ.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "ಅಮಾನ್ಯ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್" + }, + "twoStepLoginConfirmation": { + "message": "ಭದ್ರತಾ ಕೀ, ದೃಢೀಕರಣ ಅಪ್ಲಿಕೇಶನ್, ಎಸ್‌ಎಂಎಸ್, ಫೋನ್ ಕರೆ ಅಥವಾ ಇಮೇಲ್‌ನಂತಹ ಮತ್ತೊಂದು ಸಾಧನದೊಂದಿಗೆ ನಿಮ್ಮ ಲಾಗಿನ್ ಅನ್ನು ಪರಿಶೀಲಿಸುವ ಅಗತ್ಯವಿರುವ ಎರಡು ಹಂತದ ಲಾಗಿನ್ ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಹೆಚ್ಚು ಸುರಕ್ಷಿತಗೊಳಿಸುತ್ತದೆ. ಬಿಟ್ವಾರ್ಡೆನ್.ಕಾಮ್ ವೆಬ್ ವಾಲ್ಟ್ನಲ್ಲಿ ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "twoStepLogin": { + "message": "ಎರಡು ಹಂತದ ಲಾಗಿನ್" + }, + "vaultTimeout": { + "message": "ವಾಲ್ಟ್ ಕಾಲಾವಧಿ" + }, + "vaultTimeoutDesc": { + "message": "ನಿಮ್ಮ ಕಮಾನು ಸಮಯ ಮೀರಲಿ ಮತ್ತು ಆಯ್ದ ಕ್ರಮವನ್ನು ನಿರ್ವಹಿಸುವಾಗ ಆರಿಸಿಕೊಳ್ಳಿ." + }, + "immediately": { + "message": "ತಕ್ಷಣ" + }, + "tenSeconds": { + "message": "೧೦ ಕ್ಷಣ" + }, + "twentySeconds": { + "message": "೨0 ಸೆಕೆಂಡುಗಳು" + }, + "thirtySeconds": { + "message": "೩೦ ಕ್ಷಣ" + }, + "oneMinute": { + "message": "೧ ನಿಮಿಷ" + }, + "twoMinutes": { + "message": "೨ ನಿಮಿಷಗಳು" + }, + "fiveMinutes": { + "message": "೫ ನಿಮಿಷಗಳು" + }, + "fifteenMinutes": { + "message": "೧೫ ನಿಮಿಷಗಳು" + }, + "thirtyMinutes": { + "message": "30 ನಿಮಿಷಗಳು" + }, + "oneHour": { + "message": "೧ ಗಂಟೆ" + }, + "fourHours": { + "message": "೪ ಗಂಟೆಗಳು" + }, + "onIdle": { + "message": "ಸಿಸ್ಟಮ್ ಐಡಲ್‌ನಲ್ಲಿ" + }, + "onSleep": { + "message": "ಸಿಸ್ಟಮ್ ಸ್ಲೀಪ್‌ನಲ್ಲಿ" + }, + "onLocked": { + "message": "ಸಿಸ್ಟಮ್ ಲಾಕ್‌ನಲ್ಲಿ" + }, + "onRestart": { + "message": "ಅಪ್ಲಿಕೇಶನ್ ಮರುಪ್ರಾರಂಭದಲ್ಲಿ" + }, + "never": { + "message": "ಇಲ್ಲವೇ ಇಲ್ಲ" + }, + "security": { + "message": "ಭದ್ರತೆ" + }, + "clearClipboard": { + "message": "ಕ್ಲಿಪ್‌ಬೋರ್ಡ್ ತೆರವುಗೊಳಿಸಿ", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "ನಿಮ್ಮ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಿಂದ ನಕಲಿಸಿದ ಮೌಲ್ಯಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆರವುಗೊಳಿಸಿ.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "ವೆಬ್‌ಸೈಟ್ ಚಿಹ್ನೆಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + }, + "disableFaviconDesc": { + "message": "ವೆಬ್‌ಸೈಟ್ ಐಕಾನ್‌ಗಳು ನಿಮ್ಮ ವಾಲ್ಟ್‌ನಲ್ಲಿರುವ ಪ್ರತಿ ಲಾಗಿನ್ ಐಟಂನ ಪಕ್ಕದಲ್ಲಿ ಗುರುತಿಸಬಹುದಾದ ಚಿತ್ರವನ್ನು ಒದಗಿಸುತ್ತದೆ." + }, + "enableMinToTray": { + "message": "ಟ್ರೇ ಐಕಾನ್‌ಗೆ ಕಡಿಮೆ ಮಾಡಿ" + }, + "enableMinToTrayDesc": { + "message": "ವಿಂಡೋವನ್ನು ಕಡಿಮೆ ಮಾಡುವಾಗ, ಸಿಸ್ಟಮ್ ಟ್ರೇನಲ್ಲಿ ಐಕಾನ್ ಅನ್ನು ತೋರಿಸಿ." + }, + "enableMinToMenuBar": { + "message": "ಮೆನು ಬಾರ್‌ಗೆ ಕಡಿಮೆ ಮಾಡಿ" + }, + "enableMinToMenuBarDesc": { + "message": "ವಿಂಡೋವನ್ನು ಕಡಿಮೆ ಮಾಡುವಾಗ, ಬದಲಿಗೆ ಮೆನು ಬಾರ್‌ನಲ್ಲಿ ಐಕಾನ್ ತೋರಿಸಿ." + }, + "enableCloseToTray": { + "message": "ಟ್ರೇ ಐಕಾನ್ ಹತ್ತಿರ" + }, + "enableCloseToTrayDesc": { + "message": "ವಿಂಡೋವನ್ನು ಮುಚ್ಚುವಾಗ, ಸಿಸ್ಟಮ್ ಟ್ರೇನಲ್ಲಿ ಐಕಾನ್ ಅನ್ನು ತೋರಿಸಿ." + }, + "enableCloseToMenuBar": { + "message": "ಮೆನು ಬಾರ್‌ಗೆ ಹತ್ತಿರದಲ್ಲಿದೆ" + }, + "enableCloseToMenuBarDesc": { + "message": "ವಿಂಡೋವನ್ನು ಮುಚ್ಚುವಾಗ, ಬದಲಿಗೆ ಮೆನು ಬಾರ್‌ನಲ್ಲಿ ಐಕಾನ್ ತೋರಿಸಿ." + }, + "enableTray": { + "message": "ಟ್ರೇ ಐಕಾನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ" + }, + "enableTrayDesc": { + "message": "ಸಿಸ್ಟಮ್ ಟ್ರೇನಲ್ಲಿ ಯಾವಾಗಲೂ ಐಕಾನ್ ತೋರಿಸಿ." + }, + "startToTray": { + "message": "ಐಕಾನ್ ಟ್ರೇ ಮಾಡಲು ಪ್ರಾರಂಭಿಸಿ" + }, + "startToTrayDesc": { + "message": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮೊದಲು ಪ್ರಾರಂಭಿಸಿದಾಗ, ಸಿಸ್ಟಮ್ ಟ್ರೇನಲ್ಲಿ ಐಕಾನ್ ಅನ್ನು ಮಾತ್ರ ತೋರಿಸಿ." + }, + "startToMenuBar": { + "message": "ಮೆನು ಬಾರ್‌ಗೆ ಪ್ರಾರಂಭಿಸಿ" + }, + "startToMenuBarDesc": { + "message": "ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮೊದಲು ಪ್ರಾರಂಭಿಸಿದಾಗ, ಮೆನು ಬಾರ್‌ನಲ್ಲಿ ಐಕಾನ್ ಅನ್ನು ಮಾತ್ರ ತೋರಿಸಿ." + }, + "openAtLogin": { + "message": "ಲಾಗಿನ್‌ನಲ್ಲಿ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಪ್ರಾರಂಭಿಸಿ" + }, + "openAtLoginDesc": { + "message": "ಲಾಗಿನ್‌ನಲ್ಲಿ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಡೆಸ್ಕ್‌ಟಾಪ್ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಪ್ರಾರಂಭಿಸಿ." + }, + "alwaysShowDock": { + "message": "ಯಾವಾಗಲೂ ಡಾಕ್‌ನಲ್ಲಿ ತೋರಿಸಿ" + }, + "alwaysShowDockDesc": { + "message": "ಮೆನು ಬಾರ್‌ಗೆ ಕಡಿಮೆಗೊಳಿಸಿದಾಗಲೂ ಡಾಕ್‌ನಲ್ಲಿ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಐಕಾನ್ ತೋರಿಸಿ." + }, + "confirmTrayTitle": { + "message": "ಟ್ರೇ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುವುದನ್ನು ದೃಢೀಕರಿಸಿ" + }, + "confirmTrayDesc": { + "message": "ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುವುದರಿಂದ ಇತರ ಎಲ್ಲಾ ಟ್ರೇ ಸಂಬಂಧಿತ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಸಹ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ." + }, + "language": { + "message": "ಭಾಷೆ" + }, + "languageDesc": { + "message": "ಅಪ್ಲಿಕೇಶನ್ ಬಳಸುವ ಭಾಷೆಯನ್ನು ಬದಲಾಯಿಸಿ. ಮರುಪ್ರಾರಂಭಿಸುವ ಅಗತ್ಯವಿದೆ." + }, + "theme": { + "message": "ಥೀಮ್ಸ್" + }, + "themeDesc": { + "message": "ಅಪ್ಲಿಕೇಶನ್‌ನ ಬಣ್ಣ ಥೀಮ್ ಅನ್ನು ಬದಲಾಯಿಸಿ." + }, + "dark": { + "message": "ಡಾರ್ಕ್", + "description": "Dark color" + }, + "light": { + "message": "ಬೆಳಕು", + "description": "Light color" + }, + "copy": { + "message": "ನಕಲಿಸಿ", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "ನವೀಕರಣೆಗಳಿಗಾಗಿ ಪರೀಕ್ಷಿಸಿ" + }, + "version": { + "message": "ಸಂವಹನ $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "ನವೀಕರಿಸಲು ಮರುಪ್ರಾರಂಭಿಸಿ" + }, + "restartToUpdateDesc": { + "message": "ಆವೃತ್ತಿ $VERSION_NUM$ ಸ್ಥಾಪಿಸಲು ಸಿದ್ಧವಾಗಿದೆ. ಅನುಸ್ಥಾಪನೆಯನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ನೀವು ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಬೇಕು. ನೀವು ಈಗ ಮರುಪ್ರಾರಂಭಿಸಲು ಮತ್ತು ನವೀಕರಿಸಲು ಬಯಸುವಿರಾ?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "ನವೀಕರಣ ಲಭ್ಯವಿದೆ" + }, + "updateAvailableDesc": { + "message": "ಒಂದು ಅಪ್ಡೇಟ್ ಕಂಡುಬಂದಿದೆ. ನೀವು ಈಗ ಅದನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲು ಬಯಸುತ್ತೀರಾ?" + }, + "restart": { + "message": "ಪುನರಾರಂಭ" + }, + "later": { + "message": "ನಂತರ" + }, + "noUpdatesAvailable": { + "message": "ಯಾವುದೇ ನವೀಕರಣಗಳು ಪ್ರಸ್ತುತ ಲಭ್ಯವಿಲ್ಲ. ನೀವು ಇತ್ತೀಚಿನ ಆವೃತ್ತಿಯನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ." + }, + "updateError": { + "message": "ದೋಷವನ್ನು ನವೀಕರಿಸಿ" + }, + "unknown": { + "message": "ಅಪರಿಚಿತ" + }, + "copyUsername": { + "message": "ಬಳಕೆಹೆಸರು ನಕಲಿಸು" + }, + "copyNumber": { + "message": "ನಕಲು ಸಂಖ್ಯೆ", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "ಭದ್ರತಾ ಕೋಡ್ ಅನ್ನು ನಕಲಿಸಿ", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವ" + }, + "premiumManage": { + "message": "ಸದಸ್ಯತ್ವವನ್ನು ನಿರ್ವಹಿಸಿ" + }, + "premiumManageAlert": { + "message": "ನಿಮ್ಮ ಸದಸ್ಯತ್ವವನ್ನು ನೀವು bitwarden.com ವೆಬ್ ವಾಲ್ಟ್‌ನಲ್ಲಿ ನಿರ್ವಹಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "premiumRefresh": { + "message": "ಸದಸ್ಯತ್ವವನ್ನು ರಿಫ್ರೆಶ್ ಮಾಡಿ" + }, + "premiumNotCurrentMember": { + "message": "ನೀವು ಪ್ರಸ್ತುತ ಪ್ರೀಮಿಯಂ ಸದಸ್ಯರಲ್ಲ." + }, + "premiumSignUpAndGet": { + "message": "ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವಕ್ಕಾಗಿ ಸೈನ್ ಅಪ್ ಮಾಡಿ ಮತ್ತು ಪಡೆಯಿರಿ:" + }, + "premiumSignUpStorage": { + "message": "ಫೈಲ್ ಲಗತ್ತುಗಳಿಗಾಗಿ 1 ಜಿಬಿ ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ಸಂಗ್ರಹ." + }, + "premiumSignUpTwoStep": { + "message": "ಹೆಚ್ಚುವರಿ ಎರಡು-ಹಂತದ ಲಾಗಿನ್ ಆಯ್ಕೆಗಳಾದ ಯೂಬಿಕೆ, ಎಫ್‌ಐಡಿಒ ಯು 2 ಎಫ್, ಮತ್ತು ಡ್ಯುವೋ." + }, + "premiumSignUpReports": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಅನ್ನು ಸುರಕ್ಷಿತವಾಗಿರಿಸಲು ಪಾಸ್ವರ್ಡ್ ನೈರ್ಮಲ್ಯ, ಖಾತೆ ಆರೋಗ್ಯ ಮತ್ತು ಡೇಟಾ ಉಲ್ಲಂಘನೆ ವರದಿಗಳು." + }, + "premiumSignUpTotp": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್‌ನಲ್ಲಿನ ಲಾಗಿನ್‌ಗಳಿಗಾಗಿ TOTP ಪರಿಶೀಲನಾ ಕೋಡ್ (2FA) ಜನರೇಟರ್." + }, + "premiumSignUpSupport": { + "message": "ಆದ್ಯತೆಯ ಗ್ರಾಹಕ ಬೆಂಬಲ." + }, + "premiumSignUpFuture": { + "message": "ಎಲ್ಲಾ ಭವಿಷ್ಯದ ಪ್ರೀಮಿಯಂ ವೈಶಿಷ್ಟ್ಯಗಳು. ಹೆಚ್ಚು ಶೀಘ್ರದಲ್ಲೇ ಬರಲಿದೆ!" + }, + "premiumPurchase": { + "message": "ಪ್ರೀಮಿಯಂ ಖರೀದಿಸಿ" + }, + "premiumPurchaseAlert": { + "message": "ನೀವು ಬಿಟ್ವಾರ್ಡೆನ್.ಕಾಮ್ ವೆಬ್ ವಾಲ್ಟ್ನಲ್ಲಿ ಪ್ರೀಮಿಯಂ ಸದಸ್ಯತ್ವವನ್ನು ಖರೀದಿಸಬಹುದು. ನೀವು ಈಗ ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "premiumCurrentMember": { + "message": "ನೀವು ಪ್ರೀಮಿಯಂ ಸದಸ್ಯರಾಗಿದ್ದೀರಿ!" + }, + "premiumCurrentMemberThanks": { + "message": "ಬಿಟ್ವಾರ್ಡೆನ್ ಅವರನ್ನು ಬೆಂಬಲಿಸಿದ್ದಕ್ಕಾಗಿ ಧನ್ಯವಾದಗಳು." + }, + "premiumPrice": { + "message": "ಎಲ್ಲವೂ ಕೇವಲ $PRICE$ / ವರ್ಷಕ್ಕೆ!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "ರಿಫ್ರೆಶ್ ಪೂರ್ಣಗೊಂಡಿದೆ" + }, + "passwordHistory": { + "message": "ಪಾಸ್ವರ್ಡ್ ಇತಿಹಾಸ" + }, + "clear": { + "message": "ಕ್ಲಿಯರ್‌", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "ಪಟ್ಟಿ ಮಾಡಲು ಯಾವುದೇ ಪಾಸ್ವರ್ಡ್ಗಳು ಇಲ್ಲ." + }, + "undo": { + "message": "ರದ್ದುಮಾಡು" + }, + "redo": { + "message": "ಮತ್ತೆಮಾಡು" + }, + "cut": { + "message": "ಕತ್ತರಿಸು", + "description": "Cut to clipboard" + }, + "paste": { + "message": "ಅಂಟಿಸಿ", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "ಎಲ್ಲವನ್ನು ಆರಿಸು" + }, + "zoomIn": { + "message": "ಗಾತ್ರ ಹಿಗ್ಗಿಸಿ" + }, + "zoomOut": { + "message": "ಗಾತ್ರ ಕುಗ್ಗಿಸಿ" + }, + "resetZoom": { + "message": "ಜೂಮ್ ಮರುಹೊಂದಿಸಿ" + }, + "toggleFullScreen": { + "message": "ಟಾಗಲ್ ಫುಲ್ ಸ್ಕ್ರೀನ್" + }, + "reload": { + "message": "ಮರುತುಂಬಿಸು" + }, + "toggleDevTools": { + "message": "ಡೆವೆಲಪರ್ ಟೂಲ್ಸ್ನ ಸ್ವಿಚ್ ಮಾಡಿ" + }, + "minimize": { + "message": "ಕನಿಷ್ಟ ಮಾಡಿ", + "description": "Minimize window" + }, + "zoom": { + "message": "ಝೂಮ್" + }, + "bringAllToFront": { + "message": "ಎಲ್ಲಾವನ್ನು ಮುಂದೆ ತನ್ನಿ", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "ಬಿಟ್ವಾರ್ಡನ್ ಬಗ್ಗೆ" + }, + "services": { + "message": "ಸೇವೆಗಳು" + }, + "hideBitwarden": { + "message": "ಬಿಟ್ವಾರ್ಡೆನ್ ಅನ್ನು ಮರೆಮಾಡಿ" + }, + "hideOthers": { + "message": "ಬೇರೆಲ್ಲವನ್ನೂ ಮರೆಮಾಚು" + }, + "showAll": { + "message": "ಎಲ್ಲಾ ತೋರಿಸಿ" + }, + "quitBitwarden": { + "message": "ಬಿಟ್ವಾರ್ಡೆನ್ ಬಿಟ್ಟುಬಿಡಿ" + }, + "valueCopied": { + "message": "$VALUE$ ನಕಲಿಸಲಾಗಿದೆ", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "ಸಹಾಯ" + }, + "window": { + "message": "ಕಿಟಕಿ" + }, + "checkPassword": { + "message": "ಪಾಸ್ವರ್ಡ್ ಬಹಿರಂಗಗೊಂಡಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ." + }, + "passwordExposed": { + "message": "ಈ ಗುಪ್ತಪದವು ಡೇಟಾ ಉಲ್ಲಂಘನೆಯಲ್ಲಿ $VALUE$ ಮೌಲ್ಯವನ್ನು (ಗಳು) ಬಹಿರಂಗಪಡಿಸಲಾಗಿದೆ. ನೀವು ಅದನ್ನು ಬದಲಾಯಿಸಬೇಕು.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "ತಿಳಿದಿರುವ ಯಾವುದೇ ಡೇಟಾ ಉಲ್ಲಂಘನೆಗಳಲ್ಲಿ ಈ ಪಾಸ್‌ವರ್ಡ್ ಕಂಡುಬಂದಿಲ್ಲ. ಅದನ್ನು ಬಳಸಲು ಸುರಕ್ಷಿತವಾಗಿರಬೇಕು." + }, + "baseDomain": { + "message": "ಮೂಲ ಡೊಮೇನ್", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "ಅತಿಥೆಯ", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "ನಿಖರವಾಗಿ" + }, + "startsWith": { + "message": "ಇದರೊಂದಿಗೆ ಪ್ರಾರಂಭವಾಗುತ್ತದೆ" + }, + "regEx": { + "message": "ನಿಯಮಿತ ಅಭಿವ್ಯಕ್ತಿ", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "ಹೊಂದಾಣಿಕೆ ಪತ್ತೆ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "ಡೀಫಾಲ್ಟ್ ಪಂದ್ಯ ಪತ್ತೆ", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "ಟಾಗಲ್ ಆಯ್ಕೆಗಳು" + }, + "organization": { + "message": "ಸಂಸ್ಥೆ", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "ಡಿಫಾಲ್ಟ್" + }, + "exit": { + "message": "ನಿರ್ಗಮಿಸು" + }, + "showHide": { + "message": "ತೋರಿಸು / ಮರೆಮಾಡಿ", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "ಟ್ರೇಗೆ ಮರೆಮಾಡಿ" + }, + "alwaysOnTop": { + "message": "ಯಾವಾಗಲೂ ಮೇಲೆ", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "ಅಪ್‌ಡೇಟ್", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "ಪಾಸ್ವರ್ಡ್ ನವೀಕರಿಸಲಾಗಿದೆ", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "ರಫ್ತು ವಾಲ್ಟ್" + }, + "fileFormat": { + "message": "ಕಡತದ ಮಾದರಿ" + }, + "warning": { + "message": "ಎಚ್ಚರಿಕೆ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "ವಾಲ್ಟ್ ರಫ್ತು ಖಚಿತಪಡಿಸಿ" + }, + "exportWarningDesc": { + "message": "ಈ ರಫ್ತು ನಿಮ್ಮ ವಾಲ್ಟ್ ಡೇಟಾವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡದ ಸ್ವರೂಪದಲ್ಲಿ ಒಳಗೊಂಡಿದೆ. ನೀವು ರಫ್ತು ಮಾಡಿದ ಫೈಲ್ ಅನ್ನು ಅಸುರಕ್ಷಿತ ಚಾನಲ್‌ಗಳಲ್ಲಿ (ಇಮೇಲ್ ನಂತಹ) ಸಂಗ್ರಹಿಸಬಾರದು ಅಥವಾ ಕಳುಹಿಸಬಾರದು. ನೀವು ಅದನ್ನು ಬಳಸಿದ ನಂತರ ಅದನ್ನು ಅಳಿಸಿ." + }, + "encExportKeyWarningDesc": { + "message": "ಈ ರಫ್ತು ನಿಮ್ಮ ಖಾತೆಯ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಲಿಯನ್ನು ಬಳಸಿಕೊಂಡು ನಿಮ್ಮ ಡೇಟಾವನ್ನು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡುತ್ತದೆ. ನಿಮ್ಮ ಖಾತೆಯ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಲಿಯನ್ನು ನೀವು ಎಂದಾದರೂ ತಿರುಗಿಸಿದರೆ ನೀವು ಈ ರಫ್ತು ಫೈಲ್ ಅನ್ನು ಡೀಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗದ ಕಾರಣ ನೀವು ಮತ್ತೆ ರಫ್ತು ಮಾಡಬೇಕು." + }, + "encExportAccountWarningDesc": { + "message": "ಖಾತೆ ಎನ್‌ಕ್ರಿಪ್ಶನ್ ಕೀಗಳು ಪ್ರತಿ ಬಿಟ್‌ವಾರ್ಡೆನ್ ಬಳಕೆದಾರ ಖಾತೆಗೆ ಅನನ್ಯವಾಗಿವೆ, ಆದ್ದರಿಂದ ನೀವು ಎನ್‌ಕ್ರಿಪ್ಟ್ ಮಾಡಿದ ರಫ್ತು ಬೇರೆ ಖಾತೆಗೆ ಆಮದು ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ." + }, + "noOrganizationsList": { + "message": "ನೀವು ಯಾವುದೇ ಸಂಸ್ಥೆಗಳಿಗೆ ಸೇರಿಲ್ಲ. ಇತರ ಬಳಕೆದಾರರೊಂದಿಗೆ ವಸ್ತುಗಳನ್ನು ಸುರಕ್ಷಿತವಾಗಿ ಹಂಚಿಕೊಳ್ಳಲು ಸಂಘಟನೆಗಳು ನಿಮಗೆ ಅವಕಾಶ ನೀಡುತ್ತವೆ." + }, + "noCollectionsInList": { + "message": "ಪಟ್ಟಿ ಮಾಡಲು ಯಾವುದೇ ಸಂಗ್ರಹಗಳಿಲ್ಲ." + }, + "ownership": { + "message": "ಮಾಲೀಕತ್ವ" + }, + "whoOwnsThisItem": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಯಾರು ಹೊಂದಿದ್ದಾರೆ?" + }, + "strong": { + "message": "ಬಲಶಾಲಿ", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "ಒಳ್ಳೆಯ", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "ದುರ್ಬಲ", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "ದುರ್ಬಲ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್" + }, + "weakMasterPasswordDesc": { + "message": "ನೀವು ಆಯ್ಕೆ ಮಾಡಿದ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ದುರ್ಬಲವಾಗಿದೆ. ನಿಮ್ಮ ಬಿಟ್ವರ್ಡ್ ಖಾತೆಯನ್ನು ಸರಿಯಾಗಿ ರಕ್ಷಿಸಲು ನೀವು ಬಲವಾದ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ (ಅಥವಾ ಪಾಸ್ಫ್ರೇಸ್) ಅನ್ನು ಬಳಸಬೇಕು. ಈ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ನೀವು ಬಳಸಲು ಬಯಸುತ್ತೀರಾ?" + }, + "pin": { + "message": "ಪಿನ್", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "ಪಿನ್‌ನೊಂದಿಗೆ ಅನ್ಲಾಕ್ ಮಾಡಿ" + }, + "setYourPinCode": { + "message": "ಬಿಟ್‌ವಾರ್ಡೆನ್ ಅನ್ಲಾಕ್ ಮಾಡಲು ನಿಮ್ಮ ಪಿನ್ ಕೋಡ್ ಅನ್ನು ಹೊಂದಿಸಿ. ನೀವು ಎಂದಾದರೂ ಅಪ್ಲಿಕೇಶನ್‌ನಿಂದ ಸಂಪೂರ್ಣವಾಗಿ ಲಾಗ್ ಔಟ್ ಆಗಿದ್ದರೆ ನಿಮ್ಮ ಪಿನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಮರುಹೊಂದಿಸಲಾಗುತ್ತದೆ." + }, + "pinRequired": { + "message": "ಪಿನ್ ಕೋಡ್ ಅಗತ್ಯವಿದೆ." + }, + "invalidPin": { + "message": "ಅಮಾನ್ಯ ಪಿನ್ ಕೋಡ್." + }, + "unlockWithWindowsHello": { + "message": "ವಿಂಡೋಸ್ ಹಲೋನೊಂದಿಗೆ ಅನ್ಲಾಕ್ ಮಾಡಿ" + }, + "windowsHelloConsentMessage": { + "message": "ಬಿಟ್‌ವಾರ್ಡೆನ್‌ಗಾಗಿ ಪರಿಶೀಲಿಸಿ." + }, + "unlockWithTouchId": { + "message": "ಟಚ್ ಐಡಿ ಯೊಂದಿಗೆ ಅನ್ಲಾಕ್ ಮಾಡಿ" + }, + "touchIdConsentMessage": { + "message": "ನಿಮ್ಮ ವಾಲ್ಟ್ ಅನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಿ" + }, + "noAutoPromptWindowsHello": { + "message": "ಪ್ರಾರಂಭದಲ್ಲಿ ವಿಂಡೋಸ್ ಹಲೋಗಾಗಿ ಕೇಳಬೇಡಿ." + }, + "noAutoPromptTouchId": { + "message": "ಪ್ರಾರಂಭದಲ್ಲಿ ಟಚ್ ಐಡಿಗಾಗಿ ಕೇಳಬೇಡಿ." + }, + "lockWithMasterPassOnRestart": { + "message": "ಮರುಪ್ರಾರಂಭಿಸಿದಾಗ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್‌ನೊಂದಿಗೆ ಲಾಕ್ ಮಾಡಿ" + }, + "preferences": { + "message": "ಆದ್ಯತೆಗಳು" + }, + "enableMenuBar": { + "message": "ಮೆನು ಬಾರ್ ಐಕಾನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ" + }, + "enableMenuBarDesc": { + "message": "ಮೆನು ಬಾರ್‌ನಲ್ಲಿ ಯಾವಾಗಲೂ ಐಕಾನ್ ತೋರಿಸಿ." + }, + "hideToMenuBar": { + "message": "ಮೆನು ಬಾರ್‌ಗೆ ಮರೆಮಾಡಿ" + }, + "selectOneCollection": { + "message": "ನೀವು ಕನಿಷ್ಠ ಒಂದು ಸಂಗ್ರಹವನ್ನು ಆರಿಸಬೇಕು." + }, + "premiumUpdated": { + "message": "ನೀವು ಪ್ರೀಮಿಯಂಗೆ ಅಪ್‌ಗ್ರೇಡ್ ಮಾಡಿದ್ದೀರಿ." + }, + "restore": { + "message": "ಪುನಸ್ಥಾಪಿಸಿ" + }, + "premiumManageAlertAppStore": { + "message": "ಆಪ್ ಸ್ಟೋರ್‌ನಿಂದ ನಿಮ್ಮ ಚಂದಾದಾರಿಕೆಯನ್ನು ನೀವು ನಿರ್ವಹಿಸಬಹುದು. ನೀವು ಈಗ ಆಪ್ ಸ್ಟೋರ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಬಯಸುವಿರಾ?" + }, + "legal": { + "message": "ಕಾನೂನು", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "ಸೇವಾ ನಿಯಮಗಳು" + }, + "privacyPolicy": { + "message": "ಗೌಪ್ಯತಾ ನೀತಿ" + }, + "unsavedChangesConfirmation": { + "message": "ನೀವು ಬಿಡಲು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ? ನೀವು ಈಗ ಹೊರಟು ಹೋದರೆ ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಮಾಹಿತಿಯನ್ನು ಉಳಿಸಲಾಗುವುದಿಲ್ಲ." + }, + "unsavedChangesTitle": { + "message": "ಉಳಿಸದ ಬದಲಾವಣೆಗಳು" + }, + "clone": { + "message": "ಕ್ಲೋನ್" + }, + "passwordGeneratorPolicyInEffect": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಸ್ಥೆ ನೀತಿಗಳು ನಿಮ್ಮ ಜನರೇಟರ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತವೆ." + }, + "vaultTimeoutAction": { + "message": "ವಾಲ್ಟ್ ಸಮಯ ಮೀರುವ ಕ್ರಿಯೆ" + }, + "vaultTimeoutActionLockDesc": { + "message": "ಲಾಕ್ ಮಾಡಿದ ವಾಲ್ಟ್‌ಗೆ ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮತ್ತೆ ಪ್ರವೇಶಿಸಲು ನೀವು ಅದನ್ನು ಮರು ನಮೂದಿಸುವ ಅಗತ್ಯವಿದೆ." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "ಲಾಗ್ out ಟ್ ವಾಲ್ಟ್‌ಗೆ ನೀವು ಅದನ್ನು ಮತ್ತೆ ಪ್ರವೇಶಿಸಲು ಮರು ದೃಢೀಕರಿಸುವ ಅಗತ್ಯವಿದೆ." + }, + "lock": { + "message": "ಲಾಕ್‌", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "ಅನುಪಯುಕ್ತ", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "ಅನುಪಯುಕ್ತವನ್ನು ಹುಡುಕಿ" + }, + "permanentlyDeleteItem": { + "message": "ಐಟಂ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಿ" + }, + "permanentlyDeleteItemConfirmation": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "permanentlyDeletedItem": { + "message": "ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಲಾದ ಐಟಂ" + }, + "restoreItem": { + "message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಿ" + }, + "restoreItemConfirmation": { + "message": "ಈ ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "restoredItem": { + "message": "ಐಟಂ ಅನ್ನು ಮರುಸ್ಥಾಪಿಸಲಾಗಿದೆ" + }, + "permanentlyDelete": { + "message": "ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಿ" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "ಲಾಗ್ out ಟ್ ಆಗುವುದರಿಂದ ನಿಮ್ಮ ವಾಲ್ಟ್‌ನ ಎಲ್ಲಾ ಪ್ರವೇಶವನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ ಮತ್ತು ಕಾಲಾವಧಿ ಅವಧಿಯ ನಂತರ ಆನ್‌ಲೈನ್ ದೃ hentic ೀಕರಣದ ಅಗತ್ಯವಿದೆ. ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬಳಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "ಕಾಲಾವಧಿ ಕ್ರಿಯೆಯ ದೃಢೀಕರಣ" + }, + "enterpriseSingleSignOn": { + "message": "ಎಂಟರ್‌ಪ್ರೈಸ್ ಏಕ ಸೈನ್-ಆನ್" + }, + "setMasterPassword": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಹೊಂದಿಸಿ" + }, + "ssoCompleteRegistration": { + "message": "ಎಸ್‌ಎಸ್‌ಒನೊಂದಿಗೆ ಲಾಗಿನ್ ಆಗುವುದನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು, ದಯವಿಟ್ಟು ನಿಮ್ಮ ವಾಲ್ಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಮತ್ತು ರಕ್ಷಿಸಲು ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಹೊಂದಿಸಿ." + }, + "newMasterPass": { + "message": "ಹೊಸ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್" + }, + "confirmNewMasterPass": { + "message": "ಹೊಸ ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ದೃಢೀಕರಣ" + }, + "masterPasswordPolicyInEffect": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಸ್ಥೆ ನೀತಿಗಳಿಗೆ ಈ ಕೆಳಗಿನ ಅವಶ್ಯಕತೆಗಳನ್ನು ಪೂರೈಸಲು ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅಗತ್ಯವಿದೆ:" + }, + "policyInEffectMinComplexity": { + "message": "$SCORE$ ನ ಕನಿಷ್ಠ ಸಂಕೀರ್ಣತೆಯ ಸ್ಕೋರ್", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "$LENGTH$ನ ಕನಿಷ್ಠ ಉದ್ದ", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ದೊಡ್ಡಕ್ಷರಗಳನ್ನು ಹೊಂದಿರುತ್ತದೆ" + }, + "policyInEffectLowercase": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಣ್ಣ ಅಕ್ಷರಗಳನ್ನು ಹೊಂದಿರುತ್ತದೆ" + }, + "policyInEffectNumbers": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಖ್ಯೆಗಳನ್ನು ಹೊಂದಿರುತ್ತದೆ" + }, + "policyInEffectSpecial": { + "message": "ಕೆಳಗಿನ ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ವಿಶೇಷ ಅಕ್ಷರಗಳನ್ನು ಒಳಗೊಂಡಿರುತ್ತದೆ: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "ನಿಮ್ಮ ಹೊಸ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ನೀತಿಯ ಅವಶ್ಯಕತೆಗಳನ್ನು ಪೂರೈಸುವುದಿಲ್ಲ." + }, + "acceptPolicies": { + "message": "ಈ ಪೆಟ್ಟಿಗೆಯನ್ನು ಪರಿಶೀಲಿಸುವ ಮೂಲಕ ನೀವು ಈ ಕೆಳಗಿನವುಗಳನ್ನು ಒಪ್ಪುತ್ತೀರಿ:" + }, + "acceptPoliciesError": { + "message": "ಸೇವಾ ನಿಯಮಗಳು ಮತ್ತು ಗೌಪ್ಯತೆ ನೀತಿಯನ್ನು ಅಂಗೀಕರಿಸಲಾಗಿಲ್ಲ." + }, + "enableBrowserIntegration": { + "message": "ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ" + }, + "enableBrowserIntegrationDesc": { + "message": "ಬ್ರೌಸರ್ನಲ್ಲಿ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ಗಾಗಿ ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಬಳಸಲಾಗುತ್ತದೆ." + }, + "browserIntegrationMasOnlyTitle": { + "message": "ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ" + }, + "browserIntegrationMasOnlyDesc": { + "message": "ದುರದೃಷ್ಟವಶಾತ್ ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಇದೀಗ ಮ್ಯಾಕ್ ಆಪ್ ಸ್ಟೋರ್ ಆವೃತ್ತಿಯಲ್ಲಿ ಮಾತ್ರ ಬೆಂಬಲಿಸಲಾಗುತ್ತದೆ." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "ದುರದೃಷ್ಟವಶಾತ್ ವಿಂಡೋಸ್ ಸ್ಟೋರ್ ಆವೃತ್ತಿಯಲ್ಲಿ ಬ್ರೌಸರ್ ಏಕೀಕರಣವನ್ನು ಪ್ರಸ್ತುತ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ." + }, + "enableBrowserIntegrationFingerprint": { + "message": "ಬ್ರೌಸರ್ ಏಕೀಕರಣಕ್ಕಾಗಿ ಪರಿಶೀಲನೆ ಅಗತ್ಯವಿದೆ" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "ನಿಮ್ಮ ಡೆಸ್ಕ್‌ಟಾಪ್ ಮತ್ತು ಬ್ರೌಸರ್ ನಡುವೆ ಲಿಂಕ್ ಅನ್ನು ಸ್ಥಾಪಿಸುವಾಗ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಪದಗುಚ್ ಕಾಯಂಗೊಳಿಸುವಿಕೆ ಅಗತ್ಯವಿರುವ ಮೂಲಕ ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಯ ಪದರವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ. ಸಕ್ರಿಯಗೊಳಿಸಿದಾಗ, ಪ್ರತಿ ಬಾರಿ ಸಂಪರ್ಕವನ್ನು ಸ್ಥಾಪಿಸಿದಾಗ ಬಳಕೆದಾರರ ಹಸ್ತಕ್ಷೇಪ ಮತ್ತು ಪರಿಶೀಲನೆ ಅಗತ್ಯವಾಗಿರುತ್ತದೆ." + }, + "approve": { + "message": "ಅನುಮೋದಿಸಿದೆ" + }, + "verifyBrowserTitle": { + "message": "ಬ್ರೌಸರ್ ಸಂಪರ್ಕವನ್ನು ಪರಿಶೀಲಿಸಿ" + }, + "verifyBrowserDesc": { + "message": "ತೋರಿಸಿದ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬ್ರೌಸರ್ ವಿಸ್ತರಣೆಯಲ್ಲಿ ತೋರಿಸಿರುವ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್‌ಗೆ ಹೋಲುತ್ತದೆ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ." + }, + "biometricsNotEnabledTitle": { + "message": "ಬಯೊಮಿಟ್ರಿಕ್ಸ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿಲ್ಲ" + }, + "biometricsNotEnabledDesc": { + "message": "ಬ್ರೌಸರ್ ಬಯೋಮೆಟ್ರಿಕ್ಸ್ ಮೊದಲು ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಡೆಸ್ಕ್ಟಾಪ್ ಬಯೋಮೆಟ್ರಿಕ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕಾಗುತ್ತದೆ." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ಸುಳಿವು ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್‌ನಂತೆಯೇ ಇರಬಾರದು." + }, + "personalOwnershipPolicyInEffect": { + "message": "ಸಂಸ್ಥೆಯ ನೀತಿಯು ನಿಮ್ಮ ಮಾಲೀಕತ್ವದ ಆಯ್ಕೆಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತಿದೆ." + }, + "allSends": { + "message": "ಎಲ್ಲಾ ಕಳುಹಿಸುತ್ತದೆ", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "ಫೈಲ್" + }, + "sendTypeText": { + "message": "ಪಠ್ಯ" + }, + "searchSends": { + "message": "ಹುಡುಕಾಟ ಕಳುಹಿಸುತ್ತದೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "ಕಳುಹಿಸು ಸಂಪಾದಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "ನನ್ನ ವಾಲ್ಟ್" + }, + "text": { + "message": "ಪಠ್ಯ" + }, + "deletionDate": { + "message": "ಅಳಿಸುವ ದಿನಾಂಕ" + }, + "deletionDateDesc": { + "message": "ಕಳುಹಿಸಿದ ದಿನಾಂಕ ಮತ್ತು ಸಮಯದ ಮೇಲೆ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಶಾಶ್ವತವಾಗಿ ಅಳಿಸಲಾಗುತ್ತದೆ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "ಮುಕ್ತಾಯ ದಿನಾಂಕ" + }, + "expirationDateDesc": { + "message": "ಹೊಂದಿಸಿದ್ದರೆ, ಈ ಕಳುಹಿಸುವಿಕೆಯ ಪ್ರವೇಶವು ನಿಗದಿತ ದಿನಾಂಕ ಮತ್ತು ಸಮಯದ ಮೇಲೆ ಮುಕ್ತಾಯಗೊಳ್ಳುತ್ತದೆ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "ಗರಿಷ್ಠ ಪ್ರವೇಶ ಎಣಿಕೆ" + }, + "maxAccessCountDesc": { + "message": "ಹೊಂದಿಸಿದ್ದರೆ, ಗರಿಷ್ಠ ಪ್ರವೇಶ ಎಣಿಕೆ ತಲುಪಿದ ನಂತರ ಬಳಕೆದಾರರಿಗೆ ಈ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಾಗುವುದಿಲ್ಲ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "ಪ್ರಸ್ತುತ ಪ್ರವೇಶ ಎಣಿಕೆ" + }, + "disableSend": { + "message": "ಇದನ್ನು ಕಳುಹಿಸುವುದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ ಇದರಿಂದ ಯಾರೂ ಅದನ್ನು ಪ್ರವೇಶಿಸಲಾಗುವುದಿಲ್ಲ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "ಈ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಪ್ರವೇಶಿಸಲು ಬಳಕೆದಾರರಿಗೆ ಪಾಸ್‌ವರ್ಡ್ ಐಚ್ ಗತ್ಯವಿದೆ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "ಈ ಕಳುಹಿಸುವ ಬಗ್ಗೆ ಖಾಸಗಿ ಟಿಪ್ಪಣಿಗಳು.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "ಲಿಂಕ್ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "ಲಿಂಕ್ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಪ್ರವೇಶಿಸುವಾಗ, ಪಠ್ಯವನ್ನು ಪೂರ್ವನಿಯೋಜಿತವಾಗಿ ಮರೆಮಾಡಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "ಕಳುಹಿಸು ರಚಿಸಲಾಗಿದೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "ಕಳುಹಿಸಿದ ಸಂಪಾದನೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "ಅಳಿಸಿದ ಕಳುಹಿಸಲಾಗಿದೆ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "ಹೊಸ ಪಾಸ್‌ವರ್ಡ್" + }, + "whatTypeOfSend": { + "message": "ಇದು ಯಾವ ರೀತಿಯ ಕಳುಹಿಸುತ್ತದೆ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "ಕಳುಹಿಸು ರಚಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "ನೀವು ಕಳುಹಿಸಲು ಬಯಸುವ ಪಠ್ಯ." + }, + "sendFileDesc": { + "message": "ನೀವು ಕಳುಹಿಸಲು ಬಯಸುವ ಫೈಲ್." + }, + "days": { + "message": "$DAYS$ ದಿನಗಳು", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 ದಿನ" + }, + "custom": { + "message": "ಕಸ್ಟಮ್" + }, + "deleteSendConfirmation": { + "message": "ಈ ಕಳುಹಿಸುವಿಕೆಯನ್ನು ಅಳಿಸಲು ನೀವು ಖಚಿತವಾಗಿ ಬಯಸುವಿರಾ?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "ನಕಲಿಸಿ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ಲಿಂಕ್ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "ಇದನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಲಿಂಕ್ ಅನ್ನು ನಕಲಿಸಿ ಉಳಿಸಿದ ನಂತರ ನನ್ನ ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ಗೆ ಕಳುಹಿಸಿ." + }, + "sendDisabled": { + "message": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ ಕಳುಹಿಸಿ", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "ಲಿಂಕ್ ಕಾಪಿ ಮಾಡಿ" + }, + "disabled": { + "message": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" + }, + "maxAccessCountReached": { + "message": "ಗರಿಷ್ಠ ಪ್ರವೇಶ ಎಣಿಕೆ ತಲುಪಿದೆ" + }, + "expired": { + "message": "ಅವಧಿ ಮೀರಿದೆ" + }, + "pendingDeletion": { + "message": "ಅಳಿಸುವಿಕೆ ಬಾಕಿ ಉಳಿದಿದೆ" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn ಅನ್ನು ಪ್ರಮಾಣಿಕರಿಸು" + }, + "hideEmail": { + "message": "ಸ್ವೀಕರಿಸುವವರಿಂದ ನನ್ನ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ಮರೆಮಾಡಿ." + }, + "sendOptionsPolicyInEffect": { + "message": "ಒಂದು ಅಥವಾ ಹೆಚ್ಚಿನ ಸಂಸ್ಥೆಯ ನೀತಿಗಳು ನಿಮ್ಮ ಕಳುಹಿಸುವ ಆಯ್ಕೆಗಳ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರುತ್ತವೆ." + }, + "emailVerificationRequired": { + "message": "ಇಮೇಲ್ ಪರಿಶೀಲನೆ ಅಗತ್ಯವಿದೆ" + }, + "emailVerificationRequiredDesc": { + "message": "ಈ ವೈಶಿಷ್ಟ್ಯವನ್ನು ಬಳಸಲು ನಿಮ್ಮ ಇಮೇಲ್ ಅನ್ನು ನೀವು ಪರಿಶೀಲಿಸಬೇಕು." + }, + "passwordPrompt": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ಮರು-ಪ್ರಾಂಪ್ಟ್" + }, + "passwordConfirmation": { + "message": "ಮಾಸ್ಟರ್ ಪಾಸ್ವರ್ಡ್ ದೃಢೀಕರಣ" + }, + "passwordConfirmationDesc": { + "message": "ಮುಂದುವರಿಯಲು ಈ ಕ್ರಿಯೆಯನ್ನು ರಕ್ಷಿಸಲಾಗಿದೆ, ದಯವಿಟ್ಟು ನಿಮ್ಮ ಗುರುತನ್ನು ಪರಿಶೀಲಿಸಲು ನಿಮ್ಮ ಮಾಸ್ಟರ್ ಪಾಸ್‌ವರ್ಡ್ ಅನ್ನು ಮರು ನಮೂದಿಸಿ." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/ko/messages.json b/apps/desktop/src/locales/ko/messages.json new file mode 100644 index 0000000000..dddd5abab2 --- /dev/null +++ b/apps/desktop/src/locales/ko/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "필터" + }, + "allItems": { + "message": "모든 항목" + }, + "favorites": { + "message": "즐겨찾기" + }, + "types": { + "message": "유형" + }, + "typeLogin": { + "message": "로그인" + }, + "typeCard": { + "message": "카드" + }, + "typeIdentity": { + "message": "신원" + }, + "typeSecureNote": { + "message": "보안 메모" + }, + "folders": { + "message": "폴더" + }, + "collections": { + "message": "컬렉션" + }, + "searchVault": { + "message": "보관함 검색" + }, + "addItem": { + "message": "항목 추가" + }, + "shared": { + "message": "공유됨" + }, + "share": { + "message": "공유" + }, + "moveToOrganization": { + "message": "조직으로 이동하기" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$이(가) $ORGNAME$(으)로 이동됨", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "이 항목을 이동할 조직을 선택하십시오. 항목이 조직으로 이동되면 소유권이 조직으로 이전됩니다. 일단 이동되면, 더는 이동된 항목의 직접적인 소유자가 아니게 됩니다." + }, + "attachments": { + "message": "첨부 파일" + }, + "viewItem": { + "message": "항목 보기" + }, + "name": { + "message": "이름" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "새 URI" + }, + "username": { + "message": "사용자 이름" + }, + "password": { + "message": "비밀번호" + }, + "passphrase": { + "message": "패스프레이즈" + }, + "editItem": { + "message": "항목 편집" + }, + "emailAddress": { + "message": "이메일 주소" + }, + "verificationCodeTotp": { + "message": "인증 코드 (TOTP)" + }, + "website": { + "message": "웹 사이트" + }, + "notes": { + "message": "메모" + }, + "customFields": { + "message": "사용자 지정 필드" + }, + "launch": { + "message": "열기" + }, + "copyValue": { + "message": "값 복사", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "클립보드로 복사할 때 최소화" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "항목의 데이터를 클립보드로 복사할 때 최소화합니다." + }, + "toggleVisibility": { + "message": "표시 전환" + }, + "toggleCollapse": { + "message": "감추기 전환", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "카드 소유자 이름" + }, + "number": { + "message": "번호" + }, + "brand": { + "message": "브랜드" + }, + "expiration": { + "message": "만료" + }, + "securityCode": { + "message": "보안 코드" + }, + "identityName": { + "message": "ID 이름" + }, + "company": { + "message": "회사" + }, + "ssn": { + "message": "주민등록번호" + }, + "passportNumber": { + "message": "여권 번호" + }, + "licenseNumber": { + "message": "면허 번호" + }, + "email": { + "message": "이메일" + }, + "phone": { + "message": "전화번호" + }, + "address": { + "message": "주소" + }, + "premiumRequired": { + "message": "프리미엄 멤버십 필요" + }, + "premiumRequiredDesc": { + "message": "이 기능을 사용하려면 프리미엄 멤버십이 필요합니다." + }, + "errorOccurred": { + "message": "오류가 발생했습니다." + }, + "error": { + "message": "오류" + }, + "january": { + "message": "1월" + }, + "february": { + "message": "2월" + }, + "march": { + "message": "3월" + }, + "april": { + "message": "4월" + }, + "may": { + "message": "5월" + }, + "june": { + "message": "6월" + }, + "july": { + "message": "7월" + }, + "august": { + "message": "8월" + }, + "september": { + "message": "9월" + }, + "october": { + "message": "10월" + }, + "november": { + "message": "11월" + }, + "december": { + "message": "12월" + }, + "ex": { + "message": "예)", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "제목" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "만료 월" + }, + "expirationYear": { + "message": "만료 연도" + }, + "select": { + "message": "선택" + }, + "other": { + "message": "기타" + }, + "generatePassword": { + "message": "비밀번호 생성" + }, + "type": { + "message": "유형" + }, + "firstName": { + "message": "이름" + }, + "middleName": { + "message": "가운데 이름" + }, + "lastName": { + "message": "성" + }, + "fullName": { + "message": "전체 이름" + }, + "address1": { + "message": "주소 1" + }, + "address2": { + "message": "주소 2" + }, + "address3": { + "message": "주소 3" + }, + "cityTown": { + "message": "읍 / 면 / 동" + }, + "stateProvince": { + "message": "시 / 도" + }, + "zipPostalCode": { + "message": "우편번호" + }, + "country": { + "message": "국가" + }, + "save": { + "message": "저장" + }, + "cancel": { + "message": "취소" + }, + "delete": { + "message": "삭제" + }, + "favorite": { + "message": "즐겨찾기" + }, + "edit": { + "message": "편집" + }, + "authenticatorKeyTotp": { + "message": "인증 키 (TOTP)" + }, + "folder": { + "message": "폴더" + }, + "newCustomField": { + "message": "새 사용자 지정 필드" + }, + "value": { + "message": "값" + }, + "dragToSort": { + "message": "드래그하여 정렬" + }, + "cfTypeText": { + "message": "텍스트" + }, + "cfTypeHidden": { + "message": "숨김" + }, + "cfTypeBoolean": { + "message": "참 / 거짓" + }, + "cfTypeLinked": { + "message": "연결됨", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "연결된 값", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "제거" + }, + "nameRequired": { + "message": "이름은 반드시 입력해야 합니다." + }, + "addedItem": { + "message": "항목 추가함" + }, + "editedItem": { + "message": "항목 편집함" + }, + "deleteItem": { + "message": "항목 삭제" + }, + "deleteFolder": { + "message": "폴더 삭제" + }, + "deleteAttachment": { + "message": "첨부 파일 삭제" + }, + "deleteItemConfirmation": { + "message": "정말로 휴지통으로 이동시킬까요?" + }, + "deletedItem": { + "message": "삭제한 항목" + }, + "overwritePasswordConfirmation": { + "message": "정말 현재 비밀번호를 덮어쓰시겠습니까?" + }, + "overwriteUsername": { + "message": "아이디 덮어쓰기" + }, + "overwriteUsernameConfirmation": { + "message": "정말 현재 아이디를 덮어쓰시겠습니까?" + }, + "noneFolder": { + "message": "폴더 없음", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "폴더 추가" + }, + "editFolder": { + "message": "폴더 편집" + }, + "regeneratePassword": { + "message": "비밀번호 재생성" + }, + "copyPassword": { + "message": "비밀번호 복사" + }, + "copyUri": { + "message": "URI 복사" + }, + "copyVerificationCodeTotp": { + "message": "인증 코드 (TOTP) 복사" + }, + "length": { + "message": "길이" + }, + "numWords": { + "message": "단어 수" + }, + "wordSeparator": { + "message": "구분 기호" + }, + "capitalize": { + "message": "첫 글자를 대문자로", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "숫자 포함" + }, + "close": { + "message": "닫기" + }, + "minNumbers": { + "message": "숫자 최소 개수" + }, + "minSpecial": { + "message": "특수 문자 최소 개수", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "모호한 문자 사용 안 함" + }, + "searchCollection": { + "message": "컬렉션 검색" + }, + "searchFolder": { + "message": "폴더 검색" + }, + "searchFavorites": { + "message": "즐겨찾기 검색" + }, + "searchType": { + "message": "유형 검색", + "description": "Search item type" + }, + "newAttachment": { + "message": "새 첨부 파일 추가" + }, + "deletedAttachment": { + "message": "첨부 파일 삭제함" + }, + "deleteAttachmentConfirmation": { + "message": "정말 이 첨부 파일을 삭제하시겠습니까?" + }, + "attachmentSaved": { + "message": "첨부 파일을 저장했습니다." + }, + "file": { + "message": "파일" + }, + "selectFile": { + "message": "파일을 선택하세요." + }, + "maxFileSize": { + "message": "최대 파일 크기는 500MB입니다." + }, + "updateKey": { + "message": "이 기능을 사용하려면 암호화 키를 업데이트해야 합니다." + }, + "editedFolder": { + "message": "폴더 편집함" + }, + "addedFolder": { + "message": "폴더 추가함" + }, + "deleteFolderConfirmation": { + "message": "정말 이 폴더를 삭제하시겠습니까?" + }, + "deletedFolder": { + "message": "폴더 삭제함" + }, + "loginOrCreateNewAccount": { + "message": "안전 보관함에 접근하려면 로그인하거나 새 계정을 만드세요." + }, + "createAccount": { + "message": "계정 만들기" + }, + "logIn": { + "message": "로그인" + }, + "submit": { + "message": "보내기" + }, + "masterPass": { + "message": "마스터 비밀번호" + }, + "masterPassDesc": { + "message": "마스터 비밀번호는 보관함을 열 때 필요한 비밀번호입니다. 절대 마스터 비밀번호를 잊어버리지 마세요. 잊어버리면 복구할 수 있는 방법이 없습니다." + }, + "masterPassHintDesc": { + "message": "마스터 비밀번호 힌트는 마스터 비밀번호를 잊었을 때 도움이 될 수 있습니다." + }, + "reTypeMasterPass": { + "message": "마스터 비밀번호 다시 입력" + }, + "masterPassHint": { + "message": "마스터 비밀번호 힌트 (선택)" + }, + "settings": { + "message": "설정" + }, + "passwordHint": { + "message": "비밀번호 힌트" + }, + "enterEmailToGetHint": { + "message": "마스터 비밀번호 힌트를 받으려면 계정의 이메일 주소를 입력하세요." + }, + "getMasterPasswordHint": { + "message": "마스터 비밀번호 힌트 얻기" + }, + "emailRequired": { + "message": "이메일은 반드시 입력해야 합니다." + }, + "invalidEmail": { + "message": "잘못된 이메일 주소입니다." + }, + "masterPassRequired": { + "message": "마스터 비밀번호는 반드시 입력해야 합니다." + }, + "masterPassLength": { + "message": "마스터 비밀번호는 최소 8자 이상이어야 합니다." + }, + "masterPassDoesntMatch": { + "message": "마스터 비밀번호 확인과 마스터 비밀번호가 일치하지 않습니다." + }, + "newAccountCreated": { + "message": "계정 생성이 완료되었습니다! 이제 로그인하실 수 있습니다." + }, + "masterPassSent": { + "message": "마스터 비밀번호 힌트가 담긴 이메일을 보냈습니다." + }, + "unexpectedError": { + "message": "예기치 못한 오류가 발생했습니다." + }, + "itemInformation": { + "message": "항목 정보" + }, + "noItemsInList": { + "message": "항목이 없습니다." + }, + "sendVerificationCode": { + "message": "이메일로 인증 코드 보내기" + }, + "sendCode": { + "message": "코드 전송" + }, + "codeSent": { + "message": "코드 전송됨" + }, + "verificationCode": { + "message": "인증 코드" + }, + "confirmIdentity": { + "message": "계속하려면 암호를 확인하세요." + }, + "verificationCodeRequired": { + "message": "인증 코드는 반드시 입력해야 합니다." + }, + "invalidVerificationCode": { + "message": "유효하지 않은 확인 코드" + }, + "continue": { + "message": "계속" + }, + "enterVerificationCodeApp": { + "message": "인증 앱에서 6자리 인증 코드를 입력하세요." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ 주소로 전송된 6자리 인증 코드를 입력하세요.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "$EMAIL$ 주소로 인증 이메일을 보냈습니다.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "기억하기" + }, + "sendVerificationCodeEmailAgain": { + "message": "인증 코드 이메일 다시 보내기" + }, + "useAnotherTwoStepMethod": { + "message": "다른 2단계 인증 사용" + }, + "insertYubiKey": { + "message": "YubiKey를 컴퓨터의 USB 포트에 삽입하고 버튼을 누르세요." + }, + "insertU2f": { + "message": "보안 키를 컴퓨터의 USB 포트에 삽입하고 버튼이 있는 경우 누르세요." + }, + "recoveryCodeDesc": { + "message": "모든 2단계 인증을 사용할 수 없는 상황인가요? 복구 코드를 사용하여 계정의 모든 2단계 인증을 비활성화할 수 있습니다." + }, + "recoveryCodeTitle": { + "message": "복구 코드" + }, + "authenticatorAppTitle": { + "message": "인증 앱" + }, + "authenticatorAppDesc": { + "message": "인증 앱(Authy, Google OTP 등)을 통하여 일회용 인증 코드를 생성합니다.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP 보안 키" + }, + "yubiKeyDesc": { + "message": "YubiKey를 사용하여 사용자의 계정에 접근합니다. YubiKey 4, 4 Nano, 4C 및 NEO 기기를 사용할 수 있습니다." + }, + "duoDesc": { + "message": "Duo Mobile 앱, SMS, 전화 통화를 사용한 Duo Security 또는 U2F 보안 키를 사용하여 인증하세요.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo Mobile 앱, SMS, 전화 통화를 사용한 조직용 Duo Security 또는 U2F 보안 키를 사용하여 인증하세요.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "WebAuthn이 활성화된 보안 키를 사용하여 계정에 접근하세요." + }, + "emailTitle": { + "message": "이메일" + }, + "emailDesc": { + "message": "인증 코드가 담긴 이메일을 다시 보냅니다." + }, + "loginUnavailable": { + "message": "로그인 불가능" + }, + "noTwoStepProviders": { + "message": "이 계정은 2단계 인증을 사용합니다. 그러나 설정된 2단계 인증 중 이 기기에서 지원하는 방식이 없습니다." + }, + "noTwoStepProviders2": { + "message": "더 많은 기기를 지원하는 2단계 인증 방식(인증 앱 등)을 추가하세요." + }, + "twoStepOptions": { + "message": "2단계 인증 옵션" + }, + "selfHostedEnvironment": { + "message": "자체 호스팅 환경" + }, + "selfHostedEnvironmentFooter": { + "message": "온-프레미스 Bitwarden이 호스팅되고 있는 서버의 기본 URL을 지정하세요." + }, + "customEnvironment": { + "message": "사용자 지정 환경" + }, + "customEnvironmentFooter": { + "message": "고급 사용자 전용 설정입니다. 각 서비스의 기본 URL을 개별적으로 지정할 수 있습니다." + }, + "baseUrl": { + "message": "서버 URL" + }, + "apiUrl": { + "message": "API 서버 URL" + }, + "webVaultUrl": { + "message": "웹 보관함 서버 URL" + }, + "identityUrl": { + "message": "ID 서버 URL" + }, + "notificationsUrl": { + "message": "알림 서버 URL" + }, + "iconsUrl": { + "message": "아이콘 서버 URL" + }, + "environmentSaved": { + "message": "환경 URL 값을 저장했습니다." + }, + "ok": { + "message": "확인" + }, + "yes": { + "message": "예" + }, + "no": { + "message": "아니오" + }, + "overwritePassword": { + "message": "비밀번호 덮어쓰기" + }, + "learnMore": { + "message": "더 알아보기" + }, + "featureUnavailable": { + "message": "기능 사용할 수 없음" + }, + "loggedOut": { + "message": "로그아웃됨" + }, + "loginExpired": { + "message": "로그인 세션이 만료되었습니다." + }, + "logOutConfirmation": { + "message": "정말 로그아웃하시겠습니까?" + }, + "logOut": { + "message": "로그아웃" + }, + "addNewLogin": { + "message": "새 로그인 추가" + }, + "addNewItem": { + "message": "새 항목 추가" + }, + "addNewFolder": { + "message": "새 폴더 추가" + }, + "view": { + "message": "보기" + }, + "account": { + "message": "계정" + }, + "loading": { + "message": "불러오는 중..." + }, + "lockVault": { + "message": "보관함 잠그기" + }, + "passwordGenerator": { + "message": "비밀번호 생성기" + }, + "contactUs": { + "message": "문의하기" + }, + "getHelp": { + "message": "도움말" + }, + "fileBugReport": { + "message": "버그 보고서 첨부" + }, + "blog": { + "message": "블로그" + }, + "followUs": { + "message": "팔로우하기" + }, + "syncVault": { + "message": "보관함 동기화" + }, + "changeMasterPass": { + "message": "마스터 비밀번호 변경" + }, + "changeMasterPasswordConfirmation": { + "message": "bitwarden.com 웹 보관함에서 마스터 비밀번호를 바꿀 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "fingerprintPhrase": { + "message": "지문 구절", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "계정 지문 구절", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "웹 보관함으로 이동" + }, + "getMobileApp": { + "message": "모바일 앱 설치" + }, + "getBrowserExtension": { + "message": "브라우저 확장 프로그램 설치" + }, + "syncingComplete": { + "message": "동기화 완료" + }, + "syncingFailed": { + "message": "동기화 실패" + }, + "yourVaultIsLocked": { + "message": "보관함이 잠겨 있습니다. 마스터 비밀번호를 입력하여 계속하세요." + }, + "unlock": { + "message": "잠금 해제" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ 에 $EMAIL$ 로 로그인했습니다.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "잘못된 마스터 비밀번호" + }, + "twoStepLoginConfirmation": { + "message": "2단계 인증은 보안 키, 인증 앱, SMS, 전화 통화 등의 다른 기기로 사용자의 로그인 시도를 검증하여 사용자의 계정을 더욱 안전하게 만듭니다. 2단계 인증은 bitwarden.com 웹 보관함에서 활성화할 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "twoStepLogin": { + "message": "2단계 인증" + }, + "vaultTimeout": { + "message": "보관함 시간 제한" + }, + "vaultTimeoutDesc": { + "message": "보관함이 언제까지 시간을 제한하고 선택된 행동을 수행하지 선택해주세요." + }, + "immediately": { + "message": "즉시" + }, + "tenSeconds": { + "message": "10초" + }, + "twentySeconds": { + "message": "20초" + }, + "thirtySeconds": { + "message": "30초" + }, + "oneMinute": { + "message": "1분" + }, + "twoMinutes": { + "message": "2분" + }, + "fiveMinutes": { + "message": "5분" + }, + "fifteenMinutes": { + "message": "15분" + }, + "thirtyMinutes": { + "message": "30분" + }, + "oneHour": { + "message": "1시간" + }, + "fourHours": { + "message": "4시간" + }, + "onIdle": { + "message": "시스템 유휴 시" + }, + "onSleep": { + "message": "시스템 절전 시" + }, + "onLocked": { + "message": "시스템 잠금 시" + }, + "onRestart": { + "message": "다시 시작 시" + }, + "never": { + "message": "잠그지 않음" + }, + "security": { + "message": "보안" + }, + "clearClipboard": { + "message": "클립보드 비우기", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "자동으로 클립보드에 복사된 값을 제거합니다.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "웹 사이트 아이콘 사용 안 함" + }, + "disableFaviconDesc": { + "message": "웹 사이트 아이콘을 사용하면 보관함 각 항목 옆에 이미지를 보여줍니다." + }, + "enableMinToTray": { + "message": "알림 영역으로 최소화" + }, + "enableMinToTrayDesc": { + "message": "창을 최소화하면 작업 표시줄 대신 알림 영역에 아이콘을 표시합니다." + }, + "enableMinToMenuBar": { + "message": "메뉴 막대로 최소화" + }, + "enableMinToMenuBarDesc": { + "message": "창을 최소화하면 메뉴 막대에 아이콘을 표시합니다." + }, + "enableCloseToTray": { + "message": "트레이 아이콘으로 닫기" + }, + "enableCloseToTrayDesc": { + "message": "창을 닫으면 프로그램 종료 대신 알림 영역에 아이콘으로 표시합니다." + }, + "enableCloseToMenuBar": { + "message": "메뉴 막대로 닫기" + }, + "enableCloseToMenuBarDesc": { + "message": "창을 닫으면 메뉴 막대에 아이콘을 표시합니다." + }, + "enableTray": { + "message": "알림 영역 아이콘 사용" + }, + "enableTrayDesc": { + "message": "항상 알림 영역에 아이콘을 표시합니다." + }, + "startToTray": { + "message": "트레이 아이콘으로 시작" + }, + "startToTrayDesc": { + "message": "응용프로그램을 시작할 때 알림 영역에 아이콘으로 표시합니다." + }, + "startToMenuBar": { + "message": "메뉴 막대에서 시작하기" + }, + "startToMenuBarDesc": { + "message": "앱을 시작할 때 메뉴 바에 아이콘으로 표시합니다." + }, + "openAtLogin": { + "message": "로그인할 때 자동으로 실행" + }, + "openAtLoginDesc": { + "message": "로그인할 때 Bitwarden 데스크톱 앱을 자동으로 실행합니다." + }, + "alwaysShowDock": { + "message": "Dock에 항상 표시하기" + }, + "alwaysShowDockDesc": { + "message": "메뉴 막대에 숨겨진 경우에도 Bitwarden 아이콘을 Dock에 표시합니다." + }, + "confirmTrayTitle": { + "message": "알림 영역 비활성화 확인" + }, + "confirmTrayDesc": { + "message": "이 설정을 끄면 알림 영역과 관련된 다른 모든 설정이 함께 꺼집니다." + }, + "language": { + "message": "언어(Language)" + }, + "languageDesc": { + "message": "애플리케이션에 사용할 언어를 변경합니다. 설정을 적용하려면 애플리케이션을 다시 시작해야 합니다." + }, + "theme": { + "message": "테마" + }, + "themeDesc": { + "message": "애플리케이션의 색상 테마를 변경합니다." + }, + "dark": { + "message": "어두운 테마", + "description": "Dark color" + }, + "light": { + "message": "밝은 테마", + "description": "Light color" + }, + "copy": { + "message": "복사", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "업데이트 확인" + }, + "version": { + "message": "$VERSION_NUM$ 버전", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "다시 시작하여 업데이트" + }, + "restartToUpdateDesc": { + "message": "$VERSION_NUM$ 버전을 설치할 준비가 되었습니다. 설치를 완료하려면 애플리케이션을 다시 시작해야 합니다. 지금 다시 시작하고 업데이트하시겠습니까?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "업데이트 사용 가능" + }, + "updateAvailableDesc": { + "message": "업데이트가 있습니다. 지금 다운로드하시겠습니까?" + }, + "restart": { + "message": "다시 시작" + }, + "later": { + "message": "나중에" + }, + "noUpdatesAvailable": { + "message": "사용할 수 있는 업데이트가 없습니다. 최신 버전을 사용하고 있습니다." + }, + "updateError": { + "message": "업데이트 오류" + }, + "unknown": { + "message": "알 수 없음" + }, + "copyUsername": { + "message": "사용자 이름 복사" + }, + "copyNumber": { + "message": "번호 복사", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "보안 코드 복사", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "프리미엄 멤버십" + }, + "premiumManage": { + "message": "멤버십 관리" + }, + "premiumManageAlert": { + "message": "bitwarden.com 웹 보관함에서 멤버십을 관리할 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "premiumRefresh": { + "message": "멤버십 새로 고침" + }, + "premiumNotCurrentMember": { + "message": "프리미엄 사용자가 아닙니다." + }, + "premiumSignUpAndGet": { + "message": "프리미엄 멤버십에 가입하면 얻을 수 있는 것:" + }, + "premiumSignUpStorage": { + "message": "1GB의 암호화된 파일 저장소." + }, + "premiumSignUpTwoStep": { + "message": "YubiKey나 FIDO U2F, Duo 등의 추가적인 2단계 인증 옵션." + }, + "premiumSignUpReports": { + "message": "보관함을 안전하게 유지하기 위한 암호 위생, 계정 상태, 데이터 유출 보고서" + }, + "premiumSignUpTotp": { + "message": "보관함에 등록된 로그인 항목을 위한 TOTP 인증 코드(2FA) 생성기." + }, + "premiumSignUpSupport": { + "message": "고객 지원 우선 순위 제공." + }, + "premiumSignUpFuture": { + "message": "앞으로 추가될 모든 프리미엄 기능을 사용할 수 있습니다. 기대하세요!" + }, + "premiumPurchase": { + "message": "프리미엄 멤버십 구입" + }, + "premiumPurchaseAlert": { + "message": "bitwarden.com 웹 보관함에서 프리미엄 멤버십을 구입할 수 있습니다. 지금 웹 사이트를 방문하시겠습니까?" + }, + "premiumCurrentMember": { + "message": "프리미엄 사용자입니다!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden을 지원해 주셔서 감사합니다." + }, + "premiumPrice": { + "message": "이 모든 기능을 연 $PRICE$에 이용하실 수 있습니다!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "새로 고침 완료" + }, + "passwordHistory": { + "message": "비밀번호 변경 기록" + }, + "clear": { + "message": "삭제", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "비밀번호가 없습니다." + }, + "undo": { + "message": "실행 취소" + }, + "redo": { + "message": "다시 실행" + }, + "cut": { + "message": "잘라내기", + "description": "Cut to clipboard" + }, + "paste": { + "message": "붙여넣기", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "모두 선택" + }, + "zoomIn": { + "message": "확대" + }, + "zoomOut": { + "message": "축소" + }, + "resetZoom": { + "message": "확대 / 축소 수준 초기화" + }, + "toggleFullScreen": { + "message": "전체 화면 전환" + }, + "reload": { + "message": "새로 고침" + }, + "toggleDevTools": { + "message": "개발자 도구" + }, + "minimize": { + "message": "최소화", + "description": "Minimize window" + }, + "zoom": { + "message": "확대/축소" + }, + "bringAllToFront": { + "message": "모두 앞으로 가져오기", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Bitwarden 정보" + }, + "services": { + "message": "서비스" + }, + "hideBitwarden": { + "message": "Bitwarden 숨기기" + }, + "hideOthers": { + "message": "다른 항목 숨기기" + }, + "showAll": { + "message": "모두 보기" + }, + "quitBitwarden": { + "message": "Bitwarden 종료" + }, + "valueCopied": { + "message": "$VALUE$를 클립보드에 복사함", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "도움말" + }, + "window": { + "message": "창" + }, + "checkPassword": { + "message": "비밀번호가 노출되었는지 확인합니다." + }, + "passwordExposed": { + "message": "이 비밀번호는 데이터 유출에 $VALUE$회 노출되었습니다. 비밀번호를 변경하는 것이 좋습니다.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "이 비밀번호는 데이터 유출 목록에 없습니다. 사용하기에 안전한 비밀번호입니다." + }, + "baseDomain": { + "message": "기본 도메인", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "도메인 이름", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "호스트", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "정확히 일치" + }, + "startsWith": { + "message": "...으로 시작" + }, + "regEx": { + "message": "정규 표현식", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "일치 인식", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "기본 일치 인식", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "표시 / 숨기기" + }, + "organization": { + "message": "조직", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "기본값" + }, + "exit": { + "message": "끝내기" + }, + "showHide": { + "message": "표시 / 숨기기", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "알림 영역으로 숨기기" + }, + "alwaysOnTop": { + "message": "항상 위에", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "업데이트됨", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "비밀번호 업데이트됨", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "보관함 내보내기" + }, + "fileFormat": { + "message": "파일 형식" + }, + "warning": { + "message": "경고", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "보관함 내보내기 확인" + }, + "exportWarningDesc": { + "message": "내보내기는 보관함 데이터가 암호화되지 않은 형식으로 포함됩니다. 내보낸 파일을 안전하지 않은 채널(예: 이메일)을 통해 저장하거나 보내지 마십시오. 사용이 끝난 후에는 즉시 삭제하십시오." + }, + "encExportKeyWarningDesc": { + "message": "이 내보내기는 계정의 암호화 키를 사용하여 데이터를 암호화합니다. 추후 계정의 암호화 키를 교체할 경우 다시 내보내기를 진행해야 합니다. 그러지 않을 경우 이 내보내기 파일을 해독할 수 없게 됩니다." + }, + "encExportAccountWarningDesc": { + "message": "모든 Bitwarden 사용자 계정은 고유한 계정 암호화 키를 가지고 있습니다. 따라서, 다른 계정에서는 암호화된 내보내기를 가져올 수 없습니다." + }, + "noOrganizationsList": { + "message": "속해 있는 조직이 없습니다. 조직에 속하면 다른 사용자들과 항목을 안전하게 공유할 수 있습니다." + }, + "noCollectionsInList": { + "message": "컬렉션이 없습니다." + }, + "ownership": { + "message": "소유자" + }, + "whoOwnsThisItem": { + "message": "이 항목의 소유자는 누구입니까?" + }, + "strong": { + "message": "강함", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "괜찮음", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "약함", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "취약한 마스터 비밀번호" + }, + "weakMasterPasswordDesc": { + "message": "선택한 마스터 비밀번호는 취약합니다. Bitwarden 계정을 확실히 보호하려면 강력한 마스터 비밀번호(혹은 패스프레이즈)를 사용해야 합니다. 정말 이 마스터 비밀번호를 사용하시겠습니까?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "PIN 코드를 사용하여 잠금 해제" + }, + "setYourPinCode": { + "message": "Bitwarden 잠금해제에 사용될 PIN 코드를 설정합니다. 이 애플리케이션에서 완전히 로그아웃할 경우 PIN 설정이 초기화됩니다." + }, + "pinRequired": { + "message": "PIN 코드가 필요합니다." + }, + "invalidPin": { + "message": "잘못된 PIN 코드입니다." + }, + "unlockWithWindowsHello": { + "message": "Windows Hello를 사용하여 잠금 해제" + }, + "windowsHelloConsentMessage": { + "message": "Bitwarden에서 인증을 요청합니다." + }, + "unlockWithTouchId": { + "message": "Touch ID를 사용하여 잠금 해제" + }, + "touchIdConsentMessage": { + "message": "보관함 잠금 해제" + }, + "noAutoPromptWindowsHello": { + "message": "시작할 때 Windows Hello 요구하지 않음" + }, + "noAutoPromptTouchId": { + "message": "시작할 때 Touch ID 요구하지 않음" + }, + "lockWithMasterPassOnRestart": { + "message": "다시 시작 시 마스터 비밀번호로 잠금" + }, + "preferences": { + "message": "설정" + }, + "enableMenuBar": { + "message": "메뉴 막대 아이콘 사용" + }, + "enableMenuBarDesc": { + "message": "항상 메뉴 막대에 아이콘을 표시합니다." + }, + "hideToMenuBar": { + "message": "메뉴 막대에 숨기기" + }, + "selectOneCollection": { + "message": "반드시 하나 이상의 컬렉션을 선택해야 합니다." + }, + "premiumUpdated": { + "message": "프리미엄으로 업그레이드했습니다." + }, + "restore": { + "message": "복원" + }, + "premiumManageAlertAppStore": { + "message": "App Store에서 구독을 관리할 수 있습니다. 지금 App Store에 접속하시겠습니까?" + }, + "legal": { + "message": "법적", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "이용약관" + }, + "privacyPolicy": { + "message": "개인 정보 보호 정책" + }, + "unsavedChangesConfirmation": { + "message": "정말로 떠나시겠습니까? 지금 떠난다면 현재 정보는 저장되지 않습니다." + }, + "unsavedChangesTitle": { + "message": "저장되지 않은 변경 사항" + }, + "clone": { + "message": "복제" + }, + "passwordGeneratorPolicyInEffect": { + "message": "하나 이상의 단체 정책이 생성기 규칙에 영항을 미치고 있습니다." + }, + "vaultTimeoutAction": { + "message": "보관함 시간 제한 초과시 동작" + }, + "vaultTimeoutActionLockDesc": { + "message": "잠긴 보관함에 다시 접근하려면 마스터 비밀번호를 입력해야 합니다." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "로그아웃한 보관함에 다시 접근하려면 다시 인증해야 합니다." + }, + "lock": { + "message": "잠금", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "휴지통", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "휴지통 검색" + }, + "permanentlyDeleteItem": { + "message": "영구적으로 항목 삭제" + }, + "permanentlyDeleteItemConfirmation": { + "message": "정말로 이 항목을 영구적으로 삭제하시겠습니까?" + }, + "permanentlyDeletedItem": { + "message": "영구적으로 삭제된 항목" + }, + "restoreItem": { + "message": "항목 복원" + }, + "restoreItemConfirmation": { + "message": "정말 이 항목을 복원하시겠습니까?" + }, + "restoredItem": { + "message": "복원된 항목" + }, + "permanentlyDelete": { + "message": "영구적으로 삭제" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "로그아웃하면 보관함에 대한 모든 접근이 제거되며 시간 제한을 초과하면 온라인 인증을 요구합니다. 정말로 이 설정을 사용하시겠습니까?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "시간 제한 초과시 동작 확인" + }, + "enterpriseSingleSignOn": { + "message": "엔터프라이즈 통합 인증 (SSO)" + }, + "setMasterPassword": { + "message": "마스터 비밀번호 설정" + }, + "ssoCompleteRegistration": { + "message": "SSO 로그인을 하기 위해서 보관함에 접근하고 보호할 수 있도록 마스터 비밀번호를 설정해주세요." + }, + "newMasterPass": { + "message": "새 마스터 비밀번호" + }, + "confirmNewMasterPass": { + "message": "새 마스터 비밀번호 확인" + }, + "masterPasswordPolicyInEffect": { + "message": "하나 이상의 단체 정책이 마스터 비밀번호가 다음 사항을 따르도록 요구합니다:" + }, + "policyInEffectMinComplexity": { + "message": "최소 복잡도 점수 $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "최소 길이 $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "하나 이상의 대문자 포함" + }, + "policyInEffectLowercase": { + "message": "하나 이상의 소문자 포함" + }, + "policyInEffectNumbers": { + "message": "하나 이상의 숫자 포함" + }, + "policyInEffectSpecial": { + "message": "하나 이상의 다음 특수문자 포함 $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "새 마스터 비밀번호가 정책 요구 사항을 따르지 않습니다." + }, + "acceptPolicies": { + "message": "이 박스를 체크하면 다음에 동의하는 것으로 간주됩니다:" + }, + "acceptPoliciesError": { + "message": "서비스 약관 및 개인 정보 보호 정책을 확인하지 않았습니다." + }, + "enableBrowserIntegration": { + "message": "브라우저와 연결 활성화" + }, + "enableBrowserIntegrationDesc": { + "message": "브라우저와 연결하면 브라우저에서 생체 인식을 사용할 수 있습니다." + }, + "browserIntegrationMasOnlyTitle": { + "message": "브라우저와 연결 지원되지 않음" + }, + "browserIntegrationMasOnlyDesc": { + "message": "브라우저와 연결은 현재 Mac App Store 버전에서만 지원됩니다." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "브라우저와 연결 지원되지 않음" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "현재 Microsoft Store 버전에서는 브라우저와 연결이 지원되지 않습니다." + }, + "enableBrowserIntegrationFingerprint": { + "message": "브라우저와 연결을 위해 인증이 필요함" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "데스크탑 앱과 브라우저를 연결할 때 지문 구절을 확인하는 과정을 제공함으로써 추가적인 보안을 제공합니다. 이 옵션을 켜면, 연결이 설정될 때마다 사용자의 확인을 요구합니다." + }, + "approve": { + "message": "승인" + }, + "verifyBrowserTitle": { + "message": "브라우저와 연결 인증" + }, + "verifyBrowserDesc": { + "message": "다음의 지문 구절이 브라우저 확장 프로그램에 표시된 지문 구절과 동일한지 확인해주세요." + }, + "biometricsNotEnabledTitle": { + "message": "생체 인식이 활성화되지 않음" + }, + "biometricsNotEnabledDesc": { + "message": "브라우저에서 생체 인식을 사용하기 위해서는 설정에서 데스크톱 생체 인식을 먼저 활성화해야 합니다." + }, + "personalOwnershipSubmitError": { + "message": "엔터프라이즈 정책으로 인해 개인 보관함에 항목을 저장할 수 없습니다. 조직에서 소유권 설정을 변경한 다음, 사용 가능한 컬렉션 중에서 선택해주세요." + }, + "hintEqualsPassword": { + "message": "비밀번호 힌트는 비밀번호와 같을 수 없습니다." + }, + "personalOwnershipPolicyInEffect": { + "message": "조직의 정책이 소유권 설정에 영향을 미치고 있습니다." + }, + "allSends": { + "message": "모든 Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "파일" + }, + "sendTypeText": { + "message": "텍스트" + }, + "searchSends": { + "message": "Send 검색", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send 편집", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "내 보관함" + }, + "text": { + "message": "텍스트" + }, + "deletionDate": { + "message": "삭제 날짜" + }, + "deletionDateDesc": { + "message": "이 Send가 정해진 일시에 영구적으로 삭제됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "만료 날짜" + }, + "expirationDateDesc": { + "message": "설정할 경우, 이 Send에 대한 접근 권한이 정해진 일시에 만료됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "최대 접근 횟수" + }, + "maxAccessCountDesc": { + "message": "설정할 경우, 최대 접근 횟수에 도달할 때 이 Send에 접근할 수 없게 됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "현재 접근 횟수" + }, + "disableSend": { + "message": "이 Send를 비활성화하여 아무도 접근할 수 없게 합니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "이 Send에 접근하기 위해 암호를 입력하도록 선택적으로 요구합니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "이 Send에 대한 비공개 메모", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "링크 보내기", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "링크 보내기", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Send에 접근할 때 기본적으로 텍스트를 숨김", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send 생성함", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send 수정함", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send 삭제함", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "새 비밀번호" + }, + "whatTypeOfSend": { + "message": "어떤 유형의 Send인가요?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Send 생성", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "전송하려는 텍스트" + }, + "sendFileDesc": { + "message": "전송하려는 파일" + }, + "days": { + "message": "$DAYS$일", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1일" + }, + "custom": { + "message": "사용자 지정" + }, + "deleteSendConfirmation": { + "message": "정말 이 Send를 삭제하시겠습니까?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Send 링크를 클립보드에 복사", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "저장할 때 이 Send를 공유하기 위한 링크를 클립보드에 복사합니다." + }, + "sendDisabled": { + "message": "Send 비활성화됨", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "엔터프라이즈 정책으로 인해 이미 생성된 Send를 삭제하는 것만 허용됩니다.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "링크 복사" + }, + "disabled": { + "message": "비활성화됨" + }, + "maxAccessCountReached": { + "message": "최대 접근 횟수 도달" + }, + "expired": { + "message": "만료됨" + }, + "pendingDeletion": { + "message": "삭제 대기 중" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn 인증" + }, + "hideEmail": { + "message": "받는 사람으로부터 나의 이메일 주소 숨기기" + }, + "sendOptionsPolicyInEffect": { + "message": "하나 이상의 단체 정책이 Send 설정에 영향을 미치고 있습니다." + }, + "emailVerificationRequired": { + "message": "이메일 인증 필요함" + }, + "emailVerificationRequiredDesc": { + "message": "이 기능을 이용하기 위해서는 이메일을 인증해야 합니다." + }, + "passwordPrompt": { + "message": "마스터 비밀번호 재확인" + }, + "passwordConfirmation": { + "message": "마스터 비밀번호 확인" + }, + "passwordConfirmationDesc": { + "message": "이 작업은 보호되어 있습니다. 계속하려면 마스터 비밀번호를 입력하여 신원을 인증하세요." + }, + "updatedMasterPassword": { + "message": "마스터 비밀번호 변경됨" + }, + "updateMasterPassword": { + "message": "마스터 비밀번호 변경" + }, + "updateMasterPasswordWarning": { + "message": "최근에 조직 관리자가 마스터 비밀번호를 변경했습니다. 보관함에 액세스하려면 지금 업데이트해야 합니다. 계속하면 현재 세션에서 로그아웃되며 다시 로그인해야 합니다. 다른 장치의 활성 세션은 최대 1시간 동안 계속 활성 상태로 유지될 수 있습니다." + }, + "hours": { + "message": "시" + }, + "minutes": { + "message": "분" + }, + "vaultTimeoutPolicyInEffect": { + "message": "조직 정책이 보관함 제한 시간에 영향을 미치고 있습니다. 최대 허용 보관함 제한 시간은 $HOURS$시간 $MINUTES$분입니다", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "볼트 제한 시간이 조직에서 설정한 제한을 초과합니다." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "자동 등록" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "이 조직에는 자동으로 비밀번호 재설정에 등록하는 기업 정책이 있습니다. 등록하면 조직 관리자가 마스터 암호를 변경할 수 있습니다." + }, + "vaultExportDisabled": { + "message": "보관함 내보내기 비활성화됨" + }, + "personalVaultExportPolicyInEffect": { + "message": "하나 이상의 조직 정책이 개인 보관함을 내보내는 것을 제한하고 있습니다." + }, + "addAccount": { + "message": "계정 추가" + }, + "removeMasterPassword": { + "message": "마스터 비밀번호 제거" + }, + "removedMasterPassword": { + "message": "마스터 비밀번호가 제거되었습니다." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ 조직은 자체 호스팅 키 서버로 SSO를 사용하고 있습니다 이 조직의 멤버들은 로그인할 때에 마스터 비밀번호를 필요로 하지 않습니다.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "조직 나가기" + }, + "leaveOrganizationConfirmation": { + "message": "정말 이 조직을 떠나시겠습니까?" + }, + "leftOrganization": { + "message": "조직을 떠났습니다." + }, + "ssoKeyConnectorUnavailable": { + "message": "키 제공자와 통신할 수 없습니다. 다시 시도해보세요." + }, + "lockAllVaults": { + "message": "모든 보관함 잠그기" + }, + "accountLimitReached": { + "message": "5개 이상의 계정은 동시에 로그인할 수 없습니다." + }, + "accountPreferences": { + "message": "설정" + }, + "appPreferences": { + "message": "앱 설정 (모든 계정)" + }, + "accountSwitcherLimitReached": { + "message": "계정 개수 제한에 도달했습니다. 추가로 로그인하려면 다른 계정을 로그아웃 해주세요." + }, + "settingsTitle": { + "message": "$EMAIL$의 앱 설정", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "계정 전환" + }, + "options": { + "message": "선택" + }, + "sessionTimeout": { + "message": "세션 시간이 초과되었습니다. 다시 로그인해주세요." + }, + "exportingPersonalVaultTitle": { + "message": "개인 보관함을 내보내는 중" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "생성기" + }, + "whatWouldYouLikeToGenerate": { + "message": "무엇을 생성하실건가요?" + }, + "passwordType": { + "message": "비밀번호 유형" + }, + "regenerateUsername": { + "message": "아이디 재생성" + }, + "generateUsername": { + "message": "아이디 생성" + }, + "usernameType": { + "message": "아이디 유형" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "무작위" + }, + "randomWord": { + "message": "무작위 단어" + }, + "websiteName": { + "message": "웹사이트 이름" + }, + "service": { + "message": "서비스" + } +} diff --git a/apps/desktop/src/locales/lv/messages.json b/apps/desktop/src/locales/lv/messages.json new file mode 100644 index 0000000000..43e96c79ba --- /dev/null +++ b/apps/desktop/src/locales/lv/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Atlases" + }, + "allItems": { + "message": "Visi vienumi" + }, + "favorites": { + "message": "Izlase" + }, + "types": { + "message": "Veidi" + }, + "typeLogin": { + "message": "Pierakstīšanās vienums" + }, + "typeCard": { + "message": "Karte" + }, + "typeIdentity": { + "message": "Identitāte" + }, + "typeSecureNote": { + "message": "Droša piezīme" + }, + "folders": { + "message": "Mapes" + }, + "collections": { + "message": "Krājumi" + }, + "searchVault": { + "message": "Meklēt glabātavā" + }, + "addItem": { + "message": "Pievienot vienumu" + }, + "shared": { + "message": "Kopīgots" + }, + "share": { + "message": "Kopīgot" + }, + "moveToOrganization": { + "message": "Pārvietot uz apvienību" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ pārvietots uz $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Izvēlies apvienību, uz kuru pārvietot šo vienumu. Pārvietošana nodod šī vienuma piederību apvienībai. Tu vairs nebūsi šī vienuma tiešais īpašnieks pēc tā pārvietošanas." + }, + "attachments": { + "message": "Pielikumi" + }, + "viewItem": { + "message": "Skatīt vienumu" + }, + "name": { + "message": "Nosaukums" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Jauns URI" + }, + "username": { + "message": "Lietotājvārds" + }, + "password": { + "message": "Parole" + }, + "passphrase": { + "message": "Paroles vārdkopa" + }, + "editItem": { + "message": "Labot vienumu" + }, + "emailAddress": { + "message": "E-pasta adrese" + }, + "verificationCodeTotp": { + "message": "Apstiprinājuma kods (TOTP)" + }, + "website": { + "message": "Tīmekļa vietne" + }, + "notes": { + "message": "Piezīmes" + }, + "customFields": { + "message": "Pielāgoti lauki" + }, + "launch": { + "message": "Palaist" + }, + "copyValue": { + "message": "Ievietot vērtību starpliktuvē", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Samazināt, kad ievieto starpliktuvē" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Samazināt, kad vienuma saturs tiek ievietots starpliktuvē." + }, + "toggleVisibility": { + "message": "Pārslēgt redzamību" + }, + "toggleCollapse": { + "message": "Pārslēgt sakļaušanu", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kartes īpašnieka vārds" + }, + "number": { + "message": "Numurs" + }, + "brand": { + "message": "Zīmols" + }, + "expiration": { + "message": "Derīgums" + }, + "securityCode": { + "message": "Drošības kods" + }, + "identityName": { + "message": "Identitātes nosaukums" + }, + "company": { + "message": "Uzņēmums" + }, + "ssn": { + "message": "Personas kods" + }, + "passportNumber": { + "message": "Pases numurs" + }, + "licenseNumber": { + "message": "Autovadītāja apliecības numurs" + }, + "email": { + "message": "E-pasts" + }, + "phone": { + "message": "Tālrunis" + }, + "address": { + "message": "Adrese" + }, + "premiumRequired": { + "message": "Nepieciešams Premium" + }, + "premiumRequiredDesc": { + "message": "Ir nepieciešama Premium dalība, lai izmantotu šo iespēju." + }, + "errorOccurred": { + "message": "Radusies kļūda." + }, + "error": { + "message": "Kļūda" + }, + "january": { + "message": "Janvāris" + }, + "february": { + "message": "Februāris" + }, + "march": { + "message": "Marts" + }, + "april": { + "message": "Aprīlis" + }, + "may": { + "message": "Maijs" + }, + "june": { + "message": "Jūnijs" + }, + "july": { + "message": "Jūlijs" + }, + "august": { + "message": "Augusts" + }, + "september": { + "message": "Septembris" + }, + "october": { + "message": "Oktobris" + }, + "november": { + "message": "Novembris" + }, + "december": { + "message": "Decembris" + }, + "ex": { + "message": "piem.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Uzruna" + }, + "mr": { + "message": "K-gs" + }, + "mrs": { + "message": "K-dze" + }, + "ms": { + "message": "Jk-dze" + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Derīguma mēnesis" + }, + "expirationYear": { + "message": "Derīguma gads" + }, + "select": { + "message": "Atlasīt" + }, + "other": { + "message": "Cits" + }, + "generatePassword": { + "message": "Veidot paroli" + }, + "type": { + "message": "Veids" + }, + "firstName": { + "message": "Vārds" + }, + "middleName": { + "message": "Citi vārdi" + }, + "lastName": { + "message": "Uzvārds" + }, + "fullName": { + "message": "Pilnais vārds" + }, + "address1": { + "message": "Adrese 1" + }, + "address2": { + "message": "Adrese 2" + }, + "address3": { + "message": "Adrese 3" + }, + "cityTown": { + "message": "Pilsēta / ciems" + }, + "stateProvince": { + "message": "Novads / pagasts" + }, + "zipPostalCode": { + "message": "Pasta indekss" + }, + "country": { + "message": "Valsts" + }, + "save": { + "message": "Saglabāt" + }, + "cancel": { + "message": "Atcelt" + }, + "delete": { + "message": "Dzēst" + }, + "favorite": { + "message": "Izlasē" + }, + "edit": { + "message": "Labot" + }, + "authenticatorKeyTotp": { + "message": "Autentificētāja atslēga (TOTP)" + }, + "folder": { + "message": "Mape" + }, + "newCustomField": { + "message": "Jauns pielāgotais lauks" + }, + "value": { + "message": "Vērtība" + }, + "dragToSort": { + "message": "Vilkt, lai kārtotu" + }, + "cfTypeText": { + "message": "Teksts" + }, + "cfTypeHidden": { + "message": "Paslēpts" + }, + "cfTypeBoolean": { + "message": "Patiesuma vērtība" + }, + "cfTypeLinked": { + "message": "Saistīts", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Saistīta vērtība", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Noņemt" + }, + "nameRequired": { + "message": "Nosaukums ir nepieciešams." + }, + "addedItem": { + "message": "Vienums pievienots" + }, + "editedItem": { + "message": "Vienums labots" + }, + "deleteItem": { + "message": "Izdzēst vienumu" + }, + "deleteFolder": { + "message": "Dzēst mapi" + }, + "deleteAttachment": { + "message": "Izdzēst pielikumu" + }, + "deleteItemConfirmation": { + "message": "Vai tiešām pārvietot uz atkritni?" + }, + "deletedItem": { + "message": "Vienums ir pārvietots uz atkritni" + }, + "overwritePasswordConfirmation": { + "message": "Vai tiešām pārrakstīt esošo paroli?" + }, + "overwriteUsername": { + "message": "Pārrakstīt lietotājvārdu" + }, + "overwriteUsernameConfirmation": { + "message": "Vai tiešām pārrakstīt pašreizējo lietotājvārdu?" + }, + "noneFolder": { + "message": "Nav mapes", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Pievienot mapi" + }, + "editFolder": { + "message": "Labot mapi" + }, + "regeneratePassword": { + "message": "Pārizveidot paroli" + }, + "copyPassword": { + "message": "Ievietot paroli starpliktuvē" + }, + "copyUri": { + "message": "Ievietot URI starpliktuvē" + }, + "copyVerificationCodeTotp": { + "message": "Ievietot apstiprinājuma kodu (TOTP) starpliktuvē" + }, + "length": { + "message": "Garums" + }, + "numWords": { + "message": "Vārdu skaits" + }, + "wordSeparator": { + "message": "Vārdu atdalītājs" + }, + "capitalize": { + "message": "Izmantot lielos sākumburtus", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Iekļaut ciparu" + }, + "close": { + "message": "Aizvērt" + }, + "minNumbers": { + "message": "Mazākais pieļaujamais ciparu skaits" + }, + "minSpecial": { + "message": "Mazākais pieļaujamais īpašo rakstzīmju skaits", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Izvairīties no viegli sajaucamām rakstzīmēm" + }, + "searchCollection": { + "message": "Meklēt krājumā" + }, + "searchFolder": { + "message": "Meklēt mapē" + }, + "searchFavorites": { + "message": "Meklēt izlasē" + }, + "searchType": { + "message": "Meklēt veidu", + "description": "Search item type" + }, + "newAttachment": { + "message": "Pievienot jaunu pielikumu" + }, + "deletedAttachment": { + "message": "Pielikums izdzēsts" + }, + "deleteAttachmentConfirmation": { + "message": "Vai tiešām izdzēst šo pielikumu?" + }, + "attachmentSaved": { + "message": "Pielikums tika saglabāts." + }, + "file": { + "message": "Datne" + }, + "selectFile": { + "message": "Atlasīt datni." + }, + "maxFileSize": { + "message": "Lielākais pieļaujamais datnes izmērs ir 500 MB." + }, + "updateKey": { + "message": "Šo iespēju nevar izmantot, kamēr nav atjaunināta šifrēšanas atslēga." + }, + "editedFolder": { + "message": "Mape labota" + }, + "addedFolder": { + "message": "Mape pievienota" + }, + "deleteFolderConfirmation": { + "message": "Vai tiešām izdzēst šo mapi?" + }, + "deletedFolder": { + "message": "Mape izdzēsta" + }, + "loginOrCreateNewAccount": { + "message": "Pieraksties vai izveido jaunu kontu, lai piekļūtu drošajai glabātavai!" + }, + "createAccount": { + "message": "Izveidot kontu" + }, + "logIn": { + "message": "Pierakstīties" + }, + "submit": { + "message": "Iesniegt" + }, + "masterPass": { + "message": "Galvenā parole" + }, + "masterPassDesc": { + "message": "Galvenā parole ir parole, kas tiek izmantota, lai piekļūtu glabātavai. Ir ļoti svarīgi, ka tā netiek aizmirsta, jo tādā gadījumā to nav iespējams atgūt." + }, + "masterPassHintDesc": { + "message": "Galvenās paroles norāde var palīdzēt atcerēties paroli, ja tā ir aizmirsta." + }, + "reTypeMasterPass": { + "message": "Atkārtoti ievadīt galveno paroli" + }, + "masterPassHint": { + "message": "Galvenās paroles norāde (nav nepieciešama)" + }, + "settings": { + "message": "Iestatījumi" + }, + "passwordHint": { + "message": "Paroles norāde" + }, + "enterEmailToGetHint": { + "message": "Ievadiet sava konta e-pasta adresi, lai saņemtu galvenās paroles norādi!" + }, + "getMasterPasswordHint": { + "message": "Saņemt galvenās paroles norādi" + }, + "emailRequired": { + "message": "Ir jānorāda e-pasta adrese." + }, + "invalidEmail": { + "message": "Nederīga e-pasta adrese." + }, + "masterPassRequired": { + "message": "Ir jānorāda galvenā parole." + }, + "masterPassLength": { + "message": "Galvenajai parolei ir jābūt vismaz 8 rakstzīmes garai." + }, + "masterPassDoesntMatch": { + "message": "Galvenās paroles apstiprinājums nesakrīt." + }, + "newAccountCreated": { + "message": "Tavs jaunais konts ir izveidots. Tagad Tu vari pierakstīties." + }, + "masterPassSent": { + "message": "Mēs nosūtījām galvenās paroles norādi e-pastā." + }, + "unexpectedError": { + "message": "Ir radusies neparedzēta kļūda." + }, + "itemInformation": { + "message": "Vienuma informācija" + }, + "noItemsInList": { + "message": "Nav vienumu, ko parādīt." + }, + "sendVerificationCode": { + "message": "Sūtīt apstiprinājuma kodu uz e-pastu" + }, + "sendCode": { + "message": "Nosūtīt kodu" + }, + "codeSent": { + "message": "Kods nosūtīts" + }, + "verificationCode": { + "message": "Apstiprinājuma kods" + }, + "confirmIdentity": { + "message": "Apstiprināt identitāti, lai turpinātu." + }, + "verificationCodeRequired": { + "message": "Ir nepieciešams apstiprinājuma kods." + }, + "invalidVerificationCode": { + "message": "Nederīgs apstiprinājuma kods" + }, + "continue": { + "message": "Turpināt" + }, + "enterVerificationCodeApp": { + "message": "Ievadi 6 ciparu apstiprinājuma kodu no autentificētāja lietotnes!" + }, + "enterVerificationCodeEmail": { + "message": "Ievadi 6 ciparu apstiprinājuma kodu, kas tika nosūtīts uz $EMAIL$!", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-pasts apstiprināšanai nosūtīts uz $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Atcerēties mani" + }, + "sendVerificationCodeEmailAgain": { + "message": "Sūtīt apstiprinājuma koda e-pastu vēlreiz" + }, + "useAnotherTwoStepMethod": { + "message": "Izmantot citu divpakāpju pierakstīšanās veidu" + }, + "insertYubiKey": { + "message": "Ievieto savu YubiKey datora USB ligzdā un pieskaries tā pogai!" + }, + "insertU2f": { + "message": "Ievieto savu drošības atslēgu datora USB ligzdā! Ja tai ir poga, pieskaries tai!" + }, + "recoveryCodeDesc": { + "message": "Zaudēta piekļuve visiem divpakāpju nodrošinātājiem? Izmanto atkopšanas kodus, lai atspējotu visus sava konta divpakāpju nodrošinātājus!" + }, + "recoveryCodeTitle": { + "message": "Atgūšanas kods" + }, + "authenticatorAppTitle": { + "message": "Autentificētāja lietotne" + }, + "authenticatorAppDesc": { + "message": "Izmanto autentificētāja lietotni (piemēram, Authy vai Google autentifikators), lai izveidotu laikā balstītus apstiprinājuma kodus!", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP drošības atslēga" + }, + "yubiKeyDesc": { + "message": "Izmanto YubiKey, lai piekļūtu savam kontam! Darbojas ar YubiKey 4, 4 Nano, 4C un NEO ierīcēm." + }, + "duoDesc": { + "message": "Apstiprini ar Duo Security, izmantojot Duo Mobile lietotni, īsziņu, tālruņa zvanu vai U2F drošības atslēgu!", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Apstiprini ar Duo Security savā apvienībā, izmantojot Duo Mobile lietotni, īsziņu, tālruņa zvanu vai U2F drošības atslēgu!", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Izmantot jebkuru WebAuthn atbalstošu drošības atslēgu, lai piekļūtu kontam." + }, + "emailTitle": { + "message": "E-pasts" + }, + "emailDesc": { + "message": "Apstiprinājuma kodi tiks nosūtīti e-pastā." + }, + "loginUnavailable": { + "message": "Pierakstīšanās nav pieejama" + }, + "noTwoStepProviders": { + "message": "Šim kontam ir iespējota divpakāpju pierakstīšanās, bet šajā ierīcē netiek atbalstīts neviens no uzstādītajiem divpakāpju pārbaudes nodrošinātājiem." + }, + "noTwoStepProviders2": { + "message": "Lūgums pievienot papildus nodrošinātājus, kas tiek labāk atbalstīti dažādās ierīcēs (piemēram, autentificētāja lietotne)." + }, + "twoStepOptions": { + "message": "Divpakāpju pierakstīšanās iespējas" + }, + "selfHostedEnvironment": { + "message": "Pašuzturēta vide" + }, + "selfHostedEnvironmentFooter": { + "message": "Norādīt pašuzstādīta Bitwarden pamata URL." + }, + "customEnvironment": { + "message": "Pielāgota vide" + }, + "customEnvironmentFooter": { + "message": "Pieredzējušiem lietotājiem. Ir iespējams norādīt URL katram pakalpojumam atsevišķi." + }, + "baseUrl": { + "message": "Servera URL" + }, + "apiUrl": { + "message": "API servera URL" + }, + "webVaultUrl": { + "message": "Tīmekļa glabātavas servera URL" + }, + "identityUrl": { + "message": "Identitātes servera URL" + }, + "notificationsUrl": { + "message": "Paziņojumu servera URL" + }, + "iconsUrl": { + "message": "Ikonu servera URL" + }, + "environmentSaved": { + "message": "Vides URL ir saglabāti." + }, + "ok": { + "message": "Labi" + }, + "yes": { + "message": "Jā" + }, + "no": { + "message": "Nē" + }, + "overwritePassword": { + "message": "Pārrakstīt paroli" + }, + "learnMore": { + "message": "Uzzināt vairāk" + }, + "featureUnavailable": { + "message": "Iespēja nav pieejama" + }, + "loggedOut": { + "message": "Izrakstījies" + }, + "loginExpired": { + "message": "Pierakstīšanās sesija ir beigusies." + }, + "logOutConfirmation": { + "message": "Vai tiešām izrakstīties?" + }, + "logOut": { + "message": "Izrakstīties" + }, + "addNewLogin": { + "message": "Pievienot jaunu pierakstīšanās vienumu" + }, + "addNewItem": { + "message": "Pievienot jaunu vienumu" + }, + "addNewFolder": { + "message": "Pievienot jaunu mapi" + }, + "view": { + "message": "Skats" + }, + "account": { + "message": "Konts" + }, + "loading": { + "message": "Notiek ielāde..." + }, + "lockVault": { + "message": "Aizslēgt glabātavu" + }, + "passwordGenerator": { + "message": "Paroļu veidotājs" + }, + "contactUs": { + "message": "Sazināties ar mums" + }, + "getHelp": { + "message": "Saņemt palīdzību" + }, + "fileBugReport": { + "message": "Iesniegt kļūdas ziņojumu" + }, + "blog": { + "message": "Emuārs" + }, + "followUs": { + "message": "Sekot mums" + }, + "syncVault": { + "message": "Sinhronizēt glabātavu" + }, + "changeMasterPass": { + "message": "Mainīt galveno paroli" + }, + "changeMasterPasswordConfirmation": { + "message": "Galveno paroli ir iespējams mainīt bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "fingerprintPhrase": { + "message": "Atpazīšanas vārdkopa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Konta atpazīšanas vārdkopa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Doties uz tīmekļa glabātavu" + }, + "getMobileApp": { + "message": "Iegūt tālruņa lietotni" + }, + "getBrowserExtension": { + "message": "Iegūt pārlūka paplašinājumu" + }, + "syncingComplete": { + "message": "Sinhronizācija pabeigta" + }, + "syncingFailed": { + "message": "Sinhronizācija neizdevās" + }, + "yourVaultIsLocked": { + "message": "Glabātava ir slēgta. Nepieciešams norādīt galveno paroli, lai turpinātu." + }, + "unlock": { + "message": "Atslēgt" + }, + "loggedInAsOn": { + "message": "Pierakstījies $HOSTNAME$ kā $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Nederīga galvenā parole" + }, + "twoStepLoginConfirmation": { + "message": "Divpakāpju pieslēgšanās padara kontu krietni drošāku, pieprasot apstiprināt pierakstīšanos ar tādu citu ierīču vai pakalpojumu starpniecību kā drošības atslēga, autentificētāja lietotne, īsziņa, tālruņa zvans vai e-pasts. Divpakāpju pierakstīšanos var iespējot bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "twoStepLogin": { + "message": "Divpakāpju pierakstīšanās" + }, + "vaultTimeout": { + "message": "Glabātavas noildze" + }, + "vaultTimeoutDesc": { + "message": "Izvēlēties, kad glabātavai iestāsies noildze un tiks izpildīta atlasītā darbība." + }, + "immediately": { + "message": "Nekavējoties" + }, + "tenSeconds": { + "message": "10 sekundes" + }, + "twentySeconds": { + "message": "20 sekundes" + }, + "thirtySeconds": { + "message": "30 sekundes" + }, + "oneMinute": { + "message": "1 minūte" + }, + "twoMinutes": { + "message": "2 minūtes" + }, + "fiveMinutes": { + "message": "5 minūtes" + }, + "fifteenMinutes": { + "message": "15 minūtes" + }, + "thirtyMinutes": { + "message": "30 minūtes" + }, + "oneHour": { + "message": "1 stunda" + }, + "fourHours": { + "message": "4 stundas" + }, + "onIdle": { + "message": "Sistēmas dīkstāvē" + }, + "onSleep": { + "message": "Pēc sistēmas iemigšanas" + }, + "onLocked": { + "message": "Pēc sistēmas aizslēgšanas" + }, + "onRestart": { + "message": "Pārsāknējot" + }, + "never": { + "message": "Nekad" + }, + "security": { + "message": "Drošība" + }, + "clearClipboard": { + "message": "Notīrīt starpliktuvi", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automātiski noņemt starpliktuvē ievietotās vērtības.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Atspējot tīmekļa vietņu ikonas" + }, + "disableFaviconDesc": { + "message": "Tīmekļā vietņu ikonas nodrošina atpazīstamu attēlu pie katra glabātavas pieteikšanās vienuma." + }, + "enableMinToTray": { + "message": "Samazināt ikonu joslā" + }, + "enableMinToTrayDesc": { + "message": "Tā vietā, lai samazinātu logu, parādīt ikonu sistēmas joslā." + }, + "enableMinToMenuBar": { + "message": "Samazināt izvēļņjoslā" + }, + "enableMinToMenuBarDesc": { + "message": "Tā vietā, lai samazinātu logu, parādīt ikonu izvēļņjoslā." + }, + "enableCloseToTray": { + "message": "Aizverot pārvietot uz ikonu joslu" + }, + "enableCloseToTrayDesc": { + "message": "Tā vietā, lai aizvērtu logu, parādīt ikonu sistēmas joslā." + }, + "enableCloseToMenuBar": { + "message": "Aizvērt izvēļņjoslā" + }, + "enableCloseToMenuBarDesc": { + "message": "Tā vietā, lai aizvērtu logu, parādīt ikonu izvēļņjoslā." + }, + "enableTray": { + "message": "Iespējot parādīšanu ikonjoslā" + }, + "enableTrayDesc": { + "message": "Vienmēr rādīt ikonu sistēmas joslā." + }, + "startToTray": { + "message": "Sāknēt samazinātu ikonu joslā" + }, + "startToTrayDesc": { + "message": "Kad lietotne tiek sāknēta, rādīt tikai ikonu sistēmas ikonu joslā." + }, + "startToMenuBar": { + "message": "Sāknēt samazinātu izvēļņjoslā" + }, + "startToMenuBarDesc": { + "message": "Kad lietotne tiek sāknēta, attēlot tikai ikonu izvēļņjoslā." + }, + "openAtLogin": { + "message": "Automātiski sāknēt pēc pierakstīšanās" + }, + "openAtLoginDesc": { + "message": "Automātiski sāknēt Bitwarden darbvirsmas lietotni pēc pierakstīšanās." + }, + "alwaysShowDock": { + "message": "Vienmēr rādīt lietotņu joslā" + }, + "alwaysShowDockDesc": { + "message": "Rādīt Bitwarden ikonu lietotņu joslā pat tad, ka notiek samazināšana uz izvēļņjoslu." + }, + "confirmTrayTitle": { + "message": "Apstiprināt parādīšanas ikonjoslā atspējošanu" + }, + "confirmTrayDesc": { + "message": "Šī iestatījuma atspējošana padarīs nepieejamas arī citus ar ikonjoslu saistītus uzstādījumus." + }, + "language": { + "message": "Valoda" + }, + "languageDesc": { + "message": "Mainīt lietotnes valodu. Ir nepieciešama pārsāknēšana." + }, + "theme": { + "message": "Izskats" + }, + "themeDesc": { + "message": "Mainīt lietotnes izskata krāsas." + }, + "dark": { + "message": "Tumšs", + "description": "Dark color" + }, + "light": { + "message": "Gaišs", + "description": "Light color" + }, + "copy": { + "message": "Ievietot starpliktuvē", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Pārbaudīt, vai ir pieejami atjauninājumi" + }, + "version": { + "message": "Laidiens $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Pārsāknēt, lai atjauninātu" + }, + "restartToUpdateDesc": { + "message": "Laidiens $VERSION_NUM$ ir gatavs uzstādīšanai. Ir jāpārsāknē lietotne, lai pabeigtu atjaunināšanu. Vai pārsāknēt un atjaunināt?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Pieejams atjauninājums" + }, + "updateAvailableDesc": { + "message": "Atrasts atjauninājums. Vai lejupielādēt to?" + }, + "restart": { + "message": "Pārsāknēt" + }, + "later": { + "message": "Vēlāk" + }, + "noUpdatesAvailable": { + "message": "Atjauninājumi pašlaik nav pieejami. Tiek izmantots jaunākais laidiens." + }, + "updateError": { + "message": "Atjaunināšanas kļūda" + }, + "unknown": { + "message": "Nezināms" + }, + "copyUsername": { + "message": "Ievietot lietotājvārdu starpliktuvē" + }, + "copyNumber": { + "message": "Ievietot numuru starpliktuvē", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Ievietot drošības kodu starpliktuvē", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium dalība" + }, + "premiumManage": { + "message": "Pārvaldīt dalību" + }, + "premiumManageAlert": { + "message": "Dalību ir iespējams pārvaldīt bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "premiumRefresh": { + "message": "Atjaunot dalību" + }, + "premiumNotCurrentMember": { + "message": "Tu pašlaik neesi Premium dalībnieks." + }, + "premiumSignUpAndGet": { + "message": "Piesakies Premium dalībai un saņem:" + }, + "premiumSignUpStorage": { + "message": "1 GB šifrētas krātuves datņu pielikumiem." + }, + "premiumSignUpTwoStep": { + "message": "Tādas papildus divpakāpju pierakstīšanās iespējas kā YubiKey, FIDO U2F un Duo." + }, + "premiumSignUpReports": { + "message": "Paroļu higiēnas, kontu veselības un datu pārkāpumu pārskati, lai uzturētu glabātavu drošu." + }, + "premiumSignUpTotp": { + "message": "TOTP apstiprinājuma kodu (2FA) veidotājs piekļuves ierakstiem glabātavā." + }, + "premiumSignUpSupport": { + "message": "Priekšrocīgs lietotāju atbalsts." + }, + "premiumSignUpFuture": { + "message": "Visas nākotnes Premium iespējas. Vairāk drīzumā!" + }, + "premiumPurchase": { + "message": "Iegādāties Premium" + }, + "premiumPurchaseAlert": { + "message": "Premium dalību ir iespējams iegādāties bitwarden.com tīmekļa glabātavā. Vai apmeklēt tīmekļa vietni?" + }, + "premiumCurrentMember": { + "message": "Tu esi Premium dalībnieks!" + }, + "premiumCurrentMemberThanks": { + "message": "Paldies, ka atbalsti Bitwarden!" + }, + "premiumPrice": { + "message": "Viss par tikai $PRICE$ gadā!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Atsvaidzināšana pabeigta" + }, + "passwordHistory": { + "message": "Paroles izmaiņu vēsture" + }, + "clear": { + "message": "Notīrīt", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Nav paroļu, ko parādīt." + }, + "undo": { + "message": "Atsaukt" + }, + "redo": { + "message": "Atatsaukt" + }, + "cut": { + "message": "Izgriezt", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Ielīmēt", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Atlasīt visu" + }, + "zoomIn": { + "message": "Pietuvināt" + }, + "zoomOut": { + "message": "Attālināt" + }, + "resetZoom": { + "message": "Atiestatīt tālummaiņu" + }, + "toggleFullScreen": { + "message": "Atvērt pilnekrānu" + }, + "reload": { + "message": "Pārlādēt" + }, + "toggleDevTools": { + "message": "Ieslēgt izstrādātāja rīkus" + }, + "minimize": { + "message": "Samazināt", + "description": "Minimize window" + }, + "zoom": { + "message": "Tālummaiņa" + }, + "bringAllToFront": { + "message": "Novietot visu priekšā", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Par Bitwarden" + }, + "services": { + "message": "Pakalpojumi" + }, + "hideBitwarden": { + "message": "Paslēpt Bitwarden" + }, + "hideOthers": { + "message": "Paslēpt citus" + }, + "showAll": { + "message": "Rādīt visu" + }, + "quitBitwarden": { + "message": "Izslēgt Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ ievietota starpliktuvē", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Palīdzība" + }, + "window": { + "message": "Logs" + }, + "checkPassword": { + "message": "Pārbaudīt, vai parole ir bijusi nopludināta." + }, + "passwordExposed": { + "message": "Šī parole datu pārkāpumos ir atklāta $VALUE$ reizi(es). To vajag mainīt.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Šī parole netika atrasta nevienā no zināmajiem datu pārkāpumiem. Tai vajadzētu būt droši izmantojamai." + }, + "baseDomain": { + "message": "Pamata domēns", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domēna vārds", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Saimniekdators", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tiešs" + }, + "startsWith": { + "message": "Sākas ar" + }, + "regEx": { + "message": "Regulārā izteiksme", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Atbilstības noteikšana", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Noklusējuma atbilstības noteikšana", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Pārslēgt iespējas" + }, + "organization": { + "message": "Apvienība", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Noklusējums" + }, + "exit": { + "message": "Iziet" + }, + "showHide": { + "message": "Rādīt / paslēpt", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Paslēpt rīkjoslā" + }, + "alwaysOnTop": { + "message": "Vienmēr priekšā", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Atjaunināts", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parole atjaunināta", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Izgūt glabātavas saturu" + }, + "fileFormat": { + "message": "Datnes veids" + }, + "warning": { + "message": "UZMANĪBU", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Apstiprināt glabātavas satura izgūšanu" + }, + "exportWarningDesc": { + "message": "Šī izguve satur glabātavas datus nešifrētā veidā. Izdoto datni nevajadzētu glabāt vai sūtīt nedrošos veidos (piemēram, e-pastā). Izdzēst to uzreiz pēc izmantošanas." + }, + "encExportKeyWarningDesc": { + "message": "Šī izguve šifrē datus ar konta šifrēšanas atslēgu. Ja tā jebkad tiks mainīta, izvadi vajadzētu veikt vēlreiz, jo vairs nebūs iespējams atšifrēt šo datni." + }, + "encExportAccountWarningDesc": { + "message": "Katram Bitwarden kontam ir neatkārtojamas šifrēšanas atslēgas, tādēļ nav iespējams ievietot šifrētu izguvi citā kontā." + }, + "noOrganizationsList": { + "message": "Tu neesi iekļauts nevienā apvienībā. Apvienības sniedz iespēju droši kopīgot vienumus ar citiem lietotājiem." + }, + "noCollectionsInList": { + "message": "Nav krājumu, ko parādīt." + }, + "ownership": { + "message": "Īpašumtiesības" + }, + "whoOwnsThisItem": { + "message": "Kam pieder šis vienums?" + }, + "strong": { + "message": "Spēcīga", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Laba", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Vāja", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Vāja galvenā parole" + }, + "weakMasterPasswordDesc": { + "message": "Izvēlētā galvenā parole ir vāja. Ir ieteicams izmantot spēcīgu galveno paroli (vai paroles vārdu salikumu), lai pienācīgi aizsargātu Bitwarden kontu. Vai tiešām izmanto šo galveno paroli?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Atslēgt ar PIN" + }, + "setYourPinCode": { + "message": "Uzstādi savu PIN kodu Bitwarden atslēgšanai! Tavi PIN iestatījumi tiks atiestatīti, ja Tu pilnībā izrakstīsies no lietotnes." + }, + "pinRequired": { + "message": "Ir nepieciešams PIN kods." + }, + "invalidPin": { + "message": "Nederīgs PIN kods." + }, + "unlockWithWindowsHello": { + "message": "Atslēgt ar Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Apstiprināt Bitwarden." + }, + "unlockWithTouchId": { + "message": "Atslēgt ar Touch ID" + }, + "touchIdConsentMessage": { + "message": "atslēgt glabātavu" + }, + "noAutoPromptWindowsHello": { + "message": "Palaišanas brīdī nevaicāt par Windows Hello." + }, + "noAutoPromptTouchId": { + "message": "Palaišanas brīdī nevaicāt par Touch ID." + }, + "lockWithMasterPassOnRestart": { + "message": "Aizslēgt ar galveno paroli pēc pārsāknēšanas" + }, + "preferences": { + "message": "Uzstādījumi" + }, + "enableMenuBar": { + "message": "Iespējot izvēļņjoslas ikonu" + }, + "enableMenuBarDesc": { + "message": "Vienmēr rādīt ikonu izvēļņjoslā." + }, + "hideToMenuBar": { + "message": "Paslēpt izvēļņjoslā" + }, + "selectOneCollection": { + "message": "Ir jāizvēlas vismaz viens krājums." + }, + "premiumUpdated": { + "message": "Tu esi pārgājis uz Premium." + }, + "restore": { + "message": "Atjaunot" + }, + "premiumManageAlertAppStore": { + "message": "Abonementu ir iespējams pārvaldīt App Store. Vai doties uz App Store?" + }, + "legal": { + "message": "Tiesiskums", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Izmantošanas nosacījumi" + }, + "privacyPolicy": { + "message": "Privātuma nosacījumi" + }, + "unsavedChangesConfirmation": { + "message": "Vai tiešām iziet? Ja Tu aiziesi, tad pašreizējā informācija netiks saglabāta." + }, + "unsavedChangesTitle": { + "message": "Nesaglabātas izmaiņas" + }, + "clone": { + "message": "Pavairot" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Viens vai vairāki apvienības nosacījumi ietekmē veidotāja iestatījumus." + }, + "vaultTimeoutAction": { + "message": "Glabātavas noildzes darbība" + }, + "vaultTimeoutActionLockDesc": { + "message": "Ir nepieciešams atkārtoti ievadīt galveno paroli, lai piekļūt aizslēgtai glabātavai." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Pēc izrakstīšanās no glabātavas ir nepieciešams tai pieslēgties atkārtoti." + }, + "lock": { + "message": "Aizslēgt", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Atkritne", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Meklēt atkritnē" + }, + "permanentlyDeleteItem": { + "message": "Neatgriezeniski izdzēst vienumu" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Vai tiešām neatgriezeniski izdzēst šo vienumu?" + }, + "permanentlyDeletedItem": { + "message": "Vienums neatgriezeniski izdzēsts" + }, + "restoreItem": { + "message": "Atjaunot vienumu" + }, + "restoreItemConfirmation": { + "message": "Vai tiešām atjaunot šo vienumu?" + }, + "restoredItem": { + "message": "Vienums atjaunots" + }, + "permanentlyDelete": { + "message": "Neatgriezeniski izdzēst" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Izrakstīšanās noņems piekļuvi glabātavai un pieprasa tiešsaistes pierakstīšanos pēc noildzes laika. Vai tiešām izmantot šo iestatījumu?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Noildzes darbības apstiprināšana" + }, + "enterpriseSingleSignOn": { + "message": "Uzņēmuma vienotā pierakstīšanās" + }, + "setMasterPassword": { + "message": "Uzstādīt galveno paroli" + }, + "ssoCompleteRegistration": { + "message": "Lai pabeigtu vienotās pieteikšanās uzstādīšanu, ir jānorāda galvenā parole, lai piekļūtu glabātavai un aizsargātu to." + }, + "newMasterPass": { + "message": "Jaunā galvenā parole" + }, + "confirmNewMasterPass": { + "message": "Apstiprināt jauno galveno paroli" + }, + "masterPasswordPolicyInEffect": { + "message": "Vienā vai vairākos apvienības nosacījumos ir norādīts, ka galvenajai parolei ir jāatbilst šādām prasībām:" + }, + "policyInEffectMinComplexity": { + "message": "Mazākais pieļaujamais sarežģītības novērtējums ir $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Mazākais pieļaujamais garums ir $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Satur vienu vai vairākus lielos burtus" + }, + "policyInEffectLowercase": { + "message": "Satur vienu vai vairākus mazos burtus" + }, + "policyInEffectNumbers": { + "message": "Satur vienu vai vairākus ciparus" + }, + "policyInEffectSpecial": { + "message": "Satur vienu vai vairākas no šīm īpašajām rakstzīmēm: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Jaunā galvenā parole neatbilst nosacījumu prasībām." + }, + "acceptPolicies": { + "message": "Atzīmējot šo rūtiņu, Tu piekrīti sekojošajam:" + }, + "acceptPoliciesError": { + "message": "Nav pieņemti izmantošanas nosacījumi un privātuma politika." + }, + "enableBrowserIntegration": { + "message": "Iespējot pārlūka saistīšanu" + }, + "enableBrowserIntegrationDesc": { + "message": "Pārlūka saistīšana tiek izmantota pārlūka biometrijas nodrošināšanai." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Pārlūka saistīšana nav atbalstīta" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Diemžēl pārlūka saistīšana pagaidām ir nodrošināta tikai Mac App Store laidienā." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Pārlūka saistīšana nav atbalstīta" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Diemžēl pārlūka saistīšana pagaidām nav nodrošināta Windows veikala laidienā." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Pieprasīt apstiprinājumu pārlūka saistīšanai" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Iespējo papildus drošības slāni, pieprasot atpazīšanas vārdkopas pārbaudi, kad tiek izveidota saikne starp darbvirsmu un pārlūku. Kad iespējots, ir nepieciešama lietotāja mijiedarbīga un apstiprināšana katru reizi, kad tiek izveidots savienojums." + }, + "approve": { + "message": "Apstiprināt" + }, + "verifyBrowserTitle": { + "message": "Pārbaudīt pārlūka savienojumu" + }, + "verifyBrowserDesc": { + "message": "Lūgums pārliecināties, ka attēlotā atpazīšanas vārdkopa ir tāda pati kā tā, kas ir redzama pārlūka paplašinājumā." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrija nav iespējota" + }, + "biometricsNotEnabledDesc": { + "message": "Vispirms ir nepieciešams iespējot biometriju darbvirsmas iestatījumos, lai to varētu izmantot pārlūkā." + }, + "personalOwnershipSubmitError": { + "message": "Uzņēmuma nosacījumi liedz saglabāt vienumus privātajā glabātavā. Ir jānorāda piederība apvienībai un jāizvēlas kāds no pieejamajiem krājumiem." + }, + "hintEqualsPassword": { + "message": "Paroles norāde nedrīkst būt tāda pati kā parole." + }, + "personalOwnershipPolicyInEffect": { + "message": "Apvienības nosacījumi ietekmē Tavas īpašumtiesību iespējas." + }, + "allSends": { + "message": "Visi \"Send\"", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Datne" + }, + "sendTypeText": { + "message": "Teksts" + }, + "searchSends": { + "message": "Meklēt \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Labot \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mana glabātava" + }, + "text": { + "message": "Teksts" + }, + "deletionDate": { + "message": "Dzēšanas datums" + }, + "deletionDateDesc": { + "message": "\"Send\" tiks pastāvīgi izdzēsts norādītajā dienā un laikā.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Derīguma beigu datums" + }, + "expirationDateDesc": { + "message": "Ja uzstādīts, piekļuve šim \"Send\" beigsies norādītajā dienā un laikā.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Lielākais pieļaujamais piekļuvju skaits" + }, + "maxAccessCountDesc": { + "message": "Ja uzstādīts, lietotāji nevarēs piekļūt šim \"Send\", kad tiks sasniegts lielākais pieļaujamais piekļūšanas reižu skaits.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Pašreizējais piekļuvju skaits" + }, + "disableSend": { + "message": "Atspējot šo \"Send\", lai neviens tam nevarētu piekļūt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Pēc izvēles pieprasīt lietotājiem paroli, lai viņi varētu piekļūt šim \"Send\".", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Personīgās piezīmes par šo \"Send\".", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "\"Send\" saite", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "\"Send\" saite", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Kad piekļūst šim \"Send\", pēc noklusējuma paslēpt saturu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "\"Send\" izveidots", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "\"Send\" labots", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "\"Send\" izdzēsts", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Jauna parole" + }, + "whatTypeOfSend": { + "message": "Kāds veids ir šim \"Send\"?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Izveidot \"Send\"", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teksts, kuru ir vēlme nosūtīt." + }, + "sendFileDesc": { + "message": "Datne, kuru ir vēlme nosūtīt." + }, + "days": { + "message": "$DAYS$ dienas", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 diena" + }, + "custom": { + "message": "Pielāgots" + }, + "deleteSendConfirmation": { + "message": "Vai tiešām izdzēst šo \"Send\"?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Ievietot \"Send\" saiti starpliktuvē", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Saglabājot ievietot šī \"Send\" saiti starpliktuvē." + }, + "sendDisabled": { + "message": "\"Send\" atspējots", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Uzņēmuma nosacījumu kopas dēļ ir tikai iespējams dzēst esošu \"Send\".", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Ievietot saiti starpliktuvē" + }, + "disabled": { + "message": "Atspējots" + }, + "maxAccessCountReached": { + "message": "Sasniegts lielākais pieļaujamais piekļuvju skaits" + }, + "expired": { + "message": "Beidzies izmantošanas laiks" + }, + "pendingDeletion": { + "message": "Gaida dzēšanu" + }, + "webAuthnAuthenticate": { + "message": "Autentificēt WebAuthn" + }, + "hideEmail": { + "message": "Slēpt e-pasta adresi no saņēmējiem." + }, + "sendOptionsPolicyInEffect": { + "message": "Viens vai vairāki apvienības nosacījumi ietekmē \"Send\" iestatījumus." + }, + "emailVerificationRequired": { + "message": "Nepieciešama e-pasta adreses apstiprināšana" + }, + "emailVerificationRequiredDesc": { + "message": "Ir jāapstiprina e-pasta adrese, lai izmantotu šo iespēju." + }, + "passwordPrompt": { + "message": "Galvenās paroles pārvaicāšana" + }, + "passwordConfirmation": { + "message": "Galvenās paroles apstiprināšana" + }, + "passwordConfirmationDesc": { + "message": "Šī darbība ir aizsargāta. Lai turpinātu, ir jāievada galvenā parole, lai apstiprinātu identitāti." + }, + "updatedMasterPassword": { + "message": "Galvenā parole atjaunināta" + }, + "updateMasterPassword": { + "message": "Atjaunināt galveno paroli" + }, + "updateMasterPasswordWarning": { + "message": "Apvienības pārvaldnieks nesen nomainīja galveno paroli. Lai piekļūtu glabātavai, tā ir jāatjaunina. Turpinot tiks izbeigta pašreizējā sesija un tiks pieprasīta atkārtota pierakstīšanās. Esošās sesijas citās iekārtās var turpināt darboties līdz vienai stundai." + }, + "hours": { + "message": "Stundas" + }, + "minutes": { + "message": "Minūtes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Apvienības nosacījumi ietekmē glabātavas noildzi. Lielākā atļautā glabātavas noildze ir $HOURS$ stunda(s) un $MINUTES$ minūte(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Glabātavas noildze pāŗsniedz apvienības uzstādītos ierobežojumus." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automātiska ievietošana sarakstā" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Šajā apvienībā ir uzņēmuma nosacījums, kas automātiski ievieto lietotājus paroles atiestatīšanas sarakstā. Tas ļauj apvienības pārvaldniekiem mainīt lietotāju galveno paroli." + }, + "vaultExportDisabled": { + "message": "Glabātavas izgūšana ir atspējota" + }, + "personalVaultExportPolicyInEffect": { + "message": "Viens vai vairāki apvienības nosacījumi neļauj izgūt privātās glabātavas saturu." + }, + "addAccount": { + "message": "Pievienot kontu" + }, + "removeMasterPassword": { + "message": "Noņemt galveno paroli" + }, + "removedMasterPassword": { + "message": "Galvenā parole tika noņemta." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ izmanto vienoto pieteikšanos ar pašizvietotu atslēgu serveri. Tās dalībniekiem vairs nav nepieciešama galvenā parole, lai pieslēgtos.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Pamest apvienību" + }, + "leaveOrganizationConfirmation": { + "message": "Vai tiešām pamest šo apvienību?" + }, + "leftOrganization": { + "message": "Apvienība ir pamesta." + }, + "ssoKeyConnectorUnavailable": { + "message": "Nav iespējams sasniegt Key Connector, tāpēc vēlāk jāmēģina atkal." + }, + "lockAllVaults": { + "message": "Aizslēgt visas glabātavas" + }, + "accountLimitReached": { + "message": "Vienlaicīgi var būt pierakstījušies ne vairāk kā 5 konti." + }, + "accountPreferences": { + "message": "Uzstādījumi" + }, + "appPreferences": { + "message": "Lietotnes iestatījumi (visi konti)" + }, + "accountSwitcherLimitReached": { + "message": "Sasniegti konta ierobežojumi. Izrakstīties, lai pievienotu citu." + }, + "settingsTitle": { + "message": "Lietotnes iestatījumi kontam $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Pārslēgties starp kontiem" + }, + "options": { + "message": "Iespējas" + }, + "sessionTimeout": { + "message": "Sesijai iestājās noildze. Lūgums mēģināt pierakstīties vēlreiz." + }, + "exportingPersonalVaultTitle": { + "message": "Izdod personīgo glabātavu" + }, + "exportingPersonalVaultDescription": { + "message": "Tiks izdoti tikai personīgie glabātavas vienumi, kas ir saistīti ar $EMAIL$. Apvienības glabātavas vienumi netiks iekļauti.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Veidotājs" + }, + "whatWouldYouLikeToGenerate": { + "message": "Ko ir nepieciešams izveidot?" + }, + "passwordType": { + "message": "Paroles veids" + }, + "regenerateUsername": { + "message": "Pārizveidot lietotājvārdu" + }, + "generateUsername": { + "message": "Izveidot lietotājvārdu" + }, + "usernameType": { + "message": "Lietotājvārda veids" + }, + "plusAddressedEmail": { + "message": "E-pasta adrese ar plusu" + }, + "plusAddressedEmailDesc": { + "message": "Izmantot e-pasta pakalpojuma nodrošinātāja apakšadresēšanas spējas." + }, + "catchallEmail": { + "message": "Visu tverošā e-pasta adrese" + }, + "catchallEmailDesc": { + "message": "Izmantot uzstādīto domēna visu tverošo iesūtni." + }, + "random": { + "message": "Nejauši" + }, + "randomWord": { + "message": "Nejaušs vārds" + }, + "websiteName": { + "message": "Tīmekļa vietnes nosaukums" + }, + "service": { + "message": "Pakalpojums" + } +} diff --git a/apps/desktop/src/locales/me/messages.json b/apps/desktop/src/locales/me/messages.json new file mode 100644 index 0000000000..5a73033d19 --- /dev/null +++ b/apps/desktop/src/locales/me/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filteri" + }, + "allItems": { + "message": "Sve stavke" + }, + "favorites": { + "message": "Favoriti" + }, + "types": { + "message": "Tipovi" + }, + "typeLogin": { + "message": "Prijava" + }, + "typeCard": { + "message": "Kartica" + }, + "typeIdentity": { + "message": "Identitet" + }, + "typeSecureNote": { + "message": "Sigurna belješka" + }, + "folders": { + "message": "Fascikle" + }, + "collections": { + "message": "Kolekcije" + }, + "searchVault": { + "message": "Pretraži trezor" + }, + "addItem": { + "message": "Dodaj stavku" + }, + "shared": { + "message": "Podijeljeno" + }, + "share": { + "message": "Podijeli" + }, + "moveToOrganization": { + "message": "Prebaci u Organizaciju" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Izaberite organizaciju u koju želite da premjestite ovu stavku. Prelazak u organizaciju prenosi vlasništvo nad stavkom na tu organizaciju. Nećete više biti direktan vlasnik ove stavke kada bude premještena." + }, + "attachments": { + "message": "Prilog" + }, + "viewItem": { + "message": "Vidi stavku" + }, + "name": { + "message": "Ime" + }, + "uri": { + "message": "Link" + }, + "uriPosition": { + "message": "Link $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novi link" + }, + "username": { + "message": "Korisničko ime" + }, + "password": { + "message": "Lozinka" + }, + "passphrase": { + "message": "Pristupna fraza" + }, + "editItem": { + "message": "Uredi stavku" + }, + "emailAddress": { + "message": "Email adresa" + }, + "verificationCodeTotp": { + "message": "Verifikacioni kod (TOTP)" + }, + "website": { + "message": "Internet strana" + }, + "notes": { + "message": "Bilješka" + }, + "customFields": { + "message": "Prilagođeno polje" + }, + "launch": { + "message": "Pokreni" + }, + "copyValue": { + "message": "Kopiraj vrijednost", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimizirajte prilikom kopiranja u međuspremnik" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Isključi vidljivost" + }, + "toggleCollapse": { + "message": "Sažmi/Proširi", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Ime vlasnika kartice" + }, + "number": { + "message": "Broj" + }, + "brand": { + "message": "Vrsta kartice" + }, + "expiration": { + "message": "Datum do kada važi kartica" + }, + "securityCode": { + "message": "Siguronosni kod" + }, + "identityName": { + "message": "Ime identiteta" + }, + "company": { + "message": "Kompanija" + }, + "ssn": { + "message": "Broj socijalnog osiguranja" + }, + "passportNumber": { + "message": "Broj pasoša" + }, + "licenseNumber": { + "message": "Broj licence" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresa" + }, + "premiumRequired": { + "message": "Premium obavezan" + }, + "premiumRequiredDesc": { + "message": "Za upotrebu ove funkcije potrebno je premium članstvo." + }, + "errorOccurred": { + "message": "Dogodila se greška." + }, + "error": { + "message": "Greška" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Jun" + }, + "july": { + "message": "Jul" + }, + "august": { + "message": "Avgust" + }, + "september": { + "message": "Septembar" + }, + "october": { + "message": "Oktobar" + }, + "november": { + "message": "Novembar" + }, + "december": { + "message": "Decembar" + }, + "ex": { + "message": "Primjer", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Naslov" + }, + "mr": { + "message": "G" + }, + "mrs": { + "message": "Gđa" + }, + "ms": { + "message": "Gđica" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Mjesec isticanja" + }, + "expirationYear": { + "message": "Godina isticanja" + }, + "select": { + "message": "Odaberi" + }, + "other": { + "message": "Drugo" + }, + "generatePassword": { + "message": "Generiši lozinku" + }, + "type": { + "message": "Tip" + }, + "firstName": { + "message": "Ime" + }, + "middleName": { + "message": "Srednje ime" + }, + "lastName": { + "message": "Prezime" + }, + "fullName": { + "message": "Puno ime" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Grad" + }, + "stateProvince": { + "message": "Država/Provincija" + }, + "zipPostalCode": { + "message": "Poštanski kod" + }, + "country": { + "message": "Država" + }, + "save": { + "message": "Sačuvaj" + }, + "cancel": { + "message": "Poništi" + }, + "delete": { + "message": "Obriši" + }, + "favorite": { + "message": "Favorit" + }, + "edit": { + "message": "Uredi" + }, + "authenticatorKeyTotp": { + "message": "Autentifikacioni ključ (TOTP)" + }, + "folder": { + "message": "Fascikla" + }, + "newCustomField": { + "message": "Novo prilagođeno polje" + }, + "value": { + "message": "Vrijednost" + }, + "dragToSort": { + "message": "Prevucite za sortiranje" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Sakriveno" + }, + "cfTypeBoolean": { + "message": "Binarna promjenljiva" + }, + "cfTypeLinked": { + "message": "Povezan", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Povezana vrijednost", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Ukloni" + }, + "nameRequired": { + "message": "Potrebno je ime." + }, + "addedItem": { + "message": "Dodata stavka" + }, + "editedItem": { + "message": "Uređena stavka" + }, + "deleteItem": { + "message": "Obriši stavku" + }, + "deleteFolder": { + "message": "Obriši fasciklu" + }, + "deleteAttachment": { + "message": "Obriši prilog" + }, + "deleteItemConfirmation": { + "message": "Jeste li sigurni da želite da izbrišete ovu stavku?" + }, + "deletedItem": { + "message": "Obrisana stavka" + }, + "overwritePasswordConfirmation": { + "message": "Jeste li sigurni da želite da zamijenite trenutnu lozinku?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Nema fascikle", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Dodaj fasciklu" + }, + "editFolder": { + "message": "Uredi fasciklu" + }, + "regeneratePassword": { + "message": "Regereniši lozinku" + }, + "copyPassword": { + "message": "Kopiraj lozinku" + }, + "copyUri": { + "message": "Kopiraj link" + }, + "copyVerificationCodeTotp": { + "message": "Iskopiraj Verifikacioni Kod (TOTP)" + }, + "length": { + "message": "Dužina" + }, + "numWords": { + "message": "Broj riječi" + }, + "wordSeparator": { + "message": "Separator riječi" + }, + "capitalize": { + "message": "Velika slova", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Uključi broj" + }, + "close": { + "message": "Zatvori" + }, + "minNumbers": { + "message": "Minimum brojeva" + }, + "minSpecial": { + "message": "Minimum specijalnih", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Izbjegni dvosmislene karaktere" + }, + "searchCollection": { + "message": "Pretraži kolekciju" + }, + "searchFolder": { + "message": "Pretraži fasciklu" + }, + "searchFavorites": { + "message": "Pretraži favorite" + }, + "searchType": { + "message": "Pretraži tip", + "description": "Search item type" + }, + "newAttachment": { + "message": "Dodaj novi prilog" + }, + "deletedAttachment": { + "message": "Obrisani prilog" + }, + "deleteAttachmentConfirmation": { + "message": "Da li ste sigurni da želite da obrišete ovaj prilog?" + }, + "attachmentSaved": { + "message": "Prilog je sačuvan." + }, + "file": { + "message": "Datoteka" + }, + "selectFile": { + "message": "Izaberi datoteku." + }, + "maxFileSize": { + "message": "Maximalna veličina datoteke je 500 MB." + }, + "updateKey": { + "message": "Ovu funkciju ne možete da koristite dok ne ažurirate ključ za šifrovanje." + }, + "editedFolder": { + "message": "Izmijenjena fascikla" + }, + "addedFolder": { + "message": "Dodata fascikla" + }, + "deleteFolderConfirmation": { + "message": "Jeste li sigurni da želite da izbrišete ovu fasciklu?" + }, + "deletedFolder": { + "message": "Obrisana fascikla" + }, + "loginOrCreateNewAccount": { + "message": "Prijavite se ili otvorite novi nalog da biste pristupili svom sigurnom trezoru." + }, + "createAccount": { + "message": "Kreiraj nalog" + }, + "logIn": { + "message": "Prijavi se" + }, + "submit": { + "message": "Podnesi" + }, + "masterPass": { + "message": "Glavna lozinka" + }, + "masterPassDesc": { + "message": "Glavna lozinka je lozinka koju koristite za pristup trezoru. Veoma je važno da ne zaboravite svoju glavnu lozinku. Nema načina da povratite lozinku u slučaju da je zaboravite." + }, + "masterPassHintDesc": { + "message": "Podsjetnik na glavnu lozinku vam može pomoći da zapamtite lozinku ako je zaboravite." + }, + "reTypeMasterPass": { + "message": "Prekucaj glavnu lozinku" + }, + "masterPassHint": { + "message": "Podsjetnik glavne lozinke (opcija)" + }, + "settings": { + "message": "Podešavanja" + }, + "passwordHint": { + "message": "Podsjetnik na lozinku" + }, + "enterEmailToGetHint": { + "message": "Unesi email svog naloga kako bi ste primili podsjetnik na glavnu lozinku." + }, + "getMasterPasswordHint": { + "message": "Podsjetnik na glavnu lozinku" + }, + "emailRequired": { + "message": "Potrebna je email adresa." + }, + "invalidEmail": { + "message": "Nepravilna email adresa." + }, + "masterPassRequired": { + "message": "Potrebna je glavna lozinka." + }, + "masterPassLength": { + "message": "Glavna lozinka mora imati najmanje 8 karaktera." + }, + "masterPassDoesntMatch": { + "message": "Potvrda glavne lozinke ne odgovara." + }, + "newAccountCreated": { + "message": "Vaš novi nalog je kreiran! Sada se možete prijaviti." + }, + "masterPassSent": { + "message": "Poslali smo vam email sa podsjetnikom na glavnu lozinku." + }, + "unexpectedError": { + "message": "Došlo je do neočekivane greške." + }, + "itemInformation": { + "message": "Informacija o stavki" + }, + "noItemsInList": { + "message": "Nema stavki u listi." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verifikacioni kod (TOTP)" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Potreban je verifikacioni kod." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Nastavi" + }, + "enterVerificationCodeApp": { + "message": "Unesi kod sa 6 cifri iz vaše aplikacije za autentifikaciju." + }, + "enterVerificationCodeEmail": { + "message": "Unesi kod sa 6 cifri koji vam je poslat na email $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verifikacioni email poslat na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamti me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Pošalji ponovo verifikacioni kod na email" + }, + "useAnotherTwoStepMethod": { + "message": "Koristi drugi metod prijave u dva koraka" + }, + "insertYubiKey": { + "message": "Priključi svoj YubiKey u USB port na kompjuteru i onda takni njegovo dugme." + }, + "insertU2f": { + "message": "Priključi svoj sigurnonosni ključ u USB port na kompjuteru. Ako ima dugme, takni ga." + }, + "recoveryCodeDesc": { + "message": "Izgubili ste pristup svim dobavljačima prijave u dva koraka? Upotrijebite sigurnonosni kod kako biste onemogućili sve prijave u dva koraka na vaš račun." + }, + "recoveryCodeTitle": { + "message": "Sigurnosni kod" + }, + "authenticatorAppTitle": { + "message": "Aplikacija za autentifikaciju" + }, + "authenticatorAppDesc": { + "message": "Koristi aplikaciju za autentifkaciju (kao što su Authy ili Google autentificator) da generišeš verfikacione kodove bazirane na vremenu.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP siguronosni ključ" + }, + "yubiKeyDesc": { + "message": "Koristi YubiKey da pristupis svom nalogu. Radi sa YubiKey 4, 4 Nano, 4C i NEO uređajima." + }, + "duoDesc": { + "message": "Potvrdite sa Duo Security, korišćenjem Duo Mobile aplikacije, SMS-a, telefonskog poziva ili U2F sigurnosnog ključa.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Potvrdite sa Duo Security za svoju organizaciju pomoću aplikacije Duo Mobile, SMS-a, telefonskog poziva ili U2F sigurnosnog ključa.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Koristite bilo koji bezbjedonosni ključ za koji je omogućen WebAuthn da biste pristupili svom nalogu." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verifikacioni kodovi će vam biti poslati na email adresu." + }, + "loginUnavailable": { + "message": "Prijava nije dostupna" + }, + "noTwoStepProviders": { + "message": "Na ovom nalogu je omogućena prijava u dva koraka, međutim, ovaj uređaj ne podržava nijednog od konfigurisanih dobavljača u dva koraka." + }, + "noTwoStepProviders2": { + "message": "Dodajte dodatne dobavljače koji su bolje podržani na svim uređajima (poput aplikacije za autentifikaciju)." + }, + "twoStepOptions": { + "message": "Opcije prijave u dva koraka" + }, + "selfHostedEnvironment": { + "message": "Okruženje lokalne instalacije (SELF HOST)" + }, + "selfHostedEnvironmentFooter": { + "message": "Navedite osnovni URL vaše lokalne instalacije (HOST) Bitwardena." + }, + "customEnvironment": { + "message": "Prilagođeno okruženje" + }, + "customEnvironmentFooter": { + "message": "Za napredne korisnike. Možete odrediti osnovni URL svake usluge nezavisno." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API server URL" + }, + "webVaultUrl": { + "message": "URL trezora na internetu" + }, + "identityUrl": { + "message": "URL servera indentifikacije" + }, + "notificationsUrl": { + "message": "URL servera obavještenja" + }, + "iconsUrl": { + "message": "URL servera ikonica" + }, + "environmentSaved": { + "message": "URL-ovi okruženja su sačuvani." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Ne" + }, + "overwritePassword": { + "message": "Zamijeni lozinku" + }, + "learnMore": { + "message": "Saznaj više" + }, + "featureUnavailable": { + "message": "Funkcija nije dostupna" + }, + "loggedOut": { + "message": "Odjavljen" + }, + "loginExpired": { + "message": "Vaša sesija je istekla." + }, + "logOutConfirmation": { + "message": "Jeste li sigurni da se želite odjaviti?" + }, + "logOut": { + "message": "Odjavi se" + }, + "addNewLogin": { + "message": "Dodaj novu prijavu" + }, + "addNewItem": { + "message": "Dodaj novu stavku" + }, + "addNewFolder": { + "message": "Dodaj novu fasciklu" + }, + "view": { + "message": "Pogled" + }, + "account": { + "message": "Nalog" + }, + "loading": { + "message": "Učitavanje..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Generator lozinki" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Pošaljite izvještaj o grešci" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Prati nas" + }, + "syncVault": { + "message": "Sinhronizacija trezora" + }, + "changeMasterPass": { + "message": "Promjena glavne lozinke" + }, + "changeMasterPasswordConfirmation": { + "message": "Možete promijeniti svoju glavnu lozinku u trezoru na internet strani bitwarden.com. Da li želite da posjetite internet lokaciju sada?" + }, + "fingerprintPhrase": { + "message": "Fraza računa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Jedinstvena fraza vašeg računa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Idi na internet stranu trezora" + }, + "getMobileApp": { + "message": "Preuzmi mobilnu aplikaciju" + }, + "getBrowserExtension": { + "message": "Preuzmi ekstenziju za pretraživač" + }, + "syncingComplete": { + "message": "Završena sinhronizacija" + }, + "syncingFailed": { + "message": "Sinhronizacija nije uspjela" + }, + "yourVaultIsLocked": { + "message": "Vaš trezor je zaključan. Verifikuj svoju glavnu lozinku za nastavak." + }, + "unlock": { + "message": "Otključaj" + }, + "loggedInAsOn": { + "message": "Prijavljen kao $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Nevažeća glavna lozinka" + }, + "twoStepLoginConfirmation": { + "message": "Prijavljivanje u dva koraka čini vaš nalog sigurnijim tako što ćete morati da verifikujete prijavu na drugom uređaju, kao što su bezbjedonosni ključ, aplikacija za potvrđivanje, SMS, telefonski poziv ili e-pošta. Prijava u dva koraka može se omogućiti u trezoru na internet strani bitwarden.com. Da li želite da posjetite internet lokaciju sada?" + }, + "twoStepLogin": { + "message": "Prijava u dva koraka" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Odmah" + }, + "tenSeconds": { + "message": "10 sekundi" + }, + "twentySeconds": { + "message": "20 sekundi" + }, + "thirtySeconds": { + "message": "30 sekundi" + }, + "oneMinute": { + "message": "1 Minut" + }, + "twoMinutes": { + "message": "2 Minuta" + }, + "fiveMinutes": { + "message": "5 Minuta" + }, + "fifteenMinutes": { + "message": "15 Minuta" + }, + "thirtyMinutes": { + "message": "30 Minuta" + }, + "oneHour": { + "message": "1 Sat" + }, + "fourHours": { + "message": "4 Sata" + }, + "onIdle": { + "message": "Kada je sistem neaktivan" + }, + "onSleep": { + "message": "Kada je sistem u hibernaciji" + }, + "onLocked": { + "message": "Kada je sistem zaključan" + }, + "onRestart": { + "message": "Na restart" + }, + "never": { + "message": "Nikada" + }, + "security": { + "message": "Bezbjednost" + }, + "clearClipboard": { + "message": "Obrisati međuspremnik", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatsko brisanje kopiranih vrijednosti iz vašeg međuspremnika.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Onesposobi ikone internet strane" + }, + "disableFaviconDesc": { + "message": "Ikone internet strane omogućavaju prepoznatljivu sliku pored svake stavke za prijavu u vašem trezoru." + }, + "enableMinToTray": { + "message": "MInimiziraj u sistemsku traku" + }, + "enableMinToTrayDesc": { + "message": "Kada se minimizira prozor, prikaži ikonu u sistemskoj traci." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Zatvori u sistemsku traku" + }, + "enableCloseToTrayDesc": { + "message": "Kada se zatvori prozor, prikaži ikonu u sistemskoj traci." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Omogući sistemsku traku" + }, + "enableTrayDesc": { + "message": "Uvijek prikaži ikonu u sistemskoj traci." + }, + "startToTray": { + "message": "Pokreni samo ikonu sistemske trake" + }, + "startToTrayDesc": { + "message": "Kada se aplikacija prvi put pokrene, prikaži samo ikonu u sistemskoj traci." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Jezik" + }, + "languageDesc": { + "message": "Promijenite jezik koji koristi aplikacija. Potrebno je ponovno pokretanje." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Promijenite boju teme aplikacije." + }, + "dark": { + "message": "Tamna", + "description": "Dark color" + }, + "light": { + "message": "Svijetla", + "description": "Light color" + }, + "copy": { + "message": "Kopiraj", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Provjeri ažuriranje" + }, + "version": { + "message": "Verzija $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Ponovo pokreni za ažuriranje" + }, + "restartToUpdateDesc": { + "message": "Verzija $VERSION_NUM$ je spremna za instaliranje. Da biste dovršili instalaciju, morate ponovo pokrenuti aplikaciju. Da li želite da ponovo pokrenete i ažurirate?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Dostupna su ažuriranja" + }, + "updateAvailableDesc": { + "message": "Pronađeno je ažuriranje. Želite li ga preuzeti sada?" + }, + "restart": { + "message": "Ponovno pokretanje" + }, + "later": { + "message": "Kasnije" + }, + "noUpdatesAvailable": { + "message": "Trenutno nema dostupnih ažuriranja. Koristite najnoviju verziju." + }, + "updateError": { + "message": "Ažuriraj grešku" + }, + "unknown": { + "message": "Nepoznat" + }, + "copyUsername": { + "message": "Kopiraj korisnički nalog" + }, + "copyNumber": { + "message": "Kopiraj broj", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopiraj siguronosni kod", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premijum članstvo" + }, + "premiumManage": { + "message": "Upravljanje članstvom" + }, + "premiumManageAlert": { + "message": "Svojim članstvom možete upravljati na trezoru u sklopu internet strane bitwarden.com. Da li želite da posjetite internet lokaciju sada?" + }, + "premiumRefresh": { + "message": "Osvježi članstvo" + }, + "premiumNotCurrentMember": { + "message": "Trenutno nijeste premijum član." + }, + "premiumSignUpAndGet": { + "message": "Prijavite se za premijum članstvo i dobijte:" + }, + "premiumSignUpStorage": { + "message": "1 GB šifrovanog skladišta za priloge datoteka." + }, + "premiumSignUpTwoStep": { + "message": "Dodatne opcije prijave u dva koraka kao što su YubiKey, FIDO U2F i Duo." + }, + "premiumSignUpReports": { + "message": "Higijena lozinke, zdravlje računa i podaci o krađi podataka kako bi trezor bio siguran." + }, + "premiumSignUpTotp": { + "message": "Generator TOTP verifikacionog koda (2FA) za prijavu u vaš trezor." + }, + "premiumSignUpSupport": { + "message": "Prioritetna korisnička podrška." + }, + "premiumSignUpFuture": { + "message": "Sve buduće premijum karakteristike. Više uskoro!" + }, + "premiumPurchase": { + "message": "Kupi Premijum članstvo" + }, + "premiumPurchaseAlert": { + "message": "Premium članstvo možete kupiti u trezoru na internet strani bitwarden.com. Da li želite da posjetite internet lokaciju sada?" + }, + "premiumCurrentMember": { + "message": "Vi ste premijum član!" + }, + "premiumCurrentMemberThanks": { + "message": "Hvala vam što podržavate Bitwarden." + }, + "premiumPrice": { + "message": "Sve za $PRICE$ /godišnje!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Osvježavanje završeno" + }, + "passwordHistory": { + "message": "Istorija lozinki" + }, + "clear": { + "message": "Očisti", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Nema lozinki za prikazivanje." + }, + "undo": { + "message": "Poništi" + }, + "redo": { + "message": "Vrati" + }, + "cut": { + "message": "Izreži", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Zalijepi", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Izaberi sve" + }, + "zoomIn": { + "message": "Uveličati" + }, + "zoomOut": { + "message": "Umanjiti" + }, + "resetZoom": { + "message": "Reset povećavanja" + }, + "toggleFullScreen": { + "message": "Uključi/isključi prikaz preko cijelog ekrana" + }, + "reload": { + "message": "Osvježi" + }, + "toggleDevTools": { + "message": "Uključivanje/Isključivanje razvojnih alata" + }, + "minimize": { + "message": "Minimiziraj", + "description": "Minimize window" + }, + "zoom": { + "message": "Povećavanje" + }, + "bringAllToFront": { + "message": "Prikaži sve", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "O Bitwardenu" + }, + "services": { + "message": "Servisi" + }, + "hideBitwarden": { + "message": "Sakrij Bitwarden" + }, + "hideOthers": { + "message": "Sakrij ostale" + }, + "showAll": { + "message": "Pokaži sve" + }, + "quitBitwarden": { + "message": "Napusti Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ kopiran", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Pomoć" + }, + "window": { + "message": "Prozor" + }, + "checkPassword": { + "message": "Provjerite da li je lozinka izložena." + }, + "passwordExposed": { + "message": "Ova lozinka je izložena kradji podataka $VALUE$ put(a). Trebalo bi da je promijenite.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Ova lozinka nije pronađena ni u jednoj poznatoj krađi podataka. Trebala bi biti sigurna za upotrebu." + }, + "baseDomain": { + "message": "Osnovni domen", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Lokalna instalacija (HOST)", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tačan" + }, + "startsWith": { + "message": "Počinje sa" + }, + "regEx": { + "message": "Uobičajeni izraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Otkrivanje podudaranja", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Zadato otkrivanje podudaranja", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Uključi/Isključi opcije" + }, + "organization": { + "message": "Organizacija", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Zadato" + }, + "exit": { + "message": "Izađi" + }, + "showHide": { + "message": "Prikaži/Sakrij", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Sakrij u sistemskoj traci" + }, + "alwaysOnTop": { + "message": "Uvijek na vrhu", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Ažurirano", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Lozinka ažurirana", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Izvezi trezor" + }, + "fileFormat": { + "message": "Format datoteke" + }, + "warning": { + "message": "UPOZORENJE", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "Ovaj izvoz sadrži vaše podatke o trezoru u nešifrovanom formatu. Izvezenu datoteku ne treba da čuvate ili šaljete preko nesigurnih kanala (kao što je e-pošta). Izbrišite ga odmah nakon što završite sa upotrebom." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "Ne pripadate nijednoj organizaciji. Organizacije vam omogućavaju da bezbjedno dijelite stavke sa drugim korisnicima." + }, + "noCollectionsInList": { + "message": "Ne postoje kolekcije u listi." + }, + "ownership": { + "message": "Vlasništvo" + }, + "whoOwnsThisItem": { + "message": "Ko je vlasnik ove stavke?" + }, + "strong": { + "message": "Jaka", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobar", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slaba", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slaba glavna lozinka" + }, + "weakMasterPasswordDesc": { + "message": "Glavna lozinka koju ste odabrali je slaba. Trebate koristiti jaku glavnu lozinku (ili pristupnu frazu) da biste pravilno zaštitili svoj Bitwarden nalog. Jeste li sigurni da želite da koristite ovu glavnu lozinku?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Otključaj sa PINom" + }, + "setYourPinCode": { + "message": "Podesite svoj PIN kod za otključavanje Bitwarden-a. Podešavanja PIN-a će se resetovati ako se ikada u potpunosti odjavite iz aplikacije." + }, + "pinRequired": { + "message": "Potreban je PIN kod." + }, + "invalidPin": { + "message": "Nevažeći PIN kod." + }, + "unlockWithWindowsHello": { + "message": "Otključaj sa Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verifikuj za Bitwarden." + }, + "unlockWithTouchId": { + "message": "Otključaj sa Touch ID" + }, + "touchIdConsentMessage": { + "message": "Verifikuj za Bitwarden." + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Zaključajte glavnom lozinkom pri ponovnom pokretanju" + }, + "preferences": { + "message": "Podešavanja" + }, + "enableMenuBar": { + "message": "Omogući ikonu trake menija" + }, + "enableMenuBarDesc": { + "message": "Uvijek prikaži ikonu trake menija." + }, + "hideToMenuBar": { + "message": "Sakrij u traci menija" + }, + "selectOneCollection": { + "message": "Morate izabrati barem jednu kolekciju." + }, + "premiumUpdated": { + "message": "Nadogradili ste na premijum." + }, + "restore": { + "message": "Vrati" + }, + "premiumManageAlertAppStore": { + "message": "Pretplatom možete da upravljate iz App Store-a. Da li želite da posjetite App Store sada?" + }, + "legal": { + "message": "Pravne informacije", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Uslovi korišćenja" + }, + "privacyPolicy": { + "message": "Pravila o privatnosti" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Klon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Jedno ili više pravila organizacije utiču na podešavanje vašeg generatora." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "Označavanjem ovog polja pristajete na sledeće:" + }, + "acceptPoliciesError": { + "message": "Uslovi usluge i Politika privatnosti nisu prihvaćeni." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/ml/messages.json b/apps/desktop/src/locales/ml/messages.json new file mode 100644 index 0000000000..4e2fe8f964 --- /dev/null +++ b/apps/desktop/src/locales/ml/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "ഫിൽറ്ററുകൾ" + }, + "allItems": { + "message": "എല്ലാ ഇനങ്ങൾ" + }, + "favorites": { + "message": "പ്രിയങ്കരങ്ങള്‍" + }, + "types": { + "message": "തരങ്ങൾ" + }, + "typeLogin": { + "message": "പ്രവേശനം" + }, + "typeCard": { + "message": "കാർഡ്" + }, + "typeIdentity": { + "message": "തിരിച്ചറിയൽ" + }, + "typeSecureNote": { + "message": "സുരക്ഷിത കുറിപ്പ്" + }, + "folders": { + "message": "ഫോൾഡറുകൾ" + }, + "collections": { + "message": "കളക്ഷൻസ്" + }, + "searchVault": { + "message": "വാൾട് തിരയുക" + }, + "addItem": { + "message": "ഇനം ചേർക്കുക" + }, + "shared": { + "message": "പങ്കിട്ടവ" + }, + "share": { + "message": "പങ്കിടുക" + }, + "moveToOrganization": { + "message": "സംഘടനയിലേക്ക് മാറുക" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ $ORGNAME$-യിലേക്ക് മാറ്റി", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "അറ്റാച്ചുമെന്റുകൾ" + }, + "viewItem": { + "message": "ഇനം കാണുക" + }, + "name": { + "message": "പേര്" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "പുതിയ URI" + }, + "username": { + "message": "ഉപയോക്തൃനാമം" + }, + "password": { + "message": "പാസ്‌വേഡ്" + }, + "passphrase": { + "message": "രഹസ്യ വാചകം" + }, + "editItem": { + "message": "ഇനം എഡിറ്റുചെയ്യുക" + }, + "emailAddress": { + "message": "ഇ-മെയിൽ വിലാസം" + }, + "verificationCodeTotp": { + "message": "സ്ഥിരീകരണ കോഡ് (TOTP)" + }, + "website": { + "message": "വെബ്സൈറ്റ്" + }, + "notes": { + "message": "കുറിപ്പുകൾ" + }, + "customFields": { + "message": "ഇഷ്‌ടാനുസൃത ഫീൽഡുകൾ" + }, + "launch": { + "message": "തുറക്കുക" + }, + "copyValue": { + "message": "മൂല്യം പകർത്തുക", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "ക്ലിപ്പ്ബോർഡിലേക്ക് പകർത്തുമ്പോൾ ചെറുതാക്കുക" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "ക്ലിപ്പ്ബോർഡിലേക്ക് ഒരു ഇനത്തിന്റെ ഡാറ്റ പകർത്തുമ്പോൾ ചെറുതാക്കുക." + }, + "toggleVisibility": { + "message": "ദൃശ്യപരത ടോഗിൾ ചെയ്യുക" + }, + "toggleCollapse": { + "message": "ചുരുക്കുക", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "കാർഡ് ഉടമയുടെ പേര്" + }, + "number": { + "message": "നമ്പർ" + }, + "brand": { + "message": "ബ്രാൻഡ്" + }, + "expiration": { + "message": "കാലഹരണപ്പെടൽ" + }, + "securityCode": { + "message": "സുരക്ഷാ കോഡ് സിവി‌വി" + }, + "identityName": { + "message": "തിരിച്ചറിയലിൻ്റെ പേര്" + }, + "company": { + "message": "കമ്പനി" + }, + "ssn": { + "message": "സാമൂഹിക സുരക്ഷാ നമ്പർ" + }, + "passportNumber": { + "message": "പാസ്പോർട്ട് നമ്പർ" + }, + "licenseNumber": { + "message": "ലൈസൻസ് നമ്പർ" + }, + "email": { + "message": "ഇമെയിൽ" + }, + "phone": { + "message": "ഫോൺ" + }, + "address": { + "message": "മേൽവിലാസം" + }, + "premiumRequired": { + "message": "പ്രീമിയം അംഗത്വം ആവശ്യമാണ്" + }, + "premiumRequiredDesc": { + "message": "ഈ സവിശേഷത ഉപയോഗിക്കുന്നതിന് പ്രീമിയം അംഗത്വം ആവശ്യമാണ്." + }, + "errorOccurred": { + "message": "ഒരു പിഴവ് സംഭവിച്ചിരിക്കുന്നു." + }, + "error": { + "message": "പിശക്" + }, + "january": { + "message": "ജനുവരി" + }, + "february": { + "message": "ഫെബ്രുവരി" + }, + "march": { + "message": "മാർച്ച്‌" + }, + "april": { + "message": "ഏപ്രിൽ" + }, + "may": { + "message": "മെയ്‌" + }, + "june": { + "message": "ജൂണ്‍" + }, + "july": { + "message": "ജൂലൈ" + }, + "august": { + "message": "ഓഗസ്റ്റ്" + }, + "september": { + "message": "സെപ്റ്റംബർ" + }, + "october": { + "message": "ഒക്ടോബര്‍" + }, + "november": { + "message": "നവംബർ" + }, + "december": { + "message": "ഡിസംബർ" + }, + "ex": { + "message": "ഉദാഹരണം.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "ശീർഷകം" + }, + "mr": { + "message": "ശ്രീ" + }, + "mrs": { + "message": "ശ്രിമതി" + }, + "ms": { + "message": "കുമാരി" + }, + "dr": { + "message": "ഡോ" + }, + "expirationMonth": { + "message": "കാലാവതി കഴിയുന്ന മാസം" + }, + "expirationYear": { + "message": "കാലാവതി കഴിയുന്ന വർഷം" + }, + "select": { + "message": "തിരഞ്ഞെടുക്കുക" + }, + "other": { + "message": "മറ്റുള്ളവ" + }, + "generatePassword": { + "message": "പാസ്‌വേഡ് സൃഷ്ടിക്കുക" + }, + "type": { + "message": "തരം" + }, + "firstName": { + "message": "പേരിന്റെ ആദ്യഭാഗം" + }, + "middleName": { + "message": "മധ്യ നാമം" + }, + "lastName": { + "message": "പേരിന്റെ അവസാന ഭാഗം" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "മേൽവിലാസം 1" + }, + "address2": { + "message": "മേൽവിലാസം 2" + }, + "address3": { + "message": "മേൽവിലാസം 3" + }, + "cityTown": { + "message": "നഗരം / പട്ടണം" + }, + "stateProvince": { + "message": "സംസ്ഥാനം/ ദേശം" + }, + "zipPostalCode": { + "message": "പിൻകോഡ്" + }, + "country": { + "message": "രാജ്യം" + }, + "save": { + "message": "സംരക്ഷിക്കുക" + }, + "cancel": { + "message": "റദ്ദാക്കുക" + }, + "delete": { + "message": "നീക്കംചെയ്യുക" + }, + "favorite": { + "message": "പ്രിയങ്കരം" + }, + "edit": { + "message": "തിരുത്തുക" + }, + "authenticatorKeyTotp": { + "message": "ഓതന്റിക്കേറ്റർ കീ (TOTP)" + }, + "folder": { + "message": "ഫോൾഡർ" + }, + "newCustomField": { + "message": "പുതിയ ഇഷ്‌ടാനുസൃത ഫീൽഡ്" + }, + "value": { + "message": "മൂല്യം" + }, + "dragToSort": { + "message": "അടുക്കാൻ വലിച്ചിടുക" + }, + "cfTypeText": { + "message": "വാചകം" + }, + "cfTypeHidden": { + "message": "മറച്ചത്" + }, + "cfTypeBoolean": { + "message": "ബൂളിയൻ" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "നീക്കംചെയ്യുക" + }, + "nameRequired": { + "message": "പേര് നിർബന്ധമാണ്‌." + }, + "addedItem": { + "message": "ചേർക്കപ്പെട്ട ഇനം" + }, + "editedItem": { + "message": "ഇനം തിരുത്തി" + }, + "deleteItem": { + "message": "ഇനം ഇല്ലാതാക്കുക" + }, + "deleteFolder": { + "message": "ഫോൾഡർ ഇല്ലാതാക്കുക" + }, + "deleteAttachment": { + "message": "അറ്റാച്ചുമെന്റ് ഇല്ലാതാക്കുക" + }, + "deleteItemConfirmation": { + "message": "ഈ ഇനം ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "deletedItem": { + "message": "ഇനം ട്രാഷിലേക്ക് അയച്ചു" + }, + "overwritePasswordConfirmation": { + "message": "നിലവിലെ പാസ്‌വേഡ് പുനരാലേഖനം ചെയ്യണമെന്ന് നിങ്ങൾക്ക് ഉറപ്പാണോ?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "ഫോൾഡർ ഇല്ല", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "ഫോൾഡർ ചേർക്കുക" + }, + "editFolder": { + "message": "ഫോൾഡർ തിരുത്തുക" + }, + "regeneratePassword": { + "message": "പാസ്സ്‌വേഡ് വീണ്ടും സൃഷ്ടിക്കുക" + }, + "copyPassword": { + "message": "പാസ്‌വേഡ് പകർത്തുക" + }, + "copyUri": { + "message": "URL പകർത്തുക" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "ദൈര്‍ഘ്യം" + }, + "numWords": { + "message": "വാക്കുകളുടെ എണ്ണം" + }, + "wordSeparator": { + "message": "വേര്‍പെടുത്തുക" + }, + "capitalize": { + "message": "വലിയഅക്ഷരമാകുക", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "നമ്പർ ഉൾപ്പെടുത്തുക" + }, + "close": { + "message": "അടയ്ക്കുക" + }, + "minNumbers": { + "message": "കുറഞ്ഞ സംഖ്യകൾ" + }, + "minSpecial": { + "message": "കുറഞ്ഞ പ്രത്യേക പ്രതീകങ്ങൾ", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "അവ്യക്തമായ പ്രതീകങ്ങൾ ഒഴിവാക്കുക" + }, + "searchCollection": { + "message": "കളക്ഷൻസ് തിരയുക" + }, + "searchFolder": { + "message": "ഫോൾഡറുകൾ തിരയുക" + }, + "searchFavorites": { + "message": "പ്രിയങ്കരങ്ങൾ തിരയുക" + }, + "searchType": { + "message": "തരം തിരയുക", + "description": "Search item type" + }, + "newAttachment": { + "message": "പുതിയ അറ്റാച്ചുമെന്റ് ചേർക്കുക" + }, + "deletedAttachment": { + "message": "മായ്ച്ച അറ്റാച്ചുമെന്റ്" + }, + "deleteAttachmentConfirmation": { + "message": "ഈ അറ്റാച്ചുമെന്റ് ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "attachmentSaved": { + "message": "ഈ അറ്റാച്ചുമെന്റ് സംരക്ഷിച്ചു." + }, + "file": { + "message": "ഫയൽ" + }, + "selectFile": { + "message": "ഫയൽ തിരഞ്ഞെടുക്കുക." + }, + "maxFileSize": { + "message": "പരമാവധി ഫയൽ വലുപ്പം 500 MB ആണ്." + }, + "updateKey": { + "message": "നിങ്ങളുടെ എൻ‌ക്രിപ്ഷൻ കീ അപ്‌ഡേറ്റ് ചെയ്യുന്നതുവരെ നിങ്ങൾക്ക് ഈ സവിശേഷത ഉപയോഗിക്കാൻ കഴിയില്ല." + }, + "editedFolder": { + "message": "ഫോൾഡർ തിരുത്തി" + }, + "addedFolder": { + "message": "ചേർക്കപ്പെട്ട ഫോൾഡർ" + }, + "deleteFolderConfirmation": { + "message": "ഈ ഫോൾഡർ ഇല്ലാതാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "deletedFolder": { + "message": "ഇല്ലാതാക്കിയ ഫോൾഡർ" + }, + "loginOrCreateNewAccount": { + "message": "നിങ്ങളുടെ സുരക്ഷിത വാൾട്ടിലേക്ക് പ്രവേശിക്കാൻ ലോഗിൻ ചെയ്യുക അല്ലെങ്കിൽ ഒരു പുതിയ അക്കൗണ്ട് സൃഷ്ടിക്കുക." + }, + "createAccount": { + "message": "അക്കൗണ്ട് സൃഷ്ടിക്കുക" + }, + "logIn": { + "message": "പ്രവേശിക്കുക" + }, + "submit": { + "message": "സമർപ്പിക്കുക" + }, + "masterPass": { + "message": "പ്രാഥമിക പാസ്‌വേഡ്" + }, + "masterPassDesc": { + "message": "നിങ്ങളുടെ വാൾട്ടിലേക്ക് പ്രവേശിക്കാൻ ഉപയോഗിക്കുന്ന പാസ്‌വേഡാണ് പ്രാഥമിക പാസ്‌വേഡ്. പ്രാഥമിക പാസ്‌വേഡ് നിങ്ങൾ ഒരു കാരണവശാലും മറക്കരുത്. നിങ്ങൾ പാസ്‌വേഡ് മറന്നാൽ, വീണ്ടെടുക്കാൻ വേറെ ഒരു മാർഗ്ഗവുമില്ല." + }, + "masterPassHintDesc": { + "message": "നിങ്ങളുടെ പാസ്‌വേഡ് മറന്നാൽ അത് ഓർമ്മിക്കാൻ ഒരു പ്രാഥമിക പാസ്‌വേഡ് സൂചന സഹായിക്കും." + }, + "reTypeMasterPass": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് വീണ്ടും ടൈപ്പ്‌ ചെയ്യുക" + }, + "masterPassHint": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സൂചന (ഇഷ്ടാനുസൃതമായ)" + }, + "settings": { + "message": "ക്രമീകരണങ്ങള്‍" + }, + "passwordHint": { + "message": "പാസ്സ്‌വേഡ് സൂചനാ" + }, + "enterEmailToGetHint": { + "message": "നിങ്ങളുടെ പ്രാഥമിക പാസ്‌വേഡ് സൂചന ലഭിക്കുന്നതിന് നിങ്ങളുടെ അക്കൗണ്ട് ഇമെയിൽ വിലാസം നൽകുക." + }, + "getMasterPasswordHint": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സൂചന നേടുക" + }, + "emailRequired": { + "message": "ഇമെയിൽ അഡ്രസ്സ് നിർബന്ധമാണ്‌." + }, + "invalidEmail": { + "message": "അസാധുവായ ഇമെയിൽ." + }, + "masterPassRequired": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് നിർബന്ധമാണ്‌." + }, + "masterPassLength": { + "message": "പ്രാഥമിക പാസ്‌വേഡിന് കുറഞ്ഞത് 8 പ്രതീകങ്ങളെങ്കിലും ദൈർഘ്യമുണ്ടായിരിക്കണം." + }, + "masterPassDoesntMatch": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സ്ഥിരീകരണം പൊരുത്തപ്പെടുന്നില്ല." + }, + "newAccountCreated": { + "message": "തങ്ങളുടെ അക്കൗണ്ട് സൃഷ്ടിക്കപ്പെട്ടു. ഇനി താങ്കൾക്ക് ലോഗിൻ ചെയ്യാം." + }, + "masterPassSent": { + "message": "നിങ്ങളുടെ പ്രാഥമിക പാസ്‌വേഡ് സൂചനയുള്ള ഒരു ഇമെയിൽ ഞങ്ങൾ നിങ്ങൾക്ക് അയച്ചു." + }, + "unexpectedError": { + "message": "ഒരു അപ്രതീക്ഷിത പിശക് സംഭവിച്ചു." + }, + "itemInformation": { + "message": "വിവരം" + }, + "noItemsInList": { + "message": "പ്രദർശിപ്പിക്കാൻ ഇനങ്ങളൊന്നുമില്ല." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "പരിശോധിച്ചുറപ്പിക്കൽ കോഡ്" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "പരിശോധിച്ചുറപ്പിക്കൽ കോഡ് ആവശ്യമാണ്." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "തുടരുക" + }, + "enterVerificationCodeApp": { + "message": "നിങ്ങളുടെ ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷനിൽ നിന്ന് 6 അക്ക സ്ഥിരീകരണ കോഡ് നൽകുക." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$-ൽ ഇമെയിൽ ചെയ്ത 6 അക്ക സ്ഥിരീകരണ കോഡ് നൽകുക.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "സ്ഥിരീകരണ ഇമെയിൽ $EMAIL$-ലേക്ക് അയച്ചു.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "എന്നെ ഓർക്കണം" + }, + "sendVerificationCodeEmailAgain": { + "message": "സ്ഥിരീകരണ കോഡ് ഇമെയിൽ വഴി വീണ്ടും അയയ്ക്കുക" + }, + "useAnotherTwoStepMethod": { + "message": "മറ്റൊരു രണ്ട് ഘട്ട പ്രവേശന രീതി ഉപയോഗിക്കുക" + }, + "insertYubiKey": { + "message": "നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ യു‌എസ്‌ബി പോർട്ടിലേക്ക് YubiKey ഇടുക, തുടർന്ന് അതിന്റെ ബട്ടൺ അമർത്തുക." + }, + "insertU2f": { + "message": "നിങ്ങളുടെ കമ്പ്യൂട്ടറിന്റെ യുഎസ്ബി പോർട്ടിൽ സുരക്ഷാ കീ ഇടുക. അതിന് ഒരു ബട്ടൺ ഉണ്ടെങ്കിൽ അത് അമർത്തുക." + }, + "recoveryCodeDesc": { + "message": "നിങ്ങളുടെ രണ്ട്-ഘടക ദാതാക്കളിലേക്കുള്ള ആക്‌സസ്സ് നഷ്‌ടപ്പെട്ടോ? നിങ്ങളുടെ അക്കൗണ്ടിൽ നിന്ന് രണ്ട്-ഘടക ദാതാക്കളെ പ്രവർത്തനരഹിതമാക്കാൻ നിങ്ങളുടെ റിക്കവറി കോഡ് ഉപയോഗിക്കുക." + }, + "recoveryCodeTitle": { + "message": "റിക്കവറി കോഡ്" + }, + "authenticatorAppTitle": { + "message": "ഓതന്റിക്കേറ്റർ ആപ്പ്" + }, + "authenticatorAppDesc": { + "message": "സമയ-അടിസ്ഥാന പരിശോധന കോഡുകൾ സൃഷ്ടിക്കുന്നതിന് ഒരു ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷൻ (ഓത്തി അല്ലെങ്കിൽ Google ഓതന്റിക്കേറ്റർ പോലുള്ളവ) ഉപയോഗിക്കുക.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP സുരക്ഷാ കീ" + }, + "yubiKeyDesc": { + "message": "നിങ്ങളുടെ അക്കൗണ്ട് ആക്സസ് ചെയ്യുന്നതിന് ഒരു യൂബിക്കി ഉപയോഗിക്കുക. YubiKey 4, 4 Nano, 4C, NEO ഉപകരണങ്ങളിൽ പ്രവർത്തിക്കുന്നു." + }, + "duoDesc": { + "message": "Duo Mobile അപ്ലിക്കേഷൻ, എസ്എംഎസ്, ഫോൺ കോൾ അല്ലെങ്കിൽ യു 2 എഫ് സുരക്ഷാ കീ ഉപയോഗിച്ച് Duoസെക്യൂരിറ്റി ഉപയോഗിച്ച് പരിശോധിക്കുക.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Duo Mobile, SMS, ഫോൺ കോൾ അല്ലെങ്കിൽ U2F സുരക്ഷാ കീ ഉപയോഗിച്ച് നിങ്ങളുടെ ഓർഗനൈസേഷനെ Duo Security ഉപയോഗിച്ച് പരിശോധിക്കുക.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "ഇമെയിൽ" + }, + "emailDesc": { + "message": "സ്ഥിരീകരണ കോഡുകൾ നിങ്ങൾക്ക് ഇമെയിൽ ചെയ്യും." + }, + "loginUnavailable": { + "message": "പ്രവേശനം ലഭ്യമല്ല" + }, + "noTwoStepProviders": { + "message": "ഈ അക്കൗണ്ടിന് രണ്ട്-ഘട്ട പ്രവേശനം പ്രാപ്തമാക്കിയിട്ടുണ്ട്, എന്നിരുന്നാലും, ക്രമീകരിച്ച രണ്ട്-ഘട്ട ദാതാക്കളെയൊന്നും ഈ ഉപകരണം പിന്തുണയ്ക്കുന്നില്ല." + }, + "noTwoStepProviders2": { + "message": "മികച്ച പിന്തുണയുള്ള, കൂടുതൽ ദാതാക്കളെ ദയവായി ചേർക്കുക (ഒരു ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷൻ പോലുള്ളവ)." + }, + "twoStepOptions": { + "message": "രണ്ട്-ഘട്ട പ്രവേശനം ഓപ്ഷനുകൾ" + }, + "selfHostedEnvironment": { + "message": "സ്വയം ഹോസ്റ്റുചെയ്‌ത എൻവിയോണ്മെന്റ്" + }, + "selfHostedEnvironmentFooter": { + "message": "നിങ്ങളുടെ പരിസരത്ത് ചെയ്യുന്ന Bitwarden ഇൻസ്റ്റാളേഷന്റെ അടിസ്ഥാന URL വ്യക്തമാക്കുക." + }, + "customEnvironment": { + "message": "ഇഷ്‌ടാനുസൃത എൻവിയോണ്മെന്റ്" + }, + "customEnvironmentFooter": { + "message": "വിപുലമായ ഉപയോക്താക്കൾക്കായി. ഓരോ സേവനത്തിന്റെയും അടിസ്ഥാന URL നിങ്ങൾക്ക് സ്വതന്ത്രമായി വ്യക്തമാക്കാൻ കഴിയും." + }, + "baseUrl": { + "message": "സെർവർ യു ർ ൽ" + }, + "apiUrl": { + "message": "API സെർവർ URL" + }, + "webVaultUrl": { + "message": "വെബ് വാൾട് സെർവർ URL" + }, + "identityUrl": { + "message": "ഐഡന്റിറ്റി സെർവർ URL" + }, + "notificationsUrl": { + "message": "നോട്ടിഫിക്കേഷൻ സെർവർ URL" + }, + "iconsUrl": { + "message": "ഐക്കണുകളുടെ സെർവർ URL" + }, + "environmentSaved": { + "message": "എന്വിയാണമെന്റ് URL സംരക്ഷിച്ചു." + }, + "ok": { + "message": "ശരി" + }, + "yes": { + "message": "അതെ" + }, + "no": { + "message": "അല്ല" + }, + "overwritePassword": { + "message": "പാസ്‌വേഡ് പുനരാലേഖനം ചെയ്യുക" + }, + "learnMore": { + "message": "കൂടുതൽ അറിയുക" + }, + "featureUnavailable": { + "message": "സവിശേഷത ലഭ്യമല്ല" + }, + "loggedOut": { + "message": "ലോഗ് ഔട്ട് ചെയ്തിരിക്കുന്നു" + }, + "loginExpired": { + "message": "നിങ്ങളുടെ പ്രവർത്തന സമയം കഴിഞ്ഞിരിക്കുന്നു." + }, + "logOutConfirmation": { + "message": "നിങ്ങൾക്ക് ലോഗ് ഔട്ട് ചെയ്യണമെന്ന് ഉറപ്പാണോ?" + }, + "logOut": { + "message": "ലോഗൗട്ട്" + }, + "addNewLogin": { + "message": "പുതിയ പ്രവേശനം ചേർക്കുക" + }, + "addNewItem": { + "message": "പുതിയ ഇനം ചേർക്കുക" + }, + "addNewFolder": { + "message": "പുതിയ ഫോൾഡർ ചേർക്കുക" + }, + "view": { + "message": "പ്രദർശനം" + }, + "account": { + "message": "അക്കൗണ്ട്" + }, + "loading": { + "message": "ലഭ്യമാക്കുന്നു..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "പാസ്സ്‌വേഡ് സൃഷ്ടാവ്" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "ബഗ്ഗ്‌ റിപ്പോർട്ട് ഫയൽ ചെയ്യുക" + }, + "blog": { + "message": "ബ്ലോഗ്" + }, + "followUs": { + "message": "ഞങ്ങളെ പിന്തുടരുക" + }, + "syncVault": { + "message": "വാൾട് സമന്വയിപ്പിക്കുക" + }, + "changeMasterPass": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് മാറ്റുക" + }, + "changeMasterPasswordConfirmation": { + "message": "തങ്ങൾക്കു Bitwarden വെബ് വാൾട്ടിൽ പ്രാഥമിക പാസ്‌വേഡ് മാറ്റാൻ സാധിക്കും.വെബ്സൈറ്റ് ഇപ്പോൾ സന്ദർശിക്കാൻ ആഗ്രഹിക്കുന്നുവോ?" + }, + "fingerprintPhrase": { + "message": "ഫിംഗർപ്രിന്റ് ഫ്രേസ്‌", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "നിങ്ങളുടെ അക്കൗണ്ടിൻ്റെ ഫിംഗർപ്രിന്റ് ഫ്രേസ്‌", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "വെബ് വാൾട്ടിലേക്ക് പോകുക" + }, + "getMobileApp": { + "message": "മൊബൈൽ ആപ്പ് എടുക്കുക" + }, + "getBrowserExtension": { + "message": "ബ്രൌസർ എക്സ്റ്റൻഷൻ എടുക്കുക" + }, + "syncingComplete": { + "message": "സമന്വയം പൂർത്തിയായി" + }, + "syncingFailed": { + "message": "സമന്വയം പരാജയപ്പെട്ടു" + }, + "yourVaultIsLocked": { + "message": "തങ്ങളുടെ വാൾട് പൂട്ടിയിരിക്കുന്നു. തുടരുന്നതിന് നിങ്ങളുടെ പ്രാഥമിക പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക." + }, + "unlock": { + "message": "അൺലോക്ക്" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$-ൽ $EMAIL$ ലോഗിൻ ചെയ്തിരിക്കുന്നു.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "അസാധുവായ പ്രാഥമിക പാസ്‌വേഡ്" + }, + "twoStepLoginConfirmation": { + "message": "സുരക്ഷാ കീ, ഓതന്റിക്കേറ്റർ അപ്ലിക്കേഷൻ, SMS, ഫോൺ കോൾ അല്ലെങ്കിൽ ഇമെയിൽ പോലുള്ള മറ്റൊരു ഉപകരണം ഉപയോഗിച്ച് തങ്ങളുടെ ലോഗിൻ സ്ഥിരീകരിക്കാൻ ആവശ്യപ്പെടുന്നതിലൂടെ രണ്ട്-ഘട്ട ലോഗിൻ തങ്ങളുടെ അക്കൗണ്ടിനെ കൂടുതൽ സുരക്ഷിതമാക്കുന്നു. bitwarden.com വെബ് വാൾട്ടിൽ രണ്ട്-ഘട്ട ലോഗിൻ പ്രവർത്തനക്ഷമമാക്കാനാകും.തങ്ങള്ക്കു ഇപ്പോൾ വെബ്സൈറ്റ് സന്ദർശിക്കാൻ ആഗ്രഹമുണ്ടോ?" + }, + "twoStepLogin": { + "message": "രണ്ട്-ഘട്ട പ്രവേശനം" + }, + "vaultTimeout": { + "message": "വാൾട് ടൈംഔട്ട്" + }, + "vaultTimeoutDesc": { + "message": "തങ്ങളുടെ വാൾട് എപ്പോൾ ടൈംഔട്ട് ആകും എന്ന് നിശ്ചയിക്കുക. തിരഞ്ഞെടുത്ത പ്രവർത്തനം നടത്തുക." + }, + "immediately": { + "message": "ഉടനെ" + }, + "tenSeconds": { + "message": "10 സെക്കൻഡ്" + }, + "twentySeconds": { + "message": "20 സെക്കന്റുകള്‍" + }, + "thirtySeconds": { + "message": "30 സെക്കൻഡ്" + }, + "oneMinute": { + "message": "1 മിനിറ്റ്" + }, + "twoMinutes": { + "message": "2 മിനിറ്റ്" + }, + "fiveMinutes": { + "message": "5 മിനിറ്റ്" + }, + "fifteenMinutes": { + "message": "15 മിനിറ്റ്" + }, + "thirtyMinutes": { + "message": "30 മിനിറ്റ്" + }, + "oneHour": { + "message": "1 മണിക്കൂർ" + }, + "fourHours": { + "message": "4 മണിക്കൂർ" + }, + "onIdle": { + "message": "സിസ്റ്റം നിഷ്‌ക്രിയം" + }, + "onSleep": { + "message": "സിസ്റ്റം സ്ലീപ്പിൽ" + }, + "onLocked": { + "message": "സിസ്റ്റം ലോക്കിൽ" + }, + "onRestart": { + "message": "പുനരാരംഭിക്കുമ്പോൾ" + }, + "never": { + "message": "അത് ചെയ്യരുത്" + }, + "security": { + "message": "സുരക്ഷ" + }, + "clearClipboard": { + "message": "ക്ലിപ്ബോര്‍ഡ് മായ്ക്കുക", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "നിങ്ങളുടെ ക്ലിപ്പ്ബോർഡിൽ നിന്ന് പകർത്തിയ മൂല്യങ്ങൾ സ്വയം മായ്‌ക്കുക.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "വെബ്‌സൈറ്റ് ഐക്കണുകൾ പ്രവർത്തനരഹിതമാക്കുക" + }, + "disableFaviconDesc": { + "message": "വെബ്സൈറ്റ് ഐക്കണുകൾ നിങ്ങളുടെ വാൾട്ടിലെ പ്രവേശനങ്ങളുടെ അടുത്തായി തിരിച്ചറിയുന്ന ഒരു ചിത്രം ഉൾപ്പെടുത്തുന്നു." + }, + "enableMinToTray": { + "message": "ട്രേ ഐക്കണിലേക്ക് ചെറുതാക്കുക" + }, + "enableMinToTrayDesc": { + "message": "വിൻഡോ ചെറുതാക്കുമ്പോൾ, പകരം സിസ്റ്റം ട്രേയിൽ ഒരു ഐക്കൺ കാണിക്കുക." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "ട്രേ ഐക്കണിൽ ക്ലോസ് ചെയ്യുക" + }, + "enableCloseToTrayDesc": { + "message": "വിൻഡോ അടയ്‌ക്കുമ്പോൾ, സിസ്റ്റം ട്രേയിൽ ഒരു ഐക്കൺ പകരമായി കാണിക്കുക." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "ട്രേ ഐക്കൺ പ്രവർത്തനക്ഷമമാക്കുക" + }, + "enableTrayDesc": { + "message": "സിസ്റ്റം ട്രേയിൽ എല്ലായ്പ്പോഴും ഒരു ഐക്കൺ കാണിക്കുക." + }, + "startToTray": { + "message": "ട്രേ ഐക്കണിൽ ആരംഭിക്കുക" + }, + "startToTrayDesc": { + "message": "അപ്ലിക്കേഷൻ ആദ്യം ആരംഭിക്കുമ്പോൾ, സിസ്റ്റം ട്രേയിൽ ഒരു ഐക്കൺ മാത്രം കാണിക്കുക." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "ഭാഷ" + }, + "languageDesc": { + "message": "അപ്ലിക്കേഷൻ ഉപയോഗിക്കുന്ന ഭാഷ മാറ്റുക. പുനരാരംഭിക്കൽ ആവശ്യമാണ്." + }, + "theme": { + "message": "തീം" + }, + "themeDesc": { + "message": "അപ്ലിക്കേഷന്റെ തീമും വർണ്ണങ്ങളും മാറ്റുക." + }, + "dark": { + "message": "ഇരുണ്ടത്", + "description": "Dark color" + }, + "light": { + "message": "ലൈറ്റ്", + "description": "Light color" + }, + "copy": { + "message": "പകർത്തുക", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "അപ്‌ഡേറ്റുകൾക്കായി പരിശോധിക്കുക" + }, + "version": { + "message": "വേർഷൻ $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "അപ്‌ഡേറ്റുചെയ്യാൻ പുനരാരംഭിക്കുക" + }, + "restartToUpdateDesc": { + "message": "വേർഷൻ $VERSION_NUM$ ഇൻസ്റ്റാൾ ചെയ്യാൻ തയ്യാറാണ്. ഇൻസ്റ്റാളേഷൻ പൂർത്തിയാക്കുന്നതിന് നിങ്ങൾ അപ്ലിക്കേഷൻ പുനരാരംഭിക്കണം. ഇപ്പോൾ പുനരാരംഭിച്ച് അപ്‌ഡേറ്റ് ചെയ്യാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "അപ്ഡേറ്റ് ലഭ്യമാണ്" + }, + "updateAvailableDesc": { + "message": "ഒരു അപ്‌ഡേറ്റ് കണ്ടെത്തി. നിങ്ങൾക്കിപ്പോൾ ഇത് ഡൌൺലോഡ് ചെയ്യണോ?" + }, + "restart": { + "message": "പുനരാരംഭിക്കുക" + }, + "later": { + "message": "പിന്നീട്" + }, + "noUpdatesAvailable": { + "message": "അപ്‌ഡേറ്റുകളൊന്നും നിലവിൽ ലഭ്യമല്ല. നിങ്ങൾ ഏറ്റവും പുതിയ വേർഷൻ ഉപയോഗിക്കുന്നു." + }, + "updateError": { + "message": "അപ്ഡേറ്റിൽ പിശക് സംഭവിച്ചു" + }, + "unknown": { + "message": "അറിയപ്പെടാത്ത" + }, + "copyUsername": { + "message": "ഉപയോക്തൃനാമം പകർത്തുക" + }, + "copyNumber": { + "message": "അക്കം പകർത്തുക", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "സുരക്ഷാ കോഡ് പകർത്തുക", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "പ്രീമിയം അംഗത്വം" + }, + "premiumManage": { + "message": "അംഗത്വം നിയന്ത്രിക്കുക" + }, + "premiumManageAlert": { + "message": "നിങ്ങളുടെ അംഗത്വം bitwarden.com വെബ് വാൾട്ടിൽ നിയന്ദ്രിക്കാൻ സാധിക്കും. നിങ്ങൾക്ക് ഇപ്പോൾ വെബ്സൈറ്റ് സന്ദർശിക്കാൻ ആഗ്രഹമുണ്ടോ?" + }, + "premiumRefresh": { + "message": "അംഗത്വം റിഫ്രഷ് ചെയ്യുക" + }, + "premiumNotCurrentMember": { + "message": "നിങ്ങൾ നിലവിൽ ഒരു പ്രീമിയം അംഗമല്ല." + }, + "premiumSignUpAndGet": { + "message": "ഒരു പ്രീമിയം അംഗത്വത്തിനായി സൈൻ അപ്പ് ചെയ്ത് നേടുക:" + }, + "premiumSignUpStorage": { + "message": "ഫയൽ അറ്റാച്ചുമെന്റുകൾക്കായി 1 GB എൻക്രിപ്റ്റുചെയ്‌ത സ്റ്റോറേജ്." + }, + "premiumSignUpTwoStep": { + "message": "രണ്ട്-ഘട്ട പ്രവേശന ഓപ്ഷനുകളായ Yubikey, FIDO U2F, Duo." + }, + "premiumSignUpReports": { + "message": "നിങ്ങളുടെ വാൾട് സൂക്ഷിക്കുന്നതിന്. പാസ്‌വേഡ് ശുചിത്വം, അക്കൗണ്ട് ആരോഗ്യം, ഡാറ്റ ലംഘന റിപ്പോർട്ടുകൾ." + }, + "premiumSignUpTotp": { + "message": "നിങ്ങളുടെ വാൾട്ടിലെ പ്രവേശനങ്ങൾക്കായി TOTP പരിശോധന കോഡ് (2FA) സൃഷ്ടാവ്." + }, + "premiumSignUpSupport": { + "message": "മുൻ‌ഗണന ഉപഭോക്തൃ പിന്തുണ." + }, + "premiumSignUpFuture": { + "message": "ഭാവിയിലെ എല്ലാ പ്രീമിയം സവിശേഷതകളും. കൂടുതൽ ഉടനെ വരുന്നു !" + }, + "premiumPurchase": { + "message": "പ്രീമിയം വാങ്ങുക" + }, + "premiumPurchaseAlert": { + "message": "നിങ്ങൾക്ക് bitwarden.com വെബ് വാൾട്ടിൽ പ്രീമിയം അംഗത്വം വാങ്ങാം. നിങ്ങൾക്ക് ഇപ്പോൾ വെബ്സൈറ്റ് സന്ദർശിക്കാൻ ആഗ്രഹമുണ്ടോ?" + }, + "premiumCurrentMember": { + "message": "തങ്ങൾ ഒരു പ്രീമിയം അംഗമാണ്!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden-നെ പിന്തുണച്ചതിന് നന്ദി." + }, + "premiumPrice": { + "message": "എല്ലാം വെറും $PRICE$/ വർഷത്തേക്ക്!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "റിഫ്രഷ് പൂർത്തിയായി" + }, + "passwordHistory": { + "message": "പാസ്സ്‌വേഡ് ചരിത്രം" + }, + "clear": { + "message": "മായ്ക്കുക", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "പ്രദർശിപ്പിക്കാൻ പാസ്സ്‌വേഡുകൾ ഒന്നും ഇല്ല." + }, + "undo": { + "message": "തിരിച്ചാക്കുക" + }, + "redo": { + "message": "പുതിയപടിയാക്കുക" + }, + "cut": { + "message": "കട്ട്", + "description": "Cut to clipboard" + }, + "paste": { + "message": "ഒട്ടിക്കുക", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "എല്ലാം തിരഞ്ഞെടുക്കുക" + }, + "zoomIn": { + "message": "വലുതാക്കുക" + }, + "zoomOut": { + "message": "ചെറുതാക്കുക" + }, + "resetZoom": { + "message": "സൂം പുന സജ്ജമാക്കുക" + }, + "toggleFullScreen": { + "message": "ഫുൾ സ്ക്രീൻ ആക്കുക" + }, + "reload": { + "message": "വീണ്ടും ലഭ്യമാക്കുക" + }, + "toggleDevTools": { + "message": "ഡവലപ്പർ ഉപകരണങ്ങൾ ടോഗിൾ ചെയ്യുക" + }, + "minimize": { + "message": "ചെറുതാക്കുക", + "description": "Minimize window" + }, + "zoom": { + "message": "സൂം" + }, + "bringAllToFront": { + "message": "എല്ലാം മുന്നിലേക്ക് കൊണ്ടുവരുക", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Bitwarden-നെ കുറിച്ച്" + }, + "services": { + "message": "സേവനങ്ങള്‍" + }, + "hideBitwarden": { + "message": "Bitwarden മറയ്ക്കുക" + }, + "hideOthers": { + "message": "മറ്റുള്ളതിനെ മറയ്കുക" + }, + "showAll": { + "message": "എല്ലാം കാണിക്കുക" + }, + "quitBitwarden": { + "message": "Bitwarden നിർത്തുക" + }, + "valueCopied": { + "message": "$VALUE$ പകർത്തി", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "സഹായം" + }, + "window": { + "message": "വിൻഡോ" + }, + "checkPassword": { + "message": "പാസ്സ്‌വേർഡ് ചോർന്നോ എന്ന് നോക്കുക." + }, + "passwordExposed": { + "message": "ഈ പാസ്‌വേഡ് ഡാറ്റാ $VALUE$ ലംഘനങ്ങളിൽ ചോർന്നു. തങ്ങൾ ഇത് മാറ്റണം.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "അറിയപ്പെടുന്ന ഡാറ്റാ ലംഘനങ്ങളിൽ ഒന്നും ഈ പാസ്‌വേഡ് കണ്ടെത്തിയില്ല. ഇത് ഉപയോഗിക്കുന്നത് സുരക്ഷിതമായിരിക്കും." + }, + "baseDomain": { + "message": "അടിസ്ഥാന ഡൊമെയ്ൻ", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "ഹോസ്റ്റ്", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "കൃത്യമായി" + }, + "startsWith": { + "message": "തുടങ്ങുന്നത്" + }, + "regEx": { + "message": "പതിവ് പദപ്രയോഗം", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "പൊരുത്തം കണ്ടെത്തൽ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "സാധാരണ കണ്ടെത്തൽ", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "ഓപ്ഷനുകൾ ടോഗിൾ ചെയ്യുക" + }, + "organization": { + "message": "ഓർഗനൈസേഷൻ", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "സാധാരണ പോലെ" + }, + "exit": { + "message": "പുറത്തേക്കുപോവുക" + }, + "showHide": { + "message": "കാണിക്കുക/മറയ്ക്കുക", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "ട്രേയിലേക്ക് മറയ്‌ക്കുക" + }, + "alwaysOnTop": { + "message": "എപ്പോഴും മുകളിൽ", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "പുതുക്കിയത്", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "പാസ്‍വേഡ് പുതുക്കി", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "വാൾട് എക്സ്പോർട്" + }, + "fileFormat": { + "message": "ഫയൽ ഫോർമാറ്റ്" + }, + "warning": { + "message": "മുന്നറിയിപ്പ്", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "വാൾട് എക്‌സ്‌പോർട്ട് ഉറപ്പാക്കു" + }, + "exportWarningDesc": { + "message": "ഈ എക്‌സ്‌പോർട്ടിൽ എൻക്രിപ്റ്റ് ചെയ്യാത്ത ഫോർമാറ്റിൽ നിങ്ങളുടെ വാൾട് ഡാറ്റ അടങ്ങിയിരിക്കുന്നു. എക്‌സ്‌പോർട് ചെയ്ത ഫയൽ സുരക്ഷിതമല്ലാത്ത ചാനലുകളിൽ (ഇമെയിൽ പോലുള്ളവ) നിങ്ങൾ സംഭരിക്കുകയോ അയയ്ക്കുകയോ ചെയ്യരുത്. നിങ്ങൾ ഇത് ഉപയോഗിച്ചുകഴിഞ്ഞാലുടൻ അത് മായ്ച്ചുകളയണം." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "നിങ്ങൾ ഒരു സംഘടനയുടെയും അംഗമല്ല. മറ്റ് ഉപയോക്താക്കളുമായി ഇനങ്ങൾ സുരക്ഷിതമായി പങ്കിടാൻ ഓർഗനൈസേഷനുകൾ നിങ്ങളെ അനുവദിക്കുന്നു." + }, + "noCollectionsInList": { + "message": "പ്രദർശിപ്പിക്കാൻ കളക്ഷൻസ് ഒന്നും ഇല്ല." + }, + "ownership": { + "message": "ഉടമസ്ഥാവകാശം" + }, + "whoOwnsThisItem": { + "message": "ഈ ഇനം ആരുടേതാണ്?" + }, + "strong": { + "message": "ശക്തമാണ്", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "നല്ലതാണ്", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "ദുർബലമാണ്", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "ദുര്ബലമായ പ്രാഥമിക പാസ്‌വേഡ്" + }, + "weakMasterPasswordDesc": { + "message": "നിങ്ങൾ തിരഞ്ഞെടുത്ത പ്രാഥമിക പാസ്‌വേഡ് ദുർബലമാണ്. നിങ്ങളുടെ Bitwarden അക്കൗണ്ട് ശരിയായി സുരക്ഷിതമാക്കാൻ നിങ്ങൾ ഒരു ശക്തമായ മാസ്റ്റർ പാസ്‌വേഡ് (അല്ലെങ്കിൽ ഒരു പാസ്‌ഫ്രേസ്) ഉപയോഗിക്കണം. ഈ മാസ്റ്റർ പാസ്‌വേഡ് ഉപയോഗിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "pin": { + "message": "പിൻ", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "പിൻ ഉപയോഗിച്ച് അൺലോക്കുചെയ്യുക" + }, + "setYourPinCode": { + "message": "Bitwarden അൺലോക്കുചെയ്യുന്നതിന് നിങ്ങളുടെ പിൻ കോഡ് ക്രമീകരിക്കുക. നിങ്ങൾ എപ്പോഴെങ്കിലും അപ്ലിക്കേഷനിൽ നിന്ന് പൂർണ്ണമായി ലോഗ് ഔട്ട് ചെയ്യുകയാണെങ്കിൽ, പിൻ ക്രമീകരണങ്ങൾ പുനസജ്ജമാക്കും." + }, + "pinRequired": { + "message": "പിൻ കോഡ് നിർബന്ധമാണ്‌." + }, + "invalidPin": { + "message": "അസാധുവായ പിൻ കോഡ്." + }, + "unlockWithWindowsHello": { + "message": "Windows Hello ഉപയോഗിച്ച് അൺലോക്കുചെയ്യുക" + }, + "windowsHelloConsentMessage": { + "message": "Bitwarden വേണ്ടി പരിശോധിച്ചുറപ്പിക്കുക." + }, + "unlockWithTouchId": { + "message": "Touch ID ഉപയോഗിച്ച് അൺലോക്കുചെയ്യുക" + }, + "touchIdConsentMessage": { + "message": "Bitwarden വേണ്ടി പരിശോധിച്ചുറപ്പിക്കുക." + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "പുനരാരംഭിക്കുമ്പോൾ പ്രാഥമിക പാസ്‌വേഡ് ഉപയോഗിച്ച് പൂട്ടുക" + }, + "preferences": { + "message": "ക്രമീകരണങ്ങൾ" + }, + "enableMenuBar": { + "message": "മെനു ബാറിലെ ഐക്കണുകൾ പ്രാപ്തമാക്കുക" + }, + "enableMenuBarDesc": { + "message": "മെനു ബാറിൽ എല്ലായ്പ്പോഴും ഐക്കൺ കാണിക്കുക." + }, + "hideToMenuBar": { + "message": "മെനു ബാറിലേക്ക് മറയ്‌ക്കുക" + }, + "selectOneCollection": { + "message": "നിങ്ങൾ ഒരു കളക്ഷനെങ്കിലും തിരഞ്ഞെടുക്കണം." + }, + "premiumUpdated": { + "message": "നിങ്ങൾ പ്രീമിയത്തിലേക്ക് അപ്‌ഗ്രേഡുചെയ്‌തു." + }, + "restore": { + "message": "വീണ്ടെടുക്കുക" + }, + "premiumManageAlertAppStore": { + "message": "ആപ്പ് സ്റ്റോറിൽ നിന്ന് നിങ്ങളുടെ സബ്‌സ്‌ക്രിപ്‌ഷൻ മാനേജുചെയ്യാനാകും. തങ്ങൾക്കു ഇപ്പോൾ ആപ്പ് സ്റ്റോർ സന്ദർശിക്കണോ?" + }, + "legal": { + "message": "നിയമപരമായ", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "സേവന വ്യവസ്ഥകൾ" + }, + "privacyPolicy": { + "message": "സ്വകാര്യതാനയം" + }, + "unsavedChangesConfirmation": { + "message": "നിങ്ങൾക്ക് പോകണമെന്ന് ഉറപ്പാണോ? നിങ്ങൾ ഇപ്പോൾ പോയാൽ നിങ്ങളുടെ നിലവിലെ വിവരങ്ങൾ സംരക്ഷിക്കില്ല." + }, + "unsavedChangesTitle": { + "message": "സ്ഥിരപ്പെടാത്ത മാറ്റങ്ങൾ" + }, + "clone": { + "message": "ക്ലോൺ" + }, + "passwordGeneratorPolicyInEffect": { + "message": "ഒന്നോ അതിലധികമോ സംഘടന നയങ്ങൾ നിങ്ങളുടെ പാസ്സ്‌വേഡ് സൃഷ്ടാവിൻ്റെ ക്രമീകരണങ്ങളെ ബാധിക്കുന്നു." + }, + "vaultTimeoutAction": { + "message": "വാൾട് ടൈം ഔട്ട് പ്രവർത്തനം" + }, + "vaultTimeoutActionLockDesc": { + "message": "ലോക്കുചെയ്‌ത വാൾട് വീണ്ടും ആക്‌സസ് ചെയ്യുന്നതിന് തങ്ങളുടെ പ്രാഥമിക പാസ്‌വേഡ് വീണ്ടും നൽകേണ്ടതാണ്." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "ലോഗ് ഔട്ട് ചെയ്ത വാൾട് വീണ്ടും അക്സസ്സ് ചെയ്യാൻ ഓതെന്റിക്കേഷൻ ആവശ്യം വേരും." + }, + "lock": { + "message": "പൂട്ടുക", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "ട്രാഷ്", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "ട്രാഷ് തിരയുക" + }, + "permanentlyDeleteItem": { + "message": "ഇനം എന്നെന്നേക്കുമായി നീക്കം ചെയ്യുക" + }, + "permanentlyDeleteItemConfirmation": { + "message": "ഈ എന്നെന്നേക്കുമായി നീക്കം ചെയ്യാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "permanentlyDeletedItem": { + "message": "എന്നെന്നേക്കുമായി നീക്കം ചെയ്ത ഇനം" + }, + "restoreItem": { + "message": "ഇനം വീണ്ടെടുക്കുക" + }, + "restoreItemConfirmation": { + "message": "ഈ ഇനം വീണ്ടെടുക്കണമെന്ന് ഉറപ്പാണോ?" + }, + "restoredItem": { + "message": "വീണ്ടെടുത്ത ഇനങ്ങൾ" + }, + "permanentlyDelete": { + "message": "എന്നെന്നേക്കുമായി നീക്കം ചെയ്യുക" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "ലോഗ് ഔട്ട് ചെയ്യുന്നത് തങ്ങളുടെ വാൾട്ടിലേക്കുള്ള എല്ലാ ആക്സസും നീക്കംചെയ്യുകയും. കാലയളവിനുശേഷം ഓൺലൈൻ ഓതന്റിക്കേറ്റർ ആവശ്യമാണ്. ഈ ക്രമീകരണം ഉപയോഗിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "ടൈംഔട് ആക്ഷൻ സ്ഥിരീകരണം" + }, + "enterpriseSingleSignOn": { + "message": "എന്റർപ്രൈസ് SSO" + }, + "setMasterPassword": { + "message": "പ്രാഥമിക പാസ്‌വേഡ് സജ്ജമാക്കുക" + }, + "ssoCompleteRegistration": { + "message": "SSO ഉപയോഗിച്ച് പ്രവേശനം പൂർത്തിയാക്കാനും, നിങ്ങളുടെ വാൾട് ആക്സസ് ചെയ്യാനും സുരക്ഷിതമാക്കാനും ഒരു പ്രാഥമിക പാസ്‌വേഡ് സജ്ജമാക്കുക." + }, + "newMasterPass": { + "message": "പുതിയ പ്രാഥമിക പാസ്‌വേഡ്" + }, + "confirmNewMasterPass": { + "message": "പുതിയ പ്രാഥമിക പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക" + }, + "masterPasswordPolicyInEffect": { + "message": "ഒന്നോ അതിലധികമോ ഓർഗനൈസേഷൻ നയങ്ങൾക്ക് ഇനിപ്പറയുന്ന ആവശ്യകതകൾ നിറവേറ്റുന്നതിന് നിങ്ങളുടെ മാസ്റ്റർ പാസ്‌വേഡ് ആവശ്യമാണ്:" + }, + "policyInEffectMinComplexity": { + "message": "സങ്കീർണ്ണതയുടെ കുറഞ്ഞ സ്കോർ$SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "കുറഞ്ഞ ദൈർഘ്യം $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "ഒന്നോ അതിലധികമോ വലിയക്ഷരങ്ങൾ അടങ്ങിയിരിക്കുന്ന" + }, + "policyInEffectLowercase": { + "message": "ഒന്നോ അതിലധികമോ ചെറിയക്ഷരങ്ങൾ അടങ്ങിയിരിക്കുന്ന" + }, + "policyInEffectNumbers": { + "message": "ഒന്നോ അതിലധികമോ അക്കങ്ങൾ അടങ്ങിയിരിക്കുന്ന" + }, + "policyInEffectSpecial": { + "message": "ഇനിപ്പറയുന്ന ഒന്നോ അതിലധികമോ പ്രത്യേക പ്രതീകങ്ങൾ അടങ്ങിയിരിക്കുന്ന:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "നിങ്ങളുടെ പുതിയ മാസ്റ്റർ പാസ്‌വേഡ് നയ ആവശ്യകതകൾ നിറവേറ്റുന്നില്ല." + }, + "acceptPolicies": { + "message": "ഈ ബോക്സ് ചെക്കുചെയ്യുന്നതിലൂടെ നിങ്ങൾ ഇനിപ്പറയുന്നവ അംഗീകരിക്കുന്നു:" + }, + "acceptPoliciesError": { + "message": "സേവന നിബന്ധനകളും സ്വകാര്യതാ നയവും അംഗീകരിച്ചിട്ടില്ല." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "അംഗീകരിക്കുക" + }, + "verifyBrowserTitle": { + "message": "ബ്രൗസർ കണക്ഷൻ ഉറപ്പാക്കുക" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "ബയോമെട്രിക്സ് പ്രാപ്തമാക്കിയിട്ടില്ല" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "എല്ലാം Send-കൾ", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "ഫയൽ" + }, + "sendTypeText": { + "message": "വാചകം" + }, + "searchSends": { + "message": "Sends തിരയുക", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send തിരുത്തുക", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "എൻ്റെ വാൾട്" + }, + "text": { + "message": "വാചകം" + }, + "deletionDate": { + "message": "ഇല്ലാതാക്കൽ തീയതി" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/nb/messages.json b/apps/desktop/src/locales/nb/messages.json new file mode 100644 index 0000000000..bbfbab3419 --- /dev/null +++ b/apps/desktop/src/locales/nb/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtre" + }, + "allItems": { + "message": "Alle objekter" + }, + "favorites": { + "message": "Favoritter" + }, + "types": { + "message": "Typer" + }, + "typeLogin": { + "message": "Innlogging" + }, + "typeCard": { + "message": "Kort" + }, + "typeIdentity": { + "message": "Identitet" + }, + "typeSecureNote": { + "message": "Sikker notis" + }, + "folders": { + "message": "Mapper" + }, + "collections": { + "message": "Samlinger" + }, + "searchVault": { + "message": "Søk i hvelvet" + }, + "addItem": { + "message": "Legg til objekt" + }, + "shared": { + "message": "Delt" + }, + "share": { + "message": "Del" + }, + "moveToOrganization": { + "message": "Flytt til organisasjon" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ flyttet til $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Velg en organisasjon som du ønsker å flyttet elementet til. Ved å flytte til en organisasjon, overfører du eierskapet til elementet til den organisasjonen. Du vil ikke lenger være den direkte eieren av elementet etter at den har blitt flyttet." + }, + "attachments": { + "message": "Vedlegg" + }, + "viewItem": { + "message": "Vis objektet" + }, + "name": { + "message": "Navn" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Ny URI" + }, + "username": { + "message": "Brukernavn" + }, + "password": { + "message": "Passord" + }, + "passphrase": { + "message": "Passfrase" + }, + "editItem": { + "message": "Rediger objektet" + }, + "emailAddress": { + "message": "E-postadresse" + }, + "verificationCodeTotp": { + "message": "Verifiseringskode (TOTP)" + }, + "website": { + "message": "Nettsted" + }, + "notes": { + "message": "Notater" + }, + "customFields": { + "message": "Tilpassede felter" + }, + "launch": { + "message": "Åpne" + }, + "copyValue": { + "message": "Kopier verdien", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimer vinduet ved kopiering til utklippstavlen" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Bitwarden-vinduet minimeres automatisk når et objekts data kopieres til utklippstavlen." + }, + "toggleVisibility": { + "message": "Juster synlighet" + }, + "toggleCollapse": { + "message": "Bytt mellom skjul/utvid", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kortholderens navn" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Merke" + }, + "expiration": { + "message": "Utløp" + }, + "securityCode": { + "message": "Sikkerhetskode" + }, + "identityName": { + "message": "Identitetsnavn" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Personnummer" + }, + "passportNumber": { + "message": "Passnummer" + }, + "licenseNumber": { + "message": "Lisensnummer" + }, + "email": { + "message": "E-post" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresse" + }, + "premiumRequired": { + "message": "Premium er påkrevd" + }, + "premiumRequiredDesc": { + "message": "Et Premium-medlemskap er påkrevd for å bruke denne funksjonen." + }, + "errorOccurred": { + "message": "En feil har oppstått." + }, + "error": { + "message": "Feil" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Mars" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Mai" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "Desember" + }, + "ex": { + "message": "f․eks.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Tittel" + }, + "mr": { + "message": "Herr" + }, + "mrs": { + "message": "Fru" + }, + "ms": { + "message": "Frøken" + }, + "dr": { + "message": "Dr․" + }, + "expirationMonth": { + "message": "Utløpsmåned" + }, + "expirationYear": { + "message": "Utløpsår" + }, + "select": { + "message": "Velg" + }, + "other": { + "message": "Annet" + }, + "generatePassword": { + "message": "Generer et passord" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "Fornavn" + }, + "middleName": { + "message": "Mellomnavn" + }, + "lastName": { + "message": "Etternavn" + }, + "fullName": { + "message": "Fullt navn" + }, + "address1": { + "message": "Adresse 1" + }, + "address2": { + "message": "Adresse 2" + }, + "address3": { + "message": "Adresse 3" + }, + "cityTown": { + "message": "By / Tettsted" + }, + "stateProvince": { + "message": "Fylke / Region" + }, + "zipPostalCode": { + "message": "Postnummer" + }, + "country": { + "message": "Land" + }, + "save": { + "message": "Lagre" + }, + "cancel": { + "message": "Lukk" + }, + "delete": { + "message": "Slett" + }, + "favorite": { + "message": "Favoritt" + }, + "edit": { + "message": "Rediger" + }, + "authenticatorKeyTotp": { + "message": "Autentiseringsnøkkel (TOTP)" + }, + "folder": { + "message": "Mappe" + }, + "newCustomField": { + "message": "Nytt egendefinert felt" + }, + "value": { + "message": "Verdi" + }, + "dragToSort": { + "message": "Dra for å sortere" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Skjult" + }, + "cfTypeBoolean": { + "message": "Boolsk verdi" + }, + "cfTypeLinked": { + "message": "Tilknyttet", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Tilknyttet verdi", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Fjern" + }, + "nameRequired": { + "message": "Et navn er påkrevd." + }, + "addedItem": { + "message": "La til gjenstanden" + }, + "editedItem": { + "message": "Redigerte gjenstanden" + }, + "deleteItem": { + "message": "Slett objektet" + }, + "deleteFolder": { + "message": "Slett mappen" + }, + "deleteAttachment": { + "message": "Slett vedlegget" + }, + "deleteItemConfirmation": { + "message": "Er du sikker på at du vil slette dette objektet?" + }, + "deletedItem": { + "message": "Slettet objektet" + }, + "overwritePasswordConfirmation": { + "message": "Er du sikker på at du vil overskrive det nåværende passordet?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Ingen mappe", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Legg til en mappe" + }, + "editFolder": { + "message": "Rediger mappen" + }, + "regeneratePassword": { + "message": "Regenerer passord" + }, + "copyPassword": { + "message": "Kopier passordet" + }, + "copyUri": { + "message": "Kopier URIen" + }, + "copyVerificationCodeTotp": { + "message": "Kopier verifiseringskode (TOTP)" + }, + "length": { + "message": "Lengde" + }, + "numWords": { + "message": "Antall ord" + }, + "wordSeparator": { + "message": "Ordskiller" + }, + "capitalize": { + "message": "Stor forbokstav", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inkluder nummer" + }, + "close": { + "message": "Lukk" + }, + "minNumbers": { + "message": "Minst antall numre" + }, + "minSpecial": { + "message": "Minst antall spesialtegn", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Unngå tvetydige tegn" + }, + "searchCollection": { + "message": "Søk i samling" + }, + "searchFolder": { + "message": "Søk i mappe" + }, + "searchFavorites": { + "message": "Søk i favoritter" + }, + "searchType": { + "message": "Søk i type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Legg til et nytt vedlegg" + }, + "deletedAttachment": { + "message": "Slettet vedlegget" + }, + "deleteAttachmentConfirmation": { + "message": "Er du sikker på at du vil slette dette vedlegget?" + }, + "attachmentSaved": { + "message": "Vedlegget har blitt lagret." + }, + "file": { + "message": "Fil" + }, + "selectFile": { + "message": "Velg en fil." + }, + "maxFileSize": { + "message": "Den maksimale filstørrelsen er 500 MB." + }, + "updateKey": { + "message": "Du kan ikke bruke denne funksjonen før du oppdaterer krypteringsnøkkelen din." + }, + "editedFolder": { + "message": "Redigerte mappen" + }, + "addedFolder": { + "message": "La til en mappe" + }, + "deleteFolderConfirmation": { + "message": "Er du sikker på at du vil slette denne mappen?" + }, + "deletedFolder": { + "message": "Slettet mappen" + }, + "loginOrCreateNewAccount": { + "message": "Logg på eller opprett en ny konto for å få tilgang til ditt sikre hvelv." + }, + "createAccount": { + "message": "Opprett en konto" + }, + "logIn": { + "message": "Logg på" + }, + "submit": { + "message": "Send inn" + }, + "masterPass": { + "message": "Hovedpassord" + }, + "masterPassDesc": { + "message": "Superpassordet er passordet du bruker for å få tilgang til hvelvet ditt. Det er veldig viktig at du aldri glemmer ditt superpassord. Det er ingen måter å få tilbake passordet på dersom du noensinne skulle klare å glemme det." + }, + "masterPassHintDesc": { + "message": "Et hint for superpassordet kan hjelpe deg med å huske på passordet dersom du skulle glemme det." + }, + "reTypeMasterPass": { + "message": "Skriv inn hovedpassordet på nytt" + }, + "masterPassHint": { + "message": "Hint for hovedpassordet (valgfritt)" + }, + "settings": { + "message": "Innstillinger" + }, + "passwordHint": { + "message": "Passordhint" + }, + "enterEmailToGetHint": { + "message": "Skriv inn din kontos E-postadresse for å motta hintet til ditt superpassord." + }, + "getMasterPasswordHint": { + "message": "Få et hint om superpassordet" + }, + "emailRequired": { + "message": "E-postadressen er påkrevd." + }, + "invalidEmail": { + "message": "Ugyldig E-postadresse." + }, + "masterPassRequired": { + "message": "Superpassordet er påkrevd." + }, + "masterPassLength": { + "message": "Superpassordet må være ≥8 tegn lang." + }, + "masterPassDoesntMatch": { + "message": "Superpassord-bekreftelsen er ikke samsvarende." + }, + "newAccountCreated": { + "message": "Din nye konto har blitt opprettet! Du kan nå logge på." + }, + "masterPassSent": { + "message": "Vi har sendt deg en E-post med hintet til superpassordet." + }, + "unexpectedError": { + "message": "En uventet feil har oppstått." + }, + "itemInformation": { + "message": "Objektsinformasjon" + }, + "noItemsInList": { + "message": "Det er ingen gjenstander å liste opp." + }, + "sendVerificationCode": { + "message": "Send en verifiseringskode til e-posten din" + }, + "sendCode": { + "message": "Send kode" + }, + "codeSent": { + "message": "Kode sendt" + }, + "verificationCode": { + "message": "Verifiseringskode" + }, + "confirmIdentity": { + "message": "Bekreft identiteten din for å fortsette." + }, + "verificationCodeRequired": { + "message": "En verifiseringskode er påkrevd." + }, + "invalidVerificationCode": { + "message": "Ugyldig verifiseringskode" + }, + "continue": { + "message": "Fortsett" + }, + "enterVerificationCodeApp": { + "message": "Skriv inn den 6-sifrede verifiseringskoden som står på din autentiseringsapp." + }, + "enterVerificationCodeEmail": { + "message": "Skriv inn den 6-sifrede verifiseringskoden som ble sendt til $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "En verifiserings-E-post har blitt sendt til $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Husk på meg" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send E-posten med verifiseringskoden på nytt" + }, + "useAnotherTwoStepMethod": { + "message": "Bruk en annen 2-trinnsinnloggingsmetode" + }, + "insertYubiKey": { + "message": "Sett inn din YubiKey i din datamaskins USB-uttak, og så trykk på dens knapp." + }, + "insertU2f": { + "message": "Sett din sikkerhetsnøkkel inn i din datamaskins USB-uttak. Dersom den har en knapp, trykk på den." + }, + "recoveryCodeDesc": { + "message": "Har du mistet tilgang til alle dine 2-trinnsleverandører? Bruk din gjenopprettingskode til å fjerne alle 2-trinnsleverandører fra din konto." + }, + "recoveryCodeTitle": { + "message": "Gjenopprettingskode" + }, + "authenticatorAppTitle": { + "message": "Autentiseringsapp" + }, + "authenticatorAppDesc": { + "message": "Bruk en autentiseringsapp (f․eks․ Authy eller Google Authenticator) for å generere tidsbegrensede verifiseringskoder.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP-sikkerhetsnøkkel" + }, + "yubiKeyDesc": { + "message": "Bruk en YubiKey for å få tilgang til kontoen din. Virker med enheter av typene YubiKey 4, 4 Nano, 4C, og NEO." + }, + "duoDesc": { + "message": "Verifiser med Duo Security gjennom Duo Mobile-appen, SMS, telefonsamtale, eller en U2F-sikkerhetsnøkkel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifiser med Duo Security for din organisasjon gjennom Duo Mobile-appen, SMS, telefonsamtale, eller en U2F-sikkerhetsnøkkel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Bruk en hvilken som helst WebAuthn-aktivert sikkerhetsnøkkel for å få tilgang til kontoen din." + }, + "emailTitle": { + "message": "E-post" + }, + "emailDesc": { + "message": "Verifiseringskoder vil bli sendt til deg med E-post." + }, + "loginUnavailable": { + "message": "Innloggingen er utilgjengelig" + }, + "noTwoStepProviders": { + "message": "Denne kontoen har aktivert 2-trinnsinnlogging, men ingen av de oppsatte 2-trinnsleverandørene er støttet av denne enheten." + }, + "noTwoStepProviders2": { + "message": "Vennligst legg til ytterligere leverandører som er støttet bedre mellom enheter (f․eks․ en autentiseringsapp)." + }, + "twoStepOptions": { + "message": "Totrinns innloggingsalternativer" + }, + "selfHostedEnvironment": { + "message": "Selvbetjent miljø" + }, + "selfHostedEnvironmentFooter": { + "message": "Spesifiser grunn-nettadressen til din selvbetjente Bitwarden-installasjon." + }, + "customEnvironment": { + "message": "Tilpasset miljø" + }, + "customEnvironmentFooter": { + "message": "For avanserte brukere. Du kan bestemme grunn-nettadressen til hver tjeneste separat." + }, + "baseUrl": { + "message": "Tjener-nettadresse" + }, + "apiUrl": { + "message": "API-tjenernettadresse" + }, + "webVaultUrl": { + "message": "Netthvelvets tjeneradresse" + }, + "identityUrl": { + "message": "Identitetstjenerens nettadresse" + }, + "notificationsUrl": { + "message": "Varslingstjener-URL" + }, + "iconsUrl": { + "message": "Ikonenes tjenernettadresse" + }, + "environmentSaved": { + "message": "Miljø-nettadressene har blitt lagret." + }, + "ok": { + "message": "OK" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nei" + }, + "overwritePassword": { + "message": "Overskriv passordet" + }, + "learnMore": { + "message": "Lær mer" + }, + "featureUnavailable": { + "message": "Funksjonen er utilgjengelig" + }, + "loggedOut": { + "message": "Logget av" + }, + "loginExpired": { + "message": "Din innloggingsøkt har utløpt." + }, + "logOutConfirmation": { + "message": "Er du sikker på at du vil logge av?" + }, + "logOut": { + "message": "Logg av" + }, + "addNewLogin": { + "message": "Legg til en ny innlogging" + }, + "addNewItem": { + "message": "Legg til et nytt objekt" + }, + "addNewFolder": { + "message": "Legg til en ny mappe" + }, + "view": { + "message": "Vis" + }, + "account": { + "message": "Konto" + }, + "loading": { + "message": "Laster inn..." + }, + "lockVault": { + "message": "Lås hvelv" + }, + "passwordGenerator": { + "message": "Passordgenerator" + }, + "contactUs": { + "message": "Kontakt oss" + }, + "getHelp": { + "message": "Få hjelp" + }, + "fileBugReport": { + "message": "Legg inn en feilrapport" + }, + "blog": { + "message": "Blogg" + }, + "followUs": { + "message": "Følg oss" + }, + "syncVault": { + "message": "Synkroniser hvelvet" + }, + "changeMasterPass": { + "message": "Endre hovedpassordet" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kan endre superpassordet ditt på bitwarden.net-netthvelvet. Vil du besøke det nettstedet nå?" + }, + "fingerprintPhrase": { + "message": "Fingeravtrykksfrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Din kontos fingeravtrykksfrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Gå til netthvelvet" + }, + "getMobileApp": { + "message": "Skaff deg mobilappene" + }, + "getBrowserExtension": { + "message": "Skaff deg nettleserutvidelsene" + }, + "syncingComplete": { + "message": "Synkronisering fullført" + }, + "syncingFailed": { + "message": "Synkronisering mislyktes" + }, + "yourVaultIsLocked": { + "message": "Hvelvet ditt er låst. Bekreft hovedpassordet ditt for å fortsette." + }, + "unlock": { + "message": "Lås opp" + }, + "loggedInAsOn": { + "message": "Logget inn som $EMAIL$ på $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ugyldig superpassord" + }, + "twoStepLoginConfirmation": { + "message": "2-trinnsinnlogging gjør kontoen din mer sikker, ved å kreve at du verifiserer din innlogging med en annen enhet, f.eks. en autentiseringsapp, SMS, E-post, telefonsamtale, eller sikkerhetsnøkkel. 2-trinnsinnlogging kan aktiveres på bitwarden.com-netthvelvet. Vil du besøke den nettsiden nå?" + }, + "twoStepLogin": { + "message": "2-trinnsinnlogging" + }, + "vaultTimeout": { + "message": "Tidsavbrudd i hvelvet" + }, + "vaultTimeoutDesc": { + "message": "Velg når hvelvet ditt skal tidsavbrytes og utføre den valgte handlingen." + }, + "immediately": { + "message": "Umiddelbart" + }, + "tenSeconds": { + "message": "10 sekunder" + }, + "twentySeconds": { + "message": "20 sekunder" + }, + "thirtySeconds": { + "message": "30 sekunder" + }, + "oneMinute": { + "message": "1 minutt" + }, + "twoMinutes": { + "message": "2 minutter" + }, + "fiveMinutes": { + "message": "5 minutter" + }, + "fifteenMinutes": { + "message": "15 minutter" + }, + "thirtyMinutes": { + "message": "30 minutter" + }, + "oneHour": { + "message": "1 time" + }, + "fourHours": { + "message": "4 timer" + }, + "onIdle": { + "message": "Når PCen er inaktiv" + }, + "onSleep": { + "message": "Når PCen går i hvilemodus" + }, + "onLocked": { + "message": "Når PCen låses" + }, + "onRestart": { + "message": "Ved omstart" + }, + "never": { + "message": "Aldri" + }, + "security": { + "message": "Sikkerhet" + }, + "clearClipboard": { + "message": "Tøm utklippstavlen", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Slett automatisk kopierte verdier fra utklippstavlen.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Skru av nettstedsikoner" + }, + "disableFaviconDesc": { + "message": "Nettstedsikoner sørger for et gjenkjennelig bilde ved siden av hvert innloggingsobjekt i hvelvet ditt." + }, + "enableMinToTray": { + "message": "Minimer til oppgavelinjen" + }, + "enableMinToTrayDesc": { + "message": "Når du lukker vinduet, skal et ikon vises i oppgavelinjen i stedet." + }, + "enableMinToMenuBar": { + "message": "Minimer til menylinjen" + }, + "enableMinToMenuBarDesc": { + "message": "Når du minimerer vinduet, vil et ikon vises i oppgavelinjen i stedet." + }, + "enableCloseToTray": { + "message": "Lukk til oppgavelinjen" + }, + "enableCloseToTrayDesc": { + "message": "Når du lukker vinduet, skal et ikon vises i verktøykassen i stedet." + }, + "enableCloseToMenuBar": { + "message": "Lukk til menylinje" + }, + "enableCloseToMenuBarDesc": { + "message": "Når du lukker vinduet, vis et ikon i menylinjen i stedet." + }, + "enableTray": { + "message": "Skru på oppgavelinjeikon" + }, + "enableTrayDesc": { + "message": "Vis et ikon i verktøykassen til enhver tid." + }, + "startToTray": { + "message": "Start med oppgavelinjeikonet" + }, + "startToTrayDesc": { + "message": "Når applikasjonen starter for første gang, vises et ikon i oppgavelinjen." + }, + "startToMenuBar": { + "message": "Start på menylinjen" + }, + "startToMenuBarDesc": { + "message": "Når programmet først startes opp, vis kun et ikon i menylinjen." + }, + "openAtLogin": { + "message": "Start automatisk ved innlogging" + }, + "openAtLoginDesc": { + "message": "Start Bitwardens skrivebordsprogram automatisk ved innlogging." + }, + "alwaysShowDock": { + "message": "Alltid vis i dokken" + }, + "alwaysShowDockDesc": { + "message": "Vis Bitwarden-ikonet i dokken selv når den er minimert til menylinjen." + }, + "confirmTrayTitle": { + "message": "Bekreft avskruing av skuffen" + }, + "confirmTrayDesc": { + "message": "Å skru av denne innstillingen vil også skru av alle andre skufferelaterte innstillinger." + }, + "language": { + "message": "Språk" + }, + "languageDesc": { + "message": "Endre språket som brukes av programmet. En programomstart er påkrevd." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Endre appens fargetema." + }, + "dark": { + "message": "Mørkt", + "description": "Dark color" + }, + "light": { + "message": "Lyst", + "description": "Light color" + }, + "copy": { + "message": "Kopier", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Se etter oppdateringer" + }, + "version": { + "message": "Versjon $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Start på nytt for å oppdatere" + }, + "restartToUpdateDesc": { + "message": "Versjon $VERSION_NUM$ er klar til å installeres. Du må starte appen på nytt for å fullføre installasjonen. Vil du starte Bitwarden på nytt nå og oppdatere den?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Oppdatering tilgjengelig" + }, + "updateAvailableDesc": { + "message": "En oppdatering ble funnet. Vil du laste den ned nå?" + }, + "restart": { + "message": "Start på nytt" + }, + "later": { + "message": "Senere" + }, + "noUpdatesAvailable": { + "message": "Ingen oppdateringer er tilgjengelig for øyeblikket. Du bruker den seneste versjonen." + }, + "updateError": { + "message": "Feil ved oppdatering" + }, + "unknown": { + "message": "Ukjent" + }, + "copyUsername": { + "message": "Kopier brukernavnet" + }, + "copyNumber": { + "message": "Kopier nummeret", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopier sikkerhetskoden", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium-medlemskap" + }, + "premiumManage": { + "message": "Behandle medlemsskapet" + }, + "premiumManageAlert": { + "message": "Du kan behandle medlemskapet ditt på bitwarden.net-netthvelvet. Vil du besøke det nettstedet nå?" + }, + "premiumRefresh": { + "message": "Oppfrisk medlemsskapet" + }, + "premiumNotCurrentMember": { + "message": "Du er ikke for øyeblikket et Premium-medlem." + }, + "premiumSignUpAndGet": { + "message": "Skriv deg opp på et Premium-abonnement og få:" + }, + "premiumSignUpStorage": { + "message": "1 GB med kryptert fillagring." + }, + "premiumSignUpTwoStep": { + "message": "Ytterligere 2-trinnsinnloggingsmuligheter, slik som YubiKey, FIDO U2F, og Duo." + }, + "premiumSignUpReports": { + "message": "Passordhygiene, kontohelse, og databruddsrapporter som holder hvelvet ditt trygt." + }, + "premiumSignUpTotp": { + "message": "TOTP-verifiseringskodegenerator (2FA) for innlogginger i ditt hvelv." + }, + "premiumSignUpSupport": { + "message": "Prioritert kundestøtte." + }, + "premiumSignUpFuture": { + "message": "Alle fremtidige Premium-egenskaper. Mere er planlagt snart!" + }, + "premiumPurchase": { + "message": "Kjøp Premium" + }, + "premiumPurchaseAlert": { + "message": "Du kan kjøpe et Premium-medlemskap på bitwarden.net-netthvelvet. Vil du besøke det nettstedet nå?" + }, + "premiumCurrentMember": { + "message": "Du er et Premium-medlem!" + }, + "premiumCurrentMemberThanks": { + "message": "Takk for at du støtter Bitwarden." + }, + "premiumPrice": { + "message": "Alt dette for bare $PRICE$/år!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Oppfriskning fullført" + }, + "passwordHistory": { + "message": "Passordhistorikk" + }, + "clear": { + "message": "Tøm", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Det er ingen passord å liste opp." + }, + "undo": { + "message": "Angre" + }, + "redo": { + "message": "Gjør om" + }, + "cut": { + "message": "Klipp ut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Lim inn", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Velg alt" + }, + "zoomIn": { + "message": "Forstørr" + }, + "zoomOut": { + "message": "Forminsk" + }, + "resetZoom": { + "message": "Tilbakestill forstørring" + }, + "toggleFullScreen": { + "message": "Gå inn/ut av fullskjerm" + }, + "reload": { + "message": "Oppfrisk" + }, + "toggleDevTools": { + "message": "Skru av/på utviklerverktøy" + }, + "minimize": { + "message": "Minimer", + "description": "Minimize window" + }, + "zoom": { + "message": "Forstørr" + }, + "bringAllToFront": { + "message": "Plasser fremst", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Om Bitwarden" + }, + "services": { + "message": "Tjenester" + }, + "hideBitwarden": { + "message": "Skjul Bitwarden" + }, + "hideOthers": { + "message": "Skjul andre" + }, + "showAll": { + "message": "Vis alle" + }, + "quitBitwarden": { + "message": "Avslutt Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ har blitt kopiert", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Hjelp" + }, + "window": { + "message": "Vindu" + }, + "checkPassword": { + "message": "Sjekk om passordet har blitt utsatt." + }, + "passwordExposed": { + "message": "Dette passordet har blitt utsatt $VALUE$ gang(er) i et databrudd. Du burde endre det.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Dette passordet ble ikke funnet i noen kjente databrudd. Det burde være trygt å bruke." + }, + "baseDomain": { + "message": "Grunndomene", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Vert", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Nøyaktig" + }, + "startsWith": { + "message": "Starter med" + }, + "regEx": { + "message": "Regulært uttrykk", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match-gjenkjenning", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standard match-gjenkjenning", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Skru av/på innstillinger" + }, + "organization": { + "message": "Organisasjon", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Standard" + }, + "exit": { + "message": "Avslutt" + }, + "showHide": { + "message": "Vis/Skjul", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Skjul til oppgavelinjen" + }, + "alwaysOnTop": { + "message": "Foran andre vinduer", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Oppdatert den", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Passordet ble oppdatert den", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Eksporter hvelvet" + }, + "fileFormat": { + "message": "Filformat" + }, + "warning": { + "message": "ADVARSEL", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Bekreft eksport av hvelvet" + }, + "exportWarningDesc": { + "message": "Eksporten inneholder dine hvelvdataer i et ukryptert format. Du burde ikke lagre eller sende den eksporterte filen over usikre tjenester (f.eks. E-post). Slett det umiddelbart etter at du er ferdig med å bruke dem." + }, + "encExportKeyWarningDesc": { + "message": "Denne eksporten krypterer dataene dine ved hjelp av kontoen din sin krypteringsnøkkel. Hvis du noen gang endrer krypteringsnøkkelen til kontoen din, bør du eksportere dataene igjen, ettersom du da ikke vil kunne dekryptere denne eksportfilen." + }, + "encExportAccountWarningDesc": { + "message": "Kontokrypteringsnøkler er unike for hver Bitwarden sin brukerkonto, og du kan ikke importere en kryptert eksport til en annen konto." + }, + "noOrganizationsList": { + "message": "Du tilhører ikke noen organisasjoner. Organisasjoner gjør det mulig for deg å sikkert dele objekter med andre brukere." + }, + "noCollectionsInList": { + "message": "Det er ingen samlinger å liste opp." + }, + "ownership": { + "message": "Eierskap" + }, + "whoOwnsThisItem": { + "message": "Hvem eier dette elementet?" + }, + "strong": { + "message": "Sterkt", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bra", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Svakt", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Svakt hovedpassord" + }, + "weakMasterPasswordDesc": { + "message": "Superpassordet du har valgt er svakt. Du bør bruke et sterkt superpassord (eller en passordfrase) for å sikre Bitwarden-kontoen din på en forsvarlig måte. Er du sikker på at du vil bruke dette superpassordet?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Lås opp med PIN" + }, + "setYourPinCode": { + "message": "Angi PIN-koden for å låse opp Bitwarden. PIN-innstillingene dine blir tilbakestilt hvis du noen gang logger deg ut av applikasjonen." + }, + "pinRequired": { + "message": "PIN-kode er påkrevd." + }, + "invalidPin": { + "message": "Ugyldig PIN-kode." + }, + "unlockWithWindowsHello": { + "message": "Lås opp med Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Bekreft for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Lås opp med Touch ID" + }, + "touchIdConsentMessage": { + "message": "lås opp hvelvet ditt" + }, + "noAutoPromptWindowsHello": { + "message": "Ikke be om Windows Hello ved oppstart." + }, + "noAutoPromptTouchId": { + "message": "Ikke be om Touch ID ved oppstart." + }, + "lockWithMasterPassOnRestart": { + "message": "Lås med hovedpassord ved omstart" + }, + "preferences": { + "message": "Innstillinger" + }, + "enableMenuBar": { + "message": "Aktiver menylinjeikon" + }, + "enableMenuBarDesc": { + "message": "Vis alltid et ikon i menylinjen." + }, + "hideToMenuBar": { + "message": "Skjul til menylinjen" + }, + "selectOneCollection": { + "message": "Du må velge minst én samling." + }, + "premiumUpdated": { + "message": "Du har oppgradert til premium." + }, + "restore": { + "message": "Gjenopprett" + }, + "premiumManageAlertAppStore": { + "message": "Du kan administrere abonnementet ditt fra App Store. Ønsker du å besøke App Store nå?" + }, + "legal": { + "message": "Juridisk", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Vilkår for bruk" + }, + "privacyPolicy": { + "message": "Personvern" + }, + "unsavedChangesConfirmation": { + "message": "Er du sikker på at du ønsker å avslutte? Hvis du avslutter nå, blir ikke den nåværende informasjonen lagret." + }, + "unsavedChangesTitle": { + "message": "Ikke lagrede endringer" + }, + "clone": { + "message": "Klon" + }, + "passwordGeneratorPolicyInEffect": { + "message": "En eller flere av organisasjons retningslinjer påvirker generatorinnstillingene dine." + }, + "vaultTimeoutAction": { + "message": "Handling ved tidsavbrudd i hvelvet" + }, + "vaultTimeoutActionLockDesc": { + "message": "Et låst hvelv krever at du skriver inn hovedpassordet ditt på nytt for å få tilgang til hvelvet igjen." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Et utlogget hvelv krever at du autentiserer deg selv på nytt for å få tilgang til det igjen." + }, + "lock": { + "message": "Lås", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papirkurv", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Søk i papirkurven" + }, + "permanentlyDeleteItem": { + "message": "Slett objektet permanent" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Er du sikker på at du vil slette dette objektet permanent?" + }, + "permanentlyDeletedItem": { + "message": "Slett objektet permanent" + }, + "restoreItem": { + "message": "Gjenopprett objekt" + }, + "restoreItemConfirmation": { + "message": "Er du sikker på at du vil gjenopprette dette objektet?" + }, + "restoredItem": { + "message": "Gjenopprettet objekt" + }, + "permanentlyDelete": { + "message": "Slett permanent" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Hvis du logger ut, fjerner du all tilgang til hvelvet ditt og det vil bli krevd online autentisering på nytt etter tidsavbruddet. Er du sikker på at du vil bruke denne innstillingen?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bekreftelse av handling ved tidsavbrudd" + }, + "enterpriseSingleSignOn": { + "message": "Bedriftsinnlogging (SSO)" + }, + "setMasterPassword": { + "message": "Angi hovedpassord" + }, + "ssoCompleteRegistration": { + "message": "For å fullføre innloggingen med SSO, angi et superpassord for å få tilgang til og beskytte hvelvet ditt." + }, + "newMasterPass": { + "message": "Nytt hovedpassord" + }, + "confirmNewMasterPass": { + "message": "Bekreft nytt hovedpassord" + }, + "masterPasswordPolicyInEffect": { + "message": "En eller flere av organisasjonens vilkår krever hovedpassordet ditt for å oppfylle følgende krav:" + }, + "policyInEffectMinComplexity": { + "message": "Minimumspoengsum for kompleksistet er $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimumslengde på $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Inneholder én eller flere store bokstaver" + }, + "policyInEffectLowercase": { + "message": "Inneholder én eller flere små bokstaver" + }, + "policyInEffectNumbers": { + "message": "Inneholder ett eller flere tall" + }, + "policyInEffectSpecial": { + "message": "Inneholder ett eller flere av følgende spesialtegn $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Det nye hovedpassordet ditt oppfyller ikke vilkårene." + }, + "acceptPolicies": { + "message": "Ved å huke av i denne boksen sier du deg enig i følgende:" + }, + "acceptPoliciesError": { + "message": "Bruksvilkårene og personvernerklæring er ikke godkjent." + }, + "enableBrowserIntegration": { + "message": "Aktiver nettleserintegrasjon" + }, + "enableBrowserIntegrationDesc": { + "message": "Nettleserintegrasjon brukes til biometri i nettleseren." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Nettleserintegrasjon støttes ikke" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Nettleserintegrasjon støttes dessverre bare i Mac App Store-versjonen for øyeblikket." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Nettleserintegrasjon støttes ikke" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Nettleserintegrasjon er for øyeblikket dessverre ikke støttet i Windows Store-versjonen." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Krev verifisering av nettleserintegrasjon" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Aktiver et ekstra lag sikkerhet ved å kreve fingeravtrykksvalidering når du oppretter en kobling mellom skrivebordet og nettleseren. Når dette er aktivert kreves det brukerintervensjon og verifisering hver gang en tilkobling etableres." + }, + "approve": { + "message": "Godkjenn" + }, + "verifyBrowserTitle": { + "message": "Verifiser nettlesertilkoblingen" + }, + "verifyBrowserDesc": { + "message": "Kontroller at vist fingeravtrykk er identisk med fingeravtrykket som vises i nettleserutvidelsen." + }, + "biometricsNotEnabledTitle": { + "message": "Biometri er ikke aktivert" + }, + "biometricsNotEnabledDesc": { + "message": "Biometri i nettleserutvidelsen krever først aktivering i innstillinger i skrivebordsprogrammet." + }, + "personalOwnershipSubmitError": { + "message": "På grunn av bedrifsretningslinjer er du begrenset fra å lagre objekter til ditt personlige hvelv. Endre alternativ for eierskap til en organisasjon og velg blant tilgjengelige samlinger." + }, + "hintEqualsPassword": { + "message": "Passordhintet ditt kan ikke være det samme som passordet ditt." + }, + "personalOwnershipPolicyInEffect": { + "message": "En bedriftsretningslinje påvirker dine eierskapsinnstillinger." + }, + "allSends": { + "message": "Alle Send-er", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fil" + }, + "sendTypeText": { + "message": "Tekst" + }, + "searchSends": { + "message": "Søk i Send-ene", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Rediger Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mitt hvelv" + }, + "text": { + "message": "Tekst" + }, + "deletionDate": { + "message": "Dato for sletting" + }, + "deletionDateDesc": { + "message": "Send-en vil bli slettet permanent på den angitte dato og klokkeslett.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Utløpsdato" + }, + "expirationDateDesc": { + "message": "Hvis satt, vil tilgang til denne Send gå ut på angitt dato og klokkeslett.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maksimal antall tilganger" + }, + "maxAccessCountDesc": { + "message": "Hvis satt, vil brukere ikke lenger ha tilgang til dette send når maksimal antall tilgang er nådd.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Antall nåværende tilgang" + }, + "disableSend": { + "message": "Deaktiver denne Send-en, slik at ingen får tilgang til den.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Eventuelt krever et passord for brukere å få tilgang til denne Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notater om denne Send-en.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send lenke", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send lenke", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Når du åpner Send-en, er teksten skjult som standard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Opprettet Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Redigerte Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Slettet Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nytt passord" + }, + "whatTypeOfSend": { + "message": "Hvilken type Send er dette?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Opprett Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Teksten du ønsker å sende." + }, + "sendFileDesc": { + "message": "Filen du vil sende." + }, + "days": { + "message": "$DAYS$ dager", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dag" + }, + "custom": { + "message": "Egendefinert" + }, + "deleteSendConfirmation": { + "message": "Er du sikker på at du vil slette denne Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopier Send-lenke til utklippstavlen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kopier lenken for å dele denne Send-en til utklippstavlen min ved lagring." + }, + "sendDisabled": { + "message": "Send er skrudd av", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "På grunn av en virksomhetsregel kan du kun slette en eksisterende Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopier lenke" + }, + "disabled": { + "message": "Deaktivert" + }, + "maxAccessCountReached": { + "message": "Maksimalt antall tilganger nådd" + }, + "expired": { + "message": "Utløpt" + }, + "pendingDeletion": { + "message": "Venter på sletting" + }, + "webAuthnAuthenticate": { + "message": "Autentiser WebAuthn" + }, + "hideEmail": { + "message": "Skjul min e-postadresse fra mottakere." + }, + "sendOptionsPolicyInEffect": { + "message": "En eller flere av organisasjons retningslinjer påvirker generatorinnstillingene dine." + }, + "emailVerificationRequired": { + "message": "E-postbekreftelse kreves" + }, + "emailVerificationRequiredDesc": { + "message": "Du må bekrefte E-postadressen din for å bruke denne funksjonen." + }, + "passwordPrompt": { + "message": "Forespørsel om hovedpassord på nytt" + }, + "passwordConfirmation": { + "message": "Superpassord bekreftelse" + }, + "passwordConfirmationDesc": { + "message": "Denne handlingen er beskyttet. For å fortsette, skriv inn hovedpassordet ditt på nytt for å verifisere din identitet." + }, + "updatedMasterPassword": { + "message": "Oppdaterte hovedpassordet" + }, + "updateMasterPassword": { + "message": "Oppdater hovedpassord" + }, + "updateMasterPasswordWarning": { + "message": "Hovedpassordet ditt ble nylig endret av en administrator i organisasjonen din. For å få tilgang til hvelvet, må du oppdatere det nå. Hvis du fortsetter, logges du ut av den nåværende økten, og du må logge på igjen. Aktive økter på andre enheter kan fortsette å være aktive i opptil én time." + }, + "hours": { + "message": "Timer" + }, + "minutes": { + "message": "Minutter" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Organisasjonens retningslinjer påvirker tidsavbruddet for hvelvet ditt. Maksimalt tillatt tidsavbrudd for hvelv er $HOURS$ time(r) og $MINUTES$ minutt(er)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Tidsavbruddet ditt for hvelvet overstiger begrensningene som er satt av organisasjonen din." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatisk registrering" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Denne organisasjonen har en bedriftsoppsettsregel som automatisk innrullerer deg i tilbakestilling av passord. Registrering vil tillate organisasjonsadministratorer å endre hovedpassordet ditt." + }, + "vaultExportDisabled": { + "message": "Hvelveksportering er skrudd av" + }, + "personalVaultExportPolicyInEffect": { + "message": "En eller flere regler i organisasjonsoppsettet forhindrer deg i å eksportere ditt personlige hvelv." + }, + "addAccount": { + "message": "Legg til konto" + }, + "removeMasterPassword": { + "message": "Fjern hovedpassord" + }, + "removedMasterPassword": { + "message": "Hovedpassordet er fjernet." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ bruker SSO med en selvdrevet nøkkelserver. Et hovedpassord er ikke lenger nødvendig for å logge inn for medlemmer av denne organisasjonen.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Forlat organisasjon" + }, + "leaveOrganizationConfirmation": { + "message": "Er du sikker på at du vil forlate organisasjonen?" + }, + "leftOrganization": { + "message": "Du forlot organisasjonen." + }, + "ssoKeyConnectorUnavailable": { + "message": "Kan ikke nå nøkkeltilkobleren. Prøv igjen senere." + }, + "lockAllVaults": { + "message": "Lås alle hvelv" + }, + "accountLimitReached": { + "message": "Ikke mer enn 5 kontoer kan være logget på samtidig." + }, + "accountPreferences": { + "message": "Preferanser" + }, + "appPreferences": { + "message": "Appinnstillinger (alle kontoer)" + }, + "accountSwitcherLimitReached": { + "message": "Kontogrense nådd. Logg ut av en konto for å legge til en annen en." + }, + "settingsTitle": { + "message": "Appinnstillinger for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Bytt konto" + }, + "options": { + "message": "Alternativer" + }, + "sessionTimeout": { + "message": "Økten ble tidsavbrutt. Vennligst gå tilbake og prøv å logge inn på nytt." + }, + "exportingPersonalVaultTitle": { + "message": "Eksporter personlig hvelv" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/nl/messages.json b/apps/desktop/src/locales/nl/messages.json new file mode 100644 index 0000000000..385877cf85 --- /dev/null +++ b/apps/desktop/src/locales/nl/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "Alle items" + }, + "favorites": { + "message": "Favorieten" + }, + "types": { + "message": "Categorieën" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Kaart" + }, + "typeIdentity": { + "message": "Identiteit" + }, + "typeSecureNote": { + "message": "Veilige notitie" + }, + "folders": { + "message": "Mappen" + }, + "collections": { + "message": "Verzamelingen" + }, + "searchVault": { + "message": "Kluis doorzoeken" + }, + "addItem": { + "message": "Item toevoegen" + }, + "shared": { + "message": "Gedeeld" + }, + "share": { + "message": "Delen" + }, + "moveToOrganization": { + "message": "Naar organisatie verplaatsen" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ verplaatst naar $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Kies een organisatie waarnaar je dit item wilt verplaatsen. Door het verplaatsen krijgt de organisatie de eigendomsrechten van het item. Je bent niet langer de directe eigenaar meer van het item als het is verplaatst." + }, + "attachments": { + "message": "Bijlagen" + }, + "viewItem": { + "message": "Item weergeven" + }, + "name": { + "message": "Naam" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nieuwe URI" + }, + "username": { + "message": "Gebruikersnaam" + }, + "password": { + "message": "Wachtwoord" + }, + "passphrase": { + "message": "Wachtwoordzin" + }, + "editItem": { + "message": "Item bewerken" + }, + "emailAddress": { + "message": "E-mailadres" + }, + "verificationCodeTotp": { + "message": "Verificatiecode (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notities" + }, + "customFields": { + "message": "Aangepaste velden" + }, + "launch": { + "message": "Starten" + }, + "copyValue": { + "message": "Waarde kopiëren", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimaliseren bij kopiëren naar klembord" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimaliseren bij het kopiëren van itemgegevens naar het klembord." + }, + "toggleVisibility": { + "message": "Zichtbaarheid wisselen" + }, + "toggleCollapse": { + "message": "Inklappen/uitklappen", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Naam kaarthouder" + }, + "number": { + "message": "Kaartnummer" + }, + "brand": { + "message": "Merk" + }, + "expiration": { + "message": "Vervaldatum" + }, + "securityCode": { + "message": "Veiligheidscode" + }, + "identityName": { + "message": "Identiteitsnaam" + }, + "company": { + "message": "Bedrijf" + }, + "ssn": { + "message": "Burgerservicenummer" + }, + "passportNumber": { + "message": "Paspoortnummer" + }, + "licenseNumber": { + "message": "Rijbewijsnummer" + }, + "email": { + "message": "E-mailadres" + }, + "phone": { + "message": "Telefoonnummer" + }, + "address": { + "message": "Adres" + }, + "premiumRequired": { + "message": "Premium is vereist" + }, + "premiumRequiredDesc": { + "message": "Voor deze functionaliteit heb je een Premium-abonnement nodig." + }, + "errorOccurred": { + "message": "Er is een fout opgetreden." + }, + "error": { + "message": "Fout" + }, + "january": { + "message": "januari" + }, + "february": { + "message": "februari" + }, + "march": { + "message": "maart" + }, + "april": { + "message": "april" + }, + "may": { + "message": "mei" + }, + "june": { + "message": "juni" + }, + "july": { + "message": "juli" + }, + "august": { + "message": "augustus" + }, + "september": { + "message": "september" + }, + "october": { + "message": "oktober" + }, + "november": { + "message": "november" + }, + "december": { + "message": "december" + }, + "ex": { + "message": "bijv.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Aanhef" + }, + "mr": { + "message": "Dhr." + }, + "mrs": { + "message": "Mevr." + }, + "ms": { + "message": "Mej." + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Vervalmaand" + }, + "expirationYear": { + "message": "Vervaljaar" + }, + "select": { + "message": "Selecteren" + }, + "other": { + "message": "Overig" + }, + "generatePassword": { + "message": "Wachtwoord genereren" + }, + "type": { + "message": "Categorie" + }, + "firstName": { + "message": "Voornaam" + }, + "middleName": { + "message": "Tweede naam" + }, + "lastName": { + "message": "Achternaam" + }, + "fullName": { + "message": "Volledige naam" + }, + "address1": { + "message": "Adres 1" + }, + "address2": { + "message": "Adres 2" + }, + "address3": { + "message": "Adres 3" + }, + "cityTown": { + "message": "Stad / gemeente" + }, + "stateProvince": { + "message": "Staat / provincie" + }, + "zipPostalCode": { + "message": "Postcode" + }, + "country": { + "message": "Land" + }, + "save": { + "message": "Opslaan" + }, + "cancel": { + "message": "Annuleren" + }, + "delete": { + "message": "Verwijderen" + }, + "favorite": { + "message": "Favoriet" + }, + "edit": { + "message": "Bewerken" + }, + "authenticatorKeyTotp": { + "message": "Authenticatiecode (TOTP)" + }, + "folder": { + "message": "Map" + }, + "newCustomField": { + "message": "Nieuw aangepast veld" + }, + "value": { + "message": "Waarde" + }, + "dragToSort": { + "message": "Slepen om te sorteren" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Verborgen" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Gekoppeld", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Gekoppelde waarde", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Verwijderen" + }, + "nameRequired": { + "message": "Naam is vereist." + }, + "addedItem": { + "message": "Item is toegevoegd" + }, + "editedItem": { + "message": "Item is bewerkt" + }, + "deleteItem": { + "message": "Item verwijderen" + }, + "deleteFolder": { + "message": "Map verwijderen" + }, + "deleteAttachment": { + "message": "Bijlage verwijderen" + }, + "deleteItemConfirmation": { + "message": "Weet je zeker dat je dit naar de prullenbak wilt verplaatsen?" + }, + "deletedItem": { + "message": "Item is verwijderd" + }, + "overwritePasswordConfirmation": { + "message": "Weet je zeker dat je het huidige wachtwoord wilt overschrijven?" + }, + "overwriteUsername": { + "message": "Gebruikersnaam overschrijven" + }, + "overwriteUsernameConfirmation": { + "message": "Weet je zeker dat je de huidige gebruikersnaam wilt overschrijven?" + }, + "noneFolder": { + "message": "Geen map", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Map toevoegen" + }, + "editFolder": { + "message": "Map bewerken" + }, + "regeneratePassword": { + "message": "Opnieuw genereren" + }, + "copyPassword": { + "message": "Wachtwoord kopiëren" + }, + "copyUri": { + "message": "URI kopiëren" + }, + "copyVerificationCodeTotp": { + "message": "Verificatiecode kopiëren (TOTP)" + }, + "length": { + "message": "Lengte" + }, + "numWords": { + "message": "Aantal woorden" + }, + "wordSeparator": { + "message": "Scheidingsteken" + }, + "capitalize": { + "message": "Beginhoofdletters", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Cijfer toevoegen" + }, + "close": { + "message": "Sluiten" + }, + "minNumbers": { + "message": "Minimum aantal cijfers" + }, + "minSpecial": { + "message": "Minimum aantal speciale tekens", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Dubbelzinnige tekens vermijden" + }, + "searchCollection": { + "message": "Verzameling doorzoeken" + }, + "searchFolder": { + "message": "Map doorzoeken" + }, + "searchFavorites": { + "message": "Favorieten doorzoeken" + }, + "searchType": { + "message": "Categorie doorzoeken", + "description": "Search item type" + }, + "newAttachment": { + "message": "Nieuwe bijlage toevoegen" + }, + "deletedAttachment": { + "message": "Bijlage is verwijderd" + }, + "deleteAttachmentConfirmation": { + "message": "Weet je zeker dat je deze bijlage wilt verwijderen?" + }, + "attachmentSaved": { + "message": "De bijlage is opgeslagen." + }, + "file": { + "message": "Bestand" + }, + "selectFile": { + "message": "Selecteer een bestand." + }, + "maxFileSize": { + "message": "Maximale bestandsgrootte is 500 MB." + }, + "updateKey": { + "message": "Je kunt deze functie pas gebruiken als je je encryptiesleutel bijwerkt." + }, + "editedFolder": { + "message": "Map is bewerkt" + }, + "addedFolder": { + "message": "Map is toegevoegd" + }, + "deleteFolderConfirmation": { + "message": "Weet je zeker dat je deze map wilt verwijderen?" + }, + "deletedFolder": { + "message": "Map is verwijderd" + }, + "loginOrCreateNewAccount": { + "message": "Log in of maak een nieuw account aan om toegang te krijgen tot je beveiligde kluis." + }, + "createAccount": { + "message": "Account aanmaken" + }, + "logIn": { + "message": "Inloggen" + }, + "submit": { + "message": "Opslaan" + }, + "masterPass": { + "message": "Hoofdwachtwoord" + }, + "masterPassDesc": { + "message": "Het hoofdwachtwoord is het wachtwoord waarmee je toegang krijgt tot je beveiligde kluis. Het is belangrijk dat je het hoofdwachtwoord niet vergeet, want er is geen manier om het te herstellen." + }, + "masterPassHintDesc": { + "message": "Een hoofdwachtwoordhint kan je helpen je wachtwoord te herinneren als je het vergeten bent." + }, + "reTypeMasterPass": { + "message": "Hoofdwachtwoord opnieuw invoeren" + }, + "masterPassHint": { + "message": "Hoofdwachtwoordhint (optioneel)" + }, + "settings": { + "message": "Instellingen" + }, + "passwordHint": { + "message": "Wachtwoordhint" + }, + "enterEmailToGetHint": { + "message": "Voer het e-mailadres van je account in om je hoofdwachtwoordhint te ontvangen." + }, + "getMasterPasswordHint": { + "message": "Hoofdwachtwoordhint opvragen" + }, + "emailRequired": { + "message": "E-mailadres vereist." + }, + "invalidEmail": { + "message": "Ongeldig e-mailadres." + }, + "masterPassRequired": { + "message": "Hoofdwachtwoord vereist." + }, + "masterPassLength": { + "message": "Het hoofdwachtwoord moet minimaal 8 tekens lang zijn." + }, + "masterPassDoesntMatch": { + "message": "De hoofdwachtwoorden komen niet overeen." + }, + "newAccountCreated": { + "message": "Je nieuwe account is aangemaakt! Je kunt nu inloggen." + }, + "masterPassSent": { + "message": "We hebben je een e-mail gestuurd met je hoofdwachtwoordhint." + }, + "unexpectedError": { + "message": "Er is een onverwachte fout opgetreden." + }, + "itemInformation": { + "message": "Item" + }, + "noItemsInList": { + "message": "Er zijn geen items om weer te geven." + }, + "sendVerificationCode": { + "message": "Stuur een verificatiecode naar je e-mail" + }, + "sendCode": { + "message": "Code versturen" + }, + "codeSent": { + "message": "Code verstuurd" + }, + "verificationCode": { + "message": "Verificatiecode" + }, + "confirmIdentity": { + "message": "Bevestig je identiteit om door te gaan." + }, + "verificationCodeRequired": { + "message": "Verificatiecode vereist." + }, + "invalidVerificationCode": { + "message": "Ongeldige verificatiecode" + }, + "continue": { + "message": "Doorgaan" + }, + "enterVerificationCodeApp": { + "message": "Voer de 6-cijferige verificatiecode uit je authenticatie-app in." + }, + "enterVerificationCodeEmail": { + "message": "Voer de 6-cijferige verificatiecode in die via e-mail is verstuurd naar $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mail met verificatiecode is verzonden naar $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Mijn gegevens onthouden" + }, + "sendVerificationCodeEmailAgain": { + "message": "E-mail met verificatiecode opnieuw versturen" + }, + "useAnotherTwoStepMethod": { + "message": "Gebruik een andere methode voor tweestapsaanmelding" + }, + "insertYubiKey": { + "message": "Plaats je YubiKey in de USB-poort van je computer en druk op de knop." + }, + "insertU2f": { + "message": "Plaats je beveilingssleutel in de USB-poort van je computer. Als het een knop heeft, druk deze dan in." + }, + "recoveryCodeDesc": { + "message": "Ben je de toegang tot al je tweestapsaanbieders verloren? Gebruik dan je herstelcode om alle tweestapsaanbieders op je account uit te schakelen." + }, + "recoveryCodeTitle": { + "message": "Herstelcode" + }, + "authenticatorAppTitle": { + "message": "Authenticatie-app" + }, + "authenticatorAppDesc": { + "message": "Gebruik een authenticatie-app (zoals Authy of Google Authenticator) om tijdgebaseerde authenticatiecodes te genereren.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP-beveiligingssleutel" + }, + "yubiKeyDesc": { + "message": "Gebruik een YubiKey om toegang te krijgen tot je account. Werkt met YubiKey 4, 4 Nano, 4C en Neo-apparaten." + }, + "duoDesc": { + "message": "Verificatie met Duo Security middels de Duo Mobile-app, sms, spraakoproep of een U2F-beveiligingssleutel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verificatie met Duo Security middels de Duo Mobile-app, sms, spraakoproep of een U2F-beveiligingssleutel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Gebruik een WebAuthn-beveilingssleutel om toegang te krijgen tot je account." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Je ontvangt verificatiecodes via e-mail." + }, + "loginUnavailable": { + "message": "Login niet beschikbaar" + }, + "noTwoStepProviders": { + "message": "Dit account heeft tweestapsaanmelding ingeschakeld, maar dit apparaat ondersteunt geen van de geconfigureerde aanbieders." + }, + "noTwoStepProviders2": { + "message": "Voeg aanvullende aanbieders toe die beter worden ondersteund op verschillende apparaten (zoals een authenticator app)." + }, + "twoStepOptions": { + "message": "Opties voor tweestapsaanmelding" + }, + "selfHostedEnvironment": { + "message": "Zelfgehoste omgeving" + }, + "selfHostedEnvironmentFooter": { + "message": "Geef de basis-URL van jouw zelfgehoste Bitwarden-installatie." + }, + "customEnvironment": { + "message": "Aangepaste omgeving" + }, + "customEnvironmentFooter": { + "message": "Voor gevorderde gebruikers. Je kunt de basis-URL van elke dienst afzonderlijk instellen." + }, + "baseUrl": { + "message": "Server-URL" + }, + "apiUrl": { + "message": "API server-URL" + }, + "webVaultUrl": { + "message": "Webkluis server-URL" + }, + "identityUrl": { + "message": "Identiteitsserver-URL" + }, + "notificationsUrl": { + "message": "Meldingenserver-URL" + }, + "iconsUrl": { + "message": "Pictogrammenserver-URL" + }, + "environmentSaved": { + "message": "De omgevings-URL's zijn opgeslagen." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nee" + }, + "overwritePassword": { + "message": "Wachtwoord overschrijven" + }, + "learnMore": { + "message": "Meer informatie" + }, + "featureUnavailable": { + "message": "Functionaliteit niet beschikbaar" + }, + "loggedOut": { + "message": "Uitgelogd" + }, + "loginExpired": { + "message": "Je inlogsessie is verlopen." + }, + "logOutConfirmation": { + "message": "Weet je zeker dat je wilt uitloggen?" + }, + "logOut": { + "message": "Uitloggen" + }, + "addNewLogin": { + "message": "Nieuwe login" + }, + "addNewItem": { + "message": "Nieuw item" + }, + "addNewFolder": { + "message": "Nieuwe map" + }, + "view": { + "message": "Beeld" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Laden..." + }, + "lockVault": { + "message": "Kluis vergrendelen" + }, + "passwordGenerator": { + "message": "Wachtwoordgenerator" + }, + "contactUs": { + "message": "Contact opnemen" + }, + "getHelp": { + "message": "Hulp vragen" + }, + "fileBugReport": { + "message": "Rapporteer een fout (bug)" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Volg ons" + }, + "syncVault": { + "message": "Kluis synchroniseren" + }, + "changeMasterPass": { + "message": "Hoofdwachtwoord wijzigen" + }, + "changeMasterPasswordConfirmation": { + "message": "Je kunt je hoofdwachtwoord wijzigen in de kluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "fingerprintPhrase": { + "message": "Vingerafdrukzin", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Vingerafdrukzin van je account", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Ga naar de webkluis" + }, + "getMobileApp": { + "message": "Download de mobiele app" + }, + "getBrowserExtension": { + "message": "Download de browserextensie" + }, + "syncingComplete": { + "message": "Synchronisatie voltooid" + }, + "syncingFailed": { + "message": "Synchronisatie mislukt" + }, + "yourVaultIsLocked": { + "message": "Je kluis is vergrendeld. Voer je hoofdwachtwoord in om door te gaan." + }, + "unlock": { + "message": "Ontgrendelen" + }, + "loggedInAsOn": { + "message": "Aangemeld als $EMAIL$ op $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ongeldig hoofdwachtwoord" + }, + "twoStepLoginConfirmation": { + "message": "Tweestapsaanmelding beschermt je account door je inlogpoging te bevestigen met een ander apparaat zoals een beveiligingssleutel, authenticatie-app, SMS, spraakoproep of e-mail. Je kunt Tweestapsaanmelding inschakelen in de webkluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "twoStepLogin": { + "message": "Tweestapsaanmelding" + }, + "vaultTimeout": { + "message": "Time-out van de kluis" + }, + "vaultTimeoutDesc": { + "message": "Stel de time-out van de kluis en de bijbehorende actie in." + }, + "immediately": { + "message": "Onmiddellijk" + }, + "tenSeconds": { + "message": "10 seconden" + }, + "twentySeconds": { + "message": "20 seconden" + }, + "thirtySeconds": { + "message": "30 seconden" + }, + "oneMinute": { + "message": "1 minuut" + }, + "twoMinutes": { + "message": "2 minuten" + }, + "fiveMinutes": { + "message": "5 minuten" + }, + "fifteenMinutes": { + "message": "15 minuten" + }, + "thirtyMinutes": { + "message": "30 minuten" + }, + "oneHour": { + "message": "1 uur" + }, + "fourHours": { + "message": "4 uur" + }, + "onIdle": { + "message": "Bij systeeminactiviteit" + }, + "onSleep": { + "message": "Bij slaapmodus" + }, + "onLocked": { + "message": "Bij systeemvergrendeling" + }, + "onRestart": { + "message": "Bij herstart" + }, + "never": { + "message": "Nooit" + }, + "security": { + "message": "Beveiliging" + }, + "clearClipboard": { + "message": "Klembord wissen", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Gekopieerde waarden automatisch van het klembord wissen.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Websitepictogrammen uitschakelen" + }, + "disableFaviconDesc": { + "message": "Websitepictogrammen geven een herkenbare afbeelding naast elk item in je kluis." + }, + "enableMinToTray": { + "message": "Minimaliseren naar systeemvak" + }, + "enableMinToTrayDesc": { + "message": "Wanneer het venster wordt geminimaliseerd, een pictogram in het systeemvak weergeven." + }, + "enableMinToMenuBar": { + "message": "Minimaliseren naar menubalk" + }, + "enableMinToMenuBarDesc": { + "message": "Bij het minimaliseren van het venster, een pictogram in de menubalk weergeven." + }, + "enableCloseToTray": { + "message": "Sluiten naar systeemvak" + }, + "enableCloseToTrayDesc": { + "message": "Bij het sluiten van het venster, een pictogram in het systeemvak weergeven." + }, + "enableCloseToMenuBar": { + "message": "Menubalk sluiten" + }, + "enableCloseToMenuBarDesc": { + "message": "Bij het sluiten van het venster, een pictogram in de menubalk weergeven." + }, + "enableTray": { + "message": "Systeemvakpictogram inschakelen" + }, + "enableTrayDesc": { + "message": "Altijd een pictogram in het systeemvak weergeven." + }, + "startToTray": { + "message": "Opstarten als systeemvakpictogram" + }, + "startToTrayDesc": { + "message": "Wanneer de applicatie voor het eerst wordt gestart, alleen een pictogram in het systeemvak weergeven." + }, + "startToMenuBar": { + "message": "Menubalk starten" + }, + "startToMenuBarDesc": { + "message": "Wanneer de applicatie voor het eerst is gestart, alleen een pictogram weergeven in de menubalk." + }, + "openAtLogin": { + "message": "Automatisch starten bij inloggen" + }, + "openAtLoginDesc": { + "message": "Bitwarden-desktopapplicatie automatisch starten bij inloggen." + }, + "alwaysShowDock": { + "message": "Altijd laten zien in het dock" + }, + "alwaysShowDockDesc": { + "message": "Toon het Bitwarden-pictogram in het dock, zelfs wanneer geminimaliseerd in de menubalk." + }, + "confirmTrayTitle": { + "message": "Uitschakelen van het systeemvakpictogram bevestigen" + }, + "confirmTrayDesc": { + "message": "Het uitschakelen van deze instelling zal ook alle andere instellingen van het systeemvakpictogram uitschakelen." + }, + "language": { + "message": "Taal" + }, + "languageDesc": { + "message": "De taal van de applicatie wijzigen. Werkt pas na herstarten." + }, + "theme": { + "message": "Thema" + }, + "themeDesc": { + "message": "Het kleurenthema van de applicatie wijzigen." + }, + "dark": { + "message": "Donker", + "description": "Dark color" + }, + "light": { + "message": "Licht", + "description": "Light color" + }, + "copy": { + "message": "Kopiëren", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Controleren op updates" + }, + "version": { + "message": "Versie $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Bitwarden opnieuw starten om bij te werken" + }, + "restartToUpdateDesc": { + "message": "Versie $VERSION_NUM$ is klaar voor installatie. Je moet Bitwarden opnieuw opstarten om de installatie af te ronden. Wil je nu opnieuw opstarten en bijwerken?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update beschikbaar" + }, + "updateAvailableDesc": { + "message": "Er is een update gevonden. Wil je deze nu downloaden?" + }, + "restart": { + "message": "Applicatie herstarten" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "Er zijn momenteel geen updates beschikbaar. Je gebruikt de laatste versie." + }, + "updateError": { + "message": "Fout bij het bijwerken" + }, + "unknown": { + "message": "Onbekend" + }, + "copyUsername": { + "message": "Gebruikersnaam kopiëren" + }, + "copyNumber": { + "message": "Nummer kopiëren", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Beveiligingscode kopiëren", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium-abonnement" + }, + "premiumManage": { + "message": "Abonnement beheren" + }, + "premiumManageAlert": { + "message": "Je kunt je abonnement aanpassen in de webkluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "premiumRefresh": { + "message": "Abonnement vernieuwen" + }, + "premiumNotCurrentMember": { + "message": "Je bent momenteel geen Premium-lid." + }, + "premiumSignUpAndGet": { + "message": "Meld je aan voor een Premium-abonnement en krijg:" + }, + "premiumSignUpStorage": { + "message": "1 GB versleutelde opslag voor bijlagen." + }, + "premiumSignUpTwoStep": { + "message": "Extra opties voor tweestapsaanmelding zoals YubiKey, FIDO U2F en Duo." + }, + "premiumSignUpReports": { + "message": "Rapportage op wachtwoordhygiëne, gezondheid van je account en gegevensinbreuk om je kluis veilig te houden." + }, + "premiumSignUpTotp": { + "message": "TOTP-verificatiecodegenerator (2FA) voor logins in je kluis." + }, + "premiumSignUpSupport": { + "message": "Klantondersteuning met hoge prioriteit." + }, + "premiumSignUpFuture": { + "message": "Alle toekomstige Premium-functionaliteiten. Binnenkort meer!" + }, + "premiumPurchase": { + "message": "Premium aanschaffen" + }, + "premiumPurchaseAlert": { + "message": "Je kunt een Premium-abonnement aanschaffen in de webkluis op bitwarden.com. Wil je de website nu bezoeken?" + }, + "premiumCurrentMember": { + "message": "Je bent Premium-lid!" + }, + "premiumCurrentMemberThanks": { + "message": "Bedankt voor het ondersteunen van Bitwarden." + }, + "premiumPrice": { + "message": "Dit alles voor slechts $PRICE$ per jaar!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Bijwerken voltooid" + }, + "passwordHistory": { + "message": "Geschiedenis" + }, + "clear": { + "message": "Wissen", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Er zijn geen wachtwoorden om weer te geven." + }, + "undo": { + "message": "Ongedaan maken" + }, + "redo": { + "message": "Opnieuw" + }, + "cut": { + "message": "Knippen", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Plakken", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Alles selecteren" + }, + "zoomIn": { + "message": "Inzoomen" + }, + "zoomOut": { + "message": "Uitzoomen" + }, + "resetZoom": { + "message": "Zoom herstellen" + }, + "toggleFullScreen": { + "message": "Volledig scherm aan/uit" + }, + "reload": { + "message": "Opnieuw laden" + }, + "toggleDevTools": { + "message": "Ontwikkelaarsgereedschap in-/uitschakelen" + }, + "minimize": { + "message": "Minimaliseren", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoomen" + }, + "bringAllToFront": { + "message": "Alles naar voorgrond brengen", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Over Bitwarden" + }, + "services": { + "message": "Diensten" + }, + "hideBitwarden": { + "message": "Bitwarden verbergen" + }, + "hideOthers": { + "message": "Overige verbergen" + }, + "showAll": { + "message": "Alles weergeven" + }, + "quitBitwarden": { + "message": "Bitwarden afsluiten" + }, + "valueCopied": { + "message": "$VALUE$ gekopieerd", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Venster" + }, + "checkPassword": { + "message": "Controleer of wachtwoord is gelekt." + }, + "passwordExposed": { + "message": "Dit wachtwoord is $VALUE$ keer gelekt. Je zou het moeten veranderen.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Dit wachtwoord is niet gevonden in de bekende gegevenslekken. Het kan veilig gebruikt worden." + }, + "baseDomain": { + "message": "Basisdomein", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domeinnaam", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Hostnaam", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Begint met" + }, + "regEx": { + "message": "Reguliere expressie", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Overeenkomstdetectie", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standaard overeenkomstdetectie", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Opties schakelen" + }, + "organization": { + "message": "Organisatie", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Standaard" + }, + "exit": { + "message": "Afsluiten" + }, + "showHide": { + "message": "Weergeven/verbergen", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Verbergen naar het systeemvak" + }, + "alwaysOnTop": { + "message": "Altijd op de voorgrond", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Bijgewerkt", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Wachtwoord bijgewerkt", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Kluis exporteren" + }, + "fileFormat": { + "message": "Bestandsindeling" + }, + "warning": { + "message": "WAARSCHUWING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Kluisexport bevestigen" + }, + "exportWarningDesc": { + "message": "Deze export bevat jouw kluisgegevens in een niet-versleutelde opmaak. Je moet het geëxporteerde bestand niet opslaan of verzenden over onbeveiligde kanalen (zoals e-mail). Verwijder het exportbestand direct na gebruik." + }, + "encExportKeyWarningDesc": { + "message": "Deze export versleutelt je gegevens met de encryptiesleutel van je account. Als je je encryptiesleutel verandert moet je opnieuw exporteren, omdat je deze export dan niet meer kunt ontcijferen." + }, + "encExportAccountWarningDesc": { + "message": "Encryptiesleutels zijn uniek voor elk Bitwarden-gebruikersaccount, je kun kunt een versleutelde niet in een ander account importeren." + }, + "noOrganizationsList": { + "message": "Je behoort niet tot een organisatie. Via organisaties deel je je items veilig met andere gebruikers." + }, + "noCollectionsInList": { + "message": "Er zijn geen verzamelingen om weer te geven." + }, + "ownership": { + "message": "Eigendom" + }, + "whoOwnsThisItem": { + "message": "Wie is eigenaar van dit item?" + }, + "strong": { + "message": "Sterk", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Goed", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Zwak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Zwak hoofdwachtwoord" + }, + "weakMasterPasswordDesc": { + "message": "Je hebt een zwak hoofdwachtwoord gekozen. Gebruik een sterk hoofdwachtwoord (of wachtwoordzin) om jouw Bitwarden-account goed te beschermen. Weet je zeker dat je dit hoofdwachtwoord wilt gebruiken?" + }, + "pin": { + "message": "PIN-code", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Ontgrendelen met PIN" + }, + "setYourPinCode": { + "message": "Stel je PIN-code in voor het ontgrendelen van Bitwarden. Je PIN-code wordt opnieuw ingesteld als je je ooit volledig afmeldt bij de applicatie." + }, + "pinRequired": { + "message": "PIN-code vereist." + }, + "invalidPin": { + "message": "Ongeldige PIN-code." + }, + "unlockWithWindowsHello": { + "message": "Ontgrendelen met Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verifiëren voor Bitwarden." + }, + "unlockWithTouchId": { + "message": "Ontgrendelen met Touch ID" + }, + "touchIdConsentMessage": { + "message": "ontgrendel je kluis" + }, + "noAutoPromptWindowsHello": { + "message": "Bij het opstarten niet om Windows Hello vragen." + }, + "noAutoPromptTouchId": { + "message": "Bij het opstarten niet om Touch ID vragen." + }, + "lockWithMasterPassOnRestart": { + "message": "Bij herstart vergrendelen met hoofdwachtwoord" + }, + "preferences": { + "message": "Voorkeuren" + }, + "enableMenuBar": { + "message": "Pictogram in de taakbalk" + }, + "enableMenuBarDesc": { + "message": "Altijd een pictogram in de taakbalk weergeven." + }, + "hideToMenuBar": { + "message": "Verbergen naar de taakbalk" + }, + "selectOneCollection": { + "message": "Je moet tenminste één verzameling selecteren." + }, + "premiumUpdated": { + "message": "Je bent opgewaardeerd naar Premium." + }, + "restore": { + "message": "Terugzetten" + }, + "premiumManageAlertAppStore": { + "message": "Je kunt je abonnement beheren vanuit de App Store. Wil je de App Store nu bezoeken?" + }, + "legal": { + "message": "Juridisch", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Algemene gebruiksvoorwaarden" + }, + "privacyPolicy": { + "message": "Privacybeleid" + }, + "unsavedChangesConfirmation": { + "message": "Weet je zeker dat je wilt afsluiten? Als je nu afsluiten, gaan je laatste wijzigingen verloren." + }, + "unsavedChangesTitle": { + "message": "Niet-opgeslagen wijzigingen" + }, + "clone": { + "message": "Dupliceren" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Een of meer organisatiebeleidseisen heeft invloed op de instellingen van je generator." + }, + "vaultTimeoutAction": { + "message": "Actie bij time-out" + }, + "vaultTimeoutActionLockDesc": { + "message": "Om toegang te krijgen tot een vergrendelde kluis moet het hoofdwachtwoord opnieuw worden ingevoerd." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Om toegang te krijgen tot een uitgelogde kluis te krijgen moet je opnieuw inloggen." + }, + "lock": { + "message": "Vergrendelen", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Prullenbak", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Prullenbak doorzoeken" + }, + "permanentlyDeleteItem": { + "message": "Item definitief verwijderen" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Weet je zeker dat je dit item definitief wilt verwijderen?" + }, + "permanentlyDeletedItem": { + "message": "Definitief verwijderd item" + }, + "restoreItem": { + "message": "Item herstellen" + }, + "restoreItemConfirmation": { + "message": "Weet je zeker dat je dit item wilt herstellen?" + }, + "restoredItem": { + "message": "Hersteld item" + }, + "permanentlyDelete": { + "message": "Definitief verwijderen" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Uitloggen ontneemt je de toegang tot je kluis en vereist online authenticatie na een periode van time-out. Weet je zeker dat je deze instelling wilt gebruiken?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bevestiging actie bij time-out" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Hoofdwachtwoord instellen" + }, + "ssoCompleteRegistration": { + "message": "Voor het inloggen met SSO moet je een hoofdwachtwoord instellen voor toegang tot en bescherming van je kluis." + }, + "newMasterPass": { + "message": "Nieuw hoofdwachtwoord" + }, + "confirmNewMasterPass": { + "message": "Nieuw hoofdwachtwoord bevestigen" + }, + "masterPasswordPolicyInEffect": { + "message": "Een of meer organisatiebeleidseisen stelt de volgende eisen aan je hoofdwachtwoord:" + }, + "policyInEffectMinComplexity": { + "message": "Minimale complexiteitsscore van $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimale lengte van $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Bevat een of meer hoofdletters" + }, + "policyInEffectLowercase": { + "message": "Bevat een of meer kleine letters" + }, + "policyInEffectNumbers": { + "message": "Bevat een of meer cijfers" + }, + "policyInEffectSpecial": { + "message": "Bevat een of meer van de volgende speciale tekens $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Je nieuwe hoofdwachtwoord voldoet niet aan de beleidseisen." + }, + "acceptPolicies": { + "message": "Door dit vakje aan te vinken, ga je akkoord met het volgende:" + }, + "acceptPoliciesError": { + "message": "Algemene voorwaarden en privacybeleid zijn nog niet erkend." + }, + "enableBrowserIntegration": { + "message": "Browserintegratie inschakelen" + }, + "enableBrowserIntegrationDesc": { + "message": "Browserintegratie wordt gebruikt voor biometrie in de browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browserintegratie niet ondersteund" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Helaas wordt browserintegratie momenteel alleen ondersteund in de Mac App Store-versie." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browserintegratie niet ondersteund" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Helaas wordt browserintegratie momenteel niet ondersteund in de Windows Store-versie." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Vereis verificatie voor browserintegratie" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Schakel een extra beveiligingsniveau in door een vingerafdrukzin te vereisen bij het verbinden van je desktop en browser. Wanneer ingeschakeld moet je iedere verbinding verifiëren." + }, + "approve": { + "message": "Goedkeuren" + }, + "verifyBrowserTitle": { + "message": "Browserverbinding verifiëren" + }, + "verifyBrowserDesc": { + "message": "Verzeker je ervan dat de getoonde vingerafdruk hetzelfde is als de vingerafdruk in de browserextensie." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrie niet ingeschakeld" + }, + "biometricsNotEnabledDesc": { + "message": "Voor browserbiometrie moet je eerst desktopbiometrie inschakelen in de instellingen." + }, + "personalOwnershipSubmitError": { + "message": "Wegens bedrijfsbeleid mag je geen wachtwoorden opslaan in je persoonlijke kluis. Verander het eigenaarschap naar een organisatie en kies uit een van de beschikbare collecties." + }, + "hintEqualsPassword": { + "message": "Je wachtwoordhint moet anders zijn dan je wachtwoord." + }, + "personalOwnershipPolicyInEffect": { + "message": "Een organisatiebeleid heeft invloed op je eigendomsopties." + }, + "allSends": { + "message": "Alle Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Bestand" + }, + "sendTypeText": { + "message": "Tekst" + }, + "searchSends": { + "message": "Sends zoeken", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send bewerken", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mijn kluis" + }, + "text": { + "message": "Tekst" + }, + "deletionDate": { + "message": "Verwijderingsdatum" + }, + "deletionDateDesc": { + "message": "Deze Send wordt op de aangegeven datum en tijd definitief verwijderd.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Vervaldatum" + }, + "expirationDateDesc": { + "message": "Als dit is ingesteld verloopt deze Send op een specifieke datum en tijd.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum toegangsaantal" + }, + "maxAccessCountDesc": { + "message": "Als dit is ingesteld kunnen gebruikers deze Send niet meer benaderen zodra het maximale aantal toegang is bereikt.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Huidige toegangsaantal" + }, + "disableSend": { + "message": "Schakel deze Send uit zodat niemand hem kan benaderen.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Vereis optioneel een wachtwoord voor gebruikers om toegang te krijgen tot deze Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Privénotities over deze Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send-link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send-link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Verberg de tekst standaard bij het gebruiken van de Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send aangemaakt", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send bewerkt", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send verwijderd", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nieuw wachtwoord" + }, + "whatTypeOfSend": { + "message": "Wat voor soort Send is dit?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Send aanmaken", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "De tekst die je wilt versturen." + }, + "sendFileDesc": { + "message": "Het bestand dat je wilt versturen." + }, + "days": { + "message": "$DAYS$ dagen", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dag" + }, + "custom": { + "message": "Aangepast" + }, + "deleteSendConfirmation": { + "message": "Weet je zeker dat je deze Send wilt verwijderen?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Send-link naar klembord kopiëren", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kopieer de link om deze Share te delen bij het opslaan naar mijn klembord." + }, + "sendDisabled": { + "message": "Send uitgeschakeld", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Als gevolg van een ondernemingsbeleid kun je alleen een bestaande Send verwijderen.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Link kopiëren" + }, + "disabled": { + "message": "Uitgeschakeld" + }, + "maxAccessCountReached": { + "message": "Maximum aantal keren benaderd" + }, + "expired": { + "message": "Verlopen" + }, + "pendingDeletion": { + "message": "Wordt verwijderd" + }, + "webAuthnAuthenticate": { + "message": "Authenticeer WebAuthn" + }, + "hideEmail": { + "message": "Verberg mijn e-mailadres voor ontvangers." + }, + "sendOptionsPolicyInEffect": { + "message": "Een of meer organisatiebeleidseisen heeft invloed op de mogelijkheden van je Send." + }, + "emailVerificationRequired": { + "message": "E-mailverificatie vereist" + }, + "emailVerificationRequiredDesc": { + "message": "Je moet je e-mailadres verifiëren om deze functionaliteit te gebruiken." + }, + "passwordPrompt": { + "message": "Hoofdwachtwoord opnieuw vragen" + }, + "passwordConfirmation": { + "message": "Hoofdwachtwoord bevestigen" + }, + "passwordConfirmationDesc": { + "message": "Deze actie is beveiligd. Voer je hoofdwachtwoord opnieuw in om je identiteit vast te stellen en door te gaan." + }, + "updatedMasterPassword": { + "message": "Hoofdwachtwoord bijgewerkt" + }, + "updateMasterPassword": { + "message": "Hoofdwachtwoord bijgewerken" + }, + "updateMasterPasswordWarning": { + "message": "Je hoofdwachtwoord is onlangs veranderd door een beheerder in jouw organisatie. Om toegang te krijgen tot de kluis, moet je deze nu bijwerken. Doorgaan zal je huidige sessie uitloggen, waarna je opnieuw moet inloggen. Actieve sessies op andere apparaten blijven mogelijk nog een uur actief." + }, + "hours": { + "message": "Uren" + }, + "minutes": { + "message": "Minuten" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Het beleid van je organisatie heeft invloed op de time-out van je kluis. De maximaal toegestane Kluis Time-out is $HOURS$ uur en $MINUTES$ minuten", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Je kluis time-out is hoger dan het maximum van jouw organisatie." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatische inschrijving" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Deze organisatie heeft een ondernemingsbeleid dat je automatisch inschrijft bij het resetten van je wachtwoord. Inschrijving stelt organisatiebeheerders in staat om je hoofdwachtwoord te wijzigen." + }, + "vaultExportDisabled": { + "message": "Kluis exporteren uitgeschakeld" + }, + "personalVaultExportPolicyInEffect": { + "message": "Organisatiebeleid voorkomt dat je je persoonlijke kluis exporteert." + }, + "addAccount": { + "message": "Account toevoegen" + }, + "removeMasterPassword": { + "message": "Hoofdwachtwoord verwijderen" + }, + "removedMasterPassword": { + "message": "Hoofdwachtwoord verwijderd." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ gebruikt SSO met een zelf gehoste sleutelserver. Leden van deze organisatie kunnen inloggen zonder hoofdwachtwoord.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Organisatie verlaten" + }, + "leaveOrganizationConfirmation": { + "message": "Weet je zeker dat je deze organisatie wilt verlaten?" + }, + "leftOrganization": { + "message": "Je hebt de organisatie verlaten." + }, + "ssoKeyConnectorUnavailable": { + "message": "Kan de sleutelconnector niet bereiken, probeer het later opnieuw." + }, + "lockAllVaults": { + "message": "Alle kluizen vergrendelen" + }, + "accountLimitReached": { + "message": "Er mogen niet meer dan 5 accounts tegelijkertijd ingelogd zijn." + }, + "accountPreferences": { + "message": "Voorkeuren" + }, + "appPreferences": { + "message": "App-instellingen (alle accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Limiet van het aantal accounts bereikt. Log een account uit voor het toevoegen van een andere." + }, + "settingsTitle": { + "message": "App-instellingen voor $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Account wisselen" + }, + "options": { + "message": "Opties" + }, + "sessionTimeout": { + "message": "Je sessie is verlopen. Ga terug en probeer opnieuw in te loggen." + }, + "exportingPersonalVaultTitle": { + "message": "Persoonlijke kluis exporteren" + }, + "exportingPersonalVaultDescription": { + "message": "Exporteert alleen de persoonlijke kluis-items gerelateerd aan $EMAIL$. Geen kluis-items van de organisatie.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "Wat wil je genereren?" + }, + "passwordType": { + "message": "Type wachtwoord" + }, + "regenerateUsername": { + "message": "Gebruikersnaam opnieuw genereren" + }, + "generateUsername": { + "message": "Gebruikersnamen genereren" + }, + "usernameType": { + "message": "Type gebruikersnaam" + }, + "plusAddressedEmail": { + "message": "E-mailadres-met-plus" + }, + "plusAddressedEmailDesc": { + "message": "Gebruik de subadressen van je e-mailprovider." + }, + "catchallEmail": { + "message": "Catch-all e-mail" + }, + "catchallEmailDesc": { + "message": "Gebruik de catch-all inbox van je domein." + }, + "random": { + "message": "Willekeurig" + }, + "randomWord": { + "message": "Willekeurig woord" + }, + "websiteName": { + "message": "Websitenaam" + }, + "service": { + "message": "Dienst" + } +} diff --git a/apps/desktop/src/locales/nn/messages.json b/apps/desktop/src/locales/nn/messages.json new file mode 100644 index 0000000000..1b909d5de4 --- /dev/null +++ b/apps/desktop/src/locales/nn/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filters" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "Favorites" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "Login" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identity" + }, + "typeSecureNote": { + "message": "Secure Note" + }, + "folders": { + "message": "Folders" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "Name" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "Username" + }, + "password": { + "message": "Password" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "Email Address" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "Copy Value", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "Number" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "Expiration" + }, + "securityCode": { + "message": "Security Code" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "Company" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Phone" + }, + "address": { + "message": "Address" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "Error" + }, + "january": { + "message": "January" + }, + "february": { + "message": "February" + }, + "march": { + "message": "March" + }, + "april": { + "message": "April" + }, + "may": { + "message": "May" + }, + "june": { + "message": "June" + }, + "july": { + "message": "July" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "October" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "Country" + }, + "save": { + "message": "Save" + }, + "cancel": { + "message": "Cancel" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "Favorite" + }, + "edit": { + "message": "Edit" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remove" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "No Folder", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Add Folder" + }, + "editFolder": { + "message": "Edit Folder" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "Copy Password" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "Close" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "Search Folder" + }, + "searchFavorites": { + "message": "Search Favorites" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Settings" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Invalid email address." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Continue" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Recovery Code" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Yes" + }, + "no": { + "message": "No" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "Add New Folder" + }, + "view": { + "message": "View" + }, + "account": { + "message": "Account" + }, + "loading": { + "message": "Loading..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 minute" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 minutes" + }, + "fifteenMinutes": { + "message": "15 minutes" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "Copy", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check For Updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "Later" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/pl/messages.json b/apps/desktop/src/locales/pl/messages.json new file mode 100644 index 0000000000..a981ce7652 --- /dev/null +++ b/apps/desktop/src/locales/pl/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtry" + }, + "allItems": { + "message": "Wszystkie elementy" + }, + "favorites": { + "message": "Ulubione" + }, + "types": { + "message": "Rodzaje" + }, + "typeLogin": { + "message": "Dane logowania" + }, + "typeCard": { + "message": "Karta" + }, + "typeIdentity": { + "message": "Tożsamość" + }, + "typeSecureNote": { + "message": "Bezpieczna notatka" + }, + "folders": { + "message": "Foldery" + }, + "collections": { + "message": "Kolekcje" + }, + "searchVault": { + "message": "Szukaj w sejfie" + }, + "addItem": { + "message": "Dodaj element" + }, + "shared": { + "message": "Udostępnione" + }, + "share": { + "message": "Udostępnij" + }, + "moveToOrganization": { + "message": "Przenieś do organizacji" + }, + "movedItemToOrg": { + "message": "Element $ITEMNAME$ został przeniesiony do organizacji $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Wybierz organizację, do której chcesz przenieść ten element. Ta czynność spowoduje utratę własności elementu i przenosi te uprawnienia do organizacji." + }, + "attachments": { + "message": "Załączniki" + }, + "viewItem": { + "message": "Zobacz element" + }, + "name": { + "message": "Nazwa" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nowy URI" + }, + "username": { + "message": "Nazwa użytkownika" + }, + "password": { + "message": "Hasło" + }, + "passphrase": { + "message": "Hasło wyrazowe" + }, + "editItem": { + "message": "Edytuj element" + }, + "emailAddress": { + "message": "Adres e-mail" + }, + "verificationCodeTotp": { + "message": "Kod weryfikacyjny (TOTP)" + }, + "website": { + "message": "Strona" + }, + "notes": { + "message": "Notatki" + }, + "customFields": { + "message": "Pola niestandardowe" + }, + "launch": { + "message": "Uruchom" + }, + "copyValue": { + "message": "Kopiuj wartość", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimalizuj podczas kopiowania do schowka" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimalizuj podczas kopiowania danych elementu do schowka." + }, + "toggleVisibility": { + "message": "Pokaż / Ukryj" + }, + "toggleCollapse": { + "message": "Zwiń/rozwiń", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Właściciel karty" + }, + "number": { + "message": "Numer" + }, + "brand": { + "message": "Wydawca" + }, + "expiration": { + "message": "Data wygaśnięcia" + }, + "securityCode": { + "message": "Kod zabezpieczający" + }, + "identityName": { + "message": "Nazwa profilu" + }, + "company": { + "message": "Firma" + }, + "ssn": { + "message": "Numer PESEL" + }, + "passportNumber": { + "message": "Numer paszportu" + }, + "licenseNumber": { + "message": "Numer prawa jazdy" + }, + "email": { + "message": "Adres e-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adres" + }, + "premiumRequired": { + "message": "Konto Premium jest wymagane" + }, + "premiumRequiredDesc": { + "message": "Konto Premium jest wymagane, aby skorzystać z tej funkcji." + }, + "errorOccurred": { + "message": "Wystąpił błąd." + }, + "error": { + "message": "Błąd" + }, + "january": { + "message": "Styczeń" + }, + "february": { + "message": "Luty" + }, + "march": { + "message": "Marzec" + }, + "april": { + "message": "Kwiecień" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Czerwiec" + }, + "july": { + "message": "Lipiec" + }, + "august": { + "message": "Sierpień" + }, + "september": { + "message": "Wrzesień" + }, + "october": { + "message": "Październik" + }, + "november": { + "message": "Listopad" + }, + "december": { + "message": "Grudzień" + }, + "ex": { + "message": "np.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Tytuł" + }, + "mr": { + "message": "Pan" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Pani" + }, + "dr": { + "message": "Doktor" + }, + "expirationMonth": { + "message": "Miesiąc wygaśnięcia" + }, + "expirationYear": { + "message": "Rok wygaśnięcia" + }, + "select": { + "message": "Wybierz" + }, + "other": { + "message": "Inne" + }, + "generatePassword": { + "message": "Generuj hasło" + }, + "type": { + "message": "Rodzaj" + }, + "firstName": { + "message": "Imię" + }, + "middleName": { + "message": "Drugie imię" + }, + "lastName": { + "message": "Nazwisko" + }, + "fullName": { + "message": "Imię i nazwisko" + }, + "address1": { + "message": "Adres 1" + }, + "address2": { + "message": "Adres 2" + }, + "address3": { + "message": "Adres 3" + }, + "cityTown": { + "message": "Miasto" + }, + "stateProvince": { + "message": "Województwo" + }, + "zipPostalCode": { + "message": "Kod pocztowy" + }, + "country": { + "message": "Kraj" + }, + "save": { + "message": "Zapisz" + }, + "cancel": { + "message": "Anuluj" + }, + "delete": { + "message": "Usuń" + }, + "favorite": { + "message": "Ulubione" + }, + "edit": { + "message": "Edytuj" + }, + "authenticatorKeyTotp": { + "message": "Klucz Uwierzytelniający (TOTP)" + }, + "folder": { + "message": "Folder" + }, + "newCustomField": { + "message": "Nowe pole niestandardowe" + }, + "value": { + "message": "Wartość" + }, + "dragToSort": { + "message": "Przeciągnij, aby posortować" + }, + "cfTypeText": { + "message": "Tekst" + }, + "cfTypeHidden": { + "message": "Pole maskowane" + }, + "cfTypeBoolean": { + "message": "Wartość logiczna" + }, + "cfTypeLinked": { + "message": "Powiązane pole", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Powiązana wartość", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Usuń" + }, + "nameRequired": { + "message": "Nazwa jest wymagana." + }, + "addedItem": { + "message": "Element został dodany" + }, + "editedItem": { + "message": "Element został zaktualizowany" + }, + "deleteItem": { + "message": "Usuń element" + }, + "deleteFolder": { + "message": "Usuń folder" + }, + "deleteAttachment": { + "message": "Usuń załącznik" + }, + "deleteItemConfirmation": { + "message": "Czy na pewno chcesz to usunąć?" + }, + "deletedItem": { + "message": "Element został przeniesiony do kosza" + }, + "overwritePasswordConfirmation": { + "message": "Czy na pewno chcesz zastąpić obecne hasło?" + }, + "overwriteUsername": { + "message": "Nadpisz nazwę użytkownika" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Nieprzypisane", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Dodaj folder" + }, + "editFolder": { + "message": "Edytuj folder" + }, + "regeneratePassword": { + "message": "Wygeneruj hasło ponownie" + }, + "copyPassword": { + "message": "Kopiuj hasło" + }, + "copyUri": { + "message": "Kopiuj URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopiuj kod weryfikacyjny (TOTP)" + }, + "length": { + "message": "Długość" + }, + "numWords": { + "message": "Liczba słów" + }, + "wordSeparator": { + "message": "Separator słów" + }, + "capitalize": { + "message": "Wielkie litery", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Uwzględnij cyfry" + }, + "close": { + "message": "Zamknij" + }, + "minNumbers": { + "message": "Minimalna liczba cyfr" + }, + "minSpecial": { + "message": "Minimalna liczba znaków specjalnych", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Unikaj niejednoznacznych znaków" + }, + "searchCollection": { + "message": "Szukaj w kolekcji" + }, + "searchFolder": { + "message": "Szukaj w folderze" + }, + "searchFavorites": { + "message": "Szukaj w ulubionych" + }, + "searchType": { + "message": "Szukaj elementu", + "description": "Search item type" + }, + "newAttachment": { + "message": "Dodaj załącznik" + }, + "deletedAttachment": { + "message": "Załącznik został usunięty" + }, + "deleteAttachmentConfirmation": { + "message": "Czy na pewno chcesz usunąć ten załącznik?" + }, + "attachmentSaved": { + "message": "Załącznik został zapisany." + }, + "file": { + "message": "Plik" + }, + "selectFile": { + "message": "Wybierz plik." + }, + "maxFileSize": { + "message": "Maksymalny rozmiar pliku to 500 MB." + }, + "updateKey": { + "message": "Nie możesz używać tej funkcji, dopóki nie zaktualizujesz klucza szyfrowania." + }, + "editedFolder": { + "message": "Folder został zaktualizowany" + }, + "addedFolder": { + "message": "Folder został dodany" + }, + "deleteFolderConfirmation": { + "message": "Czy na pewno chcesz usunąć ten folder?" + }, + "deletedFolder": { + "message": "Folder został usunięty" + }, + "loginOrCreateNewAccount": { + "message": "Zaloguj się lub utwórz nowe konto, aby uzyskać dostęp do Twojego bezpiecznego sejfu." + }, + "createAccount": { + "message": "Utwórz konto" + }, + "logIn": { + "message": "Zaloguj się" + }, + "submit": { + "message": "Wyślij" + }, + "masterPass": { + "message": "Hasło główne" + }, + "masterPassDesc": { + "message": "Hasło główne zapewnia dostęp do sejfu. To bardzo ważne, aby je pamiętać, ponieważ zapomnianego hasła nie będzie można odzyskać." + }, + "masterPassHintDesc": { + "message": "Podpowiedź do hasła głównego może pomóc Ci przypomnieć hasło, jeśli je zapomnisz." + }, + "reTypeMasterPass": { + "message": "Wpisz ponownie hasło główne" + }, + "masterPassHint": { + "message": "Podpowiedź do hasła głównego (opcjonalnie)" + }, + "settings": { + "message": "Ustawienia" + }, + "passwordHint": { + "message": "Podpowiedź do hasła" + }, + "enterEmailToGetHint": { + "message": "Wpisz adres e-mail powiązany z kontem, aby otrzymać podpowiedź do hasła głównego." + }, + "getMasterPasswordHint": { + "message": "Uzyskaj podpowiedź do hasła głównego" + }, + "emailRequired": { + "message": "Adres e-mail jest wymagany." + }, + "invalidEmail": { + "message": "Adres e-mail jest nieprawidłowy." + }, + "masterPassRequired": { + "message": "Hasło główne jest wymagane." + }, + "masterPassLength": { + "message": "Hasło główne musi zawierać co najmniej 8 znaków." + }, + "masterPassDoesntMatch": { + "message": "Hasła nie pasują do siebie." + }, + "newAccountCreated": { + "message": "Konto zostało utworzone! Teraz możesz się zalogować." + }, + "masterPassSent": { + "message": "Wysłaliśmy Tobie wiadomość e-mail z podpowiedzią do hasła głównego." + }, + "unexpectedError": { + "message": "Wystąpił nieoczekiwany błąd." + }, + "itemInformation": { + "message": "Informacje o elemencie" + }, + "noItemsInList": { + "message": "Brak elementów." + }, + "sendVerificationCode": { + "message": "Wyślij kod weryfikacyjny na adres e-mail" + }, + "sendCode": { + "message": "Wyślij kod" + }, + "codeSent": { + "message": "Kod został wysłany" + }, + "verificationCode": { + "message": "Kod weryfikacyjny" + }, + "confirmIdentity": { + "message": "Potwierdź swoją tożsamość, aby kontynuować." + }, + "verificationCodeRequired": { + "message": "Kod weryfikacyjny jest wymagany." + }, + "invalidVerificationCode": { + "message": "Kod weryfikacyjny jest nieprawidłowy" + }, + "continue": { + "message": "Kontynuuj" + }, + "enterVerificationCodeApp": { + "message": "Wpisz 6-cyfrowy kod weryfikacyjny z aplikacji uwierzytelniającej." + }, + "enterVerificationCodeEmail": { + "message": "Wpisz 6-cyfrowy kod weryfikacyjny, który został przesłany na adres $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Kod weryfikacyjny został wysłany na adres $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamiętaj mnie" + }, + "sendVerificationCodeEmailAgain": { + "message": "Wyślij ponownie wiadomość z kodem weryfikacyjnym" + }, + "useAnotherTwoStepMethod": { + "message": "Użyj innej metody logowania dwustopniowego" + }, + "insertYubiKey": { + "message": "Włóż klucz YubiKey do portu USB komputera, a następnie dotknij jego przycisku." + }, + "insertU2f": { + "message": "Włóż klucz bezpieczeństwa do portu USB komputera. Jeśli klucz posiada przycisk, dotknij go." + }, + "recoveryCodeDesc": { + "message": "Utraciłeś dostęp do wszystkich swoich mechanizmów dwustopniowego logowania? Użyj kodów odzyskiwania, aby wyłączyć dwustopniowe logowanie na Twoim koncie." + }, + "recoveryCodeTitle": { + "message": "Kod odzyskiwania" + }, + "authenticatorAppTitle": { + "message": "Aplikacja uwierzytelniająca" + }, + "authenticatorAppDesc": { + "message": "Użyj aplikacji mobilnej (np. Authy lub Google Authenticator) do generowania czasowych kodów weryfikacyjnych.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Klucz bezpieczeństwa YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Użyj YubiKey jako metody dostępu do konta. Działa z YubiKey 4, 4 Nano, 4C i urządzeniami NEO." + }, + "duoDesc": { + "message": "Weryfikacja z użyciem Duo Security poprzez aplikację Duo Mobile, SMS, połączenie telefoniczne lub klucz bezpieczeństwa U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Weryfikacja dostępu do Twojej organizacji z użyciem Duo Security poprzez aplikację Duo Mobile, SMS, połączenie telefoniczne lub klucz bezpieczeństwa U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Użyj dowolnego klucza bezpieczeństwa WebAuthn, aby uzyskać dostęp do swojego konta." + }, + "emailTitle": { + "message": "Adres e-mail" + }, + "emailDesc": { + "message": "Kody weryfikacyjne zostaną wysłane do Ciebie wiadomością e-mail." + }, + "loginUnavailable": { + "message": "Logowanie jest niedostępne" + }, + "noTwoStepProviders": { + "message": "Konto posiada włączoną opcję logowania dwustopniowego, jednak to urządzenie nie wspiera żadnego ze skonfigurowanych mechanizmów autoryzacji dwustopniowej." + }, + "noTwoStepProviders2": { + "message": "Dodaj dodatkowe mechanizmy, które są lepiej obsługiwane przez różne urządzenia (np. aplikacje uwierzytelniające)." + }, + "twoStepOptions": { + "message": "Opcje logowania dwustopniowego" + }, + "selfHostedEnvironment": { + "message": "Samodzielnie hostowane środowisko" + }, + "selfHostedEnvironmentFooter": { + "message": "Wpisz podstawowy adres URL hostowanej instalacji Bitwarden." + }, + "customEnvironment": { + "message": "Niestandardowe środowisko" + }, + "customEnvironmentFooter": { + "message": "Dla zaawansowanych użytkowników. Możesz wpisać podstawowy adres URL niezależnie dla każdej usługi." + }, + "baseUrl": { + "message": "Adres URL serwera" + }, + "apiUrl": { + "message": "Adres URL serwera interfejsu API" + }, + "webVaultUrl": { + "message": "Adres URL serwera sejfu internetowego" + }, + "identityUrl": { + "message": "Adres URL serwera tożsamości" + }, + "notificationsUrl": { + "message": "Adres URL serwera powiadomień" + }, + "iconsUrl": { + "message": "Adres URL serwera ikon" + }, + "environmentSaved": { + "message": "Adresy URL środowiska zostały zapisane." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Tak" + }, + "no": { + "message": "Nie" + }, + "overwritePassword": { + "message": "Zastąp hasło" + }, + "learnMore": { + "message": "Dowiedz się więcej" + }, + "featureUnavailable": { + "message": "Funkcja jest niedostępna" + }, + "loggedOut": { + "message": "Wylogowano" + }, + "loginExpired": { + "message": "Twoja sesja wygasła." + }, + "logOutConfirmation": { + "message": "Czy na pewno chcesz się wylogować?" + }, + "logOut": { + "message": "Wyloguj się" + }, + "addNewLogin": { + "message": "Dodaj dane logowania" + }, + "addNewItem": { + "message": "Dodaj element" + }, + "addNewFolder": { + "message": "Dodaj folder" + }, + "view": { + "message": "Widok" + }, + "account": { + "message": "Konto" + }, + "loading": { + "message": "Ładowanie..." + }, + "lockVault": { + "message": "Zablokuj sejf" + }, + "passwordGenerator": { + "message": "Generator hasła" + }, + "contactUs": { + "message": "Skontaktuj się z nami" + }, + "getHelp": { + "message": "Uzyskaj pomoc" + }, + "fileBugReport": { + "message": "Zgłoś błąd" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Obserwuj nas" + }, + "syncVault": { + "message": "Synchronizuj sejf" + }, + "changeMasterPass": { + "message": "Zmień hasło główne" + }, + "changeMasterPasswordConfirmation": { + "message": "Hasło główne możesz zmienić na stronie sejfu bitwarden.com. Czy chcesz przejść do tej strony?" + }, + "fingerprintPhrase": { + "message": "Unikalny identyfikator konta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Unikalny identyfikator Twojego konta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Przejdź do sejfu internetowego" + }, + "getMobileApp": { + "message": "Pobierz aplikację mobilną" + }, + "getBrowserExtension": { + "message": "Pobierz rozszerzenie przeglądarki" + }, + "syncingComplete": { + "message": "Synchronizacja została zakończona" + }, + "syncingFailed": { + "message": "Synchronizacja nie powiodła się" + }, + "yourVaultIsLocked": { + "message": "Sejf jest zablokowany. Zweryfikuj swoją tożsamość, aby kontynuować." + }, + "unlock": { + "message": "Odblokuj" + }, + "loggedInAsOn": { + "message": "Zalogowano jako $EMAIL$ do $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Hasło główne jest nieprawidłowe" + }, + "twoStepLoginConfirmation": { + "message": "Logowanie dwustopniowe sprawia, że konto jest bardziej bezpieczne poprzez wymuszenie potwierdzenia logowania z innego urządzenia, takiego jak z klucza bezpieczeństwa, aplikacji uwierzytelniającej, wiadomości SMS, telefonu lub adresu e-mail. Logowanie dwustopniowe możesz włączyć w sejfie internetowym bitwarden.com. Czy chcesz przejść do tej strony?" + }, + "twoStepLogin": { + "message": "Logowanie dwustopniowe" + }, + "vaultTimeout": { + "message": "Blokowanie sejfu" + }, + "vaultTimeoutDesc": { + "message": "Wybierz kiedy sejf zostanie zablokowany i wykonaj następującą akcję." + }, + "immediately": { + "message": "Natychmiast" + }, + "tenSeconds": { + "message": "10 sekund" + }, + "twentySeconds": { + "message": "20 sekund" + }, + "thirtySeconds": { + "message": "30 sekund" + }, + "oneMinute": { + "message": "1 minuta" + }, + "twoMinutes": { + "message": "2 minuty" + }, + "fiveMinutes": { + "message": "5 minut" + }, + "fifteenMinutes": { + "message": "15 minut" + }, + "thirtyMinutes": { + "message": "30 minut" + }, + "oneHour": { + "message": "1 godzina" + }, + "fourHours": { + "message": "4 godziny" + }, + "onIdle": { + "message": "Po bezczynności przez 5 minut" + }, + "onSleep": { + "message": "Po uśpieniu komputera" + }, + "onLocked": { + "message": "Po zablokowaniu komputera" + }, + "onRestart": { + "message": "Po restarcie aplikacji" + }, + "never": { + "message": "Nigdy" + }, + "security": { + "message": "Zabezpieczenia" + }, + "clearClipboard": { + "message": "Wyczyść schowek", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatycznie wyczyść skopiowaną wartość ze schowka.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Wyłącz ikony stron" + }, + "disableFaviconDesc": { + "message": "Wyświetlaj rozpoznawalną ikonę serwisu obok danych logowania w sejfie." + }, + "enableMinToTray": { + "message": "Minimalizuj do zasobnika systemowego" + }, + "enableMinToTrayDesc": { + "message": "Po zminimalizowaniu okna, pokaż ikonę w zasobniku systemowym." + }, + "enableMinToMenuBar": { + "message": "Minimalizuj do paska menu" + }, + "enableMinToMenuBarDesc": { + "message": "Po zminimalizowaniu okna, pokaż ikonę w pasku zadań." + }, + "enableCloseToTray": { + "message": "Zamknij do zasobnika systemowego" + }, + "enableCloseToTrayDesc": { + "message": "Po zamknięciu okna, pokaż ikonę w zasobniku systemowym." + }, + "enableCloseToMenuBar": { + "message": "Zamknij do paska menu" + }, + "enableCloseToMenuBarDesc": { + "message": "Po zamknięciu okna, pokaż ikonę w pasku menu." + }, + "enableTray": { + "message": "Włącz ikonę w zasobniku systemowym" + }, + "enableTrayDesc": { + "message": "Zawsze pokazuj ikonę w zasobniku systemowym." + }, + "startToTray": { + "message": "Uruchom zminimalizowany do zasobnika systemowego" + }, + "startToTrayDesc": { + "message": "Przy pierwszym uruchomieniu aplikacji, pokaż tylko ikonę w zasobniku systemowym." + }, + "startToMenuBar": { + "message": "Uruchom zminimalizowany do paska menu" + }, + "startToMenuBarDesc": { + "message": "Przy pierwszym uruchomieniu aplikacji, pokaż tylko ikonę w pasku menu." + }, + "openAtLogin": { + "message": "Uruchom automatycznie po zalogowaniu" + }, + "openAtLoginDesc": { + "message": "Uruchom aplikację Bitwarden automatycznie po zalogowaniu." + }, + "alwaysShowDock": { + "message": "Zawsze pokazuj w Docku" + }, + "alwaysShowDockDesc": { + "message": "Pokaż ikonę Bitwarden w Docku po zminimalizowaniu do paska menu." + }, + "confirmTrayTitle": { + "message": "Potwierdź wyłączenie zasobnika systemowego" + }, + "confirmTrayDesc": { + "message": "Wyłączenie tej opcji spowoduje wyłącznie wszystkich innych powiązanych ustawień z zasobnikiem systemowym." + }, + "language": { + "message": "Język" + }, + "languageDesc": { + "message": "Zmień język aplikacji. Uruchomienie ponowne jest wymagane." + }, + "theme": { + "message": "Motyw" + }, + "themeDesc": { + "message": "Zmień motyw kolorystyczny aplikacji." + }, + "dark": { + "message": "Ciemny", + "description": "Dark color" + }, + "light": { + "message": "Jasny", + "description": "Light color" + }, + "copy": { + "message": "Kopiuj", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Sprawdź dostępność aktualizacji" + }, + "version": { + "message": "Wersja $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Uruchom ponownie, aby zaktualizować" + }, + "restartToUpdateDesc": { + "message": "Wersja $VERSION_NUM$ jest gotowa do zainstalowania. Czy chcesz uruchomić ponownie aplikację i ją zaktualizować?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Dostępna jest aktualizacja" + }, + "updateAvailableDesc": { + "message": "Aktualizacja została znaleziona. Czy chcesz pobrać ją teraz?" + }, + "restart": { + "message": "Uruchom ponownie" + }, + "later": { + "message": "Później" + }, + "noUpdatesAvailable": { + "message": "Aktualizacje nie są obecnie dostępne. Używasz najnowszej wersji." + }, + "updateError": { + "message": "Błąd aktualizacji" + }, + "unknown": { + "message": "Nieznane" + }, + "copyUsername": { + "message": "Kopiuj nazwę użytkownika" + }, + "copyNumber": { + "message": "Kopiuj numer karty", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopiuj kod zabezpieczający", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Konto Premium" + }, + "premiumManage": { + "message": "Zarządzaj kontem Premium" + }, + "premiumManageAlert": { + "message": "Kontem Premium możesz zarządzać na stronie sejfu bitwarden.com. Czy chcesz otworzyć tę stronę?" + }, + "premiumRefresh": { + "message": "Przedłuż konto Premium" + }, + "premiumNotCurrentMember": { + "message": "Nie posiadasz obecnie konta Premium." + }, + "premiumSignUpAndGet": { + "message": "Zarejestruj konto Premium, aby otrzymać:" + }, + "premiumSignUpStorage": { + "message": "1 GB miejsca na zaszyfrowane załączniki." + }, + "premiumSignUpTwoStep": { + "message": "Dodatkowe opcje logowania dwustopniowego, takie jak klucze YubiKey, FIDO U2F oraz Duo." + }, + "premiumSignUpReports": { + "message": "Raporty bezpieczeństwa haseł, stanu konta i raporty wycieków danych, aby Twoje dane były bezpieczne." + }, + "premiumSignUpTotp": { + "message": "Generator kodów weryfikacyjnych TOTP (2FA) dla danych logowania w sejfie." + }, + "premiumSignUpSupport": { + "message": "Priorytetowe wsparcie klienta." + }, + "premiumSignUpFuture": { + "message": "Wszystkie przyszłe funkcje premium. Więcej już wkrótce!" + }, + "premiumPurchase": { + "message": "Kup konto Premium" + }, + "premiumPurchaseAlert": { + "message": "Konto Premium możesz zakupić na stronie sejfu bitwarden.com. Czy chcesz otworzyć tę stronę?" + }, + "premiumCurrentMember": { + "message": "Posiadasz konto Premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Dziękujemy za wspieranie Bitwarden." + }, + "premiumPrice": { + "message": "Wszystko to jedynie za $PRICE$ /rok!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Odświeżanie zostało zakończone" + }, + "passwordHistory": { + "message": "Historia haseł" + }, + "clear": { + "message": "Wyczyść", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Brak haseł." + }, + "undo": { + "message": "Cofnij" + }, + "redo": { + "message": "Ponów" + }, + "cut": { + "message": "Wytnij", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Wklej", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Zaznacz wszystko" + }, + "zoomIn": { + "message": "Powiększ" + }, + "zoomOut": { + "message": "Pomniejsz" + }, + "resetZoom": { + "message": "Zresetuj powiększenie" + }, + "toggleFullScreen": { + "message": "Włącz/wyłącz pełny ekran" + }, + "reload": { + "message": "Odśwież" + }, + "toggleDevTools": { + "message": "Włącz/wyłącz narzędzia dla deweloperów" + }, + "minimize": { + "message": "Minimalizuj", + "description": "Minimize window" + }, + "zoom": { + "message": "Powiększenie" + }, + "bringAllToFront": { + "message": "Przenieś wszystko na wierzch", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "O Bitwarden" + }, + "services": { + "message": "Usługi" + }, + "hideBitwarden": { + "message": "Ukryj Bitwarden" + }, + "hideOthers": { + "message": "Ukryj pozostałe" + }, + "showAll": { + "message": "Pokaż wszystkie" + }, + "quitBitwarden": { + "message": "Zamknij Bitwarden" + }, + "valueCopied": { + "message": "Skopiowano $VALUE$", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Pomoc" + }, + "window": { + "message": "Okno" + }, + "checkPassword": { + "message": "Sprawdź, czy hasło zostało ujawnione." + }, + "passwordExposed": { + "message": "To hasło znajduje się w $VALUE$ wykradzionej(ych) bazie(ach) danych. Należy je zmienić.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "To hasło nie znajduje się w żadnej znanej wykradzionej bazie danych. Powinno być bezpieczne w użyciu." + }, + "baseDomain": { + "message": "Domena podstawowa", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nazwa domeny", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Dokładnie" + }, + "startsWith": { + "message": "Rozpoczyna się od" + }, + "regEx": { + "message": "Wyrażenie regularne", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Wykrywanie dopasowania", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Domyślne wykrywanie dopasowania", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Zmień opcje" + }, + "organization": { + "message": "Organizacja", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Domyślny" + }, + "exit": { + "message": "Wyjście" + }, + "showHide": { + "message": "Pokaż / Ukryj", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Ukryj w zasobniku systemowym" + }, + "alwaysOnTop": { + "message": "Zawsze na wierzchu", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Zaktualizowano", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Aktualizacja hasła", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Eksportuj sejf" + }, + "fileFormat": { + "message": "Format pliku" + }, + "warning": { + "message": "UWAGA", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potwierdź eksportowanie sejfu" + }, + "exportWarningDesc": { + "message": "Plik zawiera dane sejfu w niezaszyfrowanym formacie. Nie powinieneś go przechowywać, ani przesyłać poprzez niezabezpieczone kanały (takie jak poczta e-mail). Skasuj go natychmiast po użyciu." + }, + "encExportKeyWarningDesc": { + "message": "Dane eksportu zostaną zaszyfrowane za pomocą klucza szyfrowania konta. Jeśli kiedykolwiek zmienisz ten klucz, wyeksportuj dane ponownie, ponieważ nie będziesz w stanie odszyfrować tego pliku." + }, + "encExportAccountWarningDesc": { + "message": "Klucze szyfrowania konta są unikalne dla każdego użytkownika Bitwarden, więc nie możesz zaimportować zaszyfrowanego pliku eksportu na inne konto." + }, + "noOrganizationsList": { + "message": "Nie należysz do żadnej organizacji. Organizacje pozwalają na bezpieczne udostępnianie elementów innym użytkownikom." + }, + "noCollectionsInList": { + "message": "Brak kolekcji do wyświetlenia." + }, + "ownership": { + "message": "Właściciel" + }, + "whoOwnsThisItem": { + "message": "Kto jest właścicielem tego elementu?" + }, + "strong": { + "message": "Silne", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobre", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Słabe", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Słabe hasło główne" + }, + "weakMasterPasswordDesc": { + "message": "Wybrane przez Ciebie hasło główne jest słabe. Powinieneś użyć silniejszego hasła (lub frazy), aby właściwie chronić swoje konto Bitwarden. Czy na pewno chcesz użyć tego hasła głównego?" + }, + "pin": { + "message": "Kod PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Odblokuj kodem PIN" + }, + "setYourPinCode": { + "message": "Ustaw kod PIN do odblokowywania aplikacji Bitwarden. Ustawienia odblokowywania kodem PIN zostaną zresetowane po wylogowaniu." + }, + "pinRequired": { + "message": "Kod PIN jest wymagany." + }, + "invalidPin": { + "message": "Kod PIN jest nieprawidłowy." + }, + "unlockWithWindowsHello": { + "message": "Odblokuj za pomocą Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Zweryfikuj dla Bitwarden." + }, + "unlockWithTouchId": { + "message": "Odblokuj za pomocą Touch ID" + }, + "touchIdConsentMessage": { + "message": "odblokuj sejf" + }, + "noAutoPromptWindowsHello": { + "message": "Zapamiętaj autoryzację Windows Hello." + }, + "noAutoPromptTouchId": { + "message": "Zapamiętaj autoryzację Touch ID." + }, + "lockWithMasterPassOnRestart": { + "message": "Zablokuj hasłem głównym po uruchomieniu ponownym" + }, + "preferences": { + "message": "Ustawienia" + }, + "enableMenuBar": { + "message": "Włącz ikonę na pasku menu" + }, + "enableMenuBarDesc": { + "message": "Zawsze pokazuj ikonę na pasku menu." + }, + "hideToMenuBar": { + "message": "Schowaj do paska menu" + }, + "selectOneCollection": { + "message": "Musisz wybrać co najmniej jedną kolekcję." + }, + "premiumUpdated": { + "message": "Konto Premium zostało zaktualizowane." + }, + "restore": { + "message": "Przywróć" + }, + "premiumManageAlertAppStore": { + "message": "Możesz zarządzać subskrypcją w sklepie App Store. Czy chcesz przejść do sklepu App Store?" + }, + "legal": { + "message": "Informacje prawne", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Regulamin" + }, + "privacyPolicy": { + "message": "Polityka prywatności" + }, + "unsavedChangesConfirmation": { + "message": "Czy na pewno chcesz wyjść? Jeśli wyjdziesz, obecne informacje nie zostaną zapisane." + }, + "unsavedChangesTitle": { + "message": "Niezapisane zmiany" + }, + "clone": { + "message": "Klonuj" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji wpływa na ustawienia generatora." + }, + "vaultTimeoutAction": { + "message": "Sposób blokowania sejfu" + }, + "vaultTimeoutActionLockDesc": { + "message": "Po zablokowaniu sejfu, musisz ponownie wpisać hasło główne, aby uzyskać do niego dostęp." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Po wylogowaniu się z sejfu, musisz ponownie zalogować się, aby uzyskać do niego dostęp." + }, + "lock": { + "message": "Zablokuj", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Kosz", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Szukaj w koszu" + }, + "permanentlyDeleteItem": { + "message": "Usuń trwale element" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Czy na pewno chcesz usunąć trwale ten element?" + }, + "permanentlyDeletedItem": { + "message": "Element został trwale usunięty" + }, + "restoreItem": { + "message": "Przywróć element" + }, + "restoreItemConfirmation": { + "message": "Czy na pewno chcesz przywrócić ten element?" + }, + "restoredItem": { + "message": "Element został przywrócony" + }, + "permanentlyDelete": { + "message": "Usuń trwale" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Po wylogowaniu się z sejfu musisz ponownie zalogować się, aby uzyskać do niego dostęp. Czy na pewno chcesz użyć tego ustawienia?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potwierdź sposób blokowania sejfu" + }, + "enterpriseSingleSignOn": { + "message": "Logowanie jednokrotne" + }, + "setMasterPassword": { + "message": "Ustaw hasło główne" + }, + "ssoCompleteRegistration": { + "message": "W celu zakończenia jednokrotnego logowania SSO, ustaw hasło główne, aby uzyskać dostęp do sejfu." + }, + "newMasterPass": { + "message": "Nowe hasło główne" + }, + "confirmNewMasterPass": { + "message": "Potwierdź nowe hasło główne" + }, + "masterPasswordPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji wymaga, aby hasło główne spełniało następujące wymagania:" + }, + "policyInEffectMinComplexity": { + "message": "Minimalny poziom złożoności wynosi $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimalna długość wynosi $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Zawiera co najmniej jedną wielką literę" + }, + "policyInEffectLowercase": { + "message": "Zawiera co najmniej jedną małą literę" + }, + "policyInEffectNumbers": { + "message": "Zawiera co najmniej jedną cyfrę" + }, + "policyInEffectSpecial": { + "message": "Zawiera co najmniej jeden następujący znak specjalny $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Nowe hasło główne nie spełnia wymaganych zasad." + }, + "acceptPolicies": { + "message": "Zaznaczając tę opcję, akceptujesz:" + }, + "acceptPoliciesError": { + "message": "Nie zaakceptowałeś regulaminu i polityki prywatności." + }, + "enableBrowserIntegration": { + "message": "Włącz połączenie z przeglądarką" + }, + "enableBrowserIntegrationDesc": { + "message": "Połączenie z przeglądarką jest używane do odblokowania danymi biometrycznymi." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Połączenie z przeglądarką nie jest obsługiwane" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Połączenie z przeglądarką jest obsługiwane tylko z wersją aplikacji ze sklepu Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Połączenie z przeglądarką nie jest obsługiwane" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Połączenie z przeglądarką nie jest obecnie obsługiwane w aplikacji w wersji Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Wymagaj weryfikacji połączenia z przeglądarką" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Wymagaj sprawdzenia identyfikatora podczas tworzenia połączenia między aplikacją a przeglądarką. Po włączeniu tej funkcji, musisz zweryfikować każde nawiązywane połączenie." + }, + "approve": { + "message": "Zatwierdź" + }, + "verifyBrowserTitle": { + "message": "Zweryfikuj połączenie z przeglądarką" + }, + "verifyBrowserDesc": { + "message": "Upewnij się, że wyświetlony identyfikator jest identyczny z pokazanym w rozszerzeniu przeglądarki." + }, + "biometricsNotEnabledTitle": { + "message": "Dane biometryczne są wyłączone" + }, + "biometricsNotEnabledDesc": { + "message": "Aby włączyć dane biometryczne w przeglądarce, musisz włączyć tę samą funkcję w ustawianiach aplikacji." + }, + "personalOwnershipSubmitError": { + "message": "Ze względu na zasadę przedsiębiorstwa, nie możesz zapisywać elementów w osobistym sejfie. Zmień właściciela elementu na organizację i wybierz jedną z dostępnych kolekcji,." + }, + "hintEqualsPassword": { + "message": "Podpowiedź do hasła nie może być taka sama jak hasło." + }, + "personalOwnershipPolicyInEffect": { + "message": "Zasada organizacji ma wpływ na opcję własności elementów." + }, + "allSends": { + "message": "Wszystkie wysyłki", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Plik" + }, + "sendTypeText": { + "message": "Tekst" + }, + "searchSends": { + "message": "Szukaj w wysyłkach", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edytuj wysyłkę", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mój sejf" + }, + "text": { + "message": "Tekst" + }, + "deletionDate": { + "message": "Data usunięcia" + }, + "deletionDateDesc": { + "message": "Wysyłka zostanie trwale usunięta w określonym czasie.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data wygaśnięcia" + }, + "expirationDateDesc": { + "message": "Jeśli funkcja jest włączona, dostęp do wysyłki wygaśnie po określonym czasie.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maksymalna liczba dostępów" + }, + "maxAccessCountDesc": { + "message": "Jeśli funkcja jest włączona, po osiągnięciu maksymalnej liczby dostępów, użytkownicy nie będą mieli dostępu do tej wysyłki.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Obecna liczba dostępów" + }, + "disableSend": { + "message": "Wyłącz wysyłkę, aby nikt nie miał do niej dostępu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcjonalne hasło dla użytkownika, aby uzyskać dostęp do wysyłki.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Prywatne notatki o tej wysyłce.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Link wysyłki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Link wysyłki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Ukryj domyślnie tekst wysyłki", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Wysyłka została utworzona", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Wysyłka została zaktualizowana", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Wysyłka została usunięta", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nowe hasło" + }, + "whatTypeOfSend": { + "message": "Jakiego typu jest to wysyłka?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Utwórz wysyłkę", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Tekst, który chcesz wysłać." + }, + "sendFileDesc": { + "message": "Plik, który chcesz wysłać." + }, + "days": { + "message": "$DAYS$ dni", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dzień" + }, + "custom": { + "message": "Niestandardowe" + }, + "deleteSendConfirmation": { + "message": "Czy na pewno chcesz usunąć tę wysyłkę?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopiuj link wysyłki do schowka", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Po zapisaniu wysyłki, skopiuj link do schowka." + }, + "sendDisabled": { + "message": "Wysyłka została wyłączona", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Ze względu na zasadę przedsiębiorstwa, tylko Ty możesz usunąć obecną wysyłkę.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopiuj link" + }, + "disabled": { + "message": "Wyłączona" + }, + "maxAccessCountReached": { + "message": "Maksymalna liczba dostępów została osiągnięta" + }, + "expired": { + "message": "Wygasła" + }, + "pendingDeletion": { + "message": "Oczekiwanie na usunięcie" + }, + "webAuthnAuthenticate": { + "message": "Uwierzytelnianie WebAuthn" + }, + "hideEmail": { + "message": "Ukryj mój adres e-mail przed odbiorcami." + }, + "sendOptionsPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji wpływa na ustawienia wysyłek." + }, + "emailVerificationRequired": { + "message": "Weryfikacja adresu e-mail jest wymagana" + }, + "emailVerificationRequiredDesc": { + "message": "Musisz zweryfikować adres e-mail, aby używać tej funkcji." + }, + "passwordPrompt": { + "message": "Potwierdź hasłem głównym" + }, + "passwordConfirmation": { + "message": "Potwierdź hasło główne" + }, + "passwordConfirmationDesc": { + "message": "Ta operacja jest chroniona. Aby kontynuować, wpisz ponownie hasło główne." + }, + "updatedMasterPassword": { + "message": "Hasło główne zostało zaktualizowane" + }, + "updateMasterPassword": { + "message": "Zaktualizuj hasło główne" + }, + "updateMasterPasswordWarning": { + "message": "Hasło główne zostało zmienione przez administratora Twojej organizacji. Musisz je zaktualizować, aby uzyskać dostęp do sejfu. Ta czynność spowoduje wylogowanie z bieżącej sesji, przez co konieczne będzie ponowne zalogowanie się. Aktywne sesje na innych urządzeniach mogą pozostać aktywne przez maksymalnie godzinę." + }, + "hours": { + "message": "Godziny" + }, + "minutes": { + "message": "Minuty" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Zasady organizacji mają wpływ czas blokowania sejfu. Maksymalny dozwolony czas wynosi $HOURS$ godz. i $MINUTES$ min.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Czas blokowania sejfu przekracza limit określony przez organizację." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatyczne rejestrowanie użytkowników do resetowania hasła" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ta organizacja posługuje się zasadą, która automatycznie rejestruje użytkowników do resetowania hasła. Rejestracja umożliwia administratorom organizacji zmianę Twojego hasła głównego." + }, + "vaultExportDisabled": { + "message": "Eksportowanie sejfu zostało wyłączone" + }, + "personalVaultExportPolicyInEffect": { + "message": "Co najmniej jedna zasada organizacji uniemożliwia wyeksportowanie Twojego sejfu." + }, + "addAccount": { + "message": "Dodaj konto" + }, + "removeMasterPassword": { + "message": "Usuń hasło główne" + }, + "removedMasterPassword": { + "message": "Hasło główne zostało usunięte." + }, + "convertOrganizationEncryptionDesc": { + "message": "Organizacja $ORGANIZATION$ używa jednokrotnego logowania SSO z własnym serwerem kluczy. Użytkownicy nie muszą logować się za pomocą hasła głównego.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Opuść organizację" + }, + "leaveOrganizationConfirmation": { + "message": "Czy na pewno chcesz opuścić tę organizację?" + }, + "leftOrganization": { + "message": "Nie należysz już do tej organizacji." + }, + "ssoKeyConnectorUnavailable": { + "message": "Nie można nawiązać połączenia z serwerem Key Connector. Spróbuj ponownie później." + }, + "lockAllVaults": { + "message": "Zablokuj wszystkie sejfy" + }, + "accountLimitReached": { + "message": "Nie możesz zalogować się na więcej niż 5 kont jednocześnie." + }, + "accountPreferences": { + "message": "Ustawienia" + }, + "appPreferences": { + "message": "Ustawienia aplikacji (wszystkie konta)" + }, + "accountSwitcherLimitReached": { + "message": "Limit konta został osiągnięty. Wyloguj się z konta, aby dodać inne." + }, + "settingsTitle": { + "message": "Ustawienia aplikacji (konto $EMAIL$)", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Przełącz konto" + }, + "options": { + "message": "Opcje" + }, + "sessionTimeout": { + "message": "Twoja sesja wygasła. Zaloguj się ponownie." + }, + "exportingPersonalVaultTitle": { + "message": "Eksportowanie osobistego sejfu" + }, + "exportingPersonalVaultDescription": { + "message": "Tylko osobiste elementy sejfu powiązane z adresem $EMAIL$ zostaną wyeksportowane. Elementy sejfu należące do organizacji nie będą uwzględnione.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "Co chcesz wygenerować?" + }, + "passwordType": { + "message": "Rodzaj hasła" + }, + "regenerateUsername": { + "message": "Wygeneruj ponownie nazwę użytkownika" + }, + "generateUsername": { + "message": "Wygeneruj nazwę użytkownika" + }, + "usernameType": { + "message": "Rodzaj nazwy użytkownika" + }, + "plusAddressedEmail": { + "message": "Adres e-mail z plusem" + }, + "plusAddressedEmailDesc": { + "message": "Użyj możliwości dodawania aliasów u swojego dostawcy poczty e-mail." + }, + "catchallEmail": { + "message": "Adres catch-all" + }, + "catchallEmailDesc": { + "message": "Użyj skonfigurowanej skrzynki catch-all w swojej domenie." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Losowe słowo" + }, + "websiteName": { + "message": "Nazwa witryny" + }, + "service": { + "message": "Usługa" + } +} diff --git a/apps/desktop/src/locales/pt_BR/messages.json b/apps/desktop/src/locales/pt_BR/messages.json new file mode 100644 index 0000000000..2dc86d67af --- /dev/null +++ b/apps/desktop/src/locales/pt_BR/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtros" + }, + "allItems": { + "message": "Todos os Itens" + }, + "favorites": { + "message": "Favoritos" + }, + "types": { + "message": "Tipos" + }, + "typeLogin": { + "message": "Credencial" + }, + "typeCard": { + "message": "Cartão" + }, + "typeIdentity": { + "message": "Identidade" + }, + "typeSecureNote": { + "message": "Nota Segura" + }, + "folders": { + "message": "Pastas" + }, + "collections": { + "message": "Coleções" + }, + "searchVault": { + "message": "Pesquisar no Cofre" + }, + "addItem": { + "message": "Adicionar Item" + }, + "shared": { + "message": "Compartilhado" + }, + "share": { + "message": "Compartilhar" + }, + "moveToOrganization": { + "message": "Mover para a Organização" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ movido para $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Escolha uma organização para a qual deseja mover este item. Mudar para uma organização transfere a propriedade do item para essa organização. Você não será mais o proprietário direto deste item depois que ele for movido." + }, + "attachments": { + "message": "Anexos" + }, + "viewItem": { + "message": "Ver Item" + }, + "name": { + "message": "Nome" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novo URI" + }, + "username": { + "message": "Nome de Usuário" + }, + "password": { + "message": "Senha" + }, + "passphrase": { + "message": "Frase Secreta" + }, + "editItem": { + "message": "Editar Item" + }, + "emailAddress": { + "message": "Endereço de E-mail" + }, + "verificationCodeTotp": { + "message": "Código de Verificação (TOTP)" + }, + "website": { + "message": "Site" + }, + "notes": { + "message": "Notas" + }, + "customFields": { + "message": "Campos Personalizados" + }, + "launch": { + "message": "Abrir" + }, + "copyValue": { + "message": "Copiar Valor", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimizar ao copiar para a área de transferência" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimizar ao copiar dados de um item para a área de transferência." + }, + "toggleVisibility": { + "message": "Alternar Visibilidade" + }, + "toggleCollapse": { + "message": "Alternar Colapso", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Titular do Cartão" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Bandeira" + }, + "expiration": { + "message": "Vencimento" + }, + "securityCode": { + "message": "Código de Segurança" + }, + "identityName": { + "message": "Nome de Identidade" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Cadastro de Pessoas Físicas (CPF)" + }, + "passportNumber": { + "message": "Número do Passaporte" + }, + "licenseNumber": { + "message": "Número da Licença" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefone" + }, + "address": { + "message": "Endereço" + }, + "premiumRequired": { + "message": "Requer Assinatura Premium" + }, + "premiumRequiredDesc": { + "message": "Uma conta premium é necessária para usar esse recurso." + }, + "errorOccurred": { + "message": "Ocorreu um erro." + }, + "error": { + "message": "Erro" + }, + "january": { + "message": "Janeiro" + }, + "february": { + "message": "Fevereiro" + }, + "march": { + "message": "Março" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Maio" + }, + "june": { + "message": "Junho" + }, + "july": { + "message": "Julho" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Setembro" + }, + "october": { + "message": "Outubro" + }, + "november": { + "message": "Novembro" + }, + "december": { + "message": "Dezembro" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Título" + }, + "mr": { + "message": "Sr" + }, + "mrs": { + "message": "Sra" + }, + "ms": { + "message": "Sra" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Mês de Vencimento" + }, + "expirationYear": { + "message": "Ano de Vencimento" + }, + "select": { + "message": "Selecionar" + }, + "other": { + "message": "Outros" + }, + "generatePassword": { + "message": "Gerar Senha" + }, + "type": { + "message": "Tipo" + }, + "firstName": { + "message": "Primeiro Nome" + }, + "middleName": { + "message": "Nome do Meio" + }, + "lastName": { + "message": "Sobrenome" + }, + "fullName": { + "message": "Nome Completo" + }, + "address1": { + "message": "Endereço 1" + }, + "address2": { + "message": "Endereço 2" + }, + "address3": { + "message": "Endereço 3" + }, + "cityTown": { + "message": "Cidade / Localidade" + }, + "stateProvince": { + "message": "Estado / Província" + }, + "zipPostalCode": { + "message": "CEP / Código Postal" + }, + "country": { + "message": "País" + }, + "save": { + "message": "Salvar" + }, + "cancel": { + "message": "Cancelar" + }, + "delete": { + "message": "Excluir" + }, + "favorite": { + "message": "Favorito" + }, + "edit": { + "message": "Editar" + }, + "authenticatorKeyTotp": { + "message": "Chave de Autenticação (TOTP)" + }, + "folder": { + "message": "Pasta" + }, + "newCustomField": { + "message": "Novo Campo Personalizado" + }, + "value": { + "message": "Valor" + }, + "dragToSort": { + "message": "Arrastar para ordenar" + }, + "cfTypeText": { + "message": "Texto" + }, + "cfTypeHidden": { + "message": "Oculto" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "cfTypeLinked": { + "message": "Vinculado", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Valor vinculado", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Remover" + }, + "nameRequired": { + "message": "Requer o nome." + }, + "addedItem": { + "message": "Item adicionado" + }, + "editedItem": { + "message": "Item editado" + }, + "deleteItem": { + "message": "Excluir Item" + }, + "deleteFolder": { + "message": "Excluir Pasta" + }, + "deleteAttachment": { + "message": "Excluir Anexo" + }, + "deleteItemConfirmation": { + "message": "Você realmente deseja enviar para a lixeira?" + }, + "deletedItem": { + "message": "Enviar item para lixeira" + }, + "overwritePasswordConfirmation": { + "message": "Você tem certeza que deseja substituir a senha atual?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Tem certeza que deseja substituir o usuário atual?" + }, + "noneFolder": { + "message": "Nenhuma Pasta", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Adicionar Pasta" + }, + "editFolder": { + "message": "Editar Pasta" + }, + "regeneratePassword": { + "message": "Gerar Nova Senha" + }, + "copyPassword": { + "message": "Copiar Senha" + }, + "copyUri": { + "message": "Copiar URI" + }, + "copyVerificationCodeTotp": { + "message": "Copiar Código de Verificação (TOTP)" + }, + "length": { + "message": "Comprimento" + }, + "numWords": { + "message": "Número de Palavras" + }, + "wordSeparator": { + "message": "Separador de Palavra" + }, + "capitalize": { + "message": "Iniciais em Maiúsculas", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Incluir Número" + }, + "close": { + "message": "Fechar" + }, + "minNumbers": { + "message": "Mínimo de números" + }, + "minSpecial": { + "message": "Mínimo Especial", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Evitar Caracteres Ambíguos" + }, + "searchCollection": { + "message": "Pesquisar Coleção" + }, + "searchFolder": { + "message": "Pesquisar Pasta" + }, + "searchFavorites": { + "message": "Pesquisar Favoritos" + }, + "searchType": { + "message": "Pesquisar Tipo", + "description": "Search item type" + }, + "newAttachment": { + "message": "Adicionar Novo Anexo" + }, + "deletedAttachment": { + "message": "Anexo Excluído" + }, + "deleteAttachmentConfirmation": { + "message": "Tem certeza que deseja excluir esse anexo?" + }, + "attachmentSaved": { + "message": "O anexo foi salvo." + }, + "file": { + "message": "Arquivo" + }, + "selectFile": { + "message": "Selecione um arquivo." + }, + "maxFileSize": { + "message": "O tamanho máximo do arquivo é de 500 MB." + }, + "updateKey": { + "message": "Você não pode usar este recurso até você atualizar sua chave de criptografia." + }, + "editedFolder": { + "message": "Pasta editada" + }, + "addedFolder": { + "message": "Pasta adicionada" + }, + "deleteFolderConfirmation": { + "message": "Você tem certeza que deseja excluir esta pasta?" + }, + "deletedFolder": { + "message": "Pasta excluída" + }, + "loginOrCreateNewAccount": { + "message": "Inicie a sessão ou crie uma nova conta para acessar seu cofre seguro." + }, + "createAccount": { + "message": "Criar Conta" + }, + "logIn": { + "message": "Iniciar Sessão" + }, + "submit": { + "message": "Enviar" + }, + "masterPass": { + "message": "Senha Mestra" + }, + "masterPassDesc": { + "message": "A senha mestra é a senha que você usa para acessar o seu cofre. É muito importante que você não esqueça sua senha mestra. Não há maneira de recuperar a senha caso você se esqueça." + }, + "masterPassHintDesc": { + "message": "Uma dica de senha mestra pode ajudá-lo(a) a lembrá-lo(a) caso você esqueça." + }, + "reTypeMasterPass": { + "message": "Digite Novamente a Senha Mestra" + }, + "masterPassHint": { + "message": "Dica da Senha Mestra (opcional)" + }, + "settings": { + "message": "Configurações" + }, + "passwordHint": { + "message": "Dica da Senha" + }, + "enterEmailToGetHint": { + "message": "Insira o seu endereço de e-mail para receber a dica da sua senha mestra." + }, + "getMasterPasswordHint": { + "message": "Obter dica da senha mestra" + }, + "emailRequired": { + "message": "O endereço de e-mail é obrigatório." + }, + "invalidEmail": { + "message": "Endereço de e-mail inválido." + }, + "masterPassRequired": { + "message": "A senha mestra é obrigatória." + }, + "masterPassLength": { + "message": "A senha mestra deve ter pelo menos 8 caracteres." + }, + "masterPassDoesntMatch": { + "message": "A confirmação da senha mestra não corresponde." + }, + "newAccountCreated": { + "message": "A sua nova conta foi criada! Agora você pode iniciar a sessão." + }, + "masterPassSent": { + "message": "Enviamos um e-mail com a dica da sua senha mestra." + }, + "unexpectedError": { + "message": "Ocorreu um erro inesperado." + }, + "itemInformation": { + "message": "Informação do Item" + }, + "noItemsInList": { + "message": "Não há itens para listar." + }, + "sendVerificationCode": { + "message": "Enviar um código de verificação para o seu e-mail" + }, + "sendCode": { + "message": "Enviar Código" + }, + "codeSent": { + "message": "Código Enviado" + }, + "verificationCode": { + "message": "Código de Verificação" + }, + "confirmIdentity": { + "message": "Confirme a sua identidade para continuar." + }, + "verificationCodeRequired": { + "message": "Requer o código de verificação." + }, + "invalidVerificationCode": { + "message": "Código de verificação inválido" + }, + "continue": { + "message": "Continuar" + }, + "enterVerificationCodeApp": { + "message": "Insira o código de verificação de 6 dígitos do seu aplicativo de autenticação." + }, + "enterVerificationCodeEmail": { + "message": "Insira o código de verificação de 6 dígitos que foi enviado por e-mail para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mail de verificação enviado para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Lembrar de mim" + }, + "sendVerificationCodeEmailAgain": { + "message": "Enviar código de verificação para o e-mail novamente" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizar outro método de verificação em duas etapas" + }, + "insertYubiKey": { + "message": "Introduza a sua YubiKey na porta USB do seu computador, e depois toque no botão da mesma." + }, + "insertU2f": { + "message": "Insira a sua chave de segurança na porta USB do seu computador. Se ele tiver um botão, toque nele." + }, + "recoveryCodeDesc": { + "message": "Perdeu o acesso a todos os seus provedores de duas etapas? Utilize o seu código de recuperação para desativar todos os provedores de duas etapas da sua conta." + }, + "recoveryCodeTitle": { + "message": "Código de Recuperação" + }, + "authenticatorAppTitle": { + "message": "Aplicativo de Autenticação" + }, + "authenticatorAppDesc": { + "message": "Utilize um aplicativo de autenticação (tal como Authy ou Google Authenticator) para gerar códigos de verificação baseados no tempo.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Chave de Segurança YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utilize uma YubiKey para acessar a sua conta. Funciona com YubiKey 4, 4 Nano, 4C, e dispositivos NEO." + }, + "duoDesc": { + "message": "Verifique com o Duo Security utilizando o aplicativo Duo Mobile, SMS, chamada telefônica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifique com o Duo Security utilizando o aplicativo Duo Mobile, SMS, chamada telefônica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "WebAuthn FIDO2" + }, + "webAuthnDesc": { + "message": "Utilize qualquer chave de segurança ativada por WebAuthn para acessar a sua conta." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Os códigos de verificação vão ser enviados por e-mail para você." + }, + "loginUnavailable": { + "message": "Sessão Indisponível" + }, + "noTwoStepProviders": { + "message": "Esta conta tem a verificação em duas etapas ativada, no entanto, nenhum dos provedores de verificação em duas etapas configurados são suportados por este navegador web." + }, + "noTwoStepProviders2": { + "message": "Por favor inclua provedores adicionais que são melhor suportados entre dispositivos (como um aplicativo de autenticação)." + }, + "twoStepOptions": { + "message": "Opções de Login em Duas Etapas" + }, + "selfHostedEnvironment": { + "message": "Ambiente Auto-hospedado" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifique a URL de base da sua instalação local do Bitwarden." + }, + "customEnvironment": { + "message": "Ambiente Personalizado" + }, + "customEnvironmentFooter": { + "message": "Para usuários avançados. Você pode especificar a URL de base de cada serviço independentemente." + }, + "baseUrl": { + "message": "URL do Servidor" + }, + "apiUrl": { + "message": "URL do Servidor da API" + }, + "webVaultUrl": { + "message": "URL do Servidor do Cofre Web" + }, + "identityUrl": { + "message": "URL do Servidor de Identidade" + }, + "notificationsUrl": { + "message": "URL do Servidor de Notificações" + }, + "iconsUrl": { + "message": "URL do Servidor de Ícones" + }, + "environmentSaved": { + "message": "As URLs do ambiente foram salvas." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Sim" + }, + "no": { + "message": "Não" + }, + "overwritePassword": { + "message": "Substituir Senha" + }, + "learnMore": { + "message": "Saber mais" + }, + "featureUnavailable": { + "message": "Recurso Indisponível" + }, + "loggedOut": { + "message": "Sessão encerrada" + }, + "loginExpired": { + "message": "A sua sessão expirou." + }, + "logOutConfirmation": { + "message": "Você tem certeza que deseja sair?" + }, + "logOut": { + "message": "Encerrar a Sessão" + }, + "addNewLogin": { + "message": "Adicionar Nova Credencial" + }, + "addNewItem": { + "message": "Adicionar Novo Item" + }, + "addNewFolder": { + "message": "Adicionar Nova Pasta" + }, + "view": { + "message": "Ver" + }, + "account": { + "message": "Conta" + }, + "loading": { + "message": "Carregando..." + }, + "lockVault": { + "message": "Bloquear Cofre" + }, + "passwordGenerator": { + "message": "Gerador de Senha" + }, + "contactUs": { + "message": "Fale Conosco" + }, + "getHelp": { + "message": "Obter Ajuda" + }, + "fileBugReport": { + "message": "Enviar um Relatório de Bug" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Siga-nos" + }, + "syncVault": { + "message": "Sincronizar Cofre" + }, + "changeMasterPass": { + "message": "Alterar Senha Mestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Você pode alterar a sua senha mestra no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "fingerprintPhrase": { + "message": "Frase biométrica", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "A sua frase biométrica", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Ir para o Cofre Web" + }, + "getMobileApp": { + "message": "Obter o Aplicativo Móvel" + }, + "getBrowserExtension": { + "message": "Obter a Extensão de Navegador" + }, + "syncingComplete": { + "message": "Sincronização completada" + }, + "syncingFailed": { + "message": "A sincronização falhou" + }, + "yourVaultIsLocked": { + "message": "Seu cofre está trancado. Verifique sua identidade para continuar." + }, + "unlock": { + "message": "Desbloquear" + }, + "loggedInAsOn": { + "message": "Entrou como $EMAIL$ em $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Senha mestra inválida" + }, + "twoStepLoginConfirmation": { + "message": "A autenticação em duas etapas torna sua conta mais segura, exigindo que você verifique o seu login com outro dispositivo, como uma chave de segurança, um aplicativo de autenticação, SMS, chamada telefônica ou e-mail. A autenticação em duas etapas pode ser ativada no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "twoStepLogin": { + "message": "Login em Duas Etapas" + }, + "vaultTimeout": { + "message": "Tempo Limite do Cofre" + }, + "vaultTimeoutDesc": { + "message": "Escolha quando o tempo limite do seu cofre irá se esgotar e execute a ação selecionada." + }, + "immediately": { + "message": "Imediatamente" + }, + "tenSeconds": { + "message": "10 segundos" + }, + "twentySeconds": { + "message": "20 segundos" + }, + "thirtySeconds": { + "message": "30 segundos" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minutos" + }, + "fiveMinutes": { + "message": "5 minutos" + }, + "fifteenMinutes": { + "message": "15 minutos" + }, + "thirtyMinutes": { + "message": "30 minutos" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 horas" + }, + "onIdle": { + "message": "Quando o Sistema estiver Inativo" + }, + "onSleep": { + "message": "Quando o Sistema Hibernar" + }, + "onLocked": { + "message": "Quando o Sistema estiver Bloqueado" + }, + "onRestart": { + "message": "Ao Reiniciar" + }, + "never": { + "message": "Nunca" + }, + "security": { + "message": "Segurança" + }, + "clearClipboard": { + "message": "Limpar Área de Transferência", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Limpar automaticamente os valores copiados da sua área de transferência.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Desativar Ícones de Sites" + }, + "disableFaviconDesc": { + "message": "Os ícones de sites fornecem uma imagem reconhecível próxima de cada item de credencial no seu cofre." + }, + "enableMinToTray": { + "message": "Minimizar para Ícone da Bandeja" + }, + "enableMinToTrayDesc": { + "message": "Ao minimizar a janela, mostra um ícone na bandeja do sistema." + }, + "enableMinToMenuBar": { + "message": "Minimizar para a barra de menu" + }, + "enableMinToMenuBarDesc": { + "message": "Ao minimizar a janela, mostra um ícone na barra de menus." + }, + "enableCloseToTray": { + "message": "Fechar para Ícone da Bandeja" + }, + "enableCloseToTrayDesc": { + "message": "Ao fechar a janela, mostra um ícone na bandeja do sistema." + }, + "enableCloseToMenuBar": { + "message": "Fechar para barra de menu" + }, + "enableCloseToMenuBarDesc": { + "message": "Ao fechar a janela, mostra um ícone na barra de menu." + }, + "enableTray": { + "message": "Ativar Ícone de Bandeja" + }, + "enableTrayDesc": { + "message": "Sempre mostrar um ícone na bandeja do sistema." + }, + "startToTray": { + "message": "Iniciar com o ícone para a Bandeja" + }, + "startToTrayDesc": { + "message": "Quando o aplicativo for iniciado, apenas mostrar um ícone na bandeja do sistema." + }, + "startToMenuBar": { + "message": "Iniciar na barra de menu" + }, + "startToMenuBarDesc": { + "message": "Quando o aplicativo for iniciado, apenas mostrar um ícone na barra de menu." + }, + "openAtLogin": { + "message": "Iniciar automaticamente ao iniciar sessão" + }, + "openAtLoginDesc": { + "message": "Inicia o aplicativo Bitwarden Desktop automaticamente no logon." + }, + "alwaysShowDock": { + "message": "Exibir sempre na Dock" + }, + "alwaysShowDockDesc": { + "message": "Mostrar o ícone do Bitwarden na Dock, mesmo quando minimizado para a barra de menu." + }, + "confirmTrayTitle": { + "message": "Confirmar desativação da bandeja" + }, + "confirmTrayDesc": { + "message": "Desativar esta configuração também desativará todas as outras configurações relacionadas à bandeja." + }, + "language": { + "message": "Idioma" + }, + "languageDesc": { + "message": "Altere o idioma utilizado pelo aplicativo. É necessário reiniciar." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Altere o tema de cores do aplicativo." + }, + "dark": { + "message": "Escuro", + "description": "Dark color" + }, + "light": { + "message": "Claro", + "description": "Light color" + }, + "copy": { + "message": "Copiar", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Procurar Por Atualizações" + }, + "version": { + "message": "Versão $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Reiniciar Para Atualizar" + }, + "restartToUpdateDesc": { + "message": "A versão $VERSION_NUM$ está pronta para ser instalada. Você deve reiniciar o Bitwarden para completar a instalação. Você quer reiniciar e atualizar agora?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Atualização Disponível" + }, + "updateAvailableDesc": { + "message": "Uma atualização foi encontrada. Você quer baixá-la agora?" + }, + "restart": { + "message": "Reiniciar" + }, + "later": { + "message": "Mais Tarde" + }, + "noUpdatesAvailable": { + "message": "Não há atualizações disponíveis no momento. Você está usando a versão mais recente." + }, + "updateError": { + "message": "Erro na Atualização" + }, + "unknown": { + "message": "Desconhecido" + }, + "copyUsername": { + "message": "Copiar Nome de Usuário" + }, + "copyNumber": { + "message": "Copiar Número", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copiar Código de Segurança", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Assinatura Premium" + }, + "premiumManage": { + "message": "Gerenciar Plano" + }, + "premiumManageAlert": { + "message": "Você pode gerenciar a sua assinatura premium no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "premiumRefresh": { + "message": "Atualizar Assinatura" + }, + "premiumNotCurrentMember": { + "message": "Você não é um membro premium atualmente." + }, + "premiumSignUpAndGet": { + "message": "Registe-se para uma assinatura premium e obtenha:" + }, + "premiumSignUpStorage": { + "message": "1 GB de armazenamento de arquivos encriptados." + }, + "premiumSignUpTwoStep": { + "message": "Opções de autenticação em duas etapas adicionais como YubiKey, FIDO U2F, e Duo." + }, + "premiumSignUpReports": { + "message": "Higiene de senha, saúde da conta, e relatórios sobre violação de dados para manter o seu cofre seguro." + }, + "premiumSignUpTotp": { + "message": "Gerador de códigos de verificação TOTP (2FA) para credenciais no seu cofre." + }, + "premiumSignUpSupport": { + "message": "Prioridade no suporte ao cliente." + }, + "premiumSignUpFuture": { + "message": "Todos os recursos premium no futuro. Mais em breve!" + }, + "premiumPurchase": { + "message": "Comprar Premium" + }, + "premiumPurchaseAlert": { + "message": "Você pode comprar a assinatura premium no cofre web em bitwarden.com. Você deseja visitar o site agora?" + }, + "premiumCurrentMember": { + "message": "Você é um membro premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Obrigado por apoiar o Bitwarden." + }, + "premiumPrice": { + "message": "Tudo por apenas $PRICE$ /ano!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Atualização completada" + }, + "passwordHistory": { + "message": "Histórico de Senha" + }, + "clear": { + "message": "Limpar", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Não existem senhas para listar." + }, + "undo": { + "message": "Desfazer" + }, + "redo": { + "message": "Refazer" + }, + "cut": { + "message": "Cortar", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Colar", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Selecionar Tudo" + }, + "zoomIn": { + "message": "Ampliar" + }, + "zoomOut": { + "message": "Reduzir" + }, + "resetZoom": { + "message": "Redefinir Zoom" + }, + "toggleFullScreen": { + "message": "Alternar para Tela Cheia" + }, + "reload": { + "message": "Recarregar" + }, + "toggleDevTools": { + "message": "Alternar para Ferramentas de Desenvolvedor" + }, + "minimize": { + "message": "Minimizar", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Trazer Tudo para a Frente", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Sobre o Bitwarden" + }, + "services": { + "message": "Serviços" + }, + "hideBitwarden": { + "message": "Ocultar o Bitwarden" + }, + "hideOthers": { + "message": "Ocultar Outros" + }, + "showAll": { + "message": "Mostrar Todos" + }, + "quitBitwarden": { + "message": "Sair do Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copiado(a)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Ajuda" + }, + "window": { + "message": "Janela" + }, + "checkPassword": { + "message": "Verifique se a senha foi exposta." + }, + "passwordExposed": { + "message": "Esta senha foi exposta $VALUE$ vez(es) em brechas de dados. Você deve alterá-la.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Esta senha não foi encontrada em brechas de dados conhecidas. Deve ser seguro de usar." + }, + "baseDomain": { + "message": "Domínio de base", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Servidor", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exato" + }, + "startsWith": { + "message": "Começa com" + }, + "regEx": { + "message": "Expressão regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Detecção de Correspondência", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detecção de correspondência padrão", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Alternar Opções" + }, + "organization": { + "message": "Organização", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Padrão" + }, + "exit": { + "message": "Sair" + }, + "showHide": { + "message": "Mostrar / Ocultar", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Ocultar para a Bandeja" + }, + "alwaysOnTop": { + "message": "Sempre no Topo", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Atualizado", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Senha Atualizada", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Exportar Cofre" + }, + "fileFormat": { + "message": "Formato do Arquivo" + }, + "warning": { + "message": "AVISO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirmar Exportação do Cofre" + }, + "exportWarningDesc": { + "message": "Esta exportação contém os dados do seu cofre em um formato não criptografado. Você não deve armazenar ou enviar o arquivo exportado por canais inseguros (como e-mail). Exclua o arquivo imediatamente após terminar de usá-lo." + }, + "encExportKeyWarningDesc": { + "message": "Esta exportação criptografa seus dados usando a chave de criptografia da sua conta. Se você rotacionar a chave de criptografia da sua conta, você deve exportar novamente, já que você não será capaz de descriptografar este arquivo de exportação." + }, + "encExportAccountWarningDesc": { + "message": "As chaves de criptografia de conta são únicas para cada conta de usuário do Bitwarden, então você não pode importar uma exportação criptografada para uma conta diferente." + }, + "noOrganizationsList": { + "message": "Você não pertence a nenhuma organização. Organizações permitem-lhe compartilhar itens em segurança com outros usuários." + }, + "noCollectionsInList": { + "message": "Não há coleções para listar." + }, + "ownership": { + "message": "Propriedade" + }, + "whoOwnsThisItem": { + "message": "Quem possui este item?" + }, + "strong": { + "message": "Forte", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Boa", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Fraca", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Senha Mestra Fraca" + }, + "weakMasterPasswordDesc": { + "message": "A senha mestra que você selecionou está fraca. Você deve usar uma senha mestra forte (ou uma frase-passe) para proteger a sua conta Bitwarden adequadamente. Tem certeza que deseja usar esta senha mestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloquear com o PIN" + }, + "setYourPinCode": { + "message": "Defina o seu código PIN para desbloquear o Bitwarden. Suas configurações de PIN serão redefinidas se alguma vez você encerrar completamente toda a sessão do aplicativo." + }, + "pinRequired": { + "message": "O código PIN é necessário." + }, + "invalidPin": { + "message": "Código PIN inválido." + }, + "unlockWithWindowsHello": { + "message": "Desbloquear com o Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verifique para o Bitwarden." + }, + "unlockWithTouchId": { + "message": "Desbloquear com o Touch ID" + }, + "touchIdConsentMessage": { + "message": "desbloquear o seu cofre" + }, + "noAutoPromptWindowsHello": { + "message": "Não solicite por Windows Hello na inicialização." + }, + "noAutoPromptTouchId": { + "message": "Não solicite por Touch ID na inicialização." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloquear com senha mestra ao reiniciar" + }, + "preferences": { + "message": "Preferências" + }, + "enableMenuBar": { + "message": "Ativar Ícone da Barra de Menu" + }, + "enableMenuBarDesc": { + "message": "Sempre mostrar um ícone na barra de menu." + }, + "hideToMenuBar": { + "message": "Ocultar para a Barra de Menu" + }, + "selectOneCollection": { + "message": "Você deve selecionar pelo menos uma coleção." + }, + "premiumUpdated": { + "message": "Você atualizou para premium." + }, + "restore": { + "message": "Restaurar" + }, + "premiumManageAlertAppStore": { + "message": "Você pode gerenciar sua assinatura da App Store. Você quer visitar a App Store agora?" + }, + "legal": { + "message": "Aspectos Legais", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Termos de Serviço" + }, + "privacyPolicy": { + "message": "Política de Privacidade" + }, + "unsavedChangesConfirmation": { + "message": "Você tem certeza que deseja sair? Se sair agora, as suas informações atuais não serão salvas." + }, + "unsavedChangesTitle": { + "message": "Alterações não Salvas" + }, + "clone": { + "message": "Clonar" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Uma ou mais políticas da organização estão afetando as suas configurações do gerador." + }, + "vaultTimeoutAction": { + "message": "Ação de Tempo Limite do Cofre" + }, + "vaultTimeoutActionLockDesc": { + "message": "Um cofre bloqueado requer que você reinsira a sua senha mestra para entrar novamente." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Uma sessão encerrada com o cofre requer que você autentique-se novamente para acessá-lo de novo." + }, + "lock": { + "message": "Bloquear", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Lixeira", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Pesquisar na lixeira" + }, + "permanentlyDeleteItem": { + "message": "Excluir o Item Permanentemente" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Você tem certeza que deseja excluir permanentemente esse item?" + }, + "permanentlyDeletedItem": { + "message": "Item Permanentemente Excluído" + }, + "restoreItem": { + "message": "Restaurar Item" + }, + "restoreItemConfirmation": { + "message": "Você tem certeza que deseja restaurar esse item?" + }, + "restoredItem": { + "message": "Item Restaurado" + }, + "permanentlyDelete": { + "message": "Excluir Permanentemente" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Sair irá remover todo o acesso ao seu cofre e requer autenticação online após o período de tempo limite. Tem certeza de que deseja usar esta configuração?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmação de Ação de Tempo Limite" + }, + "enterpriseSingleSignOn": { + "message": "Iniciar Sessão Empresarial Única" + }, + "setMasterPassword": { + "message": "Definir Senha Mestra" + }, + "ssoCompleteRegistration": { + "message": "Para concluir o login com o SSO, defina uma senha mestra para acessar e proteger o seu cofre." + }, + "newMasterPass": { + "message": "Nova Senha Mestra" + }, + "confirmNewMasterPass": { + "message": "Confirme a Nova Senha Mestra" + }, + "masterPasswordPolicyInEffect": { + "message": "Uma ou mais políticas da organização exigem que a sua senha mestra cumpra aos seguintes requisitos:" + }, + "policyInEffectMinComplexity": { + "message": "Pontuação mínima de complexidade de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Comprimento mínimo de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contém um ou mais caracteres em maiúsculo" + }, + "policyInEffectLowercase": { + "message": "Contém um ou mais caracteres em minúsculo" + }, + "policyInEffectNumbers": { + "message": "Contém um ou mais números" + }, + "policyInEffectSpecial": { + "message": "Contém um ou mais dos seguintes caracteres especiais $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "A sua nova senha mestra não cumpre aos requisitos da política." + }, + "acceptPolicies": { + "message": "Ao marcar esta caixa, você concorda com o seguinte:" + }, + "acceptPoliciesError": { + "message": "Os Termos de Serviço e a Política de Privacidade não foram reconhecidos." + }, + "enableBrowserIntegration": { + "message": "Ativar integração com o navegador" + }, + "enableBrowserIntegrationDesc": { + "message": "A integração do navegador é usada para biometria no navegador." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Integração com o navegador não suportada" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Infelizmente, por ora, a integração do navegador só é suportada na versão da Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Integração com o navegador não suportada" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Infelizmente, a integração do navegador não é suportada na versão da Microsoft Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Exigir verificação para integração com o navegador" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Ative uma camada adicional de segurança, exigindo validação de frase de impressão digital ao estabelecer uma ligação entre o computador e o navegador. Quando ativado, isto requer intervenção do usuário e verificação cada vez que uma conexão é estabelecida." + }, + "approve": { + "message": "Aprovar" + }, + "verifyBrowserTitle": { + "message": "Verificar conexão do navegador" + }, + "verifyBrowserDesc": { + "message": "Por favor, certifique-se que a impressão digital mostrada é idêntica à impressão digital exibida na extensão do navegador." + }, + "biometricsNotEnabledTitle": { + "message": "Biometria não ativada" + }, + "biometricsNotEnabledDesc": { + "message": "A biometria com o navegador requer que a biometria de desktop seja ativada nas configurações primeiro." + }, + "personalOwnershipSubmitError": { + "message": "Devido a uma Política Empresarial, você está restrito de salvar itens para seu cofre pessoal. Altere a opção de Propriedade para uma organização e escolha entre as Coleções disponíveis." + }, + "hintEqualsPassword": { + "message": "Sua dica de senha não pode ser o mesmo que sua senha." + }, + "personalOwnershipPolicyInEffect": { + "message": "Uma política de organização está afetando suas opções de propriedade." + }, + "allSends": { + "message": "Todos os Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Arquivo" + }, + "sendTypeText": { + "message": "Texto" + }, + "searchSends": { + "message": "Pesquisar Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Editar Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Meu Cofre" + }, + "text": { + "message": "Texto" + }, + "deletionDate": { + "message": "Data de Exclusão" + }, + "deletionDateDesc": { + "message": "O Send será eliminado permanentemente na data e hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data de Validade" + }, + "expirationDateDesc": { + "message": "Se definido, o acesso a este Send expirará na data e hora especificadas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Contagem Máxima de Acessos" + }, + "maxAccessCountDesc": { + "message": "Se atribuído, usuários não poderão mais acessar este Send assim que o número máximo de acessos for atingido.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Contagem Atual de Acessos" + }, + "disableSend": { + "message": "Desative este Send para que ninguém possa acessá-lo.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opcionalmente exigir uma senha para os usuários acessarem este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Notas privadas sobre este Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Link do Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Link do Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Ao acessar o Send, ocultar o texto por padrão", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send Criado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send Editado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send Excluído", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nova Senha" + }, + "whatTypeOfSend": { + "message": "Que tipo de Send é este?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Criar Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "O texto que você deseja enviar." + }, + "sendFileDesc": { + "message": "O arquivo que você deseja enviar." + }, + "days": { + "message": "$DAYS$ dias", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dia" + }, + "custom": { + "message": "Personalizado" + }, + "deleteSendConfirmation": { + "message": "Você tem certeza que deseja excluir este Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copiar link do Send para a área de transferência", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copiar o link para compartilhar este Send para minha área de transferência ao salvar." + }, + "sendDisabled": { + "message": "Send desativado", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Devido a uma política corporativa, você só pode excluir um Send existente.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copiar link" + }, + "disabled": { + "message": "Desativado" + }, + "maxAccessCountReached": { + "message": "Número máximo de acessos atingido" + }, + "expired": { + "message": "Expirado" + }, + "pendingDeletion": { + "message": "Exclusão pendente" + }, + "webAuthnAuthenticate": { + "message": "Autenticar WebAuthn" + }, + "hideEmail": { + "message": "Ocultar meu endereço de e-mail dos destinatários." + }, + "sendOptionsPolicyInEffect": { + "message": "Uma ou mais políticas da organização estão afetando as suas opções de Send." + }, + "emailVerificationRequired": { + "message": "Verificação de E-mail Necessária" + }, + "emailVerificationRequiredDesc": { + "message": "Você precisa verificar o seu e-mail para usar este recurso." + }, + "passwordPrompt": { + "message": "Solicitação nova de senha mestra" + }, + "passwordConfirmation": { + "message": "Confirmação de senha mestra" + }, + "passwordConfirmationDesc": { + "message": "Esta ação está protegida. Para continuar, por favor, reinsira a sua senha mestra para verificar sua identidade." + }, + "updatedMasterPassword": { + "message": "Senha Mestra Atualizada" + }, + "updateMasterPassword": { + "message": "Atualizar Senha Mestra" + }, + "updateMasterPasswordWarning": { + "message": "Sua Senha Mestra foi alterada recentemente por um administrador de sua organização. Para acessar o cofre, você precisa atualizá-la agora. O processo desconectará você da sessão atual, exigindo que você inicie a sessão novamente. Sessões ativas em outros dispositivos podem continuar ativas por até uma hora." + }, + "hours": { + "message": "Horas" + }, + "minutes": { + "message": "Minutos" + }, + "vaultTimeoutPolicyInEffect": { + "message": "As políticas da sua organização estão afetando o tempo limite do seu cofre. O Tempo Limite Máximo permitido do Cofre é $HOURS$ hora(s) e $MINUTES$ minuto(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "O tempo limite do seu cofre excede as restrições definidas por sua organização." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Inscrição Automática" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Esta organização possui uma política empresarial que irá inscrevê-lo automaticamente na redefinição de senha. A inscrição permitirá que os administradores da organização alterem sua senha mestra." + }, + "vaultExportDisabled": { + "message": "Exportação de Cofre Desativada" + }, + "personalVaultExportPolicyInEffect": { + "message": "Uma ou mais políticas da organização impdem que você exporte seu cofre pessoal." + }, + "addAccount": { + "message": "Adicionar Conta" + }, + "removeMasterPassword": { + "message": "Remover Senha Mestra" + }, + "removedMasterPassword": { + "message": "Senha mestra removida." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ está usando SSO com um servidor de chaves auto-hospedado. Não é mais necessária uma senha mestra para os membros desta organização entrarem.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Sair da Organização" + }, + "leaveOrganizationConfirmation": { + "message": "Você tem certeza que deseja sair desta organização?" + }, + "leftOrganization": { + "message": "Você saiu da organização." + }, + "ssoKeyConnectorUnavailable": { + "message": "Não foi possível acessar o conector de chave, tente novamente mais tarde." + }, + "lockAllVaults": { + "message": "Bloquear Todos os Cofres" + }, + "accountLimitReached": { + "message": "Não mais do que 5 contas podem estar logadas ao mesmo tempo." + }, + "accountPreferences": { + "message": "Preferências" + }, + "appPreferences": { + "message": "Configurações do Aplicativo (Todas as Contas)" + }, + "accountSwitcherLimitReached": { + "message": "Limite de Contas atingido. Saia de uma conta para adicionar outra." + }, + "settingsTitle": { + "message": "Configurações do Aplicativo para $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Trocar de Conta" + }, + "options": { + "message": "Opções" + }, + "sessionTimeout": { + "message": "Sua sessão expirou. Por favor, volte e tente iniciar a sessão novamente." + }, + "exportingPersonalVaultTitle": { + "message": "Exportação do Cofre Pessoal" + }, + "exportingPersonalVaultDescription": { + "message": "Apenas os itens pessoais do cofre associados com $EMAIL$ serão exportados. Os itens do cofre da organização não serão incluídos.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/pt_PT/messages.json b/apps/desktop/src/locales/pt_PT/messages.json new file mode 100644 index 0000000000..346685749b --- /dev/null +++ b/apps/desktop/src/locales/pt_PT/messages.json @@ -0,0 +1,1740 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtros" + }, + "allItems": { + "message": "Todos os itens" + }, + "favorites": { + "message": "Favoritos" + }, + "types": { + "message": "Tipos" + }, + "typeLogin": { + "message": "Credencial" + }, + "typeCard": { + "message": "Cartão" + }, + "typeIdentity": { + "message": "Identidade" + }, + "typeSecureNote": { + "message": "Nota segura" + }, + "folders": { + "message": "Pastas" + }, + "collections": { + "message": "Coleções" + }, + "searchVault": { + "message": "Pesquisar cofre" + }, + "addItem": { + "message": "Adicionar item" + }, + "shared": { + "message": "Partilhado" + }, + "share": { + "message": "Partilhar" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Anexos" + }, + "viewItem": { + "message": "Ver item" + }, + "name": { + "message": "Nome" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Novo URI" + }, + "username": { + "message": "Nome de utilizador" + }, + "password": { + "message": "Palavra-passe" + }, + "passphrase": { + "message": "Frase-passe" + }, + "editItem": { + "message": "Editar item" + }, + "emailAddress": { + "message": "Endereço de email" + }, + "verificationCodeTotp": { + "message": "Código de verificação (TOTP)" + }, + "website": { + "message": "Website" + }, + "notes": { + "message": "Notas" + }, + "customFields": { + "message": "Campos personalizados" + }, + "launch": { + "message": "Iniciar" + }, + "copyValue": { + "message": "Copiar valor", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimizar ao copiar para a área de transferência" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimizar ao copiar dados de um item para a área de transferência." + }, + "toggleVisibility": { + "message": "Alternar visibilidade" + }, + "toggleCollapse": { + "message": "Alternar colapso", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Titular do cartão" + }, + "number": { + "message": "Número" + }, + "brand": { + "message": "Marca" + }, + "expiration": { + "message": "Expiração" + }, + "securityCode": { + "message": "Código de segurança" + }, + "identityName": { + "message": "Nome de identidade" + }, + "company": { + "message": "Empresa" + }, + "ssn": { + "message": "Número de segurança social" + }, + "passportNumber": { + "message": "Número do passaporte" + }, + "licenseNumber": { + "message": "Número da licença" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telefone" + }, + "address": { + "message": "Endereço" + }, + "premiumRequired": { + "message": "Premium requerido" + }, + "premiumRequiredDesc": { + "message": "É requerida uma adesão premium para utilizar esta funcionalidade." + }, + "errorOccurred": { + "message": "Ocorreu um erro." + }, + "error": { + "message": "Erro" + }, + "january": { + "message": "Janeiro" + }, + "february": { + "message": "Fevereiro" + }, + "march": { + "message": "Março" + }, + "april": { + "message": "Abril" + }, + "may": { + "message": "Maio" + }, + "june": { + "message": "Junho" + }, + "july": { + "message": "Julho" + }, + "august": { + "message": "Agosto" + }, + "september": { + "message": "Setembro" + }, + "october": { + "message": "Outubro" + }, + "november": { + "message": "Novembro" + }, + "december": { + "message": "Dezembro" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Título" + }, + "mr": { + "message": "Sr" + }, + "mrs": { + "message": "Sra" + }, + "ms": { + "message": "Sra" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Mês de expiração" + }, + "expirationYear": { + "message": "Ano de expiração" + }, + "select": { + "message": "Selecionar" + }, + "other": { + "message": "Outros" + }, + "generatePassword": { + "message": "Gerar palavra-passe" + }, + "type": { + "message": "Tipo" + }, + "firstName": { + "message": "Primeiro nome" + }, + "middleName": { + "message": "Nome do meio" + }, + "lastName": { + "message": "Último nome" + }, + "address1": { + "message": "Endereço 1" + }, + "address2": { + "message": "Endereço 2" + }, + "address3": { + "message": "Endereço 3" + }, + "cityTown": { + "message": "Cidade / localidade" + }, + "stateProvince": { + "message": "Estado / província" + }, + "zipPostalCode": { + "message": "Código postal" + }, + "country": { + "message": "País" + }, + "save": { + "message": "Guardar" + }, + "cancel": { + "message": "Cancelar" + }, + "delete": { + "message": "Eliminar" + }, + "favorite": { + "message": "Favorito" + }, + "edit": { + "message": "Editar" + }, + "authenticatorKeyTotp": { + "message": "Chave de autenticador (TOTP)" + }, + "folder": { + "message": "Pasta" + }, + "newCustomField": { + "message": "Novo campo personalizado" + }, + "value": { + "message": "Valor" + }, + "dragToSort": { + "message": "Arraste para ordenar" + }, + "cfTypeText": { + "message": "Texto" + }, + "cfTypeHidden": { + "message": "Ocultado" + }, + "cfTypeBoolean": { + "message": "Booleano" + }, + "remove": { + "message": "Remover" + }, + "nameRequired": { + "message": "O nome é requerido." + }, + "addedItem": { + "message": "Item adicionado" + }, + "editedItem": { + "message": "Item editado" + }, + "deleteItem": { + "message": "Eliminar item" + }, + "deleteFolder": { + "message": "Eliminar pasta" + }, + "deleteAttachment": { + "message": "Eliminar anexo" + }, + "deleteItemConfirmation": { + "message": "Tem a certeza de que pretende eliminar este item?" + }, + "deletedItem": { + "message": "Item enviado para o lixo" + }, + "overwritePasswordConfirmation": { + "message": "Tem a certeza de que pretende sobreescrever a palavra-passe atual?" + }, + "noneFolder": { + "message": "Nenhuma pasta", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Adicionar pasta" + }, + "editFolder": { + "message": "Editar pasta" + }, + "regeneratePassword": { + "message": "Regenerar palavra-passe" + }, + "copyPassword": { + "message": "Copiar palavra-passe" + }, + "copyUri": { + "message": "Copiar URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Comprimento" + }, + "numWords": { + "message": "Número de palavras" + }, + "wordSeparator": { + "message": "Separador de palavras" + }, + "capitalize": { + "message": "Capitalizar", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Incluir número" + }, + "close": { + "message": "Fechar" + }, + "minNumbers": { + "message": "Números mínimos" + }, + "minSpecial": { + "message": "Especiais mínimos", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Evitar caracteres ambíguos" + }, + "searchCollection": { + "message": "Pesquisar coleção" + }, + "searchFolder": { + "message": "Pesquisar pasta" + }, + "searchFavorites": { + "message": "Pesquisar favoritos" + }, + "searchType": { + "message": "Pesquisar tipo", + "description": "Search item type" + }, + "newAttachment": { + "message": "Adicionar novo anexo" + }, + "deletedAttachment": { + "message": "Anexo eliminado" + }, + "deleteAttachmentConfirmation": { + "message": "Tem a certeza de que deseja eliminar este anexo?" + }, + "attachmentSaved": { + "message": "O anexo foi guardado." + }, + "file": { + "message": "Ficheiro" + }, + "selectFile": { + "message": "Selecione um ficheiro." + }, + "maxFileSize": { + "message": "O tamanho máximo do ficheiro é de 500 MB." + }, + "updateKey": { + "message": "Não pode utilizar esta funcionalidade até atualizar a sua chave de encriptação." + }, + "options": { + "message": "Opções" + }, + "editedFolder": { + "message": "Pasta editada" + }, + "addedFolder": { + "message": "Pasta adicionada" + }, + "deleteFolderConfirmation": { + "message": "Tem certeza de que pretende eliminar esta pasta?" + }, + "deletedFolder": { + "message": "Pasta eliminada" + }, + "loginOrCreateNewAccount": { + "message": "Inicie sessão ou crie uma nova conta para aceder ao seu cofre seguro." + }, + "createAccount": { + "message": "Criar conta" + }, + "logIn": { + "message": "Iniciar sessão" + }, + "submit": { + "message": "Submeter" + }, + "masterPass": { + "message": "Palavra-passe mestra" + }, + "masterPassDesc": { + "message": "A palavra-passe mestra é a palavra-passe que utiliza para aceder ao seu cofre. É muito importante que não se esqueça da sua palavra-passe mestra. Não existe maneira de recuperar a palavra-passe no caso de a esquecer." + }, + "masterPassHintDesc": { + "message": "Uma dica da palavra-passe mestra pode ajudar a lembrar-se da sua palavra-passe se a esquecer." + }, + "reTypeMasterPass": { + "message": "Reescreva a palavra-passe mestra" + }, + "masterPassHint": { + "message": "Dica da palavra-passe mestra (opcional)" + }, + "settings": { + "message": "Definições" + }, + "passwordHint": { + "message": "Dica da palavra-passe" + }, + "enterEmailToGetHint": { + "message": "Introduza o endereço de email da sua conta para receber a dica da sua palavra-passe mestra." + }, + "getMasterPasswordHint": { + "message": "Obter dica da palavra-passe mestra" + }, + "emailRequired": { + "message": "O endereço de email é requerido." + }, + "invalidEmail": { + "message": "Endereço de email inválido." + }, + "masterPassRequired": { + "message": "A palavra-passe mestra é requerida." + }, + "masterPassLength": { + "message": "A palavra-passe mestra tem de ter pelo menos 8 caracteres." + }, + "masterPassDoesntMatch": { + "message": "A confirmação da palavra-passe mestra não corresponde." + }, + "newAccountCreated": { + "message": "A sua nova conta foi criada! Agora pode iniciar sessão." + }, + "masterPassSent": { + "message": "Enviámos-lhe um email com a dica da sua palavra-passe mestra." + }, + "unexpectedError": { + "message": "Ocorreu um erro inesperado." + }, + "itemInformation": { + "message": "Informação do item" + }, + "noItemsInList": { + "message": "Não existem itens para listar." + }, + "verificationCode": { + "message": "Código de verificação" + }, + "verificationCodeRequired": { + "message": "O código de verificação é requerido." + }, + "continue": { + "message": "Continuar" + }, + "enterVerificationCodeApp": { + "message": "Introduza o código de verificação de 6 dígitos da sua aplicação de autenticador." + }, + "enterVerificationCodeEmail": { + "message": "Introduza o código de verificação de 6 dígitos que foi enviado por email para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Email de verificação enviado para $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Memorizar-me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Enviar código de verificação novamente" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizar outro método de início de sessão de dois passos" + }, + "insertYubiKey": { + "message": "Introduza a sua YubiKey na porta USB do seu computador, depois toque no botão da mesma." + }, + "insertU2f": { + "message": "Introduza a sua chave de segurança na porta USB do seu computador. Se tiver um botão, toque no mesmo." + }, + "recoveryCodeDesc": { + "message": "Perdeu o acesso a todos os seus provedores de dois passos? Utilize o seu código de recuperação para desativar todos os provedores de dois passos da sua conta." + }, + "recoveryCodeTitle": { + "message": "Código de recuperação" + }, + "authenticatorAppTitle": { + "message": "Aplicação de autenticador" + }, + "authenticatorAppDesc": { + "message": "Utilize uma aplicação de autenticador (tal como Authy ou Google Authenticator) para gerar códigos de verificação baseados na hora.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Chave de segurança YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utilize uma YubiKey para aceder à sua conta. Funciona com YubiKey 4, 4 Nano, 4C, e dispositivos NEO." + }, + "duoDesc": { + "message": "Verifique com Duo Security utilizando a aplicação Duo Mobile, SMS, chamada telefónica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifique com Duo Security para a sua organização utilizando a aplicação Duo Mobile, SMS, chamada telefónica, ou chave de segurança U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Os códigos de verificação vão ser enviados para si." + }, + "loginUnavailable": { + "message": "Início de sessão indisponível" + }, + "noTwoStepProviders": { + "message": "Esta conta tem o início de sessão de dois passos ativado, no entanto, nenhum dos provedores de início de sessão de dois passos configurados são suportados por este dispositivo." + }, + "noTwoStepProviders2": { + "message": "Por favor adicione provedores adicionais que são melhor suportados entre dispositivos (como uma aplicação de autenticador)." + }, + "twoStepOptions": { + "message": "Opções de início de sessão de dois passos" + }, + "selfHostedEnvironment": { + "message": "Ambiente auto-hospedado" + }, + "selfHostedEnvironmentFooter": { + "message": "Especifique o URL de base da sua instalação do Bitwarden alojada nas suas premissas." + }, + "customEnvironment": { + "message": "Ambiente personalizado" + }, + "customEnvironmentFooter": { + "message": "Para utilizadores avançados. Pode especificar o URL de base de cada serviço independentemente." + }, + "baseUrl": { + "message": "URL do servidor" + }, + "apiUrl": { + "message": "URL do servidor da API" + }, + "webVaultUrl": { + "message": "URL do servidor do cofre web" + }, + "identityUrl": { + "message": "URL do servidor de identidade" + }, + "notificationsUrl": { + "message": "URL do servidor de notificações" + }, + "iconsUrl": { + "message": "URL do servidor de ícones" + }, + "environmentSaved": { + "message": "Os URLs de ambiente foram guardados." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Sim" + }, + "no": { + "message": "Não" + }, + "overwritePassword": { + "message": "Sobreescrever palavra-passe" + }, + "learnMore": { + "message": "Saber mais" + }, + "featureUnavailable": { + "message": "Funcionalidade indisponível" + }, + "loggedOut": { + "message": "Sessão terminada" + }, + "loginExpired": { + "message": "A sua sessão expirou." + }, + "logOutConfirmation": { + "message": "Tem a certeza de que pretende terminar sessão?" + }, + "logOut": { + "message": "Terminar sessão" + }, + "addNewLogin": { + "message": "Adicionar nova credencial" + }, + "addNewItem": { + "message": "Adicionar novo item" + }, + "addNewFolder": { + "message": "Adicionar nova pasta" + }, + "view": { + "message": "Ver" + }, + "account": { + "message": "Conta" + }, + "loading": { + "message": "A carregar..." + }, + "lockNow": { + "message": "Bloquear agora" + }, + "passwordGenerator": { + "message": "Gerador de palavras-passe" + }, + "emailUs": { + "message": "Enviar-nos um email" + }, + "visitOurWebsite": { + "message": "Visitar o nosso website" + }, + "fileBugReport": { + "message": "Submeter um relatório de bug" + }, + "blog": { + "message": "Blogue" + }, + "followUs": { + "message": "Seguir-nos" + }, + "syncVault": { + "message": "Sincronizar cofre" + }, + "changeMasterPass": { + "message": "Alterar palavra-passe mestra" + }, + "changeMasterPasswordConfirmation": { + "message": "Pode alterar a sua palavra-passe mestra no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "fingerprintPhrase": { + "message": "Frase de impressão digital", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "A frase de impressão digital da sua conta", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Ir para o cofre web" + }, + "getMobileApp": { + "message": "Obter aplicação móvel" + }, + "getBrowserExtension": { + "message": "Obter extensão de navegador" + }, + "syncingComplete": { + "message": "Sincronização completada" + }, + "syncingFailed": { + "message": "Sincronização falhada" + }, + "yourVaultIsLocked": { + "message": "O seu cofre está bloqueado. Verifique a sua palavra-passe mestra para continuar." + }, + "unlock": { + "message": "Desbloquear" + }, + "loggedInAsOn": { + "message": "Sessão iniciada como $EMAIL$ em $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Palavra-passe mestra inválida" + }, + "twoStepLoginConfirmation": { + "message": "O início de sessão de dois passos torna a sua conta mais segura ao requerer que verifique o seu início de sessão com outro dispositivo como uma chave de segurança, aplicação de autenticação, SMS, chamada telefónica, ou email. O início de sessão de dois passos pode ser ativado no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "twoStepLogin": { + "message": "Início de sessão de dois passos" + }, + "vaultTimeout": { + "message": "Expiração do cofre" + }, + "vaultTimeoutDesc": { + "message": "Escolha quando o seu cofre irá expirar e realizar a ação selecionada." + }, + "immediately": { + "message": "Imediatamente" + }, + "tenSeconds": { + "message": "10 segundos" + }, + "twentySeconds": { + "message": "20 segundos" + }, + "thirtySeconds": { + "message": "30 segundos" + }, + "oneMinute": { + "message": "1 minuto" + }, + "twoMinutes": { + "message": "2 minutos" + }, + "fiveMinutes": { + "message": "5 minutos" + }, + "fifteenMinutes": { + "message": "15 minutos" + }, + "thirtyMinutes": { + "message": "30 minutos" + }, + "oneHour": { + "message": "1 hora" + }, + "fourHours": { + "message": "4 horas" + }, + "onIdle": { + "message": "Quando o sistema está inativo" + }, + "onSleep": { + "message": "Quando o sistema está hibernado" + }, + "onLocked": { + "message": "Quando o sistema está bloqueado" + }, + "onRestart": { + "message": "Quando reiniciar" + }, + "never": { + "message": "Nunca" + }, + "security": { + "message": "Segurança" + }, + "clearClipboard": { + "message": "Limpar área de transferência", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Limpar automaticamente valores copiados da sua área de transferência.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Desativar ícones de websites" + }, + "disableFaviconDesc": { + "message": "Os ícones de websites providenciam uma imagem reconhecível ao lado de cada item de credencial no seu cofre." + }, + "enableMinToTray": { + "message": "Minimizar para ícone de bandeja" + }, + "enableMinToTrayDesc": { + "message": "Ao minimizar a janela, mostrar um ícone na bandeja do sistema em alternativa." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Fechar para ícone de bandeja" + }, + "enableCloseToTrayDesc": { + "message": "Ao fechar a janela, mostrar um ícone na bandeja do sistema em alternativa." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Ativar ícone de bandeja" + }, + "enableTrayDesc": { + "message": "Mostrar sempre um ícone na bandeja do sistema." + }, + "startToTray": { + "message": "Iniciar para o ícone de bandeja" + }, + "startToTrayDesc": { + "message": "Quando a aplicação é iniciada pela primeira vez, mostrar apenas um ícone na bandeja do sistema." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Idioma" + }, + "languageDesc": { + "message": "Altere o idioma utilizado pela aplicação. Reinício é requerido." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Altere o tema de cor da aplicação." + }, + "dark": { + "message": "Escuro", + "description": "Dark color" + }, + "light": { + "message": "Claro", + "description": "Light color" + }, + "copy": { + "message": "Copiar", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Procurar atualizações" + }, + "version": { + "message": "Versão $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Reiniciar para atualizar" + }, + "restartToUpdateDesc": { + "message": "A versão $VERSION_NUM$ está pronta para instalar. Tem de reiniciar a aplicação para completar a instalação. Pretende reiniciar e atualizar agora?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Atualização disponível" + }, + "updateAvailableDesc": { + "message": "Foi encontrada uma atualização. Pretende transferi-la agora?" + }, + "restart": { + "message": "Reiniciar" + }, + "later": { + "message": "Mais tarde" + }, + "noUpdatesAvailable": { + "message": "Não existem atualizações disponíveis atualmente. Está a atualizar a versão mais recente." + }, + "updateError": { + "message": "Erro de atualização" + }, + "unknown": { + "message": "Desconhecido" + }, + "copyUsername": { + "message": "Copiar nome de utilizador" + }, + "copyNumber": { + "message": "Copiar número", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copiar código de segurança", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Adesão Premium" + }, + "premiumManage": { + "message": "Gerir adesão" + }, + "premiumManageAlert": { + "message": "Pode gerir a sua adesão premium no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "premiumRefresh": { + "message": "Atualizar adesão" + }, + "premiumNotCurrentMember": { + "message": "Não é atualmente um membro premium." + }, + "premiumSignUpAndGet": { + "message": "Registe-se para uma adesão premium e obtenha:" + }, + "premiumSignUpStorage": { + "message": "1 GB de armazenamento encriptado para anexos de ficheiros." + }, + "premiumSignUpTwoStep": { + "message": "Opções de início de sessão de dois passos adicionais como YubiKey, FIDO U2F, e Duo." + }, + "premiumSignUpReports": { + "message": "Higiene de palavras-passe, saúde das contas, e relatórios de brechas de dados para manter o seu cofre seguro." + }, + "premiumSignUpTotp": { + "message": "Gerador de códigos de verificação TOTP (2FA) para credenciais no seu cofre." + }, + "premiumSignUpSupport": { + "message": "Prioridade no apoio ao cliente." + }, + "premiumSignUpFuture": { + "message": "Todas as funcionalidades premium futuras. Mais a chegar brevemente!" + }, + "premiumPurchase": { + "message": "Comprar Premium" + }, + "premiumPurchaseAlert": { + "message": "Pode comprar adesão premium no cofre web bitwarden.com. Pretende visitar o website agora?" + }, + "premiumCurrentMember": { + "message": "É um membro premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Obrigado por apoiar o Bitwarden." + }, + "premiumPrice": { + "message": "Tudo por apenas $PRICE$ /ano!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Atualização completada" + }, + "passwordHistory": { + "message": "Histórico de palavras-passe" + }, + "clear": { + "message": "Limpar", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Não existem palavras-passe para listar." + }, + "undo": { + "message": "Desfazer" + }, + "redo": { + "message": "Refazer" + }, + "cut": { + "message": "Cortar", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Colar", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Selecionar tudo" + }, + "zoomIn": { + "message": "Ampliar" + }, + "zoomOut": { + "message": "Reduzir" + }, + "resetZoom": { + "message": "Repor zoom" + }, + "toggleFullScreen": { + "message": "Alternar ecrã completo" + }, + "reload": { + "message": "Recarregar" + }, + "toggleDevTools": { + "message": "Alternar ferramentas de programador" + }, + "minimize": { + "message": "Minimizar", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Trazer tudo para a frente", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Acerca do Bitwarden" + }, + "services": { + "message": "Serviços" + }, + "hideBitwarden": { + "message": "Ocultar o Bitwarden" + }, + "hideOthers": { + "message": "Ocultar outros" + }, + "showAll": { + "message": "Mostrar todos" + }, + "quitBitwarden": { + "message": "Sair do Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copiado(a)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Ajuda" + }, + "window": { + "message": "Janela" + }, + "checkPassword": { + "message": "Verifica se a palavra-passe foi exposta." + }, + "passwordExposed": { + "message": "Esta palavra-passe foi exposta $VALUE$ vez(es) em brechas de dados. Deve alterá-la.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Esta palavra-passe não foi encontrada em nenhuma brecha de dados conhecida. Esta deve ser segura de utilizar." + }, + "baseDomain": { + "message": "Domínio base" + }, + "host": { + "message": "Servidor", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exato" + }, + "startsWith": { + "message": "Começa por" + }, + "regEx": { + "message": "Expressão regular", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Deteção de correspondência", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Deteção de correspondência predefinida", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Alternar opções" + }, + "organization": { + "message": "Organização", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Predefinido" + }, + "exit": { + "message": "Sair" + }, + "showHide": { + "message": "Mostrar / ocultar", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Ocultar para a bandeja" + }, + "alwaysOnTop": { + "message": "Sempre no topo", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Atualizado", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Palavra passe atualizada", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Exportar cofre" + }, + "fileFormat": { + "message": "Formato do ficheiro" + }, + "warning": { + "message": "AVISO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "Esta exportação contém os seus dados do cofre num formato desencriptado. Não deve armazenar ou enviar o ficheiro exportado através de canais inseguros (como email). Elimine-o imediatamente após o utilizar." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "exportMasterPassword": { + "message": "Introduza a sua palavra-passe mestra para exportar os dados do seu cofre." + }, + "noOrganizationsList": { + "message": "Você não pertence a nenhuma organização. Organizações permitem-lhe partilhar itens em segurança com outros utilizadores." + }, + "noCollectionsInList": { + "message": "Não existem coleções para exibir." + }, + "ownership": { + "message": "Propriedade" + }, + "whoOwnsThisItem": { + "message": "Quem é o proprietário deste item?" + }, + "strong": { + "message": "Forte", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Boa", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Fraca", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Palavra-passe mestra fraca" + }, + "weakMasterPasswordDesc": { + "message": "A palavra-passe mestra que escolheu é fraca. Deve utilizar uma palavra-passe mestra forte (ou uma frase-passe) para proteger adequadamente a sua conta Bitwarden. Tem a certeza de que pretende utilizar esta palavra-passe mestra?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Desbloquear com PIN" + }, + "setYourPinCode": { + "message": "Defina o seu código PIN para desbloquear o Bitwarden. As suas definições PIN serão redefinidas se terminar sessão completamente da aplicação." + }, + "pinRequired": { + "message": "O código PIN é requerido." + }, + "invalidPin": { + "message": "Código PIN inválido." + }, + "yourVaultIsLockedPinCode": { + "message": "O seu cofre está bloqueado. Verifique o seu PIN para continuar." + }, + "unlockWithWindowsHello": { + "message": "Desbloquear com Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verificar para Bitwarden." + }, + "unlockWithTouchId": { + "message": "Desbloquear com Touch ID" + }, + "touchIdConsentMessage": { + "message": "Verificar para Bitwarden." + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Bloquear com palavra-passe mestra ao reiniciar" + }, + "preferences": { + "message": "Preferências" + }, + "enableMenuBar": { + "message": "Ativar ícone da barra de menu" + }, + "enableMenuBarDesc": { + "message": "Mostrar sempre um ícone na barra de menu." + }, + "hideToMenuBar": { + "message": "Ocultar para a barra de menu" + }, + "selectOneCollection": { + "message": "Tem de selecionar pelo menos uma coleção." + }, + "premiumUpdated": { + "message": "Atualizou para premium." + }, + "restore": { + "message": "Restaurar" + }, + "premiumManageAlertAppStore": { + "message": "Pode gerir a sua assinatura através da App Store. Pretende visitar a App Store agora?" + }, + "legal": { + "message": "Informação legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Termos de serviço" + }, + "privacyPolicy": { + "message": "Política de privacidade" + }, + "unsavedChangesConfirmation": { + "message": "Tem a certeza que pretende sair? Se sair agora, as suas informações atuais não irão ser guardadas" + }, + "unsavedChangesTitle": { + "message": "Alterações por guardar" + }, + "clone": { + "message": "Clonar" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Uma ou mais políticas de organização estão a afetar as suas definições do gerador." + }, + "vaultTimeoutAction": { + "message": "Ação de expiração do cofre" + }, + "vaultTimeoutActionLockDesc": { + "message": "Um cofre bloqueado requer que reintroduza a sua palavra-passe mestra para aceder novamente." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Um cofre com sessão terminada requer que se volte a autenticar para o poder aceder novamente." + }, + "lock": { + "message": "Bloquear", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Lixo", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Pesquisar lixo" + }, + "permanentlyDeleteItem": { + "message": "Eliminar item permanentemente" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Tem a certeza de que pretende eliminar este item permanentemente?" + }, + "permanentlyDeletedItem": { + "message": "Item eliminado permanentemente" + }, + "restoreItem": { + "message": "Restaurar item" + }, + "restoreItemConfirmation": { + "message": "Tem a certeza de que pretende restaurar este item?" + }, + "restoredItem": { + "message": "Item restaurado" + }, + "permanentlyDelete": { + "message": "Eliminar permanentemente" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Terminar sessão irá remover todos os acessos ao seu cofre e requer autenticação online após o período de expiração. Tem a certeza de que pretende utilizar esta definição?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmação de expiração do cofre" + }, + "enterpriseSingleSignOn": { + "message": "Início de Sessão Único da Empresa" + }, + "setMasterPassword": { + "message": "Definir palavra-passe mestra" + }, + "ssoCompleteRegistration": { + "message": "Para concluir o início de sessão com SSO, por favor defina uma palavra-passe mestra para aceder e proteger o seu cofre." + }, + "newMasterPass": { + "message": "Nova palavra-passe mestra" + }, + "confirmNewMasterPass": { + "message": "Confirmar nova palavra-passe mestra" + }, + "masterPasswordPolicyInEffect": { + "message": "Uma ou mais políticas da organização requerem que a sua palavra-passe mestra cumpra aos seguintes requisitos:" + }, + "policyInEffectMinComplexity": { + "message": "Pontuação mínima de complexidade de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Comprimento mínimo de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contém um ou mais caracteres em maiúsculas" + }, + "policyInEffectLowercase": { + "message": "Contém um ou mais caracteres em minúsculas" + }, + "policyInEffectNumbers": { + "message": "Contém um ou mais números" + }, + "policyInEffectSpecial": { + "message": "Contém um ou mais dos seguintes caracteres especiais $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "A sua nova palavra-passe mestra não cumpre os requisitos da política." + }, + "acceptPolicies": { + "message": "Ao marcar esta caixa concorda com o seguinte:" + }, + "acceptPoliciesError": { + "message": "Os Termos de Serviço e a Política de Privacidade não foram aceites." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + } +} diff --git a/apps/desktop/src/locales/ro/messages.json b/apps/desktop/src/locales/ro/messages.json new file mode 100644 index 0000000000..a15f2386b7 --- /dev/null +++ b/apps/desktop/src/locales/ro/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtre" + }, + "allItems": { + "message": "Toate elementele" + }, + "favorites": { + "message": "Favorite" + }, + "types": { + "message": "Tipuri" + }, + "typeLogin": { + "message": "Conectare" + }, + "typeCard": { + "message": "Card" + }, + "typeIdentity": { + "message": "Identitate" + }, + "typeSecureNote": { + "message": "Notă protejată" + }, + "folders": { + "message": "Dosare" + }, + "collections": { + "message": "Colecții" + }, + "searchVault": { + "message": "Căutare în seif" + }, + "addItem": { + "message": "Adăugare articol" + }, + "shared": { + "message": "Partajate" + }, + "share": { + "message": "Partajare" + }, + "moveToOrganization": { + "message": "Mutare la organizație" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ mutat la $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Alegeți o organizație la care doriți să mutați acest articol. Mutarea într-o organizație, transferă proprietatea asupra articolului către organizația respectivă. Nu veți mai fi proprietarul direct al acestui articol odată ce a fost mutat." + }, + "attachments": { + "message": "Atașamente" + }, + "viewItem": { + "message": "Afișare articol" + }, + "name": { + "message": "Denumire" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "URI nou" + }, + "username": { + "message": "Nume utilizator" + }, + "password": { + "message": "Parolă" + }, + "passphrase": { + "message": "Frază de acces" + }, + "editItem": { + "message": "Editare articol" + }, + "emailAddress": { + "message": "Adresă de e-mail" + }, + "verificationCodeTotp": { + "message": "Cod de verificare (TOTP)" + }, + "website": { + "message": "Sait web" + }, + "notes": { + "message": "Note" + }, + "customFields": { + "message": "Câmpuri particularizate" + }, + "launch": { + "message": "Lansare" + }, + "copyValue": { + "message": "Copiere valoare", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Se minimizează la copierea în clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Se minimizează când se copiază datele unui articol în clipboard." + }, + "toggleVisibility": { + "message": "Comutare vizibilitate" + }, + "toggleCollapse": { + "message": "Restrângere / Extindere", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Deținător card" + }, + "number": { + "message": "Număr card" + }, + "brand": { + "message": "Tip card" + }, + "expiration": { + "message": "Expirare" + }, + "securityCode": { + "message": "Cod de securitate (CVV/CVC)" + }, + "identityName": { + "message": "Nume identitate" + }, + "company": { + "message": "Companie" + }, + "ssn": { + "message": "Cod Numeric Personal" + }, + "passportNumber": { + "message": "Număr CI / Pașaport" + }, + "licenseNumber": { + "message": "Număr licență" + }, + "email": { + "message": "E-mail" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adresă" + }, + "premiumRequired": { + "message": "Este necesară versiunea Premium" + }, + "premiumRequiredDesc": { + "message": "Este necesar statutul de membru Premium pentru a utiliza această caracteristică." + }, + "errorOccurred": { + "message": "S-a produs o eroare." + }, + "error": { + "message": "Eroare" + }, + "january": { + "message": "ianuarie" + }, + "february": { + "message": "februarie" + }, + "march": { + "message": "martie" + }, + "april": { + "message": "aprilie" + }, + "may": { + "message": "mai" + }, + "june": { + "message": "iunie" + }, + "july": { + "message": "iulie" + }, + "august": { + "message": "august" + }, + "september": { + "message": "septembrie" + }, + "october": { + "message": "octombrie" + }, + "november": { + "message": "noiembrie" + }, + "december": { + "message": "decembrie" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titlu" + }, + "mr": { + "message": "Dl" + }, + "mrs": { + "message": "Dna" + }, + "ms": { + "message": "Dra" + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Luna expirării" + }, + "expirationYear": { + "message": "Anul expirării" + }, + "select": { + "message": "Selectare" + }, + "other": { + "message": "Altele" + }, + "generatePassword": { + "message": "Generare parolă" + }, + "type": { + "message": "Tip" + }, + "firstName": { + "message": "Prenume" + }, + "middleName": { + "message": "Al doilea prenume" + }, + "lastName": { + "message": "Nume" + }, + "fullName": { + "message": "Numele complet" + }, + "address1": { + "message": "Adresă 1" + }, + "address2": { + "message": "Adresă 2" + }, + "address3": { + "message": "Adresă 3" + }, + "cityTown": { + "message": "Localitate" + }, + "stateProvince": { + "message": "Județ" + }, + "zipPostalCode": { + "message": "Cod poștal" + }, + "country": { + "message": "Țară" + }, + "save": { + "message": "Salvare" + }, + "cancel": { + "message": "Anulare" + }, + "delete": { + "message": "Ștergere" + }, + "favorite": { + "message": "Favorit" + }, + "edit": { + "message": "Editare" + }, + "authenticatorKeyTotp": { + "message": "Cheie autentificare (TOTP)" + }, + "folder": { + "message": "Dosar" + }, + "newCustomField": { + "message": "Câmp nou particularizat" + }, + "value": { + "message": "Valoare" + }, + "dragToSort": { + "message": "Trageți pentru sortare" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Ascuns" + }, + "cfTypeBoolean": { + "message": "Valoare logică" + }, + "cfTypeLinked": { + "message": "Conectat", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Valoarea conectată", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Ștergere" + }, + "nameRequired": { + "message": "Numele utilizator este obligatoriu." + }, + "addedItem": { + "message": "Articol adăugat" + }, + "editedItem": { + "message": "Articol editat" + }, + "deleteItem": { + "message": "Ștergere articol" + }, + "deleteFolder": { + "message": "Ștergere dosar" + }, + "deleteAttachment": { + "message": "Ștergere atașament" + }, + "deleteItemConfirmation": { + "message": "Sigur doriți să trimiteți în coșul de reciclare?" + }, + "deletedItem": { + "message": "Articolul a fost trimis în coșul de reciclare" + }, + "overwritePasswordConfirmation": { + "message": "Sigur doriți să suprascrieți parola curentă?" + }, + "overwriteUsername": { + "message": "Suprascrieți numele de utilizator" + }, + "overwriteUsernameConfirmation": { + "message": "Sunteți sigur că doriți să suprascrieți numele de utilizator curent?" + }, + "noneFolder": { + "message": "Fără dosar", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Adăugare dosar" + }, + "editFolder": { + "message": "Editare dosar" + }, + "regeneratePassword": { + "message": "Regenerare parolă" + }, + "copyPassword": { + "message": "Copiere parolă" + }, + "copyUri": { + "message": "Copiere URI" + }, + "copyVerificationCodeTotp": { + "message": "Copiere cod de verificare (TOTP)" + }, + "length": { + "message": "Lungime" + }, + "numWords": { + "message": "Număr de cuvinte" + }, + "wordSeparator": { + "message": "Separator de cuvinte" + }, + "capitalize": { + "message": "Se folosesc majuscule inițiale", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Se includ cifre" + }, + "close": { + "message": "Închidere" + }, + "minNumbers": { + "message": "Minimum de cifre" + }, + "minSpecial": { + "message": "Minimum de caractere speciale", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Se evită caracterele ambigue" + }, + "searchCollection": { + "message": "Căutare în colecție" + }, + "searchFolder": { + "message": "Căutare în dosar" + }, + "searchFavorites": { + "message": "Căutare în favorite" + }, + "searchType": { + "message": "Căutare în tipuri", + "description": "Search item type" + }, + "newAttachment": { + "message": "Adăugare atașament nou" + }, + "deletedAttachment": { + "message": "Atașamentul s-a șters" + }, + "deleteAttachmentConfirmation": { + "message": "Sigur doriți să ștergeți acest atașament?" + }, + "attachmentSaved": { + "message": "Atașamentul a fost salvat." + }, + "file": { + "message": "Fișier" + }, + "selectFile": { + "message": "Selectare fișier." + }, + "maxFileSize": { + "message": "Mărimea maximă a fișierului este de 500 MB." + }, + "updateKey": { + "message": "Nu puteți utiliza această caracteristică înainte de a actualiza cheia de criptare." + }, + "editedFolder": { + "message": "Dosar editat" + }, + "addedFolder": { + "message": "Dosar adăugat" + }, + "deleteFolderConfirmation": { + "message": "Sigur doriți să ștergeți dosarul?" + }, + "deletedFolder": { + "message": "Dosar șters" + }, + "loginOrCreateNewAccount": { + "message": "Autentificați-vă sau creați un cont nou pentru a accesa seiful dvs. securizat." + }, + "createAccount": { + "message": "Creare cont" + }, + "logIn": { + "message": "Conectare" + }, + "submit": { + "message": "Trimitere" + }, + "masterPass": { + "message": "Parolă principală" + }, + "masterPassDesc": { + "message": "Parola principală este parola pe care o utilizați pentru a vă accesa seiful. Este foarte important să nu uitați această parolă. Nu există nicio modalitate de a recupera parola în cazul în care ați uitat-o." + }, + "masterPassHintDesc": { + "message": "Un indiciu pentru parola principală vă poate ajuta să v-o reamintiți dacă o uitați." + }, + "reTypeMasterPass": { + "message": "Reintroducere parolă principală" + }, + "masterPassHint": { + "message": "Indiciu pentru parola principală (opțional)" + }, + "settings": { + "message": "Setări" + }, + "passwordHint": { + "message": "Indiciu parolă" + }, + "enterEmailToGetHint": { + "message": "Adresa de e-mail a contului pentru primirea indiciului parolei principale." + }, + "getMasterPasswordHint": { + "message": "Obținere indiciu parolă principală" + }, + "emailRequired": { + "message": "Adresa de e-mail este necesară." + }, + "invalidEmail": { + "message": "Adresă de e-mail greșită." + }, + "masterPassRequired": { + "message": "Este parola principală este necesară." + }, + "masterPassLength": { + "message": "Parola principală trebuie să conțină minimum 8 caractere." + }, + "masterPassDoesntMatch": { + "message": "Parola principală și confirmarea ei nu coincid!" + }, + "newAccountCreated": { + "message": "Noul dvs. cont a fost creat! Acum vă puteți autentifica." + }, + "masterPassSent": { + "message": "V-am trimis un e-mail cu indiciul parolei principale." + }, + "unexpectedError": { + "message": "A survenit o eroare neașteptată." + }, + "itemInformation": { + "message": "Informații de autentificare" + }, + "noItemsInList": { + "message": "Niciun articol de afișat." + }, + "sendVerificationCode": { + "message": "Trimite un cod de verificare la adresa dvs. de e-mail" + }, + "sendCode": { + "message": "Trimitere cod" + }, + "codeSent": { + "message": "Cod trimis" + }, + "verificationCode": { + "message": "Cod de verificare" + }, + "confirmIdentity": { + "message": "Confirmați-vă identitatea pentru a continua." + }, + "verificationCodeRequired": { + "message": "Este necesar codul de verificare." + }, + "invalidVerificationCode": { + "message": "Cod de verificare nevalid" + }, + "continue": { + "message": "Continuare" + }, + "enterVerificationCodeApp": { + "message": "Introducere cod de verificare din 6 cifre din aplicația de autentificare." + }, + "enterVerificationCodeEmail": { + "message": "Introducere cod de verificare din 6 cifre care a fost trimis prin e-mail la $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "E-mailul de verificare a fost trimis la $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Memorare autentificare" + }, + "sendVerificationCodeEmailAgain": { + "message": "Retrimitere e-mail cu codul de verificare" + }, + "useAnotherTwoStepMethod": { + "message": "Utilizare de metodă diferită de autentificare în două etape" + }, + "insertYubiKey": { + "message": "Introduceți YubiKey în portul USB al calculatorului apoi atingeți butonul acestuia." + }, + "insertU2f": { + "message": "Introduceți cheia de securitate în portul USB al computerului. Dacă are un buton, apăsați-l." + }, + "recoveryCodeDesc": { + "message": "Ați pierdut accesul la toți furnizorii de autentificare în două etape? Utilizați codul de recuperare pentru a dezactiva toți acești furnizori din contul dvs." + }, + "recoveryCodeTitle": { + "message": "Cod de recuperare" + }, + "authenticatorAppTitle": { + "message": "Aplicație de autentificare" + }, + "authenticatorAppDesc": { + "message": "Utilizați o aplicație de autentificare (cum ar fi Authy sau Google Authenticator) pentru a genera codurile de verificare bazate pe timp.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Cheie de securitate YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Utilizați un YubiKey pentru a vă accesa contul. Funcționează cu dispozitivele YubiKey 4, 4 Nano, 4C și NEO." + }, + "duoDesc": { + "message": "Verificați cu Duo Security utilizând aplicația Duo Mobile, SMS, apel telefonic sau cheia de securitate U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verificați cu Duo Security pentru organizația dvs. utilizând aplicația Duo Mobile, SMS, apel telefonic sau cheia de securitate U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Utilizați orice cheie de securitate activată WebAuthn pentru a vă accesa contul." + }, + "emailTitle": { + "message": "E-mail" + }, + "emailDesc": { + "message": "Codurile de verificare vor fi trimise prin e-mail." + }, + "loginUnavailable": { + "message": "Conectare indisponibilă" + }, + "noTwoStepProviders": { + "message": "Acest cont are activată autentificarea în două etape, dar niciunul dintre furnizorii configurați pentru aceasta nu este acceptat pe acest dispozitiv." + }, + "noTwoStepProviders2": { + "message": "Adăugați furnizori suplimentari care sunt mai bine susținuți pe toate dispozitivele (cum ar fi o aplicație de autentificare)." + }, + "twoStepOptions": { + "message": "Opțiuni de autentificare în două etape" + }, + "selfHostedEnvironment": { + "message": "Mediu de găzduire personal" + }, + "selfHostedEnvironmentFooter": { + "message": "Specificați URL-ul de bază al implementări Bitwarden găzduită local." + }, + "customEnvironment": { + "message": "Mediu personalizat" + }, + "customEnvironmentFooter": { + "message": "Pentru utilizatorii avansați. Puteți specifica URL-ul de bază al fiecărui serviciu în mod independent." + }, + "baseUrl": { + "message": "URL server" + }, + "apiUrl": { + "message": "URL server API" + }, + "webVaultUrl": { + "message": "URL server seif Web" + }, + "identityUrl": { + "message": "URL server de identificare" + }, + "notificationsUrl": { + "message": "URL server de notificări" + }, + "iconsUrl": { + "message": "URL server de iconuri" + }, + "environmentSaved": { + "message": "URL-urile mediului au fost salvate." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Nu" + }, + "overwritePassword": { + "message": "Modificare parolă" + }, + "learnMore": { + "message": "Aflați mai multe" + }, + "featureUnavailable": { + "message": "Caracteristică indisponibilă" + }, + "loggedOut": { + "message": "Deconectat" + }, + "loginExpired": { + "message": "Sesiunea de autentificare a expirat." + }, + "logOutConfirmation": { + "message": "Sigur doriți să vă deconectați?" + }, + "logOut": { + "message": "Deconectare" + }, + "addNewLogin": { + "message": "Adăugare conectare nouă" + }, + "addNewItem": { + "message": "Adăugare element nou" + }, + "addNewFolder": { + "message": "Adăugare dosar nou" + }, + "view": { + "message": "Afișare" + }, + "account": { + "message": "Cont" + }, + "loading": { + "message": "Încărcare..." + }, + "lockVault": { + "message": "Blocare seif" + }, + "passwordGenerator": { + "message": "Generator de parole" + }, + "contactUs": { + "message": "Contactați-ne" + }, + "getHelp": { + "message": "Obținere ajutor" + }, + "fileBugReport": { + "message": "Înregistrare raport de erori" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Urmăriți-ne" + }, + "syncVault": { + "message": "Sincronizare seif" + }, + "changeMasterPass": { + "message": "Schimbare parolă principală" + }, + "changeMasterPasswordConfirmation": { + "message": "Puteți modifica parola principală pe saitul web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "fingerprintPhrase": { + "message": "Frază amprentă", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fraza amprentă a contului dvs.", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Accesare seif web" + }, + "getMobileApp": { + "message": "Obținere aplicație pentru mobil" + }, + "getBrowserExtension": { + "message": "Obținere extensie pentru browser" + }, + "syncingComplete": { + "message": "Sincronizare completă" + }, + "syncingFailed": { + "message": "Sincronizare eșuată" + }, + "yourVaultIsLocked": { + "message": "Seiful dvs. este blocat. Verificați-vă identitatea pentru a continua." + }, + "unlock": { + "message": "Deblocare" + }, + "loggedInAsOn": { + "message": "Autentificat ca $EMAIL$ pe $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Parolă principală incorectă" + }, + "twoStepLoginConfirmation": { + "message": "Autentificarea în două etape întărește siguranța contului dvs. prin solicitarea unei confirmări de autentificare cu un alt dispozitiv, cum ar fi: o cheie de securitate, o aplicație de autentificare, un SMS, un apel telefonic sau un e-mail. Autentificarea în două etape poate fi activată în seiful web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "twoStepLogin": { + "message": "Autentificare în două etape" + }, + "vaultTimeout": { + "message": "Expirare seif" + }, + "vaultTimeoutDesc": { + "message": "Alegeți când seiful dvs. va expira și va efectua acțiunea selectată." + }, + "immediately": { + "message": "Imediat" + }, + "tenSeconds": { + "message": "10 secunde" + }, + "twentySeconds": { + "message": "20 de secunde" + }, + "thirtySeconds": { + "message": "30 de secunde" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minute" + }, + "fiveMinutes": { + "message": "5 minute" + }, + "fifteenMinutes": { + "message": "15 minute" + }, + "thirtyMinutes": { + "message": "30 de minute" + }, + "oneHour": { + "message": "1 oră" + }, + "fourHours": { + "message": "4 ore" + }, + "onIdle": { + "message": "Când sistemul este inactiv" + }, + "onSleep": { + "message": "Când sistemul este în repaus" + }, + "onLocked": { + "message": "La blocarea sistemului" + }, + "onRestart": { + "message": "La repornire" + }, + "never": { + "message": "Niciodată" + }, + "security": { + "message": "Securitate" + }, + "clearClipboard": { + "message": "Golire clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Se șterg automat valorile copiate din clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Se dezactivează iconurile saiturilor" + }, + "disableFaviconDesc": { + "message": "Iconurile saiturilor oferă o imagine identificabilă lângă fiecare element de conectare din seiful dvs." + }, + "enableMinToTray": { + "message": "Se minimizează în zona de notificare" + }, + "enableMinToTrayDesc": { + "message": "La minimizarea ferestrei se afișează în schimb un icon în zona de notificare." + }, + "enableMinToMenuBar": { + "message": "Minimizați în bara de meniu" + }, + "enableMinToMenuBarDesc": { + "message": "La minimizarea ferestrei, se afișează un icon în bara de meniu." + }, + "enableCloseToTray": { + "message": "Se închide în zona de notificare" + }, + "enableCloseToTrayDesc": { + "message": "La închiderea ferestrei se afișează în schimb un icon în zona de notificare." + }, + "enableCloseToMenuBar": { + "message": "Închideți în bara de meniu" + }, + "enableCloseToMenuBarDesc": { + "message": "La închiderea ferestrei se afișează un icon în bara de meniu." + }, + "enableTray": { + "message": "Se activează un icon în zona de notificare" + }, + "enableTrayDesc": { + "message": "Se afișează întotdeauna un icon în zona de notificare." + }, + "startToTray": { + "message": "Se pornește în bara de notificări" + }, + "startToTrayDesc": { + "message": "Când aplicația este pornită, se afișează numai un icon în bara de notificări." + }, + "startToMenuBar": { + "message": "Pornire în bara de meniu" + }, + "startToMenuBarDesc": { + "message": "Când aplicația este pornită, se afișează numai un icon în bara de meniu." + }, + "openAtLogin": { + "message": "Pornire automată la conectare" + }, + "openAtLoginDesc": { + "message": "Pornește aplicația Bitwarden Desktop automat la autentificare." + }, + "alwaysShowDock": { + "message": "Se afișează întotdeauna în Dock" + }, + "alwaysShowDockDesc": { + "message": "Afișează pictograma Bitwarden în Dock chiar și atunci când este minimizată în bara de meniu." + }, + "confirmTrayTitle": { + "message": "Confirmați dezactivarea zonei de notificare" + }, + "confirmTrayDesc": { + "message": "Dezactivarea acestei setări va dezactiva, de asemenea, toate celelalte setări legate de zona de notificare." + }, + "language": { + "message": "Limbă" + }, + "languageDesc": { + "message": "Schimbă limba utilizată de aplicație. Este necesară repornirea." + }, + "theme": { + "message": "Temă" + }, + "themeDesc": { + "message": "Schimbă tema de culori a aplicației." + }, + "dark": { + "message": "Întunecat", + "description": "Dark color" + }, + "light": { + "message": "Luminos", + "description": "Light color" + }, + "copy": { + "message": "Copiere", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Căutare actualizări" + }, + "version": { + "message": "Versiunea $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Reporniți pentru actualizare" + }, + "restartToUpdateDesc": { + "message": "Versiunea $VERSION_NUM$ este gata pentru instalare. Trebuie să reporniți Bitwarden pentru a finaliza instalarea. Doriți să reporniți și să actualizați acum?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update disponibil" + }, + "updateAvailableDesc": { + "message": "A fost găsit un update. Doriți să îl descărcați acum?" + }, + "restart": { + "message": "Repornire" + }, + "later": { + "message": "Mai târziu" + }, + "noUpdatesAvailable": { + "message": "În prezent nu sunt disponibile actualizări. Folosiți cea mai recentă versiune." + }, + "updateError": { + "message": "Eroare la actualizare" + }, + "unknown": { + "message": "Necunoscut" + }, + "copyUsername": { + "message": "Copiere nume utilizator" + }, + "copyNumber": { + "message": "Copiere număr", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copiere cod de securitate", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Membru Premium" + }, + "premiumManage": { + "message": "Gestionare statut de membru" + }, + "premiumManageAlert": { + "message": "Vă puteți gestiona abonamentul pe seiful web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "premiumRefresh": { + "message": "Actualizare statut de membru" + }, + "premiumNotCurrentMember": { + "message": "În prezent nu sunteți un membru Premium." + }, + "premiumSignUpAndGet": { + "message": "Înscrieți-vă pentru statutul de membru Premium și obțineți:" + }, + "premiumSignUpStorage": { + "message": "1 GB spațiu de stocare criptat pentru atașamente de fișiere." + }, + "premiumSignUpTwoStep": { + "message": "Opțiuni adiționale de autentificare în două etape, cum ar fi YubiKey, FIDO U2F și Duo." + }, + "premiumSignUpReports": { + "message": "Rapoarte privind igiena parolelor, sănătatea contului și breșele de date pentru a vă păstra seiful în siguranță." + }, + "premiumSignUpTotp": { + "message": "Generatorul codului de verificare TOTP (2FA) pentru autentificările din seif." + }, + "premiumSignUpSupport": { + "message": "Asistență prioritară pentru clienți." + }, + "premiumSignUpFuture": { + "message": "Toate caracteristicile premium viitoare. Mai multe în curând!" + }, + "premiumPurchase": { + "message": "Achiziționare abonament Premium" + }, + "premiumPurchaseAlert": { + "message": "Puteți achiziționa un abonament premium pe saitul web bitwarden.com. Doriți să vizitați saitul acum?" + }, + "premiumCurrentMember": { + "message": "Sunteți un membru premium!" + }, + "premiumCurrentMemberThanks": { + "message": "Vă mulțumim pentru susținerea Bitwarden." + }, + "premiumPrice": { + "message": "Totul pentru doar $PRICE$ /an!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Reîmprospătare completă" + }, + "passwordHistory": { + "message": "Istoric parole" + }, + "clear": { + "message": "Ștergere", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Nicio parolă de afișat." + }, + "undo": { + "message": "Anulare" + }, + "redo": { + "message": "Refacere" + }, + "cut": { + "message": "Tăiere", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Lipire", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Selectare totală" + }, + "zoomIn": { + "message": "Mărire" + }, + "zoomOut": { + "message": "Micșorare" + }, + "resetZoom": { + "message": "Resetare Zoom" + }, + "toggleFullScreen": { + "message": "Comutare ecran complet" + }, + "reload": { + "message": "Reîncărcare" + }, + "toggleDevTools": { + "message": "Comutare instrumente de dezvoltare" + }, + "minimize": { + "message": "Minimizare", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Aducere tot în față", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Despre Bitwarden" + }, + "services": { + "message": "Servicii" + }, + "hideBitwarden": { + "message": "Ascundere Bitwarden" + }, + "hideOthers": { + "message": "Ascunde celelalte" + }, + "showAll": { + "message": "Afișare tot" + }, + "quitBitwarden": { + "message": "Închidere Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ s-a copiat", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Ajutor" + }, + "window": { + "message": "Fereastră" + }, + "checkPassword": { + "message": "Verificați dacă parola a fost dezvăluită." + }, + "passwordExposed": { + "message": "Această parolă a fost dezvăluită de $VALUE$ ori în breșe de date. Ar trebui să o schimbați.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Aceasta parola nu a fost găsită în nicio breșă de date cunoscută. Ar trebui să fie sigură de utilizat." + }, + "baseDomain": { + "message": "Domeniu de bază", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Nume de domeniu", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Gazdă", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Începe cu" + }, + "regEx": { + "message": "Expresie regulată", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Detectare de potrivire", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Detectare de potrivire implicită", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Activare/Dezactivare opțiuni" + }, + "organization": { + "message": "Organizație", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Prestabilită" + }, + "exit": { + "message": "Ieșire" + }, + "showHide": { + "message": "Afișare / Ascundere", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Ascunde în tava sistem" + }, + "alwaysOnTop": { + "message": "Mereu Deasupra", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "S-a actualizat", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parola s-a actualizat", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export seif" + }, + "fileFormat": { + "message": "Format fișier" + }, + "warning": { + "message": "AVERTISMENT", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirmare export seif" + }, + "exportWarningDesc": { + "message": "Acest export conține datele dvs. din seif în format necriptat. Nu ar trebui să stocați sau să trimiteți fișierul pe canale nesecurizate (cum ar fi e-mail). Ștergeți-l imediat după ce nu îl mai folosiți." + }, + "encExportKeyWarningDesc": { + "message": "Acest export criptează datele, utilizând cheia de criptare a contului. Dacă revocați vreodată cheia de criptare a contului dvs., ar trebui să exportați din nou, deoarece nu veți putea decripta acest fișier de export." + }, + "encExportAccountWarningDesc": { + "message": "Cheile de criptare a contului sunt unice fiecărui cont de utilizator Bitwarden, astfel încât nu puteți importa un export criptat într-un cont diferit." + }, + "noOrganizationsList": { + "message": "Nu aparțineți niciunei organizații. Organizațiile vă permit să partajați în siguranță articole cu alți utilizatori." + }, + "noCollectionsInList": { + "message": "Nicio colecție de afișat." + }, + "ownership": { + "message": "Proprietar" + }, + "whoOwnsThisItem": { + "message": "Cine deține acest element?" + }, + "strong": { + "message": "Puternică", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bună", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slabă", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Parolă principală slabă" + }, + "weakMasterPasswordDesc": { + "message": "Parola principală aleasă este slabă. Ar trebui să folosiți o parolă principală (sau o frază de acces) puternică pentru a vă proteja corespunzător contul Bitwarden. Sigur doriți să folosiți această parolă principală?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Deblocare cu codul PIN" + }, + "setYourPinCode": { + "message": "Stabiliți codul PIN de deblocare Bitwarden. Setările codului PIN vor fi reinițializate dacă vă deconectați vreodată din aplicație." + }, + "pinRequired": { + "message": "Codul PIN este necesar." + }, + "invalidPin": { + "message": "Cod PIN invalid." + }, + "unlockWithWindowsHello": { + "message": "Deblocare cu Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verificați pentru Bitwarden." + }, + "unlockWithTouchId": { + "message": "Deblocare cu Touch ID" + }, + "touchIdConsentMessage": { + "message": "deblocați-vă seiful" + }, + "noAutoPromptWindowsHello": { + "message": "Nu solicitați Windows Hello la pornire." + }, + "noAutoPromptTouchId": { + "message": "Nu solicitați Touch ID la pornire." + }, + "lockWithMasterPassOnRestart": { + "message": "Blocare cu parola principală la repornire" + }, + "preferences": { + "message": "Preferințe" + }, + "enableMenuBar": { + "message": "Activare icon în bara de meniu" + }, + "enableMenuBarDesc": { + "message": "Afișează întotdeauna un icon în bara de meniu." + }, + "hideToMenuBar": { + "message": "Ascunde în bara de meniu" + }, + "selectOneCollection": { + "message": "Trebuie să selectați cel puțin o colecție." + }, + "premiumUpdated": { + "message": "Ați trecut la Premium." + }, + "restore": { + "message": "Restabilire" + }, + "premiumManageAlertAppStore": { + "message": "Vă puteți gestiona abonamentul din App Store. Doriți să vizitați App Store acum?" + }, + "legal": { + "message": "Termeni legali", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Termeni de utilizare" + }, + "privacyPolicy": { + "message": "Politică de confidențialitate" + }, + "unsavedChangesConfirmation": { + "message": "Sigur doriți să renunțați la modificări? Dacă renunțați, informațiile dvs. actuale nu vor fi salvate." + }, + "unsavedChangesTitle": { + "message": "Modificări nesalvate" + }, + "clone": { + "message": "Clonare" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Una sau mai multe politici organizaționale vă afectează setările generatorului." + }, + "vaultTimeoutAction": { + "message": "Acțiune la expirarea seifului" + }, + "vaultTimeoutActionLockDesc": { + "message": "Un seif blocat necesită reintroducerea parolei principale pentru a-l accesa din nou." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Un seif deconectat necesită reintroducerea parolei principale pentru a-l accesa din nou." + }, + "lock": { + "message": "Blocare", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Coș de reciclare", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Căutare în coșul de reciclare" + }, + "permanentlyDeleteItem": { + "message": "Ștergere definitivă a articolului" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Sigur doriți să ștergeți definitiv acest articol?" + }, + "permanentlyDeletedItem": { + "message": "Articolul a fost șters definitiv" + }, + "restoreItem": { + "message": "Restabilire articol" + }, + "restoreItemConfirmation": { + "message": "Sigur doriți să restabiliți acest articol?" + }, + "restoredItem": { + "message": "Articol restabilit" + }, + "permanentlyDelete": { + "message": "Ștergere definitivă" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "După expirare, accesul la seiful dvs. va fi restricționat și va fi necesară autentificarea online. Sigur doriți să utilizați această setare?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Confirmare acțiune la expirare" + }, + "enterpriseSingleSignOn": { + "message": "Conectare unică organizație (SSO)" + }, + "setMasterPassword": { + "message": "Setare parolă principală" + }, + "ssoCompleteRegistration": { + "message": "Pentru a finaliza conectarea cu SSO, vă rugăm să setați o parolă principală pentru a vă accesa și proteja seiful." + }, + "newMasterPass": { + "message": "Parolă principală nouă" + }, + "confirmNewMasterPass": { + "message": "Confirmați noua parolă principală" + }, + "masterPasswordPolicyInEffect": { + "message": "Una sau mai multe politici ale organizației necesită ca parola principală să îndeplinească următoarele cerințe:" + }, + "policyInEffectMinComplexity": { + "message": "Scor minim de complexitate de $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Lungime minimă de $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Unul sau mai multe caractere majuscule" + }, + "policyInEffectLowercase": { + "message": "Unul sau mai multe caractere minuscule" + }, + "policyInEffectNumbers": { + "message": "Una sau mai multe cifre" + }, + "policyInEffectSpecial": { + "message": "Unul sau mai multe din următoarele caractere: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Noua dvs. parolă principală nu îndeplinește cerințele politicii." + }, + "acceptPolicies": { + "message": "Dacă bifați această casetă sunteți de acord cu următoarele:" + }, + "acceptPoliciesError": { + "message": "Termeni de utilizare și Politica de confidențialitate nu au fost recunoscute." + }, + "enableBrowserIntegration": { + "message": "Activați integrarea browserului" + }, + "enableBrowserIntegrationDesc": { + "message": "Integrarea browserului este folosită pentru biometria în browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Integrarea browserului nu este acceptată" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Din păcate, integrarea browserului este acceptată numai în versiunea Mac App Store pentru moment." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Integrarea browserului nu este acceptată" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Din păcate, integrarea browserului nu este acceptată în prezent în versiunea Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Necesită verificare pentru integrarea browserului" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Activează un nivel suplimentar de securitate prin solicitarea validării frazei de amprentă la stabilirea unei legături între desktop și browser. Când este activată, aceasta necesită intervenția utilizatorului și verificarea de fiecare dată când este stabilită o conexiune." + }, + "approve": { + "message": "Aprobați" + }, + "verifyBrowserTitle": { + "message": "Verificați conexiunea browserului" + }, + "verifyBrowserDesc": { + "message": "Vă rugăm să vă asigurați că amprenta afișată este identică cu amprenta indicată în extensia browserului." + }, + "biometricsNotEnabledTitle": { + "message": "Biometria nu a fost activată" + }, + "biometricsNotEnabledDesc": { + "message": "Biometria browserului necesită activarea mai întâi a biometriei de pe desktop în setări." + }, + "personalOwnershipSubmitError": { + "message": "Datorită unei politici pentru întreprinderi, vă este restricționată salvarea de elemente în seiful dvs. personal. Schimbați opțiunea de proprietate la o organizație și alegeți dintre colecțiile disponibile." + }, + "hintEqualsPassword": { + "message": "Indiciul dvs. de parolă nu poate fi același cu parola dvs." + }, + "personalOwnershipPolicyInEffect": { + "message": "O politică de organizație vă afectează opțiunile de proprietate." + }, + "allSends": { + "message": "Toate Send-urile", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fișier" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Căutare Send-uri", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Editare Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Seiful meu" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Data ștergerii" + }, + "deletionDateDesc": { + "message": "Send-ul va fi șters definitiv la data și ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Data expirării" + }, + "expirationDateDesc": { + "message": "Dacă este setat, accesul la acest Send va expira la data și ora specificate.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Număr maxim de accesări" + }, + "maxAccessCountDesc": { + "message": "Dacă este configurat, utilizatorii nu vor mai putea accesa acest Send când a fost atins numărul maxim de accesări.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Număr actual de accesări" + }, + "disableSend": { + "message": "Dezactivați acest Send astfel încât nimeni să nu-l poată accesa.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Opțional, este necesară o parolă pentru ca utilizatorii să acceseze acest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Note private despre acest Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Link Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Link Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Când Send-ul este accesat, ascundeți textul în mod implicit", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send creat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send editat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send șters", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Parolă nouă" + }, + "whatTypeOfSend": { + "message": "Ce fel de Send este acesta?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Creare de Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Textul pe care doriți să-l trimiteți." + }, + "sendFileDesc": { + "message": "Fișierul pe care doriți să-l trimiteți." + }, + "days": { + "message": "$DAYS$ zile", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 zi" + }, + "custom": { + "message": "Personalizat" + }, + "deleteSendConfirmation": { + "message": "Sigur doriți să ștergeți acest Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copiați link-ul Send-ului în clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copiați în clipboard linkul pentru partajarea acestui Send după salvare." + }, + "sendDisabled": { + "message": "Send dezactivat", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Datorită unei politici de întreprindere, puteți șterge numai un Send existent.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copiere link" + }, + "disabled": { + "message": "Dezactivat" + }, + "maxAccessCountReached": { + "message": "S-a atins numărul maxim de accesări" + }, + "expired": { + "message": "Expirat" + }, + "pendingDeletion": { + "message": "Ștergere în așteptare" + }, + "webAuthnAuthenticate": { + "message": "Autentificare WebAuthn" + }, + "hideEmail": { + "message": "Ascundeți adresa mea de e-mail de la destinatari." + }, + "sendOptionsPolicyInEffect": { + "message": "Una sau mai multe politici organizaționale vă afectează opțiunile Send-ului." + }, + "emailVerificationRequired": { + "message": "Este necesară verificarea adresei de e-mail" + }, + "emailVerificationRequiredDesc": { + "message": "Trebuie să vă verificați e-mailul pentru a utiliza această caracteristică." + }, + "passwordPrompt": { + "message": "Re-solicitare parolă principală" + }, + "passwordConfirmation": { + "message": "Confirmare parolă principală" + }, + "passwordConfirmationDesc": { + "message": "Această acțiune este protejată. Pentru a continua, vă rugăm să reintroduceți parola principală pentru a vă verifica identitatea." + }, + "updatedMasterPassword": { + "message": "Parolă principală actualizată" + }, + "updateMasterPassword": { + "message": "Actualizare parolă principală" + }, + "updateMasterPasswordWarning": { + "message": "Parola dvs. principală a fost modificată recent de unul din administratorii organizației dvs. Pentru a accesa seiful, trebuie să o actualizați acum. Procedura vă va deconecta de la sesiunea curentă, necesitând să vă reconectați. Sesiunile active de pe alte dispozitive pot continua să rămână active timp de până la o oră." + }, + "hours": { + "message": "Ore" + }, + "minutes": { + "message": "Minute" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Politicile organizației dvs vă afectează expirarea seifului. Timpul maxim permis de expirare a seifului este $HOURS$ oră (ore) și $MINUTES$ minut(e)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Timpul de expirare a seifului depășește restricțiile stabilite de organizația dvs." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Înregistrare automată" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Această organizație are o politică de întreprindere care vă va înregistra automat la resetarea parolei. Înregistrarea va permite administratorilor organizației să vă modifice parola principală." + }, + "vaultExportDisabled": { + "message": "Export de seif dezactivat" + }, + "personalVaultExportPolicyInEffect": { + "message": "Una sau mai multe politici ale organizației vă împiedică să exportați seiful personal." + }, + "addAccount": { + "message": "Adăugare cont" + }, + "removeMasterPassword": { + "message": "Eliminare parolă principală" + }, + "removedMasterPassword": { + "message": "Parolă principală eliminată." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ folosește SSO cu un server de chei auto-găzduit. Membrii acestei organizații nu mai au nevoie de o parolă principală pentru autentificare.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Părăsire organizație" + }, + "leaveOrganizationConfirmation": { + "message": "Sigur doriți să părăsiți această organizație?" + }, + "leftOrganization": { + "message": "Ați părăsit organizația." + }, + "ssoKeyConnectorUnavailable": { + "message": "Nu se poate accesa Conectorul Cheie, vă rugăm să încercați din nou mai târziu." + }, + "lockAllVaults": { + "message": "Blocare toate seifurile" + }, + "accountLimitReached": { + "message": "Nu pot fi conectate mai mult de 5 conturi în același timp." + }, + "accountPreferences": { + "message": "Preferințe" + }, + "appPreferences": { + "message": "Setări aplicație (toate conturile)" + }, + "accountSwitcherLimitReached": { + "message": "Limita contului a fost atinsă. Ieșiți dintr-un cont pentru a adăuga un altul." + }, + "settingsTitle": { + "message": "Setările aplicației pentru $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Schimbați contul" + }, + "options": { + "message": "Opțiuni" + }, + "sessionTimeout": { + "message": "Sesiunea dvs. a expirat. Vă rugăm reveniți și încercați să vă autentificați din nou." + }, + "exportingPersonalVaultTitle": { + "message": "Exportarea seifului personal" + }, + "exportingPersonalVaultDescription": { + "message": "Numai elementele personale din seif asociate cu $EMAIL$ vor fi exportate. Elementele seifului organizației nu vor fi incluse.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "Ce doriți să generați?" + }, + "passwordType": { + "message": "Tip de parolă" + }, + "regenerateUsername": { + "message": "Regenerare nume de utilizator" + }, + "generateUsername": { + "message": "Generare nume de utilizator" + }, + "usernameType": { + "message": "Tip de nume de utilizator" + }, + "plusAddressedEmail": { + "message": "Plus e-mail adresat" + }, + "plusAddressedEmailDesc": { + "message": "Utilizați capacitățile de subadresare ale furnizorului dvs. de e-mail." + }, + "catchallEmail": { + "message": "E-mail Catch-all" + }, + "catchallEmailDesc": { + "message": "Utilizați inbox-ul catch-all configurat pentru domeniul dvs." + }, + "random": { + "message": "Aleatoriu" + }, + "randomWord": { + "message": "Cuvânt aleatoriu" + }, + "websiteName": { + "message": "Numele site-ului web" + }, + "service": { + "message": "Serviciu" + } +} diff --git a/apps/desktop/src/locales/ru/messages.json b/apps/desktop/src/locales/ru/messages.json new file mode 100644 index 0000000000..b6b31c2e07 --- /dev/null +++ b/apps/desktop/src/locales/ru/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Фильтры" + }, + "allItems": { + "message": "Все элементы" + }, + "favorites": { + "message": "Избранные" + }, + "types": { + "message": "Типы элементов" + }, + "typeLogin": { + "message": "Логин" + }, + "typeCard": { + "message": "Карта" + }, + "typeIdentity": { + "message": "Личная информация" + }, + "typeSecureNote": { + "message": "Защищенная заметка" + }, + "folders": { + "message": "Папки" + }, + "collections": { + "message": "Коллекции" + }, + "searchVault": { + "message": "Поиск в хранилище" + }, + "addItem": { + "message": "Добавить элемент" + }, + "shared": { + "message": "Общие" + }, + "share": { + "message": "Поделиться" + }, + "moveToOrganization": { + "message": "Переместить в организацию" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ перемещен в $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Выберите организацию, в которую вы хотите переместить этот элемент. При перемещении в организацию право собственности на элемент переходит к этой организации. Вы больше не будете прямым владельцем этого элемента после его перемещения." + }, + "attachments": { + "message": "Вложения" + }, + "viewItem": { + "message": "Просмотр элемента" + }, + "name": { + "message": "Название" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Новый URI" + }, + "username": { + "message": "Имя пользователя" + }, + "password": { + "message": "Пароль" + }, + "passphrase": { + "message": "Парольная фраза" + }, + "editItem": { + "message": "Изменение элемента" + }, + "emailAddress": { + "message": "Адрес email" + }, + "verificationCodeTotp": { + "message": "Код подтверждения (TOTP)" + }, + "website": { + "message": "Веб-сайт" + }, + "notes": { + "message": "Заметки" + }, + "customFields": { + "message": "Пользовательские поля" + }, + "launch": { + "message": "Перейти" + }, + "copyValue": { + "message": "Скопировать значение", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Свернуть после копирования в буфер обмена" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Сворачивать после копирования данных элемента в буфер обмена." + }, + "toggleVisibility": { + "message": "Вкл/выкл видимость" + }, + "toggleCollapse": { + "message": "Свернуть/развернуть", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Имя владельца карты" + }, + "number": { + "message": "Номер" + }, + "brand": { + "message": "Тип карты" + }, + "expiration": { + "message": "Срок действия" + }, + "securityCode": { + "message": "Код безопасности" + }, + "identityName": { + "message": "Имя" + }, + "company": { + "message": "Компания" + }, + "ssn": { + "message": "Номер социального страхования" + }, + "passportNumber": { + "message": "Номер паспорта" + }, + "licenseNumber": { + "message": "ИНН" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адрес" + }, + "premiumRequired": { + "message": "Требуется Премиум" + }, + "premiumRequiredDesc": { + "message": "Для использования этой функции требуется Премиум." + }, + "errorOccurred": { + "message": "Произошла ошибка." + }, + "error": { + "message": "Ошибка" + }, + "january": { + "message": "Январь" + }, + "february": { + "message": "Февраль" + }, + "march": { + "message": "Март" + }, + "april": { + "message": "Апрель" + }, + "may": { + "message": "Май" + }, + "june": { + "message": "Июнь" + }, + "july": { + "message": "Июль" + }, + "august": { + "message": "Август" + }, + "september": { + "message": "Сентябрь" + }, + "october": { + "message": "Октябрь" + }, + "november": { + "message": "Ноябрь" + }, + "december": { + "message": "Декабрь" + }, + "ex": { + "message": "напр.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Обращение" + }, + "mr": { + "message": "Г-н" + }, + "mrs": { + "message": "Г-жа" + }, + "ms": { + "message": "Проф." + }, + "dr": { + "message": "Тов." + }, + "expirationMonth": { + "message": "Месяц" + }, + "expirationYear": { + "message": "Год" + }, + "select": { + "message": "Выбрать" + }, + "other": { + "message": "Прочее" + }, + "generatePassword": { + "message": "Сгенерировать пароль" + }, + "type": { + "message": "Тип" + }, + "firstName": { + "message": "Имя" + }, + "middleName": { + "message": "Отчество" + }, + "lastName": { + "message": "Фамилия" + }, + "fullName": { + "message": "Полное имя" + }, + "address1": { + "message": "Строка адреса 1" + }, + "address2": { + "message": "Строка адреса 2" + }, + "address3": { + "message": "Строка адреса 3" + }, + "cityTown": { + "message": "Город/поселок" + }, + "stateProvince": { + "message": "Регион/область" + }, + "zipPostalCode": { + "message": "Почтовый индекс" + }, + "country": { + "message": "Страна" + }, + "save": { + "message": "Сохранить" + }, + "cancel": { + "message": "Отмена" + }, + "delete": { + "message": "Удалить" + }, + "favorite": { + "message": "Избранный" + }, + "edit": { + "message": "Правка" + }, + "authenticatorKeyTotp": { + "message": "Ключ проверки подлинности (TOTP)" + }, + "folder": { + "message": "Папка" + }, + "newCustomField": { + "message": "Новое пользовательское поле" + }, + "value": { + "message": "Значение" + }, + "dragToSort": { + "message": "Перетащите для сортировки" + }, + "cfTypeText": { + "message": "Текстовое" + }, + "cfTypeHidden": { + "message": "Скрытое" + }, + "cfTypeBoolean": { + "message": "Логическое" + }, + "cfTypeLinked": { + "message": "Связано", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Связанное значение", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Удалить" + }, + "nameRequired": { + "message": "Требуется имя." + }, + "addedItem": { + "message": "Элемент добавлен" + }, + "editedItem": { + "message": "Элемент изменен" + }, + "deleteItem": { + "message": "Удалить элемент" + }, + "deleteFolder": { + "message": "Удалить папку" + }, + "deleteAttachment": { + "message": "Удалить вложение" + }, + "deleteItemConfirmation": { + "message": "Вы действительно хотите отправить в корзину?" + }, + "deletedItem": { + "message": "Элемент отправлен в корзину" + }, + "overwritePasswordConfirmation": { + "message": "Вы уверены, что хотите переписать текущий пароль?" + }, + "overwriteUsername": { + "message": "Перезаписать имя пользователя" + }, + "overwriteUsernameConfirmation": { + "message": "Вы хотите перезаписать текущее имя пользователя?" + }, + "noneFolder": { + "message": "Без папки", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Добавить папку" + }, + "editFolder": { + "message": "Изменить папку" + }, + "regeneratePassword": { + "message": "Создать новый пароль" + }, + "copyPassword": { + "message": "Скопировать пароль" + }, + "copyUri": { + "message": "Скопировать URI" + }, + "copyVerificationCodeTotp": { + "message": "Скопировать код подтверждения (TOTP)" + }, + "length": { + "message": "Длина" + }, + "numWords": { + "message": "Количество слов" + }, + "wordSeparator": { + "message": "Разделитель слов" + }, + "capitalize": { + "message": "С заглавной буквы", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Добавить цифру" + }, + "close": { + "message": "Закрыть" + }, + "minNumbers": { + "message": "Минимум цифр" + }, + "minSpecial": { + "message": "Минимум символов", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Избегать неоднозначных символов" + }, + "searchCollection": { + "message": "Поиск в коллекции" + }, + "searchFolder": { + "message": "Поиск в папке" + }, + "searchFavorites": { + "message": "Поиск в избранном" + }, + "searchType": { + "message": "Поиск по типу", + "description": "Search item type" + }, + "newAttachment": { + "message": "Добавить новое вложение" + }, + "deletedAttachment": { + "message": "Вложение удалено" + }, + "deleteAttachmentConfirmation": { + "message": "Вы действительно хотите удалить это вложение?" + }, + "attachmentSaved": { + "message": "Вложение сохранено." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Выберите файл." + }, + "maxFileSize": { + "message": "Максимальный размер файла 500 МБ." + }, + "updateKey": { + "message": "Вы не можете использовать эту функцию, пока не обновите свой ключ шифрования." + }, + "editedFolder": { + "message": "Папка отредактирована" + }, + "addedFolder": { + "message": "Папка добавлена" + }, + "deleteFolderConfirmation": { + "message": "Вы хотите удалить эту папку?" + }, + "deletedFolder": { + "message": "Папка удалена" + }, + "loginOrCreateNewAccount": { + "message": "Войдите или создайте новый аккаунт для доступа к вашему защищенному хранилищу." + }, + "createAccount": { + "message": "Создать аккаунт" + }, + "logIn": { + "message": "Войти" + }, + "submit": { + "message": "Отправить" + }, + "masterPass": { + "message": "Мастер-пароль" + }, + "masterPassDesc": { + "message": "Мастер-пароль – это ключ к вашему защищенному хранилищу. Он очень важен, поэтому не забывайте его. Восстановить мастер-пароль невозможно." + }, + "masterPassHintDesc": { + "message": "Подсказка к мастер-паролю может помочь вам его вспомнить." + }, + "reTypeMasterPass": { + "message": "Введите мастер-пароль повторно" + }, + "masterPassHint": { + "message": "Подсказка к мастер-паролю (необяз.)" + }, + "settings": { + "message": "Настройки" + }, + "passwordHint": { + "message": "Подсказка к паролю" + }, + "enterEmailToGetHint": { + "message": "Введите email аккаунта для получения подсказки к мастер-паролю." + }, + "getMasterPasswordHint": { + "message": "Получить подсказку к мастер-паролю" + }, + "emailRequired": { + "message": "Необходимо указать email." + }, + "invalidEmail": { + "message": "Неверный адрес email." + }, + "masterPassRequired": { + "message": "Требуется мастер-пароль." + }, + "masterPassLength": { + "message": "Мастер-пароль должен содержать не менее 8 символов." + }, + "masterPassDoesntMatch": { + "message": "Мастер-пароли не совпадают." + }, + "newAccountCreated": { + "message": "Аккаунт создан! Теперь вы можете войти в систему." + }, + "masterPassSent": { + "message": "Мы отправили вам письмо с подсказкой к мастер-паролю." + }, + "unexpectedError": { + "message": "Произошла непредвиденная ошибка." + }, + "itemInformation": { + "message": "Информация об элементе" + }, + "noItemsInList": { + "message": "Нет элементов для отображения." + }, + "sendVerificationCode": { + "message": "Отправить код подтверждения на ваш email" + }, + "sendCode": { + "message": "Отправить код" + }, + "codeSent": { + "message": "Код отправлен" + }, + "verificationCode": { + "message": "Код подтверждения" + }, + "confirmIdentity": { + "message": "Подтвердите вашу личность, чтобы продолжить." + }, + "verificationCodeRequired": { + "message": "Необходим код подтверждения." + }, + "invalidVerificationCode": { + "message": "Неверный код подтверждения" + }, + "continue": { + "message": "Продолжить" + }, + "enterVerificationCodeApp": { + "message": "Введите 6-значный код подтверждения из вашего приложения-аутентификатора." + }, + "enterVerificationCodeEmail": { + "message": "Введите 6-значный код подтверждения, который был отправлен на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Отправлено письмо подтверждения на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запомнить меня" + }, + "sendVerificationCodeEmailAgain": { + "message": "Отправить код подтверждения еще раз" + }, + "useAnotherTwoStepMethod": { + "message": "Использовать другой метод двухфакторной аутентификации" + }, + "insertYubiKey": { + "message": "Вставьте свой YubiKey в USB-порт компьютера и нажмите его кнопку." + }, + "insertU2f": { + "message": "Вставьте ключ безопасности в USB-порт компьютера. Если у ключа есть кнопка, нажмите ее." + }, + "recoveryCodeDesc": { + "message": "Потеряли доступ ко всем вариантам двухфакторной аутентификации? Используйте код восстановления, чтобы отключить ее для вашего аккаунта." + }, + "recoveryCodeTitle": { + "message": "Код восстановления" + }, + "authenticatorAppTitle": { + "message": "Приложение-аутентификатор" + }, + "authenticatorAppDesc": { + "message": "Используйте приложение-аутентификатор (например Authy или Google Authenticator) для создания кодов проверки на основе времени.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Ключ безопасности YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Используйте YubiKey для доступа к аккаунту. Работает с устройствами YubiKey серий 4, 5 и NEO." + }, + "duoDesc": { + "message": "Подтвердите с помощью Duo Security, используя приложение Duo Mobile, SMS, телефонный звонок или ключ безопасности U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Подтвердите с помощью Duo Security для вашей организации, используя приложение Duo Mobile, SMS, телефонный звонок или ключ безопасности U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Используйте любой ключ безопасности с поддержкой WebAuthn для доступа к своей учетной записи." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Коды подтверждения будут отправлены вам по электронной почте." + }, + "loginUnavailable": { + "message": "Вход недоступен" + }, + "noTwoStepProviders": { + "message": "У этой учетной записи включена двухфакторная аутентификация, однако ни один из настроенных вариантов не поддерживается этим устройством." + }, + "noTwoStepProviders2": { + "message": "Добавьте дополнительные варианты аутентификации, которые поддерживаются большинством устройств (например приложение-аутентификатор)." + }, + "twoStepOptions": { + "message": "Настройки двухфакторной аутентификации" + }, + "selfHostedEnvironment": { + "message": "Среда собственного хостинга" + }, + "selfHostedEnvironmentFooter": { + "message": "Укажите URL-адрес Bitwarden на вашем сервере." + }, + "customEnvironment": { + "message": "Пользовательское окружение" + }, + "customEnvironmentFooter": { + "message": "Для опытных пользователей. Можно указать URL отдельно для каждой службы." + }, + "baseUrl": { + "message": "URL-адрес сервера" + }, + "apiUrl": { + "message": "API URL-адреса сервера" + }, + "webVaultUrl": { + "message": "URL-адрес сервера веб-хранилища" + }, + "identityUrl": { + "message": "URL-адрес сервера идентификации" + }, + "notificationsUrl": { + "message": "URL-адрес сервера уведомлений" + }, + "iconsUrl": { + "message": "URL-адрес сервера значков" + }, + "environmentSaved": { + "message": "URL-адреса среды сохранены." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Да" + }, + "no": { + "message": "Нет" + }, + "overwritePassword": { + "message": "Перезаписать пароль" + }, + "learnMore": { + "message": "Подробнее" + }, + "featureUnavailable": { + "message": "Функция недоступна" + }, + "loggedOut": { + "message": "Вы вышли из хранилища" + }, + "loginExpired": { + "message": "Истек срок действия вашей сессии." + }, + "logOutConfirmation": { + "message": "Вы действительно хотите выйти?" + }, + "logOut": { + "message": "Выйти" + }, + "addNewLogin": { + "message": "Добавить новый логин" + }, + "addNewItem": { + "message": "Добавить новый элемент" + }, + "addNewFolder": { + "message": "Добавить новую папку" + }, + "view": { + "message": "Вид" + }, + "account": { + "message": "Аккаунт" + }, + "loading": { + "message": "Загрузка..." + }, + "lockVault": { + "message": "Заблокировать хранилище" + }, + "passwordGenerator": { + "message": "Генератор паролей" + }, + "contactUs": { + "message": "Связаться с нами" + }, + "getHelp": { + "message": "Получить помощь" + }, + "fileBugReport": { + "message": "Сообщить об ошибке" + }, + "blog": { + "message": "Блог" + }, + "followUs": { + "message": "Мы в соцсетях" + }, + "syncVault": { + "message": "Синхронизировать хранилище" + }, + "changeMasterPass": { + "message": "Изменить мастер-пароль" + }, + "changeMasterPasswordConfirmation": { + "message": "Вы можете изменить свой мастер-пароль на bitwarden.com. Перейти на сайт сейчас?" + }, + "fingerprintPhrase": { + "message": "Фраза отпечатка", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Фраза отпечатка вашего аккаунта", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Перейти в веб-хранилище" + }, + "getMobileApp": { + "message": "Мобильное приложение" + }, + "getBrowserExtension": { + "message": "Расширение для браузера" + }, + "syncingComplete": { + "message": "Синхронизация завершена" + }, + "syncingFailed": { + "message": "Ошибка синхронизации" + }, + "yourVaultIsLocked": { + "message": "Ваше xранилище заблокировано. Подтвердите свою личность для продолжения." + }, + "unlock": { + "message": "Разблокировать" + }, + "loggedInAsOn": { + "message": "Выполнен вход на $HOSTNAME$ как $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Неверный мастер-пароль" + }, + "twoStepLoginConfirmation": { + "message": "Двухфакторная аутентификация делает ваш аккаунт более защищенным, требуя подтверждения входа на другом устройстве, например, ключом безопасности, приложением-аутентификатором, SMS, телефонным звонком или письмом. Двухфакторная аутентификация включается на bitwarden.com. Перейти на сайт сейчас?" + }, + "twoStepLogin": { + "message": "Двухфакторная аутентификация" + }, + "vaultTimeout": { + "message": "Тайм-аут хранилища" + }, + "vaultTimeoutDesc": { + "message": "Выберите тайм-аут для хранилища и действие, которое необходимо предпринять." + }, + "immediately": { + "message": "Немедленно" + }, + "tenSeconds": { + "message": "10 секунд" + }, + "twentySeconds": { + "message": "20 секунд" + }, + "thirtySeconds": { + "message": "30 секунд" + }, + "oneMinute": { + "message": "1 минута" + }, + "twoMinutes": { + "message": "2 минуты" + }, + "fiveMinutes": { + "message": "5 минут" + }, + "fifteenMinutes": { + "message": "15 минут" + }, + "thirtyMinutes": { + "message": "30 минут" + }, + "oneHour": { + "message": "1 час" + }, + "fourHours": { + "message": "4 часа" + }, + "onIdle": { + "message": "При бездействии" + }, + "onSleep": { + "message": "В режиме сна" + }, + "onLocked": { + "message": "Вместе с компьютером" + }, + "onRestart": { + "message": "При перезапуске" + }, + "never": { + "message": "Никогда" + }, + "security": { + "message": "Безопасность" + }, + "clearClipboard": { + "message": "Очистка буфера обмена", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Автоматически очищать скопированные значения в вашем буфере обмена.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Отключить значки веб-сайтов" + }, + "disableFaviconDesc": { + "message": "Значки веб-сайтов отображаются рядом с каждым элементом в вашем хранилище." + }, + "enableMinToTray": { + "message": "Сворачивать в область уведомлений" + }, + "enableMinToTrayDesc": { + "message": "При сворачивании окна будет отображаться значок в области уведомлений." + }, + "enableMinToMenuBar": { + "message": "Свернуть в панель меню" + }, + "enableMinToMenuBarDesc": { + "message": "При сворачивании окна будет отображен значок в панели меню." + }, + "enableCloseToTray": { + "message": "Закрывать в область уведомлений" + }, + "enableCloseToTrayDesc": { + "message": "При закрытии окна будет отображаться значок в области уведомлений." + }, + "enableCloseToMenuBar": { + "message": "Закрыть в панель меню" + }, + "enableCloseToMenuBarDesc": { + "message": "При закрытии окна будет отображен значок в панели меню." + }, + "enableTray": { + "message": "Включить значок в области уведомлений" + }, + "enableTrayDesc": { + "message": "Всегда отображать значок в области уведомлений." + }, + "startToTray": { + "message": "Запускать свернутым в область уведомлений" + }, + "startToTrayDesc": { + "message": "При первом запуске приложения будет отображаться только значок в области уведомлений." + }, + "startToMenuBar": { + "message": "Запускать в панели меню" + }, + "startToMenuBarDesc": { + "message": "При первом запуске приложения будет отображаться только значок в панели меню." + }, + "openAtLogin": { + "message": "Запускать автоматически при входе в систему" + }, + "openAtLoginDesc": { + "message": "Автоматически запускать приложение Bitwarden для компьютера при входе в систему." + }, + "alwaysShowDock": { + "message": "Всегда показывать в Dock" + }, + "alwaysShowDockDesc": { + "message": "Показывать значок Bitwarden на панели Dock, даже если он свернут в панель меню." + }, + "confirmTrayTitle": { + "message": "Подтвердить отключение области уведомлений" + }, + "confirmTrayDesc": { + "message": "Отключение этого параметра также отключит все прочие настройки, связанные с областью уведомлений." + }, + "language": { + "message": "Язык" + }, + "languageDesc": { + "message": "Изменение языка приложения. Потребуется перезапуск." + }, + "theme": { + "message": "Тема" + }, + "themeDesc": { + "message": "Изменение цветовой темы приложения." + }, + "dark": { + "message": "Темная", + "description": "Dark color" + }, + "light": { + "message": "Светлая", + "description": "Light color" + }, + "copy": { + "message": "Скопировать", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Проверка наличия обновлений" + }, + "version": { + "message": "Версия $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Перезапуск для обновления" + }, + "restartToUpdateDesc": { + "message": "Версия $VERSION_NUM$ готова к установке. Для завершения установки необходимо перезапустить Bitwarden. Сделать это сейчас?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Доступно обновление" + }, + "updateAvailableDesc": { + "message": "Найдено обновление. Загрузить его сейчас?" + }, + "restart": { + "message": "Перезапустить" + }, + "later": { + "message": "Позже" + }, + "noUpdatesAvailable": { + "message": "Обновлений нет. Вы используете последнюю версию." + }, + "updateError": { + "message": "Ошибка обновления" + }, + "unknown": { + "message": "Неизвестно" + }, + "copyUsername": { + "message": "Скопировать имя пользователя" + }, + "copyNumber": { + "message": "Скопировать номер", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Скопировать код безопасности", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Премиум" + }, + "premiumManage": { + "message": "Управление Премиум" + }, + "premiumManageAlert": { + "message": "Вы можете управлять Премиум на bitwarden.com. Перейти на сайт сейчас?" + }, + "premiumRefresh": { + "message": "Обновить Премиум" + }, + "premiumNotCurrentMember": { + "message": "Сейчас у вас отсутствует Премиум." + }, + "premiumSignUpAndGet": { + "message": "Подпишитесь на Премиум и получите:" + }, + "premiumSignUpStorage": { + "message": "1 ГБ зашифрованного хранилища для вложенных файлов." + }, + "premiumSignUpTwoStep": { + "message": "Дополнительные варианты двухфакторной аутентификации, такие как YubiKey, FIDO U2F и Duo." + }, + "premiumSignUpReports": { + "message": "Гигиена паролей, здоровье аккаунта и отчеты об утечках данных для обеспечения безопасности вашего хранилища." + }, + "premiumSignUpTotp": { + "message": "TOTP-генератор кодов (2ФА) для логинов в хранилище." + }, + "premiumSignUpSupport": { + "message": "Приоритетная поддержка." + }, + "premiumSignUpFuture": { + "message": "Все будущие функции Премиум. Их будет больше!" + }, + "premiumPurchase": { + "message": "Купить Премиум" + }, + "premiumPurchaseAlert": { + "message": "Вы можете купить Премиум на bitwarden.com. Перейти на сайт сейчас?" + }, + "premiumCurrentMember": { + "message": "У вас есть Премиум!" + }, + "premiumCurrentMemberThanks": { + "message": "Благодарим вас за поддержку Bitwarden." + }, + "premiumPrice": { + "message": "Всего лишь $PRICE$ в год!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Обновление завершено" + }, + "passwordHistory": { + "message": "История паролей" + }, + "clear": { + "message": "Очистить", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Нет паролей для отображения." + }, + "undo": { + "message": "Отменить" + }, + "redo": { + "message": "Вернуть" + }, + "cut": { + "message": "Вырезать", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Вставить", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Выбрать все" + }, + "zoomIn": { + "message": "Увеличить" + }, + "zoomOut": { + "message": "Уменьшить" + }, + "resetZoom": { + "message": "Сбросить масштаб" + }, + "toggleFullScreen": { + "message": "Переключить полноэкранный режим" + }, + "reload": { + "message": "Перезагрузка" + }, + "toggleDevTools": { + "message": "Переключить инструменты разработчика" + }, + "minimize": { + "message": "Свернуть", + "description": "Minimize window" + }, + "zoom": { + "message": "Масштаб" + }, + "bringAllToFront": { + "message": "На передний план", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "О Bitwarden" + }, + "services": { + "message": "Службы" + }, + "hideBitwarden": { + "message": "Скрыть Bitwarden" + }, + "hideOthers": { + "message": "Скрыть другие" + }, + "showAll": { + "message": "Показать все" + }, + "quitBitwarden": { + "message": "Выйти из Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ скопирован(о)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Помощь" + }, + "window": { + "message": "Окно" + }, + "checkPassword": { + "message": "Проверьте, не скомпрометирован ли пароль." + }, + "passwordExposed": { + "message": "Этот пароль был скомпрометирован $VALUE$ раз(а). Вам следует его изменить.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Этот пароль не обнаружен в известных базах утечек. Можно продолжать его использовать." + }, + "baseDomain": { + "message": "Основной домен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Доменное имя", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Хост", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Точно" + }, + "startsWith": { + "message": "Начинается с" + }, + "regEx": { + "message": "Регулярное выражение", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Обнаружение совпадений", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Метод обнаружения по умолчанию", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Переключить настройки" + }, + "organization": { + "message": "Организация", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "По умолчанию" + }, + "exit": { + "message": "Выйти" + }, + "showHide": { + "message": "Показать/скрыть", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Свернуть в область уведомлений" + }, + "alwaysOnTop": { + "message": "Поверх всех окон", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Обновлено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Пароль обновлен", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Экспорт хранилища" + }, + "fileFormat": { + "message": "Формат файла" + }, + "warning": { + "message": "ВНИМАНИЕ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Подтвердить экспорт хранилища" + }, + "exportWarningDesc": { + "message": "Экспортируемый файл содержит данные вашего хранилища в незашифрованном формате. Его не следует хранить или отправлять по небезопасным каналам (например по электронной почте). Удалите его сразу после использования." + }, + "encExportKeyWarningDesc": { + "message": "При экспорте данные шифруются при помощи ключа шифрования учетной записи. Если вы решите сменить ключ шифрования, вам следует экспортировать данные повторно, поскольку вы не сможете расшифровать этот файл экспорта." + }, + "encExportAccountWarningDesc": { + "message": "Ключи шифрования уникальны для каждой учетной записи Bitwarden, поэтому нельзя импортировать зашифрованное хранилище в другой аккаунт." + }, + "noOrganizationsList": { + "message": "Вы не являетесь членом какой-либо организации. Организации позволяют безопасно обмениваться элементами с другими пользователями." + }, + "noCollectionsInList": { + "message": "Нет коллекций для отображения." + }, + "ownership": { + "message": "Владелец" + }, + "whoOwnsThisItem": { + "message": "Кому принадлежит этот элемент?" + }, + "strong": { + "message": "Сильный", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Хороший", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабый", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слабый мастер-пароль" + }, + "weakMasterPasswordDesc": { + "message": "Вы выбрали слабый мастер-пароль. Для надежной защиты аккаунта Bitwarden следует использовать сильный мастер-пароль (или парольную фразу). Вы действительно хотите использовать этот мастер-пароль?" + }, + "pin": { + "message": "PIN-код", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Разблокировка PIN-кодом" + }, + "setYourPinCode": { + "message": "Установите PIN-код для разблокировки Bitwarden. Настройки PIN-кода будут сброшены, если вы когда-либо полностью выйдете из приложения." + }, + "pinRequired": { + "message": "Требуется PIN-код." + }, + "invalidPin": { + "message": "Неверный PIN-код." + }, + "unlockWithWindowsHello": { + "message": "Разблокировать с Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Верификация для Bitwarden." + }, + "unlockWithTouchId": { + "message": "Разблокировать с Touch ID" + }, + "touchIdConsentMessage": { + "message": "разблокировать ваше хранилище" + }, + "noAutoPromptWindowsHello": { + "message": "Не запрашивать Windows Hello при запуске." + }, + "noAutoPromptTouchId": { + "message": "Не запрашивать Touch ID при запуске." + }, + "lockWithMasterPassOnRestart": { + "message": "Блокировать мастер-паролем при перезапуске" + }, + "preferences": { + "message": "Настройки" + }, + "enableMenuBar": { + "message": "Включить значок в строке меню" + }, + "enableMenuBarDesc": { + "message": "Всегда показывать значок в строке меню." + }, + "hideToMenuBar": { + "message": "Скрыть в строке меню" + }, + "selectOneCollection": { + "message": "Необходимо выбрать хотя бы одну коллекцию." + }, + "premiumUpdated": { + "message": "Вы обновились до Премиум." + }, + "restore": { + "message": "Восстановить" + }, + "premiumManageAlertAppStore": { + "message": "Вы можете управлять своей подпиской из App Store. Открыть App Store?" + }, + "legal": { + "message": "Правовая информация", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Условия использования" + }, + "privacyPolicy": { + "message": "Политика конфиденциальности" + }, + "unsavedChangesConfirmation": { + "message": "Вы действительно хотите выйти? Ваша текущая информация не будет сохранена." + }, + "unsavedChangesTitle": { + "message": "Несохраненные изменения" + }, + "clone": { + "message": "Клонировать" + }, + "passwordGeneratorPolicyInEffect": { + "message": "На настройки генератора влияют одна или несколько политик организации." + }, + "vaultTimeoutAction": { + "message": "Действие по тайм-ауту хранилища" + }, + "vaultTimeoutActionLockDesc": { + "message": "Заблокированное хранилище потребует повторного ввода мастер-пароля для получения доступа к нему." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Выход из хранилища потребует повторную аутентификацию для получения доступа к нему." + }, + "lock": { + "message": "Заблокировать", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Корзина", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Поиск в корзине" + }, + "permanentlyDeleteItem": { + "message": "Окончательно удалить элемент" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Вы уверены, что хотите окончательно удалить этот элемент?" + }, + "permanentlyDeletedItem": { + "message": "Элемент удален навсегда" + }, + "restoreItem": { + "message": "Восстановить элемент" + }, + "restoreItemConfirmation": { + "message": "Вы уверены, что хотите восстановить этот элемент?" + }, + "restoredItem": { + "message": "Элемент восстановлен" + }, + "permanentlyDelete": { + "message": "Удалить окончательно" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "По истечении тайм-аута будет выполнен выход, что приведет к отмене всех прав доступа к вашему хранилищу и потребует онлайн-аутентификации. Вы уверены, что хотите использовать этот параметр?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Подтверждение действия по тайм-ауту" + }, + "enterpriseSingleSignOn": { + "message": "Единая корпоративная авторизация (SSO)" + }, + "setMasterPassword": { + "message": "Задать мастер-пароль" + }, + "ssoCompleteRegistration": { + "message": "Для завершения процесса авторизации при помощи SSO, установите мастер-пароль для доступа к вашему хранилищу и его защиты." + }, + "newMasterPass": { + "message": "Новый мастер-пароль" + }, + "confirmNewMasterPass": { + "message": "Подтвердите новый мастер-пароль" + }, + "masterPasswordPolicyInEffect": { + "message": "Согласно одной или нескольким политикам организации необходимо, чтобы ваш мастер-пароль отвечал следующим требованиям:" + }, + "policyInEffectMinComplexity": { + "message": "Минимальный уровень сложности $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Минимальная длина $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Содержать хотя бы одну заглавную букву" + }, + "policyInEffectLowercase": { + "message": "Содержать хотя бы одну строчную букву" + }, + "policyInEffectNumbers": { + "message": "Содержать хотя бы одну цифру" + }, + "policyInEffectSpecial": { + "message": "Содержать хотя бы один из следующих специальных символов $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваш новый мастер-пароль не соответствует требованиям политики." + }, + "acceptPolicies": { + "message": "Отметив этот флажок, вы соглашаетесь со следующим:" + }, + "acceptPoliciesError": { + "message": "Условия предоставления услуг и Политика конфиденциальности не были подтверждены." + }, + "enableBrowserIntegration": { + "message": "Включить интеграцию с браузером" + }, + "enableBrowserIntegrationDesc": { + "message": "Интеграция с браузером используется для биометрии в браузере." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Интеграция с браузером не поддерживается" + }, + "browserIntegrationMasOnlyDesc": { + "message": "К сожалению, интеграция браузера пока поддерживается только в версии Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Интеграция с браузером не поддерживается" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "К сожалению, интеграция с браузером на текущий момент не поддерживается в версии из магазина Windows." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Требовать верификацию для интеграции с браузером" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Включите дополнительный уровень безопасности, используя проверку отпечатка фразы при установлении соединения между компьютером и браузером. Когда эта функция включена, она требует участия пользователя и верификации каждый раз при установлении соединения." + }, + "approve": { + "message": "Принять" + }, + "verifyBrowserTitle": { + "message": "Верификация соединения с браузером" + }, + "verifyBrowserDesc": { + "message": "Пожалуйста, убедитесь, что отображаемый отпечаток идентичен отпечатку, отображаемому в расширении браузера." + }, + "biometricsNotEnabledTitle": { + "message": "Биометрия не включена" + }, + "biometricsNotEnabledDesc": { + "message": "Для активации биометрии в браузере сначала необходимо включить биометрию в приложении для компьютера." + }, + "personalOwnershipSubmitError": { + "message": "В соответствии с корпоративной политикой вам запрещено сохранять элементы в личном хранилище. Измените владельца на организацию и выберите из доступных Коллекций." + }, + "hintEqualsPassword": { + "message": "Подсказка для пароля не может совпадать с паролем." + }, + "personalOwnershipPolicyInEffect": { + "message": "Политика организации влияет на ваши варианты владения." + }, + "allSends": { + "message": "Все Send’ы", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Файл" + }, + "sendTypeText": { + "message": "Текст" + }, + "searchSends": { + "message": "Поиск Send’ов", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Изменить Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Хранилище" + }, + "text": { + "message": "Текст" + }, + "deletionDate": { + "message": "Срок удаления" + }, + "deletionDateDesc": { + "message": "Эта Send будет окончательно удалена в указанные дату и время.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Срок истечения" + }, + "expirationDateDesc": { + "message": "Если задано, доступ к этой Send истечет в указанные дату и время.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Максимум обращений" + }, + "maxAccessCountDesc": { + "message": "Если задано, пользователи больше не смогут получить доступ к этой Send, как только будет достигнуто максимальное количество обращений.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Текущих обращений" + }, + "disableSend": { + "message": "Отключить эту Send, чтобы никто не мог получить к ней доступ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "По возможности запрашивать у пользователей пароль для доступа к этой Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Личные заметки об этой Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Ссылка на Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Ссылка на Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "При доступе к Send скрывать текст по умолчанию", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Созданная Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Измененная Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Удаленная Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Новый пароль" + }, + "whatTypeOfSend": { + "message": "Выберите тип Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Создать Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст, который вы хотите отправить." + }, + "sendFileDesc": { + "message": "Файл, который вы хотите отправить." + }, + "days": { + "message": "$DAYS$ дн.", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 день" + }, + "custom": { + "message": "Пользовательский" + }, + "deleteSendConfirmation": { + "message": "Вы действительно хотите удалить эту Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Скопировать ссылку на Send в буфер обмена", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Скопировать ссылку в буфер обмена после сохранения, чтобы поделиться этой Send." + }, + "sendDisabled": { + "message": "Send отключена", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "В соответствии с корпоративной политикой вы можете удалить только существующую Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Скопировать ссылку" + }, + "disabled": { + "message": "Отключено" + }, + "maxAccessCountReached": { + "message": "Достигнут максимум обращений" + }, + "expired": { + "message": "Срок истек" + }, + "pendingDeletion": { + "message": "Ожидание удаления" + }, + "webAuthnAuthenticate": { + "message": "Аутентификация WebAutn" + }, + "hideEmail": { + "message": "Скрыть мой адрес email от получателей." + }, + "sendOptionsPolicyInEffect": { + "message": "На параметры Send влияют одна или несколько политик организации." + }, + "emailVerificationRequired": { + "message": "Требуется подтверждение электронной почты" + }, + "emailVerificationRequiredDesc": { + "message": "Для использования этой функции необходимо подтвердить свою электронную почту." + }, + "passwordPrompt": { + "message": "Повторный запрос мастер-пароля" + }, + "passwordConfirmation": { + "message": "Подтверждение мастер-пароля" + }, + "passwordConfirmationDesc": { + "message": "Это действие защищено. Для продолжения введите свой мастер-пароль, чтобы подтвердить свою личность." + }, + "updatedMasterPassword": { + "message": "Мастер-пароль обновлен" + }, + "updateMasterPassword": { + "message": "Обновить мастер-пароль" + }, + "updateMasterPasswordWarning": { + "message": "Мастер-пароль недавно был изменен администратором вашей организации. Чтобы получить доступ к хранилищу, вы должны обновить его сейчас. В результате текущая сессия будет завершена, потребуется повторный вход. Активные сессии на других устройствах могут оставаться активными в течение одного часа." + }, + "hours": { + "message": "Час." + }, + "minutes": { + "message": "Мин." + }, + "vaultTimeoutPolicyInEffect": { + "message": "Политики вашей организации влияют на тайм-аут хранилища. Максимально допустимый тайм-аут хранилища составляет $HOURS$ час. и $MINUTES$ мин.", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Тайм-аут вашего хранилища превышает ограничения, установленные вашей организацией." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Автоматическая регистрация" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "В этой организации действует корпоративная политика, которая автоматически зарегистрирует вас на сброс пароля. Регистрация позволит администраторам организации изменить ваш мастер-пароль." + }, + "vaultExportDisabled": { + "message": "Экспорт хранилища отключен" + }, + "personalVaultExportPolicyInEffect": { + "message": "Экспорт вашего личного хранилища запрещен одной или несколькими политиками организации." + }, + "addAccount": { + "message": "Добавить аккаунт" + }, + "removeMasterPassword": { + "message": "Удалить мастер-пароль" + }, + "removedMasterPassword": { + "message": "Мастер-пароль удален." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ использует SSO с собственным сервером ключей. Для авторизации членам этой организации больше не требуется мастер-пароль.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Покинуть организацию" + }, + "leaveOrganizationConfirmation": { + "message": "Вы действительно хотите покинуть эту организацию?" + }, + "leftOrganization": { + "message": "Вы покинули организацию." + }, + "ssoKeyConnectorUnavailable": { + "message": "Не удается подключиться к соединителю ключей, повторите попытку позже." + }, + "lockAllVaults": { + "message": "Заблокировать все хранилища" + }, + "accountLimitReached": { + "message": "Одновременно могут быть авторизованы не более 5 аккаунтов." + }, + "accountPreferences": { + "message": "Настройки" + }, + "appPreferences": { + "message": "Настройки приложения (все аккаунты)" + }, + "accountSwitcherLimitReached": { + "message": "Достигнут лимит учетной записи. Выйдите, чтобы добавить другую." + }, + "settingsTitle": { + "message": "Настройки приложения для $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Сменить аккаунт" + }, + "options": { + "message": "Опции" + }, + "sessionTimeout": { + "message": "Время вашей сессии истекло. Пожалуйста, вернитесь и попробуйте войти снова." + }, + "exportingPersonalVaultTitle": { + "message": "Экспорт личного хранилища" + }, + "exportingPersonalVaultDescription": { + "message": "Будут экспортированы только личные элементы хранилища, связанные с $EMAIL$. Элементы хранилища организации включены не будут.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Генератор" + }, + "whatWouldYouLikeToGenerate": { + "message": "Что вы хотите сгенерировать?" + }, + "passwordType": { + "message": "Тип пароля" + }, + "regenerateUsername": { + "message": "Пересоздать имя пользователя" + }, + "generateUsername": { + "message": "Создать имя пользователя" + }, + "usernameType": { + "message": "Тип имени пользователя" + }, + "plusAddressedEmail": { + "message": "Плюс-адресованные email" + }, + "plusAddressedEmailDesc": { + "message": "Использовать возможности суб-адресации вашего провайдера электронной почты." + }, + "catchallEmail": { + "message": "Catch-all-адрес электронной почты" + }, + "catchallEmailDesc": { + "message": "Использовать настроенную в вашем домене почту catch-all." + }, + "random": { + "message": "Случайно" + }, + "randomWord": { + "message": "Случайное слово" + }, + "websiteName": { + "message": "Название сайта" + }, + "service": { + "message": "Служба" + } +} diff --git a/apps/desktop/src/locales/si/messages.json b/apps/desktop/src/locales/si/messages.json new file mode 100644 index 0000000000..6a6052b750 --- /dev/null +++ b/apps/desktop/src/locales/si/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "බිට්වාඩන්" + }, + "filters": { + "message": "පෙරහන්" + }, + "allItems": { + "message": "All Items" + }, + "favorites": { + "message": "ප්‍රියතමයන්" + }, + "types": { + "message": "වර්ග" + }, + "typeLogin": { + "message": "පිවිසෙන්න" + }, + "typeCard": { + "message": "පත" + }, + "typeIdentity": { + "message": "අනන්‍යතාව" + }, + "typeSecureNote": { + "message": "ආරක්ෂිත සටහන" + }, + "folders": { + "message": "බහාලුම්" + }, + "collections": { + "message": "Collections" + }, + "searchVault": { + "message": "Search Vault" + }, + "addItem": { + "message": "Add Item" + }, + "shared": { + "message": "Shared" + }, + "share": { + "message": "බෙදාගන්න" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "View Item" + }, + "name": { + "message": "නම" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "පරිශීලක නාමය" + }, + "password": { + "message": "මුර පදය" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "Edit Item" + }, + "emailAddress": { + "message": "වි-තැපැල් ලිපිනය" + }, + "verificationCodeTotp": { + "message": "Verification Code (TOTP)" + }, + "website": { + "message": "වියමන අඩවිය" + }, + "notes": { + "message": "සටහන්" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "දියත් කරන්න" + }, + "copyValue": { + "message": "අගය පිටපත් කරන්න", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "අංකය" + }, + "brand": { + "message": "Brand" + }, + "expiration": { + "message": "කල් ඉකුත් වීම" + }, + "securityCode": { + "message": "ආරක්ෂිත කේතය" + }, + "identityName": { + "message": "Identity Name" + }, + "company": { + "message": "සමාගම" + }, + "ssn": { + "message": "Social Security Number" + }, + "passportNumber": { + "message": "Passport Number" + }, + "licenseNumber": { + "message": "License Number" + }, + "email": { + "message": "වි-තැපෑල" + }, + "phone": { + "message": "දුරකථනය" + }, + "address": { + "message": "ලිපිනය" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "A premium membership is required to use this feature." + }, + "errorOccurred": { + "message": "An error has occurred." + }, + "error": { + "message": "දෝෂය" + }, + "january": { + "message": "දුරුතු" + }, + "february": { + "message": "නවම්" + }, + "march": { + "message": "මැදින්" + }, + "april": { + "message": "බක්" + }, + "may": { + "message": "වෙසක්" + }, + "june": { + "message": "පොසොන්" + }, + "july": { + "message": "ඇසළ" + }, + "august": { + "message": "නිකිණි" + }, + "september": { + "message": "බිනර" + }, + "october": { + "message": "වප්" + }, + "november": { + "message": "ඉල්" + }, + "december": { + "message": "උඳුවප්" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Title" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Expiration Month" + }, + "expirationYear": { + "message": "Expiration Year" + }, + "select": { + "message": "Select" + }, + "other": { + "message": "Other" + }, + "generatePassword": { + "message": "Generate Password" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "First Name" + }, + "middleName": { + "message": "Middle Name" + }, + "lastName": { + "message": "Last Name" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Address 1" + }, + "address2": { + "message": "Address 2" + }, + "address3": { + "message": "Address 3" + }, + "cityTown": { + "message": "City / Town" + }, + "stateProvince": { + "message": "State / Province" + }, + "zipPostalCode": { + "message": "Zip / Postal Code" + }, + "country": { + "message": "රට" + }, + "save": { + "message": "සුරකින්න" + }, + "cancel": { + "message": "අවලංගු කරන්න" + }, + "delete": { + "message": "Delete" + }, + "favorite": { + "message": "ප්‍රියතමය" + }, + "edit": { + "message": "සංස්කරණය" + }, + "authenticatorKeyTotp": { + "message": "Authenticator Key (TOTP)" + }, + "folder": { + "message": "බහාලුම" + }, + "newCustomField": { + "message": "New Custom Field" + }, + "value": { + "message": "අගය" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Hidden" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "ඉවත් කරන්න" + }, + "nameRequired": { + "message": "Name is required." + }, + "addedItem": { + "message": "Added item" + }, + "editedItem": { + "message": "Edited item" + }, + "deleteItem": { + "message": "Delete Item" + }, + "deleteFolder": { + "message": "Delete Folder" + }, + "deleteAttachment": { + "message": "Delete Attachment" + }, + "deleteItemConfirmation": { + "message": "Do you really want to send to the trash?" + }, + "deletedItem": { + "message": "Sent item to trash" + }, + "overwritePasswordConfirmation": { + "message": "Are you sure you want to overwrite the current password?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "බහාලුමක් නැත", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "බහාලුම එකතු කරන්න" + }, + "editFolder": { + "message": "බහාලුම සංස්කරණය කරන්න" + }, + "regeneratePassword": { + "message": "Regenerate Password" + }, + "copyPassword": { + "message": "මුරපදය පිටපත් කරන්න" + }, + "copyUri": { + "message": "Copy URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "Length" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "වසන්න" + }, + "minNumbers": { + "message": "Minimum Numbers" + }, + "minSpecial": { + "message": "Minimum Special", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Avoid Ambiguous Characters" + }, + "searchCollection": { + "message": "Search Collection" + }, + "searchFolder": { + "message": "බහාලුම සොයන්න" + }, + "searchFavorites": { + "message": "ප්‍රියතමයන් සොයන්න" + }, + "searchType": { + "message": "Search Type", + "description": "Search item type" + }, + "newAttachment": { + "message": "Add New Attachment" + }, + "deletedAttachment": { + "message": "Deleted attachment" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "Select a file." + }, + "maxFileSize": { + "message": "Maximum file size is 500 MB." + }, + "updateKey": { + "message": "You cannot use this feature until you update your encryption key." + }, + "editedFolder": { + "message": "Edited folder" + }, + "addedFolder": { + "message": "Added folder" + }, + "deleteFolderConfirmation": { + "message": "Are you sure you want to delete this folder?" + }, + "deletedFolder": { + "message": "Deleted folder" + }, + "loginOrCreateNewAccount": { + "message": "Log in or create a new account to access your secure vault." + }, + "createAccount": { + "message": "Create Account" + }, + "logIn": { + "message": "Log In" + }, + "submit": { + "message": "Submit" + }, + "masterPass": { + "message": "Master Password" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "සැකසුම්" + }, + "passwordHint": { + "message": "Password Hint" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "වලංගු නොවන වි-තැපැල් ලිපිනයකි." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Item Information" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Verification Code" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "ඉදිරියට" + }, + "enterVerificationCodeApp": { + "message": "Enter the 6 digit verification code from your authenticator app." + }, + "enterVerificationCodeEmail": { + "message": "Enter the 6 digit verification code that was emailed to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Remember me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Send verification code email again" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "ප්‍රතිසාධන කේතය" + }, + "authenticatorAppTitle": { + "message": "Authenticator App" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "වි-තැපෑල" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "Login Unavailable" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "හරි" + }, + "yes": { + "message": "ඔව්" + }, + "no": { + "message": "නැහැ" + }, + "overwritePassword": { + "message": "Overwrite Password" + }, + "learnMore": { + "message": "Learn more" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "නික්මෙන්න" + }, + "addNewLogin": { + "message": "Add New Login" + }, + "addNewItem": { + "message": "Add New Item" + }, + "addNewFolder": { + "message": "නව බහාලුමක් එකතු කරන්න" + }, + "view": { + "message": "View" + }, + "account": { + "message": "ගිණුම" + }, + "loading": { + "message": "පූරණය වෙමින්..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Password Generator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "Change Master Password" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "Get Mobile App" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "අනවහිර" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "Two-step Login" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Immediately" + }, + "tenSeconds": { + "message": "තත්පර 10" + }, + "twentySeconds": { + "message": "තත්පර 20" + }, + "thirtySeconds": { + "message": "තත්පර 30" + }, + "oneMinute": { + "message": "විනාඩි 1" + }, + "twoMinutes": { + "message": "විනාඩි 2" + }, + "fiveMinutes": { + "message": "විනාඩි 5" + }, + "fifteenMinutes": { + "message": "විනාඩි 15" + }, + "thirtyMinutes": { + "message": "30 minutes" + }, + "oneHour": { + "message": "1 hour" + }, + "fourHours": { + "message": "4 hours" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "භාෂාව" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "තේමාව" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "පිටපත්", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Check For Updates" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Restart" + }, + "later": { + "message": "පසුව" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Update Error" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "Copy Username" + }, + "copyNumber": { + "message": "Copy Number", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Copy Security Code", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Cut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Paste", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Select All" + }, + "zoomIn": { + "message": "Zoom In" + }, + "zoomOut": { + "message": "Zoom Out" + }, + "resetZoom": { + "message": "Reset Zoom" + }, + "toggleFullScreen": { + "message": "Toggle Full Screen" + }, + "reload": { + "message": "Reload" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimize", + "description": "Minimize window" + }, + "zoom": { + "message": "Zoom" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Show All" + }, + "quitBitwarden": { + "message": "Quit Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Help" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/sk/messages.json b/apps/desktop/src/locales/sk/messages.json new file mode 100644 index 0000000000..e36cea0a5c --- /dev/null +++ b/apps/desktop/src/locales/sk/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtre" + }, + "allItems": { + "message": "Všetky položky" + }, + "favorites": { + "message": "Obľúbené" + }, + "types": { + "message": "Typy" + }, + "typeLogin": { + "message": "Prihlásenie" + }, + "typeCard": { + "message": "Karta" + }, + "typeIdentity": { + "message": "Identita" + }, + "typeSecureNote": { + "message": "Zabezpečená poznámka" + }, + "folders": { + "message": "Priečinky" + }, + "collections": { + "message": "Zbierky" + }, + "searchVault": { + "message": "Hľadať v trezore" + }, + "addItem": { + "message": "Pridať položku" + }, + "shared": { + "message": "Zdieľané" + }, + "share": { + "message": "Zdieľať" + }, + "moveToOrganization": { + "message": "Presunúť do Organizácie" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ presunuté do $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Vyberte organizáciu, do ktorej chcete presunúť túto položku. Presunom do organizácie sa vlastníctvo položky prenáša na túto organizáciu. Po presunutí už nebudete priamym vlastníkom danej položky." + }, + "attachments": { + "message": "Prílohy" + }, + "viewItem": { + "message": "Zobraziť položku" + }, + "name": { + "message": "Názov" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nové URI" + }, + "username": { + "message": "Používateľské meno" + }, + "password": { + "message": "Heslo" + }, + "passphrase": { + "message": "Heslo" + }, + "editItem": { + "message": "Upraviť položku" + }, + "emailAddress": { + "message": "Emailová adresa" + }, + "verificationCodeTotp": { + "message": "Overovací kód (TOTP)" + }, + "website": { + "message": "Webstránka" + }, + "notes": { + "message": "Poznámky" + }, + "customFields": { + "message": "Vlastné polia" + }, + "launch": { + "message": "Spustiť" + }, + "copyValue": { + "message": "Skopírovať hodnotu", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimalizovať pri kopírovaní do schránky" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimalizovať pri kopírovaní údajov z položky do schránky." + }, + "toggleVisibility": { + "message": "Prepnúť viditeľnosť" + }, + "toggleCollapse": { + "message": "Prepnúť zloženie", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Meno vlastníka karty" + }, + "number": { + "message": "Číslo" + }, + "brand": { + "message": "Značka" + }, + "expiration": { + "message": "Exspirácia" + }, + "securityCode": { + "message": "Bezpečnostný kód" + }, + "identityName": { + "message": "Názov identity" + }, + "company": { + "message": "Spoločnosť" + }, + "ssn": { + "message": "Číslo poistenca sociálnej poisťovne" + }, + "passportNumber": { + "message": "Číslo pasu" + }, + "licenseNumber": { + "message": "Číslo vodičského preukazu" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Telefón" + }, + "address": { + "message": "Adresa" + }, + "premiumRequired": { + "message": "Vyžaduje prémiový účet" + }, + "premiumRequiredDesc": { + "message": "Pre použitie tejto funkcie je potrebné prémiové členstvo." + }, + "errorOccurred": { + "message": "Vyskytla sa chyba." + }, + "error": { + "message": "Chyba" + }, + "january": { + "message": "Január" + }, + "february": { + "message": "Február" + }, + "march": { + "message": "Marec" + }, + "april": { + "message": "Apríl" + }, + "may": { + "message": "Máj" + }, + "june": { + "message": "Jún" + }, + "july": { + "message": "Júl" + }, + "august": { + "message": "August" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Október" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "napr.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Oslovenie" + }, + "mr": { + "message": "Pán" + }, + "mrs": { + "message": "Pani" + }, + "ms": { + "message": "Slečna" + }, + "dr": { + "message": "Dr." + }, + "expirationMonth": { + "message": "Mesiac exspirácie" + }, + "expirationYear": { + "message": "Rok exspirácie" + }, + "select": { + "message": "Vybrať" + }, + "other": { + "message": "Ostatné" + }, + "generatePassword": { + "message": "Generovať heslo" + }, + "type": { + "message": "Typ" + }, + "firstName": { + "message": "Krstné meno" + }, + "middleName": { + "message": "Druhé meno" + }, + "lastName": { + "message": "Priezvisko" + }, + "fullName": { + "message": "Celé meno" + }, + "address1": { + "message": "Adresa 1" + }, + "address2": { + "message": "Adresa 2" + }, + "address3": { + "message": "Adresa 3" + }, + "cityTown": { + "message": "Mesto" + }, + "stateProvince": { + "message": "Región" + }, + "zipPostalCode": { + "message": "PSČ" + }, + "country": { + "message": "Krajina" + }, + "save": { + "message": "Uložiť" + }, + "cancel": { + "message": "Zrušiť" + }, + "delete": { + "message": "Odstrániť" + }, + "favorite": { + "message": "Obľúbené" + }, + "edit": { + "message": "Upraviť" + }, + "authenticatorKeyTotp": { + "message": "Kľúč overovateľa (TOTP)" + }, + "folder": { + "message": "Priečinok" + }, + "newCustomField": { + "message": "Nové vlastné pole" + }, + "value": { + "message": "Hodnota" + }, + "dragToSort": { + "message": "Zoradiť presúvaním" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Skryté" + }, + "cfTypeBoolean": { + "message": "Áno/Nie" + }, + "cfTypeLinked": { + "message": "Prepojené", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Prepojená hodnota", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Odstrániť" + }, + "nameRequired": { + "message": "Meno je povinné." + }, + "addedItem": { + "message": "Položka pridaná" + }, + "editedItem": { + "message": "Položka upravená" + }, + "deleteItem": { + "message": "Odstrániť položku" + }, + "deleteFolder": { + "message": "Odstrániť priečinok" + }, + "deleteAttachment": { + "message": "Odstrániť prílohu" + }, + "deleteItemConfirmation": { + "message": "Naozaj chcete odstrániť túto položku?" + }, + "deletedItem": { + "message": "Položka odstránená" + }, + "overwritePasswordConfirmation": { + "message": "Naozaj chcete prepísať aktuálne heslo?" + }, + "overwriteUsername": { + "message": "Prepísať používateľské meno" + }, + "overwriteUsernameConfirmation": { + "message": "Naozaj chcete prepísať aktuálne používateľské meno?" + }, + "noneFolder": { + "message": "Žiadny priečinok", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Pridať priečinok" + }, + "editFolder": { + "message": "Upraviť priečinok" + }, + "regeneratePassword": { + "message": "Vygenerovať nové heslo" + }, + "copyPassword": { + "message": "Kopírovať heslo" + }, + "copyUri": { + "message": "Kopírovať URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopírovať overovací kód (TOTP)" + }, + "length": { + "message": "Dĺžka" + }, + "numWords": { + "message": "Počet slov" + }, + "wordSeparator": { + "message": "Oddeľovač slov" + }, + "capitalize": { + "message": "Veľké prvé písmená slov", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Zahrnúť číslo" + }, + "close": { + "message": "Zavrieť" + }, + "minNumbers": { + "message": "Minimálny počet číslic" + }, + "minSpecial": { + "message": "Minimum špeciálnych", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Vyhnúť sa zameniteľným znakom" + }, + "searchCollection": { + "message": "Hľadať v zbierke" + }, + "searchFolder": { + "message": "Hľadať v priečinku" + }, + "searchFavorites": { + "message": "Hľadať v obľúbených" + }, + "searchType": { + "message": "Hľadať podľa typu", + "description": "Search item type" + }, + "newAttachment": { + "message": "Pridať novú prílohu" + }, + "deletedAttachment": { + "message": "Príloha odstránená" + }, + "deleteAttachmentConfirmation": { + "message": "Naozaj chcete odstrániť prílohu?" + }, + "attachmentSaved": { + "message": "Príloha bola uložená." + }, + "file": { + "message": "Súbor" + }, + "selectFile": { + "message": "Vybrať súbor." + }, + "maxFileSize": { + "message": "Maximálna veľkosť súboru je 500 MB." + }, + "updateKey": { + "message": "Túto funkciu je možné použiť, až keď si aktualizujete svoj šifrovací kľúč." + }, + "editedFolder": { + "message": "Priečinok upravený" + }, + "addedFolder": { + "message": "Priečinok pridaný" + }, + "deleteFolderConfirmation": { + "message": "Naozaj chcete odstrániť tento priečinok?" + }, + "deletedFolder": { + "message": "Priečinok odstránený" + }, + "loginOrCreateNewAccount": { + "message": "Prihláste sa alebo si vytvorte nový účet, aby ste mohli pristupovať k vášmu bezpečnému trezoru." + }, + "createAccount": { + "message": "Vytvoriť účet" + }, + "logIn": { + "message": "Prihlásiť sa" + }, + "submit": { + "message": "Potvrdiť" + }, + "masterPass": { + "message": "Hlavné heslo" + }, + "masterPassDesc": { + "message": "Hlavné heslo je heslo, ktoré používate na prístup k svojmu trezoru. Je veľmi dôležité, aby ste svoje hlavné heslo nezabudli. Neexistuje možnosť ako heslo obnoviť v prípade, že ho zabudnete." + }, + "masterPassHintDesc": { + "message": "Nápoveď k hlavnému heslu vám môže pomôcť spomenúť si na heslo, ak ho zabudnete." + }, + "reTypeMasterPass": { + "message": "Znovu zadajte hlavné heslo" + }, + "masterPassHint": { + "message": "Nápoveď k hlavnému heslo (voliteľné)" + }, + "settings": { + "message": "Nastavenia" + }, + "passwordHint": { + "message": "Nápoveď k heslu" + }, + "enterEmailToGetHint": { + "message": "Zadajte emailovú adresu na zaslanie nápovede pre vaše hlavné heslo." + }, + "getMasterPasswordHint": { + "message": "Získať nápoveď k hlavnému heslu" + }, + "emailRequired": { + "message": "Emailová adresa je povinná." + }, + "invalidEmail": { + "message": "Neplatná emailová adresa." + }, + "masterPassRequired": { + "message": "Hlavné heslo je povinné." + }, + "masterPassLength": { + "message": "Hlavné heslo musí obsahovať aspoň 8 znakov." + }, + "masterPassDoesntMatch": { + "message": "Potvrdenie hlavného hesla sa nezhoduje." + }, + "newAccountCreated": { + "message": "Váš nový účet bol vytvorený! Teraz sa môžete prihlásiť." + }, + "masterPassSent": { + "message": "Emailom sme vám poslali nápoveď k hlavnému heslu." + }, + "unexpectedError": { + "message": "Vyskytla sa neočakávaná chyba." + }, + "itemInformation": { + "message": "Informácie o položke" + }, + "noItemsInList": { + "message": "Neexistujú žiadne položky na zobrazenie." + }, + "sendVerificationCode": { + "message": "Poslať overovací kód na váš e-mail" + }, + "sendCode": { + "message": "Odoslať kód" + }, + "codeSent": { + "message": "Kód bol odoslaný" + }, + "verificationCode": { + "message": "Overovací kód" + }, + "confirmIdentity": { + "message": "Ak chcete pokračovať, potvrďte svoju identitu." + }, + "verificationCodeRequired": { + "message": "Overovací kód je povinný." + }, + "invalidVerificationCode": { + "message": "Neplatný verifikačný kód" + }, + "continue": { + "message": "Pokračovať" + }, + "enterVerificationCodeApp": { + "message": "Zadajte 6-miestny overovací kód z vašej overovacej aplikácie." + }, + "enterVerificationCodeEmail": { + "message": "Zadajte 6-miestny overovací kód, ktorý bol zaslaný emailom na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Overovací email odoslaný na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapamätaj si ma" + }, + "sendVerificationCodeEmailAgain": { + "message": "Znovu zaslať overovací kód emailom" + }, + "useAnotherTwoStepMethod": { + "message": "Použiť inú dvojstupňovú metódu prihlásenia" + }, + "insertYubiKey": { + "message": "Vložte váš YubiKey do USB portu počítača a stlačte jeho tlačidlo." + }, + "insertU2f": { + "message": "Vložte váš bezpečnostný kľúč do USB portu počítača. Ak má tlačidlo, stlačte ho." + }, + "recoveryCodeDesc": { + "message": "Stratili ste prístup ku všetkým vašim dvojstupňovým poskytovateľom? Použite váš záchranný kód pre vypnutie všetkých poskytovateľov vo vašom účte." + }, + "recoveryCodeTitle": { + "message": "Kód na obnovenie" + }, + "authenticatorAppTitle": { + "message": "Overovacia aplikácia" + }, + "authenticatorAppDesc": { + "message": "Použite overovaciu aplikáciu (napríklad Authy alebo Google Authenticator) na generovanie časovo obmedzených overovacích kódov.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP bezpečnostný kľúč" + }, + "yubiKeyDesc": { + "message": "Použiť YubiKey pre prístup k vášmu účtu. Pracuje s YubiKey 4, 4 Nano, 4C a s NEO zariadeniami." + }, + "duoDesc": { + "message": "Overiť sa prostredníctvom Duo Security použitím Duo Mobile aplikácie, SMS, telefonátu alebo U2F bezpečnostným kľúčom.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Overiť sa prostredníctvom Duo Security vašej organizácie použitím Duo Mobile aplikácie, SMS, telefonátu alebo U2F bezpečnostným kľúčom.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Použiť akýkoľvek WebAuthn bezpečnostný kľúč pre prístup k vášmu účtu." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Overovacie kódy vám budú zaslané emailom." + }, + "loginUnavailable": { + "message": "Prihlásenie nedostupné" + }, + "noTwoStepProviders": { + "message": "Tento účet má povolené dvojstupňové prihlásenie, ale žiadny z nakonfigurovaných poskytovateľov nie je podporovaný na tomto zariadení." + }, + "noTwoStepProviders2": { + "message": "Prosím, pridajte ďalších poskytovateľov dvojstupňového overenia, ktoré majú lepšiu podporu naprieč zariadeniami (napríklad Autentifikačnú aplikáciu)." + }, + "twoStepOptions": { + "message": "Možnosti dvojstupňového prihlásenia" + }, + "selfHostedEnvironment": { + "message": "Prevádzkované vo vlastnom prostredí" + }, + "selfHostedEnvironmentFooter": { + "message": "Zadajte URL Bitwarden inštalácie, ktorú prevádzkujete vo vlastnom prostredí." + }, + "customEnvironment": { + "message": "Vlastné prostredie" + }, + "customEnvironmentFooter": { + "message": "Pre pokročilých používateľov. Môžete špecifikovať základnú URL pre každú službu nezávisle." + }, + "baseUrl": { + "message": "URL servera" + }, + "apiUrl": { + "message": "URL API servera" + }, + "webVaultUrl": { + "message": "URL servera webového trezora" + }, + "identityUrl": { + "message": "URL servera identít" + }, + "notificationsUrl": { + "message": "URL adresa servera pre oznámenia" + }, + "iconsUrl": { + "message": "URL servera ikon" + }, + "environmentSaved": { + "message": "URL prostredia boli uložené." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Áno" + }, + "no": { + "message": "Nie" + }, + "overwritePassword": { + "message": "Prepísať heslo" + }, + "learnMore": { + "message": "Zistiť viac" + }, + "featureUnavailable": { + "message": "Funkcia nie je k dispozícii" + }, + "loggedOut": { + "message": "Odhlásený" + }, + "loginExpired": { + "message": "Platnosť prihlásenia vypršala." + }, + "logOutConfirmation": { + "message": "Naozaj sa chcete odhlásiť?" + }, + "logOut": { + "message": "Odhlásiť sa" + }, + "addNewLogin": { + "message": "Pridať nové prihlasovacie údaje" + }, + "addNewItem": { + "message": "Pridať novú položku" + }, + "addNewFolder": { + "message": "Vytvoriť nový priečinok" + }, + "view": { + "message": "Zobraziť" + }, + "account": { + "message": "Účet" + }, + "loading": { + "message": "Načítava sa..." + }, + "lockVault": { + "message": "Zamknúť trezor" + }, + "passwordGenerator": { + "message": "Generátor hesla" + }, + "contactUs": { + "message": "Kontaktujte nás" + }, + "getHelp": { + "message": "Získať pomoc" + }, + "fileBugReport": { + "message": "Nahlásiť chybu" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Sledujte nás" + }, + "syncVault": { + "message": "Synchronizovať trezor teraz" + }, + "changeMasterPass": { + "message": "Zmeniť hlavné heslo" + }, + "changeMasterPasswordConfirmation": { + "message": "Svoje hlavné heslo môžete zmeniť vo webovom trezore bitwarden.com. Chcete teraz navštíviť túto stránku?" + }, + "fingerprintPhrase": { + "message": "Fráza odtlačku", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fráza odtlačku vašeho účtu", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Prejsť do webového trezora" + }, + "getMobileApp": { + "message": "Získajte mobilnú aplikáciu" + }, + "getBrowserExtension": { + "message": "Získať rozšírenie pre prehliadač" + }, + "syncingComplete": { + "message": "Synchronizácia dokončená" + }, + "syncingFailed": { + "message": "Synchronizácia zlyhala" + }, + "yourVaultIsLocked": { + "message": "Váš trezor je uzamknutý. Ak chcete pokračovať, overte svoju identitu." + }, + "unlock": { + "message": "Odomknúť" + }, + "loggedInAsOn": { + "message": "Prihlásený ako $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Neplatné hlavné heslo" + }, + "twoStepLoginConfirmation": { + "message": "Dvojstupňové prihlasovanie robí váš účet bezpečnejším vďaka vyžadovaniu bezpečnostného kódu z overovacej aplikácie vždy, keď sa prihlásite. Dvojstupňové prihlasovanie môžete povoliť vo webovom trezore bitwarden.com. Chcete teraz navštíviť túto stránku?" + }, + "twoStepLogin": { + "message": "Dvojstupňové prihlásenie" + }, + "vaultTimeout": { + "message": "Časový limit pre trezor" + }, + "vaultTimeoutDesc": { + "message": "Vyberte, kedy vyprší časový limit trezora a vykoná sa zvolená akcia." + }, + "immediately": { + "message": "Okamžite" + }, + "tenSeconds": { + "message": "10 sekúnd" + }, + "twentySeconds": { + "message": "20 sekúnd" + }, + "thirtySeconds": { + "message": "30 sekúnd" + }, + "oneMinute": { + "message": "1 minúta" + }, + "twoMinutes": { + "message": "2 minúty" + }, + "fiveMinutes": { + "message": "5 minút" + }, + "fifteenMinutes": { + "message": "15 minút" + }, + "thirtyMinutes": { + "message": "30 minút" + }, + "oneHour": { + "message": "1 hodina" + }, + "fourHours": { + "message": "4 hodiny" + }, + "onIdle": { + "message": "Keď je systém nečinný" + }, + "onSleep": { + "message": "Keď je systém v režime spánku" + }, + "onLocked": { + "message": "Keď je systém uzamknutý" + }, + "onRestart": { + "message": "Pri reštarte" + }, + "never": { + "message": "Nikdy" + }, + "security": { + "message": "Zabezpečenie" + }, + "clearClipboard": { + "message": "Vymazať schránku", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automaticky vymazať skopírované hodnoty zo schránky.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Nezobrazovať ikony stránok" + }, + "disableFaviconDesc": { + "message": "Ikony stránok poskytujú rozoznateľný obrázok vedľa každého prihlasovacieho údaju vo webovom trezore." + }, + "enableMinToTray": { + "message": "Minimalizovať na panel úloh" + }, + "enableMinToTrayDesc": { + "message": "Namiesto minimalizácie okna zobraziť ikonu v systémovej lište." + }, + "enableMinToMenuBar": { + "message": "Minimalizovať na panel úloh" + }, + "enableMinToMenuBarDesc": { + "message": "Namiesto minimalizácie okna zobraziť ikonu na paneli úloh." + }, + "enableCloseToTray": { + "message": "Zatvoriť do systémovej lišty" + }, + "enableCloseToTrayDesc": { + "message": "Namiesto zatvorenia okna zobraziť ikonu v systémovej lište." + }, + "enableCloseToMenuBar": { + "message": "Zavrieť na panel úloh" + }, + "enableCloseToMenuBarDesc": { + "message": "Namiesto zatvorenia okna zobraziť ikonu na paneli úloh." + }, + "enableTray": { + "message": "Povoliť ikonu na systémovej lište" + }, + "enableTrayDesc": { + "message": "Vždy zobraziť ikonu na systémovej lište." + }, + "startToTray": { + "message": "Spustiť minimalizované do ikony v systémovej lište" + }, + "startToTrayDesc": { + "message": "Pri prvom spustení aplikácie zobraziť iba ikonu v systémovej lište." + }, + "startToMenuBar": { + "message": "Spustiť na panel úloh" + }, + "startToMenuBarDesc": { + "message": "Pri prvom spustení aplikácie zobraziť iba ikonu na paneli úloh." + }, + "openAtLogin": { + "message": "Automaticky spustiť po prihlásení" + }, + "openAtLoginDesc": { + "message": "Po prihlásení automaticky spustí aplikáciu Bitwarden Desktop." + }, + "alwaysShowDock": { + "message": "Vždy zobraziť v docku" + }, + "alwaysShowDockDesc": { + "message": "Zobraziť Bitwarden v Docku aj keď je minimalizovaný na panel úloh." + }, + "confirmTrayTitle": { + "message": "Potvrdiť vypnutie systémovej lišty" + }, + "confirmTrayDesc": { + "message": "Vypnutím tohto nastavenia vypnete aj ostatné nastavenia súvisiace so systémovou lištou." + }, + "language": { + "message": "Jazyk" + }, + "languageDesc": { + "message": "Zmeňte jazyk aplikácie. Vyžaduje reštart." + }, + "theme": { + "message": "Motív" + }, + "themeDesc": { + "message": "Zmeniť farebný motív aplikácie." + }, + "dark": { + "message": "Tmavý", + "description": "Dark color" + }, + "light": { + "message": "Svetlý", + "description": "Light color" + }, + "copy": { + "message": "Kopírovať", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Skontrolovať aktualizácie" + }, + "version": { + "message": "Verzia $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Reštartovať pre dokončenie aktualizácie" + }, + "restartToUpdateDesc": { + "message": "Verzia $VERSION_NUM$ je pripravená na inštaláciu. Je nutné reštartovať aplikáciu, aby sa inštalácia mohla dokončiť. Chcete ju reŝtartovať a aktualizovať teraz?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "K dispozícii je nová aktualizácia" + }, + "updateAvailableDesc": { + "message": "Je dostupná nová aktualizácia. Chcete ju stiahnuť teraz?" + }, + "restart": { + "message": "Reštartovať" + }, + "later": { + "message": "Neskôr" + }, + "noUpdatesAvailable": { + "message": "K dispozícii nie sú žiadne aktualizácie. Používate poslednú verziu." + }, + "updateError": { + "message": "Chyba aktualizácie" + }, + "unknown": { + "message": "Neznáme" + }, + "copyUsername": { + "message": "Kopírovať používateľské meno" + }, + "copyNumber": { + "message": "Kopírovať číslo", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopírovať bezpečnostný kód", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Prémiové členstvo" + }, + "premiumManage": { + "message": "Spravovať členstvo" + }, + "premiumManageAlert": { + "message": "Svoje členstvo môžete spravovať vo webovom trezore bitwarden.com. Chcete navštíviť túto stránku teraz?" + }, + "premiumRefresh": { + "message": "Obnoviť členstvo" + }, + "premiumNotCurrentMember": { + "message": "Momentálne nie ste prémiovým členom." + }, + "premiumSignUpAndGet": { + "message": "Zaregistrujte sa pre prémiové členstvo a získajte:" + }, + "premiumSignUpStorage": { + "message": "1 GB šifrovaného úložiska." + }, + "premiumSignUpTwoStep": { + "message": "Ďalšie možnosti dvojstupňového prihlásenia ako YubiKey, FIDO U2F a Duo." + }, + "premiumSignUpReports": { + "message": "Správy o sile hesla, zabezpečení účtov a únikoch dát ktoré vám pomôžu udržať vaše kontá v bezpečí." + }, + "premiumSignUpTotp": { + "message": "Generátor TOTP verifikačného kódu (2FA) pre kontá vo vašom trezore." + }, + "premiumSignUpSupport": { + "message": "Prioritná zákaznícka podpora." + }, + "premiumSignUpFuture": { + "message": "Všetky budúce prémiové funkcie. Viac už čoskoro!" + }, + "premiumPurchase": { + "message": "Zakúpiť Prémium" + }, + "premiumPurchaseAlert": { + "message": "Svoje prémiové členstvo môžete zakúpiť vo webovom trezore bitwarden.com. Chcete navštíviť túto stránku teraz?" + }, + "premiumCurrentMember": { + "message": "Ste prémiovým členom!" + }, + "premiumCurrentMemberThanks": { + "message": "Ďakujeme za podporu Bitwarden." + }, + "premiumPrice": { + "message": "Všetko len za $PRICE$/rok!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Obnova kompletná" + }, + "passwordHistory": { + "message": "História hesla" + }, + "clear": { + "message": "Vyčistiť", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Neboli nájdené žiadne heslá." + }, + "undo": { + "message": "Späť" + }, + "redo": { + "message": "Opakovať" + }, + "cut": { + "message": "Vystrihnúť", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Vložiť", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Označiť všetko" + }, + "zoomIn": { + "message": "Priblížiť" + }, + "zoomOut": { + "message": "Oddialiť" + }, + "resetZoom": { + "message": "Obnoviť pôvodné zobrazenie" + }, + "toggleFullScreen": { + "message": "Prepnúť na celú obrazovku" + }, + "reload": { + "message": "Znovu načítať" + }, + "toggleDevTools": { + "message": "Prepnúť vývojárske nástroje" + }, + "minimize": { + "message": "Minimalizovať", + "description": "Minimize window" + }, + "zoom": { + "message": "Priblíženie" + }, + "bringAllToFront": { + "message": "Preniesť všetko dopredu", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "O Bitwarden" + }, + "services": { + "message": "Služby" + }, + "hideBitwarden": { + "message": "Skryť Bitwarden" + }, + "hideOthers": { + "message": "Skryť ostatné" + }, + "showAll": { + "message": "Zobraziť všetky" + }, + "quitBitwarden": { + "message": "Ukončiť Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ skopírované", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Nápoveď" + }, + "window": { + "message": "Okno" + }, + "checkPassword": { + "message": "Overiť či došlo k úniku hesla." + }, + "passwordExposed": { + "message": "Toto heslo uniklo $VALUE$-krát v dátových únikoch. Mali by ste ho zmeniť.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Heslo nebolo nájdene v žiadnom úniku dát. Malo by byť bezpečné." + }, + "baseDomain": { + "message": "Základná doména", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Názov domény", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Hostiteľ", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Presný" + }, + "startsWith": { + "message": "Začína na" + }, + "regEx": { + "message": "Regulárny výraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Spôsob mapovania", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Predvolené mapovanie", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Voľby prepínača" + }, + "organization": { + "message": "Organizácia", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Predvolené" + }, + "exit": { + "message": "Ukončiť" + }, + "showHide": { + "message": "Zobraziť / Skryť", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Skryť do systémovej lišty" + }, + "alwaysOnTop": { + "message": "Vždy na vrchu", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Aktualizované", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Heslo bolo aktualizované", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export trezoru" + }, + "fileFormat": { + "message": "Formát Súboru" + }, + "warning": { + "message": "UPOZORNENIE", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potvrdiť export trezoru" + }, + "exportWarningDesc": { + "message": "Tento export obsahuje vaše dáta v nešifrovanom formáte. Nemali by ste ich ukladať, ani posielať cez nezabezpečené kanály (napr. email). Okamžite ho odstráňte, keď ho prestanete používať." + }, + "encExportKeyWarningDesc": { + "message": "Tento export zašifruje vaše údaje pomocou šifrovacieho kľúča vášho účtu. Ak niekedy budete rotovať šifrovací kľúč svojho účtu, mali by ste exportovať znova, pretože nebudete môcť dešifrovať tento exportovaný súbor." + }, + "encExportAccountWarningDesc": { + "message": "Šifrovacie kľúče účtu sú jedinečné pre každý používateľský účet Bitwarden, takže nemôžete importovať šifrovaný export do iného účtu." + }, + "noOrganizationsList": { + "message": "Nie ste členom žiadnej organizácie. Organizácie umožňujú bezpečne zdieľať položky s ostatnými používateľmi." + }, + "noCollectionsInList": { + "message": "Neexistujú žiadne zbierky na zobrazenie." + }, + "ownership": { + "message": "Vlastníctvo" + }, + "whoOwnsThisItem": { + "message": "Kto vlastní túto položku?" + }, + "strong": { + "message": "Silné", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobré", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Slabé", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Slabé hlavné heslo" + }, + "weakMasterPasswordDesc": { + "message": "Hlavné heslo, ktoré ste zadali, je slabé. Mali by ste použiť silné heslo (alebo frázu), aby ste spoľahlivo ochránili váš Bitwarden účet. Naozaj chcete použiť toto heslo?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Odomknúť pomocou PIN" + }, + "setYourPinCode": { + "message": "Nastaviť PIN kód na odomknutie Bitwarden. Nastavenie PIN sa vynuluje, ak úplne odhlásite z aplikácie." + }, + "pinRequired": { + "message": "PIN kód je povinný." + }, + "invalidPin": { + "message": "Neplatný PIN kód." + }, + "unlockWithWindowsHello": { + "message": "Odomknúť pomocou Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Overiť sa pre Bitwarden." + }, + "unlockWithTouchId": { + "message": "Odomknúť s Touch ID" + }, + "touchIdConsentMessage": { + "message": "odomknúť svoj trezor" + }, + "noAutoPromptWindowsHello": { + "message": "Pri spustení nezobrazovať výzvu na Windows Hello." + }, + "noAutoPromptTouchId": { + "message": "Pri spustení nezobrazovať výzvu na Touch ID." + }, + "lockWithMasterPassOnRestart": { + "message": "Pri reštarte zamknúť s hlavným heslom" + }, + "preferences": { + "message": "Predvoľby" + }, + "enableMenuBar": { + "message": "Povoliť ikonu na paneli úloh" + }, + "enableMenuBarDesc": { + "message": "Vždy zobraziť ikonu na paneli úloh." + }, + "hideToMenuBar": { + "message": "Skryť do panela úloh" + }, + "selectOneCollection": { + "message": "Musíte vybrať aspoň jednu zbierku." + }, + "premiumUpdated": { + "message": "Povýšili ste na prémium." + }, + "restore": { + "message": "Obnoviť" + }, + "premiumManageAlertAppStore": { + "message": "Predplatné môžete spravovať cez App Store. Chcete navštíviť App Store teraz?" + }, + "legal": { + "message": "Právne informácie", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Podmienky používania" + }, + "privacyPolicy": { + "message": "Zásady ochrany osobných údajov" + }, + "unsavedChangesConfirmation": { + "message": "Ste si istý, že chcete odísť? Ak teraz odídete, vaše aktuálne informácie nebudú uložené." + }, + "unsavedChangesTitle": { + "message": "Neuložené zmeny" + }, + "clone": { + "message": "Klonovať" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Jedno alebo viac nastavení organizácie ovplyvňujú vaše nastavenia generátora." + }, + "vaultTimeoutAction": { + "message": "Akcia pri vypršaní času pre trezor" + }, + "vaultTimeoutActionLockDesc": { + "message": "Uzamknutý trezor sa dá odomknúť opätovným zadaním hlavného hesla." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Odhlásený trezor bude vyžadovať opätovné prihlásenie aby ste k nemu mohli pristupovať." + }, + "lock": { + "message": "Uzamknúť", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Kôš", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Hľadať v koši" + }, + "permanentlyDeleteItem": { + "message": "Natrvalo odstrániť položku" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Naozaj chcete natrvalo odstrániť túto položku?" + }, + "permanentlyDeletedItem": { + "message": "Položka natrvalo odstránená" + }, + "restoreItem": { + "message": "Obnoviť položku" + }, + "restoreItemConfirmation": { + "message": "Naozaj chcete obnoviť túto položku?" + }, + "restoredItem": { + "message": "Obnovená položka" + }, + "permanentlyDelete": { + "message": "Natrvalo odstrániť" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Odhlásenie bude vyžadovať online prihlásenie po vypršaní časového limitu. Naozaj chcete použiť toto nastavenie?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Potvrdenie akcie pre vypršaný časový limit" + }, + "enterpriseSingleSignOn": { + "message": "Jednotné prihlásenie pre podniky (SSO)" + }, + "setMasterPassword": { + "message": "Nastaviť hlavné heslo" + }, + "ssoCompleteRegistration": { + "message": "Aby ste dokončili nastavenie prihlasovacieho portálu (SSO), prosím nastavte hlavné heslo na prístup a ochranu vášho trezora." + }, + "newMasterPass": { + "message": "Nové hlavné heslo" + }, + "confirmNewMasterPass": { + "message": "Potvrďte nové hlavné heslo" + }, + "masterPasswordPolicyInEffect": { + "message": "Jedno alebo viac pravidiel organizácie požadujú aby vaše hlavné heslo spĺňalo nasledujúce požiadavky:" + }, + "policyInEffectMinComplexity": { + "message": "Minimálna úroveň zložitosti $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimálna dĺžka $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Obsahuje aspoň jedno veľké písmeno" + }, + "policyInEffectLowercase": { + "message": "Obsahuje aspoň jedno malé písmeno" + }, + "policyInEffectNumbers": { + "message": "Obsahuje aspoň jednu číslicu" + }, + "policyInEffectSpecial": { + "message": "Obsahuje aspoň jeden z následujúcich špeciálnych znakov $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Vaše nové hlavné heslo nespĺňa pravidlá." + }, + "acceptPolicies": { + "message": "Označením tohto políčka súhlasíte s nasledovným:" + }, + "acceptPoliciesError": { + "message": "Neboli akceptované Podmienky používania a zásady Ochrany osobných údajov." + }, + "enableBrowserIntegration": { + "message": "Povoliť integráciu v prehliadači" + }, + "enableBrowserIntegrationDesc": { + "message": "Integrácia v prehliadači sa používa na biometriu v prehliadači." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Integrácia v prehliadači nie je podporovaná" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Bohužiaľ, integrácia v prehliadači je zatiaľ podporovaná iba vo verzii Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Integrácia v prehliadači nie je podporovaná" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Bohužiaľ, integrácia v prehliadači je zatiaľ podporovaná iba vo verzii Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Vyžadovať overenie pre integráciu v prehliadači" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Povoliť dodatočné zabezpečenie tým, že bude potrebné overenie odtlačku pri prepájaní desktopovej aplikácie a prehliadača. Ak je toto nastavenie zapnuté, pri každom pripojení bude od používateľa požadované overenie." + }, + "approve": { + "message": "Schváliť" + }, + "verifyBrowserTitle": { + "message": "Overiť pripojenie prehliadača" + }, + "verifyBrowserDesc": { + "message": "Uistite sa, že zobrazený odtlačok prsta je identický s odtlačkom prsta zobrazeným v rozšírení prehliadača." + }, + "biometricsNotEnabledTitle": { + "message": "Biometria nie je aktivovaná" + }, + "biometricsNotEnabledDesc": { + "message": "Biometria prehliadača vyžaduje, aby bola najskôr v nastaveniach povolená biometria počítača." + }, + "personalOwnershipSubmitError": { + "message": "Z dôvodu podnikovej politiky máte obmedzené ukladanie položiek do osobného trezora. Zmeňte možnosť vlastníctvo na organizáciu a vyberte si z dostupných zbierok." + }, + "hintEqualsPassword": { + "message": "Nápoveda pre heslo nemôže byť rovnaká ako heslo." + }, + "personalOwnershipPolicyInEffect": { + "message": "Politika organizácie ovplyvňuje vaše možnosti vlastníctva." + }, + "allSends": { + "message": "Všetky Sendy", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Súbor" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Hľadať Sendy", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Upraviť Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Môj trezor" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Dátum odstránenia" + }, + "deletionDateDesc": { + "message": "Send bude natrvalo odstránený v zadaný dátum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Dátum exspirácie" + }, + "expirationDateDesc": { + "message": "Ak je nastavené, prístup k tomuto Sendu vyprší v zadaný dátum a čas.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximálny počet prístupov" + }, + "maxAccessCountDesc": { + "message": "Ak je nastavené, používatelia už nebudú mať prístup k tomuto Sendu po dosiahnutí maximálneho počtu prístupov.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Súčasný počet prístupov" + }, + "disableSend": { + "message": "Vypnúť tento Send, aby k nemu nikto nemal prístup.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Voliteľne môžete vyžadovať heslo pre používateľov na prístup k tomuto Sendu.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Zabezpečená poznámka o tomto Sende.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Odkaz na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Odkaz na Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Pri prístupe k Sendu, predvolene skryť text", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send vytvorený", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send upravený", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send odstránený", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nové heslo" + }, + "whatTypeOfSend": { + "message": "Aký typ Sendu to je?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Vytvoriť Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Text, ktorý chcete odoslať." + }, + "sendFileDesc": { + "message": "Súbor, ktorý chcete odoslať." + }, + "days": { + "message": "$DAYS$ dní", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 deň" + }, + "custom": { + "message": "Vlastné" + }, + "deleteSendConfirmation": { + "message": "Naozaj chcete odstrániť tento Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Kopírovať odkaz na Send do schránky", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kopírovať odkaz na zdieľanie tohto Sendu do schránky počas ukladania." + }, + "sendDisabled": { + "message": "Funkcia Send zakázaná", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Z dôvodu podnikovej politiky môžete odstrániť iba existujúci Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopírovať odkaz" + }, + "disabled": { + "message": "Zakázané" + }, + "maxAccessCountReached": { + "message": "Bol dosiahnutý maximálny počet prístupov" + }, + "expired": { + "message": "Exspirované" + }, + "pendingDeletion": { + "message": "Čakajúce odstránenie" + }, + "webAuthnAuthenticate": { + "message": "Overiť cez WebAuthn" + }, + "hideEmail": { + "message": "Skryť moju emailovú adresu pred príjemcami." + }, + "sendOptionsPolicyInEffect": { + "message": "Jedno alebo viac pravidiel organizácie ovplyvňujú vaše možnosti funkcie Send." + }, + "emailVerificationRequired": { + "message": "Vyžaduje sa overenie e-mailu" + }, + "emailVerificationRequiredDesc": { + "message": "Na používanie tejto funkcie musíte overiť svoj e-mail." + }, + "passwordPrompt": { + "message": "Znova zadajte hlavné heslo" + }, + "passwordConfirmation": { + "message": "Potvrdenie hlavného hesla" + }, + "passwordConfirmationDesc": { + "message": "Táto akcia je chránená. Ak chcete pokračovať, znova zadajte hlavné heslo a overte svoju totožnosť." + }, + "updatedMasterPassword": { + "message": "Hlavné heslo aktualizované" + }, + "updateMasterPassword": { + "message": "Aktualizovať hlavné heslo" + }, + "updateMasterPasswordWarning": { + "message": "Vaše hlavné heslo nedávno zmenil správca vo vašej organizácii. Ak chcete získať prístup k trezoru, musíte ho teraz aktualizovať. Pokračovaním sa odhlásite z aktuálnej relácie a budete sa musieť znova prihlásiť. Aktívne relácie na iných zariadeniach môžu zostať aktívne až jednu hodinu." + }, + "hours": { + "message": "Hodiny" + }, + "minutes": { + "message": "Minúty" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Zásady vašej organizácie ovplyvňujú časový limit trezoru. Maximálny povolený časový limit trezoru je $HOURS$ h a $MINUTES$ m", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Časový limit vášho trezora prekračuje obmedzenia nastavené vašou organizáciou." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatická registrácia" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Táto organizácia má podnikovú politiku, ktorá vás automaticky zaregistruje na obnovenie hesla. Registrácia umožní správcom organizácie zmeniť vaše hlavné heslo." + }, + "vaultExportDisabled": { + "message": "Export trezoru je zakázaný" + }, + "personalVaultExportPolicyInEffect": { + "message": "Jedna alebo viacero zásad organizácie vám bráni exportovať váš osobný trezor." + }, + "addAccount": { + "message": "Pridať účet" + }, + "removeMasterPassword": { + "message": "Odstrániť hlavné heslo" + }, + "removedMasterPassword": { + "message": "Hlavné heslo bolo odstránené." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ používa SSO s vlastným kľúčovým serverom. Na prihlásenie členov tejto organizácie už nie je potrebné hlavné heslo.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Opustiť organizáciu" + }, + "leaveOrganizationConfirmation": { + "message": "Ste si istý, že chcete opustiť túto organizáciu?" + }, + "leftOrganization": { + "message": "Opustili ste organizáciu." + }, + "ssoKeyConnectorUnavailable": { + "message": "Nie je možné kontaktovať kľúčový konektor, skúste to znova neskôr." + }, + "lockAllVaults": { + "message": "Zamknúť všetky trezory" + }, + "accountLimitReached": { + "message": "Súčasne nemôže byť prihlásených viac ako 5 účtov." + }, + "accountPreferences": { + "message": "Predvoľby" + }, + "appPreferences": { + "message": "Nastavenia aplikácie (Všetky účty)" + }, + "accountSwitcherLimitReached": { + "message": "Dosiahnutý limit počtu účtov. Odhláste sa z účtu aby ste mohli pridať ďalší." + }, + "settingsTitle": { + "message": "Nastavenia aplikácie pre $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Prepnúť účet" + }, + "options": { + "message": "Možnosti" + }, + "sessionTimeout": { + "message": "Vaša relácia vypršala. Vráťte sa späť a skúste sa prihlásiť znova." + }, + "exportingPersonalVaultTitle": { + "message": "Exportovanie osobného trezora" + }, + "exportingPersonalVaultDescription": { + "message": "Exportované budú iba položy osobného trezora spojené s $EMAIL$. Položky trezora organizácie nebudú zahrnuté.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generátor" + }, + "whatWouldYouLikeToGenerate": { + "message": "Čo by ste chceli vygenerovať?" + }, + "passwordType": { + "message": "Typ hesla" + }, + "regenerateUsername": { + "message": "Vygenerovať nové používateľské meno" + }, + "generateUsername": { + "message": "Vygenerovať používateľské meno" + }, + "usernameType": { + "message": "Typ používateľského mena" + }, + "plusAddressedEmail": { + "message": "E-mail s plusovým aliasom" + }, + "plusAddressedEmailDesc": { + "message": "Použiť možnosti subadresovania svojho poskytovateľa e-mailu." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Použiť doručenú poštu typu catch-all nastavenú na doméne." + }, + "random": { + "message": "Náhodné" + }, + "randomWord": { + "message": "Náhodné slovo" + }, + "websiteName": { + "message": "Názov stránky" + }, + "service": { + "message": "Služba" + } +} diff --git a/apps/desktop/src/locales/sl/messages.json b/apps/desktop/src/locales/sl/messages.json new file mode 100644 index 0000000000..00e8d4063c --- /dev/null +++ b/apps/desktop/src/locales/sl/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtri" + }, + "allItems": { + "message": "Vsi elementi" + }, + "favorites": { + "message": "Priljubljene" + }, + "types": { + "message": "Tipi" + }, + "typeLogin": { + "message": "Prijava" + }, + "typeCard": { + "message": "Kartica" + }, + "typeIdentity": { + "message": "Identiteta" + }, + "typeSecureNote": { + "message": "Varni zapisek" + }, + "folders": { + "message": "Mape" + }, + "collections": { + "message": "Zbirke" + }, + "searchVault": { + "message": "Išči v trezorju" + }, + "addItem": { + "message": "Dodaj vnos" + }, + "shared": { + "message": "Deljeno" + }, + "share": { + "message": "Deli" + }, + "moveToOrganization": { + "message": "Premakni v organizacijo" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ premaknjen v $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Priloge" + }, + "viewItem": { + "message": "Ogled vnosa" + }, + "name": { + "message": "Naziv" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Nov URI" + }, + "username": { + "message": "Uporabniško ime" + }, + "password": { + "message": "Geslo" + }, + "passphrase": { + "message": "Šifrirna fraza" + }, + "editItem": { + "message": "Uredi vnos" + }, + "emailAddress": { + "message": "E-poštni naslov" + }, + "verificationCodeTotp": { + "message": "Verifikacijska koda (TOTP)" + }, + "website": { + "message": "Spletna stran" + }, + "notes": { + "message": "Zapiski" + }, + "customFields": { + "message": "Polja po meri" + }, + "launch": { + "message": "Zaženi" + }, + "copyValue": { + "message": "Kopiraj vrednost", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimiziraj okno pri kopiranju v odložišče" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimiziraj pri kopiranju podatkov elementa v odložišče." + }, + "toggleVisibility": { + "message": "Preklopi vidljivost" + }, + "toggleCollapse": { + "message": "Skrči/Razširi", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Imetnik kartice" + }, + "number": { + "message": "Številka" + }, + "brand": { + "message": "Znamka" + }, + "expiration": { + "message": "Datum poteka" + }, + "securityCode": { + "message": "Varnostna koda" + }, + "identityName": { + "message": "Ime identitete" + }, + "company": { + "message": "Podjetje" + }, + "ssn": { + "message": "Številka socialne varnosti" + }, + "passportNumber": { + "message": "Številka potnega lista" + }, + "licenseNumber": { + "message": "Številka dovoljenja" + }, + "email": { + "message": "E-pošta" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Naslov" + }, + "premiumRequired": { + "message": "Potrebno je premium članstvo" + }, + "premiumRequiredDesc": { + "message": "Za uporabo te funkcije je potrebno premium članstvo." + }, + "errorOccurred": { + "message": "Prišlo je do napake." + }, + "error": { + "message": "Napaka" + }, + "january": { + "message": "Januar" + }, + "february": { + "message": "Februar" + }, + "march": { + "message": "Marec" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Junij" + }, + "july": { + "message": "Julij" + }, + "august": { + "message": "Avgust" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "npr.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Naziv" + }, + "mr": { + "message": "G" + }, + "mrs": { + "message": "Ga" + }, + "ms": { + "message": "Gdč" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Mesec poteka" + }, + "expirationYear": { + "message": "Leto poteka" + }, + "select": { + "message": "Izberi" + }, + "other": { + "message": "Drugo" + }, + "generatePassword": { + "message": "Generiraj geslo" + }, + "type": { + "message": "Tip" + }, + "firstName": { + "message": "Ime" + }, + "middleName": { + "message": "Srednje ime" + }, + "lastName": { + "message": "Priimek" + }, + "fullName": { + "message": "Polno ime" + }, + "address1": { + "message": "Naslov 1" + }, + "address2": { + "message": "Naslov 2" + }, + "address3": { + "message": "Naslov 3" + }, + "cityTown": { + "message": "Mesto / Naselje" + }, + "stateProvince": { + "message": "Država / Regija" + }, + "zipPostalCode": { + "message": "Poštna številka" + }, + "country": { + "message": "Država" + }, + "save": { + "message": "Shrani" + }, + "cancel": { + "message": "Prekliči" + }, + "delete": { + "message": "Izbriši" + }, + "favorite": { + "message": "Priljubljeno" + }, + "edit": { + "message": "Uredi" + }, + "authenticatorKeyTotp": { + "message": "Ključ avtentikatorja (TOTP)" + }, + "folder": { + "message": "Mapa" + }, + "newCustomField": { + "message": "Novo polje po meri" + }, + "value": { + "message": "Vrednost" + }, + "dragToSort": { + "message": "Povleci za sortiranje" + }, + "cfTypeText": { + "message": "Besedilo" + }, + "cfTypeHidden": { + "message": "Skrito" + }, + "cfTypeBoolean": { + "message": "Logična vrednost" + }, + "cfTypeLinked": { + "message": "Povezano", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Povezana vrednost", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Odstrani" + }, + "nameRequired": { + "message": "Ime je obvezen podatek." + }, + "addedItem": { + "message": "Vnos dodan" + }, + "editedItem": { + "message": "Vnos urejen" + }, + "deleteItem": { + "message": "Vnos odstranjen" + }, + "deleteFolder": { + "message": "Izbriši mapo" + }, + "deleteAttachment": { + "message": "Izbriši priponoko" + }, + "deleteItemConfirmation": { + "message": "Ali res želite poslati v koš?" + }, + "deletedItem": { + "message": "Pošlji vnos v smeti" + }, + "overwritePasswordConfirmation": { + "message": "Ali ste prepričani, da želite prepisati vaše trenutno geslo?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Brez mape", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Dodaj mapo" + }, + "editFolder": { + "message": "Uredi mapo" + }, + "regeneratePassword": { + "message": "Ponovno generiraj geslo" + }, + "copyPassword": { + "message": "Kopiraj geslo" + }, + "copyUri": { + "message": "Kopiraj URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopiraj verifikacijsko kodo (TOTP)" + }, + "length": { + "message": "Dolžina" + }, + "numWords": { + "message": "Število besed" + }, + "wordSeparator": { + "message": "Ločilo besed" + }, + "capitalize": { + "message": "Zapiši z veliko začetnico", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Vključi številko" + }, + "close": { + "message": "Zapri" + }, + "minNumbers": { + "message": "Minimalna števila" + }, + "minSpecial": { + "message": "Minimalno posebnih znakov", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Izogibaj se dvoumnim znakom" + }, + "searchCollection": { + "message": "Preišči zbirko" + }, + "searchFolder": { + "message": "Preišči mapo" + }, + "searchFavorites": { + "message": "Preišči priljubljene" + }, + "searchType": { + "message": "Preišči po tipih", + "description": "Search item type" + }, + "newAttachment": { + "message": "Dodaj novo priponko" + }, + "deletedAttachment": { + "message": "Izbriši priponko" + }, + "deleteAttachmentConfirmation": { + "message": "Ste prepričani, da želite izbrisati to priponko?" + }, + "attachmentSaved": { + "message": "Priponka je bila shranjena." + }, + "file": { + "message": "Datoteka" + }, + "selectFile": { + "message": "Izberite datoteko." + }, + "maxFileSize": { + "message": "Največja velikost datoteke je 500 MB." + }, + "updateKey": { + "message": "Te funkcije ne morete koristiti, dokler dokler ne posodobite vašega ključa za šifriranje." + }, + "editedFolder": { + "message": "Mapa je bila urejena" + }, + "addedFolder": { + "message": "Mapa je bila dodana" + }, + "deleteFolderConfirmation": { + "message": "Ali ste prepričani, da želite izbrisati to mapo?" + }, + "deletedFolder": { + "message": "Mapa je bila izbrisana" + }, + "loginOrCreateNewAccount": { + "message": "Prijavite se ali ustvarite nov račun za dostop do vašega varnega trezorja." + }, + "createAccount": { + "message": "Ustvari račun" + }, + "logIn": { + "message": "Prijava" + }, + "submit": { + "message": "Potrdi" + }, + "masterPass": { + "message": "Glavno geslo" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "Nastavitve" + }, + "passwordHint": { + "message": "Namig za geslo" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "Get master password hint" + }, + "emailRequired": { + "message": "Email address is required." + }, + "invalidEmail": { + "message": "Neveljaven epoštni naslov." + }, + "masterPassRequired": { + "message": "Master password is required." + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "Informacije o vnosu" + }, + "noItemsInList": { + "message": "Ni vnosov za prikaz." + }, + "sendVerificationCode": { + "message": "Pošlji verifikacijsko kodo po e-pošti" + }, + "sendCode": { + "message": "Pošlji kodo" + }, + "codeSent": { + "message": "Koda poslana" + }, + "verificationCode": { + "message": "Verifikacijska koda" + }, + "confirmIdentity": { + "message": "Potrdite svojo identiteto za nadaljevanje." + }, + "verificationCodeRequired": { + "message": "Potrebna je verifikacijska koda." + }, + "invalidVerificationCode": { + "message": "Neveljavna verifikacijska koda" + }, + "continue": { + "message": "Nadaljuj" + }, + "enterVerificationCodeApp": { + "message": "Vnesite 6-mestno verifikacijsko kodo iz vaše avtentikacijske aplikacije." + }, + "enterVerificationCodeEmail": { + "message": "Vnesite 6-mestno verifikacijsko kodo, ki vam je bila poslana na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Potrditveno sporočilo poslano na $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Zapomni si me" + }, + "sendVerificationCodeEmailAgain": { + "message": "Ponovno pošlji verifikacijsko kodo" + }, + "useAnotherTwoStepMethod": { + "message": "Use another two-step login method" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "Koda za obnovitev" + }, + "authenticatorAppTitle": { + "message": "Avtentikacijska aplikacija" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "E-pošta" + }, + "emailDesc": { + "message": "Potrditvene kode vam bodo posredovane po e-pošti." + }, + "loginUnavailable": { + "message": "Prijava ni na voljo" + }, + "noTwoStepProviders": { + "message": "Ta račun ima omogočemo prijavo v dveh korakih, ampak nobena izmed konfiguriranih ni podprta v tem spletnem brskalniku." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "Two-step Login Options" + }, + "selfHostedEnvironment": { + "message": "Okolje z lastnim gostovanjem" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premises hosted Bitwarden installation." + }, + "customEnvironment": { + "message": "Okolje po meri" + }, + "customEnvironmentFooter": { + "message": "Za napredne uporabnike. Lahko specificirate osnovni URL, ločeno za vsako storitev." + }, + "baseUrl": { + "message": "URL naslov strežnika" + }, + "apiUrl": { + "message": "URL API strežnika" + }, + "webVaultUrl": { + "message": "URL strežniškega spletnega trezorja" + }, + "identityUrl": { + "message": "Prepoznaj strežnikov URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "URL strežnika ikon" + }, + "environmentSaved": { + "message": "Okoljski URLji so bili shranjeni." + }, + "ok": { + "message": "V redu" + }, + "yes": { + "message": "Da" + }, + "no": { + "message": "Ne" + }, + "overwritePassword": { + "message": "Prepiši geslo" + }, + "learnMore": { + "message": "Več o tem" + }, + "featureUnavailable": { + "message": "Funkcija ni na voljo" + }, + "loggedOut": { + "message": "Odjavljen" + }, + "loginExpired": { + "message": "Vaša seja je potekla." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Odjavi se" + }, + "addNewLogin": { + "message": "Dodaj prijavo" + }, + "addNewItem": { + "message": "Dodaj nov element" + }, + "addNewFolder": { + "message": "Dodaj novo mapo" + }, + "view": { + "message": "Pogled" + }, + "account": { + "message": "Račun" + }, + "loading": { + "message": "Nalaganje..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Generator gesel" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Prijavi napako" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Sledite nam" + }, + "syncVault": { + "message": "Sinhroniziraj trezor" + }, + "changeMasterPass": { + "message": "Spremeni glavno geslo" + }, + "changeMasterPasswordConfirmation": { + "message": "Svoje glavno geslo lahko spremenite v bitwarden.com spletnem trezorju. Želite obiskati spletno stran zdaj?" + }, + "fingerprintPhrase": { + "message": "Fraza prstnega odtisa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Fraza prstnega odtisa vašega računa", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Pojdite v spletni trezor" + }, + "getMobileApp": { + "message": "Priskrbite si mobilno aplikacijo" + }, + "getBrowserExtension": { + "message": "Namesti razširitev za brskalnik" + }, + "syncingComplete": { + "message": "Sinhronizacija končana" + }, + "syncingFailed": { + "message": "Sinhronizacija ni uspela" + }, + "yourVaultIsLocked": { + "message": "Vaš trezor je zaklenjen. Potrdite svojo identiteto za nadaljevanje." + }, + "unlock": { + "message": "Odkleni" + }, + "loggedInAsOn": { + "message": "Prijavljeni kot $EMAIL$ na $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Napačno glavno geslo" + }, + "twoStepLoginConfirmation": { + "message": "Avtentikacija v dveh korakih naredi vaš račun bolj varen, saj od vas zahteva, da svojo prijavo preverite z drugo napravo, kot je varnostni ključ, aplikacija za preverjanje pristnosti, SMS, telefonski klic ali e-pošta. V spletnem trezorju bitwarden.com je lahko omogočite prijavo v dveh korakih. Ali želite spletno stran obiskati sedaj?" + }, + "twoStepLogin": { + "message": "Prijava v dveh korakih" + }, + "vaultTimeout": { + "message": "Časovna omejitev trezorja" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "Nemudoma" + }, + "tenSeconds": { + "message": "10 sekund" + }, + "twentySeconds": { + "message": "20 sekund" + }, + "thirtySeconds": { + "message": "30 sekund" + }, + "oneMinute": { + "message": "1 minuta" + }, + "twoMinutes": { + "message": "2 minuti" + }, + "fiveMinutes": { + "message": "5 minut" + }, + "fifteenMinutes": { + "message": "15 minut" + }, + "thirtyMinutes": { + "message": "30 minut" + }, + "oneHour": { + "message": "1 ura" + }, + "fourHours": { + "message": "4 ure" + }, + "onIdle": { + "message": "Ob nedejavnosti sistema" + }, + "onSleep": { + "message": "Ob spanju sistema" + }, + "onLocked": { + "message": "Ob zaklepu sistema" + }, + "onRestart": { + "message": "Ob ponovnem zagonu aplikacije" + }, + "never": { + "message": "Nikoli" + }, + "security": { + "message": "Varnost" + }, + "clearClipboard": { + "message": "Počisti odložišče", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Samodejno počisti kopirane vrednosti iz odložišča.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Onemogoči ikone spletnih mest" + }, + "disableFaviconDesc": { + "message": "Ikone spletnih mest ponujajo prepoznavne ikone zraven prijav v vašem trezorju." + }, + "enableMinToTray": { + "message": "Pomanjšaj v orodno vrstico" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Jezik" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Spremeni temo aplikacije." + }, + "dark": { + "message": "Temna", + "description": "Dark color" + }, + "light": { + "message": "Svetla", + "description": "Light color" + }, + "copy": { + "message": "Kopiraj", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Preveri za posodobitve" + }, + "version": { + "message": "Različica $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Ponovno zaženi za posodobitev" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart the application to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Posodobitev je na voljo" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "Ponovno zaženi" + }, + "later": { + "message": "Pozneje" + }, + "noUpdatesAvailable": { + "message": "No updates are currently available. You are using the latest version." + }, + "updateError": { + "message": "Napaka pri posodabljanju" + }, + "unknown": { + "message": "Neznano" + }, + "copyUsername": { + "message": "Kopiraj uporabniško ime" + }, + "copyNumber": { + "message": "Kopiraj številko", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopiraj varnostno kodo", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium članstvo" + }, + "premiumManage": { + "message": "Upravljanje članstva" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Osvežite članstvo" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB encrypted storage for file attachments." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting Bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Osveževanje zaključeno" + }, + "passwordHistory": { + "message": "Zgodovina gesla" + }, + "clear": { + "message": "Počisti", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Ni gesel za na seznam." + }, + "undo": { + "message": "Razveljavi" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "Izreži", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Prilepi", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Izberi vse" + }, + "zoomIn": { + "message": "Povečaj" + }, + "zoomOut": { + "message": "Pomanjšaj" + }, + "resetZoom": { + "message": "Ponastavi povečavo" + }, + "toggleFullScreen": { + "message": "Celozaslonski način" + }, + "reload": { + "message": "Ponovno naloži" + }, + "toggleDevTools": { + "message": "Toggle Developer Tools" + }, + "minimize": { + "message": "Minimiziraj", + "description": "Minimize window" + }, + "zoom": { + "message": "Povečava" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Storitve" + }, + "hideBitwarden": { + "message": "Hide Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "Pokaži vse" + }, + "quitBitwarden": { + "message": "Izhod iz Bitwardena" + }, + "valueCopied": { + "message": "$VALUE$ copied", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Pomoč" + }, + "window": { + "message": "Okno" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "To geslo je bilo med ukradenimi podatki izpostavljeno $VALUE$ krat. Zamenjajte ga.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "To geslo do sedaj ni bilo najdeno v zbirkah ukradenih podatkov. Njegova uporaba bi morala biti varna." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Gostitelj", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Točno" + }, + "startsWith": { + "message": "Začne se z" + }, + "regEx": { + "message": "Regularni izraz", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Zaznavanje ujemanja", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Privzet način ujemanja", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organizacija", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Privzeto" + }, + "exit": { + "message": "Izhod" + }, + "showHide": { + "message": "Prikaži / Skrij", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Vedno na vrhu", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Posodobljeno", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Geslo je bilo posodobljeno", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Izvoz trezorja" + }, + "fileFormat": { + "message": "Format datoteke" + }, + "warning": { + "message": "OPOZORILO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Potrdite izvoz trezorja" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Lastništvo" + }, + "whoOwnsThisItem": { + "message": "Kdo je lastnik tega vnosa?" + }, + "strong": { + "message": "Močno", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Dobro", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Šibko", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Šibko glavno geslo" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Odkleni s PIN kodo" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "Potrebna je PIN koda." + }, + "invalidPin": { + "message": "Nepravilna koda PIN." + }, + "unlockWithWindowsHello": { + "message": "Odkleni z WindowsHello" + }, + "windowsHelloConsentMessage": { + "message": "Preverite za Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "odklenite vaš trezor" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Zakleni z glavnim geslom ob ponovnem zagonu" + }, + "preferences": { + "message": "Možnosti" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Odobri" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "Vsi Sendsi", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Datoteka" + }, + "sendTypeText": { + "message": "Besedilo" + }, + "searchSends": { + "message": "Išči Sendse", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Uredi Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Moj trezor" + }, + "text": { + "message": "Besedilo" + }, + "deletionDate": { + "message": "Datum izbrisa" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Datum poteka" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Največje število dostopov" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Pošlji povezavo", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Pošlji povezavo", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send ustvarjen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send urejen", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send izbrisan", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Novo geslo" + }, + "whatTypeOfSend": { + "message": "Kakšne vrste Send je to?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Ustvari Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Besedilo, ki ga želite poslati." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Potrdi glavno geslo" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Glavno geslo je bilo posodobljeno" + }, + "updateMasterPassword": { + "message": "Posodobi glavno geslo" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Ure" + }, + "minutes": { + "message": "Minute" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Izvoz trezorja je onemogočen" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Odstranite glavno geslo" + }, + "removedMasterPassword": { + "message": "Glavno geslo je bilo odstranjeno." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Zapusti organizacijo" + }, + "leaveOrganizationConfirmation": { + "message": "Ste prepričani, da želite zapustiti to organizacijo?" + }, + "leftOrganization": { + "message": "Zapustili ste organizacijo." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/sr/messages.json b/apps/desktop/src/locales/sr/messages.json new file mode 100644 index 0000000000..832c19216b --- /dev/null +++ b/apps/desktop/src/locales/sr/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Филтери" + }, + "allItems": { + "message": "Све ставке" + }, + "favorites": { + "message": "Омиљени" + }, + "types": { + "message": "Врсте" + }, + "typeLogin": { + "message": "Пријава" + }, + "typeCard": { + "message": "Кредитна Картица" + }, + "typeIdentity": { + "message": "Идентитет" + }, + "typeSecureNote": { + "message": "Сигурносна белешка" + }, + "folders": { + "message": "Фасцикле" + }, + "collections": { + "message": "Колекције" + }, + "searchVault": { + "message": "Претражи сеф" + }, + "addItem": { + "message": "Додај ставку" + }, + "shared": { + "message": "Дељено" + }, + "share": { + "message": "Подели" + }, + "moveToOrganization": { + "message": "Премести у организацију" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ премештен у $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Изаберите организацију у коју желите да преместите овај предмет. Прелазак на организацију преноси власништво над ставком у ту организацију. Више нећете бити директни власник ове ставке након што је премештена." + }, + "attachments": { + "message": "Прилози" + }, + "viewItem": { + "message": "Види ставку" + }, + "name": { + "message": "Име" + }, + "uri": { + "message": "УРЛ" + }, + "uriPosition": { + "message": "УРЛ $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Нови УРЛ" + }, + "username": { + "message": "Корисничко име" + }, + "password": { + "message": "Лозинка" + }, + "passphrase": { + "message": "Скривена фраза" + }, + "editItem": { + "message": "Уреди ставку" + }, + "emailAddress": { + "message": "Имејл" + }, + "verificationCodeTotp": { + "message": "Једнократни код" + }, + "website": { + "message": "Веб сајт" + }, + "notes": { + "message": "Белешке" + }, + "customFields": { + "message": "Прилагођена Поља" + }, + "launch": { + "message": "Отвори" + }, + "copyValue": { + "message": "Копирај вредност", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Минимизирај приликом копирања у привремену меморију" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Минимизирај при копиранју података ставке у привремену меморију." + }, + "toggleVisibility": { + "message": "Промени видљивост" + }, + "toggleCollapse": { + "message": "Промени проширење", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Име Власника Картице" + }, + "number": { + "message": "Број" + }, + "brand": { + "message": "Произвођач" + }, + "expiration": { + "message": "Истек" + }, + "securityCode": { + "message": "Сигурносни код" + }, + "identityName": { + "message": "Име идентитета" + }, + "company": { + "message": "Предузеће" + }, + "ssn": { + "message": "Број социјалног осигурања" + }, + "passportNumber": { + "message": "Број пасоша" + }, + "licenseNumber": { + "message": "Број возачке дозволе" + }, + "email": { + "message": "Имејл" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адреса" + }, + "premiumRequired": { + "message": "Потребан Премијум" + }, + "premiumRequiredDesc": { + "message": "Премиум чланарина је неопходна како бисте користили ову опцију." + }, + "errorOccurred": { + "message": "Појавила се грешка." + }, + "error": { + "message": "Грешка" + }, + "january": { + "message": "Јануар" + }, + "february": { + "message": "Фебруар" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "Април" + }, + "may": { + "message": "Мај" + }, + "june": { + "message": "Јун" + }, + "july": { + "message": "Јул" + }, + "august": { + "message": "Август" + }, + "september": { + "message": "Септембар" + }, + "october": { + "message": "Октобар" + }, + "november": { + "message": "Новембар" + }, + "december": { + "message": "Децембар" + }, + "ex": { + "message": "нпр.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Наслов" + }, + "mr": { + "message": "Господин" + }, + "mrs": { + "message": "Госпођица" + }, + "ms": { + "message": "Госпођа" + }, + "dr": { + "message": "Др" + }, + "expirationMonth": { + "message": "Месец истека" + }, + "expirationYear": { + "message": "Година истека" + }, + "select": { + "message": "Изабери" + }, + "other": { + "message": "Остало" + }, + "generatePassword": { + "message": "Генерисање лозинке" + }, + "type": { + "message": "Тип" + }, + "firstName": { + "message": "Име" + }, + "middleName": { + "message": "Средње име" + }, + "lastName": { + "message": "Презиме" + }, + "fullName": { + "message": "Пуно име" + }, + "address1": { + "message": "Адреса 1" + }, + "address2": { + "message": "Адреса 2" + }, + "address3": { + "message": "Адреса 3" + }, + "cityTown": { + "message": "Град" + }, + "stateProvince": { + "message": "Држава / покрајина" + }, + "zipPostalCode": { + "message": "Поштански број" + }, + "country": { + "message": "Земља" + }, + "save": { + "message": "Сачувај" + }, + "cancel": { + "message": "Откажи" + }, + "delete": { + "message": "Обриши" + }, + "favorite": { + "message": "Омиљено" + }, + "edit": { + "message": "Уреди" + }, + "authenticatorKeyTotp": { + "message": "Једнократни код" + }, + "folder": { + "message": "Фасцикла" + }, + "newCustomField": { + "message": "Ново прилагођено поље" + }, + "value": { + "message": "Вредност" + }, + "dragToSort": { + "message": "Превуците за сортирање" + }, + "cfTypeText": { + "message": "Текст" + }, + "cfTypeHidden": { + "message": "Сакривено" + }, + "cfTypeBoolean": { + "message": "Булове" + }, + "cfTypeLinked": { + "message": "Повезано", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Вредност повезана", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Уклони" + }, + "nameRequired": { + "message": "Име је неопходно." + }, + "addedItem": { + "message": "Ставка додата" + }, + "editedItem": { + "message": "Ставка уређена" + }, + "deleteItem": { + "message": "Обриши ставку" + }, + "deleteFolder": { + "message": "Избриши фасциклу" + }, + "deleteAttachment": { + "message": "Избриши прилог" + }, + "deleteItemConfirmation": { + "message": "Сигурно послати ставку у отпад?" + }, + "deletedItem": { + "message": "Ставка послата у Отпад" + }, + "overwritePasswordConfirmation": { + "message": "Сигурно променити тренутну лозинку?" + }, + "overwriteUsername": { + "message": "Препиши име" + }, + "overwriteUsernameConfirmation": { + "message": "Сигурно преписати тренутно име?" + }, + "noneFolder": { + "message": "Без фасцикле", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Додај фасциклу" + }, + "editFolder": { + "message": "Уреди фасциклу" + }, + "regeneratePassword": { + "message": "Поново генериши лозинку" + }, + "copyPassword": { + "message": "Копирај лозинку" + }, + "copyUri": { + "message": "Копирај УРЛ" + }, + "copyVerificationCodeTotp": { + "message": "Копирај потврдни код (TOTP)" + }, + "length": { + "message": "Дужина" + }, + "numWords": { + "message": "Број речи" + }, + "wordSeparator": { + "message": "Одвајач речи" + }, + "capitalize": { + "message": "Прво слово велико", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Убаци број" + }, + "close": { + "message": "Затвори" + }, + "minNumbers": { + "message": "Минимално Бројева" + }, + "minSpecial": { + "message": "Минимално Специјално", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Избегавај двосмислене карактере" + }, + "searchCollection": { + "message": "Претражи колекцију" + }, + "searchFolder": { + "message": "Претражи фасциклу" + }, + "searchFavorites": { + "message": "Претражи омиљене" + }, + "searchType": { + "message": "Претражи тип", + "description": "Search item type" + }, + "newAttachment": { + "message": "Додај нови прилог" + }, + "deletedAttachment": { + "message": "Прилог избрисан" + }, + "deleteAttachmentConfirmation": { + "message": "Сигурно обрисати овај прилог?" + }, + "attachmentSaved": { + "message": "Прилог је сачуван." + }, + "file": { + "message": "Датотека" + }, + "selectFile": { + "message": "Изабери датотеку." + }, + "maxFileSize": { + "message": "Максимална величина је 500МБ." + }, + "updateKey": { + "message": "Не можете да користите ову опцију док не промените Ваш кључ за шифровање." + }, + "editedFolder": { + "message": "Фасцикла измењена" + }, + "addedFolder": { + "message": "Фасцикла додата" + }, + "deleteFolderConfirmation": { + "message": "Сигурно обрисати ову фасциклу?" + }, + "deletedFolder": { + "message": "Фасцикла обрисана" + }, + "loginOrCreateNewAccount": { + "message": "Пријавите се или креирајте нови налог за приступ Сефу." + }, + "createAccount": { + "message": "Креирај налог" + }, + "logIn": { + "message": "Пријавите се" + }, + "submit": { + "message": "Пошаљи" + }, + "masterPass": { + "message": "Главна Лозинка" + }, + "masterPassDesc": { + "message": "Главна Лозинка је лозинка коју користите за приступ Вашем сефу. Врло је важно да је не заборавите. Не постоји начин да повратите лозинку у случају да је заборавите." + }, + "masterPassHintDesc": { + "message": "Савет Главне Лозинке може да Вам помогне да се подсетите ако је заборавите." + }, + "reTypeMasterPass": { + "message": "Поновите Главну Лозинку" + }, + "masterPassHint": { + "message": "Савет Главне Лозинке (опционо)" + }, + "settings": { + "message": "Подешавања" + }, + "passwordHint": { + "message": "Савет главне лозинке" + }, + "enterEmailToGetHint": { + "message": "Унесите Ваш имејл да би добили савет за Вашу Главну Лозинку." + }, + "getMasterPasswordHint": { + "message": "Добити савет за Главну Лозинку" + }, + "emailRequired": { + "message": "Имејл је неопходан." + }, + "invalidEmail": { + "message": "Неисправан имејл." + }, + "masterPassRequired": { + "message": "Главна Лозинка је неопходна." + }, + "masterPassLength": { + "message": "Главна Лозинка треба имати бар 8 знака." + }, + "masterPassDoesntMatch": { + "message": "Потврђена Главна Лозинка се не подудара." + }, + "newAccountCreated": { + "message": "Ваш налог је креиран! Сада се можете пријавити." + }, + "masterPassSent": { + "message": "Послали смо Вам поруку са саветом главне лозинке." + }, + "unexpectedError": { + "message": "Дошло је до неочекиване грешке." + }, + "itemInformation": { + "message": "Инфо о ставци" + }, + "noItemsInList": { + "message": "Нема ставке која се може приказати." + }, + "sendVerificationCode": { + "message": "Пошаљите верификациони код на вашу е-пошту" + }, + "sendCode": { + "message": "Пошаљи код" + }, + "codeSent": { + "message": "Код послан" + }, + "verificationCode": { + "message": "Верификациони код" + }, + "confirmIdentity": { + "message": "Потврдите свој идентитет да би наставили." + }, + "verificationCodeRequired": { + "message": "Верификациони код је обавезан." + }, + "invalidVerificationCode": { + "message": "Неисправан верификациони код" + }, + "continue": { + "message": "Настави" + }, + "enterVerificationCodeApp": { + "message": "Унесите шестоцифрени верификациони код из апликације за утврђивање аутентичности." + }, + "enterVerificationCodeEmail": { + "message": "Унесите шестоцифрени верификациони код који је послан на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Провера имејла послата на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запамти ме" + }, + "sendVerificationCodeEmailAgain": { + "message": "Поново послати верификациони код на имејл" + }, + "useAnotherTwoStepMethod": { + "message": "Користите другу методу пријављивања у два корака" + }, + "insertYubiKey": { + "message": "Убаците свој YubiKey у УСБ порт рачунара, а затим додирните његово дугме." + }, + "insertU2f": { + "message": "Убаците свој сигурносни кључ у УСБ порт рачунара, и ако има дугме , додирните га." + }, + "recoveryCodeDesc": { + "message": "Изгубили сте приступ свим својим двофакторским добављачима? Употребите код за опоравак да онемогућите све двофакторске добављаче из налога." + }, + "recoveryCodeTitle": { + "message": "Шифра за опоравак" + }, + "authenticatorAppTitle": { + "message": "Апликација Аутентификатор" + }, + "authenticatorAppDesc": { + "message": "Користите апликацију за аутентификацију (као што је Authy или Google Authenticator) за генерисање верификационих кодова.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP сигурносни кључ" + }, + "yubiKeyDesc": { + "message": "Користите YubiKey за приступ налогу. Ради са YubiKey 4, 4 Nano, 4C, и NEO уређајима." + }, + "duoDesc": { + "message": "Провери са Duo Security користећи Duo Mobile апликацију, СМС, телефонски позив, или U2F кључ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Провери са Duo Security за вашу организацију користећи Duo Mobile апликацију, СМС, телефонски позив, или U2F кључ.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Користите било који WebAuthn сигурносни кључ за присту налогу." + }, + "emailTitle": { + "message": "Имејл" + }, + "emailDesc": { + "message": "Верификациони кодови ће вам бити послати имејлом." + }, + "loginUnavailable": { + "message": "Пријава недоступна" + }, + "noTwoStepProviders": { + "message": "Овај налог има омогућено пријављивање у два корака, међутим уређај не подржава ниједног од конфигурисаних добављача." + }, + "noTwoStepProviders2": { + "message": "Додајте додатне добављаче који су боље подржани на свим уређајима (као што је апликација за утврђивање аутентичности)." + }, + "twoStepOptions": { + "message": "Опције дво-коракне пријаве" + }, + "selfHostedEnvironment": { + "message": "Самостално окружење" + }, + "selfHostedEnvironmentFooter": { + "message": "Наведите основни УРЛ ваше локалне Bitwarden инсталације." + }, + "customEnvironment": { + "message": "Прилагођено окружење" + }, + "customEnvironmentFooter": { + "message": "За напредне кориснике. Можете да одредите независно основни УРЛ сваког сервиса." + }, + "baseUrl": { + "message": "УРЛ Сервера" + }, + "apiUrl": { + "message": "УРЛ АПИ Сервера" + }, + "webVaultUrl": { + "message": "УРЛ сервера Сефа" + }, + "identityUrl": { + "message": "УРЛ сервера идентитета" + }, + "notificationsUrl": { + "message": "УРЛ сервера обавештења" + }, + "iconsUrl": { + "message": "УРЛ сервера иконице" + }, + "environmentSaved": { + "message": "УРЛ адресе окружења су сачуване." + }, + "ok": { + "message": "У реду" + }, + "yes": { + "message": "Да" + }, + "no": { + "message": "Не" + }, + "overwritePassword": { + "message": "Промени лозинку" + }, + "learnMore": { + "message": "Сазнај више" + }, + "featureUnavailable": { + "message": "Функција је недоступна" + }, + "loggedOut": { + "message": "Одјављено" + }, + "loginExpired": { + "message": "Ваша сесија је истекла." + }, + "logOutConfirmation": { + "message": "Заиста желите да се одјавите?" + }, + "logOut": { + "message": "Одјави се" + }, + "addNewLogin": { + "message": "Додај нову пријаву" + }, + "addNewItem": { + "message": "Додај нову ставку" + }, + "addNewFolder": { + "message": "Додај нову фасциклу" + }, + "view": { + "message": "Приказ" + }, + "account": { + "message": "Налог" + }, + "loading": { + "message": "Учитавање..." + }, + "lockVault": { + "message": "Закључај сеф" + }, + "passwordGenerator": { + "message": "Генератор Лозинке" + }, + "contactUs": { + "message": "Контактирајте нас" + }, + "getHelp": { + "message": "Потражи помоћ" + }, + "fileBugReport": { + "message": "Пријавите грешку" + }, + "blog": { + "message": "Блог" + }, + "followUs": { + "message": "Пратите нас" + }, + "syncVault": { + "message": "Синхронизуј сеф" + }, + "changeMasterPass": { + "message": "Промени главну лозинку" + }, + "changeMasterPasswordConfirmation": { + "message": "Можете променити главну лозинку у Вашем сефу на bitwarden.com. Да ли желите да посетите веб страницу сада?" + }, + "fingerprintPhrase": { + "message": "Сигурносна Фраза Сефа", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Ваша Сигурносна Фраза Сефа", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Ићи на Сеф" + }, + "getMobileApp": { + "message": "Апликација за телефон" + }, + "getBrowserExtension": { + "message": "Додатак за прегледач" + }, + "syncingComplete": { + "message": "Синхронизација је завршена" + }, + "syncingFailed": { + "message": "Синхронизација није успела" + }, + "yourVaultIsLocked": { + "message": "Сеф је заклјучан. Унесите главну лозинку за наставак." + }, + "unlock": { + "message": "Откључај" + }, + "loggedInAsOn": { + "message": "Пријављено са $EMAIL$ на $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Погрешна главна лозинка" + }, + "twoStepLoginConfirmation": { + "message": "Пријава у два корака чини ваш налог сигурнијим захтевом да верификујете своје податке помоћу другог уређаја, као што су безбедносни кључ, апликација, СМС-а, телефонски позив или имејл. Пријављивање у два корака може се омогућити на веб сефу. Да ли желите да посетите веб страницу сада?" + }, + "twoStepLogin": { + "message": "Дво-коракна лозинка" + }, + "vaultTimeout": { + "message": "Тајмаут сефа" + }, + "vaultTimeoutDesc": { + "message": "Изаберите када ће сеф истећи и извршити одабрану радњу." + }, + "immediately": { + "message": "Одмах" + }, + "tenSeconds": { + "message": "10 секунди" + }, + "twentySeconds": { + "message": "20 секунди" + }, + "thirtySeconds": { + "message": "30 секунди" + }, + "oneMinute": { + "message": "1 минут" + }, + "twoMinutes": { + "message": "2 минута" + }, + "fiveMinutes": { + "message": "5 минута" + }, + "fifteenMinutes": { + "message": "15 минута" + }, + "thirtyMinutes": { + "message": "30 минута" + }, + "oneHour": { + "message": "1 сат" + }, + "fourHours": { + "message": "4 сата" + }, + "onIdle": { + "message": "На мировање система" + }, + "onSleep": { + "message": "Након спаванја система" + }, + "onLocked": { + "message": "На закључавање система" + }, + "onRestart": { + "message": "На поновно покретање" + }, + "never": { + "message": "Никада" + }, + "security": { + "message": "Сигурност" + }, + "clearClipboard": { + "message": "Обриши привремену меморију", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Аутоматски обришите копиране вредности из привремене меморије.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Онемогући иконице сајта" + }, + "disableFaviconDesc": { + "message": "Иконе веб сајта пружају препознатљиву слику поред сваке пријаве у сефу." + }, + "enableMinToTray": { + "message": "Минимизирај као иконицу у системској траци" + }, + "enableMinToTrayDesc": { + "message": "Када минимизујете прозор, уместо тога покажите икону у системској траци." + }, + "enableMinToMenuBar": { + "message": "Смањи на траку менија" + }, + "enableMinToMenuBarDesc": { + "message": "Када минимизујете прозор, покажи икону у траци менија." + }, + "enableCloseToTray": { + "message": "Затваранје оставлја иконицу у системској траци" + }, + "enableCloseToTrayDesc": { + "message": "Када затворите прозор, уместо тога покажите икону у системској траци." + }, + "enableCloseToMenuBar": { + "message": "Затвори у траку менија" + }, + "enableCloseToMenuBarDesc": { + "message": "Када затворите прозор, покажите икону у траци менија." + }, + "enableTray": { + "message": "Омогући иконицу у системској траци" + }, + "enableTrayDesc": { + "message": "Увек прикажи иконицу на системској траци." + }, + "startToTray": { + "message": "Покрени као иконицу у системској траци" + }, + "startToTrayDesc": { + "message": "Када се апликација први пут покрене, прикажи је само као икону у системској траци." + }, + "startToMenuBar": { + "message": "Покрени у траци менија" + }, + "startToMenuBarDesc": { + "message": "Када се апликација први пут покрене, прикажи само икону у траци менија." + }, + "openAtLogin": { + "message": "Аутоматски покрени након пријављивања" + }, + "openAtLoginDesc": { + "message": "Покрени Bitwarden Desktop апликацију аутоматски након пријављивања." + }, + "alwaysShowDock": { + "message": "Увек покажи у Dock" + }, + "alwaysShowDockDesc": { + "message": "Покажи Bitwarden иконицу у Dock чак и када је умањен на траци менија." + }, + "confirmTrayTitle": { + "message": "Потврди онемогућавање траке" + }, + "confirmTrayDesc": { + "message": "Ако онемогућите ово подешавање сва остала подешавања везана за системску траку ће такође бити онемогућена." + }, + "language": { + "message": "Језик" + }, + "languageDesc": { + "message": "Промените језик који апликација користи. Потребно је поновно покретање." + }, + "theme": { + "message": "Тема" + }, + "themeDesc": { + "message": "Промени боје апликације." + }, + "dark": { + "message": "Тамна", + "description": "Dark color" + }, + "light": { + "message": "Светла", + "description": "Light color" + }, + "copy": { + "message": "Копирај", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Провери доступна ажурирања" + }, + "version": { + "message": "Верзија $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Поново покренути за ажурирање" + }, + "restartToUpdateDesc": { + "message": "Верзија $VERSION_NUM$ је спремна за инсталацију. Морате поново покренути апликацију да бисте довршили инсталацију. Да ли желите да поново покренете и ажурирате сада?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Ажурирање је доступно" + }, + "updateAvailableDesc": { + "message": "Пронађено је ажурирање. Да ли желите да га преузмете сада?" + }, + "restart": { + "message": "Поново покрени" + }, + "later": { + "message": "Касније" + }, + "noUpdatesAvailable": { + "message": "Тренутно нису доступна ажурирања. Користите најновију верзију." + }, + "updateError": { + "message": "Грешка при ажурирању" + }, + "unknown": { + "message": "Непознато" + }, + "copyUsername": { + "message": "Копирај име" + }, + "copyNumber": { + "message": "Копирај број", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Копирај сигурносни код", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Премијум чланство" + }, + "premiumManage": { + "message": "Управљање чланством" + }, + "premiumManageAlert": { + "message": "Можете управљати вашим чланством на bitwarden.com. Да ли желите да посетите веб сајт сада?" + }, + "premiumRefresh": { + "message": "Освежите чланство" + }, + "premiumNotCurrentMember": { + "message": "Тренутно нисте премијум члан." + }, + "premiumSignUpAndGet": { + "message": "Пријавите се за премијум чланство и добијте:" + }, + "premiumSignUpStorage": { + "message": "1ГБ шифровано складиште за прилоге." + }, + "premiumSignUpTwoStep": { + "message": "Додатне опције пријаве у два корака као што су YubiKey, FIDO U2F, и Duo." + }, + "premiumSignUpReports": { + "message": "Извештаји о хигијени лозинки, здравственом стању налога и кршењу података да бисте заштитили сеф." + }, + "premiumSignUpTotp": { + "message": "Генератор једнократног кода (2FA) за пријаве из сефа." + }, + "premiumSignUpSupport": { + "message": "Приоритетна корисничка подршка." + }, + "premiumSignUpFuture": { + "message": "Све будуће премијум функције. Више ускоро!" + }, + "premiumPurchase": { + "message": "Купити премијум" + }, + "premiumPurchaseAlert": { + "message": "Можете купити премијум претплату на bitwarden.com. Да ли желите да посетите веб сајт сада?" + }, + "premiumCurrentMember": { + "message": "Ви сте премијум члан!" + }, + "premiumCurrentMemberThanks": { + "message": "Хвала Вам за подршку Bitwarden-а." + }, + "premiumPrice": { + "message": "Све за само $PRICE$ годишње!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Освежавање је завршено" + }, + "passwordHistory": { + "message": "Историја Лозинке" + }, + "clear": { + "message": "Очисти", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Нема лозинки за приказивање." + }, + "undo": { + "message": "Опозови" + }, + "redo": { + "message": "Понови" + }, + "cut": { + "message": "Исеци", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Налепи", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Изабери све" + }, + "zoomIn": { + "message": "Увећање" + }, + "zoomOut": { + "message": "Умањење" + }, + "resetZoom": { + "message": "Ресетуј зумирање" + }, + "toggleFullScreen": { + "message": "Укључи/искључи приказ преко целог екрана" + }, + "reload": { + "message": "Поново учитај" + }, + "toggleDevTools": { + "message": "Укључи/искључи развојне алатке" + }, + "minimize": { + "message": "Минимизирај", + "description": "Minimize window" + }, + "zoom": { + "message": "Зумирај" + }, + "bringAllToFront": { + "message": "Постави све у предњи план", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "О Bitwarden" + }, + "services": { + "message": "Услуге" + }, + "hideBitwarden": { + "message": "Сакриј Bitwarden" + }, + "hideOthers": { + "message": "Сакриј остале" + }, + "showAll": { + "message": "Прикажи све" + }, + "quitBitwarden": { + "message": "Затвори Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ копиран(а/о)", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Помоћ" + }, + "window": { + "message": "Прозор" + }, + "checkPassword": { + "message": "Проверите да ли је лозинка изложена." + }, + "passwordExposed": { + "message": "Ова лозинка је изложена $VALUE$ пута. Требали би да је промените.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Ова лозинка није никада изложена. Треба да је сигурна за употребу." + }, + "baseDomain": { + "message": "Главни домен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Име домена", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Хост", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Тачно" + }, + "startsWith": { + "message": "Почиње са" + }, + "regEx": { + "message": "Регуларни израз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Налажење УРЛ", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Стандардно налажење вење", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Промена опција" + }, + "organization": { + "message": "Организација", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Подразумевано" + }, + "exit": { + "message": "Изађи" + }, + "showHide": { + "message": "Покажи/Сакриј", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Сакриј у системску траку" + }, + "alwaysOnTop": { + "message": "Увек на врху", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Промењено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Лозинка ажурирана", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Извоз сефа" + }, + "fileFormat": { + "message": "Формат датотеке" + }, + "warning": { + "message": "УПОЗОРЕЊЕ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Потврдите извоз сефа" + }, + "exportWarningDesc": { + "message": "Овај извоз садржи податке сефа у нешифрираном формату. Не бисте смели да сачувате или шаљете извезену датотеку преко несигурних канала (као што је имејл). Избришите датотеку одмах након што завршите са коришћењем." + }, + "encExportKeyWarningDesc": { + "message": "Овај извоз шифрује податке користећи кључ за шифровање вашег налога. Ако икада промените кључ за шифровање свог налога, требало би да поново извезете, јер нећете моћи да дешифрујете овај извоз." + }, + "encExportAccountWarningDesc": { + "message": "Кључеви за шифровање налога су јединствени за сваки Bitwarden кориснички налог, тако да не можете да увезете шифровани извоз на други налог." + }, + "noOrganizationsList": { + "message": "Не припадате ниједној организацији. Организације вам омогућавају да безбедно делите ставке са другим корисницима." + }, + "noCollectionsInList": { + "message": "Нема колекције у листи." + }, + "ownership": { + "message": "Власништво" + }, + "whoOwnsThisItem": { + "message": "Ко је власник ове ставке?" + }, + "strong": { + "message": "Јако", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Добро", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабо", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слаба Главна Лозинка" + }, + "weakMasterPasswordDesc": { + "message": "Главна лозинка коју сте одабрали је слаба. Требали бисте користити јаку главну лозинку (или фразу лозинке) да бисте правилно заштитили свој налог. Да ли сте сигурни да желите да користите ову главну лозинку?" + }, + "pin": { + "message": "ПИН", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Откључај са ПИН" + }, + "setYourPinCode": { + "message": "Поставите свој ПИН код за откључавање Bitwarden-а. Поставке ПИН-а ће се ресетовати ако се икада потпуно одјавите из апликације." + }, + "pinRequired": { + "message": "ПИН је обавезан." + }, + "invalidPin": { + "message": "Погрешан ПИН код." + }, + "unlockWithWindowsHello": { + "message": "Откључај са Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Потврди за Bitwarden." + }, + "unlockWithTouchId": { + "message": "Откључај са Touch ID" + }, + "touchIdConsentMessage": { + "message": "Откључај свој сеф" + }, + "noAutoPromptWindowsHello": { + "message": "Не тражи Windows Hello након покретања." + }, + "noAutoPromptTouchId": { + "message": "Не тражи Touch ID након покретања." + }, + "lockWithMasterPassOnRestart": { + "message": "Закључајте са главном лозинком при поновном покретању" + }, + "preferences": { + "message": "Подешавања" + }, + "enableMenuBar": { + "message": "Омогући икону траке менија" + }, + "enableMenuBarDesc": { + "message": "Увек покажи икону у траци менија." + }, + "hideToMenuBar": { + "message": "Сакриј у траку менија" + }, + "selectOneCollection": { + "message": "Морате одабрати макар једну колекцију." + }, + "premiumUpdated": { + "message": "Надоградили сте на премијум." + }, + "restore": { + "message": "Поврати" + }, + "premiumManageAlertAppStore": { + "message": "Претплатом можете управљати из App Store. Да ли желите да посетите App Store сада?" + }, + "legal": { + "message": "Правне информације", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Услови коришћења услуге" + }, + "privacyPolicy": { + "message": "Политика приватности" + }, + "unsavedChangesConfirmation": { + "message": "Јесте ли сигурни да желите да одете? Ако одете сада, ваше тренутне информације неће бити сачуване." + }, + "unsavedChangesTitle": { + "message": "Несачуване промене" + }, + "clone": { + "message": "Клонирај" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Једна или више смерница организације утичу на поставке вашег генератора." + }, + "vaultTimeoutAction": { + "message": "Акција на тајмаут сефа" + }, + "vaultTimeoutActionLockDesc": { + "message": "Закључани сеф захтева да поново унесете главну лозинку да бисте му поново приступили." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Одјављени сеф захтева да поново потврдите идентитет да бисте му поново приступили." + }, + "lock": { + "message": "Закључај", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Отпад", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Тражи отпад" + }, + "permanentlyDeleteItem": { + "message": "Трајно избрисати ставку" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Да ли сте сигурни да желите да трајно избришете ову ставку?" + }, + "permanentlyDeletedItem": { + "message": "Трајно избрисана ставка" + }, + "restoreItem": { + "message": "Врати ставку" + }, + "restoreItemConfirmation": { + "message": "Да ли сте сигурни да желите да вратите ову ставку?" + }, + "restoredItem": { + "message": "Ставка враћена" + }, + "permanentlyDelete": { + "message": "Трајно избрисати" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Одјава ће уклонити сваки приступ вашем сефу и захтева мрежну потврду идентитета након истека тајмаута. Да ли сте сигурни да желите да користите ову поставку?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Потврда акције истека времена" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Једна Пријава" + }, + "setMasterPassword": { + "message": "Постави Главну Лозинку" + }, + "ssoCompleteRegistration": { + "message": "Да бисте довршили пријављивање помоћу SSO, молимо да поставите главну лозинку за приступ и заштиту вашег сефа." + }, + "newMasterPass": { + "message": "Нова Главна Лозинка" + }, + "confirmNewMasterPass": { + "message": "Потрдити нову Главну Лозинку" + }, + "masterPasswordPolicyInEffect": { + "message": "Једна или више полиса организације захтевају да ваша главна лозинка испуни следеће захтеве:" + }, + "policyInEffectMinComplexity": { + "message": "Оцена минималне сложености од $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Минимална дужина од $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Садржи једно или више великих слова" + }, + "policyInEffectLowercase": { + "message": "Садржи једно или више малих слова" + }, + "policyInEffectNumbers": { + "message": "Садржи један или више бројева" + }, + "policyInEffectSpecial": { + "message": "Садржи један или више ових специјалних знакова $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваша нова главна лозинка не испуњава захтеве полисе." + }, + "acceptPolicies": { + "message": "Означавањем овог поља пристајете на следеће:" + }, + "acceptPoliciesError": { + "message": "Услови услуге и Политика приватности нису прихваћени." + }, + "enableBrowserIntegration": { + "message": "Укључи интеграцију са претраживачем" + }, + "enableBrowserIntegrationDesc": { + "message": "Интеграција прегледача се користи за биометрију у прегледачу." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Интеграција претраживача није подржана" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Нажалост, интеграција прегледача за сада је подржана само у верзији Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Интеграција претраживача није подржана" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Нажалост, интеграција прегледача није за сада подржана у Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Захтева верификацију за интеграцију прегледача" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Омогућите додатни ниво заштите захтевајући проверу фразе отиска прста приликом успостављања везе између desktop-а и прегледача. Када је омогућено, ово захтева интервенцију и верификацију корисника сваки пут када се успостави веза." + }, + "approve": { + "message": "Одобри" + }, + "verifyBrowserTitle": { + "message": "Провери везу прегледача" + }, + "verifyBrowserDesc": { + "message": "Уверите се да је приказани отисак идентичан отиску приказаном у додатку прегледача." + }, + "biometricsNotEnabledTitle": { + "message": "Биометрија није омогућена" + }, + "biometricsNotEnabledDesc": { + "message": "Биометрија прегледача захтева да у поставкама прво буде омогућена биометрија desktop-а." + }, + "personalOwnershipSubmitError": { + "message": "Због смерница за предузећа, ограничено вам је чување предмета у вашем личном трезору. Промените опцију власништва у организацију и изаберите из доступних колекција." + }, + "hintEqualsPassword": { + "message": "Ваш савет за лозинку не може да буде исти као лозинка." + }, + "personalOwnershipPolicyInEffect": { + "message": "Политика организације утиче на ваше могућности власништва." + }, + "allSends": { + "message": "Сва слања", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Датотека" + }, + "sendTypeText": { + "message": "Текст" + }, + "searchSends": { + "message": "Претражи слања", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Уреди слање", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Мој сеф" + }, + "text": { + "message": "Текст" + }, + "deletionDate": { + "message": "Брисање после" + }, + "deletionDateDesc": { + "message": "Слање ће бити трајно обрисано у наведени датум и време.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Рок употребе" + }, + "expirationDateDesc": { + "message": "Ако је подешено, приступ овом слању истиче у наведени датум и време.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Максималан број приступа" + }, + "maxAccessCountDesc": { + "message": "Ако је постављено, корисници више неће моћи да приступе овом „Send“ када се достигне максимални број приступа.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Тренутни број приступа" + }, + "disableSend": { + "message": "Онемогући ово слање да нико други нема приступ.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Опционо захтевај лозинку од корисника за приступ овом слању.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Приватне белешке о овом слању.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Линк слања", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Линк слања", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Када се приступа слању, подразумевано сакриј текст", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Креирано слање", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Измењено слање", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Обрисано слање", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Нова лозинка" + }, + "whatTypeOfSend": { + "message": "Који је ово тип „Send“-a?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Креирај слање", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст који желиш да пошаљеш." + }, + "sendFileDesc": { + "message": "Датотека коју желиш да пошаљеш." + }, + "days": { + "message": "$DAYS$ дана", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 дан" + }, + "custom": { + "message": "Друго" + }, + "deleteSendConfirmation": { + "message": "Сигурно обрисати ово слање?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Копирај везу слања у привремену меморију", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Копирај линк за дељење слања у привремену меморију након чувања." + }, + "sendDisabled": { + "message": "Слање онемогућено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Због полисе компаније, можеш само да бришеш постојећа слања.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Копирај везу" + }, + "disabled": { + "message": "Онемогућено" + }, + "maxAccessCountReached": { + "message": "Достигнут максималан број приступа" + }, + "expired": { + "message": "Истекло" + }, + "pendingDeletion": { + "message": "Брисање на чекању" + }, + "webAuthnAuthenticate": { + "message": "WebAutn аутентификација" + }, + "hideEmail": { + "message": "Сакриј моју е-адресу од примаоца." + }, + "sendOptionsPolicyInEffect": { + "message": "Једна или више смерница организације утичу на опције „Send“-а." + }, + "emailVerificationRequired": { + "message": "Потребна је верификација е-поште" + }, + "emailVerificationRequiredDesc": { + "message": "Морате да проверите е-пошту да бисте користили ову функцију." + }, + "passwordPrompt": { + "message": "Поновно тражење главне лозинке" + }, + "passwordConfirmation": { + "message": "Потврда главне лозинке" + }, + "passwordConfirmationDesc": { + "message": "Ова акција је заштићена. Да бисте наставили, поново унесите своју главну лозинку да бисте проверили идентитет." + }, + "updatedMasterPassword": { + "message": "Главна лозинка ажурирана" + }, + "updateMasterPassword": { + "message": "Ажурирај главну лозинку" + }, + "updateMasterPasswordWarning": { + "message": "Ваша главна лозинка је недавно промењена од стране администратора организације. Како бисте приступили сефу, морате да је ажурирате. Ако наставите бићете одјављени из ваше тренутне сесије, што ће захтевати да се поново пријавите. Активне сесије на другим уређајима ће можда наставити да раде до сат времена." + }, + "hours": { + "message": "Сата" + }, + "minutes": { + "message": "Минута" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Полиса ваше организације утиче на време истека сефа. Максимално дозвољено време истека је $HOURS$ сат(и) и $MINUTES$ minut(а)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Време истека вашег сефа је премашило дозвољена ограничења од стране ваше организације." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Аутоматска пријава" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ова организација има полису која ће вас аутоматски пријавити за ресетовање лозинке. Пријава ће дозволити администраторима ваше организације да промене главну лозинку." + }, + "vaultExportDisabled": { + "message": "Извоз сефа онемогућен" + }, + "personalVaultExportPolicyInEffect": { + "message": "Једна или више полиса ваше организације вас спречава да извезете ваш сеф." + }, + "addAccount": { + "message": "Додај налог" + }, + "removeMasterPassword": { + "message": "Уклони главну лозинку" + }, + "removedMasterPassword": { + "message": "Главна лозинка уклоњена." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ користи SSO уз сопствени сервер за кључеве. Главна лозинка за пријаву више није неопходна за чланове ове организације.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Напусти организацију" + }, + "leaveOrganizationConfirmation": { + "message": "Да ли Сте сигурни да желите да напустите ову организацију?" + }, + "leftOrganization": { + "message": "Напустили сте организацију." + }, + "ssoKeyConnectorUnavailable": { + "message": "Немогуће повезати се са добављачем кључева, покушајте поново касније." + }, + "lockAllVaults": { + "message": "Закључај сефове" + }, + "accountLimitReached": { + "message": "Истовремено се не може пријавити више од 5 налога." + }, + "accountPreferences": { + "message": "Подешавања" + }, + "appPreferences": { + "message": "Подешавања апликације (Сви налози)" + }, + "accountSwitcherLimitReached": { + "message": "Граница налога достигнута. Одјавите се од једног налога да би додали други." + }, + "settingsTitle": { + "message": "Подешавања апликације за $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Промени налог" + }, + "options": { + "message": "Опције" + }, + "sessionTimeout": { + "message": "Ваша сесија је истекла. Вратите се и покушајте поново да се пријавите." + }, + "exportingPersonalVaultTitle": { + "message": "Извоз личног сефа" + }, + "exportingPersonalVaultDescription": { + "message": "Само предмети личног сефа повезани са $EMAIL$ биће извезени. Ставке организационог сефа неће бити укључене.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Генератор" + }, + "whatWouldYouLikeToGenerate": { + "message": "Шта желите да генеришете?" + }, + "passwordType": { + "message": "Тип лозинке" + }, + "regenerateUsername": { + "message": "Поново генериши име" + }, + "generateUsername": { + "message": "Генериши име" + }, + "usernameType": { + "message": "Тип имена" + }, + "plusAddressedEmail": { + "message": "Плус имејл адресе" + }, + "plusAddressedEmailDesc": { + "message": "Користите могућности подадресирања вашег добављача е-поште." + }, + "catchallEmail": { + "message": "„Ухвати све“ е-порука" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Случајно" + }, + "randomWord": { + "message": "Случајна реч" + }, + "websiteName": { + "message": "Име Вашег веб-сајта" + }, + "service": { + "message": "Сервис" + } +} diff --git a/apps/desktop/src/locales/sv/messages.json b/apps/desktop/src/locales/sv/messages.json new file mode 100644 index 0000000000..5f2c837f62 --- /dev/null +++ b/apps/desktop/src/locales/sv/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filter" + }, + "allItems": { + "message": "Alla objekt" + }, + "favorites": { + "message": "Favoriter" + }, + "types": { + "message": "Typer" + }, + "typeLogin": { + "message": "Inloggning" + }, + "typeCard": { + "message": "Kort" + }, + "typeIdentity": { + "message": "Identitet" + }, + "typeSecureNote": { + "message": "Säker anteckning" + }, + "folders": { + "message": "Mappar" + }, + "collections": { + "message": "Samlingar" + }, + "searchVault": { + "message": "Sök i valvet" + }, + "addItem": { + "message": "Lägg till objekt" + }, + "shared": { + "message": "Delad" + }, + "share": { + "message": "Dela" + }, + "moveToOrganization": { + "message": "Flytta till organisation" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ flyttades till $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Välj en organisation som du vill flytta detta objektet till. Flytt till en organisation överför ägandet av objektet till den organisationen. Du kommer inte längre att vara direkt ägare till detta objekt när det har flyttats." + }, + "attachments": { + "message": "Bilagor" + }, + "viewItem": { + "message": "Visa objekt" + }, + "name": { + "message": "Namn" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Ny URI" + }, + "username": { + "message": "Användarnamn" + }, + "password": { + "message": "Lösenord" + }, + "passphrase": { + "message": "Lösenordsfras" + }, + "editItem": { + "message": "Redigera objekt" + }, + "emailAddress": { + "message": "E-postadress" + }, + "verificationCodeTotp": { + "message": "Verifieringskod (TOTP)" + }, + "website": { + "message": "Webbplats" + }, + "notes": { + "message": "Anteckningar" + }, + "customFields": { + "message": "Anpassade fält" + }, + "launch": { + "message": "Öppna" + }, + "copyValue": { + "message": "Kopiera värde", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimera vid kopiering till urklipp" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimera när ett objekt kopieras till urklipp." + }, + "toggleVisibility": { + "message": "Växla synlighet" + }, + "toggleCollapse": { + "message": "Växla synlig/dold", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kortinnehavarens namn" + }, + "number": { + "message": "Nummer" + }, + "brand": { + "message": "Märke" + }, + "expiration": { + "message": "Utgång" + }, + "securityCode": { + "message": "Säkerhetskod" + }, + "identityName": { + "message": "Identitetsnamn" + }, + "company": { + "message": "Företag" + }, + "ssn": { + "message": "Personnummer" + }, + "passportNumber": { + "message": "Passnummer" + }, + "licenseNumber": { + "message": "Körkortsnummer" + }, + "email": { + "message": "E-post" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adress" + }, + "premiumRequired": { + "message": "Premium krävs" + }, + "premiumRequiredDesc": { + "message": "Ett premium-medlemskap krävs för att använda den här funktionen." + }, + "errorOccurred": { + "message": "Ett fel har inträffat." + }, + "error": { + "message": "Fel" + }, + "january": { + "message": "Januari" + }, + "february": { + "message": "Februari" + }, + "march": { + "message": "Mars" + }, + "april": { + "message": "April" + }, + "may": { + "message": "Maj" + }, + "june": { + "message": "Juni" + }, + "july": { + "message": "Juli" + }, + "august": { + "message": "Augusti" + }, + "september": { + "message": "September" + }, + "october": { + "message": "Oktober" + }, + "november": { + "message": "November" + }, + "december": { + "message": "December" + }, + "ex": { + "message": "t.ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Titel" + }, + "mr": { + "message": "Herr" + }, + "mrs": { + "message": "Fru" + }, + "ms": { + "message": "Fröken" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Utgångsmånad" + }, + "expirationYear": { + "message": "Utgångsår" + }, + "select": { + "message": "Välj" + }, + "other": { + "message": "Annat" + }, + "generatePassword": { + "message": "Skapa lösenord" + }, + "type": { + "message": "Typ" + }, + "firstName": { + "message": "Förnamn" + }, + "middleName": { + "message": "Mellannamn" + }, + "lastName": { + "message": "Efternamn" + }, + "fullName": { + "message": "Fullständigt namn" + }, + "address1": { + "message": "Adress 1" + }, + "address2": { + "message": "Adress 2" + }, + "address3": { + "message": "Adress 3" + }, + "cityTown": { + "message": "Ort" + }, + "stateProvince": { + "message": "Län" + }, + "zipPostalCode": { + "message": "Postnummer" + }, + "country": { + "message": "Land" + }, + "save": { + "message": "Spara" + }, + "cancel": { + "message": "Avbryt" + }, + "delete": { + "message": "Radera" + }, + "favorite": { + "message": "Favorit" + }, + "edit": { + "message": "Redigera" + }, + "authenticatorKeyTotp": { + "message": "Autentiseringsnyckel (TOTP)" + }, + "folder": { + "message": "Mapp" + }, + "newCustomField": { + "message": "Nytt anpassat fält" + }, + "value": { + "message": "Värde" + }, + "dragToSort": { + "message": "Dra för att sortera" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "Dold" + }, + "cfTypeBoolean": { + "message": "Booleskt värde" + }, + "cfTypeLinked": { + "message": "Länkad", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Länkat värde", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Ta bort" + }, + "nameRequired": { + "message": "Namn krävs." + }, + "addedItem": { + "message": "Lade till objekt" + }, + "editedItem": { + "message": "Redigerade objekt" + }, + "deleteItem": { + "message": "Radera objekt" + }, + "deleteFolder": { + "message": "Radera mapp" + }, + "deleteAttachment": { + "message": "Radera bilaga" + }, + "deleteItemConfirmation": { + "message": "Är du säker på att du vill radera detta objekt?" + }, + "deletedItem": { + "message": "Skickade objekt till papperskorgen" + }, + "overwritePasswordConfirmation": { + "message": "Är du säker på att du vill skriva över det nuvarande lösenordet?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Ingen mapp", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Lägg till mapp" + }, + "editFolder": { + "message": "Redigera mapp" + }, + "regeneratePassword": { + "message": "Skapa nytt lösenord" + }, + "copyPassword": { + "message": "Kopiera lösenord" + }, + "copyUri": { + "message": "Kopiera URI" + }, + "copyVerificationCodeTotp": { + "message": "Kopiera verifieringskod (TOTP)" + }, + "length": { + "message": "Längd" + }, + "numWords": { + "message": "Antal ord" + }, + "wordSeparator": { + "message": "Ordavgränsare" + }, + "capitalize": { + "message": "Versalisera", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Inkludera siffra" + }, + "close": { + "message": "Stäng" + }, + "minNumbers": { + "message": "Minsta antal siffror" + }, + "minSpecial": { + "message": "Minsta antal speciella tecken", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Undvik tvetydiga tecken" + }, + "searchCollection": { + "message": "Sök i samling" + }, + "searchFolder": { + "message": "Sök i mapp" + }, + "searchFavorites": { + "message": "Sök i favoriter" + }, + "searchType": { + "message": "Sök efter typ", + "description": "Search item type" + }, + "newAttachment": { + "message": "Lägg till ny bilaga" + }, + "deletedAttachment": { + "message": "Raderade bilaga" + }, + "deleteAttachmentConfirmation": { + "message": "Är du säker på att du vill radera denna bilaga?" + }, + "attachmentSaved": { + "message": "Bilagan har sparats." + }, + "file": { + "message": "Fil" + }, + "selectFile": { + "message": "Välj en fil." + }, + "maxFileSize": { + "message": "Maximal filstorlek är 500 MB." + }, + "updateKey": { + "message": "Du kan inte använda denna funktion förrän du uppdaterar din krypteringsnyckel." + }, + "editedFolder": { + "message": "Redigerade mapp" + }, + "addedFolder": { + "message": "Lade till mapp" + }, + "deleteFolderConfirmation": { + "message": "Är du säker på att du vill radera denna mapp?" + }, + "deletedFolder": { + "message": "Raderade mapp" + }, + "loginOrCreateNewAccount": { + "message": "Logga in eller skapa ett nytt konto för att komma åt ditt valv." + }, + "createAccount": { + "message": "Skapa konto" + }, + "logIn": { + "message": "Logga in" + }, + "submit": { + "message": "Skicka" + }, + "masterPass": { + "message": "Huvudlösenord" + }, + "masterPassDesc": { + "message": "Huvudlösenordet är det lösenord som du använder för att komma åt ditt valv. Det är väldigt viktigt att du inte glömmer bort ditt huvudlösenord, eftersom det inte går att återställa lösenordet ifall du skulle glömma bort det." + }, + "masterPassHintDesc": { + "message": "En huvudlösenordsledtråd kan hjälpa dig att komma ihåg ditt lösenord om du glömmer bort det." + }, + "reTypeMasterPass": { + "message": "Ange huvudlösenordet igen" + }, + "masterPassHint": { + "message": "Huvudlösenordsledtråd (valfri)" + }, + "settings": { + "message": "Inställningar" + }, + "passwordHint": { + "message": "Lösenordsledtråd" + }, + "enterEmailToGetHint": { + "message": "Ange din e-postadress för att få din huvudlösenordsledtråd skickad till dig." + }, + "getMasterPasswordHint": { + "message": "Hämta huvudlösenordsledtråd" + }, + "emailRequired": { + "message": "E-postadress krävs." + }, + "invalidEmail": { + "message": "Ogiltig e-postadress." + }, + "masterPassRequired": { + "message": "Huvudlösenord krävs." + }, + "masterPassLength": { + "message": "Huvudlösenordet måste vara minst 8 tecken långt." + }, + "masterPassDoesntMatch": { + "message": "Huvudlösenorden stämmer inte överens." + }, + "newAccountCreated": { + "message": "Ditt nya konto har skapats! Du kan nu logga in." + }, + "masterPassSent": { + "message": "Vi har skickat ett e-postmeddelande till dig med din huvudlösenordsledtråd." + }, + "unexpectedError": { + "message": "Ett oväntat fel har inträffat." + }, + "itemInformation": { + "message": "Objektinformation" + }, + "noItemsInList": { + "message": "Det finns inga objekt att visa." + }, + "sendVerificationCode": { + "message": "Skicka en verifieringskod till din e-postadress" + }, + "sendCode": { + "message": "Skicka kod" + }, + "codeSent": { + "message": "Kod har skickats" + }, + "verificationCode": { + "message": "Verifieringskod" + }, + "confirmIdentity": { + "message": "Bekräfta din identitet för att fortsätta." + }, + "verificationCodeRequired": { + "message": "Verifieringskod krävs." + }, + "invalidVerificationCode": { + "message": "Ogiltig verifieringskod" + }, + "continue": { + "message": "Fortsätt" + }, + "enterVerificationCodeApp": { + "message": "Ange den 6-siffriga verifieringskoden från din autentiseringsapp." + }, + "enterVerificationCodeEmail": { + "message": "Ange den 6-siffriga verifieringskoden som har skickats till $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verifieringsmeddelande har skickats till $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Kom ihåg mig" + }, + "sendVerificationCodeEmailAgain": { + "message": "Skicka e-postmeddelandet med verifieringskoden igen" + }, + "useAnotherTwoStepMethod": { + "message": "Använd en annan metod för tvåstegsverifiering" + }, + "insertYubiKey": { + "message": "Anslut din YubiKey till datorns USB-port och tryck sedan på dess knapp." + }, + "insertU2f": { + "message": "Anslut din säkerhetsnyckel till datorns USB-port. Om den har en knapp, tryck på den." + }, + "recoveryCodeDesc": { + "message": "Förlorat åtkomst till alla dina metoder för tvåstegsverifiering? Använd din återställningskod för att inaktivera tvåstegsverifiering på ditt konto." + }, + "recoveryCodeTitle": { + "message": "Återställningskod" + }, + "authenticatorAppTitle": { + "message": "Autentiseringsapp" + }, + "authenticatorAppDesc": { + "message": "Använd en autentiseringsapp (t.ex. Authy eller Google Authenticator) för att skapa tidsbaserade verifieringskoder.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP-säkerhetsnyckel" + }, + "yubiKeyDesc": { + "message": "Använd en YubiKey för att komma åt ditt konto. Fungerar med YubiKey 4, 4 Nano, 4C och NEO-enheter." + }, + "duoDesc": { + "message": "Verifiera med Duo Security genom att använda Duo Mobile-appen, SMS, telefonsamtal eller en U2F-säkerhetsnyckel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verifiera med Duo Security för din organisation genom att använda Duo Mobile-appen, SMS, telefonsamtal eller en U2F-säkerhetsnyckel.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Använd en WebAuthn-aktiverad säkerhetsnyckel för att komma åt ditt konto." + }, + "emailTitle": { + "message": "E-post" + }, + "emailDesc": { + "message": "Verifieringskoder kommer att skickas till dig via e-post." + }, + "loginUnavailable": { + "message": "Inloggning ej tillgänglig" + }, + "noTwoStepProviders": { + "message": "Detta konto har tvåstegsverifiering aktiverat, men ingen av de konfigurerade metoderna stöds av den här enheten." + }, + "noTwoStepProviders2": { + "message": "Lägg till fler metoder som har bättre stöd bland enheter (t.ex. en autentiseringsapp)." + }, + "twoStepOptions": { + "message": "Alternativ för tvåstegsverifiering" + }, + "selfHostedEnvironment": { + "message": "Egen-hostad miljö" + }, + "selfHostedEnvironmentFooter": { + "message": "Ange bas-URL:en för din \"on-premises\"-hostade Bitwarden-installation." + }, + "customEnvironment": { + "message": "Anpassad miljö" + }, + "customEnvironmentFooter": { + "message": "För avancerade användare. Du kan ange bas-URL:en för varje tjänst oberoende av varandra." + }, + "baseUrl": { + "message": "Server-URL" + }, + "apiUrl": { + "message": "API-server-URL" + }, + "webVaultUrl": { + "message": "Webbvalvsserver-URL" + }, + "identityUrl": { + "message": "Identitetsserver-URL" + }, + "notificationsUrl": { + "message": "Aviseringsserver-URL" + }, + "iconsUrl": { + "message": "Ikonserver-URL" + }, + "environmentSaved": { + "message": "Miljö-URL:erna har sparats." + }, + "ok": { + "message": "OK" + }, + "yes": { + "message": "Ja" + }, + "no": { + "message": "Nej" + }, + "overwritePassword": { + "message": "Skriv över lösenord" + }, + "learnMore": { + "message": "Läs mer" + }, + "featureUnavailable": { + "message": "Funktion ej tillgänglig" + }, + "loggedOut": { + "message": "Utloggad" + }, + "loginExpired": { + "message": "Din inloggningssession har löpt ut." + }, + "logOutConfirmation": { + "message": "Är du säker på att du vill logga ut?" + }, + "logOut": { + "message": "Logga ut" + }, + "addNewLogin": { + "message": "Lägg till ny inloggning" + }, + "addNewItem": { + "message": "Lägg till nytt objekt" + }, + "addNewFolder": { + "message": "Lägg till ny mapp" + }, + "view": { + "message": "Visa" + }, + "account": { + "message": "Konto" + }, + "loading": { + "message": "Laddar..." + }, + "lockVault": { + "message": "Lås valv" + }, + "passwordGenerator": { + "message": "Lösenordsgenerator" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Skicka en felrapport" + }, + "blog": { + "message": "Blogg" + }, + "followUs": { + "message": "Följ oss" + }, + "syncVault": { + "message": "Synkronisera valv" + }, + "changeMasterPass": { + "message": "Ändra huvudlösenord" + }, + "changeMasterPasswordConfirmation": { + "message": "Du kan ändra ditt huvudlösenord i Bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "fingerprintPhrase": { + "message": "Fingeravtrycksfras", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Ditt kontos fingeravtrycksfras", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Gå till webbvalv" + }, + "getMobileApp": { + "message": "Hämta mobilapp" + }, + "getBrowserExtension": { + "message": "Hämta webbläsartillägg" + }, + "syncingComplete": { + "message": "Synkroniseringen slutfördes" + }, + "syncingFailed": { + "message": "Synkroniseringen misslyckades" + }, + "yourVaultIsLocked": { + "message": "Ditt valv är låst. Bekräfta din identitet för att fortsätta." + }, + "unlock": { + "message": "Lås upp" + }, + "loggedInAsOn": { + "message": "Inloggad som $EMAIL$ på $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Ogiltigt huvudlösenord" + }, + "twoStepLoginConfirmation": { + "message": "Tvåstegsverifiering gör ditt konto säkrare genom att kräva att du verifierar din inloggning med en annan enhet, t.ex. en säkerhetsnyckel, autentiseringsapp, SMS, telefonsamtal eller e-post. Tvåstegsverifiering kan aktiveras i Bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "twoStepLogin": { + "message": "Tvåstegsverifiering" + }, + "vaultTimeout": { + "message": "Valvets tidsgräns" + }, + "vaultTimeoutDesc": { + "message": "Välj när valvets tidsgräns överskrids och den valda åtgärden utförs." + }, + "immediately": { + "message": "Omedelbart" + }, + "tenSeconds": { + "message": "10 sekunder" + }, + "twentySeconds": { + "message": "20 sekunder" + }, + "thirtySeconds": { + "message": "30 sekunder" + }, + "oneMinute": { + "message": "1 minut" + }, + "twoMinutes": { + "message": "2 minuter" + }, + "fiveMinutes": { + "message": "5 minuter" + }, + "fifteenMinutes": { + "message": "15 minuter" + }, + "thirtyMinutes": { + "message": "30 minuter" + }, + "oneHour": { + "message": "1 timme" + }, + "fourHours": { + "message": "4 timmar" + }, + "onIdle": { + "message": "Vid inaktivitet" + }, + "onSleep": { + "message": "Vid strömsparläge" + }, + "onLocked": { + "message": "Vid låsning av datorn" + }, + "onRestart": { + "message": "Vid omstart" + }, + "never": { + "message": "Aldrig" + }, + "security": { + "message": "Säkerhet" + }, + "clearClipboard": { + "message": "Rensa urklipp", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Rensa automatiskt kopierade värden från urklipp.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Inaktivera webbplatsikoner" + }, + "disableFaviconDesc": { + "message": "Webbplatsikoner ger en igenkännbar ikon bredvid varje inloggningsobjekt i ditt valv." + }, + "enableMinToTray": { + "message": "Minimera till systemfältsikon" + }, + "enableMinToTrayDesc": { + "message": "När fönstret minimeras, visa en ikon i systemfältet istället." + }, + "enableMinToMenuBar": { + "message": "Minimera till aktivitetsfältet" + }, + "enableMinToMenuBarDesc": { + "message": "När fönstret minimeras, visa en ikon i aktivitetsfältet istället." + }, + "enableCloseToTray": { + "message": "Stäng till systemfältet" + }, + "enableCloseToTrayDesc": { + "message": "När fönstret stängs, visa en ikon i systemfältet istället." + }, + "enableCloseToMenuBar": { + "message": "Stäng till aktivitetsfältet" + }, + "enableCloseToMenuBarDesc": { + "message": "När fönstret stängs, visa en ikon i aktivitetsfältet istället." + }, + "enableTray": { + "message": "Aktivera systemfältsikon" + }, + "enableTrayDesc": { + "message": "Visa alltid en ikon i systemfältet." + }, + "startToTray": { + "message": "Starta i systemfältet" + }, + "startToTrayDesc": { + "message": "När programmet startas, visa endast en ikon i systemfältet." + }, + "startToMenuBar": { + "message": "Öppna till aktivitetsfältet" + }, + "startToMenuBarDesc": { + "message": "När programmet startas, visa endast en ikon i aktivitetsfältet." + }, + "openAtLogin": { + "message": "Starta automatiskt vid inloggning" + }, + "openAtLoginDesc": { + "message": "Starta Bitwardens skrivbordsprogram automatiskt vid inloggning." + }, + "alwaysShowDock": { + "message": "Visa alltid i dockan" + }, + "alwaysShowDockDesc": { + "message": "Visa Bitwarden-ikonen i dockan även om den minimeras till aktivitetsfältet." + }, + "confirmTrayTitle": { + "message": "Bekräfta inaktivering av fält" + }, + "confirmTrayDesc": { + "message": "Om den här inställningen inaktiveras kommer alla andra fältrelaterade inställningar också inaktiveras." + }, + "language": { + "message": "Språk" + }, + "languageDesc": { + "message": "Ändra språket som används i programmet. Omstart krävs." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Ändra programmets färgtema." + }, + "dark": { + "message": "Mörkt", + "description": "Dark color" + }, + "light": { + "message": "Ljust", + "description": "Light color" + }, + "copy": { + "message": "Kopiera", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Sök efter uppdateringar" + }, + "version": { + "message": "Version $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Starta om för att uppdatera" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ är redo att installeras. Du måste starta om programmet för att slutföra installationen. Vill du starta om och uppdatera nu?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Uppdatering tillgänglig" + }, + "updateAvailableDesc": { + "message": "En uppdatering hittades. Vill du hämta den nu?" + }, + "restart": { + "message": "Starta om" + }, + "later": { + "message": "Senare" + }, + "noUpdatesAvailable": { + "message": "Inga uppdateringar tillgängliga. Du använder den senaste versionen." + }, + "updateError": { + "message": "Fel vid uppdatering" + }, + "unknown": { + "message": "Okänd" + }, + "copyUsername": { + "message": "Kopiera användarnamn" + }, + "copyNumber": { + "message": "Kopiera nummer", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Kopiera säkerhetskod", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium-medlemskap" + }, + "premiumManage": { + "message": "Hantera medlemskap" + }, + "premiumManageAlert": { + "message": "Du kan hantera ditt medlemskap i Bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "premiumRefresh": { + "message": "Uppdatera medlemskap" + }, + "premiumNotCurrentMember": { + "message": "Du är för närvarande inte en premium-medlem." + }, + "premiumSignUpAndGet": { + "message": "Registrera dig för ett premium-medlemskap och få:" + }, + "premiumSignUpStorage": { + "message": "1 GB krypterad lagring." + }, + "premiumSignUpTwoStep": { + "message": "Ytterligare alternativ för tvåstegsverifiering såsom YubiKey, FIDO U2F och Duo." + }, + "premiumSignUpReports": { + "message": "Lösenordshygien, kontohälsa och dataintrångsrapporter för att skydda ditt valv." + }, + "premiumSignUpTotp": { + "message": "TOTP-verifieringskodgenerator (2FA) för inloggningar i ditt valv." + }, + "premiumSignUpSupport": { + "message": "Prioriterad kundservice." + }, + "premiumSignUpFuture": { + "message": "Alla framtida premium-funktioner. Mer kommer snart!" + }, + "premiumPurchase": { + "message": "Köp premium" + }, + "premiumPurchaseAlert": { + "message": "Du kan köpa premium-medlemskap i Bitwardens webbvalv. Vill du besöka webbplatsen nu?" + }, + "premiumCurrentMember": { + "message": "Du är en premium-medlem!" + }, + "premiumCurrentMemberThanks": { + "message": "Tack för att du stödjer Bitwarden." + }, + "premiumPrice": { + "message": "Allt för endast $PRICE$/år!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Uppdateringen slutfördes" + }, + "passwordHistory": { + "message": "Lösenordshistorik" + }, + "clear": { + "message": "Rensa", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Det finns inga lösenord att visa." + }, + "undo": { + "message": "Ångra" + }, + "redo": { + "message": "Gör om" + }, + "cut": { + "message": "Klipp ut", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Klistra in", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Markera alla" + }, + "zoomIn": { + "message": "Zooma in" + }, + "zoomOut": { + "message": "Zooma ut" + }, + "resetZoom": { + "message": "Återställ zoom" + }, + "toggleFullScreen": { + "message": "Växla helskärm" + }, + "reload": { + "message": "Ladda om" + }, + "toggleDevTools": { + "message": "Växla utvecklingsverktyg" + }, + "minimize": { + "message": "Minimera", + "description": "Minimize window" + }, + "zoom": { + "message": "Zooma" + }, + "bringAllToFront": { + "message": "Lägg alla överst", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Om Bitwarden" + }, + "services": { + "message": "Tjänster" + }, + "hideBitwarden": { + "message": "Dölj Bitwarden" + }, + "hideOthers": { + "message": "Dölj övriga" + }, + "showAll": { + "message": "Visa alla" + }, + "quitBitwarden": { + "message": "Avsluta Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ kopierades", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Hjälp" + }, + "window": { + "message": "Fönster" + }, + "checkPassword": { + "message": "Kontrollera om lösenordet har avslöjats." + }, + "passwordExposed": { + "message": "Detta lösenord har avslöjats $VALUE$ gång(er) i dataintrång. Du bör ändra det.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Detta lösenord hittades inte i några kända dataintrång. Det bör vara säkert att använda." + }, + "baseDomain": { + "message": "Basdomän", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domännamn", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Värd", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exakt" + }, + "startsWith": { + "message": "Börjar med" + }, + "regEx": { + "message": "Reguljärt uttryck", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Matchning", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Standardmatchning", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Växla alternativ" + }, + "organization": { + "message": "Organisation", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Standard" + }, + "exit": { + "message": "Avsluta" + }, + "showHide": { + "message": "Visa / Dölj", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Minimera till systemfältet" + }, + "alwaysOnTop": { + "message": "Alltid överst", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Uppdaterades", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Lösenordet uppdaterades", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Exportera valv" + }, + "fileFormat": { + "message": "Filformat" + }, + "warning": { + "message": "VARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Bekräfta export av valv" + }, + "exportWarningDesc": { + "message": "Denna export innehåller ditt valv i ett okrypterat format. Du bör inte lagra eller skicka den exporterade filen över osäkra kanaler (t.ex. e-post). Radera den omedelbart när du är färdig med den." + }, + "encExportKeyWarningDesc": { + "message": "Denna export krypterar dina data med kontots krypteringsnyckel. Om du någonsin roterar kontots krypteringsnyckel bör du exportera igen eftersom du inte kommer att kunna dekryptera denna exportfil." + }, + "encExportAccountWarningDesc": { + "message": "Kypteringsnycklar är unika för varje Bitwarden-konto, så du kan inte importera en krypterad export till ett annat konto." + }, + "noOrganizationsList": { + "message": "Du tillhör inte några organisationer. Organisationer möjliggör säker delning av objekt med andra användare." + }, + "noCollectionsInList": { + "message": "Det finns inga samlingar att visa." + }, + "ownership": { + "message": "Ägarskap" + }, + "whoOwnsThisItem": { + "message": "Vem äger detta objekt?" + }, + "strong": { + "message": "Starkt", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Bra", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Svagt", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Svagt huvudlösenord" + }, + "weakMasterPasswordDesc": { + "message": "Huvudlösenordet du har valt är svagt. Du bör använda ett starkt huvudlösenord (eller en lösenordsfras) för att skydda ditt Bitwarden-konto ordentligt. Är du säker på att du vill använda detta huvudlösenord?" + }, + "pin": { + "message": "PIN-kod", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Lås upp med PIN-kod" + }, + "setYourPinCode": { + "message": "Ange en PIN-kod att låsa upp Bitwarden med. Dina PIN-kodsinställningar återställs om du någonsin loggar ut helt från programmet." + }, + "pinRequired": { + "message": "PIN-kod krävs." + }, + "invalidPin": { + "message": "Ogiltig PIN-kod." + }, + "unlockWithWindowsHello": { + "message": "Lås upp med Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Bekräfta för Bitwarden." + }, + "unlockWithTouchId": { + "message": "Lås upp med Touch ID" + }, + "touchIdConsentMessage": { + "message": "lås upp ditt valv" + }, + "noAutoPromptWindowsHello": { + "message": "Fråga inte efter Windows Hello vid uppstart." + }, + "noAutoPromptTouchId": { + "message": "Fråga inte efter Touch-ID vid uppstart." + }, + "lockWithMasterPassOnRestart": { + "message": "Lås med huvudlösenordet vid omstart" + }, + "preferences": { + "message": "Inställningar" + }, + "enableMenuBar": { + "message": "Aktivera aktivitetsfältsikon" + }, + "enableMenuBarDesc": { + "message": "Visa alltid en ikon i aktivitetsfältet." + }, + "hideToMenuBar": { + "message": "Minimera till aktivitetsfältet" + }, + "selectOneCollection": { + "message": "Du måste markera minst en samling." + }, + "premiumUpdated": { + "message": "Du har uppgraderat till premium." + }, + "restore": { + "message": "Återställ" + }, + "premiumManageAlertAppStore": { + "message": "Du kan hantera ditt abonnemang i App Store. Vill du besöka App Store nu?" + }, + "legal": { + "message": "Juridiskt", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Användarvillkor" + }, + "privacyPolicy": { + "message": "Integritetspolicy" + }, + "unsavedChangesConfirmation": { + "message": "Är du säker på att du vill lämna? Om du lämnar kommer din nuvarande information inte att sparas." + }, + "unsavedChangesTitle": { + "message": "Ändringar som inte sparats" + }, + "clone": { + "message": "Klona" + }, + "passwordGeneratorPolicyInEffect": { + "message": "En eller flera organisationspolicyer påverkar dina generatorinställningar." + }, + "vaultTimeoutAction": { + "message": "Åtgärd när valvets tidsgräns överskrids" + }, + "vaultTimeoutActionLockDesc": { + "message": "Ett låst valv kräver att du anger ditt huvudlösenord för att komma åt det igen." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Ett utloggat valv kräver att du autentiserar för att komma åt det igen." + }, + "lock": { + "message": "Lås", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Papperskorgen", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Sök i papperskorgen" + }, + "permanentlyDeleteItem": { + "message": "Radera objekt permanent" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Är du säker på att du vill radera detta objekt permanent?" + }, + "permanentlyDeletedItem": { + "message": "Raderade objekt permanent" + }, + "restoreItem": { + "message": "Återställ objekt" + }, + "restoreItemConfirmation": { + "message": "Är du säker på att du vill återställa detta objekt?" + }, + "restoredItem": { + "message": "Återställde objekt" + }, + "permanentlyDelete": { + "message": "Radera permanent" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Genom att logga ut upphör all åtkomst till valvet och onlineautentisering krävs efter att tidsgränsen överskridits. Är du säker på att du vill använda denna inställning?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Bekräftelse av åtgärd när valvets tidsgräns överskrids" + }, + "enterpriseSingleSignOn": { + "message": "Single Sign-On för företag" + }, + "setMasterPassword": { + "message": "Ange huvudlösenord" + }, + "ssoCompleteRegistration": { + "message": "För att slutföra inloggning med SSO, ange ett huvudlösenord för att komma åt och skydda ditt valv." + }, + "newMasterPass": { + "message": "Nytt huvudlösenord" + }, + "confirmNewMasterPass": { + "message": "Bekräfta nytt huvudlösenord" + }, + "masterPasswordPolicyInEffect": { + "message": "En eller flera organisationspolicyer kräver att ditt huvudlösenord uppfyller följande krav:" + }, + "policyInEffectMinComplexity": { + "message": "Minsta komplexitetspoäng på $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minsta längd på $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Innehålla en eller flera versaler" + }, + "policyInEffectLowercase": { + "message": "Innehålla en eller flera gemener" + }, + "policyInEffectNumbers": { + "message": "Innehålla en eller flera siffror" + }, + "policyInEffectSpecial": { + "message": "Innehålla ett eller flera av följande specialtecken: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ditt nya huvudlösenord uppfyller inte kraven i policyn." + }, + "acceptPolicies": { + "message": "Genom att markera denna ruta godkänner du följande:" + }, + "acceptPoliciesError": { + "message": "Användarvillkoren och Integritetspolicyn har inte accepterats." + }, + "enableBrowserIntegration": { + "message": "Aktivera webbläsarintegration" + }, + "enableBrowserIntegrationDesc": { + "message": "Webbläsarintegration används för biometri i webbläsaren." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Webbläsarintegration stöds inte" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Tyvärr stöds webbläsarintegration för tillfället endast i versionen från Mac App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Webbläsarintegration stöds inte" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Tyvärr stöds webbläsarintegration för tillfället inte i versionen från Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Kräv verifiering för webbläsarintegration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Aktivera ett ytterligare säkerhetslager genom att kräva validering av fingeravtrycksfrasen när du upprättar en länk mellan skrivbordet och webbläsaren. När det här är aktiverat krävs ingripande och verifiering från användaren varje gång en anslutning etableras." + }, + "approve": { + "message": "Godkänn" + }, + "verifyBrowserTitle": { + "message": "Verifiera webbläsaranslutning" + }, + "verifyBrowserDesc": { + "message": "Säkerställ att det fingeravtrycket som visas är identiskt med fingeravtrycket som visas i webbläsartillägget." + }, + "biometricsNotEnabledTitle": { + "message": "Biometri är inte aktiverat" + }, + "biometricsNotEnabledDesc": { + "message": "Biometri i webbläsaren kräver att biometri på skrivbordet aktiveras i inställningarna först." + }, + "personalOwnershipSubmitError": { + "message": "På grund av en av företagets policyer är du begränsad från att spara objekt till ditt personliga valv. Ändra ägarskap till en organisation och välj från tillgängliga samlingar." + }, + "hintEqualsPassword": { + "message": "Din lösenordsledtråd får inte vara samma som ditt lösenord." + }, + "personalOwnershipPolicyInEffect": { + "message": "En organisationspolicy påverkar dina ägarskapsalternativ." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Fil" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Redigera Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Mitt valv" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Raderingsdatum" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Utgångsdatum" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximalt antal åtkomster" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Nuvarande antal åtkomster" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Nytt lösenord" + }, + "whatTypeOfSend": { + "message": "Vilken typ av Send är detta?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Skapa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Texten du vill skicka." + }, + "sendFileDesc": { + "message": "Filen du vill skicka." + }, + "days": { + "message": "$DAYS$ dagar", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 dag" + }, + "custom": { + "message": "Anpassad" + }, + "deleteSendConfirmation": { + "message": "Är du säker på att du vill radera denna Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Kopiera länk" + }, + "disabled": { + "message": "Inaktiverad" + }, + "maxAccessCountReached": { + "message": "Det maximala antalet åtkomster har uppnåtts" + }, + "expired": { + "message": "Utgången" + }, + "pendingDeletion": { + "message": "Väntar på radering" + }, + "webAuthnAuthenticate": { + "message": "Autentisera WebAuthn" + }, + "hideEmail": { + "message": "Dölj min e-postadress för mottagare." + }, + "sendOptionsPolicyInEffect": { + "message": "En eller flera organisationsriktlinjer påverkar dina Send-inställningar." + }, + "emailVerificationRequired": { + "message": "E-postverifiering krävs" + }, + "emailVerificationRequiredDesc": { + "message": "Du måste verifiera din e-post för att använda den här funktionen." + }, + "passwordPrompt": { + "message": "Återupprepa huvudlösenord" + }, + "passwordConfirmation": { + "message": "Bekräfta huvudlösenord" + }, + "passwordConfirmationDesc": { + "message": "Denna åtgärd är skyddad. För att fortsätta, vänligen verifiera din identitet genom att ange ditt huvudlösenord." + }, + "updatedMasterPassword": { + "message": "Huvudlösenord uppdaterades" + }, + "updateMasterPassword": { + "message": "Uppdatera huvudlösenord" + }, + "updateMasterPasswordWarning": { + "message": "Ditt huvudlösenord ändrades nyligen av en administratör i din organisation. För att få tillgång till valvet måste du uppdatera det nu. Om du fortsätter kommer du att loggas ut från din nuvarande session, vilket kräver att du loggar in igen. Aktiva sessioner på andra enheter kan komma att vara aktiva i upp till en timme." + }, + "hours": { + "message": "Timmar" + }, + "minutes": { + "message": "Minuter" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Dina organisationsprinciper påverkar ditt valvs tid för timeout. Maximal tillåten tid innan timeout är $HOURS$ timme(ar) och $MINUTES$ minut(er)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Ditt valvs tid för timeout överskrider de begränsningar som fastställts av din organisation." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatiskt deltagande" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Denna organisation har en företagspolicy som automatiskt registrerar dig för lösenordsåterställning. Deltagandet gör det möjligt för organisationsadministratörer att ändra ditt huvudlösenord." + }, + "vaultExportDisabled": { + "message": "Valvexport inaktiverad" + }, + "personalVaultExportPolicyInEffect": { + "message": "En eller flera organisationsprinciper hindrar dig från att exportera ditt personliga valv." + }, + "addAccount": { + "message": "Lägg till konto" + }, + "removeMasterPassword": { + "message": "Ta bort huvudlösenord" + }, + "removedMasterPassword": { + "message": "Huvudlösenord togs bort." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ använder SSO med en egen nyckelserver. Ett huvudlösenord krävs inte längre för att logga in för medlemmar i denna organisation.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Lämna organisation" + }, + "leaveOrganizationConfirmation": { + "message": "Är du säker på att du vill lämna denna organisation?" + }, + "leftOrganization": { + "message": "Du har lämnat organisationen." + }, + "ssoKeyConnectorUnavailable": { + "message": "Kunde inte nå key connector, försök igen senare." + }, + "lockAllVaults": { + "message": "Lås alla valv" + }, + "accountLimitReached": { + "message": "Inte mer än 5 konton får vara inloggade samtidigt." + }, + "accountPreferences": { + "message": "Inställningar" + }, + "appPreferences": { + "message": "Appinställningar (alla konton)" + }, + "accountSwitcherLimitReached": { + "message": "Kontogränsen har nåtts. Logga ut från ett konto för att lägga till ett annat." + }, + "settingsTitle": { + "message": "Appinställningar för $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Byt konto" + }, + "options": { + "message": "Alternativ" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/th/messages.json b/apps/desktop/src/locales/th/messages.json new file mode 100644 index 0000000000..2beca203da --- /dev/null +++ b/apps/desktop/src/locales/th/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "bitwarden" + }, + "filters": { + "message": "ตัวกรอง" + }, + "allItems": { + "message": "รายการทั้งหมด" + }, + "favorites": { + "message": "รายการโปรด" + }, + "types": { + "message": "Types" + }, + "typeLogin": { + "message": "เข้าสู่ระบบ" + }, + "typeCard": { + "message": "บัตร" + }, + "typeIdentity": { + "message": "ข้อมูลระบุตัวตน" + }, + "typeSecureNote": { + "message": "บันทึกการรักษาปลอดภัย" + }, + "folders": { + "message": "โฟลเดอร์" + }, + "collections": { + "message": "คอลเลกชัน" + }, + "searchVault": { + "message": "Search vault" + }, + "addItem": { + "message": "เพิ่มรายการ" + }, + "shared": { + "message": "แบ่งปัน" + }, + "share": { + "message": "Share" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Attachments" + }, + "viewItem": { + "message": "ดูรายการ" + }, + "name": { + "message": "ชื่อ" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "New URI" + }, + "username": { + "message": "ชื่อผู้ใช้" + }, + "password": { + "message": "รหัสผ่าน" + }, + "passphrase": { + "message": "Passphrase" + }, + "editItem": { + "message": "แก้ไขรายการ" + }, + "emailAddress": { + "message": "ที่อยู่อีเมล์" + }, + "verificationCodeTotp": { + "message": "รหัสยืนยัน (TOTP)" + }, + "website": { + "message": "เว็บไซต์" + }, + "notes": { + "message": "Notes" + }, + "customFields": { + "message": "Custom Fields" + }, + "launch": { + "message": "Launch" + }, + "copyValue": { + "message": "คัดลอกค่า", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Minimize when copying to clipboard" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Minimize when copying an item's data to the clipboard." + }, + "toggleVisibility": { + "message": "Toggle Visibility" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Cardholder Name" + }, + "number": { + "message": "หมายเลข" + }, + "brand": { + "message": "แบรนด์" + }, + "expiration": { + "message": "วันหมดอายุ" + }, + "securityCode": { + "message": "รหัสความปลอดภัย" + }, + "identityName": { + "message": "identityName" + }, + "company": { + "message": "บริษัท" + }, + "ssn": { + "message": "หมายเลขประกันสังคม" + }, + "passportNumber": { + "message": "หมายเลขหนังสือเดินทาง" + }, + "licenseNumber": { + "message": "หมายเลขใบอนุญาต" + }, + "email": { + "message": "อีเมล" + }, + "phone": { + "message": "โทรศัพท์" + }, + "address": { + "message": "ที่อยู่" + }, + "premiumRequired": { + "message": "Premium Required" + }, + "premiumRequiredDesc": { + "message": "จำเป็นต้องมีสมาชิกระดับพรีเมียมเพื่อใช้คุณลักษณะนี้" + }, + "errorOccurred": { + "message": "พบข้อผิดพลาด" + }, + "error": { + "message": "ข้อผิดพลาด" + }, + "january": { + "message": "มกราคม" + }, + "february": { + "message": "กุมภาพันธ์" + }, + "march": { + "message": "มีนาคม" + }, + "april": { + "message": "เมษายน" + }, + "may": { + "message": "พฤษภาคม" + }, + "june": { + "message": "มิถุนายน" + }, + "july": { + "message": "กรกฎาคม" + }, + "august": { + "message": "สิงหาคม" + }, + "september": { + "message": "กันยายน" + }, + "october": { + "message": "ตุลาคม" + }, + "november": { + "message": "พฤศจิกายน" + }, + "december": { + "message": "ธันวาคม" + }, + "ex": { + "message": "ex.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "คำนำหน้า" + }, + "mr": { + "message": "นาย" + }, + "mrs": { + "message": "นาง" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "ดร." + }, + "expirationMonth": { + "message": "เดือนที่หมดอายุ" + }, + "expirationYear": { + "message": "ปีที่หมดอายุ" + }, + "select": { + "message": "เลือก" + }, + "other": { + "message": "อื่น ๆ" + }, + "generatePassword": { + "message": "สร้างรหัสผ่าน" + }, + "type": { + "message": "Type" + }, + "firstName": { + "message": "ชื่อจริง" + }, + "middleName": { + "message": "ชื่อกลาง" + }, + "lastName": { + "message": "นามสกุล" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "ที่อยู่ 1" + }, + "address2": { + "message": "ที่อยู่ 2" + }, + "address3": { + "message": "ที่อยู่ 3" + }, + "cityTown": { + "message": "เมือง" + }, + "stateProvince": { + "message": "รัฐ / จังหวัด" + }, + "zipPostalCode": { + "message": "รหัสไปรษณีย์" + }, + "country": { + "message": "ประเทศ" + }, + "save": { + "message": "บันทึก" + }, + "cancel": { + "message": "ยกเลิก" + }, + "delete": { + "message": "ลบ" + }, + "favorite": { + "message": "รายการโปรด" + }, + "edit": { + "message": "แก้ไข" + }, + "authenticatorKeyTotp": { + "message": "คีย์ Authenticator (TOTP)" + }, + "folder": { + "message": "โฟลเดอร์" + }, + "newCustomField": { + "message": "สร้างเขตข้อมูลแบบระบุเอง" + }, + "value": { + "message": "Value" + }, + "dragToSort": { + "message": "Drag to sort" + }, + "cfTypeText": { + "message": "Text" + }, + "cfTypeHidden": { + "message": "ซ่อน" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "เอาออก" + }, + "nameRequired": { + "message": "จำเป็นต้องกรอกชื่อ" + }, + "addedItem": { + "message": "เพิ่มรายการแล้ว" + }, + "editedItem": { + "message": "แก้ไขรายการแล้ว" + }, + "deleteItem": { + "message": "ลบรายการ" + }, + "deleteFolder": { + "message": "ลบโฟลเดอร์" + }, + "deleteAttachment": { + "message": "ลบสิ่งที่แนบมา" + }, + "deleteItemConfirmation": { + "message": "คุณแน่ใจว่าจะลบรายการนี้?" + }, + "deletedItem": { + "message": "ลบรายการแล้ว" + }, + "overwritePasswordConfirmation": { + "message": "คุณแน่ใจว่าต้องการเขียนทับรหัสผ่านปัจจุบัน?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "ไม่มีโฟลเดอร์", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "เพิ่มโฟลเดอร์" + }, + "editFolder": { + "message": "แก้ไขโฟลเดอร์" + }, + "regeneratePassword": { + "message": "สร้างรหัสผ่านใหม่" + }, + "copyPassword": { + "message": "คัดลอกรหัสผ่าน" + }, + "copyUri": { + "message": "คัดลอก URI" + }, + "copyVerificationCodeTotp": { + "message": "Copy Verification Code (TOTP)" + }, + "length": { + "message": "ความยาว" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Capitalize", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Include Number" + }, + "close": { + "message": "ปิด" + }, + "minNumbers": { + "message": "จำนวนตัวเลขต่ำสุด" + }, + "minSpecial": { + "message": "จำนวนตัวพิเศษขั้นต่ำ", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "หลีกเลี่ยงอักขระที่ไม่ชัดเจน" + }, + "searchCollection": { + "message": "Search collection" + }, + "searchFolder": { + "message": "Search folder" + }, + "searchFavorites": { + "message": "Search favorites" + }, + "searchType": { + "message": "Search type", + "description": "Search item type" + }, + "newAttachment": { + "message": "เพิ่มไฟล์แนบใหม่" + }, + "deletedAttachment": { + "message": "ลบไฟล์แนบแล้ว" + }, + "deleteAttachmentConfirmation": { + "message": "Are you sure you want to delete this attachment?" + }, + "attachmentSaved": { + "message": "The attachment has been saved." + }, + "file": { + "message": "File" + }, + "selectFile": { + "message": "เลือกไฟล์" + }, + "maxFileSize": { + "message": "ขนาดไฟล์สูงสุดคือ 500 MB" + }, + "updateKey": { + "message": "คุณไม่สามารถใช้คุณลักษณะนี้ได้จนกว่าคุณปรับปรุงคีย์การเข้ารหัสลับของคุณ" + }, + "editedFolder": { + "message": "แก้​ไข​โฟลเดอร์แล้ว" + }, + "addedFolder": { + "message": "เพิ่มโฟลเดอร์แล้ว" + }, + "deleteFolderConfirmation": { + "message": "คุณแน่ใจหรือว่าคุณต้องการลบโฟลเดอร์นี้?" + }, + "deletedFolder": { + "message": "ลบโฟลเดอร์แล้ว" + }, + "loginOrCreateNewAccount": { + "message": "ลงชื่อเข้าใช้หรือสร้างบัญชีใหม่เพื่อเข้าสู่ห้องนิรภัยที่ปลอดภัยของคุณ" + }, + "createAccount": { + "message": "สร้างบัญชี" + }, + "logIn": { + "message": "เข้าสู่ระบบ" + }, + "submit": { + "message": "ส่งข้อมูล" + }, + "masterPass": { + "message": "รหัสผ่านหลัก" + }, + "masterPassDesc": { + "message": "The master password is the password you use to access your vault. It is very important that you do not forget your master password. There is no way to recover the password in the event that you forget it." + }, + "masterPassHintDesc": { + "message": "A master password hint can help you remember your password if you forget it." + }, + "reTypeMasterPass": { + "message": "Re-type Master Password" + }, + "masterPassHint": { + "message": "Master Password Hint (optional)" + }, + "settings": { + "message": "การตั้งค่า" + }, + "passwordHint": { + "message": "คำใบ้รหัสผ่าน" + }, + "enterEmailToGetHint": { + "message": "Enter your account email address to receive your master password hint." + }, + "getMasterPasswordHint": { + "message": "รับคำใบ้เกี่ยวกับรหัสผ่านหลักของคุณ" + }, + "emailRequired": { + "message": "จำเป็นต้องกรอกที่อยู่อีเมล" + }, + "invalidEmail": { + "message": "ที่อยู่อีเมลไม่ถูกต้อง" + }, + "masterPassRequired": { + "message": "จำเป็นต้องมีรหัสผ่านหลัก" + }, + "masterPassLength": { + "message": "Master password must be at least 8 characters long." + }, + "masterPassDoesntMatch": { + "message": "Master password confirmation does not match." + }, + "newAccountCreated": { + "message": "Your new account has been created! You may now log in." + }, + "masterPassSent": { + "message": "We've sent you an email with your master password hint." + }, + "unexpectedError": { + "message": "An unexpected error has occurred." + }, + "itemInformation": { + "message": "ข้อมูลรายการ" + }, + "noItemsInList": { + "message": "There are no items to list." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "รหัสยืนยัน" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Verification code is required." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "ดำเนินการต่อไป" + }, + "enterVerificationCodeApp": { + "message": "ป้อนรหัสยืนยัน 6 หลักจากคุณแอป authenticator" + }, + "enterVerificationCodeEmail": { + "message": "ป้อนรหัสยืนยัน 6 หลักที่ส่งทางอีเมล $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Verification email sent to $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "จดจำการเข้าระบบของฉัน" + }, + "sendVerificationCodeEmailAgain": { + "message": "ส่งอีเมล์ยืนยันรหัสอีกครั้ง" + }, + "useAnotherTwoStepMethod": { + "message": "ใช้วิธีลงชื่อเข้าใช้แบบสองขั้นตอนวิธีอื่น" + }, + "insertYubiKey": { + "message": "Insert your YubiKey into your computer's USB port, then touch its button." + }, + "insertU2f": { + "message": "Insert your security key into your computer's USB port. If it has a button, touch it." + }, + "recoveryCodeDesc": { + "message": "Lost access to all of your two-factor providers? Use your recovery code to disable all two-factor providers from your account." + }, + "recoveryCodeTitle": { + "message": "รหัสกู้คืน" + }, + "authenticatorAppTitle": { + "message": "แอป Authenticator" + }, + "authenticatorAppDesc": { + "message": "Use an authenticator app (such as Authy or Google Authenticator) to generate time-based verification codes.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Security Key" + }, + "yubiKeyDesc": { + "message": "Use a YubiKey to access your account. Works with YubiKey 4, 4 Nano, 4C, and NEO devices." + }, + "duoDesc": { + "message": "Verify with Duo Security using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "อีเมล" + }, + "emailDesc": { + "message": "Verification codes will be emailed to you." + }, + "loginUnavailable": { + "message": "เข้าสู่ระบบไม่พร้อมใช้งาน" + }, + "noTwoStepProviders": { + "message": "This account has two-step login enabled, however, none of the configured two-step providers are supported by this device." + }, + "noTwoStepProviders2": { + "message": "Please add additional providers that are better supported across devices (such as an authenticator app)." + }, + "twoStepOptions": { + "message": "ตัวเลือกการเข้าสู่ระบบแบบสองขั้นตอน" + }, + "selfHostedEnvironment": { + "message": "Self-hosted Environment" + }, + "selfHostedEnvironmentFooter": { + "message": "Specify the base URL of your on-premise hosted bitwarden installation." + }, + "customEnvironment": { + "message": "Custom Environment" + }, + "customEnvironmentFooter": { + "message": "For advanced users. You can specify the base URL of each service independently." + }, + "baseUrl": { + "message": "Server URL" + }, + "apiUrl": { + "message": "API Server URL" + }, + "webVaultUrl": { + "message": "Web Vault Server URL" + }, + "identityUrl": { + "message": "Identity Server URL" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Icons Server URL" + }, + "environmentSaved": { + "message": "The environment URLs have been saved." + }, + "ok": { + "message": "ตกลง" + }, + "yes": { + "message": "ใช่" + }, + "no": { + "message": "ไม่ใช่" + }, + "overwritePassword": { + "message": "เขียนทับรหัสผ่าน" + }, + "learnMore": { + "message": "เรียนรู้เพิ่มเติม" + }, + "featureUnavailable": { + "message": "Feature Unavailable" + }, + "loggedOut": { + "message": "Logged out" + }, + "loginExpired": { + "message": "Your login session has expired." + }, + "logOutConfirmation": { + "message": "Are you sure you want to log out?" + }, + "logOut": { + "message": "Log Out" + }, + "addNewLogin": { + "message": "เพิ่มการเข้าสู่ระบบใหม่" + }, + "addNewItem": { + "message": "เพิ่มรายการใหม่" + }, + "addNewFolder": { + "message": "เพิ่มโฟลเดอร์ใหม่" + }, + "view": { + "message": "View" + }, + "account": { + "message": "บัญชี" + }, + "loading": { + "message": "กำลังโหลด..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "ตัวสร้างรหัสผ่าน" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "File a Bug Report" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Follow Us" + }, + "syncVault": { + "message": "Sync Vault" + }, + "changeMasterPass": { + "message": "เปลี่ยนรหัสผ่านหลัก" + }, + "changeMasterPasswordConfirmation": { + "message": "You can change your master password on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Your account's fingerprint phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Go To Web Vault" + }, + "getMobileApp": { + "message": "รับแอปมือถือ" + }, + "getBrowserExtension": { + "message": "Get Browser Extension" + }, + "syncingComplete": { + "message": "Syncing complete" + }, + "syncingFailed": { + "message": "Syncing failed" + }, + "yourVaultIsLocked": { + "message": "Your vault is locked. Verify your identity to continue." + }, + "unlock": { + "message": "Unlock" + }, + "loggedInAsOn": { + "message": "Logged in as $EMAIL$ on $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Invalid master password" + }, + "twoStepLoginConfirmation": { + "message": "Two-step login makes your account more secure by requiring you to verify your login with another device such as a security key, authenticator app, SMS, phone call, or email. Two-step login can be enabled on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "twoStepLogin": { + "message": "เข้าสู่ระบบแบบสองขั้นตอน" + }, + "vaultTimeout": { + "message": "Vault Timeout" + }, + "vaultTimeoutDesc": { + "message": "Choose when your vault will timeout and perform the selected action." + }, + "immediately": { + "message": "ทันที" + }, + "tenSeconds": { + "message": "10 seconds" + }, + "twentySeconds": { + "message": "20 seconds" + }, + "thirtySeconds": { + "message": "30 seconds" + }, + "oneMinute": { + "message": "1 นาที" + }, + "twoMinutes": { + "message": "2 minutes" + }, + "fiveMinutes": { + "message": "5 นาที" + }, + "fifteenMinutes": { + "message": "15 นาที" + }, + "thirtyMinutes": { + "message": "30 นาที" + }, + "oneHour": { + "message": "1 ชั่วโมง" + }, + "fourHours": { + "message": "4 ชั่วโมง" + }, + "onIdle": { + "message": "On System Idle" + }, + "onSleep": { + "message": "On System Sleep" + }, + "onLocked": { + "message": "On System Lock" + }, + "onRestart": { + "message": "On Restart" + }, + "never": { + "message": "Never" + }, + "security": { + "message": "Security" + }, + "clearClipboard": { + "message": "Clear Clipboard", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Automatically clear copied values from your clipboard.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Disable Website Icons" + }, + "disableFaviconDesc": { + "message": "Website Icons provide a recognizable image next to each login item in your vault." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "When closing the window, show an icon in the system tray instead." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Always show an icon in the system tray." + }, + "startToTray": { + "message": "Start To Tray Icon" + }, + "startToTrayDesc": { + "message": "When the application is first started, only show an icon in the system tray." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change the language used by the application. Restart is required." + }, + "theme": { + "message": "Theme" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Dark", + "description": "Dark color" + }, + "light": { + "message": "Light", + "description": "Light color" + }, + "copy": { + "message": "คัดลอก", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "ตรวจสอบการอัปเดต" + }, + "version": { + "message": "รุ่น $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Restart To Update" + }, + "restartToUpdateDesc": { + "message": "Version $VERSION_NUM$ is ready to install. You must restart Bitwarden to complete the installation. Do you want to restart and update now?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Update Available" + }, + "updateAvailableDesc": { + "message": "An update was found. Do you want to download it now?" + }, + "restart": { + "message": "เริ่มต้นใหม่" + }, + "later": { + "message": "ภายหลัง" + }, + "noUpdatesAvailable": { + "message": "โปรแกรมไม่มีการปรับปรุงอยู่ในขณะนี้ คุณกำลังใช้รุ่นล่าสุด" + }, + "updateError": { + "message": "เกิดข้อผิดพลาดในการอัปเดต" + }, + "unknown": { + "message": "Unknown" + }, + "copyUsername": { + "message": "คัดลอกชื่อผู้ใช้" + }, + "copyNumber": { + "message": "คัดลอกหมายเลข", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "คัดลอกรหัสรักษาความปลอดภัย", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium Membership" + }, + "premiumManage": { + "message": "Manage Membership" + }, + "premiumManageAlert": { + "message": "You can manage your membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumRefresh": { + "message": "Refresh Membership" + }, + "premiumNotCurrentMember": { + "message": "You are not currently a premium member." + }, + "premiumSignUpAndGet": { + "message": "Sign up for a premium membership and get:" + }, + "premiumSignUpStorage": { + "message": "1 GB of encrypted file storage." + }, + "premiumSignUpTwoStep": { + "message": "Additional two-step login options such as YubiKey, FIDO U2F, and Duo." + }, + "premiumSignUpReports": { + "message": "Password hygiene, account health, and data breach reports to keep your vault safe." + }, + "premiumSignUpTotp": { + "message": "TOTP verification code (2FA) generator for logins in your vault." + }, + "premiumSignUpSupport": { + "message": "Priority customer support." + }, + "premiumSignUpFuture": { + "message": "All future premium features. More coming soon!" + }, + "premiumPurchase": { + "message": "Purchase Premium" + }, + "premiumPurchaseAlert": { + "message": "You can purchase premium membership on the bitwarden.com web vault. Do you want to visit the website now?" + }, + "premiumCurrentMember": { + "message": "You are a premium member!" + }, + "premiumCurrentMemberThanks": { + "message": "Thank you for supporting bitwarden." + }, + "premiumPrice": { + "message": "All for just $PRICE$ /year!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Refresh complete" + }, + "passwordHistory": { + "message": "ประวัติของรหัสผ่าน" + }, + "clear": { + "message": "Clear", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "There are no passwords to list." + }, + "undo": { + "message": "Undo" + }, + "redo": { + "message": "Redo" + }, + "cut": { + "message": "ตัด", + "description": "Cut to clipboard" + }, + "paste": { + "message": "วาง", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "เลือกทั้งหมด" + }, + "zoomIn": { + "message": "ซูมเข้า" + }, + "zoomOut": { + "message": "ซูมออก" + }, + "resetZoom": { + "message": "รีเซ็ตการซูม" + }, + "toggleFullScreen": { + "message": "สลับแบบเต็มหน้าจอ" + }, + "reload": { + "message": "โหลดใหม่" + }, + "toggleDevTools": { + "message": "สลับไปเครื่องมือนักพัฒนา" + }, + "minimize": { + "message": "ย่อเล็กที่สุด", + "description": "Minimize window" + }, + "zoom": { + "message": "ซูม" + }, + "bringAllToFront": { + "message": "Bring All to Front", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "About Bitwarden" + }, + "services": { + "message": "Services" + }, + "hideBitwarden": { + "message": "ซ่อน Bitwarden" + }, + "hideOthers": { + "message": "Hide Others" + }, + "showAll": { + "message": "แสดงทั้งหมด" + }, + "quitBitwarden": { + "message": "ออกจาก Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ คัดลอกแล้ว", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "ช่วยเหลือ" + }, + "window": { + "message": "Window" + }, + "checkPassword": { + "message": "Check if password has been exposed." + }, + "passwordExposed": { + "message": "This password has been exposed $VALUE$ time(s) in data breaches. You should change it.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "This password was not found in any known data breaches. It should be safe to use." + }, + "baseDomain": { + "message": "Base domain", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Host", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Exact" + }, + "startsWith": { + "message": "Starts with" + }, + "regEx": { + "message": "Regular expression", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Match Detection", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Default match detection", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Toggle Options" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Default" + }, + "exit": { + "message": "Exit" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Always on Top", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Updated", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "WARNING", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." + }, + "ownership": { + "message": "Ownership" + }, + "whoOwnsThisItem": { + "message": "Who owns this item?" + }, + "strong": { + "message": "Strong", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Good", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Weak", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "The master password you have chosen is weak. You should use a strong master password (or a passphrase) to properly protect your Bitwarden account. Are you sure you want to use this master password?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Unlock with PIN" + }, + "setYourPinCode": { + "message": "Set your PIN code for unlocking Bitwarden. Your PIN settings will be reset if you ever fully log out of the application." + }, + "pinRequired": { + "message": "PIN code is required." + }, + "invalidPin": { + "message": "Invalid PIN code." + }, + "unlockWithWindowsHello": { + "message": "Unlock with Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Verify for Bitwarden." + }, + "unlockWithTouchId": { + "message": "Unlock with Touch ID" + }, + "touchIdConsentMessage": { + "message": "unlock your vault" + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Lock with master password on restart" + }, + "preferences": { + "message": "Preferences" + }, + "enableMenuBar": { + "message": "Enable Menu Bar Icon" + }, + "enableMenuBarDesc": { + "message": "Always show an icon in the menu bar." + }, + "hideToMenuBar": { + "message": "Hide to Menu Bar" + }, + "selectOneCollection": { + "message": "You must select at least one collection." + }, + "premiumUpdated": { + "message": "You've upgraded to premium." + }, + "restore": { + "message": "Restore" + }, + "premiumManageAlertAppStore": { + "message": "You can manage your subscription from the App Store. Do you want to visit the App Store now?" + }, + "legal": { + "message": "Legal", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Terms of Service" + }, + "privacyPolicy": { + "message": "Privacy Policy" + }, + "unsavedChangesConfirmation": { + "message": "Are you sure you want to leave? If you leave now then your current information will not be saved." + }, + "unsavedChangesTitle": { + "message": "Unsaved Changes" + }, + "clone": { + "message": "Clone" + }, + "passwordGeneratorPolicyInEffect": { + "message": "One or more organization policies are affecting your generator settings." + }, + "vaultTimeoutAction": { + "message": "Vault Timeout Action" + }, + "vaultTimeoutActionLockDesc": { + "message": "A locked vault requires that you re-enter your master password to access it again." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "A logged out vault requires that you re-authenticate to access it again." + }, + "lock": { + "message": "Lock", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Trash", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Search trash" + }, + "permanentlyDeleteItem": { + "message": "Permanently Delete Item" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Are you sure you want to permanently delete this item?" + }, + "permanentlyDeletedItem": { + "message": "Permanently Deleted item" + }, + "restoreItem": { + "message": "Restore Item" + }, + "restoreItemConfirmation": { + "message": "Are you sure you want to restore this item?" + }, + "restoredItem": { + "message": "Restored Item" + }, + "permanentlyDelete": { + "message": "Permanently Delete" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Logging out will remove all access to your vault and requires online authentication after the timeout period. Are you sure you want to use this setting?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Timeout Action Confirmation" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Set Master Password" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "New Master Password" + }, + "confirmNewMasterPass": { + "message": "Confirm New Master Password" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Contain one or more uppercase characters" + }, + "policyInEffectLowercase": { + "message": "Contain one or more lowercase characters" + }, + "policyInEffectNumbers": { + "message": "Contain one or more numbers" + }, + "policyInEffectSpecial": { + "message": "Contain one or more of the following special characters $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Approve" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "All Sends", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "File" + }, + "sendTypeText": { + "message": "Text" + }, + "searchSends": { + "message": "Search Sends", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Edit Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "My Vault" + }, + "text": { + "message": "Text" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "The Send will be permanently deleted on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Expiration Date" + }, + "expirationDateDesc": { + "message": "If set, access to this Send will expire on the specified date and time.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maximum Access Count" + }, + "maxAccessCountDesc": { + "message": "If set, users will no longer be able to access this Send once the maximum access count is reached.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Current Access Count" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Created Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Edited Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Deleted Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "New Password" + }, + "whatTypeOfSend": { + "message": "What type of Send is this?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Create Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "The text you want to send." + }, + "sendFileDesc": { + "message": "The file you want to send." + }, + "days": { + "message": "$DAYS$ days", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 day" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Are you sure you want to delete this Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Send disabled", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Due to an enterprise policy, you are only able to delete an existing Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Copy link" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Pending deletion" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/tr/messages.json b/apps/desktop/src/locales/tr/messages.json new file mode 100644 index 0000000000..a946bab5af --- /dev/null +++ b/apps/desktop/src/locales/tr/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Filtreler" + }, + "allItems": { + "message": "Tüm kayıtlar" + }, + "favorites": { + "message": "Favoriler" + }, + "types": { + "message": "Türler" + }, + "typeLogin": { + "message": "Hesap" + }, + "typeCard": { + "message": "Kart" + }, + "typeIdentity": { + "message": "Kimlik" + }, + "typeSecureNote": { + "message": "Güvenli not" + }, + "folders": { + "message": "Klasörler" + }, + "collections": { + "message": "Koleksiyonlar" + }, + "searchVault": { + "message": "Kasada ara" + }, + "addItem": { + "message": "Kayıt ekle" + }, + "shared": { + "message": "Paylaşılan" + }, + "share": { + "message": "Paylaş" + }, + "moveToOrganization": { + "message": "Kuruluşa taşı" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ $ORGNAME$ kuruluşuna taşındı", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Bu kaydı taşımak istediğiniz kuruluşu seçin. Taşıdığınız kaydın sahipliği seçtiğiniz kuruluşa aktarılacak. Artık bu kaydın doğrudan sahibi olmayacaksınız." + }, + "attachments": { + "message": "Ekler" + }, + "viewItem": { + "message": "Kaydı göster" + }, + "name": { + "message": "Ad" + }, + "uri": { + "message": "URl" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Yeni URI" + }, + "username": { + "message": "Kullanıcı adı" + }, + "password": { + "message": "Parola" + }, + "passphrase": { + "message": "Uzun söz" + }, + "editItem": { + "message": "Kaydı düzenle" + }, + "emailAddress": { + "message": "E-posta adresi" + }, + "verificationCodeTotp": { + "message": "Doğrulama kodu (TOTP)" + }, + "website": { + "message": "Web sitesi" + }, + "notes": { + "message": "Notlar" + }, + "customFields": { + "message": "Özel alanlar" + }, + "launch": { + "message": "Aç" + }, + "copyValue": { + "message": "Değeri kopyala", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Panoya kaydederken küçült" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Bir kaydın verilerini panoya kopyalarken simge durumuna küçült." + }, + "toggleVisibility": { + "message": "Görünürlüğü aç/kapat" + }, + "toggleCollapse": { + "message": "Daraltmayı aç/kapat", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Kart sahibinin adı" + }, + "number": { + "message": "Numara" + }, + "brand": { + "message": "Marka" + }, + "expiration": { + "message": "Son kullanma tarihi" + }, + "securityCode": { + "message": "Güvenlik kodu" + }, + "identityName": { + "message": "Kimlik adı" + }, + "company": { + "message": "Şirket" + }, + "ssn": { + "message": "Sosyal güvenlik numarası" + }, + "passportNumber": { + "message": "Pasaport numarası" + }, + "licenseNumber": { + "message": "Ehliyet numarası" + }, + "email": { + "message": "E-posta" + }, + "phone": { + "message": "Telefon" + }, + "address": { + "message": "Adres" + }, + "premiumRequired": { + "message": "Premium gerekli" + }, + "premiumRequiredDesc": { + "message": "Bu özelliği kullanmak için premium üyelik gereklidir." + }, + "errorOccurred": { + "message": "Bir hata oluştu." + }, + "error": { + "message": "Hata" + }, + "january": { + "message": "Ocak" + }, + "february": { + "message": "Şubat" + }, + "march": { + "message": "Mart" + }, + "april": { + "message": "Nisan" + }, + "may": { + "message": "Mayıs" + }, + "june": { + "message": "Haziran" + }, + "july": { + "message": "Temmuz" + }, + "august": { + "message": "Ağustos" + }, + "september": { + "message": "Eylül" + }, + "october": { + "message": "Ekim" + }, + "november": { + "message": "Kasım" + }, + "december": { + "message": "Aralık" + }, + "ex": { + "message": "örn.", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Unvan" + }, + "mr": { + "message": "Bay" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "Son kullanma ayı" + }, + "expirationYear": { + "message": "Son kullanma yılı" + }, + "select": { + "message": "Seç" + }, + "other": { + "message": "Diğer" + }, + "generatePassword": { + "message": "Parola oluştur" + }, + "type": { + "message": "Tür" + }, + "firstName": { + "message": "Ad" + }, + "middleName": { + "message": "İkinci ad" + }, + "lastName": { + "message": "Soyadı" + }, + "fullName": { + "message": "Adı soyadı" + }, + "address1": { + "message": "Adres 1" + }, + "address2": { + "message": "Adres 2" + }, + "address3": { + "message": "Adres 3" + }, + "cityTown": { + "message": "İlçe" + }, + "stateProvince": { + "message": "İl / eyalet" + }, + "zipPostalCode": { + "message": "Posta kodu" + }, + "country": { + "message": "Ülke" + }, + "save": { + "message": "Kaydet" + }, + "cancel": { + "message": "İptal" + }, + "delete": { + "message": "Sil" + }, + "favorite": { + "message": "Favori" + }, + "edit": { + "message": "Düzenle" + }, + "authenticatorKeyTotp": { + "message": "Kimlik doğrulama anahtarı (TOTP)" + }, + "folder": { + "message": "Klasör" + }, + "newCustomField": { + "message": "Yeni özel alan" + }, + "value": { + "message": "Değer" + }, + "dragToSort": { + "message": "Sıralamak için sürükleyin" + }, + "cfTypeText": { + "message": "Metin" + }, + "cfTypeHidden": { + "message": "Gizli" + }, + "cfTypeBoolean": { + "message": "Boolean" + }, + "cfTypeLinked": { + "message": "Bağlantılı", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Bağlı değer", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Kaldır" + }, + "nameRequired": { + "message": "Ad gereklidir." + }, + "addedItem": { + "message": "Kayıt eklendi" + }, + "editedItem": { + "message": "Kayıt düzenlendi" + }, + "deleteItem": { + "message": "Kaydı sil" + }, + "deleteFolder": { + "message": "Klasörü sil" + }, + "deleteAttachment": { + "message": "Eki sil" + }, + "deleteItemConfirmation": { + "message": "Çöp kutusuna göndermek istediğinizden emin misiniz?" + }, + "deletedItem": { + "message": "Kayıt çöp kutusuna gönderildi" + }, + "overwritePasswordConfirmation": { + "message": "Mevcut parolanın üzerine kaydetmek istediğinize emin misiniz?" + }, + "overwriteUsername": { + "message": "Kullanıcı adının üzerine yaz" + }, + "overwriteUsernameConfirmation": { + "message": "Kullanıcı adının üzerine kaydetmek istediğinizden emin misiniz?" + }, + "noneFolder": { + "message": "Klasör yok", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Klasör ekle" + }, + "editFolder": { + "message": "Klasörü düzenle" + }, + "regeneratePassword": { + "message": "Yeni parola oluştur" + }, + "copyPassword": { + "message": "Parolayı kopyala" + }, + "copyUri": { + "message": "URI'yi kopyala" + }, + "copyVerificationCodeTotp": { + "message": "Doğrulama kodunu kopyala (TOTP)" + }, + "length": { + "message": "Uzunluk" + }, + "numWords": { + "message": "Kelime sayısı" + }, + "wordSeparator": { + "message": "Kelime ayracı" + }, + "capitalize": { + "message": "Baş harfleri büyük yap", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Rakam ekle" + }, + "close": { + "message": "Kapat" + }, + "minNumbers": { + "message": "En az rakam" + }, + "minSpecial": { + "message": "En az özel karakter", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Okurken karışabilecek karakterleri kullanma" + }, + "searchCollection": { + "message": "Koleksiyonda ara" + }, + "searchFolder": { + "message": "Klasörde ara" + }, + "searchFavorites": { + "message": "Favorilerde ara" + }, + "searchType": { + "message": "Arama türü", + "description": "Search item type" + }, + "newAttachment": { + "message": "Yeni dosya ekle" + }, + "deletedAttachment": { + "message": "Ek silindi" + }, + "deleteAttachmentConfirmation": { + "message": "Bu eki silmek istediğinize emin misiniz?" + }, + "attachmentSaved": { + "message": "Ekiniz kaydedildi." + }, + "file": { + "message": "Dosya" + }, + "selectFile": { + "message": "Bir dosya seç." + }, + "maxFileSize": { + "message": "Maksimum dosya boyutu 500 MB'dir." + }, + "updateKey": { + "message": "Şifreleme anahtarınızı güncelleştirene kadar bu özelliği kullanamazsınız." + }, + "editedFolder": { + "message": "Klasör Düzenlendi" + }, + "addedFolder": { + "message": "Klasör eklendi" + }, + "deleteFolderConfirmation": { + "message": "Bu klasörü silmek istediğinize emin misiniz?" + }, + "deletedFolder": { + "message": "Klasör silindi" + }, + "loginOrCreateNewAccount": { + "message": "Güvenli kasanıza ulaşmak için giriş yapın veya yeni bir hesap oluşturun." + }, + "createAccount": { + "message": "Hesap Oluştur" + }, + "logIn": { + "message": "Giriş Yap" + }, + "submit": { + "message": "Gönder" + }, + "masterPass": { + "message": "Ana Parola" + }, + "masterPassDesc": { + "message": "Ana parola, kasanıza ulaşmak için kullanacağınız paroladır. Ana parolanızı unutmamanız çok önemlidir. Ana parolanızı unutmanız durumunda parolanızı geri getirecek herhangi bir yol bulunmuyor." + }, + "masterPassHintDesc": { + "message": "Bir ana parola ipucu, unutmanız durumunda parolanızı hatırlamanıza yardımcı olabilir." + }, + "reTypeMasterPass": { + "message": "Ana parolayı tekrar yazın" + }, + "masterPassHint": { + "message": "Ana Parola İpucu (isteğe bağlı)" + }, + "settings": { + "message": "Ayarlar" + }, + "passwordHint": { + "message": "Parola İpucu" + }, + "enterEmailToGetHint": { + "message": "Ana parola ipucunu almak için hesabınızın e-posta adresini girin." + }, + "getMasterPasswordHint": { + "message": "Ana parola ipucunu al" + }, + "emailRequired": { + "message": "E-posta adresi gereklidir." + }, + "invalidEmail": { + "message": "Geçersiz e-posta adresi." + }, + "masterPassRequired": { + "message": "Ana parola gereklidir." + }, + "masterPassLength": { + "message": "Ana parola en az 8 karakter uzunluğunda olmalıdır." + }, + "masterPassDoesntMatch": { + "message": "Parola ve parola onayı eşleşmiyor." + }, + "newAccountCreated": { + "message": "Yeni hesabınız oluşturuldu! Şimdi giriş yapabilirsiniz." + }, + "masterPassSent": { + "message": "Size ana parolanızın ipucunu içeren bir e-posta gönderdik." + }, + "unexpectedError": { + "message": "Beklenmedik bir hata oluştu." + }, + "itemInformation": { + "message": "Kayıt bilgileri" + }, + "noItemsInList": { + "message": "Görüntülenecek kayıt yok." + }, + "sendVerificationCode": { + "message": "E-posta adresime doğrulama kodu gönder" + }, + "sendCode": { + "message": "Kod gönder" + }, + "codeSent": { + "message": "Kod gönderildi" + }, + "verificationCode": { + "message": "Doğrulama Kodu" + }, + "confirmIdentity": { + "message": "Devam etmek için kimliğinizi doğrulayın." + }, + "verificationCodeRequired": { + "message": "Doğrulama kodu gereklidir." + }, + "invalidVerificationCode": { + "message": "Geçersiz doğrulama kodu" + }, + "continue": { + "message": "Devam Et" + }, + "enterVerificationCodeApp": { + "message": "Kimlik doğrulayıcı uygulamanızdaki 6 haneli doğrulama kodunu girin." + }, + "enterVerificationCodeEmail": { + "message": "$EMAIL$ adresine e-postalanan 6 haneli doğrulama kodunu girin.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Doğrulama e-postası $EMAIL$ 'e gönderildi.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Beni hatırla" + }, + "sendVerificationCodeEmailAgain": { + "message": "Doğrulama kodunu yeniden e-postala" + }, + "useAnotherTwoStepMethod": { + "message": "Başka bir iki aşamalı giriş yöntemini kullan" + }, + "insertYubiKey": { + "message": "YubiKey'i bilgisayarınızın USB portuna takın, ardından düğmesine dokunun." + }, + "insertU2f": { + "message": "Güvenlik anahtarınızı bilgisayarınızın USB portuna takın. Bir düğmesi varsa dokunun." + }, + "recoveryCodeDesc": { + "message": "İki aşamalı doğrulama sağlayıcılarınıza ulaşamıyor musunuz? Kurtarma kodunuzu kullanarak hesabınızdaki tüm iki aşamalı giriş sağlayıcılarını devre dışı bırakabilirsiniz." + }, + "recoveryCodeTitle": { + "message": "Kurtarma kodu" + }, + "authenticatorAppTitle": { + "message": "Kimlik doğrulayıcı uygulama" + }, + "authenticatorAppDesc": { + "message": "Zamana dayalı doğrulama kodları oluşturmak için bir kimlik doğrulayıcı uygulaması (Authy veya Google Authenticator gibi) kullanın.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP Güvenlik Anahtarı" + }, + "yubiKeyDesc": { + "message": "Hesabınıza erişmek için bir YubiKey kullanın. YubiKey 4, 4 Nano, 4C ve NEO cihazlarıyla çalışır." + }, + "duoDesc": { + "message": "Duo Security ile doğrulama için Duo Mobile uygulaması, SMS, telefon görüşmesi veya U2F güvenlik anahtarını kullanın.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Kuruluşunuzun Duo Security doğrulaması için Duo Mobile uygulaması, SMS, telefon görüşmesi veya U2F güvenlik anahtarını kullanın.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Hesabınıza erişmek için WebAuthn uyumlu bir güvenlik anahtarı kullanın." + }, + "emailTitle": { + "message": "E-posta" + }, + "emailDesc": { + "message": "Doğrulama kodu size e-postalanacak." + }, + "loginUnavailable": { + "message": "Giriş yapılamıyor" + }, + "noTwoStepProviders": { + "message": "Bu hesapta iki aşamalı giriş etkin ama yapılandırdığınız iki aşamalı giriş sağlayıcılarının hiçbiri bu cihazı desteklemiyor." + }, + "noTwoStepProviders2": { + "message": "Lütfen daha iyi aygıtları (örneğin, bir kimlik doğrulayıcı app) arasında desteklenen ek sağlayıcıları ekleyin." + }, + "twoStepOptions": { + "message": "İki aşamalı giriş seçenekleri" + }, + "selfHostedEnvironment": { + "message": "Şirket içinde barındırılan ortam" + }, + "selfHostedEnvironmentFooter": { + "message": "Kurum içi barındırılan Bitwarden kurulumunuzun taban URL'sini belirtin." + }, + "customEnvironment": { + "message": "Özel ortam" + }, + "customEnvironmentFooter": { + "message": "Üst düzey kullanıcılar için. Her servisin taban URL'sini bağımsız olarak belirleyebilirsiniz." + }, + "baseUrl": { + "message": "Sunucu URL'si" + }, + "apiUrl": { + "message": "API Sunucu URL'si" + }, + "webVaultUrl": { + "message": "Web Kasası Sunucu URL'si" + }, + "identityUrl": { + "message": "Kimlik Sunucu URL'si" + }, + "notificationsUrl": { + "message": "Bildirim Sunucusu URL'si" + }, + "iconsUrl": { + "message": "Simge sunucusu URL'si" + }, + "environmentSaved": { + "message": "Çevre URL'ler kaydedildi." + }, + "ok": { + "message": "Tamam" + }, + "yes": { + "message": "Evet" + }, + "no": { + "message": "Hayır" + }, + "overwritePassword": { + "message": "Parolanın üzerine yaz" + }, + "learnMore": { + "message": "Daha fazla bilgi al" + }, + "featureUnavailable": { + "message": "Özellik mevcut değil" + }, + "loggedOut": { + "message": "Çıkış yapıldı" + }, + "loginExpired": { + "message": "Oturumunuzun süresi doldu." + }, + "logOutConfirmation": { + "message": "Çıkmak istediğinize emin misiniz?" + }, + "logOut": { + "message": "Çıkış yap" + }, + "addNewLogin": { + "message": "Yeni hesap ekle" + }, + "addNewItem": { + "message": "Yeni kayıt ekle" + }, + "addNewFolder": { + "message": "Yeni klasör ekle" + }, + "view": { + "message": "Görüntüle" + }, + "account": { + "message": "Hesap" + }, + "loading": { + "message": "Yükleniyor..." + }, + "lockVault": { + "message": "Kasayı kilitle" + }, + "passwordGenerator": { + "message": "Parola oluşturucu" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Hata bildirin" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Bizi takip edin" + }, + "syncVault": { + "message": "Kasayı eşitle" + }, + "changeMasterPass": { + "message": "Ana parolayı değiştir" + }, + "changeMasterPasswordConfirmation": { + "message": "Ana parolanızı bitwarden.com web kasası üzerinden değiştirebilirsiniz. Siteyi şimdi ziyaret etmek ister misiniz?" + }, + "fingerprintPhrase": { + "message": "Parmak izi ifadesi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Hesabınızın parmak izi ifadesi", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Web kasasına git" + }, + "getMobileApp": { + "message": "Mobil uygulamayı indir" + }, + "getBrowserExtension": { + "message": "Tarayıcı uzantısını indir" + }, + "syncingComplete": { + "message": "Eşitleme tamamlandı" + }, + "syncingFailed": { + "message": "Eşitleme başarısız oldu" + }, + "yourVaultIsLocked": { + "message": "Kasanız kilitli. Devam etmek için kimliğinizi doğrulayın." + }, + "unlock": { + "message": "Kilidi aç" + }, + "loggedInAsOn": { + "message": "$HOSTNAME$ üzerinde $EMAIL$ adresiyle oturum açtınız.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Geçersiz ana parola" + }, + "twoStepLoginConfirmation": { + "message": "İki aşamalı giriş, hesabınıza girererken işlemi bir güvenlik anahtarı, şifrematik uygulaması, SMS, telefon araması veya e-posta gibi ek bir yöntemle doğrulamanızı isteyerek hesabınızın güvenliğini artırır. İki aşamalı giriş özelliğini bitwarden.com web kasası üzerinden etkinleştirebilirsiniz. Şimdi siteye gitmek ister misiniz?" + }, + "twoStepLogin": { + "message": "İki aşamalı giriş" + }, + "vaultTimeout": { + "message": "Kasa zaman aşımı" + }, + "vaultTimeoutDesc": { + "message": "Kasanızın zaman aşımına uğrayacağı ve seçilen işlemi gerçekleştirmede seçin." + }, + "immediately": { + "message": "Hemen" + }, + "tenSeconds": { + "message": "10 saniye" + }, + "twentySeconds": { + "message": "20 saniye" + }, + "thirtySeconds": { + "message": "30 saniye" + }, + "oneMinute": { + "message": "1 dakika" + }, + "twoMinutes": { + "message": "2 dakika" + }, + "fiveMinutes": { + "message": "5 dakika" + }, + "fifteenMinutes": { + "message": "15 dakika" + }, + "thirtyMinutes": { + "message": "30 dakika" + }, + "oneHour": { + "message": "1 saat" + }, + "fourHours": { + "message": "4 saat" + }, + "onIdle": { + "message": "Sistem boştayken" + }, + "onSleep": { + "message": "Sistem uyuyunca" + }, + "onLocked": { + "message": "Sistem kilitlenince" + }, + "onRestart": { + "message": "Yeniden başlatılınca" + }, + "never": { + "message": "Hiçbir zaman" + }, + "security": { + "message": "Güvenlik" + }, + "clearClipboard": { + "message": "Panoyu temizle", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Kopyalanan değerleri otomatik olarak panodan sil.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Site simgelerini devre dışı bırak" + }, + "disableFaviconDesc": { + "message": "Web sitesi simgeleri, kasanızdaki her kaydın yanında o siteyi tanımanıza yardımcı olan bir resim sunar." + }, + "enableMinToTray": { + "message": "Tepsi simgesine küçült" + }, + "enableMinToTrayDesc": { + "message": "Pencere küçültülünce sistem tepsisinde bir simge göster." + }, + "enableMinToMenuBar": { + "message": "Menü çubuğuna küçült" + }, + "enableMinToMenuBarDesc": { + "message": "Pencere küçültülünce menü çubuğunda bir simge göster." + }, + "enableCloseToTray": { + "message": "Tepsi simgesine kapat" + }, + "enableCloseToTrayDesc": { + "message": "Pencere kapatılınca sistem tepsisinde bir simge göster." + }, + "enableCloseToMenuBar": { + "message": "Menü çubuğuna kapat" + }, + "enableCloseToMenuBarDesc": { + "message": "Pencere kapatılınca menü çubuğunda bir simge göster." + }, + "enableTray": { + "message": "Tepsi simgesini etkinleştir" + }, + "enableTrayDesc": { + "message": "Sistem tepsisinde her zaman simge göster." + }, + "startToTray": { + "message": "Tepsi simgesi olarak başlat" + }, + "startToTrayDesc": { + "message": "Uygulama ilk çalıştırıldığında sadece sistem tepsisinde simge olarak görünsün." + }, + "startToMenuBar": { + "message": "Menü çubuğunda başlat" + }, + "startToMenuBarDesc": { + "message": "Uygulama ilk çalıştırıldığında sadece menü çubuğunda simge olarak görünsün." + }, + "openAtLogin": { + "message": "Oturum açıldığında otomatik başlat" + }, + "openAtLoginDesc": { + "message": "Oturum açılınca Bitwarden masaüstü uygulamasını otomatik olarak başlat." + }, + "alwaysShowDock": { + "message": "Dock'ta her zaman göster" + }, + "alwaysShowDockDesc": { + "message": "Menü çubuğuna küçültüldüğünde bile Bitwarden simgesini Dock'ta göster." + }, + "confirmTrayTitle": { + "message": "Tepsiyi kapatmayı onaylayın" + }, + "confirmTrayDesc": { + "message": "Bu ayarı kapatırsanız tepsiyle ilgili diğer ayarlar da kapanır." + }, + "language": { + "message": "Dil" + }, + "languageDesc": { + "message": "Uygulama dilini değiştirin. Yeniden başlatma gerekir." + }, + "theme": { + "message": "Tema" + }, + "themeDesc": { + "message": "Uygulamanın renk temasını değiştir." + }, + "dark": { + "message": "Koyu", + "description": "Dark color" + }, + "light": { + "message": "Açık", + "description": "Light color" + }, + "copy": { + "message": "Kopyala", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Güncellemeleri denetle" + }, + "version": { + "message": "Sürüm $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Güncellemek için yeniden başlat" + }, + "restartToUpdateDesc": { + "message": "$VERSION_NUM$ sürümü yüklenmeye hazır. Yüklemeyi tamamlamak için uygulamayı yeniden başlatmanız gerekir. Uygulamayı yeniden başlatmak ve güncellemeyi yapmak istiyor musunuz?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Güncelleme mevcut" + }, + "updateAvailableDesc": { + "message": "Bir güncelleme bulundu. Şimdi yüklemek istiyor musunuz?" + }, + "restart": { + "message": "Yeniden başlat" + }, + "later": { + "message": "Sonra" + }, + "noUpdatesAvailable": { + "message": "Şu anda yüklenebilecek bir güncelleme yok. Son sürümü kullanıyorsunuz." + }, + "updateError": { + "message": "Güncelleme Hatası" + }, + "unknown": { + "message": "Bilinmiyor" + }, + "copyUsername": { + "message": "Kullanıcı adını kopyala" + }, + "copyNumber": { + "message": "Numarayı kopyala", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Güvenlik kodunu kopyala", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Premium üyelik" + }, + "premiumManage": { + "message": "Üyeliğimi yönet" + }, + "premiumManageAlert": { + "message": "Üyeliğinizi bitwarden.com web kasası üzerinden yönetebilirsiniz. Web sitesini ziyaret etmek ister misiniz?" + }, + "premiumRefresh": { + "message": "Üyeliğimi yenile" + }, + "premiumNotCurrentMember": { + "message": "Şu anda premium üyesi değilsiniz." + }, + "premiumSignUpAndGet": { + "message": "Premium üye olarak sahip olacağınız avantajlar:" + }, + "premiumSignUpStorage": { + "message": "Dosya ekleri için 1 GB şifrelenmiş depolama." + }, + "premiumSignUpTwoStep": { + "message": "YubiKey, FIDO U2F ve Duo gibi iki aşamalı giriş seçenekleri." + }, + "premiumSignUpReports": { + "message": "Kasanızı güvende tutmak için parola hijyeni, hesap sağlığı ve veri ihlali raporları." + }, + "premiumSignUpTotp": { + "message": "Kasanızdaki hesaplar için TOTP doğrulama kodu (2FA) oluşturucu." + }, + "premiumSignUpSupport": { + "message": "Öncelikli müşteri desteği." + }, + "premiumSignUpFuture": { + "message": "Ve ileride duyuracağımız tüm premium özellikler. Daha fazlası yakında!" + }, + "premiumPurchase": { + "message": "Premium satın al" + }, + "premiumPurchaseAlert": { + "message": "Premium üyeliği bitwarden.com web kasası üzerinden satın alabilirsiniz. Şimdi siteye gitmek ister misiniz?" + }, + "premiumCurrentMember": { + "message": "Premium üyesiniz!" + }, + "premiumCurrentMemberThanks": { + "message": "Bitwarden'ı desteklediğiniz için teşekkür ederiz." + }, + "premiumPrice": { + "message": "Bunların hepsi sadece yılda $PRICE$!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Yenileme tamamlandı" + }, + "passwordHistory": { + "message": "Parola geçmişi" + }, + "clear": { + "message": "Temizle", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Listelenecek şifre yok." + }, + "undo": { + "message": "Geri al" + }, + "redo": { + "message": "Yinele" + }, + "cut": { + "message": "Kes", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Yapıştır", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Tümünü seç" + }, + "zoomIn": { + "message": "Yakınlaştır" + }, + "zoomOut": { + "message": "Uzaklaştır" + }, + "resetZoom": { + "message": "Yakınlaştırmayı sıfırla" + }, + "toggleFullScreen": { + "message": "Tam ekranı aç/kapat" + }, + "reload": { + "message": "Yenile" + }, + "toggleDevTools": { + "message": "Geliştirici araçlarını aç/kapat" + }, + "minimize": { + "message": "Küçült", + "description": "Minimize window" + }, + "zoom": { + "message": "Yakınlaştır" + }, + "bringAllToFront": { + "message": "Tümünü öne getir", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Bitwarden hakkında" + }, + "services": { + "message": "Hizmetler" + }, + "hideBitwarden": { + "message": "Bitwarden'ı gizle" + }, + "hideOthers": { + "message": "Diğerlerini gizle" + }, + "showAll": { + "message": "Tümünü göster" + }, + "quitBitwarden": { + "message": "Bitwarden'dan çık" + }, + "valueCopied": { + "message": "$VALUE$ kopyalandı", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Yardım" + }, + "window": { + "message": "Pencere" + }, + "checkPassword": { + "message": "Parolanız ele geçirilip geçirilmediğini kontrol edin." + }, + "passwordExposed": { + "message": "Bu parola, veri ihlallerinde $VALUE$ kere açığa çıkmış. Değiştirmenizi tavsiye ederiz.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Bilinen veri ihlallerinde bu parola bulunamadı. Güvenle kullanabilirsiniz." + }, + "baseDomain": { + "message": "Ana alan adı", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Alan adı", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Sunucu", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Tam" + }, + "startsWith": { + "message": "URI başlangıcı" + }, + "regEx": { + "message": "Düzenli ifade", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Eşleşme tespiti", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Varsayılan eşleşme tespiti", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Seçenekleri aç/kapat" + }, + "organization": { + "message": "Kuruluş", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Varsayılan" + }, + "exit": { + "message": "Çıkış" + }, + "showHide": { + "message": "Göster / gizle", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Tepsiye gizle" + }, + "alwaysOnTop": { + "message": "Her zaman üstte", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Güncelleme", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Parola güncelleme", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Kasayı dışa aktar" + }, + "fileFormat": { + "message": "Dosya biçimi" + }, + "warning": { + "message": "UYARI", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Kasayı dışa aktarmayı onaylayın" + }, + "exportWarningDesc": { + "message": "Dışa aktarılan dosyadaki verileriniz şifrelenmemiş olacak. Bu dosyayı güvensiz yöntemlerle (örn. e-posta) göndermemeli ve saklamamalısınız. İşiniz bittikten sonra dosyayı hemen silin." + }, + "encExportKeyWarningDesc": { + "message": "Dışa aktardığınız bu dosyadaki verileriniz, hesabınızın şifreleme anahtarıyla şifrelenir. Hesabınızın şifreleme anahtarını değiştirirseniz bu dosyanın şifresi çözülemez hale gelir, dolayısıyla dosyayı yeniden dışa aktarmanız gerekir." + }, + "encExportAccountWarningDesc": { + "message": "Hesap şifreleme anahtarları her Bitwarden kullanıcı hesabı için farklıdır. Dolayısıyla şifrelenmiş bir dışa aktarmayı başka bir hesapta içe aktaramazsınız." + }, + "noOrganizationsList": { + "message": "Herhangi bir kuruluşa dahil değilsiniz. Kuruluşlar, kayıtlarınızı diğer kullanıcılarla güvenli bir şekilde paylaşmanıza olanak verir." + }, + "noCollectionsInList": { + "message": "Listelenecek koleksiyon yok." + }, + "ownership": { + "message": "Sahip" + }, + "whoOwnsThisItem": { + "message": "Bu kaydın sahibi kim?" + }, + "strong": { + "message": "Güçlü", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "İyi", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Zayıf", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Zayıf ana parola" + }, + "weakMasterPasswordDesc": { + "message": "Seçtiğiniz ana parola zayıf. Bitwarden hesabınızı korumak için daha güçlü bir ana parola seçmenizi öneririz. Bu ana parolayı kullanmak istediğinizden emin misiniz?" + }, + "pin": { + "message": "PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Kilidi PIN koduyla aç" + }, + "setYourPinCode": { + "message": "Bitwarden'ı açarken kullanacağınız PIN kodunu belirleyin. Uygulamadan tamamen çıkış yaparsanız PIN ayarlarınız sıfırlanacaktır." + }, + "pinRequired": { + "message": "PIN kodu gereklidir." + }, + "invalidPin": { + "message": "Geçersiz PIN kodu." + }, + "unlockWithWindowsHello": { + "message": "Kilidi Windows Hello ile aç" + }, + "windowsHelloConsentMessage": { + "message": "Bitwarden için doğrulayın." + }, + "unlockWithTouchId": { + "message": "Kilidi Touch ID ile aç" + }, + "touchIdConsentMessage": { + "message": "kasanızın kilidini açma" + }, + "noAutoPromptWindowsHello": { + "message": "Açılışta Windows Hello doğrulaması isteme." + }, + "noAutoPromptTouchId": { + "message": "Açılışta Touch ID doğrulaması isteme." + }, + "lockWithMasterPassOnRestart": { + "message": "Yeniden başlatmada ana şifre ile kilitle" + }, + "preferences": { + "message": "Tercihler" + }, + "enableMenuBar": { + "message": "Menü çubuğu simgesini etkinleştir" + }, + "enableMenuBarDesc": { + "message": "Menü çubuğunda her zaman bir simge göster." + }, + "hideToMenuBar": { + "message": "Menü çubuğuna gizle" + }, + "selectOneCollection": { + "message": "En az bir koleksiyon seçmelisiniz." + }, + "premiumUpdated": { + "message": "Premium'a yükseltildiniz." + }, + "restore": { + "message": "Geri yükle" + }, + "premiumManageAlertAppStore": { + "message": "Aboneliğinizi App Store'dan yönetebilirsiniz. App Store'u şimdi ziyaret etmek ister misiniz?" + }, + "legal": { + "message": "Hukuki Bilgiler", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Hizmet Koşulları" + }, + "privacyPolicy": { + "message": "Gizlilik Politikası" + }, + "unsavedChangesConfirmation": { + "message": "Çıkmak istediğinize emin misiniz? Eğer şimdi çıkarsanız bilgileriniz kayıt edilmeyecektir." + }, + "unsavedChangesTitle": { + "message": "Kaydedilmemiş Değişiklikler" + }, + "clone": { + "message": "Klonla" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Bir ya da daha fazla kuruluş ilkesi oluşturucu ayarlarınızı etkiliyor." + }, + "vaultTimeoutAction": { + "message": "Kasa zaman aşımı eylemi" + }, + "vaultTimeoutActionLockDesc": { + "message": "Kilitli bir kasaya tekrar erişebilmeniz için ana şifrenizi tekrar girmeniz gerekir." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Çıkış yapılmış bir kasaya tekrardan erişmek için yeniden kimlik doğrulaması gerekir." + }, + "lock": { + "message": "Kilitle", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Çöp kutusu", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Çöp kutusunda ara" + }, + "permanentlyDeleteItem": { + "message": "Kaydı kalıcı olarak sil" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Bu ögeyi kalıcı olarak silmek istediğinizden emin misiniz?" + }, + "permanentlyDeletedItem": { + "message": "Kalıcı Olarak Silinmiş Öge" + }, + "restoreItem": { + "message": "Kaydı geri yükle" + }, + "restoreItemConfirmation": { + "message": "Bu ögeyi geri yüklemek istediğinizden emin misiniz?" + }, + "restoredItem": { + "message": "Kayıt geri yüklendi" + }, + "permanentlyDelete": { + "message": "Kalıcı olarak sil" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Oturumu kapatmak kasanıza olan tüm erişiminizi kaldırır ve zaman aşımından sonra çevrimiçi kimlik doğrulaması gerektirir. Bu ayarı kullanmak istediğinizden emin misiniz?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Zaman Aşımı Eylem Onayı" + }, + "enterpriseSingleSignOn": { + "message": "Kurumsal tek oturum açma" + }, + "setMasterPassword": { + "message": "Ana parolayı belirle" + }, + "ssoCompleteRegistration": { + "message": "SSO ile girişinizi tamamlamak için lütfen kasanıza erişirken kullanacağınız ana parolayı belirleyin." + }, + "newMasterPass": { + "message": "Yeni ana parola" + }, + "confirmNewMasterPass": { + "message": "Yeni ana parolayı onaylayın" + }, + "masterPasswordPolicyInEffect": { + "message": "Bir veya daha fazla kuruluş ilkesi gereğince ana parolanız aşağıdaki gereksinimleri karşılamalıdır:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum karmaşıklık puanı: $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum uzunluk: $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Bir veya daha fazla büyük harf içermeli" + }, + "policyInEffectLowercase": { + "message": "Bir veya daha fazla küçük harf içermeli" + }, + "policyInEffectNumbers": { + "message": "Bir veya daha fazla rakam içermeli" + }, + "policyInEffectSpecial": { + "message": "Şu özel karakterlerden birini veya daha fazlasını içermeli: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Yeni ana parolanız ilke gereksinimlerini karşılamıyor." + }, + "acceptPolicies": { + "message": "Bu kutuyu işaretleyerek aşağıdakileri kabul etmiş olursunuz:" + }, + "acceptPoliciesError": { + "message": "Hizmet Koşulları ve Gizlilik Politikası kabul edilmemiş." + }, + "enableBrowserIntegration": { + "message": "Tarayıcı entegrasyonunu etkinleştir" + }, + "enableBrowserIntegrationDesc": { + "message": "Tarayıcı entegrasyonu tarayıcıda biyometrik doğrulama için kullanılır." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Tarayıcı entegrasyonu desteklenmiyor" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Ne yazık ki tarayıcı entegrasyonu şu anda sadece Mac App Store sürümünde destekleniyor." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Tarayıcı entegrasyonu desteklenmiyor" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Maalesef tarayıcı entegrasyonu şimdilik Windows Store sürümünde desteklenmiyor." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Tarayıcı entegrasyonu için doğrulamayı zorunlu kıl" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Masaüstü uygulamanızla ve tarayıcınız arasında bağlantı kurulurken parmak izi ifadesi doğrulamasını zorunlu kılarak ek bir güvenlik önlemi alabilirsiniz. Bu ayar açıldıktan sonra her bağlantı kurulduğunda tekrar doğrulama yapmanız gerekir." + }, + "approve": { + "message": "Onayla" + }, + "verifyBrowserTitle": { + "message": "Tarayıcı bağlantısını doğrula" + }, + "verifyBrowserDesc": { + "message": "Lütfen gösterilen parmak izinin tarayıcı eklentisinde gösterilen parmak iziyle aynı olduğundan emin olun." + }, + "biometricsNotEnabledTitle": { + "message": "Biyometri etkin değil" + }, + "biometricsNotEnabledDesc": { + "message": "Tarayıcıda biyometriyi kullanmak için önce ayarlardan masaüstü biyometrisini etkinleştirilmeniz gerekir." + }, + "personalOwnershipSubmitError": { + "message": "Bir kuruluş ilkesi nedeniyle kişisel kasanıza hesap kaydetmeniz kısıtlanmış. Sahip seçeneğini bir kuruluş olarak değiştirin ve mevcut koleksiyonlar arasından seçim yapın." + }, + "hintEqualsPassword": { + "message": "Parola ipucunuz parolanızla aynı olamaz." + }, + "personalOwnershipPolicyInEffect": { + "message": "Bir kuruluş ilkesi sahiplik seçeneklerinizi etkiliyor." + }, + "allSends": { + "message": "Tüm Send'ler", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Dosya" + }, + "sendTypeText": { + "message": "Metin" + }, + "searchSends": { + "message": "Send'lerde ara", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Send'i düzenle", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Kasam" + }, + "text": { + "message": "Metin" + }, + "deletionDate": { + "message": "Silinme tarihi" + }, + "deletionDateDesc": { + "message": "Bu Send belirtilen tarih ve saatte kalıcı olacak silinecek.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Son kullanma tarihi" + }, + "expirationDateDesc": { + "message": "Bunu ayarlarsanız belirtilen tarih ve saatten sonra bu Send'e erişilemeyecektir.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Maksimum erişim sayısı" + }, + "maxAccessCountDesc": { + "message": "Bunu ayarlarsanız maksimum erişim sayısına ulaşıldıktan sonra bu Send'e erişilemeyecektir.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Mevcut erişim sayısı" + }, + "disableSend": { + "message": "Kimsenin erişememesi için bu Send'i devre dışı bırak.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Kullanıcıların bu Send'e erişmek için parola girmelerini isteyebilirsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Bu Send ile ilgili özel notlar.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send bağlantısı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send bağlantısı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "Send'e erişirken varsayılan olarak metni gizle", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send oluşturuldu", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send düzenlendi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send silindi", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Yeni parola" + }, + "whatTypeOfSend": { + "message": "Bu ne tür bir Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Send oluştur", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Göndermek istediğiniz metin." + }, + "sendFileDesc": { + "message": "Göndermek istediğiniz dosya." + }, + "days": { + "message": "$DAYS$ gün", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 gün" + }, + "custom": { + "message": "Özel" + }, + "deleteSendConfirmation": { + "message": "Bu Send'i silmek istediğinizden emin misiniz?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Send linkini panoya kopyala", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Kaydettikten sonra bu Send'i paylaşma linkini panoya kopyala." + }, + "sendDisabled": { + "message": "Send devre dışı", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Bir kuruluş ilkesi nedeniyle yalnızca mevcut Send'leri silebilirsiniz.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Bağlantıyı kopyala" + }, + "disabled": { + "message": "Devre dışı" + }, + "maxAccessCountReached": { + "message": "Maksimum erişim sayısına ulaşıldı" + }, + "expired": { + "message": "Süresi doldu" + }, + "pendingDeletion": { + "message": "Silinmesi bekleniyor" + }, + "webAuthnAuthenticate": { + "message": "WebAuthn ile doğrula" + }, + "hideEmail": { + "message": "E-posta adresimi alıcılardan gizle." + }, + "sendOptionsPolicyInEffect": { + "message": "Bir veya daha fazla kuruluş ilkesi Send seçeneklerinizi etkiliyor." + }, + "emailVerificationRequired": { + "message": "E-posta doğrulaması gerekiyor" + }, + "emailVerificationRequiredDesc": { + "message": "Bu özelliği kullanmak için e-postanızı doğrulamalısınız." + }, + "passwordPrompt": { + "message": "Ana parolayı yeniden iste" + }, + "passwordConfirmation": { + "message": "Ana parola onayı" + }, + "passwordConfirmationDesc": { + "message": "Bu işleme devam etmek için lütfen ana parolanızı yeniden girin." + }, + "updatedMasterPassword": { + "message": "Ana parola güncellendi" + }, + "updateMasterPassword": { + "message": "Ana parolayı güncelle" + }, + "updateMasterPasswordWarning": { + "message": "Ana parolanız kuruluşunuzdaki bir yönetici tarafından yakın zamanda değiştirildi. Kasanıza erişmek için parolanızı güncellemelisiniz. Devam ettiğinizde oturumunuz kapanacak ve yeniden oturum açmanız gerekecektir. Diğer cihazlardaki aktif oturumlar bir saate kadar aktif kalabilir." + }, + "hours": { + "message": "Saat" + }, + "minutes": { + "message": "Dakika" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Kuruluş ilkeleriniz kasa zaman aşımınızı etkiliyor. İzin verilen maksimum kasa zaman aşımı $HOURS$ saat $MINUTES$ dakikadır", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Kasa zaman aşımınız, kuruluşunuz tarafından belirlenen kısıtlamaları aşıyor." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Otomatik eklenme" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Bu kuruluşun sizi otomatik olarak parola sıfırlamaya ekleyen bir ilkesi bulunmakta. Bu ilkeye eklenmek, kuruluş yöneticilerinin ana parolanızı değiştirebilmesini sağlar." + }, + "vaultExportDisabled": { + "message": "Kasayı dışa aktarma devre dışı" + }, + "personalVaultExportPolicyInEffect": { + "message": "Bir veya daha fazla kuruluş ilkesi, kişisel kasanızı dışa aktarmanızı engelliyor." + }, + "addAccount": { + "message": "Hesap ekle" + }, + "removeMasterPassword": { + "message": "Ana parolayı kaldır" + }, + "removedMasterPassword": { + "message": "Ana parola kaldırıldı." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ kendi barındırdığı bir anahtar sunucusuyla SSO kullanıyor. Bu kuruluşun üyelerinin artık ana parola kullanması gerekmiyor.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Kuruluştan ayrıl" + }, + "leaveOrganizationConfirmation": { + "message": "Bu kuruluştan ayrılmak istediğinizden emin misiniz?" + }, + "leftOrganization": { + "message": "Kuruluştan ayrıldınız." + }, + "ssoKeyConnectorUnavailable": { + "message": "Anahtar bağlayıcısına ulaşılamıyor, daha sonra yeniden deneyin." + }, + "lockAllVaults": { + "message": "Tüm kasaları kilitle" + }, + "accountLimitReached": { + "message": "Aynı anda 5'ten fazla hesapla oturum açamazsınız." + }, + "accountPreferences": { + "message": "Tercihler" + }, + "appPreferences": { + "message": "Uygulama ayarları (tüm hesaplar)" + }, + "accountSwitcherLimitReached": { + "message": "Hesap sınırına ulaştınız. Yeni hesap eklemek için hesaplardan birinden çıkış yapın." + }, + "settingsTitle": { + "message": "$EMAIL$ uygulama ayarları", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Hesabı değiştir" + }, + "options": { + "message": "Seçenekler" + }, + "sessionTimeout": { + "message": "Oturumunuzun süresi doldu. Lütfen geri dönüp yeniden giriş yapın." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Oluşturucu" + }, + "whatWouldYouLikeToGenerate": { + "message": "Ne oluşturmak istersiniz?" + }, + "passwordType": { + "message": "Parola türü" + }, + "regenerateUsername": { + "message": "Kullanıcı adını yeniden oluştur" + }, + "generateUsername": { + "message": "Kullanıcı adı oluştur" + }, + "usernameType": { + "message": "Kullanıcı adı türü" + }, + "plusAddressedEmail": { + "message": "Artı adresli e-posta" + }, + "plusAddressedEmailDesc": { + "message": "E-posta sağlayıcınızın alt adres özelliklerini kullanın." + }, + "catchallEmail": { + "message": "Catch-all e-posta" + }, + "catchallEmailDesc": { + "message": "Alan adınızın tüm iletileri yakalamaya ayarlanmış adresini kullanın." + }, + "random": { + "message": "Rasgele" + }, + "randomWord": { + "message": "Rastgele kelime" + }, + "websiteName": { + "message": "Web sitesi adı" + }, + "service": { + "message": "Servis" + } +} diff --git a/apps/desktop/src/locales/uk/messages.json b/apps/desktop/src/locales/uk/messages.json new file mode 100644 index 0000000000..ef7c1c8809 --- /dev/null +++ b/apps/desktop/src/locales/uk/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Фільтри" + }, + "allItems": { + "message": "Всі елементи" + }, + "favorites": { + "message": "Обране" + }, + "types": { + "message": "Типи" + }, + "typeLogin": { + "message": "Вхід" + }, + "typeCard": { + "message": "Картка" + }, + "typeIdentity": { + "message": "Особисті дані" + }, + "typeSecureNote": { + "message": "Захищена нотатка" + }, + "folders": { + "message": "Теки" + }, + "collections": { + "message": "Збірки" + }, + "searchVault": { + "message": "Пошук" + }, + "addItem": { + "message": "Додати запис" + }, + "shared": { + "message": "Спільні" + }, + "share": { + "message": "Поділитися" + }, + "moveToOrganization": { + "message": "Перемістити до організації" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ переміщено до $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Виберіть організацію, до якої ви бажаєте перемістити цей запис. При переміщенні до організації власність запису передається тій організації. Ви більше не будете єдиним власником цього запису після переміщення." + }, + "attachments": { + "message": "Вкладення" + }, + "viewItem": { + "message": "Переглянути запис" + }, + "name": { + "message": "Назва" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "Новий URI" + }, + "username": { + "message": "Ім'я користувача" + }, + "password": { + "message": "Пароль" + }, + "passphrase": { + "message": "Парольна фраза" + }, + "editItem": { + "message": "Змінити запис" + }, + "emailAddress": { + "message": "Адреса е-пошти" + }, + "verificationCodeTotp": { + "message": "Код підтвердження (TOTP)" + }, + "website": { + "message": "Вебсайт" + }, + "notes": { + "message": "Нотатки" + }, + "customFields": { + "message": "Власні поля" + }, + "launch": { + "message": "Перейти" + }, + "copyValue": { + "message": "Копіювати значення", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Згортати при копіюванні в буфер обміну" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Згортати при копіюванні даних запису в буфер обміну." + }, + "toggleVisibility": { + "message": "Перемкнути видимість" + }, + "toggleCollapse": { + "message": "Згорнути/розгорнути", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Ім'я власника картки" + }, + "number": { + "message": "Номер" + }, + "brand": { + "message": "Тип картки" + }, + "expiration": { + "message": "Термін дії" + }, + "securityCode": { + "message": "Код безпеки" + }, + "identityName": { + "message": "Ім'я" + }, + "company": { + "message": "Компанія" + }, + "ssn": { + "message": "Номер соціального страхування" + }, + "passportNumber": { + "message": "Номер паспорта" + }, + "licenseNumber": { + "message": "Номер ліцензії" + }, + "email": { + "message": "Е-пошта" + }, + "phone": { + "message": "Телефон" + }, + "address": { + "message": "Адреса" + }, + "premiumRequired": { + "message": "Необхідний преміум статус" + }, + "premiumRequiredDesc": { + "message": "Для використання цієї функції необхідний преміум статус." + }, + "errorOccurred": { + "message": "Сталася помилка." + }, + "error": { + "message": "Помилка" + }, + "january": { + "message": "Січень" + }, + "february": { + "message": "Лютий" + }, + "march": { + "message": "Березень" + }, + "april": { + "message": "Квітень" + }, + "may": { + "message": "Травень" + }, + "june": { + "message": "Червень" + }, + "july": { + "message": "Липень" + }, + "august": { + "message": "Серпень" + }, + "september": { + "message": "Вересень" + }, + "october": { + "message": "Жовтень" + }, + "november": { + "message": "Листопад" + }, + "december": { + "message": "Грудень" + }, + "ex": { + "message": "зразок", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Звернення" + }, + "mr": { + "message": "Містер" + }, + "mrs": { + "message": "Місіс" + }, + "ms": { + "message": "Міс" + }, + "dr": { + "message": "Доктор" + }, + "expirationMonth": { + "message": "Місяць завершення" + }, + "expirationYear": { + "message": "Рік завершення" + }, + "select": { + "message": "Обрати" + }, + "other": { + "message": "Інше" + }, + "generatePassword": { + "message": "Генерувати пароль" + }, + "type": { + "message": "Тип" + }, + "firstName": { + "message": "Ім’я" + }, + "middleName": { + "message": "По батькові" + }, + "lastName": { + "message": "Прізвище" + }, + "fullName": { + "message": "Повне ім'я" + }, + "address1": { + "message": "Адреса 1" + }, + "address2": { + "message": "Адреса 2" + }, + "address3": { + "message": "Адреса 3" + }, + "cityTown": { + "message": "Місто / Селище" + }, + "stateProvince": { + "message": "Штат / Область" + }, + "zipPostalCode": { + "message": "Поштовий індекс" + }, + "country": { + "message": "Країна" + }, + "save": { + "message": "Зберегти" + }, + "cancel": { + "message": "Скасувати" + }, + "delete": { + "message": "Видалити" + }, + "favorite": { + "message": "Обране" + }, + "edit": { + "message": "Змінити" + }, + "authenticatorKeyTotp": { + "message": "Ключ авторизації (TOTP)" + }, + "folder": { + "message": "Тека" + }, + "newCustomField": { + "message": "Нове власне поле" + }, + "value": { + "message": "Значення" + }, + "dragToSort": { + "message": "Перетягніть, щоб відсортувати" + }, + "cfTypeText": { + "message": "Текст" + }, + "cfTypeHidden": { + "message": "Приховано" + }, + "cfTypeBoolean": { + "message": "Логічне значення" + }, + "cfTypeLinked": { + "message": "Пов'язано", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Пов'язане значення", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Видалити" + }, + "nameRequired": { + "message": "Потрібна назва." + }, + "addedItem": { + "message": "Запис додано" + }, + "editedItem": { + "message": "Запис змінено" + }, + "deleteItem": { + "message": "Видалити запис" + }, + "deleteFolder": { + "message": "Видалити теку" + }, + "deleteAttachment": { + "message": "Видалити файл" + }, + "deleteItemConfirmation": { + "message": "Ви дійсно хочете перенести до смітника?" + }, + "deletedItem": { + "message": "Запис перенесено до смітника" + }, + "overwritePasswordConfirmation": { + "message": "Ви дійсно хочете перезаписати поточний пароль?" + }, + "overwriteUsername": { + "message": "Перезаписати ім'я користувача" + }, + "overwriteUsernameConfirmation": { + "message": "Ви дійсно бажаєте перезаписати поточне ім'я користувача?" + }, + "noneFolder": { + "message": "Без теки", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Додати теку" + }, + "editFolder": { + "message": "Редагувати теку" + }, + "regeneratePassword": { + "message": "Генерувати новий" + }, + "copyPassword": { + "message": "Копіювати пароль" + }, + "copyUri": { + "message": "Копіювати URI" + }, + "copyVerificationCodeTotp": { + "message": "Копіювати код підтвердження (TOTP)" + }, + "length": { + "message": "Довжина" + }, + "numWords": { + "message": "Кількість слів" + }, + "wordSeparator": { + "message": "Розділювач слів" + }, + "capitalize": { + "message": "Великі літери", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Включити число" + }, + "close": { + "message": "Закрити" + }, + "minNumbers": { + "message": "Мінімум цифр" + }, + "minSpecial": { + "message": "Мінімум спеціальних символів", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Уникати неоднозначних символів" + }, + "searchCollection": { + "message": "Пошук в збірках" + }, + "searchFolder": { + "message": "Пошук в теці" + }, + "searchFavorites": { + "message": "Пошук в обраному" + }, + "searchType": { + "message": "Пошук за типом", + "description": "Search item type" + }, + "newAttachment": { + "message": "Додати нове вкладення" + }, + "deletedAttachment": { + "message": "Вкладення видалено" + }, + "deleteAttachmentConfirmation": { + "message": "Ви дійсно хочете видалити це вкладення?" + }, + "attachmentSaved": { + "message": "Вкладення збережено." + }, + "file": { + "message": "Файл" + }, + "selectFile": { + "message": "Оберіть файл." + }, + "maxFileSize": { + "message": "Максимальний розмір файлу 500 Мб." + }, + "updateKey": { + "message": "Ви не можете використовувати цю функцію доки не оновите свій ключ шифрування." + }, + "editedFolder": { + "message": "Тека відредагована" + }, + "addedFolder": { + "message": "Додано теку" + }, + "deleteFolderConfirmation": { + "message": "Ви дійсно хочете видалити цю теку?" + }, + "deletedFolder": { + "message": "Теку видалено" + }, + "loginOrCreateNewAccount": { + "message": "Для доступу до сховища увійдіть в обліковий запис, або створіть новий." + }, + "createAccount": { + "message": "Створити обліковий запис" + }, + "logIn": { + "message": "Увійти" + }, + "submit": { + "message": "Відправити" + }, + "masterPass": { + "message": "Головний пароль" + }, + "masterPassDesc": { + "message": "Головний пароль використовується для доступу до вашого сховища. Дуже важливо, щоб ви запам'ятали його. Якщо ви забудете головний пароль, його неможливо буде відновити." + }, + "masterPassHintDesc": { + "message": "Якщо ви забудете головний пароль, підказка може допомогти вам згадати його." + }, + "reTypeMasterPass": { + "message": "Введіть головний пароль ще раз" + }, + "masterPassHint": { + "message": "Підказка для головного пароля (необов'язково)" + }, + "settings": { + "message": "Налаштування" + }, + "passwordHint": { + "message": "Підказка для пароля" + }, + "enterEmailToGetHint": { + "message": "Введіть свою адресу е-пошти, щоб отримати підказку для головного пароля." + }, + "getMasterPasswordHint": { + "message": "Отримати підказку для головного пароля" + }, + "emailRequired": { + "message": "Необхідно вказати адресу е-пошти." + }, + "invalidEmail": { + "message": "Неправильна адреса е-пошти." + }, + "masterPassRequired": { + "message": "Потрібен головний пароль." + }, + "masterPassLength": { + "message": "Довжина головного пароля повинна бути не менше 8 символів." + }, + "masterPassDoesntMatch": { + "message": "Підтвердження головного пароля не збігається." + }, + "newAccountCreated": { + "message": "Ваш обліковий запис створений! Тепер ви можете увійти." + }, + "masterPassSent": { + "message": "Ми надіслали вам лист з підказкою для головного пароля." + }, + "unexpectedError": { + "message": "Сталася неочікувана помилка." + }, + "itemInformation": { + "message": "Інформація про запис" + }, + "noItemsInList": { + "message": "Немає записів." + }, + "sendVerificationCode": { + "message": "Надіслати код підтвердження е-поштою" + }, + "sendCode": { + "message": "Надіслати код" + }, + "codeSent": { + "message": "Код надіслано" + }, + "verificationCode": { + "message": "Код підтвердження" + }, + "confirmIdentity": { + "message": "Підтвердьте свої облікові дані для продовження." + }, + "verificationCodeRequired": { + "message": "Потрібний код підтвердження." + }, + "invalidVerificationCode": { + "message": "Недійсний код підтвердження" + }, + "continue": { + "message": "Продовжити" + }, + "enterVerificationCodeApp": { + "message": "Введіть 6-значний код підтвердження з програми авторизації." + }, + "enterVerificationCodeEmail": { + "message": "Введіть 6-значний код підтвердження, надісланий на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Код підтвердження надіслано на $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Запам'ятати мене" + }, + "sendVerificationCodeEmailAgain": { + "message": "Надіслати код підтвердження ще раз" + }, + "useAnotherTwoStepMethod": { + "message": "Інший спосіб двоетапної перевірки" + }, + "insertYubiKey": { + "message": "Вставте свій YubiKey в USB порт комп'ютера, потім торкніться цієї кнопки." + }, + "insertU2f": { + "message": "Вставте свій ключ безпеки в USB порт комп'ютера. Якщо в нього є кнопка, натисніть її." + }, + "recoveryCodeDesc": { + "message": "Втратили доступ до всіх провайдерів двоетапної перевірки? Скористайтеся кодом відновлення, щоб вимкнути двоетапну перевірку для свого облікового запису." + }, + "recoveryCodeTitle": { + "message": "Код відновлення" + }, + "authenticatorAppTitle": { + "message": "Програма авторизації" + }, + "authenticatorAppDesc": { + "message": "Використовуйте програму авторизації (наприклад, Authy або Google Authenticator), щоб генерувати тимчасові коди підтвердження.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Ключ безпеки YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Використовуйте YubiKey для доступу до сховища. Працює з YubiKey 4, 4 Nano, 4C та пристроями NEO." + }, + "duoDesc": { + "message": "Авторизуйтесь за допомогою Duo Security з використанням мобільного додатку Duo Mobile, SMS, телефонного виклику, або ключа безпеки U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Авторизуйтесь за допомогою Duo Security для вашої організації з використанням мобільного додатку Duo Mobile, SMS, телефонного виклику, або ключа безпеки U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Використовуйте будь-який ключ безпеки WebAuthn для доступу до сховища." + }, + "emailTitle": { + "message": "Е-пошта" + }, + "emailDesc": { + "message": "Коди підтвердження будуть надсилатися на вашу пошту." + }, + "loginUnavailable": { + "message": "Вхід недоступний" + }, + "noTwoStepProviders": { + "message": "Для цього облікового запису увімкнено двоетапну перевірку. Однак, жоден з налаштованих провайдерів двоетапної перевірки не підтримується цим пристроєм." + }, + "noTwoStepProviders2": { + "message": "Додайте інших провайдерів, які краще підтримуються різними пристроями, наприклад програма авторизації." + }, + "twoStepOptions": { + "message": "Налаштування двоетапної перевірки" + }, + "selfHostedEnvironment": { + "message": "Середовище власного хостингу" + }, + "selfHostedEnvironmentFooter": { + "message": "Вкажіть основну URL-адресу вашого локально розміщеного встановлення Bitwarden." + }, + "customEnvironment": { + "message": "Власне середовище" + }, + "customEnvironmentFooter": { + "message": "Для досвідчених користувачів. Ви можете вказати основну URL-адресу окремо для кожної служби." + }, + "baseUrl": { + "message": "URL-адреса сервера" + }, + "apiUrl": { + "message": "URL-адреса API" + }, + "webVaultUrl": { + "message": "URL-адреса сервера веб сховища" + }, + "identityUrl": { + "message": "URL-адреса сервера ідентифікації" + }, + "notificationsUrl": { + "message": "URL сервера сповіщень" + }, + "iconsUrl": { + "message": "URL-адреса сервера піктограм" + }, + "environmentSaved": { + "message": "URL-адреси середовища збережено." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Так" + }, + "no": { + "message": "Ні" + }, + "overwritePassword": { + "message": "Перезаписати пароль" + }, + "learnMore": { + "message": "Докладніше" + }, + "featureUnavailable": { + "message": "Функція недоступна" + }, + "loggedOut": { + "message": "Ви вийшли" + }, + "loginExpired": { + "message": "Тривалість вашого сеансу завершилась." + }, + "logOutConfirmation": { + "message": "Ви дійсно хочете вийти?" + }, + "logOut": { + "message": "Вийти" + }, + "addNewLogin": { + "message": "Додати новий запис" + }, + "addNewItem": { + "message": "Додати новий елемент" + }, + "addNewFolder": { + "message": "Додати нову теку" + }, + "view": { + "message": "Перегляд" + }, + "account": { + "message": "Обліковий запис" + }, + "loading": { + "message": "Завантаження..." + }, + "lockVault": { + "message": "Заблокувати сховище" + }, + "passwordGenerator": { + "message": "Генератор паролів" + }, + "contactUs": { + "message": "Зв'язатися з нами" + }, + "getHelp": { + "message": "Отримати допомогу" + }, + "fileBugReport": { + "message": "Повідомити про помилку" + }, + "blog": { + "message": "Блог" + }, + "followUs": { + "message": "Слідкуйте за нами" + }, + "syncVault": { + "message": "Синхронізувати сховище" + }, + "changeMasterPass": { + "message": "Змінити головний пароль" + }, + "changeMasterPasswordConfirmation": { + "message": "Ви можете змінити головний пароль в сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "fingerprintPhrase": { + "message": "Фраза відбитку", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Фраза відбитку вашого облікового запису", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Перейти у веб сховище" + }, + "getMobileApp": { + "message": "Отримати мобільний додаток" + }, + "getBrowserExtension": { + "message": "Отримати розширення браузера" + }, + "syncingComplete": { + "message": "Синхронізацію завершено" + }, + "syncingFailed": { + "message": "Не вдалося синхронізувати" + }, + "yourVaultIsLocked": { + "message": "Сховище заблоковано. Пройдіть ідентифікацію для продовження." + }, + "unlock": { + "message": "Розблокувати" + }, + "loggedInAsOn": { + "message": "Ви увійшли як $EMAIL$ на $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Неправильний головний пароль" + }, + "twoStepLoginConfirmation": { + "message": "Двоетапна перевірка робить ваш обліковий запис більш захищеним, вимагаючи підтвердження входу з використанням іншого пристрою, наприклад, за допомогою коду безпеки, програми авторизації, SMS, телефонного виклику, або е-пошти. Ви можете увімкнути двоетапну перевірку в сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "twoStepLogin": { + "message": "Двоетапна перевірка" + }, + "vaultTimeout": { + "message": "Час очікування сховища" + }, + "vaultTimeoutDesc": { + "message": "Оберіть дію, яка виконається після завершення часу очікування вашого сховища." + }, + "immediately": { + "message": "Негайно" + }, + "tenSeconds": { + "message": "10 секунд" + }, + "twentySeconds": { + "message": "20 секунд" + }, + "thirtySeconds": { + "message": "30 секунд" + }, + "oneMinute": { + "message": "1 хвилина" + }, + "twoMinutes": { + "message": "2 хвилини" + }, + "fiveMinutes": { + "message": "5 хвилин" + }, + "fifteenMinutes": { + "message": "15 хвилин" + }, + "thirtyMinutes": { + "message": "30 хвилин" + }, + "oneHour": { + "message": "1 година" + }, + "fourHours": { + "message": "4 години" + }, + "onIdle": { + "message": "При бездіяльності системи" + }, + "onSleep": { + "message": "При переході в режим сну" + }, + "onLocked": { + "message": "При блокуванні системи" + }, + "onRestart": { + "message": "При перезапуску" + }, + "never": { + "message": "Ніколи" + }, + "security": { + "message": "Безпека" + }, + "clearClipboard": { + "message": "Очистити буфер обміну", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Автоматично очищати скопійовані значення з буфера обміну.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Вимкнути піктограми вебсайтів" + }, + "disableFaviconDesc": { + "message": "Впізнавані піктограми вебсайтів додаються біля кожного запису вашого сховища." + }, + "enableMinToTray": { + "message": "Згортати до системного лотка" + }, + "enableMinToTrayDesc": { + "message": "Згортати вікно до системного лотка замість панелі інструментів." + }, + "enableMinToMenuBar": { + "message": "Згортати до панелі завдань" + }, + "enableMinToMenuBarDesc": { + "message": "При згортанні вікна, показувати піктограму в панелі завдань." + }, + "enableCloseToTray": { + "message": "Закривати до системного лотка" + }, + "enableCloseToTrayDesc": { + "message": "При закритті вікна згортати в системний лоток." + }, + "enableCloseToMenuBar": { + "message": "Закривати до панелі завдань" + }, + "enableCloseToMenuBarDesc": { + "message": "При закритті вікна, показувати піктограму в панелі завдань." + }, + "enableTray": { + "message": "Увімкнути піктограму в системному лотку" + }, + "enableTrayDesc": { + "message": "Завжди показувати піктограму в системному лотку." + }, + "startToTray": { + "message": "Запускати в згорнутому вигляді" + }, + "startToTrayDesc": { + "message": "При першому запуску програми відображатиметься лише піктограма в системному лотку." + }, + "startToMenuBar": { + "message": "Запускати в панелі завдань" + }, + "startToMenuBarDesc": { + "message": "При запуску програми показувати лише піктограму в панелі завдань." + }, + "openAtLogin": { + "message": "Запускати автоматично при вході" + }, + "openAtLoginDesc": { + "message": "Запускати програму Bitwarden для комп'ютера автоматично при вході в систему." + }, + "alwaysShowDock": { + "message": "Завжди показувати в панелі Dock" + }, + "alwaysShowDockDesc": { + "message": "Показувати піктограму Bitwarden в панелі Dock навіть при згортанні до панелі завдань." + }, + "confirmTrayTitle": { + "message": "Підтвердити вимкнення в панелі стану" + }, + "confirmTrayDesc": { + "message": "Вимкнення цього параметра також вимкне усі інші пов'язані налаштування." + }, + "language": { + "message": "Мова" + }, + "languageDesc": { + "message": "Змінити мову програми. Потрібен перезапуск." + }, + "theme": { + "message": "Тема" + }, + "themeDesc": { + "message": "Змінити колірну тему програми." + }, + "dark": { + "message": "Темна", + "description": "Dark color" + }, + "light": { + "message": "Світла", + "description": "Light color" + }, + "copy": { + "message": "Копіювати", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Перевірити оновлення" + }, + "version": { + "message": "Версія $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Перезапустити для оновлення" + }, + "restartToUpdateDesc": { + "message": "Версія $VERSION_NUM$ готова до встановлення. Для завершення встановлення ви повинні перезапустити програму. Хочете зробити це зараз?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Доступне оновлення" + }, + "updateAvailableDesc": { + "message": "Знайдено оновлення. Хочете завантажити його зараз?" + }, + "restart": { + "message": "Перезапустити" + }, + "later": { + "message": "Пізніше" + }, + "noUpdatesAvailable": { + "message": "Оновлення наразі відсутні. Ви використовуєте найновішу версію." + }, + "updateError": { + "message": "Помилка оновлення" + }, + "unknown": { + "message": "Невідомо" + }, + "copyUsername": { + "message": "Копіювати ім'я користувача" + }, + "copyNumber": { + "message": "Копіювати номер", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Копіювати код безпеки", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Преміум статус" + }, + "premiumManage": { + "message": "Керувати статусом" + }, + "premiumManageAlert": { + "message": "Ви можете керувати своїм статусом у сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "premiumRefresh": { + "message": "Оновити статус" + }, + "premiumNotCurrentMember": { + "message": "Зараз у вас немає преміум-статусу." + }, + "premiumSignUpAndGet": { + "message": "Підпишіться на преміум-статус і отримайте:" + }, + "premiumSignUpStorage": { + "message": "1 ГБ зашифрованого сховища для файлів." + }, + "premiumSignUpTwoStep": { + "message": "Додаткові можливості двоетапної перевірки, наприклад, YubiKey, FIDO U2F та Duo." + }, + "premiumSignUpReports": { + "message": "Гігієна паролів, здоров'я облікового запису, а також звіти про вразливості даних, щоб зберігати ваше сховище в безпеці." + }, + "premiumSignUpTotp": { + "message": "Генератор коду авторизації TOTP (2FA) для входу в сховище." + }, + "premiumSignUpSupport": { + "message": "Пріоритетну технічну підтримку." + }, + "premiumSignUpFuture": { + "message": "Всі майбутні функції преміум статусу. Їх буде більше!" + }, + "premiumPurchase": { + "message": "Придбати преміум" + }, + "premiumPurchaseAlert": { + "message": "Ви можете придбати преміум статус у сховищі на bitwarden.com. Хочете перейти на вебсайт зараз?" + }, + "premiumCurrentMember": { + "message": "У вас преміум статус!" + }, + "premiumCurrentMemberThanks": { + "message": "Дякуємо за підтримку Bitwarden." + }, + "premiumPrice": { + "message": "Всього лише $PRICE$ / за рік!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Оновлення завершено" + }, + "passwordHistory": { + "message": "Історія паролів" + }, + "clear": { + "message": "Стерти", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Немає паролів." + }, + "undo": { + "message": "Повернути" + }, + "redo": { + "message": "Повторити" + }, + "cut": { + "message": "Вирізати", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Вставити", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Вибрати все" + }, + "zoomIn": { + "message": "Збільшити" + }, + "zoomOut": { + "message": "Зменшити" + }, + "resetZoom": { + "message": "Скинути масштаб" + }, + "toggleFullScreen": { + "message": "Повноекранний режим" + }, + "reload": { + "message": "Перезавантажити" + }, + "toggleDevTools": { + "message": "Інструменти розробника" + }, + "minimize": { + "message": "Згорнути", + "description": "Minimize window" + }, + "zoom": { + "message": "Масштаб" + }, + "bringAllToFront": { + "message": "Все на передній план", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Про Bitwarden" + }, + "services": { + "message": "Сервіси" + }, + "hideBitwarden": { + "message": "Приховати Bitwarden" + }, + "hideOthers": { + "message": "Приховати інше" + }, + "showAll": { + "message": "Показати все" + }, + "quitBitwarden": { + "message": "Вийти з Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ скопійовано", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Допомога" + }, + "window": { + "message": "Вікно" + }, + "checkPassword": { + "message": "Перевірити чи пароль було викрито." + }, + "passwordExposed": { + "message": "Цей пароль було викрито $VALUE$ разів з витоком даних. Вам слід його змінити.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Цей пароль не було знайдено у жодних відомих витоках даних. Його можна безпечно використовувати." + }, + "baseDomain": { + "message": "Основний домен", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Ім'я домену", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Вузол", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Точно" + }, + "startsWith": { + "message": "Починається з" + }, + "regEx": { + "message": "Звичайний вираз", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Виявлення збігів", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Типове виявлення збігів", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Перемкнути налаштування" + }, + "organization": { + "message": "Організація", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Типово" + }, + "exit": { + "message": "Вийти" + }, + "showHide": { + "message": "Показати / Приховати", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Згорнути в лоток" + }, + "alwaysOnTop": { + "message": "Завжди вгорі", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Оновлено", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Пароль оновлено", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Експорт сховища" + }, + "fileFormat": { + "message": "Формат файлу" + }, + "warning": { + "message": "ПОПЕРЕДЖЕННЯ", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Підтвердити експорт сховища" + }, + "exportWarningDesc": { + "message": "Експортовані дані вашого сховища знаходяться в незашифрованому вигляді. Вам не слід зберігати чи надсилати їх через незахищені канали (наприклад, е-поштою). Після використання негайно видаліть їх." + }, + "encExportKeyWarningDesc": { + "message": "Цей експорт шифрує ваші дані за допомогою ключа шифрування облікового запису. Якщо ви коли-небудь оновите ключ шифрування облікового запису, ви повинні виконати експорт знову, оскільки не зможете розшифрувати цей файл експорту." + }, + "encExportAccountWarningDesc": { + "message": "Ключі шифрування унікальні для кожного облікового запису користувача Bitwarden, тому ви не можете імпортувати зашифрований експорт до іншого облікового запису." + }, + "noOrganizationsList": { + "message": "Ви не входите до жодної організації. Організації дозволяють безпечно обмінюватися елементами з іншими користувачами." + }, + "noCollectionsInList": { + "message": "Немає збірок." + }, + "ownership": { + "message": "Власник" + }, + "whoOwnsThisItem": { + "message": "Хто є власником цього елемента?" + }, + "strong": { + "message": "Надійний", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Хороший", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Слабкий", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Слабкий головний пароль" + }, + "weakMasterPasswordDesc": { + "message": "Обраний вами головний пароль є слабким. Для належного захисту свого облікового запису Bitwarden, вам слід використовувати надійний головний пароль (або парольну фразу). Ви впевнені, що хочете використати цей пароль?" + }, + "pin": { + "message": "PIN-код", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Розблокування з PIN-кодом" + }, + "setYourPinCode": { + "message": "Встановіть PIN-код для розблокування Bitwarden. Налаштування PIN-коду будуть скинуті, якщо ви коли-небудь повністю вийдете з програми." + }, + "pinRequired": { + "message": "Необхідний PIN-код." + }, + "invalidPin": { + "message": "Неправильний PIN-код." + }, + "unlockWithWindowsHello": { + "message": "Розблокувати з Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Перевірити на Bitwarden." + }, + "unlockWithTouchId": { + "message": "Розблокувати з Touch ID" + }, + "touchIdConsentMessage": { + "message": "розблокувати сховище" + }, + "noAutoPromptWindowsHello": { + "message": "Не запитувати Windows Hello під час запуску." + }, + "noAutoPromptTouchId": { + "message": "Не запитувати Touch ID під час запуску." + }, + "lockWithMasterPassOnRestart": { + "message": "Блокувати головним паролем при перезапуску" + }, + "preferences": { + "message": "Налаштування" + }, + "enableMenuBar": { + "message": "Увімкнути піктограму в панелі завдань" + }, + "enableMenuBarDesc": { + "message": "Завжди показувати піктограму в панелі завдань." + }, + "hideToMenuBar": { + "message": "Приховувати до панелі завдань" + }, + "selectOneCollection": { + "message": "Ви повинні обрати принаймні одну збірку." + }, + "premiumUpdated": { + "message": "Ви оновилися до версії premium." + }, + "restore": { + "message": "Відновити" + }, + "premiumManageAlertAppStore": { + "message": "Ви можете керувати своєю передплатою з App Store. Хочете перейти в App Store зараз?" + }, + "legal": { + "message": "Юридична інформація", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Умови користування" + }, + "privacyPolicy": { + "message": "Політика приватності" + }, + "unsavedChangesConfirmation": { + "message": "Ви справді хочете піти? Якщо ви зараз підете, вашу поточну інформацію не буде збережено." + }, + "unsavedChangesTitle": { + "message": "Є незбережені зміни" + }, + "clone": { + "message": "Клонувати" + }, + "passwordGeneratorPolicyInEffect": { + "message": "На параметри генератора впливають одна чи декілька політик організації." + }, + "vaultTimeoutAction": { + "message": "Дія після часу очікування сховища" + }, + "vaultTimeoutActionLockDesc": { + "message": "Щоб відновити доступ до заблокованого сховища, необхідно повторно ввести головний пароль." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Щоб відновити доступ до сховища після виходу, необхідно повторно авторизуватись." + }, + "lock": { + "message": "Блокувати", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Смітник", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Пошук у смітнику" + }, + "permanentlyDeleteItem": { + "message": "Остаточно видалити запис" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Ви дійсно хочете остаточно видалити цей запис?" + }, + "permanentlyDeletedItem": { + "message": "Запис остаточно видалено" + }, + "restoreItem": { + "message": "Відновити запис" + }, + "restoreItemConfirmation": { + "message": "Ви дійсно хочете відновити цей запис?" + }, + "restoredItem": { + "message": "Запис відновлено" + }, + "permanentlyDelete": { + "message": "Остаточно видалити" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Вихід скасує всі права доступу до вашого сховища і вимагатиме авторизації після завершення часу очікування. Ви дійсно хочете використати цей параметр?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Підтвердження дії часу очікування" + }, + "enterpriseSingleSignOn": { + "message": "Єдиний корпоративний вхід (SSO)" + }, + "setMasterPassword": { + "message": "Встановити головний пароль" + }, + "ssoCompleteRegistration": { + "message": "Щоб завершити налаштування входу з SSO, встановіть головний пароль для доступу і захисту сховища." + }, + "newMasterPass": { + "message": "Новий головний пароль" + }, + "confirmNewMasterPass": { + "message": "Підтвердьте новий головний пароль" + }, + "masterPasswordPolicyInEffect": { + "message": "Одна або декілька політик організації вимагають дотримання таких вимог для головного пароля:" + }, + "policyInEffectMinComplexity": { + "message": "Мінімальна оцінка складності $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Мінімальна довжина $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Наявність одного чи більше символів верхнього регістру" + }, + "policyInEffectLowercase": { + "message": "Наявність одного чи більше символів нижнього регістру" + }, + "policyInEffectNumbers": { + "message": "Наявність однієї чи більше цифр" + }, + "policyInEffectSpecial": { + "message": "Наявність одного чи більше таких спеціальних символів $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Ваш новий головний пароль не задовольняє вимоги політики." + }, + "acceptPolicies": { + "message": "Позначивши цей прапорець, ви погоджуєтеся з:" + }, + "acceptPoliciesError": { + "message": "Умови користування та політика приватності не погоджені." + }, + "enableBrowserIntegration": { + "message": "Увімкнути інтеграцію з браузером" + }, + "enableBrowserIntegrationDesc": { + "message": "Інтеграція з браузером використовується для біометрії в браузері." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Інтеграція з браузером не підтримується" + }, + "browserIntegrationMasOnlyDesc": { + "message": "На жаль, зараз інтеграція з браузером підтримується лише у версії для Mac з App Store." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Інтеграція з браузером не підтримується" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "На жаль, зараз інтеграція з браузером не підтримується у версії з Windows Store." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Вимагати підтвердження для інтеграції з браузером" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Увімкніть додатковий рівень безпеки, вимагаючи перевірку фрази відбитка при встановленні зв'язку між програмою на комп'ютері та браузером. Якщо увімкнено, вимагатиметься втручання користувача і перевірка щоразу при встановленні зв'язку." + }, + "approve": { + "message": "Схвалити" + }, + "verifyBrowserTitle": { + "message": "Перевірка з'єднання з браузером" + }, + "verifyBrowserDesc": { + "message": "Переконайтеся, що показаний відбиток ідентичний відбитку в розширенні браузера." + }, + "biometricsNotEnabledTitle": { + "message": "Біометрію не увімкнено" + }, + "biometricsNotEnabledDesc": { + "message": "Для активації біометрії в браузері необхідно спершу увімкнути біометрію в програмі на комп'ютері." + }, + "personalOwnershipSubmitError": { + "message": "У зв'язку з корпоративною політикою, вам не дозволено зберігати записи до особистого сховища. Змініть налаштування власності на організацію та виберіть серед доступних збірок." + }, + "hintEqualsPassword": { + "message": "Підказка для пароля не може бути такою самою, як ваш пароль." + }, + "personalOwnershipPolicyInEffect": { + "message": "Політика організації впливає на ваші параметри власності." + }, + "allSends": { + "message": "Усі відправлення", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Файл" + }, + "sendTypeText": { + "message": "Текст" + }, + "searchSends": { + "message": "Пошук відправлень", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Змінити відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Моє сховище" + }, + "text": { + "message": "Текст" + }, + "deletionDate": { + "message": "Дата видалення" + }, + "deletionDateDesc": { + "message": "Відправлення буде остаточно видалено у вказаний час.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Дата завершення" + }, + "expirationDateDesc": { + "message": "Якщо встановлено, термін дії цього відправлення завершиться у вказаний час.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Максимальна кількість доступів" + }, + "maxAccessCountDesc": { + "message": "Якщо встановлено, користувачі більше не зможуть отримати доступ до цього відправлення після досягнення максимальної кількості доступів.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Поточна кількість доступів" + }, + "disableSend": { + "message": "Деактивувати це відправлення для скасування доступу до нього.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "За бажанням вимагати пароль в користувачів для доступу до цього відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Особисті нотатки про це відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Посилання на відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Посилання на відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "При доступі до відправлення типово приховувати текст", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Відправлення створено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Відправлення змінено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Відправлення видалено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Новий пароль" + }, + "whatTypeOfSend": { + "message": "Який це тип відправлення?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Створити відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Текст, який ви хочете відправити." + }, + "sendFileDesc": { + "message": "Файл, який ви хочете відправити." + }, + "days": { + "message": "$DAYS$ днів", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 день" + }, + "custom": { + "message": "Спеціальний" + }, + "deleteSendConfirmation": { + "message": "Ви дійсно хочете видалити це відправлення?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Копіювати посилання на відправлення", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Копіювати посилання, щоб поділитися відправленням після збереження." + }, + "sendDisabled": { + "message": "Відправлення вимкнено", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "У зв'язку з політикою компанії, ви можете лише видалити наявне відправлення.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Копіювати посилання" + }, + "disabled": { + "message": "Вимкнено" + }, + "maxAccessCountReached": { + "message": "Досягнуто максимальну кількість доступів" + }, + "expired": { + "message": "Термін дії завершився" + }, + "pendingDeletion": { + "message": "Очікується видалення" + }, + "webAuthnAuthenticate": { + "message": "Авторизація WebAuthn" + }, + "hideEmail": { + "message": "Приховувати мою адресу електронної пошти від отримувачів." + }, + "sendOptionsPolicyInEffect": { + "message": "На параметри відправлень впливають одна чи декілька політик організації." + }, + "emailVerificationRequired": { + "message": "Необхідно підтвердити е-пошту" + }, + "emailVerificationRequiredDesc": { + "message": "Для використання цієї функції необхідно підтвердити електронну пошту." + }, + "passwordPrompt": { + "message": "Повторний запит головного пароля" + }, + "passwordConfirmation": { + "message": "Підтвердження головного пароля" + }, + "passwordConfirmationDesc": { + "message": "Ця дія захищена. Щоб продовжити, повторно введіть головний пароль." + }, + "updatedMasterPassword": { + "message": "Головний пароль оновлено" + }, + "updateMasterPassword": { + "message": "Оновити головний пароль" + }, + "updateMasterPasswordWarning": { + "message": "Ваш головний пароль нещодавно був змінений адміністратором організації. Щоб отримати доступ до сховища, ви повинні оновити його зараз. Продовживши, ви вийдете з поточного сеансу, після чого необхідно буде повторно виконати вхід. Сеанси на інших пристроях можуть залишатися активними протягом однієї години." + }, + "hours": { + "message": "Годин" + }, + "minutes": { + "message": "Хвилин" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Політики вашої організації впливають на час очікування сховища. Максимальний дозволений час очікування сховища $HOURS$ годин, $MINUTES$ хвилин", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Час очікування сховища перевищує обмеження, встановлені вашою організацією." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Автоматичне розгортання" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "Ця організація має корпоративну політику, яка автоматично розгортає вас на скидання пароля. Розгортання дозволятиме адміністраторам організації змінювати ваш головний пароль." + }, + "vaultExportDisabled": { + "message": "Експорт сховища вимкнено" + }, + "personalVaultExportPolicyInEffect": { + "message": "Одна чи декілька організаційних політик не дозволяють вам експортувати особисте сховище." + }, + "addAccount": { + "message": "Додати обліковий запис" + }, + "removeMasterPassword": { + "message": "Вилучити головний пароль" + }, + "removedMasterPassword": { + "message": "Головний пароль вилучено." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ використовує SSO з власним сервером ключів. Головний пароль для учасників цієї організації більше не вимагається.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Покинути організацію" + }, + "leaveOrganizationConfirmation": { + "message": "Ви справді хочете покинути цю організацію?" + }, + "leftOrganization": { + "message": "Ви покинули організацію." + }, + "ssoKeyConnectorUnavailable": { + "message": "Не вдається отримати доступ до Key Connector. Спробуйте знову пізніше." + }, + "lockAllVaults": { + "message": "Заблокувати всі сховища" + }, + "accountLimitReached": { + "message": "Можна увійти не більше, ніж у 5 облікових записів одночасно." + }, + "accountPreferences": { + "message": "Налаштування" + }, + "appPreferences": { + "message": "Налаштування програми (Усі облікові записи)" + }, + "accountSwitcherLimitReached": { + "message": "Досягнуто обмеження облікового запису. Вийдіть, щоб додати інший обліковий запис." + }, + "settingsTitle": { + "message": "Налаштування програми для $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Перемкнути обліковий запис" + }, + "options": { + "message": "Налаштування" + }, + "sessionTimeout": { + "message": "Час вашого сеансу завершився. Поверніться назад і спробуйте увійти знову." + }, + "exportingPersonalVaultTitle": { + "message": "Експортування особистого сховища" + }, + "exportingPersonalVaultDescription": { + "message": "Будуть експортовані лише записи особистого сховища, пов'язані з $EMAIL$. Записи сховища організації не буде включено.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Генератор" + }, + "whatWouldYouLikeToGenerate": { + "message": "Що ви бажаєте згенерувати?" + }, + "passwordType": { + "message": "Тип пароля" + }, + "regenerateUsername": { + "message": "Повторно генерувати ім'я користувача" + }, + "generateUsername": { + "message": "Генерувати ім'я користувача" + }, + "usernameType": { + "message": "Тип імені користувача" + }, + "plusAddressedEmail": { + "message": "Плюс адреса електронної пошти" + }, + "plusAddressedEmailDesc": { + "message": "Використовуйте розширені можливості адрес вашого постачальника електронної пошти." + }, + "catchallEmail": { + "message": "Адреса е-пошти Catch-all" + }, + "catchallEmailDesc": { + "message": "Використовуйте свою скриньку вхідних Catch-All власного домену." + }, + "random": { + "message": "Випадково" + }, + "randomWord": { + "message": "Випадкове слово" + }, + "websiteName": { + "message": "Назва вебсайту" + }, + "service": { + "message": "Послуга" + } +} diff --git a/apps/desktop/src/locales/vi/messages.json b/apps/desktop/src/locales/vi/messages.json new file mode 100644 index 0000000000..bf7329b419 --- /dev/null +++ b/apps/desktop/src/locales/vi/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "Bộ lọc" + }, + "allItems": { + "message": "Tất cả các mục" + }, + "favorites": { + "message": "Yêu thích" + }, + "types": { + "message": "Các loại" + }, + "typeLogin": { + "message": "Đăng nhập" + }, + "typeCard": { + "message": "Thẻ" + }, + "typeIdentity": { + "message": "Danh tính" + }, + "typeSecureNote": { + "message": "Ghi chú bảo mật" + }, + "folders": { + "message": "Thư mục" + }, + "collections": { + "message": "Các Bộ Sưu Tập" + }, + "searchVault": { + "message": "Tìm kiếm trong Kho" + }, + "addItem": { + "message": "Thêm Mục" + }, + "shared": { + "message": "Đã chia sẻ" + }, + "share": { + "message": "Chia sẻ" + }, + "moveToOrganization": { + "message": "Move to Organization" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ moved to $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "Choose an organization that you wish to move this item to. Moving to an organization transfers ownership of the item to that organization. You will no longer be the direct owner of this item once it has been moved." + }, + "attachments": { + "message": "Tệp đính kèm" + }, + "viewItem": { + "message": "Xem mục" + }, + "name": { + "message": "Tên mục" + }, + "uri": { + "message": "URL" + }, + "uriPosition": { + "message": "URL $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "URL Mới" + }, + "username": { + "message": "Tên người dùng" + }, + "password": { + "message": "Mật khẩu" + }, + "passphrase": { + "message": "Cụm từ mật khẩu" + }, + "editItem": { + "message": "Chỉnh sửa mục" + }, + "emailAddress": { + "message": "Địa chỉ Email" + }, + "verificationCodeTotp": { + "message": "Mã xác thực (TOTP)" + }, + "website": { + "message": "Trang web" + }, + "notes": { + "message": "Ghi chú" + }, + "customFields": { + "message": "Trường tùy chỉnh" + }, + "launch": { + "message": "Khởi chạy" + }, + "copyValue": { + "message": "Sao chép giá trị", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "Thu nhỏ sau khi sao chép vào bộ nhớ đệm" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "Thu nhỏ sau khi sao chép thông tin của một mục vào bộ nhớ đệm." + }, + "toggleVisibility": { + "message": "Bật/tắt khả năng hiển thị" + }, + "toggleCollapse": { + "message": "Toggle Collapse", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "Tên chủ thẻ" + }, + "number": { + "message": "Số" + }, + "brand": { + "message": "Thương hiệu" + }, + "expiration": { + "message": "Hết hạn" + }, + "securityCode": { + "message": "Mã bảo mật" + }, + "identityName": { + "message": "Tên đầy đủ" + }, + "company": { + "message": "Công ty" + }, + "ssn": { + "message": "Số bảo hiểm xã hội" + }, + "passportNumber": { + "message": "Số hộ chiếu" + }, + "licenseNumber": { + "message": "Số giấy phép" + }, + "email": { + "message": "Email" + }, + "phone": { + "message": "Số điện thoại" + }, + "address": { + "message": "Địa chỉ" + }, + "premiumRequired": { + "message": "Cần có tài khoản cao cấp" + }, + "premiumRequiredDesc": { + "message": "Cần là thành viên cao cấp để sử dụng tính năng này." + }, + "errorOccurred": { + "message": "Đã xảy ra lỗi chưa xác định." + }, + "error": { + "message": "Lỗi" + }, + "january": { + "message": "Tháng 1" + }, + "february": { + "message": "Tháng 2" + }, + "march": { + "message": "Tháng 3" + }, + "april": { + "message": "Tháng 4" + }, + "may": { + "message": "Tháng 5" + }, + "june": { + "message": "Tháng 6" + }, + "july": { + "message": "Tháng 7" + }, + "august": { + "message": "Tháng 8" + }, + "september": { + "message": "Tháng 9" + }, + "october": { + "message": "Tháng 10" + }, + "november": { + "message": "Tháng 11" + }, + "december": { + "message": "Tháng 12" + }, + "ex": { + "message": "Ví dụ:", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "Tiêu đề" + }, + "mr": { + "message": "Ông" + }, + "mrs": { + "message": "Bà" + }, + "ms": { + "message": "Chị" + }, + "dr": { + "message": "Tiến sĩ" + }, + "expirationMonth": { + "message": "Tháng Hết Hạn" + }, + "expirationYear": { + "message": "Năm hết hạn" + }, + "select": { + "message": "Chọn" + }, + "other": { + "message": "Khác" + }, + "generatePassword": { + "message": "Tạo mật khẩu" + }, + "type": { + "message": "Loại" + }, + "firstName": { + "message": "Tên" + }, + "middleName": { + "message": "Tên đệm" + }, + "lastName": { + "message": "Họ" + }, + "fullName": { + "message": "Full Name" + }, + "address1": { + "message": "Địa chỉ 1" + }, + "address2": { + "message": "Địa chỉ 2" + }, + "address3": { + "message": "Địa chỉ 3" + }, + "cityTown": { + "message": "Quận/Huyện/Thị trấn" + }, + "stateProvince": { + "message": "Tỉnh/Thành Phố" + }, + "zipPostalCode": { + "message": "Mã bưu chính" + }, + "country": { + "message": "Quốc Gia" + }, + "save": { + "message": "Lưu" + }, + "cancel": { + "message": "Hủy bỏ" + }, + "delete": { + "message": "Xóa" + }, + "favorite": { + "message": "Yêu thích" + }, + "edit": { + "message": "Sửa" + }, + "authenticatorKeyTotp": { + "message": "Khóa xác thực (TOTP)" + }, + "folder": { + "message": "Thư mục" + }, + "newCustomField": { + "message": "Trường tùy chỉnh mới" + }, + "value": { + "message": "Giá trị" + }, + "dragToSort": { + "message": "Kéo để sắp xếp" + }, + "cfTypeText": { + "message": "Văn bản" + }, + "cfTypeHidden": { + "message": "Ẩn" + }, + "cfTypeBoolean": { + "message": "Đúng/Sai" + }, + "cfTypeLinked": { + "message": "Linked", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "Linked value", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "Xoá" + }, + "nameRequired": { + "message": "Tên là bắt buộc." + }, + "addedItem": { + "message": "Đã thêm mục" + }, + "editedItem": { + "message": "Mục được chỉnh sửa" + }, + "deleteItem": { + "message": "Xóa mục" + }, + "deleteFolder": { + "message": "Xóa thư mục" + }, + "deleteAttachment": { + "message": "Gỡ bỏ tập tin đính kèm" + }, + "deleteItemConfirmation": { + "message": "Bạn có chắc bạn muốn xóa mục này?" + }, + "deletedItem": { + "message": "Đã xóa mục" + }, + "overwritePasswordConfirmation": { + "message": "Bạn có chắc chắn muốn ghi đè mật khẩu hiện tại không?" + }, + "overwriteUsername": { + "message": "Overwrite Username" + }, + "overwriteUsernameConfirmation": { + "message": "Are you sure you want to overwrite the current username?" + }, + "noneFolder": { + "message": "Không được phân loại", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "Thêm thư mục" + }, + "editFolder": { + "message": "Chỉnh sửa thư mục" + }, + "regeneratePassword": { + "message": "Tạo lại mật khẩu" + }, + "copyPassword": { + "message": "Sao chép Mật khẩu" + }, + "copyUri": { + "message": "Sao chép URI" + }, + "copyVerificationCodeTotp": { + "message": "Sao chép Mã xác thực (TOTP)" + }, + "length": { + "message": "Độ dài" + }, + "numWords": { + "message": "Number of Words" + }, + "wordSeparator": { + "message": "Word Separator" + }, + "capitalize": { + "message": "Viết hoa", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "Bao gồm cả số" + }, + "close": { + "message": "Đóng" + }, + "minNumbers": { + "message": "Số kí tự tối thiểu" + }, + "minSpecial": { + "message": "Số kí tự đặc biệt tối thiểu", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "Tránh các ký tự không rõ ràng" + }, + "searchCollection": { + "message": "Tìm kiếm bộ sưu tập" + }, + "searchFolder": { + "message": "Tìm kiếm thư mục" + }, + "searchFavorites": { + "message": "Tìm trong danh sách Yêu thích" + }, + "searchType": { + "message": "Tìm thể loại", + "description": "Search item type" + }, + "newAttachment": { + "message": "Thêm tệp đính kèm mới" + }, + "deletedAttachment": { + "message": "Đã xoá tệp đính kèm" + }, + "deleteAttachmentConfirmation": { + "message": "Bạn có muốn xóa tệp đính kèm này không?" + }, + "attachmentSaved": { + "message": "Tệp đính kèm đã được lưu." + }, + "file": { + "message": "Tập tin" + }, + "selectFile": { + "message": "Chọn 1 tập tin." + }, + "maxFileSize": { + "message": "Kích thước tối đa của tệp tin là 500MB." + }, + "updateKey": { + "message": "Bạn không thể sử dụng tính năng này cho đến khi bạn cập nhật khoá mã hóa." + }, + "editedFolder": { + "message": "Đã chỉnh sửa thư mục" + }, + "addedFolder": { + "message": "Đã thêm thư mục" + }, + "deleteFolderConfirmation": { + "message": "Bạn có chắc chắn muốn xóa thư mục này không?" + }, + "deletedFolder": { + "message": "Đã xóa thư mục" + }, + "loginOrCreateNewAccount": { + "message": "Đăng nhập hoặc tạo tài khoản mới để truy cập kho mật khẩu của bạn." + }, + "createAccount": { + "message": "Tạo Tài Khoản" + }, + "logIn": { + "message": "Đăng Nhập" + }, + "submit": { + "message": "Gửi" + }, + "masterPass": { + "message": "Mật khẩu chính" + }, + "masterPassDesc": { + "message": "Mật khẩu chính là mật khẩu bạn sử dụng để truy cập kho mật khẩu của bạn. Nó rất quan trọng nên bạn không được quên mật khẩu chính của mình. Không có cách nào để khôi phục lại mật khẩu chính nếu bạn quên nó." + }, + "masterPassHintDesc": { + "message": "Một gợi ý mật khẩu có thể giúp bạn nhớ lại mật khẩu chính của bạn nếu bạn quên nó." + }, + "reTypeMasterPass": { + "message": "Nhập lại mật khẩu chính" + }, + "masterPassHint": { + "message": "Gợi ý mật khẩu chính (tùy chọn)" + }, + "settings": { + "message": "Cài đặt" + }, + "passwordHint": { + "message": "Gợi ý mật khẩu" + }, + "enterEmailToGetHint": { + "message": "Nhập địa chỉ email tài khoản của bạn để nhận gợi ý mật khẩu chính." + }, + "getMasterPasswordHint": { + "message": "Nhận gợi ý mật khẩu chính" + }, + "emailRequired": { + "message": "Địa chỉ email là bắt buộc." + }, + "invalidEmail": { + "message": "Địa chỉ email không hợp lệ." + }, + "masterPassRequired": { + "message": "Mật khẩu chính là bắt buộc." + }, + "masterPassLength": { + "message": "Mật khẩu chính phải có ít nhất 8 kí tự." + }, + "masterPassDoesntMatch": { + "message": "Xác nhận mật khẩu chính không khớp." + }, + "newAccountCreated": { + "message": "Tài khoản của bạn đã được tạo. Bạn có thể đăng nhập bây giờ." + }, + "masterPassSent": { + "message": "Chúng tôi đã gửi cho bạn email có chứa gợi ý mật khẩu chính của bạn." + }, + "unexpectedError": { + "message": "Một lỗi bất ngờ đã xảy ra." + }, + "itemInformation": { + "message": "Mục thông tin" + }, + "noItemsInList": { + "message": "Không có mục nào để liệt kê." + }, + "sendVerificationCode": { + "message": "Send a verification code to your email" + }, + "sendCode": { + "message": "Send Code" + }, + "codeSent": { + "message": "Code Sent" + }, + "verificationCode": { + "message": "Mã xác nhận" + }, + "confirmIdentity": { + "message": "Confirm your identity to continue." + }, + "verificationCodeRequired": { + "message": "Yêu cầu mã xác nhận." + }, + "invalidVerificationCode": { + "message": "Invalid verification code" + }, + "continue": { + "message": "Tiếp tục" + }, + "enterVerificationCodeApp": { + "message": "Nhập mã xác nhận 6 chữ số từ ứng dụng xác thực của bạn." + }, + "enterVerificationCodeEmail": { + "message": "Nhập mã xác nhận 6 chữ số đã được gửi tới $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "Email xác minh được gửi tới $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "Ghi nhớ đăng nhập" + }, + "sendVerificationCodeEmailAgain": { + "message": "Gửi lại email chứa mã xác nhận" + }, + "useAnotherTwoStepMethod": { + "message": "Sử dụng phương pháp xác thực hai lớp khác" + }, + "insertYubiKey": { + "message": "Lắp YubiKey vào cổng USB máy tính của bạn, sau đó chạm vào nút trên nó." + }, + "insertU2f": { + "message": "Lắp khóa bảo mật vào cổng USB của máy tính. Nếu nó có một nút, nhấn vào nó." + }, + "recoveryCodeDesc": { + "message": "Bạn mất quyền truy cập vào tất cả các dịch vụ xác thực 2 lớp? Sử dụng mã phục hồi của bạn để vô hiệu hóa tất cả các dịch vụ xác thực hai lớp trong tài khoản của bạn." + }, + "recoveryCodeTitle": { + "message": "Mã phục hồi" + }, + "authenticatorAppTitle": { + "message": "Ứng dụng xác thực" + }, + "authenticatorAppDesc": { + "message": "Sử dụng một ứng dụng xác thực (chẳng hạn như Authy hoặc Google Authenticator) để tạo các mã xác nhận theo thời gian thực.", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "Khóa bảo mật YubiKey OTP" + }, + "yubiKeyDesc": { + "message": "Sử dụng YubiKey để truy cập tài khoản của bạn. Làm việc với thiết bị YubiKey 4, 4 Nano, 4C và NEO." + }, + "duoDesc": { + "message": "Xác minh với Duo Security sử dụng ứng dụng Duo Mobile, SMS, cuộc gọi điện thoại, hoặc khoá bảo mật U2F.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "Verify with Duo Security for your organization using the Duo Mobile app, SMS, phone call, or U2F security key.", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "Use any WebAuthn enabled security key to access your account." + }, + "emailTitle": { + "message": "Email" + }, + "emailDesc": { + "message": "Mã xác thực sẽ được gửi qua email cho bạn." + }, + "loginUnavailable": { + "message": "Đăng nhập không sẵn có" + }, + "noTwoStepProviders": { + "message": "Tài khoản này đã kích hoạt xác thực hai lớp, tuy nhiên, thiết bị này không hỗ trợ cấu hình dịch vụ xác thực hai lớp đang sử dụng." + }, + "noTwoStepProviders2": { + "message": "Vui lòng thêm các nhà cung cấp khác được hỗ trợ tốt hơn trên các thiết bị (chẳng hạn như một ứng dụng xác thực)." + }, + "twoStepOptions": { + "message": "Tùy chọn xác thực hai lớp" + }, + "selfHostedEnvironment": { + "message": "Môi trường độc lập" + }, + "selfHostedEnvironmentFooter": { + "message": "Chỉ định liên kết cơ bản của cài đặt Bitwarden tại chỗ của bạn." + }, + "customEnvironment": { + "message": "Môi trường tùy chỉnh" + }, + "customEnvironmentFooter": { + "message": "Đối với người dùng nâng cao. Bạn có thể chỉ định liên kết cơ bản của mỗi dịch vụ một cách độc lập." + }, + "baseUrl": { + "message": "Địa chỉ máy chủ" + }, + "apiUrl": { + "message": "Địa chỉ API máy chủ" + }, + "webVaultUrl": { + "message": "Địa chỉ máy chủ kho web" + }, + "identityUrl": { + "message": "Địa chỉ nhận dạng máy chủ" + }, + "notificationsUrl": { + "message": "Notifications Server URL" + }, + "iconsUrl": { + "message": "Biểu tượng địa chỉ máy chủ" + }, + "environmentSaved": { + "message": "Địa chỉ môi trường đã được lưu." + }, + "ok": { + "message": "Ok" + }, + "yes": { + "message": "Có" + }, + "no": { + "message": "Không" + }, + "overwritePassword": { + "message": "Ghi đè lên mật khẩu" + }, + "learnMore": { + "message": "Tìm hiểu thêm" + }, + "featureUnavailable": { + "message": "Tính năng không có sẵn" + }, + "loggedOut": { + "message": "Đăng xuất" + }, + "loginExpired": { + "message": "Phiên đăng nhập của bạn đã hết hạn." + }, + "logOutConfirmation": { + "message": "Bạn có chắc chắn muốn đăng xuất không?" + }, + "logOut": { + "message": "Đăng xuất" + }, + "addNewLogin": { + "message": "Thêm đăng nhập mới" + }, + "addNewItem": { + "message": "Thêm mục mới" + }, + "addNewFolder": { + "message": "Thêm thư mục mới" + }, + "view": { + "message": "Xem" + }, + "account": { + "message": "Tài khoản" + }, + "loading": { + "message": "Đang tải..." + }, + "lockVault": { + "message": "Lock Vault" + }, + "passwordGenerator": { + "message": "Tạo mật khẩu" + }, + "contactUs": { + "message": "Contact Us" + }, + "getHelp": { + "message": "Get Help" + }, + "fileBugReport": { + "message": "Gửi báo cáo lỗi" + }, + "blog": { + "message": "Blog" + }, + "followUs": { + "message": "Theo chúng tôi" + }, + "syncVault": { + "message": "Đồng bộ Kho mật khẩu" + }, + "changeMasterPass": { + "message": "Thay đổi mật khẩu chính" + }, + "changeMasterPasswordConfirmation": { + "message": "Bạn có thể thay đổi mật khẩu chính trong kho bitwarden nền web. Bạn có muốn truy cập trang web bây giờ?" + }, + "fingerprintPhrase": { + "message": "Fingerprint Phrase", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "Cụm từ mật khẩu tài khoản của bạn", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "Đi đến bitwarden nền Web" + }, + "getMobileApp": { + "message": "Tải ứng dụng điện thoại" + }, + "getBrowserExtension": { + "message": "Cài tiện ích mở rộng cho trình duyệt" + }, + "syncingComplete": { + "message": "Đồng bộ hoàn tất" + }, + "syncingFailed": { + "message": "Đồng bộ thất bại" + }, + "yourVaultIsLocked": { + "message": "Kho mật khẩu đã bị khóa. Xác minh mật khẩu chinhs của bạn để mở." + }, + "unlock": { + "message": "Mở khóa" + }, + "loggedInAsOn": { + "message": "Đã đăng nhập bằng $EMAIL$ trên $HOSTNAME$.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "Mật khẩu chính không hợp lệ" + }, + "twoStepLoginConfirmation": { + "message": "Xác thực hai lớp giúp cho tài khoản của bạn an toàn hơn bằng cách yêu cầu bạn xác minh thông tin đăng nhập của bạn bằng một thiết bị khác như khóa bảo mật, ứng dụng xác thực, SMS, cuộc gọi điện thoại hoặc email. Bạn có thể bật xác thực hai lớp trong kho bitwarden nền web. Bạn có muốn ghé thăm trang web bây giờ?" + }, + "twoStepLogin": { + "message": "Xác thực hai lớp" + }, + "vaultTimeout": { + "message": "Thời Gian Chờ Của Kho" + }, + "vaultTimeoutDesc": { + "message": "Chọn khi nào thì kho của bạn sẽ hết thời gian chờ và thực hiện hành động đã được chọn." + }, + "immediately": { + "message": "Tức thì" + }, + "tenSeconds": { + "message": "10 giây" + }, + "twentySeconds": { + "message": "20 giây" + }, + "thirtySeconds": { + "message": "30 giây" + }, + "oneMinute": { + "message": "1 phút" + }, + "twoMinutes": { + "message": "2 phút" + }, + "fiveMinutes": { + "message": "5 phút" + }, + "fifteenMinutes": { + "message": "15 phút" + }, + "thirtyMinutes": { + "message": "30 phút" + }, + "oneHour": { + "message": "1 giờ" + }, + "fourHours": { + "message": "4 giờ" + }, + "onIdle": { + "message": "Khi hệ thống rảnh" + }, + "onSleep": { + "message": "Khi hệ thống ngủ" + }, + "onLocked": { + "message": "Khi khóa màn hình" + }, + "onRestart": { + "message": "Khi khởi động lại máy" + }, + "never": { + "message": "Không bao giờ" + }, + "security": { + "message": "Bảo mật" + }, + "clearClipboard": { + "message": "Dọn dẹp khay nhớ tạm", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "Tự động dọn dẹp giá trị được sao chép khỏi khay nhớ tạm của bạn.", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "Vô hiệu hoá biểu tượng trang web" + }, + "disableFaviconDesc": { + "message": "Biểu tượng trang web cung cấp các biểu tượng nhận dạng trang web bên cạnh mỗi mục đăng nhập trong kho mật khẩu của bạn." + }, + "enableMinToTray": { + "message": "Minimize to Tray Icon" + }, + "enableMinToTrayDesc": { + "message": "When minimizing the window, show an icon in the system tray instead." + }, + "enableMinToMenuBar": { + "message": "Minimize to menu bar" + }, + "enableMinToMenuBarDesc": { + "message": "When minimizing the window, show an icon in the menu bar instead." + }, + "enableCloseToTray": { + "message": "Close to Tray Icon" + }, + "enableCloseToTrayDesc": { + "message": "Khi đóng cửa sổ, thay vào đó sẽ hiện một biểu tượng trên khay hệ thống." + }, + "enableCloseToMenuBar": { + "message": "Close to menu bar" + }, + "enableCloseToMenuBarDesc": { + "message": "When closing the window, show an icon in the menu bar instead." + }, + "enableTray": { + "message": "Enable Tray Icon" + }, + "enableTrayDesc": { + "message": "Luôn hiện biểu tượng trên khay hệ thống." + }, + "startToTray": { + "message": "Khởi động vào khay hệ thống" + }, + "startToTrayDesc": { + "message": "Khi ứng dụng mới mở, chỉ hiện biểu tượng trên khay hệ thống." + }, + "startToMenuBar": { + "message": "Start to menu bar" + }, + "startToMenuBarDesc": { + "message": "When the application is first started, only show an icon in the menu bar." + }, + "openAtLogin": { + "message": "Start automatically on login" + }, + "openAtLoginDesc": { + "message": "Start the Bitwarden Desktop application automatically on login." + }, + "alwaysShowDock": { + "message": "Always show in the Dock" + }, + "alwaysShowDockDesc": { + "message": "Show the Bitwarden icon in the Dock even when minimized to the menu bar." + }, + "confirmTrayTitle": { + "message": "Confirm disable tray" + }, + "confirmTrayDesc": { + "message": "Disabling this setting will also disable all other tray related settings." + }, + "language": { + "message": "Ngôn ngữ" + }, + "languageDesc": { + "message": "Thay đổi ngôn ngữ được ứng dụng sử dụng. Yêu cầu khởi động lại." + }, + "theme": { + "message": "Chủ đề" + }, + "themeDesc": { + "message": "Change the application's color theme." + }, + "dark": { + "message": "Tối", + "description": "Dark color" + }, + "light": { + "message": "Sáng", + "description": "Light color" + }, + "copy": { + "message": "Sao chép", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "Kiểm tra cập nhật mới" + }, + "version": { + "message": "Phiên bản $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "Khởi động lại để cập nhật" + }, + "restartToUpdateDesc": { + "message": "Phiên bản $VERSION_NUM$ đã sẵn sàng để cài đặt. Bitwarden cần khởi động lại để hoàn tất quá trình cài đặt. Bạn có muốn khởi động lại và cập nhật bây giờ không?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "Có bản cập nhật mới" + }, + "updateAvailableDesc": { + "message": "Một bản cập nhật đã được tìm thấy. Bạn có muốn tải xuống bây giờ không?" + }, + "restart": { + "message": "Khởi động lại" + }, + "later": { + "message": "Để sau" + }, + "noUpdatesAvailable": { + "message": "Hiện không có cập nhật nào. Bạn đang sử dụng phiên bản mới nhất." + }, + "updateError": { + "message": "Cập nhật bị lỗi" + }, + "unknown": { + "message": "Không xác định" + }, + "copyUsername": { + "message": "Sao chép Tên đăng nhập" + }, + "copyNumber": { + "message": "Chép số", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "Sao chép Mã bảo mật", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "Thành viên Cao Cấp" + }, + "premiumManage": { + "message": "Quản lý Thành viên" + }, + "premiumManageAlert": { + "message": "Bạn có thể quản lý các thành viên trong kho bitwarden nền web. Bạn có muốn truy cập trang web bây giờ?" + }, + "premiumRefresh": { + "message": "Làm mới thành viên" + }, + "premiumNotCurrentMember": { + "message": "Bạn hiện không phải là một thành viên cao cấp." + }, + "premiumSignUpAndGet": { + "message": "Đăng ký làm thành viên cao cấp và nhận được:" + }, + "premiumSignUpStorage": { + "message": "1GB bộ nhớ lưu trữ tập tin được mã hóa." + }, + "premiumSignUpTwoStep": { + "message": "Các tùy chọn xác thực hai lớp bổ sung như YubiKey, FIDO U2F và Duo." + }, + "premiumSignUpReports": { + "message": "Thanh lọc mật khẩu, kiểm tra an toàn tài khoản và các báo cáo rò rĩ dữ liệu là để giữ cho kho của bạn an toàn." + }, + "premiumSignUpTotp": { + "message": "Mã xác nhận TOTP (2FA) để đăng nhập vào kho mật khẩu của bạn." + }, + "premiumSignUpSupport": { + "message": "Hỗ trợ khách hàng ưu tiên." + }, + "premiumSignUpFuture": { + "message": "Tất cả các tính năng cao cấp trong tương lai. Nó sẽ sớm xuất hiện!" + }, + "premiumPurchase": { + "message": "Mua bản Cao Cấp" + }, + "premiumPurchaseAlert": { + "message": "Bạn có thể nâng cấp làm thành viên cao cấp trong kho bitwarden nền web. Bạn có muốn truy cập trang web bây giờ?" + }, + "premiumCurrentMember": { + "message": "Bạn là một thành viên cao cấp!" + }, + "premiumCurrentMemberThanks": { + "message": "Cảm ơn bạn đã hỗ trợ Bitwarden." + }, + "premiumPrice": { + "message": "Tất cả chỉ với $PRICE$ /năm!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "Làm mới hoàn tất" + }, + "passwordHistory": { + "message": "Lịch sử Mật khẩu" + }, + "clear": { + "message": "Xoá", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "Không có mật khẩu để liệt kê." + }, + "undo": { + "message": "Hoàn tác" + }, + "redo": { + "message": "Làm lại" + }, + "cut": { + "message": "Cắt", + "description": "Cut to clipboard" + }, + "paste": { + "message": "Dán", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "Chọn tất cả" + }, + "zoomIn": { + "message": "Phóng to" + }, + "zoomOut": { + "message": "Thu nhỏ" + }, + "resetZoom": { + "message": "Đặt lại thu phóng" + }, + "toggleFullScreen": { + "message": "Bật/Tắt Toàn Màn Hình" + }, + "reload": { + "message": "Tải lại" + }, + "toggleDevTools": { + "message": "Bật/Tắt Công Cụ Nhà Phát Triển" + }, + "minimize": { + "message": "Thu nhỏ", + "description": "Minimize window" + }, + "zoom": { + "message": "Phóng to" + }, + "bringAllToFront": { + "message": "Hiển thị trên tất cả", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "Giới thiệu về Bitwarden" + }, + "services": { + "message": "Dịch vụ" + }, + "hideBitwarden": { + "message": "Ẩn Bitwarden" + }, + "hideOthers": { + "message": "Ẩn Khác" + }, + "showAll": { + "message": "Hiện tất cả" + }, + "quitBitwarden": { + "message": "Thoát Bitwarden" + }, + "valueCopied": { + "message": "Đã sao chép $VALUE$", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "Trợ giúp" + }, + "window": { + "message": "Cửa sổ" + }, + "checkPassword": { + "message": "Kiểm tra xem mật khẩu có bị lộ không." + }, + "passwordExposed": { + "message": "Mật khẩu này đã bị lộ $VALUE$ thời gian trong các dữ liệu vi phạm. Bạn nên thay đổi nó.", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "Mật khẩu này không được tìm thấy trong bất kỳ dữ liệu vi phạm nào được biết đến. Nó an toàn để sử dụng." + }, + "baseDomain": { + "message": "Tên miền cơ sở", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "Domain Name", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "Máy chủ", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "Chính xác" + }, + "startsWith": { + "message": "Bắt đầu với" + }, + "regEx": { + "message": "Biểu thức chính quy", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "Độ phù hợp", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "Độ phù hợp mặc định", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "Bật/tắt tùy chọn" + }, + "organization": { + "message": "Organization", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "Mặc định" + }, + "exit": { + "message": "Thoát ra" + }, + "showHide": { + "message": "Show / Hide", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "Hide to Tray" + }, + "alwaysOnTop": { + "message": "Luôn trên cùng", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "Ngày cập nhật", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "Password Updated", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "Export Vault" + }, + "fileFormat": { + "message": "File Format" + }, + "warning": { + "message": "CẢNH BÁO", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "Confirm Vault Export" + }, + "exportWarningDesc": { + "message": "This export contains your vault data in an unencrypted format. You should not store or send the exported file over unsecure channels (such as email). Delete it immediately after you are done using it." + }, + "encExportKeyWarningDesc": { + "message": "This export encrypts your data using your account's encryption key. If you ever rotate your account's encryption key you should export again since you will not be able to decrypt this export file." + }, + "encExportAccountWarningDesc": { + "message": "Account encryption keys are unique to each Bitwarden user account, so you can't import an encrypted export into a different account." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "Không có bộ sưu tập nào để liệt kê." + }, + "ownership": { + "message": "Quyền sở hữu" + }, + "whoOwnsThisItem": { + "message": "Ai sở hữu mục này?" + }, + "strong": { + "message": "Mạnh", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "Tốt", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "Yếu", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "Weak Master Password" + }, + "weakMasterPasswordDesc": { + "message": "Mật khẩu chính bạn vừa chọn có vẻ yếu. Bạn nên chọn mật khẩu chính (hoặc cụm từ mật khẩu) mạnh để bảo vệ đúng cách tài khoản Bitwarden của bạn. Bạn có thực sự muốn dùng mật khẩu chính này?" + }, + "pin": { + "message": "Mã PIN", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "Mở khóa với mã PIN" + }, + "setYourPinCode": { + "message": "Đặt mã PIN của bạn để mở khóa Bitwarden. Cài đặt mã PIN của bạn sẽ bị xóa nếu bạn hoàn toàn đăng xuất khỏi ứng dụng." + }, + "pinRequired": { + "message": "Mã PIN là bắt buộc." + }, + "invalidPin": { + "message": "Mã PIN không hợp lệ." + }, + "unlockWithWindowsHello": { + "message": "Mở khóa với Windows Hello" + }, + "windowsHelloConsentMessage": { + "message": "Xác minh cho Bitwarden." + }, + "unlockWithTouchId": { + "message": "Mở khóa với Touch ID" + }, + "touchIdConsentMessage": { + "message": "Xác minh cho Bitwarden." + }, + "noAutoPromptWindowsHello": { + "message": "Do not prompt for Windows Hello on launch." + }, + "noAutoPromptTouchId": { + "message": "Do not prompt for Touch ID on launch." + }, + "lockWithMasterPassOnRestart": { + "message": "Khóa với mật khẩu chính khi khởi động lại" + }, + "preferences": { + "message": "Tuỳ chỉnh" + }, + "enableMenuBar": { + "message": "Bật biểu tượng thanh menu" + }, + "enableMenuBarDesc": { + "message": "Luôn hiển biểu tượng trên thanh menu." + }, + "hideToMenuBar": { + "message": "Ẩn vào thanh menu" + }, + "selectOneCollection": { + "message": "Bạn phải chọn ít nhất một bộ sưu tập." + }, + "premiumUpdated": { + "message": "Bạn đã nâng cấp lên Cao Cấp." + }, + "restore": { + "message": "Khôi phục" + }, + "premiumManageAlertAppStore": { + "message": "Bạn có thể quản lý đăng ký của từ App Store. Bạn có muốn truy cập vào App Store ngay không?" + }, + "legal": { + "message": "Pháp lý", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "Điều khoản dịch vụ" + }, + "privacyPolicy": { + "message": "Chính sách bảo mật" + }, + "unsavedChangesConfirmation": { + "message": "Bạn có chắc là muốn thoát? Nếu bạn thoát bây giờ, thông tin hiện tại sẽ không được lưu lại." + }, + "unsavedChangesTitle": { + "message": "Những thay đổi chưa được lưu" + }, + "clone": { + "message": "Tạo bản sao" + }, + "passwordGeneratorPolicyInEffect": { + "message": "Có một hoặc vài chính sách của tổ chức đang làm ảnh hưởng đến cài đặt tạo mật khẩu của bạn." + }, + "vaultTimeoutAction": { + "message": "Hành Động Khi Hết Thời Gian Chờ" + }, + "vaultTimeoutActionLockDesc": { + "message": "Kho bị khóa sẽ yêu cầu bạn nhập lại mật khẩu chính để có thể truy cập." + }, + "vaultTimeoutActionLogOutDesc": { + "message": "Kho bị đăng xuất sẽ yêu cầu bạn xác thực lại để có thể truy cập." + }, + "lock": { + "message": "Khóa", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "Thùng rác", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "Tìm kiếm thùng rác" + }, + "permanentlyDeleteItem": { + "message": "Xoá vĩnh viễn mục" + }, + "permanentlyDeleteItemConfirmation": { + "message": "Bạn có chắc chắn muốn xóa vĩnh viễn mục này không?" + }, + "permanentlyDeletedItem": { + "message": "Đã xóa vĩnh viễn mục" + }, + "restoreItem": { + "message": "Khôi phục mục" + }, + "restoreItemConfirmation": { + "message": "Bạn có chắc chắn muốn khôi phục mục này không?" + }, + "restoredItem": { + "message": "Mục đã được khôi phục" + }, + "permanentlyDelete": { + "message": "Xóa Vĩnh Viễn" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "Đăng xuất sẽ xóa tất các truy cập vào kho của bạn và yêu cầu xác thực trực tuyến sau khi khoảng thời gian chờ hết. Bạn có chắc bạn muốn dùng cài đặt này?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "Xác nhận hành động khi hết thời gian chờ" + }, + "enterpriseSingleSignOn": { + "message": "Enterprise Single Sign-On" + }, + "setMasterPassword": { + "message": "Thiết lập mật khẩu chính" + }, + "ssoCompleteRegistration": { + "message": "In order to complete logging in with SSO, please set a master password to access and protect your vault." + }, + "newMasterPass": { + "message": "Mật khẩu chính mới" + }, + "confirmNewMasterPass": { + "message": "Xác nhận mật khẩu chính mới" + }, + "masterPasswordPolicyInEffect": { + "message": "One or more organization policies require your master password to meet the following requirements:" + }, + "policyInEffectMinComplexity": { + "message": "Minimum complexity score of $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "Minimum length of $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "Có chứa một hay nhiều ký tự viết hoa" + }, + "policyInEffectLowercase": { + "message": "Chứa một hoặc nhiều kí tự viết thường" + }, + "policyInEffectNumbers": { + "message": "Có chứa một hay nhiều số" + }, + "policyInEffectSpecial": { + "message": "Có chứa một hay nhiều ký tự đặc biệt sau: $CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "Your new master password does not meet the policy requirements." + }, + "acceptPolicies": { + "message": "By checking this box you agree to the following:" + }, + "acceptPoliciesError": { + "message": "Terms of Service and Privacy Policy have not been acknowledged." + }, + "enableBrowserIntegration": { + "message": "Enable browser integration" + }, + "enableBrowserIntegrationDesc": { + "message": "Browser integration is used for biometrics in browser." + }, + "browserIntegrationMasOnlyTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationMasOnlyDesc": { + "message": "Unfortunately browser integration is only supported in the Mac App Store version for now." + }, + "browserIntegrationWindowsStoreTitle": { + "message": "Browser integration not supported" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "Unfortunately browser integration is currently not supported in the Windows Store version." + }, + "enableBrowserIntegrationFingerprint": { + "message": "Require verification for browser integration" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established." + }, + "approve": { + "message": "Chấp nhận" + }, + "verifyBrowserTitle": { + "message": "Verify browser connection" + }, + "verifyBrowserDesc": { + "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." + }, + "biometricsNotEnabledTitle": { + "message": "Biometrics not enabled" + }, + "biometricsNotEnabledDesc": { + "message": "Browser biometrics requires desktop biometrics to be enabled in the settings first." + }, + "personalOwnershipSubmitError": { + "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." + }, + "hintEqualsPassword": { + "message": "Your password hint cannot be the same as your password." + }, + "personalOwnershipPolicyInEffect": { + "message": "An organization policy is affecting your ownership options." + }, + "allSends": { + "message": "Toàn bộ Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "Tập tin" + }, + "sendTypeText": { + "message": "Văn bản" + }, + "searchSends": { + "message": "Tìm kiếm Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "Chỉnh sửa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "Hầm của tôi" + }, + "text": { + "message": "Văn bản" + }, + "deletionDate": { + "message": "Deletion Date" + }, + "deletionDateDesc": { + "message": "Send sẽ được xóa vĩnh viễn vào ngày và giờ được chỉ định.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "Ngày Hết Hạn" + }, + "expirationDateDesc": { + "message": "Nếu được thiết lập, truy cập vào Send này sẽ hết hạn vào ngày và giờ được chỉ định.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "Số lượng truy cập tối đa" + }, + "maxAccessCountDesc": { + "message": "Nếu được thiết lập, khi đã đạt tới số lượng truy cập tối đa, người dùng sẽ không thể truy cập Send này nữa.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "Số lượng truy cập hiện tại" + }, + "disableSend": { + "message": "Disable this Send so that no one can access it.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "Optionally require a password for users to access this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "Private notes about this Send.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Gửi liên kết", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send Link", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "When accessing the Send, hide the text by default", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Đã tạo Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Đã chỉnh sửa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Đã xóa Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "Mật khẩu mới" + }, + "whatTypeOfSend": { + "message": "Đây là loại Send gì?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "Tạo Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "Văn bản bạn muốn gửi." + }, + "sendFileDesc": { + "message": "Tập tin bạn muốn gửi." + }, + "days": { + "message": "$DAYS$ ngày", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 ngày" + }, + "custom": { + "message": "Custom" + }, + "deleteSendConfirmation": { + "message": "Bạn có chắc chắn muốn xóa Send này?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "Copy Send link to clipboard", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "Copy the link to share this Send to my clipboard upon save." + }, + "sendDisabled": { + "message": "Đã tắt Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "Do chính sách doanh nghiệp, bạn chỉ có thể xóa những Send hiện có.", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "Sao chép liên kết" + }, + "disabled": { + "message": "Disabled" + }, + "maxAccessCountReached": { + "message": "Max access count reached" + }, + "expired": { + "message": "Expired" + }, + "pendingDeletion": { + "message": "Đang chờ xóa" + }, + "webAuthnAuthenticate": { + "message": "Authenticate WebAuthn" + }, + "hideEmail": { + "message": "Hide my email address from recipients." + }, + "sendOptionsPolicyInEffect": { + "message": "One or more organization policies are affecting your Send options." + }, + "emailVerificationRequired": { + "message": "Email Verification Required" + }, + "emailVerificationRequiredDesc": { + "message": "You must verify your email to use this feature." + }, + "passwordPrompt": { + "message": "Master password re-prompt" + }, + "passwordConfirmation": { + "message": "Master password confirmation" + }, + "passwordConfirmationDesc": { + "message": "This action is protected. To continue, please re-enter your master password to verify your identity." + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + }, + "addAccount": { + "message": "Add Account" + }, + "removeMasterPassword": { + "message": "Remove Master Password" + }, + "removedMasterPassword": { + "message": "Master password removed." + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ is using SSO with a self-hosted key server. A master password is no longer required to log in for members of this organization.", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "Leave Organization" + }, + "leaveOrganizationConfirmation": { + "message": "Are you sure you want to leave this organization?" + }, + "leftOrganization": { + "message": "You have left the organization." + }, + "ssoKeyConnectorUnavailable": { + "message": "Unable to reach the key connector, try again later." + }, + "lockAllVaults": { + "message": "Lock All Vaults" + }, + "accountLimitReached": { + "message": "No more than 5 accounts may be logged in at the same time." + }, + "accountPreferences": { + "message": "Preferences" + }, + "appPreferences": { + "message": "App Settings (All Accounts)" + }, + "accountSwitcherLimitReached": { + "message": "Account limit reached. Log out of an account to add another." + }, + "settingsTitle": { + "message": "App settings for $EMAIL$", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "Switch Account" + }, + "options": { + "message": "Options" + }, + "sessionTimeout": { + "message": "Your session has timed out. Please go back and try logging in again." + }, + "exportingPersonalVaultTitle": { + "message": "Exporting Personal Vault" + }, + "exportingPersonalVaultDescription": { + "message": "Only the personal vault items associated with $EMAIL$ will be exported. Organization vault items will not be included.", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "Generator" + }, + "whatWouldYouLikeToGenerate": { + "message": "What would you like to generate?" + }, + "passwordType": { + "message": "Password Type" + }, + "regenerateUsername": { + "message": "Regenerate Username" + }, + "generateUsername": { + "message": "Generate Username" + }, + "usernameType": { + "message": "Username Type" + }, + "plusAddressedEmail": { + "message": "Plus Addressed Email" + }, + "plusAddressedEmailDesc": { + "message": "Use your email provider's sub-addressing capabilities." + }, + "catchallEmail": { + "message": "Catch-all Email" + }, + "catchallEmailDesc": { + "message": "Use your domain's configured catch-all inbox." + }, + "random": { + "message": "Random" + }, + "randomWord": { + "message": "Random Word" + }, + "websiteName": { + "message": "Website Name" + }, + "service": { + "message": "Service" + } +} diff --git a/apps/desktop/src/locales/zh_CN/messages.json b/apps/desktop/src/locales/zh_CN/messages.json new file mode 100644 index 0000000000..f4a1443cff --- /dev/null +++ b/apps/desktop/src/locales/zh_CN/messages.json @@ -0,0 +1,1740 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "筛选" + }, + "allItems": { + "message": "所有项目" + }, + "favorites": { + "message": "我的收藏" + }, + "types": { + "message": "类型" + }, + "typeLogin": { + "message": "登录" + }, + "typeCard": { + "message": "支付卡" + }, + "typeIdentity": { + "message": "身份" + }, + "typeSecureNote": { + "message": "安全笔记" + }, + "folders": { + "message": "文件夹" + }, + "collections": { + "message": "集合" + }, + "searchVault": { + "message": "搜索密码库" + }, + "addItem": { + "message": "添加项目" + }, + "shared": { + "message": "已共享" + }, + "share": { + "message": "共享" + }, + "moveToOrganization": { + "message": "移动到组织" + }, + "movedItemToOrg": { + "message": "$ITEMNAME$ 已移动到 $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "选择一个您想将此项目移至的组织。移动到组织会将该项目的所有权转让给该组织。移动后,您将不再是此项目的直接所有者。" + }, + "attachments": { + "message": "附件" + }, + "viewItem": { + "message": "查看项目" + }, + "name": { + "message": "名称" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "新增 URI" + }, + "username": { + "message": "用户名" + }, + "password": { + "message": "密码" + }, + "passphrase": { + "message": "密码短语" + }, + "editItem": { + "message": "编辑项目" + }, + "emailAddress": { + "message": "电子邮件地址" + }, + "verificationCodeTotp": { + "message": "验证码 (TOTP)" + }, + "website": { + "message": "网站" + }, + "notes": { + "message": "备注" + }, + "customFields": { + "message": "自定义字段" + }, + "launch": { + "message": "启动" + }, + "copyValue": { + "message": "复制值", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "复制到剪贴板时最小化" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "复制项目数据到剪贴板时最小化。" + }, + "toggleVisibility": { + "message": "切换可见性" + }, + "toggleCollapse": { + "message": "切换折叠", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "持卡人姓名" + }, + "number": { + "message": "号码" + }, + "brand": { + "message": "品牌" + }, + "expiration": { + "message": "到期日" + }, + "securityCode": { + "message": "安全码" + }, + "identityName": { + "message": "身份名称" + }, + "company": { + "message": "公司" + }, + "ssn": { + "message": "社会保险号码" + }, + "passportNumber": { + "message": "护照号码" + }, + "licenseNumber": { + "message": "许可证号码" + }, + "email": { + "message": "电子邮件" + }, + "phone": { + "message": "电话" + }, + "address": { + "message": "地址" + }, + "premiumRequired": { + "message": "需要高级会员" + }, + "premiumRequiredDesc": { + "message": "使用此功能需要高级会员资格。" + }, + "errorOccurred": { + "message": "发生错误。" + }, + "error": { + "message": "错误" + }, + "january": { + "message": "一月" + }, + "february": { + "message": "二月" + }, + "march": { + "message": "三月" + }, + "april": { + "message": "四月" + }, + "may": { + "message": "五月" + }, + "june": { + "message": "六月" + }, + "july": { + "message": "七月" + }, + "august": { + "message": "八月" + }, + "september": { + "message": "九月" + }, + "october": { + "message": "十月" + }, + "november": { + "message": "十一月" + }, + "december": { + "message": "十二月" + }, + "ex": { + "message": "例如", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "称呼" + }, + "mr": { + "message": "先生" + }, + "mrs": { + "message": "夫人" + }, + "ms": { + "message": "女士" + }, + "dr": { + "message": "博士" + }, + "expirationMonth": { + "message": "到期月份" + }, + "expirationYear": { + "message": "到期年份" + }, + "select": { + "message": "选择" + }, + "other": { + "message": "其他" + }, + "generatePassword": { + "message": "生成密码" + }, + "type": { + "message": "类型" + }, + "firstName": { + "message": "名" + }, + "middleName": { + "message": "中间名" + }, + "lastName": { + "message": "姓" + }, + "address1": { + "message": "地址 1" + }, + "address2": { + "message": "地址 2" + }, + "address3": { + "message": "地址 3" + }, + "cityTown": { + "message": "市 / 镇" + }, + "stateProvince": { + "message": "州 / 省" + }, + "zipPostalCode": { + "message": "邮政编码" + }, + "country": { + "message": "国家/地区" + }, + "save": { + "message": "保存" + }, + "cancel": { + "message": "取消" + }, + "delete": { + "message": "删除" + }, + "favorite": { + "message": "收藏" + }, + "edit": { + "message": "编辑" + }, + "authenticatorKeyTotp": { + "message": "验证器密钥 (TOTP)" + }, + "folder": { + "message": "文件夹" + }, + "newCustomField": { + "message": "新建自定义字段" + }, + "value": { + "message": "值" + }, + "dragToSort": { + "message": "拖动排序" + }, + "cfTypeText": { + "message": "文本" + }, + "cfTypeHidden": { + "message": "隐藏的" + }, + "cfTypeBoolean": { + "message": "布尔值" + }, + "remove": { + "message": "移除" + }, + "nameRequired": { + "message": "必须填写名称。" + }, + "addedItem": { + "message": "项目已添加" + }, + "editedItem": { + "message": "项目已编辑" + }, + "deleteItem": { + "message": "删除项目" + }, + "deleteFolder": { + "message": "删除文件夹" + }, + "deleteAttachment": { + "message": "删除附件" + }, + "deleteItemConfirmation": { + "message": "您确定要删除此项目吗?" + }, + "deletedItem": { + "message": "项目已发送到回收站" + }, + "overwritePasswordConfirmation": { + "message": "您确定要覆盖当前密码吗?" + }, + "noneFolder": { + "message": "默认文件夹", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "添加文件夹" + }, + "editFolder": { + "message": "编辑文件夹" + }, + "regeneratePassword": { + "message": "重新生成密码" + }, + "copyPassword": { + "message": "复制密码" + }, + "copyUri": { + "message": "复制 URI" + }, + "copyVerificationCodeTotp": { + "message": "复制验证码 (TOTP)" + }, + "length": { + "message": "长度" + }, + "numWords": { + "message": "单词数" + }, + "wordSeparator": { + "message": "单词分隔符" + }, + "capitalize": { + "message": "大写", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "包含数字" + }, + "close": { + "message": "关闭" + }, + "minNumbers": { + "message": "数字最少个数" + }, + "minSpecial": { + "message": "符号最少个数", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "避免易混淆的字符" + }, + "searchCollection": { + "message": "搜索集合" + }, + "searchFolder": { + "message": "搜索文件夹" + }, + "searchFavorites": { + "message": "搜索收藏" + }, + "searchType": { + "message": "搜索类型", + "description": "Search item type" + }, + "newAttachment": { + "message": "添加新附件" + }, + "deletedAttachment": { + "message": "附件已删除" + }, + "deleteAttachmentConfirmation": { + "message": "您确定要删除此附件吗?" + }, + "attachmentSaved": { + "message": "附件已保存。" + }, + "file": { + "message": "文件" + }, + "selectFile": { + "message": "选择一个文件。" + }, + "maxFileSize": { + "message": "文件最大为 500 MB。" + }, + "updateKey": { + "message": "在您更新加密密钥前,您不能使用此功能。" + }, + "options": { + "message": "选项" + }, + "editedFolder": { + "message": "文件夹已编辑" + }, + "addedFolder": { + "message": "文件夹已添加" + }, + "deleteFolderConfirmation": { + "message": "您确定要删除此文件夹吗?" + }, + "deletedFolder": { + "message": "文件夹已删除" + }, + "loginOrCreateNewAccount": { + "message": "登录或者创建一个账号来访问您的安全密码库。" + }, + "createAccount": { + "message": "创建账号" + }, + "logIn": { + "message": "登录" + }, + "submit": { + "message": "提交" + }, + "masterPass": { + "message": "主密码" + }, + "masterPassDesc": { + "message": "主密码是访问密码库的唯一密码。它非常重要,请您不要忘记。忘记主密码后,我们无法为您恢复或重置它。" + }, + "masterPassHintDesc": { + "message": "主密码提示可以在你忘记密码时帮你回忆。" + }, + "reTypeMasterPass": { + "message": "重新输入主密码" + }, + "masterPassHint": { + "message": "主密码提示 (可选)" + }, + "settings": { + "message": "设置" + }, + "passwordHint": { + "message": "密码提示" + }, + "enterEmailToGetHint": { + "message": "请输入您账号的电子邮件地址来接收密码提示。" + }, + "getMasterPasswordHint": { + "message": "获取主密码提示" + }, + "emailRequired": { + "message": "必须填写电子邮件地址。" + }, + "invalidEmail": { + "message": "无效的电子邮件地址。" + }, + "masterPassRequired": { + "message": "必须填写主密码。" + }, + "masterPassLength": { + "message": "主密码至少需要 8 个字符。" + }, + "masterPassDoesntMatch": { + "message": "两次填写的主密码不一致。" + }, + "newAccountCreated": { + "message": "已经为您建立了账户,您可以登录了。" + }, + "masterPassSent": { + "message": "我们已经为您发送了包含主密码提示的邮件。" + }, + "unexpectedError": { + "message": "发生意外错误。" + }, + "itemInformation": { + "message": "项目信息" + }, + "noItemsInList": { + "message": "没有可列出的项目。" + }, + "verificationCode": { + "message": "验证码" + }, + "verificationCodeRequired": { + "message": "必须填写验证码。" + }, + "continue": { + "message": "继续" + }, + "enterVerificationCodeApp": { + "message": "请输入您的身份验证器应用中的 6 位验证码。" + }, + "enterVerificationCodeEmail": { + "message": "请输入通过电子邮件发送给 $EMAIL$ 的 6 位验证码。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "验证邮件已发送到 $EMAIL$。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "记住我" + }, + "sendVerificationCodeEmailAgain": { + "message": "重发验证码电子邮件" + }, + "useAnotherTwoStepMethod": { + "message": "使用其他两步登录方式" + }, + "insertYubiKey": { + "message": "将您的 YubiKey 插入计算机的 USB 端口,然后按下按钮。" + }, + "insertU2f": { + "message": "将您的安全钥匙插入计算机的 USB 端口。如果它有一个按钮,按下它。" + }, + "recoveryCodeDesc": { + "message": "失去访问您所有的双重身份验证设备?请使用您的恢复代码来禁用您账户中所有的两步登录提供程序。" + }, + "recoveryCodeTitle": { + "message": "恢复代码" + }, + "authenticatorAppTitle": { + "message": "验证器应用" + }, + "authenticatorAppDesc": { + "message": "使用身份验证器应用(例如 Authy 或 Google Authenticator)来生成基于时间的验证码。", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP 安全钥匙" + }, + "yubiKeyDesc": { + "message": "使用 YubiKey 来访问您的账户。支持 YubiKey 4、4 Nano、4C 以及 NEO 设备。" + }, + "duoDesc": { + "message": "使用 Duo Security 的 Duo 移动应用、短信、电话或 U2F 安全钥匙来进行验证。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "为您的组织使用 Duo Security 的 Duo 移动应用、短信、电话或 U2F 安全钥匙来进行验证。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "使用任何 WebAuthn 安全密钥访问您的帐户。" + }, + "emailTitle": { + "message": "电子邮件地址" + }, + "emailDesc": { + "message": "验证码将会发送到您的电子邮箱。" + }, + "loginUnavailable": { + "message": "登录不可用" + }, + "noTwoStepProviders": { + "message": "此账户已启用两步登录,但此设备不支持任何已配置的两步登录提供程序。" + }, + "noTwoStepProviders2": { + "message": "请添加能更好支持跨设备使用的提供程序(比如验证器应用)。" + }, + "twoStepOptions": { + "message": "两步登录选项" + }, + "selfHostedEnvironment": { + "message": "自托管环境" + }, + "selfHostedEnvironmentFooter": { + "message": "指定您本地托管的 Bitwarden 安装的基础 URL。" + }, + "customEnvironment": { + "message": "自定义环境" + }, + "customEnvironmentFooter": { + "message": "适用于高级用户。你可以分别指定各个服务的基础 URL。" + }, + "baseUrl": { + "message": "服务器 URL" + }, + "apiUrl": { + "message": "API 服务器 URL" + }, + "webVaultUrl": { + "message": "网页密码库服务器 URL" + }, + "identityUrl": { + "message": "身份服务器 URL" + }, + "notificationsUrl": { + "message": "通知服务器 URL" + }, + "iconsUrl": { + "message": "图标服务器 URL" + }, + "environmentSaved": { + "message": "各环境 URL 已保存。" + }, + "ok": { + "message": "确定" + }, + "yes": { + "message": "是" + }, + "no": { + "message": "否" + }, + "overwritePassword": { + "message": "覆盖密码" + }, + "learnMore": { + "message": "进一步了解" + }, + "featureUnavailable": { + "message": "功能不可用" + }, + "loggedOut": { + "message": "已注销" + }, + "loginExpired": { + "message": "您的登录会话已过期。" + }, + "logOutConfirmation": { + "message": "您确定要注销吗?" + }, + "logOut": { + "message": "注销" + }, + "addNewLogin": { + "message": "添加新登录" + }, + "addNewItem": { + "message": "添加新项目" + }, + "addNewFolder": { + "message": "添加文件夹" + }, + "view": { + "message": "查看" + }, + "account": { + "message": "账户" + }, + "loading": { + "message": "正在加载..." + }, + "lockNow": { + "message": "立即锁定" + }, + "passwordGenerator": { + "message": "密码生成器" + }, + "emailUs": { + "message": "给我们发邮件" + }, + "visitOurWebsite": { + "message": "访问我们的网站" + }, + "fileBugReport": { + "message": "发送错误报告" + }, + "blog": { + "message": "博客" + }, + "followUs": { + "message": "关注我们" + }, + "syncVault": { + "message": "同步密码库" + }, + "changeMasterPass": { + "message": "修改主密码" + }, + "changeMasterPasswordConfirmation": { + "message": "您可以在 bitwarden.com 网页密码库修改您的主密码。现在要访问吗?" + }, + "fingerprintPhrase": { + "message": "指纹短语", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "您的账户的指纹短语", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "转到网页版密码库" + }, + "getMobileApp": { + "message": "获取手机应用" + }, + "getBrowserExtension": { + "message": "获取浏览器扩展" + }, + "syncingComplete": { + "message": "同步完成" + }, + "syncingFailed": { + "message": "同步失败" + }, + "yourVaultIsLocked": { + "message": "您的密码库已锁定,请验证您的主密码以继续。" + }, + "unlock": { + "message": "解锁​​​​" + }, + "loggedInAsOn": { + "message": "已使用 $EMAIL$ 在 $HOSTNAME$ 上登录。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "无效的主密码" + }, + "twoStepLoginConfirmation": { + "message": "两步登录要求您从其他设备(例如安全钥匙、验证器应用、短信、电话或者电子邮件)来验证你的登录,这能使您的账户更加安全。两步登录可以在 bitwarden.com 网页版密码库启用。现在要访问吗?" + }, + "twoStepLogin": { + "message": "两步登录" + }, + "vaultTimeout": { + "message": "密码库超时" + }, + "vaultTimeoutDesc": { + "message": "选择您的密码库何时超时并执行所选的动作。" + }, + "immediately": { + "message": "立即" + }, + "tenSeconds": { + "message": "10 秒" + }, + "twentySeconds": { + "message": "20 秒" + }, + "thirtySeconds": { + "message": "30 秒" + }, + "oneMinute": { + "message": "1 分钟" + }, + "twoMinutes": { + "message": "2 分钟" + }, + "fiveMinutes": { + "message": "5 分钟" + }, + "fifteenMinutes": { + "message": "15 分钟" + }, + "thirtyMinutes": { + "message": "30 分钟" + }, + "oneHour": { + "message": "1 小时" + }, + "fourHours": { + "message": "4 小时" + }, + "onIdle": { + "message": "系统空闲时" + }, + "onSleep": { + "message": "系统休眠时" + }, + "onLocked": { + "message": "系统锁定时" + }, + "onRestart": { + "message": "重启时" + }, + "never": { + "message": "从不" + }, + "security": { + "message": "安全" + }, + "clearClipboard": { + "message": "清除剪贴板", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "自动清除复制到剪贴板的值。", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "禁用网站图标" + }, + "disableFaviconDesc": { + "message": "在您的密码库的每个登录项旁显示一个可识别的图标。" + }, + "enableMinToTray": { + "message": "最小化到托盘图标" + }, + "enableMinToTrayDesc": { + "message": "最小化窗口后,改为在系统托盘中显示一个图标。" + }, + "enableMinToMenuBar": { + "message": "最小化到菜单栏" + }, + "enableMinToMenuBarDesc": { + "message": "最小化窗口后,改为在菜单栏中显示一个图标。" + }, + "enableCloseToTray": { + "message": "关闭到托盘图标" + }, + "enableCloseToTrayDesc": { + "message": "关闭窗口后,改为在系统托盘中显示一个图标。" + }, + "enableCloseToMenuBar": { + "message": "关闭到菜单栏" + }, + "enableCloseToMenuBarDesc": { + "message": "关闭窗口后,改为在菜单栏中显示一个图标。" + }, + "enableTray": { + "message": "启用托盘图标" + }, + "enableTrayDesc": { + "message": "始终在系统托盘中显示一个图标。" + }, + "startToTray": { + "message": "启动到托盘图标" + }, + "startToTrayDesc": { + "message": "应用程序首次启动时,启动到系统托盘。" + }, + "startToMenuBar": { + "message": "启动到菜单栏" + }, + "startToMenuBarDesc": { + "message": "应用程序首次启动时,启动到菜单栏。" + }, + "openAtLogin": { + "message": "登录时自动启动" + }, + "openAtLoginDesc": { + "message": "登录时自动启动 Bitwarden 桌面应用程序。" + }, + "alwaysShowDock": { + "message": "始终在 Dock 中显示" + }, + "alwaysShowDockDesc": { + "message": "即使已最小化到菜单栏,仍在 Dock 中显示 Bitwarden 图标。" + }, + "confirmTrayTitle": { + "message": "确认禁用托盘" + }, + "confirmTrayDesc": { + "message": "禁用此设置也将禁用其他与托盘相关的设置。" + }, + "language": { + "message": "语言" + }, + "languageDesc": { + "message": "更改本应用程序使用的语言。需要重新启动才能生效。" + }, + "theme": { + "message": "主题" + }, + "themeDesc": { + "message": "更改本应用程序的颜色主题。" + }, + "dark": { + "message": "暗", + "description": "Dark color" + }, + "light": { + "message": "亮", + "description": "Light color" + }, + "copy": { + "message": "复制", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "检查更新" + }, + "version": { + "message": "版本 $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "重启以更新" + }, + "restartToUpdateDesc": { + "message": "版本 $VERSION_NUM$ 已准备好安装。您必须重新启动本应用程序才能完成安装。是否立即重新启动并更新?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "有可用的更新" + }, + "updateAvailableDesc": { + "message": "发现更新。是否立即下载?" + }, + "restart": { + "message": "重新启动" + }, + "later": { + "message": "稍后" + }, + "noUpdatesAvailable": { + "message": "当前没有可用的更新。您使用的是最新版本。" + }, + "updateError": { + "message": "更新错误" + }, + "unknown": { + "message": "未知" + }, + "copyUsername": { + "message": "复制用户名" + }, + "copyNumber": { + "message": "复制号码", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "复制安全码", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "高级会员" + }, + "premiumManage": { + "message": "管理会员资格" + }, + "premiumManageAlert": { + "message": "您可以在 bitwarden.com 网页版密码库管理您的会员资格。现在要访问吗?" + }, + "premiumRefresh": { + "message": "刷新会员资格" + }, + "premiumNotCurrentMember": { + "message": "您目前不是高级会员。" + }, + "premiumSignUpAndGet": { + "message": "注册高级会员将获得:" + }, + "premiumSignUpStorage": { + "message": "1 GB 文件附件加密存储。" + }, + "premiumSignUpTwoStep": { + "message": "额外的两步登录选项,如 YubiKey、FIDO U2F 和 Duo。" + }, + "premiumSignUpReports": { + "message": "密码健康、账户体检以及数据泄露报告,保障您的密码库安全。" + }, + "premiumSignUpTotp": { + "message": "用于密码库中登录项目的 TOTP 验证码(2FA)生成器。" + }, + "premiumSignUpSupport": { + "message": "优先客户支持。" + }, + "premiumSignUpFuture": { + "message": "所有未来的高级功能。即将推出!" + }, + "premiumPurchase": { + "message": "购买高级版" + }, + "premiumPurchaseAlert": { + "message": "您可以在 bitwarden.com 网页版密码库购买高级会员。现在要访问吗?" + }, + "premiumCurrentMember": { + "message": "您是高级会员!" + }, + "premiumCurrentMemberThanks": { + "message": "感谢您支持 Bitwarden。" + }, + "premiumPrice": { + "message": "每年只需 $PRICE$ !", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "刷新完成" + }, + "passwordHistory": { + "message": "密码历史记录" + }, + "clear": { + "message": "清除", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "没有可列出的密码。" + }, + "undo": { + "message": "撤销" + }, + "redo": { + "message": "重做" + }, + "cut": { + "message": "剪切", + "description": "Cut to clipboard" + }, + "paste": { + "message": "粘贴", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "选择所有" + }, + "zoomIn": { + "message": "放大" + }, + "zoomOut": { + "message": "缩小" + }, + "resetZoom": { + "message": "重置缩放" + }, + "toggleFullScreen": { + "message": "切换全屏" + }, + "reload": { + "message": "重新加载" + }, + "toggleDevTools": { + "message": "切换开发工具" + }, + "minimize": { + "message": "最小化", + "description": "Minimize window" + }, + "zoom": { + "message": "缩放" + }, + "bringAllToFront": { + "message": "前置所有", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "关于 Bitwarden" + }, + "services": { + "message": "服务" + }, + "hideBitwarden": { + "message": "隐藏 Bitwarden" + }, + "hideOthers": { + "message": "隐藏其他" + }, + "showAll": { + "message": "显示全部" + }, + "quitBitwarden": { + "message": "退出 Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ 已复制", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "帮助" + }, + "window": { + "message": "窗口" + }, + "checkPassword": { + "message": "检查密码是否已经被公开。" + }, + "passwordExposed": { + "message": "此密码在泄露数据中已被公开 $VALUE$ 次。请立即修改。", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "没有在已知的数据泄露中发现此密码,它暂时比较安全。" + }, + "baseDomain": { + "message": "基础域" + }, + "host": { + "message": "主机", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "精确" + }, + "startsWith": { + "message": "开始于" + }, + "regEx": { + "message": "正则表达式", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "匹配检测", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "默认匹配检测", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "切换选项" + }, + "organization": { + "message": "组织", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "默认" + }, + "exit": { + "message": "退出" + }, + "showHide": { + "message": "显示/隐藏", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "隐藏到托盘" + }, + "alwaysOnTop": { + "message": "总是在最前面", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "更新于", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "密码更新于", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "导出密码库" + }, + "fileFormat": { + "message": "文件格式" + }, + "warning": { + "message": "警告", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "确认密码库导出" + }, + "exportWarningDesc": { + "message": "导出的密码库数据包含未加密格式。您不应该通过不安全的渠道(例如电子邮件)来存储或发送导出的文件。用完后请立即将其删除。" + }, + "encExportKeyWarningDesc": { + "message": "此导出将使用您账户的加密密钥来加密您的数据。 如果您曾经轮换过账户的加密密钥,您应将其重新导出,否则您将无法解密导出的文件。" + }, + "encExportAccountWarningDesc": { + "message": "账户加密密钥对每个 Bitwarden 用户账户都是唯一的,所以您不能将加密的导出导入到另一个账户。" + }, + "exportMasterPassword": { + "message": "输入主密码来导出你的密码库。" + }, + "noOrganizationsList": { + "message": "您没有加入任何组织。同一组织的用户可以安全地与其他用户共享项目。" + }, + "noCollectionsInList": { + "message": "没有可列出的集合。" + }, + "ownership": { + "message": "所有权" + }, + "whoOwnsThisItem": { + "message": "谁拥有这个项目?" + }, + "strong": { + "message": "强", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "良好", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "弱", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "脆弱的主密码" + }, + "weakMasterPasswordDesc": { + "message": "您选择的主密码较弱。您应该使用强密码(或密码短语)来正确保护您的 Bitwarden 账户。仍要使用此主密码吗?" + }, + "pin": { + "message": "PIN 码", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "使用 PIN 码解锁" + }, + "setYourPinCode": { + "message": "设定您用来解锁 Bitwarden 的 PIN 码。您的 PIN 设置将在您完全注销本应用程序时被重置。" + }, + "pinRequired": { + "message": "需要 PIN 码。" + }, + "invalidPin": { + "message": "无效 PIN 码。" + }, + "yourVaultIsLockedPinCode": { + "message": "您的密码库已锁定。请验证您的 PIN 码以继续。" + }, + "unlockWithWindowsHello": { + "message": "使用 Windows Hello 解锁" + }, + "windowsHelloConsentMessage": { + "message": "验证 Bitwarden。" + }, + "unlockWithTouchId": { + "message": "使用触控 ID 解锁" + }, + "touchIdConsentMessage": { + "message": "解锁您的密码库" + }, + "noAutoPromptWindowsHello": { + "message": "启动时不提示 Windows Hello。" + }, + "noAutoPromptTouchId": { + "message": "启动时不提示 Touch ID。" + }, + "lockWithMasterPassOnRestart": { + "message": "重启后使用主密码锁定" + }, + "preferences": { + "message": "设置" + }, + "enableMenuBar": { + "message": "启用菜单栏图标" + }, + "enableMenuBarDesc": { + "message": "始终显示菜单栏图标。" + }, + "hideToMenuBar": { + "message": "隐藏到菜单栏" + }, + "selectOneCollection": { + "message": "您必须至少选择一个集合。" + }, + "premiumUpdated": { + "message": "您已升级到高级会员。" + }, + "restore": { + "message": "恢复" + }, + "premiumManageAlertAppStore": { + "message": "您可以从 App Store 管理您的订阅。现在要访问 App Store 吗?" + }, + "legal": { + "message": "法律条款", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "服务条款" + }, + "privacyPolicy": { + "message": "隐私条款" + }, + "unsavedChangesConfirmation": { + "message": "您确定要离开吗?如果您现在离开,您当前的信息不会被保存。" + }, + "unsavedChangesTitle": { + "message": "更改未保存" + }, + "clone": { + "message": "克隆" + }, + "passwordGeneratorPolicyInEffect": { + "message": "一个或多个组织策略正在影响您的生成器设置。" + }, + "vaultTimeoutAction": { + "message": "密码库超时动作" + }, + "vaultTimeoutActionLockDesc": { + "message": "已锁定的密码库需要重新输入主密码才能再次访问。" + }, + "vaultTimeoutActionLogOutDesc": { + "message": "已注销的密码库需要重新验证才能再次访问。" + }, + "lock": { + "message": "锁定", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "回收站", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "搜索回收站" + }, + "permanentlyDeleteItem": { + "message": "永久删除项目" + }, + "permanentlyDeleteItemConfirmation": { + "message": "您确定要永久删除此项目吗?" + }, + "permanentlyDeletedItem": { + "message": "已永久删除项目" + }, + "restoreItem": { + "message": "恢复项目" + }, + "restoreItemConfirmation": { + "message": "您确定要恢复此项目吗?" + }, + "restoredItem": { + "message": "项目已恢复" + }, + "permanentlyDelete": { + "message": "永久删除" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "超时后注销将解除对密码库的所有访问权限,并需要进行在线验证。确定使用此设置吗?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "超时动作确认" + }, + "enterpriseSingleSignOn": { + "message": "企业单点登录(SSO)" + }, + "setMasterPassword": { + "message": "设置主密码" + }, + "ssoCompleteRegistration": { + "message": "要完成 SSO 登陆配置,请设置一个主密码以访问和保护您的密码库。" + }, + "newMasterPass": { + "message": "新的主密码" + }, + "confirmNewMasterPass": { + "message": "确认新的主密码" + }, + "masterPasswordPolicyInEffect": { + "message": "一个或多个组织策略要求您的主密码满足下列要求:" + }, + "policyInEffectMinComplexity": { + "message": "最小复杂度为 $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "最小长度为 $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "至少包含一个大写字符" + }, + "policyInEffectLowercase": { + "message": "至少包含一个小写字符" + }, + "policyInEffectNumbers": { + "message": "至少包含一个数字" + }, + "policyInEffectSpecial": { + "message": "至少包含一个以下特殊字符:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "您的新主密码不符合策略要求。" + }, + "acceptPolicies": { + "message": "选中此框表示您同意:" + }, + "acceptPoliciesError": { + "message": "尚未同意服务条款和隐私政策。" + }, + "enableBrowserIntegration": { + "message": "启用浏览器整合" + }, + "enableBrowserIntegrationDesc": { + "message": "浏览器整合用于在浏览器中提供生物识别。" + }, + "browserIntegrationMasOnlyTitle": { + "message": "不支持浏览器整合" + }, + "browserIntegrationMasOnlyDesc": { + "message": "很遗憾,目前仅 Mac App Store 版本支持浏览器整合。" + }, + "browserIntegrationWindowsStoreTitle": { + "message": "不支持浏览器整合" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "很不幸,当前 Windows Store 版本不支持浏览器整合。" + }, + "enableBrowserIntegrationFingerprint": { + "message": "要求浏览器整合验证" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "在您的桌面与浏览器间建立连接时,要求验证指纹短语以实现一个额外安全层。此选项启用后,每次建立连接都需要用户干预和验证。" + }, + "approve": { + "message": "批准" + }, + "verifyBrowserTitle": { + "message": "验证浏览器连接" + }, + "verifyBrowserDesc": { + "message": "请确保显示的指纹与浏览器扩展中显示的指纹相同。" + }, + "biometricsNotEnabledTitle": { + "message": "生物识别未启用" + }, + "biometricsNotEnabledDesc": { + "message": "需要先在桌面应用程序的设置中启用生物识别,才能使用浏览器中的生物识别。" + }, + "personalOwnershipSubmitError": { + "message": "由于企业策略,您被限制为保存项目到您的个人密码库。将所有权选项更改为组织,并从可用的集合中选择。" + }, + "hintEqualsPassword": { + "message": "您的密码提示不能与您的密码相同。" + }, + "personalOwnershipPolicyInEffect": { + "message": "一个组织策略正影响您的所有权选项。" + }, + "allSends": { + "message": "所有的 Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "文件" + }, + "sendTypeText": { + "message": "文本" + }, + "searchSends": { + "message": "搜索 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "编辑 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "密码库" + }, + "text": { + "message": "文本" + }, + "deletionDate": { + "message": "删除日期" + }, + "deletionDateDesc": { + "message": "此 Send 将在指定的日期和时间后被永久删除。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "过期日期" + }, + "expirationDateDesc": { + "message": "如果设定,此 Send 将在指定的日期和时间后过期。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "最大访问次数" + }, + "maxAccessCountDesc": { + "message": "如果设定,达到最大访问次数后用户将无法访问此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "当前访问次数" + }, + "disableSend": { + "message": "禁用此 Send 以阻止任何人访问它。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "可选,用户需要提供密码才能访问此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "关于此 Send 的私密备注。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send 链接", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send 链接", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "访问 Send 时,默认将隐藏文本", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send 已创建", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send 已编辑", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send 已删除", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "新密码" + }, + "whatTypeOfSend": { + "message": "这是什么类型的 Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "创建 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "您想要发送的文本。" + }, + "sendFileDesc": { + "message": "您想要发送的文件。" + }, + "days": { + "message": "$DAYS$ 天", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 天" + }, + "custom": { + "message": "自定义" + }, + "deleteSendConfirmation": { + "message": "确定要删除此 Send 吗?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "复制 Send 链接到剪贴板", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "保存时复制链接到剪贴板以便分享此 Send。" + }, + "sendDisabled": { + "message": "Send 已禁用", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "由于企业策略,您只能删除现有的 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "复制链接" + }, + "disabled": { + "message": "已禁用" + }, + "maxAccessCountReached": { + "message": "已达最大访问次数" + }, + "expired": { + "message": "已过期" + }, + "pendingDeletion": { + "message": "等待删除" + }, + "webAuthnAuthenticate": { + "message": "验证 WebAuthn" + }, + "hideEmail": { + "message": "对收件人隐藏我的电子邮件地址。" + }, + "sendOptionsPolicyInEffect": { + "message": "一个或多个组织策略正在影响您的 Send 设置。" + }, + "emailVerificationRequired": { + "message": "需要验证电子邮件" + }, + "emailVerificationRequiredDesc": { + "message": "您必须验证您的电子邮件才能使用此功能。" + }, + "passwordPrompt": { + "message": "重新询问主密码" + }, + "passwordConfirmation": { + "message": "确认主密码" + }, + "passwordConfirmationDesc": { + "message": "此操作受到保护。若要继续,请重新输入您的主密码以验证您的身份。" + }, + "updatedMasterPassword": { + "message": "Updated Master Password" + }, + "updateMasterPassword": { + "message": "Update Master Password" + }, + "updateMasterPasswordWarning": { + "message": "Your Master Password was recently changed by an administrator in your organization. In order to access the vault, you must update it now. Proceeding will log you out of your current session, requiring you to log back in. Active sessions on other devices may continue to remain active for up to one hour." + }, + "hours": { + "message": "Hours" + }, + "minutes": { + "message": "Minutes" + }, + "vaultTimeoutPolicyInEffect": { + "message": "Your organization policies are affecting your vault timeout. Maximum allowed Vault Timeout is $HOURS$ hour(s) and $MINUTES$ minute(s)", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "Your vault timeout exceeds the restrictions set by your organization." + }, + "resetPasswordPolicyAutoEnroll": { + "message": "Automatic Enrollment" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "This organization has an enterprise policy that will automatically enroll you in password reset. Enrollment will allow organization administrators to change your master password." + }, + "vaultExportDisabled": { + "message": "Vault Export Disabled" + }, + "personalVaultExportPolicyInEffect": { + "message": "One or more organization policies prevents you from exporting your personal vault." + } +} diff --git a/apps/desktop/src/locales/zh_TW/messages.json b/apps/desktop/src/locales/zh_TW/messages.json new file mode 100644 index 0000000000..d979e8ef41 --- /dev/null +++ b/apps/desktop/src/locales/zh_TW/messages.json @@ -0,0 +1,1885 @@ +{ + "bitwarden": { + "message": "Bitwarden" + }, + "filters": { + "message": "篩選器" + }, + "allItems": { + "message": "所有項目" + }, + "favorites": { + "message": "我的最愛" + }, + "types": { + "message": "類型" + }, + "typeLogin": { + "message": "登入" + }, + "typeCard": { + "message": "支付卡" + }, + "typeIdentity": { + "message": "身分" + }, + "typeSecureNote": { + "message": "安全筆記" + }, + "folders": { + "message": "資料夾" + }, + "collections": { + "message": "集合" + }, + "searchVault": { + "message": "搜尋密碼庫" + }, + "addItem": { + "message": "新增項目" + }, + "shared": { + "message": "已共享" + }, + "share": { + "message": "共享" + }, + "moveToOrganization": { + "message": "移動至組織" + }, + "movedItemToOrg": { + "message": "已將 $ITEMNAME$ 移動至 $ORGNAME$", + "placeholders": { + "itemname": { + "content": "$1", + "example": "Secret Item" + }, + "orgname": { + "content": "$2", + "example": "Company Name" + } + } + }, + "moveToOrgDesc": { + "message": "選擇您希望將這個項目移動到哪個組織。項目的擁有權將會轉移到該組織。一經移動,您將不再是此項目的直接擁有者。" + }, + "attachments": { + "message": "附件" + }, + "viewItem": { + "message": "檢視項目" + }, + "name": { + "message": "名稱" + }, + "uri": { + "message": "URI" + }, + "uriPosition": { + "message": "URI $POSITION$", + "description": "A listing of URIs. Ex: URI 1, URI 2, URI 3, etc.", + "placeholders": { + "position": { + "content": "$1", + "example": "2" + } + } + }, + "newUri": { + "message": "新增 URI" + }, + "username": { + "message": "使用者名稱" + }, + "password": { + "message": "密碼" + }, + "passphrase": { + "message": "密碼短語" + }, + "editItem": { + "message": "編輯項目" + }, + "emailAddress": { + "message": "電子郵件地址" + }, + "verificationCodeTotp": { + "message": "驗證碼(TOTP)" + }, + "website": { + "message": "網站" + }, + "notes": { + "message": "備註" + }, + "customFields": { + "message": "自訂欄位" + }, + "launch": { + "message": "啟動" + }, + "copyValue": { + "message": "複製值", + "description": "Copy value to clipboard" + }, + "minimizeOnCopyToClipboard": { + "message": "複製到剪貼簿後最小化" + }, + "minimizeOnCopyToClipboardDesc": { + "message": "複製項目資料到剪貼簿後最小化。" + }, + "toggleVisibility": { + "message": "切換可見性" + }, + "toggleCollapse": { + "message": "切換折疊", + "description": "Toggling an expand/collapse state." + }, + "cardholderName": { + "message": "持卡人姓名" + }, + "number": { + "message": "號碼" + }, + "brand": { + "message": "發卡組織" + }, + "expiration": { + "message": "逾期" + }, + "securityCode": { + "message": "安全代碼" + }, + "identityName": { + "message": "身分名稱" + }, + "company": { + "message": "公司" + }, + "ssn": { + "message": "社會保險號碼" + }, + "passportNumber": { + "message": "護照號碼" + }, + "licenseNumber": { + "message": "許可證編號" + }, + "email": { + "message": "電子郵件" + }, + "phone": { + "message": "電話號碼" + }, + "address": { + "message": "地址" + }, + "premiumRequired": { + "message": "需要進階會員資格" + }, + "premiumRequiredDesc": { + "message": "進階會員才可使用此功能。" + }, + "errorOccurred": { + "message": "發生錯誤。" + }, + "error": { + "message": "錯誤" + }, + "january": { + "message": "一月" + }, + "february": { + "message": "二月" + }, + "march": { + "message": "三月" + }, + "april": { + "message": "四月" + }, + "may": { + "message": "五月" + }, + "june": { + "message": "六月" + }, + "july": { + "message": "七月" + }, + "august": { + "message": "八月" + }, + "september": { + "message": "九月" + }, + "october": { + "message": "十月" + }, + "november": { + "message": "十一月" + }, + "december": { + "message": "十二月" + }, + "ex": { + "message": "例如", + "description": "Short abbreviation for 'example'." + }, + "title": { + "message": "稱呼" + }, + "mr": { + "message": "Mr" + }, + "mrs": { + "message": "Mrs" + }, + "ms": { + "message": "Ms" + }, + "dr": { + "message": "Dr" + }, + "expirationMonth": { + "message": "逾期月份" + }, + "expirationYear": { + "message": "逾期年份" + }, + "select": { + "message": "選擇" + }, + "other": { + "message": "其他" + }, + "generatePassword": { + "message": "產生密碼" + }, + "type": { + "message": "類型" + }, + "firstName": { + "message": "名" + }, + "middleName": { + "message": "中間名" + }, + "lastName": { + "message": "姓" + }, + "fullName": { + "message": "全名" + }, + "address1": { + "message": "地址 1" + }, + "address2": { + "message": "地址 2" + }, + "address3": { + "message": "地址 3" + }, + "cityTown": { + "message": "市/鎮" + }, + "stateProvince": { + "message": "州/省" + }, + "zipPostalCode": { + "message": "郵遞區號" + }, + "country": { + "message": "國家" + }, + "save": { + "message": "儲存" + }, + "cancel": { + "message": "取消" + }, + "delete": { + "message": "刪除" + }, + "favorite": { + "message": "我的最愛" + }, + "edit": { + "message": "編輯" + }, + "authenticatorKeyTotp": { + "message": "驗證器金鑰(TOTP)" + }, + "folder": { + "message": "資料夾" + }, + "newCustomField": { + "message": "新增自訂欄位" + }, + "value": { + "message": "值" + }, + "dragToSort": { + "message": "透過拖曳來排序" + }, + "cfTypeText": { + "message": "文字型" + }, + "cfTypeHidden": { + "message": "隱藏型" + }, + "cfTypeBoolean": { + "message": "布林值" + }, + "cfTypeLinked": { + "message": "連結型", + "description": "This describes a field that is 'linked' (related) to another field." + }, + "linkedValue": { + "message": "連結的數值", + "description": "This describes a value that is 'linked' (related) to another value." + }, + "remove": { + "message": "移除" + }, + "nameRequired": { + "message": "必須填入名稱。" + }, + "addedItem": { + "message": "項目已新增" + }, + "editedItem": { + "message": "項目已編輯" + }, + "deleteItem": { + "message": "刪除項目" + }, + "deleteFolder": { + "message": "刪除資料夾" + }, + "deleteAttachment": { + "message": "刪除附件" + }, + "deleteItemConfirmation": { + "message": "確定要刪除此項目嗎?" + }, + "deletedItem": { + "message": "發送項目到垃圾桶" + }, + "overwritePasswordConfirmation": { + "message": "您確定要覆寫目前的密碼嗎?" + }, + "overwriteUsername": { + "message": "覆寫使用者名稱" + }, + "overwriteUsernameConfirmation": { + "message": "您確定要覆寫目前的使用者名稱嗎?" + }, + "noneFolder": { + "message": "(未分類)", + "description": "This is the folder for uncategorized items" + }, + "addFolder": { + "message": "新增資料夾" + }, + "editFolder": { + "message": "編輯資料夾" + }, + "regeneratePassword": { + "message": "重新產生密碼" + }, + "copyPassword": { + "message": "複製密碼" + }, + "copyUri": { + "message": "複製 URI" + }, + "copyVerificationCodeTotp": { + "message": "複製驗證碼(TOTP)" + }, + "length": { + "message": "長度" + }, + "numWords": { + "message": "字數" + }, + "wordSeparator": { + "message": "文字分隔字元" + }, + "capitalize": { + "message": "大寫", + "description": "Make the first letter of a work uppercase." + }, + "includeNumber": { + "message": "包含數字" + }, + "close": { + "message": "關閉" + }, + "minNumbers": { + "message": "最少數字位數" + }, + "minSpecial": { + "message": "最少符號位數", + "description": "Minimum Special Characters" + }, + "ambiguous": { + "message": "避免易混淆的字元" + }, + "searchCollection": { + "message": "搜尋集合" + }, + "searchFolder": { + "message": "搜尋資料夾" + }, + "searchFavorites": { + "message": "搜尋我的最愛" + }, + "searchType": { + "message": "搜尋類型", + "description": "Search item type" + }, + "newAttachment": { + "message": "新增附件" + }, + "deletedAttachment": { + "message": "附件已刪除" + }, + "deleteAttachmentConfirmation": { + "message": "確定要刪除此附件嗎?" + }, + "attachmentSaved": { + "message": "附件已儲存。" + }, + "file": { + "message": "檔案" + }, + "selectFile": { + "message": "選擇檔案。" + }, + "maxFileSize": { + "message": "檔案最大為 500MB。" + }, + "updateKey": { + "message": "更新加密金鑰前不能使用此功能。" + }, + "editedFolder": { + "message": "資料夾已編輯" + }, + "addedFolder": { + "message": "資料夾已新增" + }, + "deleteFolderConfirmation": { + "message": "您確定要刪除此資料夾嗎?" + }, + "deletedFolder": { + "message": "資料夾已刪除" + }, + "loginOrCreateNewAccount": { + "message": "登入或建立帳戶來存取您的安全密碼庫。" + }, + "createAccount": { + "message": "建立帳戶" + }, + "logIn": { + "message": "登入" + }, + "submit": { + "message": "送出" + }, + "masterPass": { + "message": "主密碼" + }, + "masterPassDesc": { + "message": "主密碼是您用於存取您的密碼庫的密碼。不要忘記主密碼,這一點非常重要。如果忘記了密碼,無法將其復原。" + }, + "masterPassHintDesc": { + "message": "主密碼提示可以在您忘記主密碼時幫助您回憶主密碼。" + }, + "reTypeMasterPass": { + "message": "重新輸入主密碼" + }, + "masterPassHint": { + "message": "主密碼提示(選用)" + }, + "settings": { + "message": "設定" + }, + "passwordHint": { + "message": "密碼提示" + }, + "enterEmailToGetHint": { + "message": "請輸入您的帳户電子郵件地址以接收主密碼提示。" + }, + "getMasterPasswordHint": { + "message": "取得主密碼提示" + }, + "emailRequired": { + "message": "必須填入電子郵件地址。" + }, + "invalidEmail": { + "message": "無效的電子郵件地址。" + }, + "masterPassRequired": { + "message": "必須填入主密碼。" + }, + "masterPassLength": { + "message": "主密碼需要至少 8 個字元。" + }, + "masterPassDoesntMatch": { + "message": "兩次填入的主密碼不一致。" + }, + "newAccountCreated": { + "message": "帳戶已建立!現在可以登入了。" + }, + "masterPassSent": { + "message": "已寄出包含您主密碼提示的電子郵件。" + }, + "unexpectedError": { + "message": "發生了未預期的錯誤。" + }, + "itemInformation": { + "message": "項目資訊" + }, + "noItemsInList": { + "message": "沒有可列出的項目。" + }, + "sendVerificationCode": { + "message": "傳送驗證碼至您的電子郵件信箱" + }, + "sendCode": { + "message": "傳送驗證碼" + }, + "codeSent": { + "message": "驗證碼已傳送" + }, + "verificationCode": { + "message": "驗證碼" + }, + "confirmIdentity": { + "message": "請先確認身分後再繼續。" + }, + "verificationCodeRequired": { + "message": "必須填入驗證碼。" + }, + "invalidVerificationCode": { + "message": "無效的驗證碼" + }, + "continue": { + "message": "繼續" + }, + "enterVerificationCodeApp": { + "message": "輸入驗證器應用程式提供的 6 位數驗證碼。" + }, + "enterVerificationCodeEmail": { + "message": "請輸入 6 位數驗證碼,我們已將其傳送至 $EMAIL$.", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "verificationCodeEmailSent": { + "message": "已傳送驗證電子郵件至 $EMAIL$。", + "placeholders": { + "email": { + "content": "$1", + "example": "example@gmail.com" + } + } + }, + "rememberMe": { + "message": "記住我" + }, + "sendVerificationCodeEmailAgain": { + "message": "再次傳送​​包含驗證碼的電子郵件" + }, + "useAnotherTwoStepMethod": { + "message": "使用另一種兩步驟登入方式" + }, + "insertYubiKey": { + "message": "將您的 YubiKey 插入電腦的 USB 連接埠,然後按一下它的按鈕。" + }, + "insertU2f": { + "message": "將您的安全鑰匙插入電腦的 USB 連接埠,然後按一下它的按鈕(如有的話)。" + }, + "recoveryCodeDesc": { + "message": "無法使用任何雙要素提供程式嗎?請使用您的復原代碼以停用您賬戶的所有雙要素提供程式。" + }, + "recoveryCodeTitle": { + "message": "復原代碼" + }, + "authenticatorAppTitle": { + "message": "驗證器應用程式" + }, + "authenticatorAppDesc": { + "message": "使用驗證器應用程式(如 Authy 或 Google Authenticator)產生基於時間的驗證碼。", + "description": "'Authy' and 'Google Authenticator' are product names and should not be translated." + }, + "yubiKeyTitle": { + "message": "YubiKey OTP 安全鑰匙" + }, + "yubiKeyDesc": { + "message": "使用 YubiKey 來存取您的帳戶。支援 YubiKey 4、4 Nano、4C、以及 NEO 裝置。" + }, + "duoDesc": { + "message": "使用 Duo Security 的 Duo Mobile 程式、SMS 、致電或 U2F 安全鑰匙進行驗證。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "duoOrganizationDesc": { + "message": "爲您的組織使用 Duo Security 的 Duo Mobile 程式、SMS、致電或 U2F 安全鑰匙進行驗證。", + "description": "'Duo Security' and 'Duo Mobile' are product names and should not be translated." + }, + "webAuthnTitle": { + "message": "FIDO2 WebAuthn" + }, + "webAuthnDesc": { + "message": "使用任何具有 WebAuthn 功能的安全金鑰來存取您的帳戶。" + }, + "emailTitle": { + "message": "電子郵件" + }, + "emailDesc": { + "message": "使用電子郵件傳送驗證碼給您。" + }, + "loginUnavailable": { + "message": "登入不可用" + }, + "noTwoStepProviders": { + "message": "此帳戶已啟用兩步驟登入,但是本裝置不支援已設定的兩步驟登入方式。" + }, + "noTwoStepProviders2": { + "message": "請新增可以更好地跨裝置的兩步驟登入方法(例如驗證器應用程式)。" + }, + "twoStepOptions": { + "message": "兩步驟登入選項" + }, + "selfHostedEnvironment": { + "message": "自我託管環境" + }, + "selfHostedEnvironmentFooter": { + "message": "指定您本地托管的 Bitwarden 安裝之基礎 URL。" + }, + "customEnvironment": { + "message": "自訂環境" + }, + "customEnvironmentFooter": { + "message": "適用於進階使用者。您可以單獨指定各個服務的基礎 URL。" + }, + "baseUrl": { + "message": "伺服器 URL" + }, + "apiUrl": { + "message": "API 伺服器 URL" + }, + "webVaultUrl": { + "message": "網頁版密碼庫伺服器 URL" + }, + "identityUrl": { + "message": "身分伺服器 URL" + }, + "notificationsUrl": { + "message": "通知伺服器 URL" + }, + "iconsUrl": { + "message": "圖示伺服器 URL" + }, + "environmentSaved": { + "message": "已儲存環境 URL。" + }, + "ok": { + "message": "確定" + }, + "yes": { + "message": "是" + }, + "no": { + "message": "否" + }, + "overwritePassword": { + "message": "覆寫密碼" + }, + "learnMore": { + "message": "了解更多" + }, + "featureUnavailable": { + "message": "功能無法使用" + }, + "loggedOut": { + "message": "已登出" + }, + "loginExpired": { + "message": "您的登入會話已過期。" + }, + "logOutConfirmation": { + "message": "您確定要登出嗎?" + }, + "logOut": { + "message": "登出" + }, + "addNewLogin": { + "message": "新增登入資料" + }, + "addNewItem": { + "message": "新增項目" + }, + "addNewFolder": { + "message": "新增資料夾" + }, + "view": { + "message": "檢視" + }, + "account": { + "message": "帳戶" + }, + "loading": { + "message": "正在載入..." + }, + "lockVault": { + "message": "鎖定密碼庫" + }, + "passwordGenerator": { + "message": "密碼產生器" + }, + "contactUs": { + "message": "聯絡我們" + }, + "getHelp": { + "message": "尋求協助" + }, + "fileBugReport": { + "message": "Bug 回報" + }, + "blog": { + "message": "部落格" + }, + "followUs": { + "message": "關注我們" + }, + "syncVault": { + "message": "同步密碼庫" + }, + "changeMasterPass": { + "message": "變更主密碼" + }, + "changeMasterPasswordConfirmation": { + "message": "您可以在 Bitwarden 網頁版密碼庫變更主密碼。現在要前往嗎?" + }, + "fingerprintPhrase": { + "message": "指紋短語", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "yourAccountsFingerprint": { + "message": "您帳戶的指紋短語", + "description": "A 'fingerprint phrase' is a unique word phrase (similar to a passphrase) that a user can use to authenticate their public key with another user, for the purposes of sharing." + }, + "goToWebVault": { + "message": "前往網頁版密碼庫" + }, + "getMobileApp": { + "message": "取得行動裝置應用程式" + }, + "getBrowserExtension": { + "message": "取得瀏覽器擴充套件" + }, + "syncingComplete": { + "message": "同步完成" + }, + "syncingFailed": { + "message": "同步失敗" + }, + "yourVaultIsLocked": { + "message": "您的密碼庫已鎖定。請驗證身分以繼續。" + }, + "unlock": { + "message": "解鎖" + }, + "loggedInAsOn": { + "message": "已經在 $HOSTNAME$ 使用 $EMAIL$ 身份登入。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + }, + "hostname": { + "content": "$2", + "example": "bitwarden.com" + } + } + }, + "invalidMasterPassword": { + "message": "無效的主密碼" + }, + "twoStepLoginConfirmation": { + "message": "兩步驟登入需要您從其他設備(例如安全鑰匙、驗證器程式、SMS、手機或電子郵件)來驗證您的登入,這使您的賬戶更加安全。兩步驟登入可以在 Bitwarden 網頁版密碼庫啟用。現在要前往嗎?" + }, + "twoStepLogin": { + "message": "兩步驟登入" + }, + "vaultTimeout": { + "message": "密碼庫逾時時間" + }, + "vaultTimeoutDesc": { + "message": "選擇密碼庫多久之後才會逾時並執行選取動作。" + }, + "immediately": { + "message": "立即" + }, + "tenSeconds": { + "message": "10 秒鐘" + }, + "twentySeconds": { + "message": "20 秒鐘" + }, + "thirtySeconds": { + "message": "30 秒鐘" + }, + "oneMinute": { + "message": "1 分鐘" + }, + "twoMinutes": { + "message": "2 分鐘" + }, + "fiveMinutes": { + "message": "5 分鐘" + }, + "fifteenMinutes": { + "message": "15 分鐘" + }, + "thirtyMinutes": { + "message": "30 分鐘" + }, + "oneHour": { + "message": "1 小時" + }, + "fourHours": { + "message": "4 小時" + }, + "onIdle": { + "message": "系統閒置時" + }, + "onSleep": { + "message": "系統睡眠時" + }, + "onLocked": { + "message": "系統鎖定時" + }, + "onRestart": { + "message": "重新啟動時" + }, + "never": { + "message": "永不" + }, + "security": { + "message": "安全" + }, + "clearClipboard": { + "message": "清除剪貼簿", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "clearClipboardDesc": { + "message": "自動清除剪貼簿中複製的值。", + "description": "Clipboard is the operating system thing where you copy/paste data to on your device." + }, + "disableFavicon": { + "message": "停用網站圖示" + }, + "disableFaviconDesc": { + "message": "在您密碼庫的每個登入資料旁顯示一個可辨識的圖示。" + }, + "enableMinToTray": { + "message": "最小化至系統匣圖示" + }, + "enableMinToTrayDesc": { + "message": "最小化視窗時,改為於系統匣中顯示一個圖示。" + }, + "enableMinToMenuBar": { + "message": "最小化至選單列" + }, + "enableMinToMenuBarDesc": { + "message": "最小化視窗時,改為於選單列顯示一個圖示。" + }, + "enableCloseToTray": { + "message": "關閉至系統匣圖示" + }, + "enableCloseToTrayDesc": { + "message": "關閉視窗時,改為於系統匣中顯示一個圖示。" + }, + "enableCloseToMenuBar": { + "message": "關閉至選單列" + }, + "enableCloseToMenuBarDesc": { + "message": "關閉視窗時,改為於選單列中顯示一個圖示。" + }, + "enableTray": { + "message": "啟用系統匣圖示" + }, + "enableTrayDesc": { + "message": "總是在系統匣中顯示圖示。" + }, + "startToTray": { + "message": "啟動至系統匣圖示" + }, + "startToTrayDesc": { + "message": "應用程式首次啟動時,只在系統匣顯示一個圖示。" + }, + "startToMenuBar": { + "message": "啟動到選單列" + }, + "startToMenuBarDesc": { + "message": "應用程式首次啟動時,只在選單列顯示一個圖示。" + }, + "openAtLogin": { + "message": "登入時自動啟動" + }, + "openAtLoginDesc": { + "message": "登入時自動啟動 Bitwarden 桌面應用程式。" + }, + "alwaysShowDock": { + "message": "總是在 Dock 中顯示" + }, + "alwaysShowDockDesc": { + "message": "即使最小化到選單列,也在 Docker 中顯示 Bitwarden 圖示。" + }, + "confirmTrayTitle": { + "message": "確認禁用系統匣" + }, + "confirmTrayDesc": { + "message": "禁用此設定也將禁用所有其他系統匣相關設定。" + }, + "language": { + "message": "語言" + }, + "languageDesc": { + "message": "變更應用程式的語言。需要重新啟動程式。" + }, + "theme": { + "message": "主題" + }, + "themeDesc": { + "message": "變更應用程式的主題色彩。" + }, + "dark": { + "message": "深色", + "description": "Dark color" + }, + "light": { + "message": "淺色", + "description": "Light color" + }, + "copy": { + "message": "複製", + "description": "Copy to clipboard" + }, + "checkForUpdates": { + "message": "檢查更新" + }, + "version": { + "message": "版本 $VERSION_NUM$", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "restartToUpdate": { + "message": "重新啟動以更新" + }, + "restartToUpdateDesc": { + "message": "版本 $VERSION_NUM$ 已準備好安裝。您必須重新啟動此應用程式才能完成安裝。要立即重新啟動並更新嗎?", + "placeholders": { + "version_num": { + "content": "$1", + "example": "1.2.3" + } + } + }, + "updateAvailable": { + "message": "有可用的更新" + }, + "updateAvailableDesc": { + "message": "發現新版本。您要現在下載嗎?" + }, + "restart": { + "message": "重新啟動" + }, + "later": { + "message": "稍後" + }, + "noUpdatesAvailable": { + "message": "沒有可用的更新,您目前使用的是最新版本。" + }, + "updateError": { + "message": "更新錯誤" + }, + "unknown": { + "message": "不詳" + }, + "copyUsername": { + "message": "複製使用者名稱" + }, + "copyNumber": { + "message": "複製號碼", + "description": "Copy credit card number" + }, + "copySecurityCode": { + "message": "複製安全代碼", + "description": "Copy credit card security code (CVV)" + }, + "premiumMembership": { + "message": "進階會員" + }, + "premiumManage": { + "message": "管理會員資格" + }, + "premiumManageAlert": { + "message": "您可以在 Bitwarden 網頁版密碼庫管理你的會員資格。現在要前往嗎?" + }, + "premiumRefresh": { + "message": "刷新會員資格" + }, + "premiumNotCurrentMember": { + "message": "您目前不是進階會員。" + }, + "premiumSignUpAndGet": { + "message": "注冊成為進階會員並將獲得:" + }, + "premiumSignUpStorage": { + "message": "用於檔案附件的 1 GB 的加密檔案儲存空間。" + }, + "premiumSignUpTwoStep": { + "message": "YubiKey、FIDO U2F 和 Duo 等額外的兩步驟登入選項。" + }, + "premiumSignUpReports": { + "message": "密碼健康度檢查、提供帳戶體檢以及資料外洩報告,以保障您的密碼庫安全。" + }, + "premiumSignUpTotp": { + "message": "用於登入您的密碼庫的 TOTP 驗證碼 (2FA) 產生器。" + }, + "premiumSignUpSupport": { + "message": "優先客戶支援。" + }, + "premiumSignUpFuture": { + "message": "未來會增加更多進階功能,敬請期待!" + }, + "premiumPurchase": { + "message": "購買進階會員資格" + }, + "premiumPurchaseAlert": { + "message": "您可以在 Bitwarden 網頁版密碼庫購買進階會員資格。現在要前往嗎?" + }, + "premiumCurrentMember": { + "message": "您目前是進階會員!" + }, + "premiumCurrentMemberThanks": { + "message": "感謝您支持 Bitwarden 。" + }, + "premiumPrice": { + "message": "每年只需 $PRICE$!", + "placeholders": { + "price": { + "content": "$1", + "example": "$10" + } + } + }, + "refreshComplete": { + "message": "刷新完成" + }, + "passwordHistory": { + "message": "密碼歷史記錄" + }, + "clear": { + "message": "清除", + "description": "To clear something out. example: To clear browser history." + }, + "noPasswordsInList": { + "message": "沒有可列出的密碼。" + }, + "undo": { + "message": "復原" + }, + "redo": { + "message": "重做" + }, + "cut": { + "message": "剪切", + "description": "Cut to clipboard" + }, + "paste": { + "message": "粘貼", + "description": "Paste from clipboard" + }, + "selectAll": { + "message": "全選" + }, + "zoomIn": { + "message": "放大" + }, + "zoomOut": { + "message": "縮小" + }, + "resetZoom": { + "message": "重設縮放" + }, + "toggleFullScreen": { + "message": "切換全螢幕" + }, + "reload": { + "message": "重新載入" + }, + "toggleDevTools": { + "message": "切換開發人員工具" + }, + "minimize": { + "message": "最小化", + "description": "Minimize window" + }, + "zoom": { + "message": "縮放" + }, + "bringAllToFront": { + "message": "全部移至最上層", + "description": "Bring all windows to front (foreground)" + }, + "aboutBitwarden": { + "message": "關於 Bitwarden" + }, + "services": { + "message": "服務" + }, + "hideBitwarden": { + "message": "隱藏 Bitwarden" + }, + "hideOthers": { + "message": "隱藏其他" + }, + "showAll": { + "message": "顯示全部" + }, + "quitBitwarden": { + "message": "結束 Bitwarden" + }, + "valueCopied": { + "message": "$VALUE$ 已複製", + "description": "Value has been copied to the clipboard.", + "placeholders": { + "value": { + "content": "$1", + "example": "Password" + } + } + }, + "help": { + "message": "說明" + }, + "window": { + "message": "視窗" + }, + "checkPassword": { + "message": "檢查密碼是否已外洩。" + }, + "passwordExposed": { + "message": "此密碼已外洩了 $VALUE$ 次,應立即變更密碼。", + "placeholders": { + "value": { + "content": "$1", + "example": "2" + } + } + }, + "passwordSafe": { + "message": "任何已知的外洩密碼資料庫中都沒有此密碼,它目前是安全的。" + }, + "baseDomain": { + "message": "基底網域", + "description": "Domain name. Ex. website.com" + }, + "domainName": { + "message": "網域名稱", + "description": "Domain name. Ex. website.com" + }, + "host": { + "message": "主機", + "description": "A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'." + }, + "exact": { + "message": "完全相符" + }, + "startsWith": { + "message": "開始於" + }, + "regEx": { + "message": "規則運算式", + "description": "A programming term, also known as 'RegEx'." + }, + "matchDetection": { + "message": "一致性偵測", + "description": "URI match detection for auto-fill." + }, + "defaultMatchDetection": { + "message": "預設一致性偵測", + "description": "Default URI match detection for auto-fill." + }, + "toggleOptions": { + "message": "切換選項" + }, + "organization": { + "message": "組織", + "description": "An entity of multiple related people (ex. a team or business organization)." + }, + "default": { + "message": "預設" + }, + "exit": { + "message": "結束" + }, + "showHide": { + "message": "顯示/隱藏", + "description": "Text for a button that toggles the visibility of the window. Shows the window when it is hidden or hides the window if it is currently open." + }, + "hideToTray": { + "message": "隱藏至系統匣" + }, + "alwaysOnTop": { + "message": "總在最上層", + "description": "Application window should always stay on top of other windows" + }, + "dateUpdated": { + "message": "更新於", + "description": "ex. Date this item was updated" + }, + "datePasswordUpdated": { + "message": "密碼更新於", + "description": "ex. Date this password was updated" + }, + "exportVault": { + "message": "匯出密碼庫" + }, + "fileFormat": { + "message": "檔案格式" + }, + "warning": { + "message": "警告", + "description": "WARNING (should stay in capitalized letters if the language permits)" + }, + "confirmVaultExport": { + "message": "確認匯出密碼庫" + }, + "exportWarningDesc": { + "message": "此匯出包含未加密格式的密碼庫檔案。您不應將它存放或經由不安全的方式(例如電子郵件)傳送。用完後請立即將它刪除。" + }, + "encExportKeyWarningDesc": { + "message": "將使用您帳戶的加密金鑰來加密匯出資料,若您更新了帳戶的加密金鑰,請重新匯出,才有辦法解密匯出的檔案。" + }, + "encExportAccountWarningDesc": { + "message": "每個 Bitwarden 使用者帳戶的帳戶加密金鑰都不相同,因此無法將已加密匯出的檔案匯入至不同帳戶中。" + }, + "noOrganizationsList": { + "message": "您沒有加入任何組織。組織允許您與其他使用者安全地共用項目。" + }, + "noCollectionsInList": { + "message": "沒有可列出的集合。" + }, + "ownership": { + "message": "所有權" + }, + "whoOwnsThisItem": { + "message": "誰擁有這個項目?" + }, + "strong": { + "message": "強", + "description": "ex. A strong password. Scale: Weak -> Good -> Strong" + }, + "good": { + "message": "好", + "description": "ex. A good password. Scale: Weak -> Good -> Strong" + }, + "weak": { + "message": "弱", + "description": "ex. A weak password. Scale: Weak -> Good -> Strong" + }, + "weakMasterPassword": { + "message": "主密碼強度太弱" + }, + "weakMasterPasswordDesc": { + "message": "您設定的主密碼很脆弱。您應該使用高強度的密碼(或密碼短語)來正確保護您的 bitwarden 帳戶。仍要使用這組主密碼嗎?" + }, + "pin": { + "message": "PIN 碼", + "description": "PIN code. Ex. The short code (often numeric) that you use to unlock a device." + }, + "unlockWithPin": { + "message": "使用 PIN 碼解鎖" + }, + "setYourPinCode": { + "message": "設定您用來解鎖 Bitwarden 的 PIN 碼。您的 PIN 設定將在您完全結束本應用程式時被重設。" + }, + "pinRequired": { + "message": "需要 PIN 碼。" + }, + "invalidPin": { + "message": "無效的 PIN 碼。" + }, + "unlockWithWindowsHello": { + "message": "使用 Windows Hello 解鎖" + }, + "windowsHelloConsentMessage": { + "message": "驗證 Bitwarden。" + }, + "unlockWithTouchId": { + "message": "使用 Touch ID 解鎖" + }, + "touchIdConsentMessage": { + "message": "解鎖您的密碼庫" + }, + "noAutoPromptWindowsHello": { + "message": "啟動時不要提示使用 Windows Hello。" + }, + "noAutoPromptTouchId": { + "message": "啟動時不要提示使用 Touch ID。" + }, + "lockWithMasterPassOnRestart": { + "message": "重啟後使用主密碼鎖定" + }, + "preferences": { + "message": "偏好設定" + }, + "enableMenuBar": { + "message": "啟用選單列圖示" + }, + "enableMenuBarDesc": { + "message": "總是在選單列中顯示圖示。" + }, + "hideToMenuBar": { + "message": "隱藏至選單列" + }, + "selectOneCollection": { + "message": "您必須至少選擇一個集合。" + }, + "premiumUpdated": { + "message": "您已升級至進階會員。" + }, + "restore": { + "message": "還原" + }, + "premiumManageAlertAppStore": { + "message": "可到 App Store 管理訂閱內容。您現在要前往 App Store 嗎?" + }, + "legal": { + "message": "法律條款", + "description": "Noun. As in 'legal documents', like our terms of service and privacy policy." + }, + "termsOfService": { + "message": "服務條款" + }, + "privacyPolicy": { + "message": "隱私權政策" + }, + "unsavedChangesConfirmation": { + "message": "您確定要離開嗎?現在離開將不會儲存目前的資訊。" + }, + "unsavedChangesTitle": { + "message": "變更未被儲存" + }, + "clone": { + "message": "複製" + }, + "passwordGeneratorPolicyInEffect": { + "message": "一個或多個組織原則正影響密碼產生器設定。" + }, + "vaultTimeoutAction": { + "message": "密碼庫逾時動作" + }, + "vaultTimeoutActionLockDesc": { + "message": "鎖定密碼庫後需要重新輸入主密碼才能再次存取。" + }, + "vaultTimeoutActionLogOutDesc": { + "message": "登出密碼庫後需要重新驗證才能再次存取。" + }, + "lock": { + "message": "鎖定", + "description": "Verb form: to make secure or inaccesible by" + }, + "trash": { + "message": "垃圾桶", + "description": "Noun: a special folder to hold deleted items" + }, + "searchTrash": { + "message": "搜尋垃圾桶" + }, + "permanentlyDeleteItem": { + "message": "永久刪除項目" + }, + "permanentlyDeleteItemConfirmation": { + "message": "您確定要永久刪除此項目嗎?" + }, + "permanentlyDeletedItem": { + "message": "項目已永久刪除" + }, + "restoreItem": { + "message": "還原項目" + }, + "restoreItemConfirmation": { + "message": "您確定要恢復此項目嗎?" + }, + "restoredItem": { + "message": "項目已還原" + }, + "permanentlyDelete": { + "message": "永久刪除" + }, + "vaultTimeoutLogOutConfirmation": { + "message": "選擇登出將會在密碼庫逾時後移除對密碼庫的所有存取權限,若要重新驗證則需連線網路。確定要使用此設定嗎?" + }, + "vaultTimeoutLogOutConfirmationTitle": { + "message": "逾時動作確認" + }, + "enterpriseSingleSignOn": { + "message": "企業單一登入" + }, + "setMasterPassword": { + "message": "設定主密碼" + }, + "ssoCompleteRegistration": { + "message": "要完成 SSO 登入設定,請設定一組主密碼以存取和保護您的密碼庫。" + }, + "newMasterPass": { + "message": "新的主密碼" + }, + "confirmNewMasterPass": { + "message": "確認新的主密碼" + }, + "masterPasswordPolicyInEffect": { + "message": "一個或多個組織原則要求您的主密碼須符合下列條件:" + }, + "policyInEffectMinComplexity": { + "message": "最小複雜度為 $SCORE$", + "placeholders": { + "score": { + "content": "$1", + "example": "4" + } + } + }, + "policyInEffectMinLength": { + "message": "最小長度為 $LENGTH$", + "placeholders": { + "length": { + "content": "$1", + "example": "14" + } + } + }, + "policyInEffectUppercase": { + "message": "至少包含一個大寫字元" + }, + "policyInEffectLowercase": { + "message": "至少包含一個小寫字元" + }, + "policyInEffectNumbers": { + "message": "至少包含一個數字" + }, + "policyInEffectSpecial": { + "message": "至少包含一個下列特殊字元:$CHARS$", + "placeholders": { + "chars": { + "content": "$1", + "example": "!@#$%^&*" + } + } + }, + "masterPasswordPolicyRequirementsNotMet": { + "message": "新的主密碼不符合原則要求。" + }, + "acceptPolicies": { + "message": "選中此選取框,代表您同意下列項目:" + }, + "acceptPoliciesError": { + "message": "尚未接受服務條款與隱私權保護政策。" + }, + "enableBrowserIntegration": { + "message": "開啟瀏覽器整合" + }, + "enableBrowserIntegrationDesc": { + "message": "瀏覽器整合用於在瀏覽器中提供生物特徵辨識。" + }, + "browserIntegrationMasOnlyTitle": { + "message": "不支援瀏覽器整合" + }, + "browserIntegrationMasOnlyDesc": { + "message": "很遺憾,目前僅 Mac App Store 版本支援瀏覽器整合功能。" + }, + "browserIntegrationWindowsStoreTitle": { + "message": "不支援瀏覽器整合" + }, + "browserIntegrationWindowsStoreDesc": { + "message": "很遺憾,目前的 Windows Store 版本尚不支援瀏覽器整合功能。" + }, + "enableBrowserIntegrationFingerprint": { + "message": "要求瀏覽器整合驗證" + }, + "enableBrowserIntegrationFingerprintDesc": { + "message": "在您的桌面和瀏覽器閒建立連綫時,要求驗證指紋短語以實現一個額外的安全層。此選項啓用後,每次建立連綫都需要使用者干預和驗證。" + }, + "approve": { + "message": "核准" + }, + "verifyBrowserTitle": { + "message": "確認與瀏覽器間的連線" + }, + "verifyBrowserDesc": { + "message": "請確保顯示的指紋與瀏覽器擴充套件中顯示的指紋一致。" + }, + "biometricsNotEnabledTitle": { + "message": "生物特徵辨識未啟用" + }, + "biometricsNotEnabledDesc": { + "message": "需先在桌面應用程式的設定中啟用生物特徵辨識,才能使用瀏覽器的生物特徵辨識。" + }, + "personalOwnershipSubmitError": { + "message": "由於某個企業原則,您被限制為儲存項目到您的個人密碼庫。將擁有權變更為組織,並從可用的集合中選擇。" + }, + "hintEqualsPassword": { + "message": "密碼提示不能與您的密碼相同。" + }, + "personalOwnershipPolicyInEffect": { + "message": "組織原則正在影響您的擁有權選項。" + }, + "allSends": { + "message": "所有 Send", + "description": "'Sends' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTypeFile": { + "message": "檔案" + }, + "sendTypeText": { + "message": "文字" + }, + "searchSends": { + "message": "搜尋 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editSend": { + "message": "編輯 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "myVault": { + "message": "密碼庫" + }, + "text": { + "message": "文字" + }, + "deletionDate": { + "message": "刪除日期" + }, + "deletionDateDesc": { + "message": "此 Send 將在指定的日期和時間後被永久刪除。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "expirationDate": { + "message": "逾期日期" + }, + "expirationDateDesc": { + "message": "如果設定此選項,對此 Send 的存取將在指定的日期和時間後逾期。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "maxAccessCount": { + "message": "最大存取次數" + }, + "maxAccessCountDesc": { + "message": "如果設定此選項,當達到最大存取次數時,使用者將無法再次存取此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "currentAccessCount": { + "message": "目前存取次數" + }, + "disableSend": { + "message": "停用此 Send 以阻止任何人存取它。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendPasswordDesc": { + "message": "可選。使用者需提供密碼才能存取此 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendNotesDesc": { + "message": "關於此 Send 的私人備註。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLink": { + "message": "Send 連結", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendLinkLabel": { + "message": "Send 連結", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "textHiddenByDefault": { + "message": "存取此 Send 時,預設隱藏文字内容", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createdSend": { + "message": "Send 已創建", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "editedSend": { + "message": "Send 已編輯", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "deletedSend": { + "message": "Send 已刪除", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "newPassword": { + "message": "新密碼" + }, + "whatTypeOfSend": { + "message": "這是什麽類型的 Send?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "createSend": { + "message": "創建 Send", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendTextDesc": { + "message": "您想要傳送的文字。" + }, + "sendFileDesc": { + "message": "您想要傳送的檔案。" + }, + "days": { + "message": "$DAYS$ 天", + "placeholders": { + "days": { + "content": "$1", + "example": "1" + } + } + }, + "oneDay": { + "message": "1 天" + }, + "custom": { + "message": "自訂" + }, + "deleteSendConfirmation": { + "message": "您確定要刪除此 Send 嗎?", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkToClipboard": { + "message": "複製 Send 連結到剪貼簿", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copySendLinkOnSave": { + "message": "储存時複製連結到剪貼簿以便分享此 Send。" + }, + "sendDisabled": { + "message": "Send 已停用", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "sendDisabledWarning": { + "message": "由於企業原則限制,您只能刪除現有的 Send。", + "description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated." + }, + "copyLink": { + "message": "複製連結" + }, + "disabled": { + "message": "已停用" + }, + "maxAccessCountReached": { + "message": "已達最大存取次數" + }, + "expired": { + "message": "已逾期" + }, + "pendingDeletion": { + "message": "等待刪除" + }, + "webAuthnAuthenticate": { + "message": "驗證 WebAuthn" + }, + "hideEmail": { + "message": "對收件人隱藏我的電子郵件位址。" + }, + "sendOptionsPolicyInEffect": { + "message": "一個或多個組織原則正影響您的 Send 選項。" + }, + "emailVerificationRequired": { + "message": "需要驗證電子郵件" + }, + "emailVerificationRequiredDesc": { + "message": "必須驗證您的電子郵件才能使用此功能。" + }, + "passwordPrompt": { + "message": "重新詢問主密碼" + }, + "passwordConfirmation": { + "message": "確認主密碼" + }, + "passwordConfirmationDesc": { + "message": "此操作受到保護。若要繼續,請重新輸入您的主密碼以驗證您的身份。" + }, + "updatedMasterPassword": { + "message": "已更新主密碼" + }, + "updateMasterPassword": { + "message": "更新主密碼" + }, + "updateMasterPasswordWarning": { + "message": "您的主密碼最近被您的組織管理者變更過。要存取密碼庫,您必須現在更新主密碼。繼續操作會登出目前的登入階段,要求您重新登入。其他裝置上使用中的登入階段可能持續最長一個小時。" + }, + "hours": { + "message": "小時" + }, + "minutes": { + "message": "分鐘" + }, + "vaultTimeoutPolicyInEffect": { + "message": "您的組織原則正在影響您的密碼庫逾時時間。密碼庫逾時時間最多可以設定到 $HOURS$ 小時 $MINUTES$ 分鐘。", + "placeholders": { + "hours": { + "content": "$1", + "example": "5" + }, + "minutes": { + "content": "$2", + "example": "5" + } + } + }, + "vaultTimeoutTooLarge": { + "message": "您的密碼庫逾時時間超過組織設定的限制。" + }, + "resetPasswordPolicyAutoEnroll": { + "message": "自動註冊" + }, + "resetPasswordAutoEnrollInviteWarning": { + "message": "此組織有一個可以為您自動註冊密碼重設的企業原則。註冊後將允許組織管理員變更您的主密碼。" + }, + "vaultExportDisabled": { + "message": "密碼庫匯出已停用" + }, + "personalVaultExportPolicyInEffect": { + "message": "一個或多個組織原則禁止您匯出個人密碼庫。" + }, + "addAccount": { + "message": "新增帳戶" + }, + "removeMasterPassword": { + "message": "移除主密碼" + }, + "removedMasterPassword": { + "message": "主密碼已移除。" + }, + "convertOrganizationEncryptionDesc": { + "message": "$ORGANIZATION$ 使用自我托管金輪伺服器 SSO。這個组织的成員登入時将不再需要主密碼。", + "placeholders": { + "organization": { + "content": "$1", + "example": "My Org Name" + } + } + }, + "leaveOrganization": { + "message": "離開組織" + }, + "leaveOrganizationConfirmation": { + "message": "您確定要離開這個組織嗎?" + }, + "leftOrganization": { + "message": "您已離開此組織。" + }, + "ssoKeyConnectorUnavailable": { + "message": "無法連線到 Key Connector。請稍後再試。" + }, + "lockAllVaults": { + "message": "鎖定所有密碼庫" + }, + "accountLimitReached": { + "message": "最多只能同時登入 5 隻帳戶。" + }, + "accountPreferences": { + "message": "偏好設定" + }, + "appPreferences": { + "message": "應用程式設定(所有帳戶)" + }, + "accountSwitcherLimitReached": { + "message": "已達帳戶數量上限。登出一個帳戶後再加入其他的帳戶。" + }, + "settingsTitle": { + "message": "$EMAIL$ 的應用程式設定", + "placeholders": { + "email": { + "content": "$1", + "example": "jdoe@example.com" + } + } + }, + "switchAccount": { + "message": "切換帳戶" + }, + "options": { + "message": "選項" + }, + "sessionTimeout": { + "message": "您的登入階段已逾時,請返回並嘗試重新登入。" + }, + "exportingPersonalVaultTitle": { + "message": "匯出個人密碼庫" + }, + "exportingPersonalVaultDescription": { + "message": "只會匯出與 $EMAIL$ 關聯的個人密碼庫。組織密碼庫的項目不包含在內。", + "placeholders": { + "email": { + "content": "$1", + "example": "name@example.com" + } + } + }, + "generator": { + "message": "產生器" + }, + "whatWouldYouLikeToGenerate": { + "message": "您想要產生什麼?" + }, + "passwordType": { + "message": "密碼類型" + }, + "regenerateUsername": { + "message": "重新產生使用者名稱" + }, + "generateUsername": { + "message": "產生使用者名稱" + }, + "usernameType": { + "message": "使用者名稱類型" + }, + "plusAddressedEmail": { + "message": "加號地址電子郵件" + }, + "plusAddressedEmailDesc": { + "message": "使用您的電子郵件提供者的子地址功能。" + }, + "catchallEmail": { + "message": "Catch-all 電子郵件" + }, + "catchallEmailDesc": { + "message": "使用您的網域配置的 Catch-all 收件匣。" + }, + "random": { + "message": "隨機" + }, + "randomWord": { + "message": "隨機單字" + }, + "websiteName": { + "message": "網站名稱" + }, + "service": { + "message": "服務" + } +} diff --git a/apps/desktop/src/main.ts b/apps/desktop/src/main.ts new file mode 100644 index 0000000000..66cc06a118 --- /dev/null +++ b/apps/desktop/src/main.ts @@ -0,0 +1,218 @@ +import * as path from "path"; + +import { app } from "electron"; + +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { StateService } from "jslib-common/services/state.service"; +import { ElectronLogService } from "jslib-electron/services/electronLog.service"; +import { ElectronMainMessagingService } from "jslib-electron/services/electronMainMessaging.service"; +import { ElectronStorageService } from "jslib-electron/services/electronStorage.service"; +import { TrayMain } from "jslib-electron/tray.main"; +import { UpdaterMain } from "jslib-electron/updater.main"; +import { WindowMain } from "jslib-electron/window.main"; + +import { BiometricMain } from "./main/biometric/biometric.main"; +import { DesktopCredentialStorageListener } from "./main/desktopCredentialStorageListener"; +import { MenuMain } from "./main/menu/menu.main"; +import { MessagingMain } from "./main/messaging.main"; +import { NativeMessagingMain } from "./main/nativeMessaging.main"; +import { PowerMonitorMain } from "./main/powerMonitor.main"; +import { Account } from "./models/account"; +import { I18nService } from "./services/i18n.service"; + +export class Main { + logService: ElectronLogService; + i18nService: I18nService; + storageService: ElectronStorageService; + messagingService: ElectronMainMessagingService; + stateService: StateService; + desktopCredentialStorageListener: DesktopCredentialStorageListener; + + windowMain: WindowMain; + messagingMain: MessagingMain; + updaterMain: UpdaterMain; + menuMain: MenuMain; + powerMonitorMain: PowerMonitorMain; + trayMain: TrayMain; + biometricMain: BiometricMain; + nativeMessagingMain: NativeMessagingMain; + + constructor() { + // Set paths for portable builds + let appDataPath = null; + if (process.env.BITWARDEN_APPDATA_DIR != null) { + appDataPath = process.env.BITWARDEN_APPDATA_DIR; + } else if (process.platform === "win32" && process.env.PORTABLE_EXECUTABLE_DIR != null) { + appDataPath = path.join(process.env.PORTABLE_EXECUTABLE_DIR, "bitwarden-appdata"); + } else if (process.platform === "linux" && process.env.SNAP_USER_DATA != null) { + appDataPath = path.join(process.env.SNAP_USER_DATA, "appdata"); + } + + app.on("ready", () => { + // on ready stuff... + }); + + if (appDataPath != null) { + app.setPath("userData", appDataPath); + } + app.setPath("logs", path.join(app.getPath("userData"), "logs")); + + const args = process.argv.slice(1); + const watch = args.some((val) => val === "--watch"); + + if (watch) { + // eslint-disable-next-line + require("electron-reload")(__dirname, {}); + } + + this.logService = new ElectronLogService(null, app.getPath("userData")); + this.i18nService = new I18nService("en", "./locales/"); + + const storageDefaults: any = {}; + // Default vault timeout to "on restart", and action to "lock" + storageDefaults["global.vaultTimeout"] = -1; + storageDefaults["global.vaultTimeoutAction"] = "lock"; + this.storageService = new ElectronStorageService(app.getPath("userData"), storageDefaults); + + // TODO: this state service will have access to on disk storage, but not in memory storage. + // If we could get this to work using the stateService singleton that the rest of the app uses we could save + // ourselves from some hacks, like having to manually update the app menu vs. the menu subscribing to events. + this.stateService = new StateService( + this.storageService, + null, + this.logService, + null, + new StateFactory(GlobalState, Account), + false // Do not use disk caching because this will get out of sync with the renderer service + ); + + this.windowMain = new WindowMain( + this.stateService, + this.logService, + true, + undefined, + undefined, + (arg) => this.processDeepLink(arg), + (win) => this.trayMain.setupWindowListeners(win) + ); + this.messagingMain = new MessagingMain(this, this.stateService); + this.updaterMain = new UpdaterMain( + this.i18nService, + this.windowMain, + "desktop", + null, + null, + null, + "bitwarden" + ); + this.menuMain = new MenuMain(this); + this.powerMonitorMain = new PowerMonitorMain(this); + this.trayMain = new TrayMain(this.windowMain, this.i18nService, this.stateService); + + this.messagingService = new ElectronMainMessagingService(this.windowMain, (message) => { + this.messagingMain.onMessage(message); + }); + + if (process.platform === "win32") { + // eslint-disable-next-line + const BiometricWindowsMain = require("./main/biometric/biometric.windows.main").default; + this.biometricMain = new BiometricWindowsMain( + this.i18nService, + this.windowMain, + this.stateService, + this.logService + ); + } else if (process.platform === "darwin") { + // eslint-disable-next-line + const BiometricDarwinMain = require("./main/biometric/biometric.darwin.main").default; + this.biometricMain = new BiometricDarwinMain(this.i18nService, this.stateService); + } + + this.desktopCredentialStorageListener = new DesktopCredentialStorageListener( + "Bitwarden", + this.biometricMain + ); + + this.nativeMessagingMain = new NativeMessagingMain( + this.logService, + this.windowMain, + app.getPath("userData"), + app.getPath("exe") + ); + } + + bootstrap() { + this.desktopCredentialStorageListener.init(); + this.windowMain.init().then( + async () => { + const locale = await this.stateService.getLocale(); + await this.i18nService.init(locale != null ? locale : app.getLocale()); + this.messagingMain.init(); + this.menuMain.init(); + await this.trayMain.init("Bitwarden", [ + { + label: this.i18nService.t("lockVault"), + enabled: false, + id: "lockVault", + click: () => this.messagingService.send("lockVault"), + }, + ]); + if (await this.stateService.getEnableStartToTray()) { + this.trayMain.hideToTray(); + } + this.powerMonitorMain.init(); + await this.updaterMain.init(); + if (this.biometricMain != null) { + await this.biometricMain.init(); + } + + if (await this.stateService.getEnableBrowserIntegration()) { + this.nativeMessagingMain.listen(); + } + + app.removeAsDefaultProtocolClient("bitwarden"); + if (process.env.NODE_ENV === "development" && process.platform === "win32") { + // Fix development build on Windows requirering a different protocol client + app.setAsDefaultProtocolClient("bitwarden", process.execPath, [ + process.argv[1], + path.resolve(process.argv[2]), + ]); + } else { + app.setAsDefaultProtocolClient("bitwarden"); + } + + // Process protocol for macOS + app.on("open-url", (event, url) => { + event.preventDefault(); + this.processDeepLink([url]); + }); + + // Handle window visibility events + this.windowMain.win.on("hide", () => { + this.messagingService.send("windowHidden"); + }); + this.windowMain.win.on("minimize", () => { + this.messagingService.send("windowHidden"); + }); + }, + (e: any) => { + // eslint-disable-next-line + console.error(e); + } + ); + } + + private processDeepLink(argv: string[]): void { + argv + .filter((s) => s.indexOf("bitwarden://") === 0) + .forEach((s) => { + const url = new URL(s); + const code = url.searchParams.get("code"); + const receivedState = url.searchParams.get("state"); + if (code != null && receivedState != null) { + this.messagingService.send("ssoCallback", { code: code, state: receivedState }); + } + }); + } +} diff --git a/apps/desktop/src/main/biometric/biometric.darwin.main.ts b/apps/desktop/src/main/biometric/biometric.darwin.main.ts new file mode 100644 index 0000000000..03ee546033 --- /dev/null +++ b/apps/desktop/src/main/biometric/biometric.darwin.main.ts @@ -0,0 +1,36 @@ +import { ipcMain, systemPreferences } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +import { BiometricMain } from "../biometric/biometric.main"; + +export default class BiometricDarwinMain implements BiometricMain { + isError = false; + + constructor(private i18nservice: I18nService, private stateService: StateService) {} + + async init() { + await this.stateService.setEnableBiometric(await this.supportsBiometric()); + await this.stateService.setBiometricText("unlockWithTouchId"); + await this.stateService.setNoAutoPromptBiometricsText("noAutoPromptTouchId"); + + // eslint-disable-next-line + ipcMain.on("biometric", async (event: any, message: any) => { + event.returnValue = await this.authenticateBiometric(); + }); + } + + supportsBiometric(): Promise { + return Promise.resolve(systemPreferences.canPromptTouchID()); + } + + async authenticateBiometric(): Promise { + try { + await systemPreferences.promptTouchID(this.i18nservice.t("touchIdConsentMessage")); + return true; + } catch { + return false; + } + } +} diff --git a/apps/desktop/src/main/biometric/biometric.main.ts b/apps/desktop/src/main/biometric/biometric.main.ts new file mode 100644 index 0000000000..a8557c4032 --- /dev/null +++ b/apps/desktop/src/main/biometric/biometric.main.ts @@ -0,0 +1,6 @@ +export abstract class BiometricMain { + isError: boolean; + init: () => Promise; + supportsBiometric: () => Promise; + authenticateBiometric: () => Promise; +} diff --git a/apps/desktop/src/main/biometric/biometric.windows.main.ts b/apps/desktop/src/main/biometric/biometric.windows.main.ts new file mode 100644 index 0000000000..aac4f4dc6d --- /dev/null +++ b/apps/desktop/src/main/biometric/biometric.windows.main.ts @@ -0,0 +1,146 @@ +import { ipcMain } from "electron"; +import forceFocus from "forcefocus"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { WindowMain } from "jslib-electron/window.main"; + +import { BiometricMain } from "src/main/biometric/biometric.main"; + +export default class BiometricWindowsMain implements BiometricMain { + isError = false; + + private windowsSecurityCredentialsUiModule: any; + + constructor( + private i18nservice: I18nService, + private windowMain: WindowMain, + private stateService: StateService, + private logService: LogService + ) {} + + async init() { + this.windowsSecurityCredentialsUiModule = this.getWindowsSecurityCredentialsUiModule(); + let supportsBiometric = false; + try { + supportsBiometric = await this.supportsBiometric(); + } catch { + // store error state so we can let the user know on the settings page + this.isError = true; + } + await this.stateService.setEnableBiometric(supportsBiometric); + await this.stateService.setBiometricText("unlockWithWindowsHello"); + await this.stateService.setNoAutoPromptBiometricsText("noAutoPromptWindowsHello"); + + ipcMain.on("biometric", async (event: any, message: any) => { + event.returnValue = await this.authenticateBiometric(); + }); + } + + async supportsBiometric(): Promise { + const availability = await this.checkAvailabilityAsync(); + + return this.getAllowedAvailabilities().includes(availability); + } + + async authenticateBiometric(): Promise { + const module = this.getWindowsSecurityCredentialsUiModule(); + if (module == null) { + return false; + } + + const verification = await this.requestVerificationAsync( + this.i18nservice.t("windowsHelloConsentMessage") + ); + + return verification === module.UserConsentVerificationResult.verified; + } + + getWindowsSecurityCredentialsUiModule(): any { + try { + if (this.windowsSecurityCredentialsUiModule == null && this.getWindowsMajorVersion() >= 10) { + this.windowsSecurityCredentialsUiModule = require("@nodert-win10-rs4/windows.security.credentials.ui"); + } + return this.windowsSecurityCredentialsUiModule; + } catch { + this.isError = true; + } + return null; + } + + async checkAvailabilityAsync(): Promise { + const module = this.getWindowsSecurityCredentialsUiModule(); + if (module != null) { + // eslint-disable-next-line + return new Promise((resolve, reject) => { + try { + module.UserConsentVerifier.checkAvailabilityAsync((error: Error, result: any) => { + if (error) { + return resolve(null); + } + return resolve(result); + }); + } catch { + this.isError = true; + return resolve(null); + } + }); + } + return Promise.resolve(null); + } + + async requestVerificationAsync(message: string): Promise { + const module = this.getWindowsSecurityCredentialsUiModule(); + if (module != null) { + return new Promise((resolve, reject) => { + try { + module.UserConsentVerifier.requestVerificationAsync( + message, + (error: Error, result: any) => { + if (error) { + return resolve(null); + } + return resolve(result); + } + ); + + forceFocus.focusWindow(this.windowMain.win); + } catch (error) { + this.isError = true; + return reject(error); + } + }); + } + return Promise.resolve(null); + } + + getAllowedAvailabilities(): any[] { + try { + const module = this.getWindowsSecurityCredentialsUiModule(); + if (module != null) { + return [ + module.UserConsentVerifierAvailability.available, + module.UserConsentVerifierAvailability.deviceBusy, + ]; + } + } catch { + /*Ignore error*/ + } + return []; + } + + getWindowsMajorVersion(): number { + if (process.platform !== "win32") { + return -1; + } + try { + // eslint-disable-next-line + const version = require("os").release(); + return Number.parseInt(version.split(".")[0], 10); + } catch { + this.logService.error("Unable to resolve windows major version number"); + } + return -1; + } +} diff --git a/apps/desktop/src/main/desktopCredentialStorageListener.ts b/apps/desktop/src/main/desktopCredentialStorageListener.ts new file mode 100644 index 0000000000..1c6d06b019 --- /dev/null +++ b/apps/desktop/src/main/desktopCredentialStorageListener.ts @@ -0,0 +1,51 @@ +import { ipcMain } from "electron"; +import { deletePassword, getPassword, setPassword } from "keytar"; + +import { BiometricMain } from "./biometric/biometric.main"; + +const AuthRequiredSuffix = "_biometric"; +const AuthenticatedActions = ["getPassword"]; + +export class DesktopCredentialStorageListener { + constructor(private serviceName: string, private biometricService: BiometricMain) {} + + init() { + ipcMain.on("keytar", async (event: any, message: any) => { + try { + let serviceName = this.serviceName; + message.keySuffix = "_" + (message.keySuffix ?? ""); + if (message.keySuffix !== "_") { + serviceName += message.keySuffix; + } + + const authenticationRequired = + AuthenticatedActions.includes(message.action) && AuthRequiredSuffix === message.keySuffix; + const authenticated = !authenticationRequired || (await this.authenticateBiometric()); + + let val: string | boolean = null; + if (authenticated && message.action && message.key) { + if (message.action === "getPassword") { + val = await getPassword(serviceName, message.key); + } else if (message.action === "hasPassword") { + const result = await getPassword(serviceName, message.key); + val = result != null; + } else if (message.action === "setPassword" && message.value) { + await setPassword(serviceName, message.key, message.value); + } else if (message.action === "deletePassword") { + await deletePassword(serviceName, message.key); + } + } + event.returnValue = val; + } catch { + event.returnValue = null; + } + }); + } + + private async authenticateBiometric(): Promise { + if (this.biometricService) { + return await this.biometricService.authenticateBiometric(); + } + return false; + } +} diff --git a/apps/desktop/src/main/menu/menu.about.ts b/apps/desktop/src/main/menu/menu.about.ts new file mode 100644 index 0000000000..10ce23d123 --- /dev/null +++ b/apps/desktop/src/main/menu/menu.about.ts @@ -0,0 +1,87 @@ +import { BrowserWindow, clipboard, dialog, MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { UpdaterMain } from "jslib-electron/updater.main"; +import { isMacAppStore, isSnapStore, isWindowsStore } from "jslib-electron/utils"; + +import { IMenubarMenu } from "./menubar"; + +export class AboutMenu implements IMenubarMenu { + readonly id: string = "about"; + + get label(): string { + return ""; + } + + get items(): MenuItemConstructorOptions[] { + return [this.separator, this.checkForUpdates, this.aboutBitwarden]; + } + + private readonly _i18nService: I18nService; + private readonly _updater: UpdaterMain; + private readonly _window: BrowserWindow; + private readonly _version: string; + + constructor( + i18nService: I18nService, + version: string, + window: BrowserWindow, + updater: UpdaterMain + ) { + this._i18nService = i18nService; + this._updater = updater; + this._version = version; + this._window = window; + } + + private get separator(): MenuItemConstructorOptions { + return { type: "separator" }; + } + + private get checkForUpdates(): MenuItemConstructorOptions { + return { + id: "checkForUpdates", + label: this.localize("checkForUpdates"), + visible: !isWindowsStore() && !isSnapStore() && !isMacAppStore(), + click: () => this.checkForUpdate(), + }; + } + + private get aboutBitwarden(): MenuItemConstructorOptions { + return { + id: "aboutBitwarden", + label: this.localize("aboutBitwarden"), + click: async () => { + const aboutInformation = + this.localize("version", this._version) + + "\nShell " + + process.versions.electron + + "\nRenderer " + + process.versions.chrome + + "\nNode " + + process.versions.node + + "\nArchitecture " + + process.arch; + const result = await dialog.showMessageBox(this._window, { + title: "Bitwarden", + message: "Bitwarden", + detail: aboutInformation, + type: "info", + noLink: true, + buttons: [this.localize("ok"), this.localize("copy")], + }); + if (result.response === 1) { + clipboard.writeText(aboutInformation); + } + }, + }; + } + + private localize(s: string, p?: string) { + return this._i18nService.t(s, p); + } + + private async checkForUpdate() { + this._updater.checkForUpdate(true); + } +} diff --git a/apps/desktop/src/main/menu/menu.account.ts b/apps/desktop/src/main/menu/menu.account.ts new file mode 100644 index 0000000000..cce734beac --- /dev/null +++ b/apps/desktop/src/main/menu/menu.account.ts @@ -0,0 +1,115 @@ +import { BrowserWindow, dialog, MenuItemConstructorOptions, shell } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { isMacAppStore, isWindowsStore } from "jslib-electron/utils"; + +import { IMenubarMenu } from "./menubar"; + +export class AccountMenu implements IMenubarMenu { + readonly id: string = "accountMenu"; + + get label(): string { + return this.localize("account"); + } + + get items(): MenuItemConstructorOptions[] { + return [ + this.premiumMembership, + this.changeMasterPassword, + this.twoStepLogin, + this.fingerprintPhrase, + ]; + } + + private readonly _i18nService: I18nService; + private readonly _messagingService: MessagingService; + private readonly _webVaultUrl: string; + private readonly _window: BrowserWindow; + private readonly _isLocked: boolean; + + constructor( + i18nService: I18nService, + messagingService: MessagingService, + webVaultUrl: string, + window: BrowserWindow, + isLocked: boolean + ) { + this._i18nService = i18nService; + this._messagingService = messagingService; + this._webVaultUrl = webVaultUrl; + this._window = window; + this._isLocked = isLocked; + } + + private get premiumMembership(): MenuItemConstructorOptions { + return { + label: this.localize("premiumMembership"), + click: () => this.sendMessage("openPremium"), + id: "premiumMembership", + visible: !isWindowsStore() && !isMacAppStore(), + enabled: !this._isLocked, + }; + } + + private get changeMasterPassword(): MenuItemConstructorOptions { + return { + label: this.localize("changeMasterPass"), + id: "changeMasterPass", + click: async () => { + const result = await dialog.showMessageBox(this._window, { + title: this.localize("changeMasterPass"), + message: this.localize("changeMasterPass"), + detail: this.localize("changeMasterPasswordConfirmation"), + buttons: [this.localize("yes"), this.localize("no")], + cancelId: 1, + defaultId: 0, + noLink: true, + }); + if (result.response === 0) { + shell.openExternal(this._webVaultUrl); + } + }, + enabled: !this._isLocked, + }; + } + + private get twoStepLogin(): MenuItemConstructorOptions { + return { + label: this.localize("twoStepLogin"), + id: "twoStepLogin", + click: async () => { + const result = await dialog.showMessageBox(this._window, { + title: this.localize("twoStepLogin"), + message: this.localize("twoStepLogin"), + detail: this.localize("twoStepLoginConfirmation"), + buttons: [this.localize("yes"), this.localize("no")], + cancelId: 1, + defaultId: 0, + noLink: true, + }); + if (result.response === 0) { + shell.openExternal(this._webVaultUrl); + } + }, + enabled: !this._isLocked, + }; + } + + private get fingerprintPhrase(): MenuItemConstructorOptions { + return { + label: this.localize("fingerprintPhrase"), + id: "fingerprintPhrase", + click: () => this.sendMessage("showFingerprintPhrase"), + enabled: !this._isLocked, + }; + } + + private localize(s: string) { + return this._i18nService.t(s); + } + + private sendMessage(message: string, args?: any) { + this._messagingService.send(message, args); + } +} diff --git a/apps/desktop/src/main/menu/menu.bitwarden.ts b/apps/desktop/src/main/menu/menu.bitwarden.ts new file mode 100644 index 0000000000..6ee3be9dbc --- /dev/null +++ b/apps/desktop/src/main/menu/menu.bitwarden.ts @@ -0,0 +1,113 @@ +import { BrowserWindow, MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { UpdaterMain } from "jslib-electron/updater.main"; +import { isMac } from "jslib-electron/utils"; + +import { FirstMenu } from "./menu.first"; +import { MenuAccount } from "./menu.updater"; +import { IMenubarMenu } from "./menubar"; + +// AKA: "FirstMenu" or "MacMenu" - the first menu that shows on all macOs apps +export class BitwardenMenu extends FirstMenu implements IMenubarMenu { + readonly id: string = "bitwarden"; + readonly label: string = "Bitwarden"; + + get items(): MenuItemConstructorOptions[] { + const items = [this.aboutBitwarden, this.checkForUpdates]; + if (this.aboutBitwarden.visible === true || this.checkForUpdates.visible === true) { + items.push(this.separator); + } + items.push(this.settings); + items.push(this.lock); + items.push(this.lockAll); + items.push(this.logOut); + items.push(this.separator); + items.push(this.services); + + if ( + this.hideBitwarden.visible === true || + this.hideOthers.visible === true || + this.showAll.visible === true + ) { + items.push(this.separator); + } + + items.push(this.hideBitwarden); + items.push(this.hideOthers); + items.push(this.showAll); + + if (this.quitBitwarden.visible === true) { + items.push(this.separator); + } + items.push(this.quitBitwarden); + return items; + } + + constructor( + i18nService: I18nService, + messagingService: MessagingService, + updater: UpdaterMain, + window: BrowserWindow, + accounts: { [userId: string]: MenuAccount }, + isLocked: boolean + ) { + super(i18nService, messagingService, updater, window, accounts, isLocked); + } + + private get aboutBitwarden(): MenuItemConstructorOptions { + return { + id: "aboutBitwarden", + label: this.localize("aboutBitwarden"), + role: "about", + visible: isMac(), + }; + } + + private get services(): MenuItemConstructorOptions { + return { + id: "services", + label: this.localize("services"), + role: "services", + submenu: [], + visible: isMac(), + }; + } + + private get hideBitwarden(): MenuItemConstructorOptions { + return { + id: "hideBitwarden", + label: this.localize("hideBitwarden"), + role: "hide", + visible: isMac(), + }; + } + + private get hideOthers(): MenuItemConstructorOptions { + return { + id: "hideOthers", + label: this.localize("hideOthers"), + role: "hideOthers", + visible: isMac(), + }; + } + + private get showAll(): MenuItemConstructorOptions { + return { + id: "showAll", + label: this.localize("showAll"), + role: "unhide", + visible: isMac(), + }; + } + + private get quitBitwarden(): MenuItemConstructorOptions { + return { + id: "quitBitwarden", + label: this.localize("quitBitwarden"), + role: "quit", + visible: isMac(), + }; + } +} diff --git a/apps/desktop/src/main/menu/menu.edit.ts b/apps/desktop/src/main/menu/menu.edit.ts new file mode 100644 index 0000000000..a48afc745b --- /dev/null +++ b/apps/desktop/src/main/menu/menu.edit.ts @@ -0,0 +1,131 @@ +import { MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; + +import { IMenubarMenu } from "./menubar"; + +export class EditMenu implements IMenubarMenu { + readonly id: string = "editMenu"; + + get label(): string { + return this.localize("edit"); + } + + get items(): MenuItemConstructorOptions[] { + return [ + this.undo, + this.redo, + this.separator, + this.cut, + this.copy, + this.paste, + this.separator, + this.selectAll, + this.separator, + this.copyUsername, + this.copyPassword, + this.copyVerificationCodeTotp, + ]; + } + + private readonly _i18nService: I18nService; + private readonly _messagingService: MessagingService; + private readonly _isLocked: boolean; + + constructor(i18nService: I18nService, messagingService: MessagingService, isLocked: boolean) { + this._i18nService = i18nService; + this._messagingService = messagingService; + this._isLocked = isLocked; + } + + private get undo(): MenuItemConstructorOptions { + return { + id: "undo", + label: this.localize("undo"), + role: "undo", + }; + } + + private get redo(): MenuItemConstructorOptions { + return { + id: "redo", + label: this.localize("redo"), + role: "redo", + }; + } + + private get separator(): MenuItemConstructorOptions { + return { type: "separator" }; + } + + private get cut(): MenuItemConstructorOptions { + return { + id: "cut", + label: this.localize("cut"), + role: "cut", + }; + } + + private get copy(): MenuItemConstructorOptions { + return { + id: "copy", + label: this.localize("copy"), + role: "copy", + }; + } + + private get paste(): MenuItemConstructorOptions { + return { + id: "paste", + label: this.localize("paste"), + role: "paste", + }; + } + + private get selectAll(): MenuItemConstructorOptions { + return { + id: "selectAll", + label: this.localize("selectAll"), + role: "selectAll", + }; + } + + private get copyUsername(): MenuItemConstructorOptions { + return { + label: this.localize("copyUsername"), + id: "copyUsername", + click: () => this.sendMessage("copyUsername"), + accelerator: "CmdOrCtrl+U", + enabled: !this._isLocked, + }; + } + + private get copyPassword(): MenuItemConstructorOptions { + return { + label: this.localize("copyPassword"), + id: "copyPassword", + click: () => this.sendMessage("copyPassword"), + accelerator: "CmdOrCtrl+P", + enabled: !this._isLocked, + }; + } + + private get copyVerificationCodeTotp(): MenuItemConstructorOptions { + return { + label: this.localize("copyVerificationCodeTotp"), + id: "copyTotp", + click: () => this.sendMessage("copyTotp"), + accelerator: "CmdOrCtrl+T", + enabled: !this._isLocked, + }; + } + + private localize(s: string) { + return this._i18nService.t(s); + } + + private sendMessage(message: string) { + this._messagingService.send(message); + } +} diff --git a/apps/desktop/src/main/menu/menu.file.ts b/apps/desktop/src/main/menu/menu.file.ts new file mode 100644 index 0000000000..9ef4bc6da3 --- /dev/null +++ b/apps/desktop/src/main/menu/menu.file.ts @@ -0,0 +1,141 @@ +import { BrowserWindow, MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { UpdaterMain } from "jslib-electron/updater.main"; +import { isMac, isMacAppStore } from "jslib-electron/utils"; + +import { FirstMenu } from "./menu.first"; +import { MenuAccount } from "./menu.updater"; +import { IMenubarMenu } from "./menubar"; + +export class FileMenu extends FirstMenu implements IMenubarMenu { + readonly id: string = "fileMenu"; + + get label(): string { + return this.localize("file"); + } + + get items(): MenuItemConstructorOptions[] { + let items = [ + this.addNewLogin, + this.addNewItem, + this.addNewFolder, + this.separator, + this.syncVault, + this.exportVault, + ]; + + if (!isMac()) { + items = [ + ...items, + ...[ + this.separator, + this.settings, + this.lock, + this.lockAll, + this.logOut, + this.separator, + this.quitBitwarden, + ], + ]; + } + + return items; + } + + constructor( + i18nService: I18nService, + messagingService: MessagingService, + updater: UpdaterMain, + window: BrowserWindow, + accounts: { [userId: string]: MenuAccount }, + isLocked: boolean + ) { + super(i18nService, messagingService, updater, window, accounts, isLocked); + } + + private get addNewLogin(): MenuItemConstructorOptions { + return { + label: this.localize("addNewLogin"), + click: () => this.sendMessage("newLogin"), + accelerator: "CmdOrCtrl+N", + id: "addNewLogin", + enabled: !this._isLocked, + }; + } + + private get addNewItem(): MenuItemConstructorOptions { + return { + label: this.localize("addNewItem"), + id: "addNewItem", + submenu: this.addNewItemSubmenu, + enabled: !this._isLocked, + }; + } + + private get addNewItemSubmenu(): MenuItemConstructorOptions[] { + return [ + { + id: "typeLogin", + label: this.localize("typeLogin"), + click: () => this.sendMessage("newLogin"), + accelerator: "CmdOrCtrl+Shift+L", + }, + { + id: "typeCard", + label: this.localize("typeCard"), + click: () => this.sendMessage("newCard"), + accelerator: "CmdOrCtrl+Shift+C", + }, + { + id: "typeIdentity", + label: this.localize("typeIdentity"), + click: () => this.sendMessage("newIdentity"), + accelerator: "CmdOrCtrl+Shift+I", + }, + { + id: "typeSecureNote", + label: this.localize("typeSecureNote"), + click: () => this.sendMessage("newSecureNote"), + accelerator: "CmdOrCtrl+Shift+S", + }, + ]; + } + + private get addNewFolder(): MenuItemConstructorOptions { + return { + id: "addNewFolder", + label: this.localize("addNewFolder"), + click: () => this.sendMessage("newFolder"), + enabled: !this._isLocked, + }; + } + + private get syncVault(): MenuItemConstructorOptions { + return { + id: "syncVault", + label: this.localize("syncVault"), + click: () => this.sendMessage("syncVault"), + enabled: !this._isLocked, + }; + } + + private get exportVault(): MenuItemConstructorOptions { + return { + id: "exportVault", + label: this.localize("exportVault"), + click: () => this.sendMessage("exportVault"), + enabled: !this._isLocked, + }; + } + + private get quitBitwarden(): MenuItemConstructorOptions { + return { + id: "quitBitwarden", + label: this.localize("quitBitwarden"), + visible: !isMacAppStore(), + role: "quit", + }; + } +} diff --git a/apps/desktop/src/main/menu/menu.first.ts b/apps/desktop/src/main/menu/menu.first.ts new file mode 100644 index 0000000000..bccce323bf --- /dev/null +++ b/apps/desktop/src/main/menu/menu.first.ts @@ -0,0 +1,152 @@ +import { BrowserWindow, dialog, MenuItem, MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { UpdaterMain } from "jslib-electron/updater.main"; +import { isMacAppStore, isSnapStore, isWindowsStore } from "jslib-electron/utils"; + +import { MenuAccount } from "./menu.updater"; + +export class FirstMenu { + protected readonly _i18nService: I18nService; + protected readonly _updater: UpdaterMain; + protected readonly _messagingService: MessagingService; + protected readonly _accounts: { [userId: string]: MenuAccount }; + protected readonly _window: BrowserWindow; + protected readonly _isLocked: boolean; + + constructor( + i18nService: I18nService, + messagingService: MessagingService, + updater: UpdaterMain, + window: BrowserWindow, + accounts: { [userId: string]: MenuAccount }, + isLocked: boolean + ) { + this._i18nService = i18nService; + this._updater = updater; + this._messagingService = messagingService; + this._window = window; + this._accounts = accounts; + this._isLocked = isLocked; + } + + protected get hasAccounts(): boolean { + return this._accounts != null && Object.keys(this._accounts).length > 0; + } + + protected get checkForUpdates(): MenuItemConstructorOptions { + return { + id: "checkForUpdates", + label: this.localize("checkForUpdates"), + click: (menuItem) => this.checkForUpdate(menuItem), + visible: !isMacAppStore() && !isWindowsStore() && !isSnapStore(), + }; + } + + protected get separator(): MenuItemConstructorOptions { + return { + type: "separator", + }; + } + + protected get settings(): MenuItemConstructorOptions { + return { + id: "settings", + label: this.localize(process.platform === "darwin" ? "preferences" : "settings"), + click: () => this.sendMessage("openSettings"), + accelerator: "CmdOrCtrl+,", + enabled: !this._isLocked, + }; + } + + protected get lock(): MenuItemConstructorOptions { + return { + id: "lock", + label: this.localize("lockVault"), + submenu: this.lockSubmenu, + enabled: this.hasAccounts, + }; + } + + protected get lockSubmenu(): MenuItemConstructorOptions[] { + const value: MenuItemConstructorOptions[] = []; + for (const userId in this._accounts) { + if (userId == null) { + continue; + } + + value.push({ + label: this._accounts[userId].email, + id: `lockNow_${this._accounts[userId].userId}`, + click: () => this.sendMessage("lockVault", { userId: this._accounts[userId].userId }), + enabled: !this._accounts[userId].isLocked, + visible: this._accounts[userId].isAuthenticated, + }); + } + return value; + } + + protected get lockAll(): MenuItemConstructorOptions { + return { + id: "lockAllNow", + label: this.localize("lockAllVaults"), + click: () => this.sendMessage("lockAllVaults"), + accelerator: "CmdOrCtrl+L", + enabled: this.hasAccounts, + }; + } + + protected get logOut(): MenuItemConstructorOptions { + return { + id: "logOut", + label: this.localize("logOut"), + submenu: this.logOutSubmenu, + enabled: this.hasAccounts, + }; + } + + protected get logOutSubmenu(): MenuItemConstructorOptions[] { + const value: MenuItemConstructorOptions[] = []; + for (const userId in this._accounts) { + if (userId == null) { + continue; + } + + value.push({ + label: this._accounts[userId].email, + id: `logOut_${this._accounts[userId].userId}`, + click: async () => { + const result = await dialog.showMessageBox(this._window, { + title: this.localize("logOut"), + message: this.localize("logOut"), + detail: this.localize("logOutConfirmation"), + buttons: [this.localize("logOut"), this.localize("cancel")], + cancelId: 1, + defaultId: 0, + noLink: true, + }); + if (result.response === 0) { + this.sendMessage("logout", { userId: this._accounts[userId].userId }); + } + }, + visible: this._accounts[userId].isAuthenticated, + }); + } + return value; + } + + protected localize(s: string) { + return this._i18nService.t(s); + } + + protected async checkForUpdate(menuItem: MenuItem) { + menuItem.enabled = false; + this._updater.checkForUpdate(true); + menuItem.enabled = true; + } + + protected sendMessage(message: string, args?: any) { + this._messagingService.send(message, args); + } +} diff --git a/apps/desktop/src/main/menu/menu.help.ts b/apps/desktop/src/main/menu/menu.help.ts new file mode 100644 index 0000000000..4ac04c490b --- /dev/null +++ b/apps/desktop/src/main/menu/menu.help.ts @@ -0,0 +1,234 @@ +import { shell, MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { isMacAppStore, isWindowsStore } from "jslib-electron/utils"; + +import { AboutMenu } from "./menu.about"; +import { IMenubarMenu } from "./menubar"; + +export class HelpMenu implements IMenubarMenu { + readonly id: string = "help"; + + get label(): string { + return this.localize("help"); + } + + get items(): MenuItemConstructorOptions[] { + const items = [ + this.getHelp, + this.contactUs, + this.fileBugReport, + this.legal, + this.separator, + this.followUs, + this.separator, + this.goToWebVault, + this.separator, + this.getMobileApp, + this.getBrowserExtension, + ]; + + if (this._aboutMenu != null) { + items.push(...this._aboutMenu.items); + } + return items; + } + + private readonly _i18nService: I18nService; + private readonly _webVaultUrl: string; + private readonly _aboutMenu: AboutMenu; + + constructor(i18nService: I18nService, webVaultUrl: string, aboutMenu: AboutMenu) { + this._i18nService = i18nService; + this._webVaultUrl = webVaultUrl; + this._aboutMenu = aboutMenu; + } + + private get contactUs(): MenuItemConstructorOptions { + return { + id: "contactUs", + label: this.localize("contactUs"), + click: () => shell.openExternal("https://bitwarden.com/contact"), + }; + } + + private get getHelp(): MenuItemConstructorOptions { + return { + id: "getHelp", + label: this.localize("getHelp"), + click: () => shell.openExternal("https://bitwarden.com/help"), + }; + } + + private get fileBugReport(): MenuItemConstructorOptions { + return { + id: "fileBugReport", + label: this.localize("fileBugReport"), + click: () => shell.openExternal("https://github.com/bitwarden/clients/issues"), + }; + } + + private get legal(): MenuItemConstructorOptions { + return { + id: "legal", + label: this.localize("legal"), + visible: isMacAppStore(), + submenu: this.legalSubmenu, + }; + } + + private get legalSubmenu(): MenuItemConstructorOptions[] { + return [ + { + id: "termsOfService", + label: this.localize("termsOfService"), + click: () => shell.openExternal("https://bitwarden.com/terms/"), + }, + { + id: "privacyPolicy", + label: this.localize("privacyPolicy"), + click: () => shell.openExternal("https://bitwarden.com/privacy/"), + }, + ]; + } + + private get separator(): MenuItemConstructorOptions { + return { type: "separator" }; + } + + private get followUs(): MenuItemConstructorOptions { + return { + id: "followUs", + label: this.localize("followUs"), + submenu: this.followUsSubmenu, + }; + } + + private get followUsSubmenu(): MenuItemConstructorOptions[] { + return [ + { + id: "blog", + label: this.localize("blog"), + click: () => shell.openExternal("https://blog.bitwarden.com"), + }, + { + id: "twitter", + label: "Twitter", + click: () => shell.openExternal("https://twitter.com/bitwarden"), + }, + { + id: "facebook", + label: "Facebook", + click: () => shell.openExternal("https://www.facebook.com/bitwarden/"), + }, + { + id: "github", + label: "GitHub", + click: () => shell.openExternal("https://github.com/bitwarden"), + }, + ]; + } + + private get goToWebVault(): MenuItemConstructorOptions { + return { + id: "goToWebVault", + label: this.localize("goToWebVault"), + click: () => shell.openExternal(this._webVaultUrl), + }; + } + + private get getMobileApp(): MenuItemConstructorOptions { + return { + id: "getMobileApp", + label: this.localize("getMobileApp"), + visible: !isWindowsStore(), + submenu: this.getMobileAppSubmenu, + }; + } + + private get getMobileAppSubmenu(): MenuItemConstructorOptions[] { + return [ + { + id: "iOS", + label: "iOS", + click: () => { + shell.openExternal( + "https://itunes.apple.com/app/" + "bitwarden-free-password-manager/id1137397744?mt=8" + ); + }, + }, + { + id: "android", + label: "Android", + click: () => { + shell.openExternal( + "https://play.google.com/store/apps/" + "details?id=com.x8bit.bitwarden" + ); + }, + }, + ]; + } + + private get getBrowserExtension(): MenuItemConstructorOptions { + return { + id: "getBrowserExtension", + label: this.localize("getBrowserExtension"), + visible: !isWindowsStore(), + submenu: this.getBrowserExtensionSubmenu, + }; + } + + private get getBrowserExtensionSubmenu(): MenuItemConstructorOptions[] { + return [ + { + id: "chrome", + label: "Chrome", + click: () => { + shell.openExternal( + "https://chrome.google.com/webstore/detail/" + + "bitwarden-free-password-m/nngceckbapebfimnlniiiahkandclblb" + ); + }, + }, + { + id: "firefox", + label: "Firefox", + click: () => { + shell.openExternal( + "https://addons.mozilla.org/firefox/addon/" + "bitwarden-password-manager/" + ); + }, + }, + { + id: "firefox", + label: "Opera", + click: () => { + shell.openExternal( + "https://addons.opera.com/extensions/details/" + "bitwarden-free-password-manager/" + ); + }, + }, + { + id: "firefox", + label: "Edge", + click: () => { + shell.openExternal( + "https://microsoftedge.microsoft.com/addons/" + + "detail/jbkfoedolllekgbhcbcoahefnbanhhlh" + ); + }, + }, + { + id: "safari", + label: "Safari", + click: () => { + shell.openExternal("https://bitwarden.com/download/"); + }, + }, + ]; + } + + private localize(s: string) { + return this._i18nService.t(s); + } +} diff --git a/apps/desktop/src/main/menu/menu.main.ts b/apps/desktop/src/main/menu/menu.main.ts new file mode 100644 index 0000000000..2cc1935411 --- /dev/null +++ b/apps/desktop/src/main/menu/menu.main.ts @@ -0,0 +1,52 @@ +import { app, Menu } from "electron"; + +import { BaseMenu } from "jslib-electron/baseMenu"; + +import { Main } from "../../main"; + +import { MenuUpdateRequest } from "./menu.updater"; +import { Menubar } from "./menubar"; + +const cloudWebVaultUrl = "https://vault.bitwarden.com"; + +export class MenuMain extends BaseMenu { + constructor(private main: Main) { + super(main.i18nService, main.windowMain); + } + + async init() { + this.initContextMenu(); + await this.setMenu(); + } + + async updateApplicationMenuState(updateRequest: MenuUpdateRequest) { + await this.setMenu(updateRequest); + } + + private async setMenu(updateRequest?: MenuUpdateRequest) { + Menu.setApplicationMenu( + new Menubar( + this.main.i18nService, + this.main.messagingService, + this.main.updaterMain, + this.windowMain, + await this.getWebVaultUrl(), + app.getVersion(), + updateRequest + ).menu + ); + } + + private async getWebVaultUrl() { + let webVaultUrl = cloudWebVaultUrl; + const urlsObj: any = await this.main.stateService.getEnvironmentUrls(); + if (urlsObj != null) { + if (urlsObj.base != null) { + webVaultUrl = urlsObj.base; + } else if (urlsObj.webVault != null) { + webVaultUrl = urlsObj.webVault; + } + } + return webVaultUrl; + } +} diff --git a/apps/desktop/src/main/menu/menu.updater.ts b/apps/desktop/src/main/menu/menu.updater.ts new file mode 100644 index 0000000000..75454a56f8 --- /dev/null +++ b/apps/desktop/src/main/menu/menu.updater.ts @@ -0,0 +1,12 @@ +export class MenuUpdateRequest { + hideChangeMasterPassword: boolean; + activeUserId: string; + accounts: { [userId: string]: MenuAccount }; +} + +export class MenuAccount { + isAuthenticated: boolean; + isLocked: boolean; + userId: string; + email: string; +} diff --git a/apps/desktop/src/main/menu/menu.view.ts b/apps/desktop/src/main/menu/menu.view.ts new file mode 100644 index 0000000000..e3f53e35ba --- /dev/null +++ b/apps/desktop/src/main/menu/menu.view.ts @@ -0,0 +1,135 @@ +import { MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; + +import { IMenubarMenu } from "./menubar"; + +export class ViewMenu implements IMenubarMenu { + readonly id: "viewMenu"; + + get label(): string { + return this.localize("view"); + } + + get items(): MenuItemConstructorOptions[] { + return [ + this.searchVault, + this.separator, + this.generator, + this.passwordHistory, + this.separator, + this.zoomIn, + this.zoomOut, + this.resetZoom, + this.separator, + this.toggleFullscreen, + this.separator, + this.reload, + this.toggleDevTools, + ]; + } + + private readonly _i18nService: I18nService; + private readonly _messagingService: MessagingService; + private readonly _isLocked: boolean; + + constructor(i18nService: I18nService, messagingService: MessagingService, isLocked: boolean) { + this._i18nService = i18nService; + this._messagingService = messagingService; + this._isLocked = isLocked; + } + + private get searchVault(): MenuItemConstructorOptions { + return { + id: "searchVault", + label: this.localize("searchVault"), + click: () => this.sendMessage("focusSearch"), + accelerator: "CmdOrCtrl+F", + enabled: !this._isLocked, + }; + } + + private get separator(): MenuItemConstructorOptions { + return { type: "separator" }; + } + + private get generator(): MenuItemConstructorOptions { + return { + id: "generator", + label: this.localize("generator"), + click: () => this.sendMessage("openGenerator"), + accelerator: "CmdOrCtrl+G", + enabled: !this._isLocked, + }; + } + + private get passwordHistory(): MenuItemConstructorOptions { + return { + id: "passwordHistory", + label: this.localize("passwordHistory"), + click: () => this.sendMessage("openPasswordHistory"), + enabled: !this._isLocked, + }; + } + + private get zoomIn(): MenuItemConstructorOptions { + return { + id: "zoomIn", + label: this.localize("zoomIn"), + role: "zoomIn", + accelerator: "CmdOrCtrl+=", + }; + } + + private get zoomOut(): MenuItemConstructorOptions { + return { + id: "zoomOut", + label: this.localize("zoomOut"), + role: "zoomOut", + accelerator: "CmdOrCtrl+-", + }; + } + + private get resetZoom(): MenuItemConstructorOptions { + return { + id: "resetZoom", + label: this.localize("resetZoom"), + role: "resetZoom", + accelerator: "CmdOrCtrl+0", + }; + } + + private get toggleFullscreen(): MenuItemConstructorOptions { + return { + id: "toggleFullScreen", + label: this.localize("toggleFullScreen"), + role: "togglefullscreen", + }; + } + + private get reload(): MenuItemConstructorOptions { + return { + id: "reload", + label: this.localize("reload"), + role: "forceReload", + }; + } + + private get toggleDevTools(): MenuItemConstructorOptions { + return { + id: "toggleDevTools", + label: this.localize("toggleDevTools"), + role: "toggleDevTools", + accelerator: "F12", + }; + } + + private localize(s: string) { + return this._i18nService.t(s); + } + + private sendMessage(message: string) { + this._messagingService.send(message); + } +} diff --git a/apps/desktop/src/main/menu/menu.window.ts b/apps/desktop/src/main/menu/menu.window.ts new file mode 100644 index 0000000000..9b63fa5d45 --- /dev/null +++ b/apps/desktop/src/main/menu/menu.window.ts @@ -0,0 +1,105 @@ +import { MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { isMac } from "jslib-electron/utils"; +import { WindowMain } from "jslib-electron/window.main"; + +import { IMenubarMenu } from "./menubar"; + +export class WindowMenu implements IMenubarMenu { + readonly id: string; + + get label(): string { + return this.localize("window"); + } + + get items(): MenuItemConstructorOptions[] { + const items = [this.minimize, this.hideToMenu, this.alwaysOnTop]; + + if (isMac()) { + items.push(this.zoom, this.separator, this.bringAllToFront); + } + + items.push(this.separator, this.close); + return items; + } + + private readonly _i18nService: I18nService; + private readonly _messagingService: MessagingService; + private readonly _window: WindowMain; + + constructor( + i18nService: I18nService, + messagingService: MessagingService, + windowMain: WindowMain + ) { + this._i18nService = i18nService; + this._messagingService = messagingService; + this._window = windowMain; + } + + private get minimize(): MenuItemConstructorOptions { + return { + id: "minimize", + label: this.localize("minimize"), + role: "minimize", + }; + } + + private get hideToMenu(): MenuItemConstructorOptions { + return { + id: "hideToMenu", + label: this.localize(isMac() ? "hideToMenuBar" : "hideToTray"), + click: () => this.sendMessage("hideToTray"), + accelerator: "CmdOrCtrl+Shift+M", + }; + } + + private get alwaysOnTop(): MenuItemConstructorOptions { + return { + id: "alwaysOnTop", + label: this.localize("alwaysOnTop"), + type: "checkbox", + checked: this._window.win.isAlwaysOnTop(), + click: () => this._window.toggleAlwaysOnTop(), + accelerator: "CmdOrCtrl+Shift+T", + }; + } + + private get zoom(): MenuItemConstructorOptions { + return { + id: "zoom", + label: this.localize("zoom"), + role: "zoom", + }; + } + + private get separator(): MenuItemConstructorOptions { + return { type: "separator" }; + } + + private get bringAllToFront(): MenuItemConstructorOptions { + return { + id: "bringAllToFront", + label: this.localize("bringAllToFront"), + role: "front", + }; + } + + private get close(): MenuItemConstructorOptions { + return { + id: "close", + label: this.localize("close"), + role: "close", + }; + } + + private localize(s: string) { + return this._i18nService.t(s); + } + + private sendMessage(message: string, args?: any) { + this._messagingService.send(message, args); + } +} diff --git a/apps/desktop/src/main/menu/menubar.ts b/apps/desktop/src/main/menu/menubar.ts new file mode 100644 index 0000000000..c9aa070687 --- /dev/null +++ b/apps/desktop/src/main/menu/menubar.ts @@ -0,0 +1,100 @@ +import { Menu, MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { UpdaterMain } from "jslib-electron/updater.main"; +import { isMac } from "jslib-electron/utils"; +import { WindowMain } from "jslib-electron/window.main"; + +import { AboutMenu } from "./menu.about"; +import { AccountMenu } from "./menu.account"; +import { BitwardenMenu } from "./menu.bitwarden"; +import { EditMenu } from "./menu.edit"; +import { FileMenu } from "./menu.file"; +import { HelpMenu } from "./menu.help"; +import { MenuUpdateRequest } from "./menu.updater"; +import { ViewMenu } from "./menu.view"; +import { WindowMenu } from "./menu.window"; + +export interface IMenubarMenu { + id: string; + label: string; + visible?: boolean; // Assumes true if null + items: MenuItemConstructorOptions[]; +} + +export class Menubar { + private readonly items: IMenubarMenu[]; + + get menu(): Menu { + const template: MenuItemConstructorOptions[] = []; + if (this.items != null) { + this.items.forEach((item: IMenubarMenu) => { + if (item != null) { + template.push({ + id: item.id, + label: item.label, + submenu: item.items, + visible: item.visible ?? true, + }); + } + }); + } + return Menu.buildFromTemplate(template); + } + + constructor( + i18nService: I18nService, + messagingService: MessagingService, + updaterMain: UpdaterMain, + windowMain: WindowMain, + webVaultUrl: string, + appVersion: string, + updateRequest?: MenuUpdateRequest + ) { + let isLocked = true; + if ( + updateRequest != null && + updateRequest.accounts != null && + updateRequest.activeUserId != null + ) { + isLocked = updateRequest.accounts[updateRequest.activeUserId]?.isLocked ?? true; + } + + this.items = [ + new FileMenu( + i18nService, + messagingService, + updaterMain, + windowMain.win, + updateRequest?.accounts, + isLocked + ), + new EditMenu(i18nService, messagingService, isLocked), + new ViewMenu(i18nService, messagingService, isLocked), + new AccountMenu(i18nService, messagingService, webVaultUrl, windowMain.win, isLocked), + new WindowMenu(i18nService, messagingService, windowMain), + new HelpMenu( + i18nService, + webVaultUrl, + new AboutMenu(i18nService, appVersion, windowMain.win, updaterMain) + ), + ]; + + if (isMac()) { + this.items = [ + ...[ + new BitwardenMenu( + i18nService, + messagingService, + updaterMain, + windowMain.win, + updateRequest?.accounts, + isLocked + ), + ], + ...this.items, + ]; + } + } +} diff --git a/apps/desktop/src/main/messaging.main.ts b/apps/desktop/src/main/messaging.main.ts new file mode 100644 index 0000000000..290109eec0 --- /dev/null +++ b/apps/desktop/src/main/messaging.main.ts @@ -0,0 +1,159 @@ +import * as fs from "fs"; +import * as path from "path"; + +import { app, ipcMain } from "electron"; + +import { StateService } from "jslib-common/abstractions/state.service"; + +import { Main } from "../main"; + +import { MenuUpdateRequest } from "./menu/menu.updater"; + +const SyncInterval = 5 * 60 * 1000; // 5 minutes + +export class MessagingMain { + private syncTimeout: NodeJS.Timer; + + constructor(private main: Main, private stateService: StateService) {} + + init() { + this.scheduleNextSync(); + if (process.platform === "linux") { + this.stateService.setOpenAtLogin(fs.existsSync(this.linuxStartupFile())); + } else { + const loginSettings = app.getLoginItemSettings(); + this.stateService.setOpenAtLogin(loginSettings.openAtLogin); + } + ipcMain.on("messagingService", async (event: any, message: any) => this.onMessage(message)); + } + + onMessage(message: any) { + switch (message.command) { + case "scheduleNextSync": + this.scheduleNextSync(); + break; + case "updateAppMenu": + this.main.menuMain.updateApplicationMenuState(message.updateRequest); + this.updateTrayMenu(message.updateRequest); + break; + case "minimizeOnCopy": + this.stateService.getMinimizeOnCopyToClipboard().then((shouldMinimize) => { + if (shouldMinimize && this.main.windowMain.win !== null) { + this.main.windowMain.win.minimize(); + } + }); + break; + case "showTray": + this.main.trayMain.showTray(); + break; + case "removeTray": + this.main.trayMain.removeTray(); + break; + case "hideToTray": + this.main.trayMain.hideToTray(); + break; + case "addOpenAtLogin": + this.addOpenAtLogin(); + break; + case "removeOpenAtLogin": + this.removeOpenAtLogin(); + break; + case "setFocus": + this.setFocus(); + break; + case "getWindowIsFocused": + this.windowIsFocused(); + break; + case "enableBrowserIntegration": + this.main.nativeMessagingMain.generateManifests(); + this.main.nativeMessagingMain.listen(); + break; + case "disableBrowserIntegration": + this.main.nativeMessagingMain.removeManifests(); + this.main.nativeMessagingMain.stop(); + break; + default: + break; + } + } + + private scheduleNextSync() { + if (this.syncTimeout) { + global.clearTimeout(this.syncTimeout); + } + + this.syncTimeout = global.setTimeout(() => { + if (this.main.windowMain.win == null) { + return; + } + + this.main.windowMain.win.webContents.send("messagingService", { + command: "checkSyncVault", + }); + }, SyncInterval); + } + + private updateTrayMenu(updateRequest: MenuUpdateRequest) { + if ( + this.main.trayMain == null || + this.main.trayMain.contextMenu == null || + updateRequest?.activeUserId == null + ) { + return; + } + const lockVaultTrayMenuItem = this.main.trayMain.contextMenu.getMenuItemById("lockVault"); + const activeAccount = updateRequest.accounts[updateRequest.activeUserId]; + if (lockVaultTrayMenuItem != null && activeAccount != null) { + lockVaultTrayMenuItem.enabled = activeAccount.isAuthenticated && !activeAccount.isLocked; + } + this.main.trayMain.updateContextMenu(); + } + + private addOpenAtLogin() { + if (process.platform === "linux") { + const data = `[Desktop Entry] +Type=Application +Version=${app.getVersion()} +Name=Bitwarden +Comment=Bitwarden startup script +Exec=${app.getPath("exe")} +StartupNotify=false +Terminal=false`; + + const dir = path.dirname(this.linuxStartupFile()); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir); + } + fs.writeFileSync(this.linuxStartupFile(), data); + } else { + app.setLoginItemSettings({ openAtLogin: true }); + } + } + + private removeOpenAtLogin() { + if (process.platform === "linux") { + if (fs.existsSync(this.linuxStartupFile())) { + fs.unlinkSync(this.linuxStartupFile()); + } + } else { + app.setLoginItemSettings({ openAtLogin: false }); + } + } + + private linuxStartupFile(): string { + return path.join(app.getPath("home"), ".config", "autostart", "bitwarden.desktop"); + } + + private setFocus() { + this.main.trayMain.restoreFromTray(); + this.main.windowMain.win.focusOnWebView(); + } + + private windowIsFocused() { + const windowIsFocused = this.main.windowMain.win.isFocused(); + this.main.windowMain.win.webContents.send("messagingService", { + command: "windowIsFocused", + windowIsFocused: windowIsFocused, + }); + } +} diff --git a/apps/desktop/src/main/nativeMessaging.main.ts b/apps/desktop/src/main/nativeMessaging.main.ts new file mode 100644 index 0000000000..0e8554a1b3 --- /dev/null +++ b/apps/desktop/src/main/nativeMessaging.main.ts @@ -0,0 +1,319 @@ +import { existsSync, promises as fs } from "fs"; +import { Socket } from "net"; +import { homedir, userInfo } from "os"; +import * as path from "path"; +import * as util from "util"; + +import { ipcMain } from "electron"; +import * as ipc from "node-ipc"; + +import { LogService } from "jslib-common/abstractions/log.service"; +import { WindowMain } from "jslib-electron/window.main"; + +export class NativeMessagingMain { + private connected: Socket[] = []; + private socket: any; + + constructor( + private logService: LogService, + private windowMain: WindowMain, + private userPath: string, + private exePath: string + ) {} + + async listen() { + ipc.config.id = "bitwarden"; + ipc.config.retry = 1500; + if (process.platform === "darwin") { + if (!existsSync(`${homedir()}/tmp`)) { + await fs.mkdir(`${homedir()}/tmp`); + } + ipc.config.socketRoot = `${homedir()}/tmp/`; + } + + ipc.serve(() => { + ipc.server.on("message", (data: any, socket: any) => { + this.socket = socket; + this.windowMain.win.webContents.send("nativeMessaging", data); + }); + + ipcMain.on("nativeMessagingReply", (event, msg) => { + if (this.socket != null && msg != null) { + this.send(msg, this.socket); + } + }); + + ipc.server.on("connect", (socket: Socket) => { + this.connected.push(socket); + }); + + ipc.server.on("socket.disconnected", (socket, destroyedSocketID) => { + const index = this.connected.indexOf(socket); + if (index > -1) { + this.connected.splice(index, 1); + } + + this.socket = null; + ipc.log("client " + destroyedSocketID + " has disconnected!"); + }); + }); + + ipc.server.start(); + } + + stop() { + ipc.server.stop(); + // Kill all existing connections + this.connected.forEach((socket) => { + if (!socket.destroyed) { + socket.destroy(); + } + }); + } + + send(message: object, socket: any) { + ipc.server.emit(socket, "message", message); + } + + generateManifests() { + const baseJson = { + name: "com.8bit.bitwarden", + description: "Bitwarden desktop <-> browser bridge", + path: this.binaryPath(), + type: "stdio", + }; + + const firefoxJson = { + ...baseJson, + ...{ allowed_extensions: ["{446900e4-71c2-419f-a6a7-df9c091e268b}"] }, + }; + const chromeJson = { + ...baseJson, + ...{ + allowed_origins: [ + "chrome-extension://nngceckbapebfimnlniiiahkandclblb/", + "chrome-extension://jbkfoedolllekgbhcbcoahefnbanhhlh/", + "chrome-extension://ccnckbpmaceehanjmeomladnmlffdjgn/", + ], + }, + }; + + switch (process.platform) { + case "win32": { + const destination = path.join(this.userPath, "browsers"); + this.writeManifest(path.join(destination, "firefox.json"), firefoxJson); + this.writeManifest(path.join(destination, "chrome.json"), chromeJson); + + this.createWindowsRegistry( + "HKLM\\SOFTWARE\\Mozilla\\Firefox", + "HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden", + path.join(destination, "firefox.json") + ); + this.createWindowsRegistry( + "HKCU\\SOFTWARE\\Google\\Chrome", + "HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden", + path.join(destination, "chrome.json") + ); + break; + } + case "darwin": { + const nmhs = this.getDarwinNMHS(); + for (const [key, value] of Object.entries(nmhs)) { + if (existsSync(value)) { + const p = path.join(value, "NativeMessagingHosts", "com.8bit.bitwarden.json"); + + let manifest: any = chromeJson; + if (key === "Firefox") { + manifest = firefoxJson; + } + + this.writeManifest(p, manifest).catch((e) => + this.logService.error(`Error writing manifest for ${key}. ${e}`) + ); + } else { + this.logService.warning(`${key} not found skipping.`); + } + } + break; + } + case "linux": + if (existsSync(`${this.homedir()}/.mozilla/`)) { + this.writeManifest( + `${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`, + firefoxJson + ); + } + + if (existsSync(`${this.homedir()}/.config/google-chrome/`)) { + this.writeManifest( + `${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json`, + chromeJson + ); + } + + if (existsSync(`${this.homedir()}/.config/microsoft-edge/`)) { + this.writeManifest( + `${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json`, + chromeJson + ); + } + break; + default: + break; + } + } + + removeManifests() { + switch (process.platform) { + case "win32": + fs.unlink(path.join(this.userPath, "browsers", "firefox.json")); + fs.unlink(path.join(this.userPath, "browsers", "chrome.json")); + this.deleteWindowsRegistry( + "HKCU\\SOFTWARE\\Mozilla\\NativeMessagingHosts\\com.8bit.bitwarden" + ); + this.deleteWindowsRegistry( + "HKCU\\SOFTWARE\\Google\\Chrome\\NativeMessagingHosts\\com.8bit.bitwarden" + ); + break; + case "darwin": { + const nmhs = this.getDarwinNMHS(); + for (const [, value] of Object.entries(nmhs)) { + const p = path.join(value, "NativeMessagingHosts", "com.8bit.bitwarden.json"); + if (existsSync(p)) { + fs.unlink(p); + } + } + break; + } + case "linux": + if ( + existsSync(`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`) + ) { + fs.unlink(`${this.homedir()}/.mozilla/native-messaging-hosts/com.8bit.bitwarden.json`); + } + + if ( + existsSync( + `${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json` + ) + ) { + fs.unlink( + `${this.homedir()}/.config/google-chrome/NativeMessagingHosts/com.8bit.bitwarden.json` + ); + } + + if ( + existsSync( + `${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json` + ) + ) { + fs.unlink( + `${this.homedir()}/.config/microsoft-edge/NativeMessagingHosts/com.8bit.bitwarden.json` + ); + } + break; + default: + break; + } + } + + private getDarwinNMHS() { + /* eslint-disable no-useless-escape */ + return { + Firefox: `${this.homedir()}/Library/Application\ Support/Mozilla/`, + Chrome: `${this.homedir()}/Library/Application\ Support/Google/Chrome/`, + "Chrome Beta": `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Beta/`, + "Chrome Dev": `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Dev/`, + "Chrome Canary": `${this.homedir()}/Library/Application\ Support/Google/Chrome\ Canary/`, + Chromium: `${this.homedir()}/Library/Application\ Support/Chromium/`, + "Microsoft Edge": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge/`, + "Microsoft Edge Beta": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Beta/`, + "Microsoft Edge Dev": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Dev/`, + "Microsoft Edge Canary": `${this.homedir()}/Library/Application\ Support/Microsoft\ Edge\ Canary/`, + Vivaldi: `${this.homedir()}/Library/Application\ Support/Vivaldi/`, + }; + /* eslint-enable no-useless-escape */ + } + + private async writeManifest(destination: string, manifest: object) { + if (!existsSync(path.dirname(destination))) { + await fs.mkdir(path.dirname(destination)); + } + fs.writeFile(destination, JSON.stringify(manifest, null, 2)).catch(this.logService.error); + } + + private binaryPath() { + if (process.platform === "win32") { + return path.join(path.dirname(this.exePath), "resources", "native-messaging.bat"); + } + + return this.exePath; + } + + private getRegeditInstance() { + // eslint-disable-next-line + const regedit = require("regedit"); + regedit.setExternalVBSLocation(path.join(path.dirname(this.exePath), "resources/regedit/vbs")); + + return regedit; + } + + private async createWindowsRegistry(check: string, location: string, jsonFile: string) { + const regedit = this.getRegeditInstance(); + + const list = util.promisify(regedit.list); + const createKey = util.promisify(regedit.createKey); + const putValue = util.promisify(regedit.putValue); + + this.logService.debug(`Adding registry: ${location}`); + + // Check installed + try { + await list(check); + } catch { + this.logService.warning(`Not finding registry ${check} skipping.`); + return; + } + + try { + await createKey(location); + + // Insert path to manifest + const obj: any = {}; + obj[location] = { + default: { + value: jsonFile, + type: "REG_DEFAULT", + }, + }; + + return putValue(obj); + } catch (error) { + this.logService.error(error); + } + } + + private async deleteWindowsRegistry(key: string) { + const regedit = this.getRegeditInstance(); + + const list = util.promisify(regedit.list); + const deleteKey = util.promisify(regedit.deleteKey); + + this.logService.debug(`Removing registry: ${key}`); + + try { + await list(key); + await deleteKey(key); + } catch { + this.logService.error(`Unable to delete registry key: ${key}`); + } + } + + private homedir() { + if (process.platform === "darwin") { + return userInfo().homedir; + } else { + return homedir(); + } + } +} diff --git a/apps/desktop/src/main/powerMonitor.main.ts b/apps/desktop/src/main/powerMonitor.main.ts new file mode 100644 index 0000000000..4fa897c21b --- /dev/null +++ b/apps/desktop/src/main/powerMonitor.main.ts @@ -0,0 +1,47 @@ +import { powerMonitor } from "electron"; + +import { isSnapStore } from "jslib-electron/utils"; + +import { Main } from "../main"; + +// tslint:disable-next-line +const IdleLockSeconds = 5 * 60; // 5 minutes +const IdleCheckInterval = 30 * 1000; // 30 seconds + +export class PowerMonitorMain { + private idle = false; + + constructor(private main: Main) {} + + init() { + // ref: https://github.com/electron/electron/issues/13767 + if (!isSnapStore()) { + // System sleep + powerMonitor.on("suspend", () => { + this.main.messagingService.send("systemSuspended"); + }); + } + + if (process.platform !== "linux") { + // System locked + powerMonitor.on("lock-screen", () => { + this.main.messagingService.send("systemLocked"); + }); + } + + // System idle + global.setInterval(() => { + const idleSeconds: number = powerMonitor.getSystemIdleTime(); + const idle = idleSeconds >= IdleLockSeconds; + if (idle) { + if (this.idle) { + return; + } + + this.main.messagingService.send("systemIdle"); + } + + this.idle = idle; + }, IdleCheckInterval); + } +} diff --git a/apps/desktop/src/models/account.ts b/apps/desktop/src/models/account.ts new file mode 100644 index 0000000000..f92947fb0d --- /dev/null +++ b/apps/desktop/src/models/account.ts @@ -0,0 +1,20 @@ +import { + Account as BaseAccount, + AccountSettings as BaseAccountSettings, +} from "jslib-common/models/domain/account"; + +export class AccountSettings extends BaseAccountSettings { + vaultTimeout = -1; // On Restart +} + +export class Account extends BaseAccount { + settings?: AccountSettings = new AccountSettings(); + + constructor(init: Partial) { + super(init); + Object.assign(this.settings, { + ...new AccountSettings(), + ...this.settings, + }); + } +} diff --git a/apps/desktop/src/package-lock.json b/apps/desktop/src/package-lock.json new file mode 100644 index 0000000000..a8c141bcf5 --- /dev/null +++ b/apps/desktop/src/package-lock.json @@ -0,0 +1,1299 @@ +{ + "name": "@bitwarden/desktop", + "version": "1.33.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@bitwarden/desktop", + "version": "1.33.1", + "license": "GPL-3.0", + "dependencies": { + "@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4", + "forcefocus": "^1.1.0", + "keytar": "^7.9.0" + } + }, + "node_modules/@nodert-win10-rs4/windows.security.credentials.ui": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@nodert-win10-rs4/windows.security.credentials.ui/-/windows.security.credentials.ui-0.4.4.tgz", + "integrity": "sha512-P+EsJw5MCQXTxp7mwXfNDvIzIYsB6ple+HNg01QjPWg/PJfAodPuxL6XM7l0sPtYHsDYnfnvoefZMdZRa2Z1ig==", + "hasInstallScript": true, + "dependencies": { + "nan": "latest" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "node_modules/forcefocus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/forcefocus/-/forcefocus-1.1.0.tgz", + "integrity": "sha512-bnY7rul5kBLyNoCn0FHNiFAF+GGUZx6TvxWhurUS4PlmOzF+FMixGIigHH5UcyM3w1gp2TxAtP6MOUSXA15Sgw==", + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0", + "prebuild-install": "^5.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keytar/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/keytar/node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/keytar/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/keytar/node_modules/node-abi": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.15.0.tgz", + "integrity": "sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/keytar/node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/keytar/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/keytar/node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node_modules/node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dependencies": { + "semver": "^5.4.1" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + }, + "node_modules/noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "dependencies": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + }, + "dependencies": { + "@nodert-win10-rs4/windows.security.credentials.ui": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@nodert-win10-rs4/windows.security.credentials.ui/-/windows.security.credentials.ui-0.4.4.tgz", + "integrity": "sha512-P+EsJw5MCQXTxp7mwXfNDvIzIYsB6ple+HNg01QjPWg/PJfAodPuxL6XM7l0sPtYHsDYnfnvoefZMdZRa2Z1ig==", + "requires": { + "nan": "latest" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "forcefocus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/forcefocus/-/forcefocus-1.1.0.tgz", + "integrity": "sha512-bnY7rul5kBLyNoCn0FHNiFAF+GGUZx6TvxWhurUS4PlmOzF+FMixGIigHH5UcyM3w1gp2TxAtP6MOUSXA15Sgw==", + "requires": { + "bindings": "^1.3.0", + "prebuild-install": "^5.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "requires": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + }, + "dependencies": { + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "requires": { + "mimic-response": "^3.1.0" + } + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==" + }, + "node-abi": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.15.0.tgz", + "integrity": "sha512-Ic6z/j6I9RLm4ov7npo1I48UQr2BEyFCqh6p7S1dhEx9jPO0GPGq/e2Rb7x7DroQrmiVMz/Bw1vJm9sPAl2nxA==", + "requires": { + "semver": "^7.3.5" + } + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + } + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==" + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "requires": { + "semver": "^5.4.1" + } + }, + "node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "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" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==" + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/apps/desktop/src/package.json b/apps/desktop/src/package.json new file mode 100644 index 0000000000..58d56b30b2 --- /dev/null +++ b/apps/desktop/src/package.json @@ -0,0 +1,19 @@ +{ + "name": "@bitwarden/desktop", + "productName": "Bitwarden", + "description": "A secure and free password manager for all of your devices.", + "version": "2022.5.0", + "author": "Bitwarden Inc. (https://bitwarden.com)", + "homepage": "https://bitwarden.com", + "license": "GPL-3.0", + "main": "main.js", + "repository": { + "type": "git", + "url": "git+https://github.com/bitwarden/clients.git" + }, + "dependencies": { + "@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4", + "forcefocus": "^1.1.0", + "keytar": "^7.9.0" + } +} diff --git a/apps/desktop/src/proxy/ipc.ts b/apps/desktop/src/proxy/ipc.ts new file mode 100644 index 0000000000..228179a5e4 --- /dev/null +++ b/apps/desktop/src/proxy/ipc.ts @@ -0,0 +1,53 @@ +/* eslint-disable no-console */ +import { homedir } from "os"; + +import * as ipc from "node-ipc"; + +ipc.config.id = "proxy"; +ipc.config.retry = 1500; +ipc.config.logger = console.warn; // Stdout is used for native messaging +if (process.platform === "darwin") { + ipc.config.socketRoot = `${homedir()}/tmp/`; +} + +export default class IPC { + onMessage: (message: object) => void; + + private connected = false; + + connect() { + ipc.connectTo("bitwarden", () => { + ipc.of.bitwarden.on("connect", () => { + this.connected = true; + console.error("## connected to bitwarden desktop ##"); + + // Notify browser extension, connection is established to desktop application. + this.onMessage({ command: "connected" }); + }); + + ipc.of.bitwarden.on("disconnect", () => { + this.connected = false; + console.error("disconnected from world"); + + // Notify browser extension, no connection to desktop application. + this.onMessage({ command: "disconnected" }); + }); + + ipc.of.bitwarden.on("message", (message: any) => { + this.onMessage(message); + }); + + ipc.of.bitwarden.on("error", (err: any) => { + console.error("error", err); + }); + }); + } + + isConnected(): boolean { + return this.connected; + } + + send(json: object) { + ipc.of.bitwarden.emit("message", json); + } +} diff --git a/apps/desktop/src/proxy/native-messaging-proxy.ts b/apps/desktop/src/proxy/native-messaging-proxy.ts new file mode 100644 index 0000000000..f1b54a8201 --- /dev/null +++ b/apps/desktop/src/proxy/native-messaging-proxy.ts @@ -0,0 +1,23 @@ +import IPC from "./ipc"; +import NativeMessage from "./nativemessage"; + +// Proxy is a lightweight application which provides bi-directional communication +// between the browser extension and a running desktop application. +// +// Browser extension <-[native messaging]-> proxy <-[ipc]-> desktop +export class NativeMessagingProxy { + private ipc: IPC; + private nativeMessage: NativeMessage; + + constructor() { + this.ipc = new IPC(); + this.nativeMessage = new NativeMessage(this.ipc); + } + + run() { + this.ipc.connect(); + this.nativeMessage.listen(); + + this.ipc.onMessage = this.nativeMessage.send; + } +} diff --git a/apps/desktop/src/proxy/nativemessage.ts b/apps/desktop/src/proxy/nativemessage.ts new file mode 100644 index 0000000000..f7a32296f8 --- /dev/null +++ b/apps/desktop/src/proxy/nativemessage.ts @@ -0,0 +1,95 @@ +/* eslint-disable no-console */ +import IPC from "./ipc"; + +// Mostly based on the example from MDN, +// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging +export default class NativeMessage { + ipc: IPC; + + constructor(ipc: IPC) { + this.ipc = ipc; + } + + send(message: object) { + const messageBuffer = Buffer.from(JSON.stringify(message)); + + const headerBuffer = Buffer.alloc(4); + headerBuffer.writeUInt32LE(messageBuffer.length, 0); + + process.stdout.write(Buffer.concat([headerBuffer, messageBuffer])); + } + + listen() { + let payloadSize: number = null; + + // A queue to store the chunks as we read them from stdin. + // This queue can be flushed when `payloadSize` data has been read + const chunks: any = []; + + // Only read the size once for each payload + const sizeHasBeenRead = () => Boolean(payloadSize); + + // All the data has been read, reset everything for the next message + const flushChunksQueue = () => { + payloadSize = null; + chunks.splice(0); + }; + + const processData = () => { + // Create one big buffer with all all the chunks + const stringData = Buffer.concat(chunks); + console.error(stringData); + + // The browser will emit the size as a header of the payload, + // if it hasn't been read yet, do it. + // The next time we'll need to read the payload size is when all of the data + // of the current payload has been read (ie. data.length >= payloadSize + 4) + if (!sizeHasBeenRead()) { + try { + payloadSize = stringData.readUInt32LE(0); + } catch (e) { + console.error(e); + return; + } + } + + // If the data we have read so far is >= to the size advertised in the header, + // it means we have all of the data sent. + // We add 4 here because that's the size of the bytes that old the payloadSize + if (stringData.length >= payloadSize + 4) { + // Remove the header + const contentWithoutSize = stringData.slice(4, payloadSize + 4).toString(); + + // Reset the read size and the queued chunks + flushChunksQueue(); + + const json = JSON.parse(contentWithoutSize); + + // Forward to desktop application + this.ipc.send(json); + } + }; + + process.stdin.on("readable", () => { + // A temporary variable holding the nodejs.Buffer of each + // chunk of data read off stdin + let chunk = null; + + // Read all of the available data + // tslint:disable-next-line:no-conditional-assignment + while ((chunk = process.stdin.read()) !== null) { + chunks.push(chunk); + } + + try { + processData(); + } catch (e) { + console.error(e); + } + }); + + process.stdin.on("end", () => { + process.exit(0); + }); + } +} diff --git a/apps/desktop/src/scripts/duo.js b/apps/desktop/src/scripts/duo.js new file mode 100644 index 0000000000..8b712dcf25 --- /dev/null +++ b/apps/desktop/src/scripts/duo.js @@ -0,0 +1,418 @@ +/** + * Duo Web SDK v2 + * Copyright 2017, Duo Security + */ + +var Duo; +(function (root, factory) { + // Browser globals (root is window) + var d = factory(); + // If the Javascript was loaded via a script tag, attempt to autoload + // the frame. + d._onReady(d.init); + // Attach Duo to the `window` object + root.Duo = Duo = d; +}(window, function () { + var DUO_MESSAGE_FORMAT = /^(?:AUTH|ENROLL)+\|[A-Za-z0-9\+\/=]+\|[A-Za-z0-9\+\/=]+$/; + var DUO_ERROR_FORMAT = /^ERR\|[\w\s\.\(\)]+$/; + var DUO_OPEN_WINDOW_FORMAT = /^DUO_OPEN_WINDOW\|/; + var VALID_OPEN_WINDOW_DOMAINS = [ + 'duo.com', + 'duosecurity.com', + 'duomobile.s3-us-west-1.amazonaws.com' + ]; + + var iframeId = 'duo_iframe', + postAction = '', + postArgument = 'sig_response', + host, + sigRequest, + duoSig, + appSig, + iframe, + submitCallback; + + function throwError(message, url) { + throw new Error( + 'Duo Web SDK error: ' + message + + (url ? ('\n' + 'See ' + url + ' for more information') : '') + ); + } + + function hyphenize(str) { + return str.replace(/([a-z])([A-Z])/, '$1-$2').toLowerCase(); + } + + // cross-browser data attributes + function getDataAttribute(element, name) { + if ('dataset' in element) { + return element.dataset[name]; + } else { + return element.getAttribute('data-' + hyphenize(name)); + } + } + + // cross-browser event binding/unbinding + function on(context, event, fallbackEvent, callback) { + if ('addEventListener' in window) { + context.addEventListener(event, callback, false); + } else { + context.attachEvent(fallbackEvent, callback); + } + } + + function off(context, event, fallbackEvent, callback) { + if ('removeEventListener' in window) { + context.removeEventListener(event, callback, false); + } else { + context.detachEvent(fallbackEvent, callback); + } + } + + function onReady(callback) { + on(document, 'DOMContentLoaded', 'onreadystatechange', callback); + } + + function offReady(callback) { + off(document, 'DOMContentLoaded', 'onreadystatechange', callback); + } + + function onMessage(callback) { + on(window, 'message', 'onmessage', callback); + } + + function offMessage(callback) { + off(window, 'message', 'onmessage', callback); + } + + /** + * Parse the sig_request parameter, throwing errors if the token contains + * a server error or if the token is invalid. + * + * @param {String} sig Request token + */ + function parseSigRequest(sig) { + if (!sig) { + // nothing to do + return; + } + + // see if the token contains an error, throwing it if it does + if (sig.indexOf('ERR|') === 0) { + throwError(sig.split('|')[1]); + } + + // validate the token + if (sig.indexOf(':') === -1 || sig.split(':').length !== 2) { + throwError( + 'Duo was given a bad token. This might indicate a configuration ' + + 'problem with one of Duo\'s client libraries.', + 'https://www.duosecurity.com/docs/duoweb#first-steps' + ); + } + + var sigParts = sig.split(':'); + + // hang on to the token, and the parsed duo and app sigs + sigRequest = sig; + duoSig = sigParts[0]; + appSig = sigParts[1]; + + return { + sigRequest: sig, + duoSig: sigParts[0], + appSig: sigParts[1] + }; + } + + /** + * This function is set up to run when the DOM is ready, if the iframe was + * not available during `init`. + */ + function onDOMReady() { + iframe = document.getElementById(iframeId); + + if (!iframe) { + throw new Error( + 'This page does not contain an iframe for Duo to use.' + + 'Add an element like ' + + 'to this page. ' + + 'See https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe ' + + 'for more information.' + ); + } + + // we've got an iframe, away we go! + ready(); + + // always clean up after yourself + offReady(onDOMReady); + } + + /** + * Validate that a MessageEvent came from the Duo service, and that it + * is a properly formatted payload. + * + * The Google Chrome sign-in page injects some JS into pages that also + * make use of postMessage, so we need to do additional validation above + * and beyond the origin. + * + * @param {MessageEvent} event Message received via postMessage + */ + function isDuoMessage(event) { + return Boolean( + event.origin === ('https://' + host) && + typeof event.data === 'string' && + ( + event.data.match(DUO_MESSAGE_FORMAT) || + event.data.match(DUO_ERROR_FORMAT) || + event.data.match(DUO_OPEN_WINDOW_FORMAT) + ) + ); + } + + /** + * Validate the request token and prepare for the iframe to become ready. + * + * All options below can be passed into an options hash to `Duo.init`, or + * specified on the iframe using `data-` attributes. + * + * Options specified using the options hash will take precedence over + * `data-` attributes. + * + * Example using options hash: + * ```javascript + * Duo.init({ + * iframe: "some_other_id", + * host: "api-main.duo.test", + * sig_request: "...", + * post_action: "/auth", + * post_argument: "resp" + * }); + * ``` + * + * Example using `data-` attributes: + * ``` + * + * ``` + * + * @param {Object} options + * @param {String} options.iframe The iframe, or id of an iframe to set up + * @param {String} options.host Hostname + * @param {String} options.sig_request Request token + * @param {String} [options.post_action=''] URL to POST back to after successful auth + * @param {String} [options.post_argument='sig_response'] Parameter name to use for response token + * @param {Function} [options.submit_callback] If provided, duo will not submit the form instead execute + * the callback function with reference to the "duo_form" form object + * submit_callback can be used to prevent the webpage from reloading. + */ + function init(options) { + if (options) { + if (options.host) { + host = options.host; + } + + if (options.sig_request) { + parseSigRequest(options.sig_request); + } + + if (options.post_action) { + postAction = options.post_action; + } + + if (options.post_argument) { + postArgument = options.post_argument; + } + + if (options.iframe) { + if (options.iframe.tagName) { + iframe = options.iframe; + } else if (typeof options.iframe === 'string') { + iframeId = options.iframe; + } + } + + if (typeof options.submit_callback === 'function') { + submitCallback = options.submit_callback; + } + } + + // if we were given an iframe, no need to wait for the rest of the DOM + if (false && iframe) { + ready(); + } else { + // try to find the iframe in the DOM + iframe = document.getElementById(iframeId); + + // iframe is in the DOM, away we go! + if (iframe) { + ready(); + } else { + // wait until the DOM is ready, then try again + onReady(onDOMReady); + } + } + + // always clean up after yourself! + offReady(init); + } + + /** + * This function is called when a message was received from another domain + * using the `postMessage` API. Check that the event came from the Duo + * service domain, and that the message is a properly formatted payload, + * then perform the post back to the primary service. + * + * @param event Event object (contains origin and data) + */ + function onReceivedMessage(event) { + if (isDuoMessage(event)) { + if (event.data.match(DUO_OPEN_WINDOW_FORMAT)) { + var url = event.data.substring("DUO_OPEN_WINDOW|".length); + if (isValidUrlToOpen(url)) { + // Open the URL that comes after the DUO_WINDOW_OPEN token. + window.open(url, "_self"); + } + } + else { + // the event came from duo, do the post back + doPostBack(event.data); + + // always clean up after yourself! + offMessage(onReceivedMessage); + } + } + } + + /** + * Validate that this passed in URL is one that we will actually allow to + * be opened. + * @param url String URL that the message poster wants to open + * @returns {boolean} true if we allow this url to be opened in the window + */ + function isValidUrlToOpen(url) { + if (!url) { + return false; + } + + var parser = document.createElement('a'); + parser.href = url; + + if (parser.protocol === "duotrustedendpoints:") { + return true; + } else if (parser.protocol !== "https:") { + return false; + } + + for (var i = 0; i < VALID_OPEN_WINDOW_DOMAINS.length; i++) { + if (parser.hostname.endsWith("." + VALID_OPEN_WINDOW_DOMAINS[i]) || + parser.hostname === VALID_OPEN_WINDOW_DOMAINS[i]) { + return true; + } + } + return false; + } + + /** + * Point the iframe at Duo, then wait for it to postMessage back to us. + */ + function ready() { + if (!host) { + host = getDataAttribute(iframe, 'host'); + + if (!host) { + throwError( + 'No API hostname is given for Duo to use. Be sure to pass ' + + 'a `host` parameter to Duo.init, or through the `data-host` ' + + 'attribute on the iframe element.', + 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' + ); + } + } + + if (!duoSig || !appSig) { + parseSigRequest(getDataAttribute(iframe, 'sigRequest')); + + if (!duoSig || !appSig) { + throwError( + 'No valid signed request is given. Be sure to give the ' + + '`sig_request` parameter to Duo.init, or use the ' + + '`data-sig-request` attribute on the iframe element.', + 'https://www.duosecurity.com/docs/duoweb#3.-show-the-iframe' + ); + } + } + + // if postAction/Argument are defaults, see if they are specified + // as data attributes on the iframe + if (postAction === '') { + postAction = getDataAttribute(iframe, 'postAction') || postAction; + } + + if (postArgument === 'sig_response') { + postArgument = getDataAttribute(iframe, 'postArgument') || postArgument; + } + + // point the iframe at Duo + iframe.src = [ + 'https://', host, '/frame/web/v1/auth?tx=', duoSig, + '&parent=', encodeURIComponent(document.location.href), + '&v=2.6' + ].join(''); + + // listen for the 'message' event + onMessage(onReceivedMessage); + } + + /** + * We received a postMessage from Duo. POST back to the primary service + * with the response token, and any additional user-supplied parameters + * given in form#duo_form. + */ + function doPostBack(response) { + // create a hidden input to contain the response token + var input = document.createElement('input'); + input.type = 'hidden'; + input.name = postArgument; + input.value = response + ':' + appSig; + + // user may supply their own form with additional inputs + var form = document.getElementById('duo_form'); + + // if the form doesn't exist, create one + if (!form) { + form = document.createElement('form'); + + // insert the new form after the iframe + iframe.parentElement.insertBefore(form, iframe.nextSibling); + } + + // make sure we are actually posting to the right place + form.method = 'POST'; + form.action = postAction; + + // add the response token input to the form + form.appendChild(input); + + // away we go! + if (typeof submitCallback === "function") { + submitCallback.call(null, form); + } else { + form.submit(); + } + } + + return { + init: init, + _onReady: onReady, + _parseSigRequest: parseSigRequest, + _isDuoMessage: isDuoMessage, + _doPostBack: doPostBack + }; +})); diff --git a/apps/desktop/src/scss/base.scss b/apps/desktop/src/scss/base.scss new file mode 100644 index 0000000000..42cbc3f7ff --- /dev/null +++ b/apps/desktop/src/scss/base.scss @@ -0,0 +1,138 @@ +@import "variables.scss"; + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + height: 100%; + font-family: $font-family-sans-serif; + font-size: $font-size-base; + line-height: $line-height-base; +} + +body { + color: $text-color; + background-color: $background-color-alt2; + + @include themify($themes) { + color: themed("textColor"); + background-color: themed("backgroundColorAlt2"); + } +} + +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: $font-family-sans-serif; + + @include themify($themes) { + color: themed("textColor"); + } +} + +p { + margin-bottom: 10px; +} + +ul, +ol { + margin-bottom: 10px; +} + +img { + border: none; +} + +a { + text-decoration: none; + + @include themify($themes) { + color: themed("primaryColor"); + } + + &:hover, + &:focus { + @include themify($themes) { + color: darken(themed("primaryColor"), 6%); + } + } +} + +input, +select, +textarea { + @include themify($themes) { + color: themed("textColor"); + background-color: themed("inputBackgroundColor"); + } +} + +input, +select, +textarea, +button { + font-size: $font-size-base; + font-family: $font-family-sans-serif; + line-height: $line-height-base; +} + +button { + border: none; + background: transparent; + color: inherit; + white-space: nowrap; + cursor: pointer; +} + +textarea { + resize: vertical; +} + +div:not(.modal)::-webkit-scrollbar, +.cdk-virtual-scroll-viewport::-webkit-scrollbar, +.vault-filters::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +div:not(.modal)::-webkit-scrollbar-track, +.cdk-virtual-scroll-viewport::-webkit-scrollbar-track, +.vault-filters::-webkit-scrollbar-track { + background-color: transparent; +} + +div:not(.modal)::-webkit-scrollbar-thumb, +.cdk-virtual-scroll-viewport::-webkit-scrollbar-thumb, +.vault-filters::-webkit-scrollbar-thumb { + border-radius: 10px; + margin-right: 1px; + + @include themify($themes) { + background-color: themed("scrollbarColor"); + } + + &:hover { + @include themify($themes) { + background-color: themed("scrollbarHoverColor"); + } + } +} + +// cdk-virtual-scroll +.cdk-virtual-scroll-viewport { + width: 100%; + height: 100%; + overflow-y: auto; + overflow-x: hidden; +} + +.cdk-virtual-scroll-content-wrapper { + width: 100%; +} diff --git a/apps/desktop/src/scss/box.scss b/apps/desktop/src/scss/box.scss new file mode 100644 index 0000000000..4f05b873b6 --- /dev/null +++ b/apps/desktop/src/scss/box.scss @@ -0,0 +1,489 @@ +@import "variables.scss"; + +.box { + position: relative; + width: 100%; + + .box-header { + margin: 0 10px 5px 10px; + text-transform: uppercase; + display: flex; + + @include themify($themes) { + color: themed("headingColor"); + } + + button { + background-color: transparent; + border: none; + text-transform: uppercase; + + @include themify($themes) { + color: themed("headingColor"); + } + } + + .toggle { + background-color: transparent; + margin-left: 4px; + font-size: $font-size-small; + @include themify($themes) { + color: themed("headingColor"); + } + } + } + + .box-header-expandable { + border: none; + padding: 5px 0px; + text-transform: uppercase; + display: flex; + width: 100%; + box-sizing: border-box; + align-items: center; + + @include themify($themes) { + color: themed("headingColor"); + background-color: themed("boxBackgroundColor"); + } + + &:hover, + &:focus, + &.active { + @include themify($themes) { + background-color: themed("boxBackgroundHoverColor"); + } + } + + .icon { + display: flex; + align-items: flex-end; + margin-left: 5px; + + @include themify($themes) { + color: themed("headingColor"); + } + } + } + + .box-content { + border-radius: $border-radius; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), + 0 1px 5px 0 rgba(0, 0, 0, 0.2); + + @include themify($themes) { + background-color: themed("boxBackgroundColor"); + } + + &.box-content-padded { + padding: 10px 15px; + } + + &.condensed .box-content-row, + .box-content-row.condensed { + padding-top: 5px; + padding-bottom: 5px; + } + + &.no-hover .box-content-row, + .box-content-row.no-hover { + &:hover, + &:focus { + background-color: initial; + } + } + } + + .box-footer { + margin: 5px 10px; + font-size: $font-size-small; + + @include themify($themes) { + color: themed("mutedColor"); + } + } +} + +.box-content-row { + display: block; + width: 100%; + padding: 10px 15px; + position: relative; + z-index: 1; + text-align: left; + + &:before { + content: ""; + position: absolute; + right: 0; + bottom: 0; + height: 1px; + width: calc(100% - 10px); + border-bottom: 1px solid #000000; + + @include themify($themes) { + border-bottom-color: themed("boxBorderColor"); + } + } + + &:first-child, + &:last-child { + border-radius: $border-radius; + + .progress { + border-bottom-left-radius: $border-radius; + border-bottom-right-radius: $border-radius; + } + } + + &:last-child { + &:before { + border: none; + height: 0; + } + } + + &:after { + content: ""; + display: table; + clear: both; + } + + &:hover, + &:focus, + &.active { + @include themify($themes) { + background-color: themed("boxBackgroundHoverColor"); + > * { + background-color: themed("boxBackgroundHoverColor"); + } + } + } + + &.pre { + white-space: pre; + overflow-x: auto; + } + + &.pre-wrap { + white-space: pre-wrap; + overflow-x: auto; + } + + .row-label, + label:not(.unstyled) { + font-size: $font-size-small; + display: block; + width: 100%; + margin-bottom: 5px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + .sub-label { + margin-left: 10px; + } + } + + .text, + .detail { + display: block; + + @include themify($themes) { + color: themed("textColor"); + } + } + + .detail { + font-size: $font-size-small; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + .img-right { + float: right; + margin-left: 10px; + } + + .row-main { + flex-grow: 1; + min-width: 0; + } + + &.box-content-row-flex, + .box-content-row-flex, + &.box-content-row-checkbox, + &.box-content-row-input, + &.box-content-row-slider, + &.box-content-row-multi { + display: flex; + align-items: center; + word-break: break-word; + } + + &.box-content-row-multi { + width: 100%; + + input:not([type="checkbox"]):not([type="radio"]) { + width: 100%; + } + + input + label.sr-only + select { + margin-top: 5px; + } + + > a, + > button { + padding: 8px 8px 8px 4px; + margin: 0; + + @include themify($themes) { + color: themed("dangerColor"); + } + } + } + + &.box-content-row-checkbox, + &.box-content-row-input, + &.box-content-row-slider { + label, + .row-label { + font-size: $font-size-base; + display: inline; + width: initial; + margin-bottom: 0; + + @include themify($themes) { + color: themed("textColor"); + } + } + + > span { + @include themify($themes) { + color: themed("mutedColor"); + } + } + + > input { + margin: 0 0 0 auto; + padding: 0; + } + + > * { + margin-right: 15px; + + &:last-child { + margin-right: 0; + } + } + } + + &.box-content-row-input { + label { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + input { + text-align: right; + width: 45px !important; + } + } + + &.box-content-row-slider { + input[type="range"] { + height: 10px; + width: 220px !important; + } + + input[type="number"] { + text-align: right; + width: 45px !important; + } + + label { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } + + &.box-content-row-radio { + display: flex; + flex-direction: column; + .item { + display: flex; + flex: 1; + align-items: center; + + > .radio { + margin-right: 5px; + margin-top: 0; + } + } + } + + input:not([type="checkbox"]):not([type="radio"]), + textarea { + border: none; + width: 100%; + background-color: transparent; + + &::-webkit-input-placeholder { + @include themify($themes) { + color: themed("inputPlaceholderColor"); + } + } + + &:focus { + outline: none; + } + } + + select { + width: 100%; + border: 1px solid #000000; + border-radius: $border-radius; + + @include themify($themes) { + border-color: themed("inputBorderColor"); + } + } + + .action-buttons { + display: flex; + margin-left: 5px; + + .row-btn { + @extend .icon-btn; + } + + &.no-pad .row-btn { + padding-top: 0; + padding-bottom: 0; + } + } + + &:not(.box-draggable-row) { + .action-buttons .row-btn:last-child { + margin-right: -6px !important; + } + } + + &.box-draggable-row { + &.box-content-row-checkbox { + input[type="checkbox"] + .drag-handle { + margin-left: 10px; + } + } + } + + .drag-handle { + cursor: move; + padding: 10px 2px 10px 8px; + user-select: none; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + &.cdk-drag-preview { + position: relative; + display: flex; + align-items: center; + opacity: 0.8; + + @include themify($themes) { + background-color: themed("boxBackgroundColor"); + } + } + + select.field-type { + margin: 5px 0 0 25px; + width: calc(100% - 25px); + } + + .row-sub-icon { + @include themify($themes) { + color: themed("disabledIconColor"); + } + } + + .row-sub-label { + margin: 0 15px; + white-space: nowrap; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + .progress { + display: flex; + height: 5px; + overflow: hidden; + margin: 5px -15px -10px; + + .progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + white-space: nowrap; + background-color: $brand-primary; + } + } + + .icon { + display: flex; + justify-content: center; + align-items: center; + min-width: 34px; + height: 100%; + margin-left: -5px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + &.icon-small { + min-width: 25px; + } + } + + .radio-group { + display: flex; + justify-content: flex-start; + align-items: center; + margin-bottom: 5px; + + input { + flex-grow: 0; + } + + label { + margin: 0 0 0 5px; + flex-grow: 1; + font-size: $font-size-base; + display: block; + width: 100%; + + @include themify($themes) { + color: themed("textColor"); + } + } + + &.align-start { + align-items: start; + margin-top: 10px; + + label { + margin-top: -4px; + } + } + } +} diff --git a/apps/desktop/src/scss/buttons.scss b/apps/desktop/src/scss/buttons.scss new file mode 100644 index 0000000000..4b6fe81f63 --- /dev/null +++ b/apps/desktop/src/scss/buttons.scss @@ -0,0 +1,182 @@ +@import "variables.scss"; + +.btn, +.vault .footer button, +.modal-footer button { + border-radius: $border-radius; + padding: 7px 15px; + border: 1px solid #000000; + font-size: $font-size-base; + white-space: nowrap; + text-align: center; + cursor: pointer; + + @include themify($themes) { + background-color: themed("buttonBackgroundColor"); + border-color: themed("buttonBorderColor"); + color: themed("buttonColor"); + } + + &.primary { + @include themify($themes) { + color: themed("buttonPrimaryColor"); + } + } + + &.danger { + @include themify($themes) { + color: themed("buttonDangerColor"); + } + } + + &:hover:not([disabled]) { + cursor: pointer; + + @include themify($themes) { + background-color: darken(themed("buttonBackgroundColor"), 1.5%); + border-color: darken(themed("buttonBorderColor"), 17%); + color: darken(themed("buttonColor"), 10%); + } + + &.primary { + @include themify($themes) { + color: darken(themed("buttonPrimaryColor"), 6%); + } + } + + &.danger { + @include themify($themes) { + color: darken(themed("buttonDangerColor"), 6%); + } + } + } + + &:focus:not([disabled]) { + cursor: pointer; + + @include themify($themes) { + background-color: darken(themed("buttonBackgroundColor"), 6%); + border-color: darken(themed("buttonBorderColor"), 25%); + } + } + + &[disabled] { + opacity: 0.65; + cursor: default !important; + } + + &.block { + display: block; + width: 100%; + } + + &.link { + border: none !important; + background: none !important; + + &:focus { + text-decoration: underline; + } + } +} + +.action-buttons { + .btn { + &:focus { + outline: auto; + } + } +} + +.btn-submit { + position: relative; + overflow: hidden; + + .bwi-spinner { + position: absolute; + display: none; + align-items: center; + justify-content: center; + bottom: 0; + top: 0; + left: 0; + right: 0; + } + + &:disabled:not(.manual), + &.loading { + .bwi-spinner { + display: flex; + } + + span { + visibility: hidden; + } + } +} + +.icon-btn { + cursor: pointer; + padding: 10px 8px; + background: none; + border: none; + + @include themify($themes) { + color: themed("boxRowButtonColor"); + } + + &.primary { + @include themify($themes) { + color: themed("buttonPrimaryColor"); + } + } + + &.danger { + @include themify($themes) { + color: themed("buttonDangerColor"); + } + } + + &:hover, + &:focus { + @include themify($themes) { + color: themed("boxRowButtonHoverColor"); + } + + &.primary { + @include themify($themes) { + color: darken(themed("buttonPrimaryColor"), 6%); + } + } + + &.danger { + @include themify($themes) { + color: darken(themed("buttonDangerColor"), 6%); + } + } + } + + &.disabled { + @include themify($themes) { + color: themed("disabledIconColor"); + } + + &:hover { + @include themify($themes) { + color: themed("disabledIconColor"); + } + } + } +} + +button.no-btn { + @extend a; + background: transparent; + border: none; + @include themify($themes) { + color: themed("textColor"); + } + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/apps/desktop/src/scss/environment.scss b/apps/desktop/src/scss/environment.scss new file mode 100644 index 0000000000..83c3440ce7 --- /dev/null +++ b/apps/desktop/src/scss/environment.scss @@ -0,0 +1,55 @@ +html.os_macos { + body.layout_frontend { + -webkit-app-region: drag; + + button, + a, + i, + b, + span, + input, + p, + h1, + h2, + h3, + h4, + h5, + h6, + img, + select, + textarea, + label, + .box, + .modal-backdrop { + -webkit-app-region: no-drag; + } + } + + #login-page { + .content { + a.settings-icon { + position: absolute; + left: unset; + right: 20px; + + span { + margin-right: 8px; + float: left; + } + } + } + } + + .vault .header-search { + -webkit-app-region: drag; + + input, + i { + -webkit-app-region: no-drag; + } + } + + .vault > .groupings > .content > .inner-content { + padding-top: 0; + } +} diff --git a/apps/desktop/src/scss/grid.scss b/apps/desktop/src/scss/grid.scss new file mode 100644 index 0000000000..8f58d81648 --- /dev/null +++ b/apps/desktop/src/scss/grid.scss @@ -0,0 +1,10 @@ +.row { + display: flex; + margin: 0 -15px; +} + +.col { + flex-basis: 0; + flex-grow: 1; + padding: 0 15px; +} diff --git a/apps/desktop/src/scss/header.scss b/apps/desktop/src/scss/header.scss new file mode 100644 index 0000000000..fdeba451c2 --- /dev/null +++ b/apps/desktop/src/scss/header.scss @@ -0,0 +1,203 @@ +.header { + -webkit-app-region: drag; + min-height: 44px; + max-height: 44px; + border-bottom: 1px solid #000000; + display: grid; + grid-template-columns: 25% 1fr 25%; + grid-column-gap: 5px; + justify-items: center; + align-items: center; + + @include themify($themes) { + background-color: themed("headerBackgroundColor"); + border-bottom-color: themed("headerBorderColor"); + + app-search { + grid-column-start: 2; + width: 100%; + + [type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; + appearance: none; + height: 15px; + width: 15px; + background-repeat: no-repeat; + mask-image: url("../images/close-button-white.svg"); + -webkit-mask-image: url("../images/close-button-white.svg"); + background-color: themed("headerInputColor"); + } + } + } + + app-account-switcher { + justify-self: end; + height: 100%; + } + + .search { + padding: 0 7px; + width: 100%; + text-align: left; + position: relative; + + .bwi { + position: absolute; + top: 7px; + left: 15px; + + @include themify($themes) { + color: themed("headerInputPlaceholderColor"); + } + } + + input { + width: 100%; + margin: 0; + border: none; + padding: 5px 10px 5px 30px; + border-radius: $border-radius; + + @include themify($themes) { + background-color: themed("headerInputBackgroundColor"); + color: themed("headerInputColor"); + } + + &:focus { + border-radius: $border-radius; + outline: none; + + @include themify($themes) { + background-color: themed("headerInputBackgroundFocusColor"); + } + } + + &::-webkit-input-placeholder { + @include themify($themes) { + color: themed("headerInputPlaceholderColor"); + } + } + } + } +} + +.account-switcher { + display: grid; + grid-template-columns: auto 1fr auto; + grid-column-gap: 5px; + align-items: center; + justify-items: center; + padding: 0 10px; + height: 100%; + user-select: none; + + border: none; + background: transparent; + width: auto; + + @include themify($themes) { + color: themed("accountSwitcherTextColor"); + } + + img { + display: block; + } + + span { + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + &:hover { + @include themify($themes) { + background-color: themed("headerBorderColor"); + color: themed("accountSwitcherTextColor"); + } + } +} + +.account-switcher-dropdown { + @include themify($themes) { + background-color: themed("accountSwitcherBackgroundColor"); + } + margin-right: 5px; + margin-top: 1px; // Fix for border-bottom in header + width: 100%; + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.12), + 0 1px 5px 0 rgba(0, 0, 0, 0.2); + border-radius: $border-radius; + + button { + border: none; + background: transparent; + width: 100%; + padding: 5px 10px; + + @include themify($themes) { + color: themed("textColor"); + } + + &:hover { + @include themify($themes) { + background-color: themed("backgroundColorAlt2"); + } + } + } + + .accounts { + padding: 7px 0; + + .account { + display: grid; + grid-template-columns: 24px auto 24px; + grid-column-gap: 11px; + align-items: center; + justify-items: left; + + .accountInfo { + display: grid; + text-align: left; + + .email { + font-size: $font-size-base; + max-width: 168px; + overflow: hidden; + text-overflow: ellipsis; + } + + .server { + font-size: $font-size-small; + } + + .status { + font-size: $font-size-small; + font-style: italic; + } + } + } + } + + .border { + @include themify($themes) { + background: themed("borderColor"); + } + left: 10px; + width: calc(100% - 20px); + height: 1px; + position: relative; + } + + .add { + margin: 4px 0; + text-align: left; + } + + .accountLimitReached { + display: block; + margin: 4px 0; + padding: 5px 10px; + font-size: $font-size-small; + } +} diff --git a/apps/desktop/src/scss/left-nav.scss b/apps/desktop/src/scss/left-nav.scss new file mode 100644 index 0000000000..bd993c3601 --- /dev/null +++ b/apps/desktop/src/scss/left-nav.scss @@ -0,0 +1,196 @@ +.left-nav { + order: 1; + display: flex; + flex-direction: column; + width: 22%; + min-width: 175px; + max-width: 250px; + border-right: 1px solid #000000; + flex-grow: 1; + justify-content: space-between; + + @include themify($themes) { + background-color: themed("backgroundColorAlt"); + border-right-color: themed("borderColor"); + } +} + +.vault-filters { + user-select: none; + scrollbar-gutter: stable; + padding: 10px 15px; + overflow-x: hidden; + overflow-y: auto; + height: 100%; + + .filter { + hr { + margin: 1em 0 1em 0; + @include themify($themes) { + border-color: themed("hrColor"); + } + } + } +} + +.filter-heading { + display: flex; + text-transform: uppercase; + font-weight: normal; + margin-bottom: 5px; + align-items: center; + padding-top: 5px; + padding-bottom: 5px; + + h2 { + @include themify($themes) { + color: themed("headingColor"); + } + font-size: $font-size-base; + } + + button { + @extend .no-btn; + text-transform: uppercase; + + @include themify($themes) { + color: themed("headingButtonColor"); + } + + &:hover, + &:focus { + @include themify($themes) { + color: themed("headingButtonHoverColor"); + } + } + } + + button.add-button { + margin-left: auto; + margin-right: 5px; + } + + &.active { + .filter-button { + h2 { + @include themify($themes) { + color: themed("primaryColor"); + } + } + } + } + + .filter-button { + &:hover { + h2 { + @include themify($themes) { + color: themed("primaryColor"); + } + } + } + } +} + +.filter-options { + word-break: break-all; + padding: 0; + list-style: none; + width: 100%; + margin: 0 0 15px 0; + .nested-filter-options { + list-style: none; + margin-bottom: 0px; + padding-left: 0.85em; + } +} + +.filter-option { + top: 8px; + width: 100%; + + @include themify($themes) { + color: themed("textColor"); + } + + &.active { + > .filter-buttons { + .filter-button { + @include themify($themes) { + color: themed("primaryColor"); + font-weight: bold; + } + } + + .edit-button { + visibility: visible; + } + } + } +} + +.filter-buttons { + padding: 5px 0; + display: flex; + align-items: center; + width: 100%; + + &:hover, + &:focus { + .filter-button { + @include themify($themes) { + color: themed("primaryColor"); + } + } + } + + button { + @extend .no-btn; + } + + .edit-button, + .toggle-button { + @include themify($themes) { + color: themed("headingButtonColor"); + } + + &:hover, + &:focus { + @include themify($themes) { + color: themed("headingButtonHoverColor"); + } + } + } + + .edit-button { + visibility: hidden; + margin-left: auto; + margin-right: 5px; + } +} + +.nav { + height: 55px; + width: 100%; + display: flex; + .btn { + width: 100%; + font-size: $font-size-base * 0.8; + flex: 1; + border: 0; + border-radius: 0; + padding-bottom: 4px; + + &:not(.active) { + @include themify($themes) { + background-color: themed("backgroundColorAlt"); + } + } + + i { + font-size: $font-size-base * 1.5; + display: block; + margin-bottom: 2px; + text-align: center; + } + } +} diff --git a/apps/desktop/src/scss/list.scss b/apps/desktop/src/scss/list.scss new file mode 100644 index 0000000000..343dd550f0 --- /dev/null +++ b/apps/desktop/src/scss/list.scss @@ -0,0 +1,154 @@ +@import "variables.scss"; + +.list > button { + padding: 3px 10px; + text-decoration: none; + user-select: none; + z-index: 1; + + @include themify($themes) { + color: themed("textColor"); + background-color: themed("listItemBackgroundColor"); + } + + &:after { + content: ""; + display: table; + clear: both; + } + + &:before { + content: ""; + position: absolute; + right: 0; + bottom: 0; + height: 1px; + width: calc(100% - 10px); + border-bottom: 1px solid #000000; + + @include themify($themes) { + border-bottom-color: themed("listItemBorderColor"); + } + } + + &:last-child:before { + border: none; + height: 0; + } + + &:hover, + &:focus, + &.active { + @include themify($themes) { + background-color: themed("listItemBackgroundHoverColor"); + } + } + + &.active { + border-left: 5px solid #000000; + padding-left: 5px; + + @include themify($themes) { + border-left-color: themed("primaryColor"); + } + } + + &:focus:not(.active) { + border-left: 5px solid #000000; + padding-left: 5px; + + @include themify($themes) { + border-left-color: themed("mutedColor"); + } + } + + .text, + .detail { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: block; + + @include themify($themes) { + color: themed("textColor"); + } + } + + .detail { + font-size: $font-size-small; + + @include themify($themes) { + color: themed("mutedColor"); + } + } + + .icon { + display: flex; + justify-content: center; + align-items: center; + float: left; + height: 36px; + width: 34px; + margin-left: -5px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + img { + border-radius: $border-radius; + max-height: 20px; + max-width: 20px; + } + } +} + +.list > button.flex-list-item { + display: flex; + align-items: center; + width: 100%; + text-align: left; + + .item-icon { + display: block; + margin-left: -5px; + margin-right: 4px; + @include themify($themes) { + color: themed("mutedColor"); + } + } + + .item-content { + display: block; + .item-title { + display: block; + .title-badges { + @include themify($themes) { + color: themed("mutedColor"); + } + } + } + + .item-details { + font-size: $font-size-small; + @include themify($themes) { + color: themed("mutedColor"); + } + } + } + + .flex-cipher-list-item { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + > * { + text-align: left; + } + } +} + +.list.full-height { + height: 100%; + overflow-y: auto; +} diff --git a/apps/desktop/src/scss/loading.scss b/apps/desktop/src/scss/loading.scss new file mode 100644 index 0000000000..2562ca4998 --- /dev/null +++ b/apps/desktop/src/scss/loading.scss @@ -0,0 +1,10 @@ +.container { + &.loading-spinner { + display: flex; + height: 100%; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + } +} diff --git a/apps/desktop/src/scss/misc.scss b/apps/desktop/src/scss/misc.scss new file mode 100644 index 0000000000..250ecc1973 --- /dev/null +++ b/apps/desktop/src/scss/misc.scss @@ -0,0 +1,470 @@ +@import "variables.scss"; + +small, +.small { + font-size: $font-size-small; +} + +.bg-primary { + @include themify($themes) { + background-color: themed("primaryColor") !important; + } +} + +.bg-success { + @include themify($themes) { + background-color: themed("successColor") !important; + } +} + +.bg-danger { + @include themify($themes) { + background-color: themed("dangerColor") !important; + } +} + +.bg-info { + @include themify($themes) { + background-color: themed("infoColor") !important; + } +} + +.bg-warning { + @include themify($themes) { + background-color: themed("warningColor") !important; + } +} + +.text-primary { + @include themify($themes) { + color: themed("primaryColor") !important; + } +} + +.text-success { + @include themify($themes) { + color: themed("successColor") !important; + } +} + +.text-danger { + @include themify($themes) { + color: themed("dangerColor") !important; + } +} + +.text-warning { + @include themify($themes) { + color: themed("warningColor") !important; + } +} + +.text-muted { + @include themify($themes) { + color: themed("mutedColor") !important; + } +} + +.text-default { + @include themify($themes) { + color: themed("textColor") !important; + } +} + +.text-center { + text-align: center; +} + +.no-margin { + margin: 0 !important; +} + +.font-weight-semibold { + font-weight: 600; +} + +p.lead { + font-size: $font-size-large; + margin-bottom: 20px; + font-weight: normal; +} + +.monospaced { + font-family: $font-family-monospace; +} + +.show-whitespace { + white-space: pre-wrap; +} + +.font-weight-bold { + font-weight: bold; +} + +.sr-only { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + border: 0 !important; +} + +.totp { + .totp-code { + font-family: $font-family-monospace; + font-size: 1.1em; + } + + .totp-countdown { + margin: 3px 3px 0 0; + display: block; + user-select: none; + + .totp-sec { + font-size: 0.85em; + position: absolute; + line-height: 32px; + width: 32px; + text-align: center; + } + + svg { + width: 32px; + height: 32px; + transform: rotate(-90deg); + } + + .totp-circle { + fill: none; + + @include themify($themes) { + stroke: themed("totpStrokeColor"); + } + + &.inner { + stroke-width: 3; + stroke-dasharray: 78.6; + stroke-dashoffset: 0; + } + + &.outer { + stroke-width: 2; + stroke-dasharray: 88; + stroke-dashoffset: 0; + } + } + } + + &.low { + .totp-sec, + .totp-code { + @include themify($themes) { + color: themed("dangerColor"); + } + } + + .totp-circle { + @include themify($themes) { + stroke: themed("dangerColor"); + } + } + } +} + +.modal-title { + margin: 0 10px 5px 10px; + text-transform: uppercase; + display: flex; + + @include themify($themes) { + color: themed("headingColor"); + } +} + +.generated-block { + font-size: $font-size-large; + font-family: $font-family-monospace; + min-height: 50px; + display: flex; + align-items: center; + justify-content: center; + + .modal-body & { + margin: 10px; + } + + .generated-wrapper { + text-align: left; + width: 100%; + } + + .action-buttons { + display: flex; + align-self: center; + + button { + margin-left: 10px; + } + } +} + +.generated-wrapper { + word-break: break-all; + white-space: pre-wrap; + min-width: 0; +} + +.password-number { + @include themify($themes) { + color: themed("passwordNumberColor"); + } +} + +.password-special { + @include themify($themes) { + color: themed("passwordSpecialColor"); + } +} + +#duo-frame { + background: url("../images/loading.svg") 0 0 no-repeat; + height: 330px; + margin: 0 -150px 15px -150px; + + iframe { + width: 100%; + height: 100%; + border: none; + } +} + +#web-authn-frame { + background: url("../images/loading.svg") 0 0 no-repeat; + height: 250px; + margin: 0 0 15px 0; + + iframe { + width: 100%; + height: 100%; + border: none; + } +} + +#hcaptcha_iframe { + width: 100%; + border: none; + transition: height 0.25s linear; +} + +form, +.form { + .form-group { + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + + label { + display: inline-block; + margin-bottom: 2px; + } + + input, + select, + textarea { + border: 1px solid #000000; + border-radius: $border-radius; + display: block; + + @include themify($themes) { + border-color: themed("inputBorderColor"); + } + } + + input[type="text"], + input[type="number"] { + padding: 5px; + width: 100%; + } + } + + .checkbox { + position: relative; + display: block; + padding-left: 18px; + + label { + margin-bottom: 0; + } + + input[type="checkbox"] { + position: absolute; + margin-top: 4px; + margin-left: -18px; + } + } + + .radio { + position: relative; + display: block; + padding-left: 18px; + margin-top: 4px; + + &.radio-mt-2 { + margin-top: 2px; + } + + label { + margin-bottom: 0; + } + + input[type="radio"] { + position: absolute; + margin-top: 4px; + margin-left: -18px; + } + } + + .help-block { + margin-top: 3px; + display: block; + + @include themify($themes) { + color: themed("mutedColor"); + } + } +} + +app-root > #loading, +.loading { + display: flex; + text-align: center; + justify-content: center; + align-items: center; + height: 100%; + width: 100%; + color: $text-muted; + + @include themify($themes) { + color: themed("mutedColor"); + } +} + +.logo-image { + @include themify($themes) { + content: url("../images/logo-" + themed("logoSuffix") + "@2x.png"); + } +} + +[hidden] { + display: none !important; +} + +.draggable { + cursor: move; +} + +.callout { + padding: 10px; + margin-bottom: 10px; + border: 1px solid #000000; + border-left-width: 5px; + border-radius: 3px; + @include themify($themes) { + border-color: themed("calloutBorderColor"); + background-color: themed("calloutBackgroundColor"); + } + + .callout-heading { + margin-top: 0; + } + + h3.callout-heading { + font-weight: bold; + text-transform: uppercase; + } + + &.callout-primary { + @include themify($themes) { + border-left-color: themed("primaryColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("primaryColor"); + } + } + } + + &.callout-info { + @include themify($themes) { + border-left-color: themed("infoColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("infoColor"); + } + } + } + + &.callout-danger { + @include themify($themes) { + border-left-color: themed("dangerColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("dangerColor"); + } + } + } + + &.callout-success { + @include themify($themes) { + border-left-color: themed("successColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("successColor"); + } + } + } + + &.callout-warning { + @include themify($themes) { + border-left-color: themed("warningColor"); + } + + .callout-heading { + @include themify($themes) { + color: themed("warningColor"); + } + } + } + + ul { + padding-left: 40px; + margin: 0; + } +} + +.password-reprompt { + text-align: left; + margin-top: 15px; +} + +.set-pin-modal { + .box { + margin-bottom: 15px; + } +} + +.rounded-circle { + border-radius: 50% !important; +} diff --git a/apps/desktop/src/scss/modal.scss b/apps/desktop/src/scss/modal.scss new file mode 100644 index 0000000000..1d86b1e880 --- /dev/null +++ b/apps/desktop/src/scss/modal.scss @@ -0,0 +1,356 @@ +@import "variables.scss"; + +$white: white; +$black: black; +$line-height-base: 14px; +$border-radius-lg: $border-radius; + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss + +$grid-breakpoints: ( + xs: 0, + sm: 576px, + md: 768px, + lg: 992px, + xl: 1200px, +) !default; + +$zindex-modal-backdrop: 1040 !default; +$zindex-modal: 1050 !default; + +// Padding applied to the modal body +$modal-inner-padding: 10px !default; + +$modal-dialog-margin: 0.5rem !default; +$modal-dialog-margin-y-sm-up: 1.75rem !default; + +$modal-title-line-height: $line-height-base !default; + +//$modal-content-bg: $background-color-alt !default; +$modal-content-border-color: rgba($black, 0.2) !default; +$modal-content-border-width: 1px !default; +$modal-content-box-shadow-xs: none; +$modal-content-box-shadow-sm-up: none; + +$modal-backdrop-bg: $black !default; +$modal-backdrop-opacity: 0.5 !default; +$modal-header-border-color: $border-color-dark !default; +$modal-footer-border-color: $modal-header-border-color !default; +$modal-header-border-width: $modal-content-border-width !default; +$modal-footer-border-width: $modal-header-border-width !default; +$modal-header-padding: 12px !default; + +$modal-lg: 800px !default; +$modal-md: 500px !default; +$modal-sm: 300px !default; + +$modal-transition: transform 0.3s ease-out !default; + +$close-font-size: $font-size-base * 1.5 !default; +$close-font-weight: bold !default; +$close-color: $black !default; +$close-text-shadow: 0 1px 0 $white !default; + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_breakpoints.scss + +@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) { + $min: breakpoint-min($name, $breakpoints); + + @if $min { + @media (min-width: $min) { + @content; + } + } @else { + @content; + } +} + +@function breakpoint-min($name, $breakpoints: $grid-breakpoints) { + $min: map-get($breakpoints, $name); + @return if($min != 0, $min, null); +} + +// Custom Added CSS animations + +@keyframes modalshow { + 0% { + opacity: 0; + transform: translate(0, -25%); + } + + 100% { + opacity: 1; + transform: translate(0, 0); + } +} + +@keyframes backdropshow { + 0% { + opacity: 0; + } + + 100% { + opacity: $modal-backdrop-opacity; + } +} + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_modal.scss + +// .modal-open - body class for killing the scroll +// .modal - container to scroll within +// .modal-dialog - positioning shell for the actual modal +// .modal-content - actual modal w/ bg and corners and stuff + +// Kill the scroll on the body +.modal-open { + overflow: hidden; +} + +// Container that the modal scrolls within +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: $zindex-modal; + //display: none; + overflow: hidden; + // Prevent Chrome on Windows from adding a focus outline. For details, see + // https://github.com/twbs/bootstrap/pull/10951. + outline: 0; + // We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a + // gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342 + // See also https://github.com/twbs/bootstrap/issues/17695 + .modal-open & { + overflow-x: hidden; + overflow-y: auto; + } +} + +// Shell div to position the modal with bottom padding +.modal-dialog { + position: relative; + width: auto; + margin: $modal-dialog-margin; + // allow clicks to pass through for custom click handling to close modal + pointer-events: none; + // When fading in the modal, animate it to slide down + .modal.fade & { + //@include transition($modal-transition); + //transform: translate(0, -25%); + animation: modalshow 0.3s ease-in; + } + //.modal.show & { + // transform: translate(0, 0); + //} + transform: translate(0, 0); +} + +.modal-dialog-centered { + display: flex; + align-items: center; + min-height: calc(100% - (#{$modal-dialog-margin} * 2)); +} + +// Actual modal +.modal-content { + position: relative; + display: flex; + flex-direction: column; + width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog` + // counteract the pointer-events: none; in the .modal-dialog + pointer-events: auto; + //background-color: $modal-content-bg; + background-clip: padding-box; + border: $modal-content-border-width solid $modal-content-border-color; + //@include border-radius($border-radius-lg); + //@include box-shadow($modal-content-box-shadow-xs); + border-radius: $border-radius-lg; + box-shadow: $modal-content-box-shadow-xs; + // Remove focus outline from opened modal + outline: 0; + + @include themify($themes) { + background-color: themed("backgroundColorAlt"); + } +} + +// Modal background +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: $zindex-modal-backdrop; + background-color: $modal-backdrop-bg; + // Fade for backdrop + &.fade { + //opacity: 0; + animation: backdropshow 0.1s ease-in; + } + //&.show { + // opacity: $modal-backdrop-opacity; + //} + opacity: $modal-backdrop-opacity; +} + +// Modal header +// Top section of the modal w/ title and dismiss +.modal-header { + display: flex; + align-items: flex-start; // so the close btn always stays on the upper right corner + justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends + padding: $modal-header-padding $modal-inner-padding; + border-bottom: $modal-header-border-width solid $modal-header-border-color; + //@include border-top-radius($border-radius-lg); + + @include themify($themes) { + border-bottom-color: themed("borderColor"); + } + + .close { + padding: $modal-header-padding $modal-inner-padding; + // auto on the left force icon to the right even when there is no .modal-title + margin: (-$modal-header-padding) (-$modal-inner-padding) (-$modal-header-padding) auto; + } + + h5 { + font-size: $font-size-base; + font-weight: bold; + display: flex; + align-items: center; + + .bwi { + margin-right: 5px; + } + } +} + +// Title text within header +.modal-title { + margin-bottom: 0; + line-height: $modal-title-line-height; +} + +// Modal body +// Where all modal content resides (sibling of .modal-header and .modal-footer) +.modal-body { + position: relative; + // Enable `flex-grow: 1` so that the body take up as much space as possible + // when should there be a fixed height on `.modal-dialog`. + flex: 1 1 auto; + padding: $modal-inner-padding; +} + +// Footer (for actions) +.modal-footer { + display: flex; + align-items: center; // vertically center + //justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items + padding: $modal-inner-padding; + border-top: $modal-footer-border-width solid $modal-footer-border-color; + + @include themify($themes) { + border-top-color: themed("borderColor"); + } + + // Easily place margin between footer elements + button { + margin-right: 10px; + + &:last-child { + margin-right: 0; + } + } + + .right { + margin-left: auto; + display: flex; + } +} + +// Measure scrollbar width for padding body during modal show/hide +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +// Scale up the modal +@include media-breakpoint-up(sm) { + // Automatically set modal's width for larger viewports + .modal-dialog { + max-width: $modal-md; + margin: $modal-dialog-margin-y-sm-up auto; + } + + .modal-dialog-centered { + min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2)); + } + + .modal-content { + //@include box-shadow($modal-content-box-shadow-sm-up); + box-shadow: $modal-content-box-shadow-sm-up; + } + + .modal-sm { + max-width: $modal-sm; + } +} + +@include media-breakpoint-up(lg) { + .modal-lg { + max-width: $modal-lg; + } +} + +// ref: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_close.scss + +.close { + float: right; + font-size: $close-font-size; + font-weight: $close-font-weight; + line-height: 1; + color: $close-color; + text-shadow: $close-text-shadow; + opacity: 0.5; + + &:hover, + &:focus { + color: $close-color; + text-decoration: none; + opacity: 0.75; + } + // Opinionated: add "hand" cursor to non-disabled .close elements + &:not(:disabled):not(.disabled) { + cursor: pointer; + } +} + +// Additional properties for button version +// iOS requires the button element instead of an anchor tag. +// If you want the anchor version, it requires `href="#"`. +// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile + +// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type +button.close { + padding: 0; + background-color: transparent; + border: 0; + -webkit-appearance: none; +} +// stylelint-enable + +// box + +.modal-content .box { + margin-top: 20px; + + &:first-child { + margin-top: 0; + } +} diff --git a/apps/desktop/src/scss/pages.scss b/apps/desktop/src/scss/pages.scss new file mode 100644 index 0000000000..cb91290e44 --- /dev/null +++ b/apps/desktop/src/scss/pages.scss @@ -0,0 +1,245 @@ +@import "variables.scss"; + +#login-page, +#lock-page, +#sso-page, +#set-password-page, +#remove-password-page { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + + @media (min-height: 500px) { + height: calc(100%); + } + + @media (min-height: 800px) { + height: calc(100%); + } + + img { + margin: 0 auto 15px; + width: 284px; + display: block; + } +} + +#register-page, +#hint-page, +#two-factor-page, +#update-temp-password-page, +#remove-password-page { + padding-top: 20px; + + .content { + margin: 0 auto; + } + + img { + margin-bottom: 10px; + max-width: 100%; + height: auto; + display: block; + border-radius: $border-radius; + } +} + +#login-page, +#register-page, +#hint-page, +#two-factor-page, +#lock-page, +#update-temp-password-page { + .content { + width: 300px; + transition: width 0.25s linear; + + p { + text-align: center; + } + + p.lead, + h1 { + font-size: $font-size-large; + text-align: center; + margin-bottom: 20px; + font-weight: normal; + } + + .box { + margin-bottom: 20px; + + &.last { + margin-bottom: 15px; + } + } + + .buttons { + &:not(.with-rows), + .buttons-row { + display: flex; + margin-bottom: 10px; + } + + &:not(.with-rows), + .buttons-row:last-child { + margin-bottom: 20px; + } + + button { + margin-right: 10px; + + &:last-child { + margin-right: 0; + } + } + } + + .sub-options { + text-align: center; + margin-bottom: 20px; + + a { + display: block; + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + } + } + + a.settings-icon { + position: absolute; + top: 10px; + left: 10px; + + @include themify($themes) { + color: themed("mutedColor"); + } + + span { + visibility: hidden; + } + + &:hover, + &:focus { + text-decoration: none; + + @include themify($themes) { + color: themed("primaryColor"); + } + + span { + visibility: visible; + } + } + } + } +} + +#sso-page { + .content { + width: 300px; + + .box { + margin-top: 30px; + margin-bottom: 30px; + text-align: center; + } + } +} + +#set-password-page, +#remove-password-page { + .content { + width: 500px; + + p { + text-align: center; + } + + p.lead, + h1 { + font-size: $font-size-large; + text-align: center; + margin-bottom: 20px; + font-weight: normal; + } + + .buttons { + &:not(.with-rows), + .buttons-row { + display: flex; + margin-bottom: 10px; + } + + &:not(.with-rows), + .buttons-row:last-child { + margin-bottom: 20px; + } + + button { + margin-right: 10px; + + &:last-child { + margin-right: 0; + } + } + } + + .box { + margin-bottom: 15px; + + &.last { + margin-bottom: 20px; + } + } + + .box-content { + margin-bottom: 10px; + } + } +} + +#register-page, +#update-temp-password-page { + .content { + width: 400px; + } +} + +#remove-password-page { + .content > p { + margin-bottom: 20px; + } +} + +#login-page { + flex-direction: column; + + .login-header { + align-self: flex-start; + padding: 1em; + font-size: 1.2em; + .environment-urls-settings-icon { + @include themify($themes) { + color: themed("mutedColor"); + } + + span { + visibility: hidden; + } + + &:hover, + &:focus { + text-decoration: none; + + @include themify($themes) { + color: themed("primaryColor"); + } + } + } + } +} diff --git a/apps/desktop/src/scss/plugins.scss b/apps/desktop/src/scss/plugins.scss new file mode 100644 index 0000000000..1bb171bb80 --- /dev/null +++ b/apps/desktop/src/scss/plugins.scss @@ -0,0 +1,203 @@ +@import "~ngx-toastr/toastr"; +@import "~sweetalert2/src/sweetalert2.scss"; + +@import "variables.scss"; + +.toast-container { + .toast-close-button { + font-size: 18px; + margin-right: 4px; + } + + .ngx-toastr { + align-items: center; + background-image: none !important; + border-radius: $border-radius; + box-shadow: 0 0 8px rgba(0, 0, 0, 0.35); + display: flex; + padding: 15px; + + .toast-close-button { + position: absolute; + right: 5px; + top: 0; + } + + &:hover { + box-shadow: 0 0 10px rgba(0, 0, 0, 0.6); + } + + .icon i::before { + float: left; + font-style: normal; + font-family: $icomoon-font-family; + font-size: 25px; + line-height: 20px; + padding-right: 15px; + } + + .toast-message { + p { + margin-bottom: 0.5rem; + + &:last-child { + margin-bottom: 0; + } + } + } + + &.toast-danger, + &.toast-error { + @include themify($themes) { + background-color: themed("dangerColor"); + } + + .icon i::before { + content: map_get($icons, "error"); + } + } + + &.toast-warning { + @include themify($themes) { + background-color: themed("warningColor"); + } + + .icon i::before { + content: map_get($icons, "exclamation-triangle"); + } + } + + &.toast-info { + @include themify($themes) { + background-color: themed("infoColor"); + } + + .icon i:before { + content: map_get($icons, "info-circle"); + } + } + + &.toast-success { + @include themify($themes) { + background-color: themed("successColor"); + } + + .icon i:before { + content: map_get($icons, "check"); + } + } + } +} + +// SweetAlert2 + +.swal2-popup { + padding: 15px; + border-radius: $border-radius; + width: 34em; + + @include themify($themes) { + background-color: themed("backgroundColorAlt"); + color: themed("textColor"); + } + + .swal2-icon { + margin: 0 auto; + width: auto; + height: auto; + border: none; + } + + .swal2-content { + margin: 0; + font-size: $font-size-base; + @include themify($themes) { + color: themed("textColor"); + } + + label.checkbox { + margin-top: 10px; + display: flex; + text-align: left; + align-items: top; + + input { + margin: 3px 5px 0 1px; + } + } + + .swal2-input, + .swal2-textarea { + border: 1px solid #000000; + border-radius: $border-radius; + margin-bottom: 0; + box-shadow: none; + // Inherit theme font-size + font-size: inherit; + + // Sweetalert 1 did not have box-shadow + &:focus { + box-shadow: none; + } + @include themify($themes) { + border-color: themed("inputBorderColor"); + color: themed("textColor"); + background-color: themed("inputBackgroundColor"); + } + &::-webkit-input-placeholder { + @include themify($themes) { + color: themed("inputPlaceholderColor"); + } + } + } + } + + i.swal-custom-icon { + display: block; + margin: 0 auto; + font-size: 35px; + } + + .swal2-title { + padding: 10px 0 15px; + margin: 0; + font-size: $font-size-large; + + @include themify($themes) { + color: themed("textColor"); + } + } + + .swal2-text { + text-align: left; // sweetalert1 behaviour + font-size: $font-size-base; + + @include themify($themes) { + color: themed("textColor"); + } + } + + > .swal2-text:first-child { + margin-top: 20px; + } + + .swal2-actions { + margin: 20px auto 0; + justify-content: flex-start; + flex-direction: row-reverse; + + button { + margin-left: 10px; + @extend .btn; + + &.swal2-confirm { + @extend .btn, .primary; + font-weight: bold; + } + } + } + + .swal2-validation-message { + margin-top: 20px; + } +} diff --git a/apps/desktop/src/scss/styles.scss b/apps/desktop/src/scss/styles.scss new file mode 100644 index 0000000000..e0a834c542 --- /dev/null +++ b/apps/desktop/src/scss/styles.scss @@ -0,0 +1,22 @@ +$icomoon-font-path: "../../../../libs/angular/src/scss/bwicons/fonts/"; +$card-icons-base: "../../../../libs/angular/src/images/cards/"; + +@import "../../../../libs/angular/src/scss/webfonts.css"; +@import "../../../../libs/angular/src/scss/bwicons/styles/style.scss"; +@import "~@angular/cdk/overlay-prebuilt.css"; +@import "variables.scss"; +@import "base.scss"; +@import "grid.scss"; +@import "pages.scss"; +@import "vault.scss"; +@import "list.scss"; +@import "box.scss"; +@import "buttons.scss"; +@import "misc.scss"; +@import "modal.scss"; +@import "plugins.scss"; +@import "environment.scss"; +@import "header.scss"; +@import "left-nav.scss"; +@import "loading.scss"; +@import "../../../../libs/angular/src/scss/icons.scss"; diff --git a/apps/desktop/src/scss/variables.scss b/apps/desktop/src/scss/variables.scss new file mode 100644 index 0000000000..0f13d18c7a --- /dev/null +++ b/apps/desktop/src/scss/variables.scss @@ -0,0 +1,229 @@ +@import "~nord/src/sass/nord.scss"; + +$dark-icon-themes: "theme_dark", "theme_nord"; + +$font-family-sans-serif: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; +$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace; +$font-size-base: 14px; +$font-size-large: 18px; +$font-size-small: 12px; +$text-color: #000000; +$border-color: #f0f0f0; +$border-color-dark: #ddd; +$list-item-hover: #fbfbfb; +$list-icon-color: #c7c7cd; +$border-radius: 3px; +$line-height-base: 1.42857143; + +$gray: #555; +$gray-light: #777; +$text-muted: $gray-light; + +$brand-primary: #175ddc; +$brand-danger: #dd4b39; +$brand-success: #00a65a; +$brand-info: #555555; +$brand-warning: #bf7e16; +$brand-primary-accent: #1252a3; + +$background-color: white; +$background-color-alt: #f9f9f9; +$background-color-alt2: #ededed; + +$box-background-color: $background-color; +$box-background-hover-color: $list-item-hover; +$box-border-color: $border-color; + +$button-border-color: darken($border-color-dark, 12%); +$button-background-color: white; +$button-color: lighten($text-color, 40%); +$button-color-primary: darken($brand-primary, 8%); +$button-color-danger: darken($brand-danger, 10%); + +$themes: ( + light: ( + textColor: $text-color, + borderColor: $border-color-dark, + backgroundColor: $background-color, + backgroundColorAlt: $background-color-alt, + backgroundColorAlt2: $background-color-alt2, + scrollbarColor: rgba(100, 100, 100, 0.2), + scrollbarHoverColor: rgba(100, 100, 100, 0.4), + boxBackgroundColor: $box-background-color, + boxBackgroundHoverColor: $box-background-hover-color, + boxBorderColor: $box-border-color, + headerBackgroundColor: $brand-primary, + headerBorderColor: darken($brand-primary, 7%), + headerInputBackgroundColor: darken($brand-primary, 8%), + headerInputBackgroundFocusColor: darken($brand-primary, 10%), + headerInputColor: #ffffff, + headerInputPlaceholderColor: lighten($brand-primary, 35%), + listItemBackgroundColor: $background-color, + listItemBackgroundHoverColor: $list-item-hover, + listItemBorderColor: $border-color, + groupingsActiveColor: darken($background-color-alt, 5%), + disabledIconColor: $list-icon-color, + headingColor: $gray-light, + headingButtonColor: lighten($gray-light, 30%), + headingButtonHoverColor: $gray-light, + labelColor: $gray-light, + mutedColor: $text-muted, + totpStrokeColor: $brand-primary, + boxRowButtonColor: $brand-primary, + boxRowButtonHoverColor: darken($brand-primary, 10%), + inputBorderColor: darken($border-color-dark, 7%), + inputBackgroundColor: #ffffff, + inputPlaceholderColor: lighten($gray-light, 35%), + buttonBackgroundColor: $button-background-color, + buttonBorderColor: $button-border-color, + buttonColor: $button-color, + buttonPrimaryColor: $button-color-primary, + buttonDangerColor: $button-color-danger, + primaryColor: $brand-primary, + primaryAccentColor: $brand-primary-accent, + dangerColor: $brand-danger, + successColor: $brand-success, + infoColor: $brand-info, + warningColor: $brand-warning, + logoSuffix: "dark", + passwordNumberColor: #007fde, + passwordSpecialColor: #c40800, + calloutBorderColor: $border-color-dark, + calloutBackgroundColor: $background-color, + accountSwitcherBackgroundColor: $background-color, + accountSwitcherTextColor: #ffffff, + svgSuffix: "-light.svg", + hrColor: #eeeeee, + ), + dark: ( + textColor: #ffffff, + borderColor: #2f2f2f, + backgroundColor: #363636, + backgroundColorAlt: #3d3d3d, + backgroundColorAlt2: #222222, + scrollbarColor: #4d4d4d, + scrollbarHoverColor: #5f5f5f, + boxBackgroundColor: #363636, + boxBackgroundHoverColor: #3f3f3f, + boxBorderColor: #2f2f2f, + headerBackgroundColor: #363636, + headerBorderColor: #272727, + headerInputBackgroundColor: #222222, + headerInputBackgroundFocusColor: #1d1d1d, + headerInputColor: #ffffff, + headerInputPlaceholderColor: #707070, + listItemBackgroundColor: #363636, + listItemBackgroundHoverColor: #3c3c3c, + listItemBorderColor: #2f2f2f, + groupingsActiveColor: #292929, + disabledIconColor: #c7c7cd, + headingColor: #a3a3a3, + headingButtonColor: #a3a3a3, + headingButtonHoverColor: #ffffff, + labelColor: #a3a3a3, + mutedColor: #a3a3a3, + totpStrokeColor: #cacaca, + boxRowButtonColor: #cacaca, + boxRowButtonHoverColor: #ffffff, + inputBorderColor: #222222, + inputBackgroundColor: #363636, + inputPlaceholderColor: #707070, + buttonBackgroundColor: #363636, + buttonBorderColor: #1f1f1f, + buttonColor: #e0e0e0, + buttonPrimaryColor: #46ace7, + buttonDangerColor: #ff3e24, + primaryColor: #52bdfb, + primaryAccentColor: #3ea1da, + dangerColor: #ff3e24, + successColor: $brand-success, + infoColor: $brand-info, + warningColor: $brand-warning, + logoSuffix: "white", + passwordNumberColor: #52bdfb, + passwordSpecialColor: #ff7c70, + calloutBorderColor: #2f2f2f, + calloutBackgroundColor: #363636, + accountSwitcherBackgroundColor: #2f2f2f, + accountSwitcherTextColor: #ffffff, + svgSuffix: "-dark.svg", + hrColor: #a3a3a3, + ), + nord: ( + textColor: $nord5, + borderColor: $nord0, + backgroundColor: $nord2, + backgroundColorAlt: $nord1, + backgroundColorAlt2: $nord1, + scrollbarColor: $nord4, + scrollbarHoverColor: $nord6, + boxBackgroundColor: $nord2, + boxBackgroundHoverColor: $nord3, + boxBorderColor: $nord1, + headerBackgroundColor: $nord2, + headerBorderColor: $nord0, + headerInputBackgroundColor: $nord6, + headerInputBackgroundFocusColor: $nord5, + headerInputColor: $nord2, + headerInputPlaceholderColor: $nord3, + listItemBackgroundColor: $nord2, + listItemBackgroundHoverColor: $nord3, + listItemBorderColor: $nord1, + groupingsActiveColor: $nord3, + disabledIconColor: $nord5, + headingColor: $nord4, + headingButtonColor: $nord5, + headingButtonHoverColor: $nord6, + labelColor: $nord4, + mutedColor: $nord4, + totpStrokeColor: $nord4, + boxRowButtonColor: $nord4, + boxRowButtonHoverColor: $nord6, + inputBorderColor: $nord0, + inputBackgroundColor: $nord2, + inputPlaceholderColor: lighten($nord3, 20%), + buttonBackgroundColor: $nord3, + buttonBorderColor: $nord0, + buttonColor: $nord5, + buttonPrimaryColor: $nord8, + buttonDangerColor: $nord11, + primaryColor: $nord9, + primaryAccentColor: $nord8, + dangerColor: $nord11, + successColor: $nord14, + infoColor: $nord9, + warningColor: $nord12, + logoSuffix: "white", + passwordNumberColor: $nord8, + passwordSpecialColor: $nord12, + calloutBorderColor: $nord1, + calloutBackgroundColor: $nord2, + accountSwitcherBackgroundColor: $nord0, + accountSwitcherTextColor: $nord5, + svgSuffix: "-dark.svg", + hrColor: $nord4, + ), +); + +@mixin themify($themes: $themes) { + @each $theme, $map in $themes { + html.theme_#{$theme} & { + $theme-map: () !global; + @each $key, $submap in $map { + $value: map-get(map-get($themes, $theme), "#{$key}"); + $theme-map: map-merge( + $theme-map, + ( + $key: $value, + ) + ) !global; + } + @content; + $theme-map: null !global; + } + } +} + +@function themed($key) { + @return map-get($theme-map, $key); +} diff --git a/apps/desktop/src/scss/vault.scss b/apps/desktop/src/scss/vault.scss new file mode 100644 index 0000000000..f7403ad62d --- /dev/null +++ b/apps/desktop/src/scss/vault.scss @@ -0,0 +1,164 @@ +@import "variables.scss"; + +app-root { + display: flex; + flex-flow: column; + height: 100%; +} + +#container { + height: 100%; + min-height: 0; +} + +.vault { + height: 100%; + display: flex; + + > .items > div, + > .details, + > .logo { + display: flex; + flex-direction: column; + + .inner-content { + padding: 10px 15px; + } + } + + > .items { + order: 2; + width: 28%; + min-width: 200px; + max-width: 350px; + border-right: 1px solid #000000; + + @include themify($themes) { + background-color: themed("backgroundColor"); + border-right-color: themed("borderColor"); + } + + .no-items { + display: flex; + height: 100%; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; + padding: 0 10px; + + .no-items-image { + @include themify($themes) { + content: url("../images/search-desktop" + themed("svgSuffix")); + } + } + + .bwi { + margin-bottom: 10px; + + @include themify($themes) { + color: themed("disabledIconColor"); + } + } + } + } + + > .details { + flex: 1; + min-width: 0; + order: 3; + + @include themify($themes) { + background-color: themed("backgroundColorAlt2"); + } + + .inner-content { + min-width: 400px; + } + + .box { + max-width: 550px; + margin: 30px auto 0 auto; + + &:first-child { + margin-top: 10px; + } + + &:last-child { + margin-bottom: 30px; + } + } + + > form { + display: flex; + flex-direction: column; + height: 100%; + } + + .footer { + button { + margin-right: 10px; + + &:last-child { + margin-right: 0; + } + } + } + } + + > .logo { + flex: 1; + min-width: 0; + order: 3; + + .content { + overflow-y: hidden; + overflow-x: auto; + } + + .inner-content { + min-width: 320px; + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + img { + width: 284px; + opacity: 0.3; + transition: all 1s ease-in-out; + + &:hover { + opacity: 1; + } + } + } + + .content { + flex: 1 1 auto; + position: relative; + overflow: auto; + height: 100%; + } + + .footer { + height: 55px; + flex: 0 0 auto; + border-top: 1px solid #000000; + display: flex; + align-items: center; + padding: 0 15px; + + @include themify($themes) { + background-color: themed("backgroundColorAlt"); + border-top-color: themed("borderColor"); + } + + .right { + margin-left: auto; + display: flex; + } + } +} diff --git a/apps/desktop/src/services/i18n.service.ts b/apps/desktop/src/services/i18n.service.ts new file mode 100644 index 0000000000..899147a075 --- /dev/null +++ b/apps/desktop/src/services/i18n.service.ts @@ -0,0 +1,76 @@ +import * as fs from "fs"; +import * as path from "path"; + +import { I18nService as BaseI18nService } from "jslib-common/services/i18n.service"; + +export class I18nService extends BaseI18nService { + constructor(systemLanguage: string, localesDirectory: string) { + super(systemLanguage, localesDirectory, (formattedLocale: string) => { + const filePath = path.join( + __dirname, + this.localesDirectory + "/" + formattedLocale + "/messages.json" + ); + const localesJson = fs.readFileSync(filePath, "utf8"); + const locales = JSON.parse(localesJson.replace(/^\uFEFF/, "")); // strip the BOM + return Promise.resolve(locales); + }); + + // Please leave 'en' where it is, as it's our fallback language in case no translation can be found + this.supportedTranslationLocales = [ + "en", + "af", + "az", + "be", + "bg", + "bn", + "bs", + "ca", + "cs", + "da", + "de", + "el", + "en-GB", + "en-IN", + "eo", + "es", + "et", + "fa", + "fi", + "fil", + "fr", + "he", + "hi", + "hr", + "hu", + "id", + "it", + "ja", + "ka", + "km", + "kn", + "ko", + "lv", + "me", + "ml", + "nb", + "nl", + "nn", + "pl", + "pt-BR", + "pt-PT", + "ro", + "ru", + "si", + "sk", + "sl", + "sr", + "sv", + "th", + "tr", + "uk", + "vi", + "zh-CN", + "zh-TW", + ]; + } +} diff --git a/apps/desktop/src/services/nativeMessaging.service.ts b/apps/desktop/src/services/nativeMessaging.service.ts new file mode 100644 index 0000000000..a1ef710a62 --- /dev/null +++ b/apps/desktop/src/services/nativeMessaging.service.ts @@ -0,0 +1,187 @@ +import { Injectable } from "@angular/core"; +import { ipcRenderer } from "electron"; +import Swal from "sweetalert2"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { KeySuffixOptions } from "jslib-common/enums/keySuffixOptions"; +import { Utils } from "jslib-common/misc/utils"; +import { EncString } from "jslib-common/models/domain/encString"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; + +const MessageValidTimeout = 10 * 1000; +const EncryptionAlgorithm = "sha1"; + +type Message = { + command: string; + + userId?: string; + timestamp?: number; + + publicKey?: string; +}; + +type OuterMessage = { + message: Message | EncString; + appId: string; +}; + +@Injectable() +export class NativeMessagingService { + private sharedSecrets = new Map(); + + constructor( + private cryptoFunctionService: CryptoFunctionService, + private cryptoService: CryptoService, + private platformUtilService: PlatformUtilsService, + private logService: LogService, + private i18nService: I18nService, + private messagingService: MessagingService, + private stateService: StateService + ) {} + + init() { + ipcRenderer.on("nativeMessaging", async (_event: any, message: any) => { + this.messageHandler(message); + }); + } + + private async messageHandler(msg: OuterMessage) { + const appId = msg.appId; + const rawMessage = msg.message; + + // Request to setup secure encryption + if ("command" in rawMessage && rawMessage.command === "setupEncryption") { + const remotePublicKey = Utils.fromB64ToArray(rawMessage.publicKey).buffer; + + // Valudate the UserId to ensure we are logged into the same account. + const userIds = Object.keys(this.stateService.accounts.getValue()); + if (!userIds.includes(rawMessage.userId)) { + ipcRenderer.send("nativeMessagingReply", { command: "wrongUserId", appId: appId }); + return; + } + + if (await this.stateService.getEnableBrowserIntegrationFingerprint()) { + ipcRenderer.send("nativeMessagingReply", { command: "verifyFingerprint", appId: appId }); + + const fingerprint = ( + await this.cryptoService.getFingerprint( + await this.stateService.getUserId(), + remotePublicKey + ) + ).join(" "); + + this.messagingService.send("setFocus"); + + // Await confirmation that fingerprint is correct + const submitted = await Swal.fire({ + titleText: this.i18nService.t("verifyBrowserTitle"), + html: `${this.i18nService.t("verifyBrowserDesc")}

${fingerprint}`, + showCancelButton: true, + cancelButtonText: this.i18nService.t("cancel"), + showConfirmButton: true, + confirmButtonText: this.i18nService.t("approve"), + allowOutsideClick: false, + }); + + if (submitted.value !== true) { + return; + } + } + + this.secureCommunication(remotePublicKey, appId); + return; + } + + if (this.sharedSecrets.get(appId) == null) { + ipcRenderer.send("nativeMessagingReply", { command: "invalidateEncryption", appId: appId }); + return; + } + + const message: Message = JSON.parse( + await this.cryptoService.decryptToUtf8(rawMessage as EncString, this.sharedSecrets.get(appId)) + ); + + // Shared secret is invalidated, force re-authentication + if (message == null) { + ipcRenderer.send("nativeMessagingReply", { command: "invalidateEncryption", appId: appId }); + return; + } + + if (Math.abs(message.timestamp - Date.now()) > MessageValidTimeout) { + this.logService.error("NativeMessage is to old, ignoring."); + return; + } + + switch (message.command) { + case "biometricUnlock": { + if (!this.platformUtilService.supportsBiometric()) { + return this.send({ command: "biometricUnlock", response: "not supported" }, appId); + } + + if (!(await this.stateService.getBiometricUnlock({ userId: message.userId }))) { + this.send({ command: "biometricUnlock", response: "not enabled" }, appId); + + return await Swal.fire({ + title: this.i18nService.t("biometricsNotEnabledTitle"), + text: this.i18nService.t("biometricsNotEnabledDesc"), + showCancelButton: true, + cancelButtonText: this.i18nService.t("cancel"), + showConfirmButton: false, + }); + } + + const key = await this.cryptoService.getKeyFromStorage( + KeySuffixOptions.Biometric, + message.userId + ); + + if (key != null) { + this.send( + { command: "biometricUnlock", response: "unlocked", keyB64: key.keyB64 }, + appId + ); + } else { + this.send({ command: "biometricUnlock", response: "canceled" }, appId); + } + + break; + } + default: + this.logService.error("NativeMessage, got unknown command."); + break; + } + } + + private async send(message: any, appId: string) { + message.timestamp = Date.now(); + + const encrypted = await this.cryptoService.encrypt( + JSON.stringify(message), + this.sharedSecrets.get(appId) + ); + + ipcRenderer.send("nativeMessagingReply", { appId: appId, message: encrypted }); + } + + private async secureCommunication(remotePublicKey: ArrayBuffer, appId: string) { + const secret = await this.cryptoFunctionService.randomBytes(64); + this.sharedSecrets.set(appId, new SymmetricCryptoKey(secret)); + + const encryptedSecret = await this.cryptoFunctionService.rsaEncrypt( + secret, + remotePublicKey, + EncryptionAlgorithm + ); + ipcRenderer.send("nativeMessagingReply", { + appId: appId, + command: "setupEncryption", + sharedSecret: Utils.fromBufferToB64(encryptedSecret), + }); + } +} diff --git a/apps/desktop/src/services/passwordReprompt.service.ts b/apps/desktop/src/services/passwordReprompt.service.ts new file mode 100644 index 0000000000..ad13a4d003 --- /dev/null +++ b/apps/desktop/src/services/passwordReprompt.service.ts @@ -0,0 +1,10 @@ +import { Injectable } from "@angular/core"; + +import { PasswordRepromptService as BasePasswordRepromptService } from "jslib-angular/services/passwordReprompt.service"; + +import { PasswordRepromptComponent } from "../app/components/password-reprompt.component"; + +@Injectable() +export class PasswordRepromptService extends BasePasswordRepromptService { + component = PasswordRepromptComponent; +} diff --git a/apps/desktop/src/services/state.service.ts b/apps/desktop/src/services/state.service.ts new file mode 100644 index 0000000000..465b684d9e --- /dev/null +++ b/apps/desktop/src/services/state.service.ts @@ -0,0 +1,16 @@ +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { StateService as BaseStateService } from "jslib-common/services/state.service"; + +import { Account } from "../models/account"; + +export class StateService + extends BaseStateService + implements StateServiceAbstraction +{ + async addAccount(account: Account) { + // Apply desktop overides to default account values + account = new Account(account); + await super.addAccount(account); + } +} diff --git a/apps/desktop/stores/apple/screenshots/macos01.png b/apps/desktop/stores/apple/screenshots/macos01.png new file mode 100644 index 0000000000..4a338f011e Binary files /dev/null and b/apps/desktop/stores/apple/screenshots/macos01.png differ diff --git a/apps/desktop/stores/apple/screenshots/macos02.png b/apps/desktop/stores/apple/screenshots/macos02.png new file mode 100644 index 0000000000..4652dbfe47 Binary files /dev/null and b/apps/desktop/stores/apple/screenshots/macos02.png differ diff --git a/apps/desktop/stores/apple/screenshots/macos03.png b/apps/desktop/stores/apple/screenshots/macos03.png new file mode 100644 index 0000000000..ce832f4470 Binary files /dev/null and b/apps/desktop/stores/apple/screenshots/macos03.png differ diff --git a/apps/desktop/stores/apple/screenshots/macos04.png b/apps/desktop/stores/apple/screenshots/macos04.png new file mode 100644 index 0000000000..0104cd6f4d Binary files /dev/null and b/apps/desktop/stores/apple/screenshots/macos04.png differ diff --git a/apps/desktop/stores/apple/screenshots/macos05.png b/apps/desktop/stores/apple/screenshots/macos05.png new file mode 100644 index 0000000000..b6c05bb6d2 Binary files /dev/null and b/apps/desktop/stores/apple/screenshots/macos05.png differ diff --git a/apps/desktop/stores/apple/screenshots/macos06.png b/apps/desktop/stores/apple/screenshots/macos06.png new file mode 100644 index 0000000000..6d045c45ad Binary files /dev/null and b/apps/desktop/stores/apple/screenshots/macos06.png differ diff --git a/apps/desktop/stores/chocolatey/bitwarden.nuspec b/apps/desktop/stores/chocolatey/bitwarden.nuspec new file mode 100644 index 0000000000..5d90b9a2ee --- /dev/null +++ b/apps/desktop/stores/chocolatey/bitwarden.nuspec @@ -0,0 +1,37 @@ + + + + + bitwarden + 0.0.0 + https://github.com/bitwarden/clients/tree/master/apps/desktop/stores/chocolatey + kspearrin + Bitwarden + Bitwarden Inc. + https://bitwarden.com/ + https://raw.githubusercontent.com/bitwarden/brand/master/icons/256x256.png + Copyright © 2015-2022 Bitwarden Inc. + https://github.com/bitwarden/clients/ + https://bitwarden.com/help/ + https://github.com/bitwarden/clients/issues + https://github.com/bitwarden/clients/releases + https://github.com/bitwarden/clients/blob/master/LICENSE.txt + false + bitwarden password manager + A secure and free password manager for all of your devices. + + Bitwarden is the easiest and safest way to store all of your logins and passwords while conveniently keeping them synced between all of your devices. + + Password theft is a serious problem. The websites and apps that you use are under attack every day. Security breaches occur and your passwords are stolen. When you reuse the same passwords across apps and websites hackers can easily access your email, bank, and other important accounts. + + Security experts recommend that you use a different, randomly generated password for every account that you create. But how do you manage all those passwords? Bitwarden makes it easy for you to create, store, and access your passwords. + + Bitwarden stores all of your logins in an encrypted vault that syncs across all of your devices. Since it's fully encrypted before it ever leaves your device, only you have access to your data. Not even the team at Bitwarden can read your data, even if we wanted to. Your data is sealed with AES-256 bit encryption, salted hashing, and PBKDF2 SHA-256. + + Bitwarden is 100% open source software. The source code for Bitwarden is hosted on GitHub and everyone is free to review, audit, and contribute to the Bitwarden codebase. + + + + + + diff --git a/apps/desktop/stores/chocolatey/tools/chocolateyinstall.ps1 b/apps/desktop/stores/chocolatey/tools/chocolateyinstall.ps1 new file mode 100644 index 0000000000..30a41ce98e --- /dev/null +++ b/apps/desktop/stores/chocolatey/tools/chocolateyinstall.ps1 @@ -0,0 +1,17 @@ +$ErrorActionPreference = 'Stop'; + +$url = 'https://github.com/bitwarden/desktop/releases/download/v__version__/Bitwarden-Installer-__version__.exe' +$checksum = '__checksum__' + +$packageArgs = @{ + packageName = 'bitwarden' + fileType = 'EXE' + softwareName = 'Bitwarden' + url = $url + checksum = $checksum + checksumType = 'sha256' + silentArgs = '/S' + validExitCodes= @(0) +} + +Install-ChocolateyPackage @packageArgs diff --git a/apps/desktop/stores/microsoft/microsoft01.png b/apps/desktop/stores/microsoft/microsoft01.png new file mode 100644 index 0000000000..a60fd1ab56 Binary files /dev/null and b/apps/desktop/stores/microsoft/microsoft01.png differ diff --git a/apps/desktop/stores/microsoft/microsoft02.png b/apps/desktop/stores/microsoft/microsoft02.png new file mode 100644 index 0000000000..ca1050319f Binary files /dev/null and b/apps/desktop/stores/microsoft/microsoft02.png differ diff --git a/apps/desktop/stores/microsoft/microsoft03.png b/apps/desktop/stores/microsoft/microsoft03.png new file mode 100644 index 0000000000..73098f2bf4 Binary files /dev/null and b/apps/desktop/stores/microsoft/microsoft03.png differ diff --git a/apps/desktop/stores/microsoft/microsoft04.png b/apps/desktop/stores/microsoft/microsoft04.png new file mode 100644 index 0000000000..74cf303ae7 Binary files /dev/null and b/apps/desktop/stores/microsoft/microsoft04.png differ diff --git a/apps/desktop/stores/microsoft/microsoft05.png b/apps/desktop/stores/microsoft/microsoft05.png new file mode 100644 index 0000000000..49ecb191ab Binary files /dev/null and b/apps/desktop/stores/microsoft/microsoft05.png differ diff --git a/apps/desktop/tsconfig.json b/apps/desktop/tsconfig.json new file mode 100644 index 0000000000..e185cd59e1 --- /dev/null +++ b/apps/desktop/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "noImplicitAny": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "es6", + "target": "ES2016", + "sourceMap": true, + "types": [], + "baseUrl": ".", + "paths": { + "tldjs": ["../../libs/common/src/misc/tldjs.noop"], + "jslib-common/*": ["../../libs/common/src/*"], + "jslib-angular/*": ["../../libs/angular/src/*"], + "jslib-electron/*": ["../../libs/electron/src/*"] + } + }, + "angularCompilerOptions": { + "preserveWhitespaces": true + }, + "include": ["src"] +} diff --git a/apps/desktop/tsconfig.renderer.json b/apps/desktop/tsconfig.renderer.json new file mode 100644 index 0000000000..9a70a18049 --- /dev/null +++ b/apps/desktop/tsconfig.renderer.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["src/entry.ts", "src/main.ts", "src/main", "src/proxy"] +} diff --git a/apps/desktop/webpack.main.js b/apps/desktop/webpack.main.js new file mode 100644 index 0000000000..85a95ad9eb --- /dev/null +++ b/apps/desktop/webpack.main.js @@ -0,0 +1,82 @@ +const path = require("path"); +const { merge } = require("webpack-merge"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const { CleanWebpackPlugin } = require("clean-webpack-plugin"); +const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin"); + +const NODE_ENV = process.env.NODE_ENV == null ? "development" : process.env.NODE_ENV; + +const common = { + module: { + rules: [ + { + test: /\.tsx?$/, + use: "ts-loader", + exclude: /node_modules\/(?!(@bitwarden)\/).*/, + }, + ], + }, + plugins: [], + resolve: { + extensions: [".tsx", ".ts", ".js"], + plugins: [new TsconfigPathsPlugin({ configFile: "./tsconfig.json" })], + }, +}; + +const prod = { + output: { + filename: "[name].js", + path: path.resolve(__dirname, "build"), + }, +}; + +const dev = { + output: { + filename: "[name].js", + path: path.resolve(__dirname, "build"), + devtoolModuleFilenameTemplate: "[absolute-resource-path]", + }, + devtool: "cheap-source-map", +}; + +const main = { + mode: NODE_ENV, + target: "electron-main", + node: { + __dirname: false, + __filename: false, + }, + entry: { + main: "./src/entry.ts", + }, + optimization: { + minimize: false, + }, + module: { + rules: [ + { + test: /\.node$/, + loader: "node-loader", + }, + ], + }, + plugins: [ + new CleanWebpackPlugin(), + new CopyWebpackPlugin({ + patterns: [ + "./src/package.json", + { from: "./src/images", to: "images" }, + { from: "./src/locales", to: "locales" }, + ], + }), + ], + externals: { + "electron-reload": "commonjs2 electron-reload", + "@nodert-win10-rs4/windows.security.credentials.ui": + "commonjs2 @nodert-win10-rs4/windows.security.credentials.ui", + forcefocus: "commonjs2 forcefocus", + keytar: "commonjs2 keytar", + }, +}; + +module.exports = merge(common, NODE_ENV === "development" ? dev : prod, main); diff --git a/apps/desktop/webpack.renderer.js b/apps/desktop/webpack.renderer.js new file mode 100644 index 0000000000..82a961385c --- /dev/null +++ b/apps/desktop/webpack.renderer.js @@ -0,0 +1,136 @@ +const path = require("path"); +const webpack = require("webpack"); +const { merge } = require("webpack-merge"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const { AngularWebpackPlugin } = require("@ngtools/webpack"); +const TerserPlugin = require("terser-webpack-plugin"); + +const NODE_ENV = process.env.NODE_ENV == null ? "development" : process.env.NODE_ENV; + +const common = { + module: { + rules: [ + { + test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, + loader: "@ngtools/webpack", + }, + { + test: /\.(jpe?g|png|gif|svg)$/i, + exclude: /.*(bwi-font)\.svg/, + generator: { + filename: "images/[name][ext]", + }, + type: "asset/resource", + }, + ], + }, + plugins: [], + resolve: { + extensions: [".tsx", ".ts", ".js"], + symlinks: false, + modules: [path.resolve("../../node_modules")], + }, + output: { + filename: "[name].js", + path: path.resolve(__dirname, "build"), + }, +}; + +const renderer = { + mode: NODE_ENV, + devtool: "source-map", + target: "electron-renderer", + node: { + __dirname: false, + }, + entry: { + "app/main": "./src/app/main.ts", + }, + optimization: { + minimizer: [ + new TerserPlugin({ + terserOptions: { + // Replicate Angular CLI behaviour + compress: { + global_defs: { + ngDevMode: false, + ngI18nClosureMode: false, + }, + }, + }, + }), + ], + splitChunks: { + cacheGroups: { + commons: { + test: /[\\/]node_modules[\\/]/, + name: "app/vendor", + chunks: (chunk) => { + return chunk.name === "app/main"; + }, + }, + }, + }, + }, + module: { + rules: [ + { + test: /\.(html)$/, + loader: "html-loader", + }, + { + test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, + exclude: /loading.svg/, + generator: { + filename: "fonts/[name][ext]", + }, + type: "asset/resource", + }, + { + test: /\.scss$/, + use: [ + { + loader: MiniCssExtractPlugin.loader, + options: { + publicPath: "../", + }, + }, + "css-loader", + "sass-loader", + ], + }, + // Hide System.import warnings. ref: https://github.com/angular/angular/issues/21560 + { + test: /[\/\\]@angular[\/\\].+\.js$/, + parser: { system: true }, + }, + ], + }, + plugins: [ + new AngularWebpackPlugin({ + tsConfigPath: "tsconfig.renderer.json", + entryModule: "src/app/app.module#AppModule", + sourceMap: true, + }), + // ref: https://github.com/angular/angular/issues/20357 + new webpack.ContextReplacementPlugin( + /\@angular(\\|\/)core(\\|\/)fesm5/, + path.resolve(__dirname, "./src") + ), + new HtmlWebpackPlugin({ + template: "./src/index.html", + filename: "index.html", + chunks: ["app/vendor", "app/main"], + }), + new webpack.SourceMapDevToolPlugin({ + include: ["app/main.js"], + }), + new MiniCssExtractPlugin({ + filename: "[name].[contenthash].css", + chunkFilename: "[id].[contenthash].css", + }), + ], +}; + +module.exports = merge(common, renderer); diff --git a/apps/web/.eslintignore b/apps/web/.eslintignore deleted file mode 100644 index c6df035b52..0000000000 --- a/apps/web/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -**/dist -**/build -jslib -webpack.config.js -scripts/optimize.js -config.js - -**/node_modules diff --git a/apps/web/.eslintrc.json b/apps/web/.eslintrc.json index 0974eafa53..bfdcc55758 100644 --- a/apps/web/.eslintrc.json +++ b/apps/web/.eslintrc.json @@ -2,30 +2,5 @@ "root": true, "env": { "browser": true - }, - "extends": ["./jslib/shared/eslintrc.json"], - "rules": { - "import/order": [ - "error", - { - "alphabetize": { - "order": "asc" - }, - "newlines-between": "always", - "pathGroups": [ - { - "pattern": "jslib-*/**", - "group": "external", - "position": "after" - }, - { - "pattern": "src/**/*", - "group": "parent", - "position": "before" - } - ], - "pathGroupsExcludedImportTypes": ["builtin"] - } - ] } } diff --git a/apps/web/.git-blame-ignore-revs b/apps/web/.git-blame-ignore-revs deleted file mode 100644 index 456a355970..0000000000 --- a/apps/web/.git-blame-ignore-revs +++ /dev/null @@ -1,2 +0,0 @@ -# Apply Prettier https://github.com/bitwarden/web/pull/1347 -56477eb39cfd8a73c9920577d24d75fed36e2cf5 diff --git a/apps/web/.github/ISSUE_TEMPLATE/config.yml b/apps/web/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 61d7e2b96f..0000000000 --- a/apps/web/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,14 +0,0 @@ -blank_issues_enabled: false -contact_links: - - name: Feature Requests - url: https://community.bitwarden.com/c/feature-requests/ - about: Request new features using the Community Forums. Please search existing feature requests before making a new one. - - name: Bitwarden Community Forums - url: https://community.bitwarden.com - about: Please visit the community forums for general community discussion, support and the development roadmap. - - name: Customer Support - url: https://bitwarden.com/contact/ - about: Please contact our customer support for account issues and general customer support. - - name: Security Issues - url: https://hackerone.com/bitwarden - about: We use HackerOne to manage security disclosures. diff --git a/apps/web/.github/workflows/qa-deploy.yml b/apps/web/.github/workflows/qa-deploy.yml deleted file mode 100644 index d654dd9241..0000000000 --- a/apps/web/.github/workflows/qa-deploy.yml +++ /dev/null @@ -1,71 +0,0 @@ ---- -name: QA Deploy - -on: - workflow_dispatch: - inputs: - image_extension: - description: "Image tag extension" - required: false - -env: - _QA_CLUSTER_RESOURCE_GROUP: "bw-env-qa" - _QA_CLUSTER_NAME: "bw-aks-qa" - _QA_K8S_NAMESPACE: "bw-qa" - _QA_K8S_APP_NAME: "bw-web" - -jobs: - deploy: - name: Deploy QA Web - runs-on: ubuntu-20.04 - steps: - - name: Checkout Repo - uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 - - - name: Setup - run: export PATH=$PATH:~/work/web/web - - - name: Login to Azure - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a - with: - creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} - - - name: Retrieve secrets - id: retrieve-secrets - uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 - with: - keyvault: "bitwarden-qa-kv" - secrets: "qa-aks-kubectl-credentials" - - - name: Login with qa-aks-kubectl-credentials SP - uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a - with: - creds: ${{ env.qa-aks-kubectl-credentials }} - - - name: Setup AKS access - #env: - # USER_ID: ${{ env.qa-kubectl-managed-identity-clientId }} - run: | - echo "---az install---" - az aks install-cli --install-location ./kubectl --kubelogin-install-location ./kubelogin - echo "---az get-creds---" - az aks get-credentials -n $_QA_CLUSTER_NAME -g $_QA_CLUSTER_RESOURCE_GROUP - - - name: Get image tag - id: image_tag - run: | - IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") - TAG_EXTENSION=${{ github.event.inputs.image_extension }} - - if [[ $TAG_EXTENSION ]]; then - IMAGE_TAG=$IMAGE_TAG-$TAG_EXTENSION - fi - echo "::set-output name=value::$IMAGE_TAG" - - - name: Deploy Web image - env: - IMAGE_TAG: ${{ steps.image_tag.outputs.value }} - run: | - kubectl set image -n $_QA_K8S_NAMESPACE deployment/web web=bitwardenqa.azurecr.io/web:$IMAGE_TAG --record - kubectl rollout restart -n $_QA_K8S_NAMESPACE deployment/web - kubectl rollout status deployment/web -n $_QA_K8S_NAMESPACE diff --git a/apps/web/.github/workflows/version-bump.yml b/apps/web/.github/workflows/version-bump.yml deleted file mode 100644 index 94cc859fd9..0000000000 --- a/apps/web/.github/workflows/version-bump.yml +++ /dev/null @@ -1,71 +0,0 @@ ---- -name: Version Bump - -on: - workflow_dispatch: - inputs: - version_number: - description: "New Version" - required: true - -jobs: - bump_props_version: - name: "Create version_bump_${{ github.event.inputs.version_number }} branch" - runs-on: ubuntu-20.04 - steps: - - name: Checkout Branch - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 - - - name: Create Version Branch - run: | - git switch -c version_bump_${{ github.event.inputs.version_number }} - git push -u origin version_bump_${{ github.event.inputs.version_number }} - - - name: Checkout Version Branch - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 - with: - ref: version_bump_${{ github.event.inputs.version_number }} - - - name: Bump Version - package.json - uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 - with: - version: ${{ github.event.inputs.version_number }} - file_path: "./package.json" - - - name: Bump Version - package-lock.json - uses: bitwarden/gh-actions/version-bump@03ad9a873c39cdc95dd8d77dbbda67f84db43945 - with: - version: ${{ github.event.inputs.version_number }} - file_path: "./package-lock.json" - - - name: Commit files - run: | - git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --local user.name "github-actions[bot]" - git commit -m "Bumped version to ${{ github.event.inputs.version_number }}" -a - - - name: Push changes - run: git push -u origin version_bump_${{ github.event.inputs.version_number }} - - - name: Create Version PR - env: - PR_BRANCH: "version_bump_${{ github.event.inputs.version_number }}" - GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" - BASE_BRANCH: master - TITLE: "Bump version to ${{ github.event.inputs.version_number }}" - run: | - gh pr create --title "$TITLE" \ - --base "$BASE" \ - --head "$PR_BRANCH" \ - --label "version update" \ - --label "automated pr" \ - --body " - ## Type of change - - [ ] Bug fix - - [ ] New feature development - - [ ] Tech debt (refactoring, code cleanup, dependency upgrades, etc) - - [ ] Build/deploy pipeline (DevOps) - - [X] Other - - ## Objective - Automated version bump to ${{ github.event.inputs.version_number }}" diff --git a/apps/web/.prettierignore b/apps/web/.prettierignore deleted file mode 100644 index b579285e2c..0000000000 --- a/apps/web/.prettierignore +++ /dev/null @@ -1,12 +0,0 @@ -# Build directories -build -dist - -#jslib - -# External libraries / auto synced locales -src/locales -src/404/*.min.css - -# Github Workflows -.github/workflows diff --git a/apps/web/package-lock.json b/apps/web/package-lock.json deleted file mode 100644 index 8e68936355..0000000000 --- a/apps/web/package-lock.json +++ /dev/null @@ -1,13568 +0,0 @@ -{ - "name": "@bitwarden/web-vault", - "version": "2022.05.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "@bitwarden/web-vault", - "version": "2022.05.0", - "hasInstallScript": true, - "license": "GPL-3.0", - "dependencies": { - "@angular/animations": "^12.2.13", - "@angular/cdk": "^12.2.13", - "@angular/common": "^12.2.13", - "@angular/compiler": "^12.2.13", - "@angular/core": "^12.2.13", - "@angular/forms": "^12.2.13", - "@angular/platform-browser": "^12.2.13", - "@angular/platform-browser-dynamic": "^12.2.13", - "@angular/router": "^12.2.13", - "@bitwarden/jslib-angular": "file:jslib/angular", - "@bitwarden/jslib-common": "file:jslib/common", - "bootstrap": "4.6.0", - "braintree-web-drop-in": "1.33.1", - "browser-hrtime": "^1.1.8", - "core-js": "^3.11.0", - "date-input-polyfill": "^2.14.0", - "jquery": "3.6.0", - "jszip": "^3.7.1", - "ngx-infinite-scroll": "^10.0.1", - "ngx-toastr": "14.1.4", - "node-forge": "^1.3.1", - "popper.js": "1.16.1", - "qrious": "4.0.2", - "rxjs": "^7.4.0", - "sweetalert2": "^10.16.6", - "webcrypto-shim": "0.1.7", - "whatwg-fetch": "3.6.2", - "zone.js": "0.11.4" - }, - "devDependencies": { - "@angular/compiler-cli": "^12.2.13", - "@ngtools/webpack": "^12.2.13", - "@types/jquery": "^3.5.5", - "@types/node": "^16.11.12", - "@types/webcrypto": "^0.0.28", - "@types/webpack": "^5.28.0", - "@typescript-eslint/eslint-plugin": "^5.10.1", - "@typescript-eslint/parser": "^5.10.1", - "autoprefixer": "^10.4.2", - "buffer": "^6.0.3", - "clean-webpack-plugin": "^4.0.0", - "copy-webpack-plugin": "^10.0.0", - "cross-env": "^7.0.3", - "css-loader": "^6.5.1", - "eslint": "^8.7.0", - "eslint-config-prettier": "^8.3.0", - "eslint-import-resolver-typescript": "^2.5.0", - "eslint-plugin-import": "^2.25.4", - "gh-pages": "^3.1.0", - "html-loader": "^3.0.1", - "html-webpack-injector": "1.1.4", - "html-webpack-plugin": "^5.5.0", - "husky": "^7.0.4", - "lint-staged": "^12.1.2", - "mini-css-extract-plugin": "^2.4.5", - "postcss": "^8.4.6", - "postcss-loader": "^6.2.1", - "prettier": "2.5.1", - "process": "^0.11.10", - "rimraf": "^3.0.2", - "sass": "^1.32.10", - "sass-loader": "^12.4.0", - "style-loader": "^3.3.1", - "tailwindcss": "^3.0.18", - "terser-webpack-plugin": "^5.2.5", - "ts-loader": "^9.2.5", - "typescript": "4.3.5", - "util": "^0.12.4", - "webpack": "^5.64.4", - "webpack-cli": "^4.9.1", - "webpack-dev-server": "^4.6.0" - }, - "engines": { - "node": "~16", - "npm": "~8" - } - }, - "jslib/angular": { - "name": "@bitwarden/jslib-angular", - "version": "0.0.0", - "license": "GPL-3.0", - "dependencies": { - "@angular/animations": "^12.2.13", - "@angular/cdk": "^12.2.13", - "@angular/common": "^12.2.13", - "@angular/compiler": "^12.2.13", - "@angular/core": "^12.2.13", - "@angular/forms": "^12.2.13", - "@angular/platform-browser": "^12.2.13", - "@angular/platform-browser-dynamic": "^12.2.13", - "@angular/router": "^12.2.13", - "@bitwarden/jslib-common": "file:../common", - "duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git", - "rxjs": "^7.4.0", - "tldjs": "^2.3.1", - "zone.js": "0.11.4" - }, - "devDependencies": { - "@types/duo_web_sdk": "^2.7.1", - "rimraf": "^3.0.2", - "typescript": "4.3.5" - } - }, - "jslib/common": { - "name": "@bitwarden/jslib-common", - "version": "0.0.0", - "license": "GPL-3.0", - "dependencies": { - "@microsoft/signalr": "5.0.10", - "@microsoft/signalr-protocol-msgpack": "5.0.10", - "big-integer": "1.6.48", - "browser-hrtime": "^1.1.8", - "lunr": "^2.3.9", - "node-forge": "^1.2.1", - "papaparse": "^5.3.0", - "rxjs": "^7.4.0", - "tldjs": "^2.3.1", - "zxcvbn": "^4.4.2" - }, - "devDependencies": { - "@types/lunr": "^2.3.3", - "@types/node": "^16.11.12", - "@types/node-forge": "^1.0.1", - "@types/papaparse": "^5.2.5", - "@types/tldjs": "^2.3.0", - "@types/zxcvbn": "^4.4.1", - "rimraf": "^3.0.2", - "typescript": "4.3.5" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@angular/animations": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "@angular/core": "12.2.16" - } - }, - "node_modules/@angular/cdk": { - "version": "12.2.13", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "optionalDependencies": { - "parse5": "^5.0.0" - }, - "peerDependencies": { - "@angular/common": "^12.0.0 || ^13.0.0-0", - "@angular/core": "^12.0.0 || ^13.0.0-0", - "rxjs": "^6.5.3 || ^7.0.0" - } - }, - "node_modules/@angular/common": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "@angular/core": "12.2.16", - "rxjs": "^6.5.3 || ^7.0.0" - } - }, - "node_modules/@angular/compiler": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - } - }, - "node_modules/@angular/compiler-cli": { - "version": "12.2.16", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.8.6", - "@babel/types": "^7.8.6", - "canonical-path": "1.0.0", - "chokidar": "^3.0.0", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.11.0", - "magic-string": "^0.25.0", - "minimist": "^1.2.0", - "reflect-metadata": "^0.1.2", - "semver": "^7.0.0", - "source-map": "^0.6.1", - "sourcemap-codec": "^1.4.8", - "tslib": "^2.2.0", - "yargs": "^17.0.0" - }, - "bin": { - "ivy-ngcc": "ngcc/main-ivy-ngcc.js", - "ng-xi18n": "src/extract_i18n.js", - "ngc": "src/main.js", - "ngcc": "ngcc/main-ngcc.js" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "@angular/compiler": "12.2.16", - "typescript": ">=4.2.3 <4.4" - } - }, - "node_modules/@angular/core": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "rxjs": "^6.5.3 || ^7.0.0", - "zone.js": "~0.11.4" - } - }, - "node_modules/@angular/forms": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "@angular/common": "12.2.16", - "@angular/core": "12.2.16", - "@angular/platform-browser": "12.2.16", - "rxjs": "^6.5.3 || ^7.0.0" - } - }, - "node_modules/@angular/platform-browser": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "@angular/animations": "12.2.16", - "@angular/common": "12.2.16", - "@angular/core": "12.2.16" - }, - "peerDependenciesMeta": { - "@angular/animations": { - "optional": true - } - } - }, - "node_modules/@angular/platform-browser-dynamic": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "@angular/common": "12.2.16", - "@angular/compiler": "12.2.16", - "@angular/core": "12.2.16", - "@angular/platform-browser": "12.2.16" - } - }, - "node_modules/@angular/router": { - "version": "12.2.16", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": "^12.14.1 || >=14.0.0" - }, - "peerDependencies": { - "@angular/common": "12.2.16", - "@angular/core": "12.2.16", - "@angular/platform-browser": "12.2.16", - "rxjs": "^6.5.3 || ^7.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.17.10", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.17.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.9", - "@babel/parser": "^7.17.10", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.10", - "@babel/types": "^7.17.10", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.17.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.17.10", - "@jridgewell/gen-mapping": "^0.1.0", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.17.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.17.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.17.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.17.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.17.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.17.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.17.10", - "dev": true, - "license": "MIT", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.16.7", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.17.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.10", - "@babel/types": "^7.17.10", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.17.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bitwarden/jslib-angular": { - "resolved": "jslib/angular", - "link": true - }, - "node_modules/@bitwarden/jslib-common": { - "resolved": "jslib/common", - "link": true - }, - "node_modules/@braintree/asset-loader": { - "version": "0.4.4", - "license": "MIT", - "dependencies": { - "promise-polyfill": "^8.1.3" - } - }, - "node_modules/@braintree/browser-detection": { - "version": "1.12.1", - "license": "MIT" - }, - "node_modules/@braintree/class-list": { - "version": "0.2.0", - "license": "MIT" - }, - "node_modules/@braintree/event-emitter": { - "version": "0.4.1", - "license": "MIT" - }, - "node_modules/@braintree/extended-promise": { - "version": "0.4.1", - "license": "MIT" - }, - "node_modules/@braintree/iframer": { - "version": "1.1.0", - "license": "MIT" - }, - "node_modules/@braintree/sanitize-url": { - "version": "6.0.0", - "license": "MIT" - }, - "node_modules/@braintree/uuid": { - "version": "0.1.0", - "license": "ISC" - }, - "node_modules/@braintree/wrap-promise": { - "version": "2.1.0", - "license": "MIT" - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.5.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.9.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" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.13", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.11", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@microsoft/signalr": { - "version": "5.0.10", - "license": "Apache-2.0", - "dependencies": { - "abort-controller": "^3.0.0", - "eventsource": "^1.0.7", - "fetch-cookie": "^0.7.3", - "node-fetch": "^2.6.0", - "ws": "^6.0.0" - } - }, - "node_modules/@microsoft/signalr-protocol-msgpack": { - "version": "5.0.10", - "license": "Apache-2.0", - "dependencies": { - "@microsoft/signalr": ">=5.0.10", - "msgpack5": "^4.5.0" - } - }, - "node_modules/@microsoft/signalr/node_modules/ws": { - "version": "6.2.2", - "license": "MIT", - "dependencies": { - "async-limiter": "~1.0.0" - } - }, - "node_modules/@ngtools/webpack": { - "version": "12.2.17", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.14.1 || >=14.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" - }, - "peerDependencies": { - "@angular/compiler-cli": "^12.0.0", - "typescript": "~4.2.3 || ~4.3.2", - "webpack": "^5.30.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@scarf/scarf": { - "version": "1.1.1", - "hasInstallScript": true, - "license": "Apache-2.0" - }, - "node_modules/@types/body-parser": { - "version": "1.19.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.35", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/duo_web_sdk": { - "version": "2.7.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/eslint": { - "version": "8.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "0.0.51", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "4.17.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "4.17.28", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "node_modules/@types/glob": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/http-proxy": { - "version": "1.17.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/jquery": { - "version": "3.5.14", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/sizzle": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/lunr": { - "version": "2.3.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mime": { - "version": "1.3.2", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "16.11.33", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node-forge": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/papaparse": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/qs": { - "version": "6.9.7", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/range-parser": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/serve-index": { - "version": "1.9.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.13.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/sizzle": { - "version": "2.3.3", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/sockjs": { - "version": "0.3.33", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/tldjs": { - "version": "2.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/webcrypto": { - "version": "0.0.28", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/webpack": { - "version": "5.28.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "tapable": "^2.2.0", - "webpack": "^5" - } - }, - "node_modules/@types/ws": { - "version": "8.5.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/zxcvbn": { - "version": "4.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.23.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "5.23.0", - "@typescript-eslint/type-utils": "5.23.0", - "@typescript-eslint/utils": "5.23.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.23.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "5.23.0", - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/typescript-estree": "5.23.0", - "debug": "^4.3.2" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.23.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/visitor-keys": "5.23.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.23.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/utils": "5.23.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.23.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.23.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/visitor-keys": "5.23.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.23.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.23.0", - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/typescript-estree": "5.23.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.23.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.23.0", - "eslint-visitor-keys": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack": "4.x.x || 5.x.x", - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "envinfo": "^7.7.3" - }, - "peerDependencies": { - "webpack-cli": "4.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "1.6.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "webpack-cli": "4.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/accepts": { - "version": "1.3.8", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.7.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-assertions": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-node": { - "version": "1.8.2", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - } - }, - "node_modules/acorn-node/node_modules/acorn": { - "version": "7.4.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.11.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "dev": true, - "engines": [ - "node >= 0.8.0" - ], - "license": "Apache-2.0", - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-flatten": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/array-includes": { - "version": "3.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array-uniq": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "2.6.4", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/async-limiter": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/autoprefixer": { - "version": "10.4.7", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.20.3", - "caniuse-lite": "^1.0.30001335", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "license": "MIT", - "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "node_modules/babel-runtime/node_modules/core-js": { - "version": "2.6.12", - "hasInstallScript": true, - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/batch": { - "version": "0.6.1", - "dev": true, - "license": "MIT" - }, - "node_modules/big-integer": { - "version": "1.6.48", - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "2.2.1", - "license": "MIT", - "dependencies": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/body-parser": { - "version": "1.20.0", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/bytes": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/bonjour-service": { - "version": "1.0.12", - "dev": true, - "license": "MIT", - "dependencies": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.4" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/bootstrap": { - "version": "4.6.0", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - }, - "peerDependencies": { - "jquery": "1.9.1 - 3", - "popper.js": "^1.16.1" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/braintree-web": { - "version": "3.85.3", - "license": "MIT", - "dependencies": { - "@braintree/asset-loader": "0.4.4", - "@braintree/browser-detection": "1.12.1", - "@braintree/class-list": "0.2.0", - "@braintree/event-emitter": "0.4.1", - "@braintree/extended-promise": "0.4.1", - "@braintree/iframer": "1.1.0", - "@braintree/sanitize-url": "6.0.0", - "@braintree/uuid": "0.1.0", - "@braintree/wrap-promise": "2.1.0", - "card-validator": "8.1.1", - "credit-card-type": "9.1.0", - "framebus": "5.1.2", - "inject-stylesheet": "5.0.0", - "promise-polyfill": "8.2.3", - "restricted-input": "3.0.5" - } - }, - "node_modules/braintree-web-drop-in": { - "version": "1.33.1", - "license": "MIT", - "dependencies": { - "@braintree/asset-loader": "0.4.4", - "@braintree/browser-detection": "1.12.1", - "@braintree/class-list": "0.2.0", - "@braintree/event-emitter": "0.4.1", - "@braintree/uuid": "0.1.0", - "@braintree/wrap-promise": "2.1.0", - "braintree-web": "3.85.3", - "promise-polyfill": "8.2.3" - } - }, - "node_modules/browser-hrtime": { - "version": "1.1.8", - "license": "MIT" - }, - "node_modules/browserslist": { - "version": "4.20.3", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001332", - "electron-to-chromium": "^1.4.118", - "escalade": "^3.1.1", - "node-releases": "^2.0.3", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/bytes": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001339", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/canonical-path": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/card-validator": { - "version": "8.1.1", - "license": "MIT", - "dependencies": { - "credit-card-type": "^9.1.0" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/clean-css": { - "version": "5.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/clean-webpack-plugin": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "del": "^4.1.1" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "webpack": ">=4.0.0 <6.0.0" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.16", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "2.20.3", - "dev": true, - "license": "MIT" - }, - "node_modules/commondir": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/compressible": { - "version": "2.0.18", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.7.4", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/connect-history-api-fallback": { - "version": "1.6.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-disposition/node_modules/safe-buffer": { - "version": "5.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/content-type": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cookie": { - "version": "0.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/copy-webpack-plugin": { - "version": "10.2.4", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "engines": { - "node": ">= 12.20.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/array-union": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/copy-webpack-plugin/node_modules/globby": { - "version": "12.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/copy-webpack-plugin/node_modules/slash": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/core-js": { - "version": "3.22.5", - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/cosmiconfig": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/credit-card-type": { - "version": "9.1.0", - "license": "MIT" - }, - "node_modules/cross-env": { - "version": "7.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-loader": { - "version": "6.7.1", - "dev": true, - "license": "MIT", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.7", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/date-input-polyfill": { - "version": "2.14.0", - "license": "MIT", - "dependencies": { - "babel-runtime": "^6.11.6" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/defined": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/del": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/del/node_modules/array-union": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/globby/node_modules/pify": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/del/node_modules/rimraf": { - "version": "2.7.1", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dependency-graph": { - "version": "0.11.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/detective": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/dns-equal": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/dns-packet": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "4.3.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/duo_web_sdk": { - "version": "2.7.0", - "resolved": "git+ssh://git@github.com/duosecurity/duo_web_sdk.git#f43ff8f1325f8630d0cff1cd9fb0df13d22cf28d", - "license": "SEE LICENSE IN LICENSE" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.4.137", - "dev": true, - "license": "ISC" - }, - "node_modules/email-addresses": { - "version": "3.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "license": "MIT" - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "dev": true, - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/envinfo": { - "version": "7.8.1", - "dev": true, - "license": "MIT", - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.20.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.4.1", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "dev": true, - "license": "MIT" - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es6-denodeify": { - "version": "0.1.5", - "license": "Unlicense" - }, - "node_modules/escalade": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "8.15.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint/eslintrc": "^1.2.3", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-prettier": { - "version": "8.5.0", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-import-resolver-typescript": { - "version": "2.7.1", - "dev": true, - "license": "ISC", - "dependencies": { - "debug": "^4.3.4", - "glob": "^7.2.0", - "is-glob": "^4.0.3", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.7.3", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.3.2", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.7.1", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/events": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/eventsource": { - "version": "1.1.0", - "license": "MIT", - "dependencies": { - "original": "^1.0.0" - }, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "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" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/express": { - "version": "4.18.1", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/express/node_modules/array-flatten": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/express/node_modules/safe-buffer": { - "version": "5.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "dev": true, - "license": "MIT", - "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.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.12", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.13.0", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fetch-cookie": { - "version": "0.7.3", - "license": "Unlicense", - "dependencies": { - "es6-denodeify": "^0.1.1", - "tough-cookie": "^2.3.3" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.0", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreach": { - "version": "2.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/forwarded": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://www.patreon.com/infusion" - } - }, - "node_modules/framebus": { - "version": "5.1.2", - "license": "MIT", - "dependencies": { - "@braintree/uuid": "^0.1.0" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.3", - "dev": true, - "license": "Unlicense" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gh-pages": { - "version": "3.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "async": "^2.6.1", - "commander": "^2.18.0", - "email-addresses": "^3.0.1", - "filenamify": "^4.3.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", - "globby": "^6.1.0" - }, - "bin": { - "gh-pages": "bin/gh-pages.js", - "gh-pages-clean": "bin/gh-pages-clean.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gh-pages/node_modules/array-union": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-uniq": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gh-pages/node_modules/globby": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gh-pages/node_modules/pify": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/globals": { - "version": "11.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "dev": true, - "license": "ISC" - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/has": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/he": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/html-entities": { - "version": "2.3.3", - "dev": true, - "license": "MIT" - }, - "node_modules/html-loader": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "html-minifier-terser": "^6.0.2", - "parse5": "^6.0.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/html-loader/node_modules/parse5": { - "version": "6.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-minifier-terser/node_modules/commander": { - "version": "8.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/html-webpack-injector": { - "version": "1.1.4", - "dev": true, - "license": "ISC" - }, - "node_modules/html-webpack-plugin": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "webpack": "^5.20.0" - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "dev": true, - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "dev": true, - "license": "MIT" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.6", - "dev": true, - "license": "MIT" - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "dev": true, - "license": "MIT", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/husky": { - "version": "7.0.4", - "dev": true, - "license": "MIT", - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "dev": true, - "license": "ISC", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "license": "MIT" - }, - "node_modules/immutable": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "license": "ISC" - }, - "node_modules/inject-stylesheet": { - "version": "5.0.0", - "license": "MIT" - }, - "node_modules/internal-slot": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/ipaddr.js": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.9.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-generator-function": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-in-cwd": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-path-inside": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-is-inside": "^1.0.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/isobject": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jquery": { - "version": "3.6.0", - "license": "MIT" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jszip": { - "version": "3.9.1", - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "set-immediate-shim": "~1.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klona": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "license": "MIT", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/lilconfig": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "dev": true, - "license": "MIT" - }, - "node_modules/lint-staged": { - "version": "12.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.16", - "commander": "^8.3.0", - "debug": "^4.3.3", - "execa": "^5.1.1", - "lilconfig": "2.0.4", - "listr2": "^4.0.1", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.0", - "pidtree": "^0.5.0", - "string-argv": "^0.3.1", - "supports-color": "^9.2.1", - "yaml": "^1.10.2" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/commander": { - "version": "8.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/lint-staged/node_modules/supports-color": { - "version": "9.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/listr2": { - "version": "4.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/listr2/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/p-map": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/media-typer": { - "version": "0.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.4.1", - "dev": true, - "license": "Unlicense", - "dependencies": { - "fs-monkey": "1.0.3" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "dev": true, - "license": "ISC" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "dev": true, - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/msgpack5": { - "version": "4.5.1", - "license": "MIT", - "dependencies": { - "bl": "^2.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.3.6", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/multicast-dns": { - "version": "7.2.4", - "dev": true, - "license": "MIT", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/nanoid": { - "version": "3.3.4", - "dev": true, - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/ngx-infinite-scroll": { - "version": "10.0.1", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@scarf/scarf": "^1.1.0", - "opencollective-postinstall": "^2.0.2" - } - }, - "node_modules/ngx-toastr": { - "version": "14.1.4", - "license": "MIT", - "dependencies": { - "tslib": "^2.2.0" - }, - "peerDependencies": { - "@angular/common": ">=12.0.0-0", - "@angular/core": ">=12.0.0-0", - "@angular/platform-browser": ">=12.0.0-0" - } - }, - "node_modules/no-case": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-fetch": { - "version": "2.6.7", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "license": "(BSD-3-Clause OR GPL-2.0)", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.4", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.0.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.12.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/opencollective-postinstall": { - "version": "2.0.3", - "license": "MIT", - "bin": { - "opencollective-postinstall": "index.js" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/original": { - "version": "1.0.2", - "license": "MIT", - "dependencies": { - "url-parse": "^1.4.3" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-map": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "license": "(MIT AND Zlib)" - }, - "node_modules/papaparse": { - "version": "5.3.2", - "license": "MIT" - }, - "node_modules/param-case": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "5.1.1", - "license": "MIT", - "optional": true - }, - "node_modules/parseurl": { - "version": "1.3.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-is-inside": { - "version": "1.0.2", - "dev": true, - "license": "(WTFPL OR MIT)" - }, - "node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/path-to-regexp": { - "version": "0.1.7", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.5.0", - "dev": true, - "license": "MIT", - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pify": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pinkie": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-try": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/popper.js": { - "version": "1.16.1", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/postcss": { - "version": "8.4.13", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-js": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/postcss-loader": { - "version": "6.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "dev": true, - "license": "ISC", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-nested": { - "version": "5.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.0.6" - }, - "engines": { - "node": ">=12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.5.1", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/process": { - "version": "0.11.10", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "license": "MIT" - }, - "node_modules/promise-polyfill": { - "version": "8.2.3", - "license": "MIT" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qrious": { - "version": "4.0.2", - "license": "GPL-3.0" - }, - "node_modules/qs": { - "version": "6.10.3", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/bytes": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/rechoir": { - "version": "0.7.1", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.9.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/reflect-metadata": { - "version": "0.1.13", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/regenerator-runtime": { - "version": "0.11.1", - "license": "MIT" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/restricted-input": { - "version": "3.0.5", - "license": "MIT", - "dependencies": { - "@braintree/browser-detection": "^1.12.1" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "7.5.5", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/sass": { - "version": "1.51.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - }, - "bin": { - "sass": "sass.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/sass-loader": { - "version": "12.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } - } - }, - "node_modules/schema-utils": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.11.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/select-hose": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/selfsigned": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.3.7", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.18.0", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "dev": true, - "license": "MIT", - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "dev": true, - "license": "MIT", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "1.15.0", - "dev": true, - "license": "MIT", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-immediate-shim": { - "version": "1.0.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "dev": true, - "license": "ISC" - }, - "node_modules/slash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "dev": true, - "license": "MIT", - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "dev": true, - "license": "MIT" - }, - "node_modules/spdy": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/spdy-transport/node_modules/readable-stream": { - "version": "3.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-outer": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/style-loader": { - "version": "3.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/sweetalert2": { - "version": "10.16.9", - "license": "MIT", - "funding": { - "url": "https://sweetalert2.github.io/#donations" - } - }, - "node_modules/tailwindcss": { - "version": "3.0.24", - "dev": true, - "license": "MIT", - "dependencies": { - "arg": "^5.0.1", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.12", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "5.0.6", - "postcss-selector-parser": "^6.0.10", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/tailwindcss/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/tailwindcss/node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/tailwindcss/node_modules/lilconfig": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/terser": { - "version": "5.13.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.8.0-beta.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.8.0-beta.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/through": { - "version": "2.3.8", - "dev": true, - "license": "MIT" - }, - "node_modules/thunky": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/tldjs": { - "version": "2.3.1", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "punycode": "^1.4.1" - }, - "engines": { - "node": ">= 4" - } - }, - "node_modules/tldjs/node_modules/punycode": { - "version": "1.4.1", - "license": "MIT" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tr46": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ts-loader": { - "version": "9.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "typescript": "*", - "webpack": "^5.0.0" - } - }, - "node_modules/ts-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-loader/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-loader/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/ts-loader/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-loader/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tslib": { - "version": "2.4.0", - "license": "0BSD" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "dev": true, - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "dev": true, - "license": "MIT", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typescript": { - "version": "4.3.5", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/util": { - "version": "0.12.4", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" - }, - "node_modules/utila": { - "version": "0.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "dev": true, - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/watchpack": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "dev": true, - "license": "MIT", - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/webcrypto-shim": { - "version": "0.1.7", - "license": "MIT" - }, - "node_modules/webidl-conversions": { - "version": "4.0.2", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/webpack": { - "version": "5.72.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.3", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "4.9.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.1.1", - "@webpack-cli/info": "^1.4.1", - "@webpack-cli/serve": "^1.6.1", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "webpack": "4.x.x || 5.x.x" - }, - "peerDependenciesMeta": { - "@webpack-cli/generators": { - "optional": true - }, - "@webpack-cli/migrate": { - "optional": true - }, - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-cli/node_modules/commander": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.1", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.9.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-merge": { - "version": "5.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "license": "MIT" - }, - "node_modules/whatwg-url": { - "version": "7.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wildcard": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.6.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "1.10.2", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "17.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "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.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.0.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/zone.js": { - "version": "0.11.4", - "license": "MIT", - "dependencies": { - "tslib": "^2.0.0" - } - }, - "node_modules/zxcvbn": { - "version": "4.4.2", - "license": "MIT" - } - }, - "dependencies": { - "@ampproject/remapping": { - "version": "2.2.0", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@angular/animations": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@angular/cdk": { - "version": "12.2.13", - "requires": { - "parse5": "^5.0.0", - "tslib": "^2.2.0" - } - }, - "@angular/common": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@angular/compiler": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@angular/compiler-cli": { - "version": "12.2.16", - "dev": true, - "requires": { - "@babel/core": "^7.8.6", - "@babel/types": "^7.8.6", - "canonical-path": "1.0.0", - "chokidar": "^3.0.0", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.11.0", - "magic-string": "^0.25.0", - "minimist": "^1.2.0", - "reflect-metadata": "^0.1.2", - "semver": "^7.0.0", - "source-map": "^0.6.1", - "sourcemap-codec": "^1.4.8", - "tslib": "^2.2.0", - "yargs": "^17.0.0" - } - }, - "@angular/core": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@angular/forms": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@angular/platform-browser": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@angular/platform-browser-dynamic": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@angular/router": { - "version": "12.2.16", - "requires": { - "tslib": "^2.2.0" - } - }, - "@babel/code-frame": { - "version": "7.16.7", - "dev": true, - "requires": { - "@babel/highlight": "^7.16.7" - } - }, - "@babel/compat-data": { - "version": "7.17.10", - "dev": true - }, - "@babel/core": { - "version": "7.17.10", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-compilation-targets": "^7.17.10", - "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.9", - "@babel/parser": "^7.17.10", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.10", - "@babel/types": "^7.17.10", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.17.10", - "dev": true, - "requires": { - "@babel/types": "^7.17.10", - "@jridgewell/gen-mapping": "^0.1.0", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.17.10", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.10", - "@babel/helper-validator-option": "^7.16.7", - "browserslist": "^4.20.2", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.16.7", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-function-name": { - "version": "7.17.9", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.16.7", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-imports": { - "version": "7.16.7", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-module-transforms": { - "version": "7.17.7", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-module-imports": "^7.16.7", - "@babel/helper-simple-access": "^7.17.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/helper-validator-identifier": "^7.16.7", - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.17.7", - "dev": true, - "requires": { - "@babel/types": "^7.17.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.16.7", - "dev": true, - "requires": { - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.16.7", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.16.7", - "dev": true - }, - "@babel/helpers": { - "version": "7.17.9", - "dev": true, - "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" - } - }, - "@babel/highlight": { - "version": "7.17.9", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.17.10", - "dev": true - }, - "@babel/template": { - "version": "7.16.7", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/traverse": { - "version": "7.17.10", - "dev": true, - "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.10", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.17.9", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.10", - "@babel/types": "^7.17.10", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.17.10", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - } - }, - "@bitwarden/jslib-angular": { - "version": "file:jslib/angular", - "requires": { - "@angular/animations": "^12.2.13", - "@angular/cdk": "^12.2.13", - "@angular/common": "^12.2.13", - "@angular/compiler": "^12.2.13", - "@angular/core": "^12.2.13", - "@angular/forms": "^12.2.13", - "@angular/platform-browser": "^12.2.13", - "@angular/platform-browser-dynamic": "^12.2.13", - "@angular/router": "^12.2.13", - "@bitwarden/jslib-common": "file:../common", - "@types/duo_web_sdk": "^2.7.1", - "duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git", - "rimraf": "^3.0.2", - "rxjs": "^7.4.0", - "tldjs": "^2.3.1", - "typescript": "4.3.5", - "zone.js": "0.11.4" - } - }, - "@bitwarden/jslib-common": { - "version": "file:jslib/common", - "requires": { - "@microsoft/signalr": "5.0.10", - "@microsoft/signalr-protocol-msgpack": "5.0.10", - "@types/lunr": "^2.3.3", - "@types/node": "^16.11.12", - "@types/node-forge": "^1.0.1", - "@types/papaparse": "^5.2.5", - "@types/tldjs": "^2.3.0", - "@types/zxcvbn": "^4.4.1", - "big-integer": "1.6.48", - "browser-hrtime": "^1.1.8", - "lunr": "^2.3.9", - "node-forge": "^1.2.1", - "papaparse": "^5.3.0", - "rimraf": "^3.0.2", - "rxjs": "^7.4.0", - "tldjs": "^2.3.1", - "typescript": "4.3.5", - "zxcvbn": "^4.4.2" - } - }, - "@braintree/asset-loader": { - "version": "0.4.4", - "requires": { - "promise-polyfill": "^8.1.3" - } - }, - "@braintree/browser-detection": { - "version": "1.12.1" - }, - "@braintree/class-list": { - "version": "0.2.0" - }, - "@braintree/event-emitter": { - "version": "0.4.1" - }, - "@braintree/extended-promise": { - "version": "0.4.1" - }, - "@braintree/iframer": { - "version": "1.1.0" - }, - "@braintree/sanitize-url": { - "version": "6.0.0" - }, - "@braintree/uuid": { - "version": "0.1.0" - }, - "@braintree/wrap-promise": { - "version": "2.1.0" - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "dev": true - }, - "@eslint/eslintrc": { - "version": "1.2.3", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.2", - "globals": "^13.9.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" - }, - "dependencies": { - "globals": { - "version": "13.14.0", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "type-fest": { - "version": "0.20.2", - "dev": true - } - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.0.7", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.1", - "dev": true - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.13", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.11", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "dev": true - }, - "@microsoft/signalr": { - "version": "5.0.10", - "requires": { - "abort-controller": "^3.0.0", - "eventsource": "^1.0.7", - "fetch-cookie": "^0.7.3", - "node-fetch": "^2.6.0", - "ws": "^6.0.0" - }, - "dependencies": { - "ws": { - "version": "6.2.2", - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "@microsoft/signalr-protocol-msgpack": { - "version": "5.0.10", - "requires": { - "@microsoft/signalr": ">=5.0.10", - "msgpack5": "^4.5.0" - } - }, - "@ngtools/webpack": { - "version": "12.2.17", - "dev": true, - "requires": {} - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@scarf/scarf": { - "version": "1.1.1" - }, - "@types/body-parser": { - "version": "1.19.2", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.10", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.3.5", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/duo_web_sdk": { - "version": "2.7.1", - "dev": true - }, - "@types/eslint": { - "version": "8.4.2", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.3", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "dev": true - }, - "@types/express": { - "version": "4.17.13", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.28", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/glob": { - "version": "7.2.0", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/html-minifier-terser": { - "version": "6.1.0", - "dev": true - }, - "@types/http-proxy": { - "version": "1.17.9", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/jquery": { - "version": "3.5.14", - "dev": true, - "requires": { - "@types/sizzle": "*" - } - }, - "@types/json-schema": { - "version": "7.0.11", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "dev": true - }, - "@types/lunr": { - "version": "2.3.4", - "dev": true - }, - "@types/mime": { - "version": "1.3.2", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.5", - "dev": true - }, - "@types/node": { - "version": "16.11.33", - "dev": true - }, - "@types/node-forge": { - "version": "1.0.2", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/papaparse": { - "version": "5.3.2", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/parse-json": { - "version": "4.0.0", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "dev": true - }, - "@types/retry": { - "version": "0.12.0", - "dev": true - }, - "@types/serve-index": { - "version": "1.9.1", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.13.10", - "dev": true, - "requires": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "@types/sizzle": { - "version": "2.3.3", - "dev": true - }, - "@types/sockjs": { - "version": "0.3.33", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/tldjs": { - "version": "2.3.1", - "dev": true - }, - "@types/webcrypto": { - "version": "0.0.28", - "dev": true - }, - "@types/webpack": { - "version": "5.28.0", - "dev": true, - "requires": { - "@types/node": "*", - "tapable": "^2.2.0", - "webpack": "^5" - } - }, - "@types/ws": { - "version": "8.5.3", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/zxcvbn": { - "version": "4.4.1", - "dev": true - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.23.0", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.23.0", - "@typescript-eslint/type-utils": "5.23.0", - "@typescript-eslint/utils": "5.23.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/parser": { - "version": "5.23.0", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.23.0", - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/typescript-estree": "5.23.0", - "debug": "^4.3.2" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.23.0", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/visitor-keys": "5.23.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.23.0", - "dev": true, - "requires": { - "@typescript-eslint/utils": "5.23.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.23.0", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.23.0", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/visitor-keys": "5.23.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/utils": { - "version": "5.23.0", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.23.0", - "@typescript-eslint/types": "5.23.0", - "@typescript-eslint/typescript-estree": "5.23.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.23.0", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.23.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "1.1.1", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "1.4.1", - "dev": true, - "requires": { - "envinfo": "^7.7.3" - } - }, - "@webpack-cli/serve": { - "version": "1.6.1", - "dev": true, - "requires": {} - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.7.1", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "dev": true, - "requires": {} - }, - "acorn-jsx": { - "version": "5.3.2", - "dev": true, - "requires": {} - }, - "acorn-node": { - "version": "1.8.2", - "dev": true, - "requires": { - "acorn": "^7.0.0", - "acorn-walk": "^7.0.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "dev": true - } - } - }, - "acorn-walk": { - "version": "7.2.0", - "dev": true - }, - "aggregate-error": { - "version": "3.1.0", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "dev": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "dev": true - } - } - }, - "ajv-keywords": { - "version": "3.5.2", - "dev": true, - "requires": {} - }, - "ansi-escapes": { - "version": "4.3.2", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-html-community": { - "version": "0.0.8", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "5.0.1", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "dev": true - }, - "array-flatten": { - "version": "2.1.2", - "dev": true - }, - "array-includes": { - "version": "3.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5", - "get-intrinsic": "^1.1.1", - "is-string": "^1.0.7" - } - }, - "array-union": { - "version": "2.1.0", - "dev": true - }, - "array-uniq": { - "version": "1.0.3", - "dev": true - }, - "array.prototype.flat": { - "version": "1.3.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.2", - "es-shim-unscopables": "^1.0.0" - } - }, - "astral-regex": { - "version": "2.0.0", - "dev": true - }, - "async": { - "version": "2.6.4", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "async-limiter": { - "version": "1.0.1" - }, - "autoprefixer": { - "version": "10.4.7", - "dev": true, - "requires": { - "browserslist": "^4.20.3", - "caniuse-lite": "^1.0.30001335", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "available-typed-arrays": { - "version": "1.0.5", - "dev": true - }, - "babel-runtime": { - "version": "6.26.0", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.12" - } - } - }, - "balanced-match": { - "version": "1.0.2", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "dev": true - }, - "batch": { - "version": "0.6.1", - "dev": true - }, - "big-integer": { - "version": "1.6.48" - }, - "binary-extensions": { - "version": "2.2.0", - "dev": true - }, - "bl": { - "version": "2.2.1", - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, - "body-parser": { - "version": "1.20.0", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.10.3", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "dev": true - }, - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - } - } - }, - "bonjour-service": { - "version": "1.0.12", - "dev": true, - "requires": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.4" - } - }, - "boolbase": { - "version": "1.0.0", - "dev": true - }, - "bootstrap": { - "version": "4.6.0", - "requires": {} - }, - "brace-expansion": { - "version": "1.1.11", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "braintree-web": { - "version": "3.85.3", - "requires": { - "@braintree/asset-loader": "0.4.4", - "@braintree/browser-detection": "1.12.1", - "@braintree/class-list": "0.2.0", - "@braintree/event-emitter": "0.4.1", - "@braintree/extended-promise": "0.4.1", - "@braintree/iframer": "1.1.0", - "@braintree/sanitize-url": "6.0.0", - "@braintree/uuid": "0.1.0", - "@braintree/wrap-promise": "2.1.0", - "card-validator": "8.1.1", - "credit-card-type": "9.1.0", - "framebus": "5.1.2", - "inject-stylesheet": "5.0.0", - "promise-polyfill": "8.2.3", - "restricted-input": "3.0.5" - } - }, - "braintree-web-drop-in": { - "version": "1.33.1", - "requires": { - "@braintree/asset-loader": "0.4.4", - "@braintree/browser-detection": "1.12.1", - "@braintree/class-list": "0.2.0", - "@braintree/event-emitter": "0.4.1", - "@braintree/uuid": "0.1.0", - "@braintree/wrap-promise": "2.1.0", - "braintree-web": "3.85.3", - "promise-polyfill": "8.2.3" - } - }, - "browser-hrtime": { - "version": "1.1.8" - }, - "browserslist": { - "version": "4.20.3", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001332", - "electron-to-chromium": "^1.4.118", - "escalade": "^3.1.1", - "node-releases": "^2.0.3", - "picocolors": "^1.0.0" - } - }, - "buffer": { - "version": "6.0.3", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "buffer-from": { - "version": "1.1.2", - "dev": true - }, - "bytes": { - "version": "3.0.0", - "dev": true - }, - "call-bind": { - "version": "1.0.2", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "dev": true - }, - "camel-case": { - "version": "4.1.2", - "dev": true, - "requires": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "camelcase-css": { - "version": "2.0.1", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001339", - "dev": true - }, - "canonical-path": { - "version": "1.0.0", - "dev": true - }, - "card-validator": { - "version": "8.1.1", - "requires": { - "credit-card-type": "^9.1.0" - } - }, - "chalk": { - "version": "2.4.2", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "3.5.3", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.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" - } - }, - "chrome-trace-event": { - "version": "1.0.3", - "dev": true - }, - "clean-css": { - "version": "5.3.0", - "dev": true, - "requires": { - "source-map": "~0.6.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "dev": true - }, - "clean-webpack-plugin": { - "version": "4.0.0", - "dev": true, - "requires": { - "del": "^4.1.1" - } - }, - "cli-cursor": { - "version": "3.1.0", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-truncate": { - "version": "3.1.0", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - } - }, - "cliui": { - "version": "7.0.4", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "clone-deep": { - "version": "4.0.1", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "dev": true - }, - "colorette": { - "version": "2.0.16", - "dev": true - }, - "commander": { - "version": "2.20.3", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "dev": true - }, - "compressible": { - "version": "2.0.18", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "dev": true - }, - "connect-history-api-fallback": { - "version": "1.6.0", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "dev": true - } - } - }, - "content-type": { - "version": "1.0.4", - "dev": true - }, - "convert-source-map": { - "version": "1.8.0", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.5.0", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "dev": true - }, - "copy-webpack-plugin": { - "version": "10.2.4", - "dev": true, - "requires": { - "fast-glob": "^3.2.7", - "glob-parent": "^6.0.1", - "globby": "^12.0.2", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "array-union": { - "version": "3.0.1", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globby": { - "version": "12.2.0", - "dev": true, - "requires": { - "array-union": "^3.0.1", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.7", - "ignore": "^5.1.9", - "merge2": "^1.4.1", - "slash": "^4.0.0" - } - }, - "slash": { - "version": "4.0.0", - "dev": true - } - } - }, - "core-js": { - "version": "3.22.5" - }, - "core-util-is": { - "version": "1.0.3" - }, - "cosmiconfig": { - "version": "7.0.1", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "credit-card-type": { - "version": "9.1.0" - }, - "cross-env": { - "version": "7.0.3", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "css-loader": { - "version": "6.7.1", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.7", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - } - }, - "css-select": { - "version": "4.3.0", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "dev": true - }, - "date-input-polyfill": { - "version": "2.14.0", - "requires": { - "babel-runtime": "^6.11.6" - } - }, - "debug": { - "version": "4.3.4", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "deep-is": { - "version": "0.1.4", - "dev": true - }, - "default-gateway": { - "version": "6.0.3", - "dev": true, - "requires": { - "execa": "^5.0.0" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "dev": true - }, - "define-properties": { - "version": "1.1.4", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "defined": { - "version": "1.0.0", - "dev": true - }, - "del": { - "version": "4.1.1", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "globby": "^6.1.0", - "is-path-cwd": "^2.0.0", - "is-path-in-cwd": "^2.0.0", - "p-map": "^2.0.0", - "pify": "^4.0.1", - "rimraf": "^2.6.3" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "dev": true - } - } - }, - "rimraf": { - "version": "2.7.1", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "depd": { - "version": "2.0.0", - "dev": true - }, - "dependency-graph": { - "version": "0.11.0", - "dev": true - }, - "destroy": { - "version": "1.2.0", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "dev": true - }, - "detective": { - "version": "5.2.0", - "dev": true, - "requires": { - "acorn-node": "^1.6.1", - "defined": "^1.0.0", - "minimist": "^1.1.1" - } - }, - "didyoumean": { - "version": "1.2.2", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dlv": { - "version": "1.1.3", - "dev": true - }, - "dns-equal": { - "version": "1.0.0", - "dev": true - }, - "dns-packet": { - "version": "5.3.1", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "doctrine": { - "version": "3.0.0", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-converter": { - "version": "0.2.0", - "dev": true, - "requires": { - "utila": "~0.4" - } - }, - "dom-serializer": { - "version": "1.4.1", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "dot-case": { - "version": "3.0.4", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "duo_web_sdk": { - "version": "git+ssh://git@github.com/duosecurity/duo_web_sdk.git#f43ff8f1325f8630d0cff1cd9fb0df13d22cf28d", - "from": "duo_web_sdk@git+https://github.com/duosecurity/duo_web_sdk.git" - }, - "eastasianwidth": { - "version": "0.2.0", - "dev": true - }, - "ee-first": { - "version": "1.1.1", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.137", - "dev": true - }, - "email-addresses": { - "version": "3.1.0", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "dev": true - }, - "enhanced-resolve": { - "version": "5.9.3", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "entities": { - "version": "2.2.0", - "dev": true - }, - "envinfo": { - "version": "7.8.1", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.20.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.4.1", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - } - }, - "es-module-lexer": { - "version": "0.9.3", - "dev": true - }, - "es-shim-unscopables": { - "version": "1.0.0", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-denodeify": { - "version": "0.1.5" - }, - "escalade": { - "version": "3.1.1", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "dev": true - }, - "eslint": { - "version": "8.15.0", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.3", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.2", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "dev": true - }, - "eslint-scope": { - "version": "7.1.1", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "globals": { - "version": "13.14.0", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "has-flag": { - "version": "4.0.0", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.20.2", - "dev": true - } - } - }, - "eslint-config-prettier": { - "version": "8.5.0", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.3.6", - "dev": true, - "requires": { - "debug": "^3.2.7", - "resolve": "^1.20.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-import-resolver-typescript": { - "version": "2.7.1", - "dev": true, - "requires": { - "debug": "^4.3.4", - "glob": "^7.2.0", - "is-glob": "^4.0.3", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - } - }, - "eslint-module-utils": { - "version": "2.7.3", - "dev": true, - "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.26.0", - "dev": true, - "requires": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "2.1.0", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "dev": true - }, - "espree": { - "version": "9.3.2", - "dev": true, - "requires": { - "acorn": "^8.7.1", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esquery": { - "version": "1.4.0", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "dev": true - }, - "etag": { - "version": "1.8.1", - "dev": true - }, - "event-target-shim": { - "version": "5.0.1" - }, - "eventemitter3": { - "version": "4.0.7", - "dev": true - }, - "events": { - "version": "3.3.0", - "dev": true - }, - "eventsource": { - "version": "1.1.0", - "requires": { - "original": "^1.0.0" - } - }, - "execa": { - "version": "5.1.1", - "dev": true, - "requires": { - "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" - } - }, - "express": { - "version": "4.18.1", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.0", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.10.3", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "dev": true - }, - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "dev": true - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "dev": true - }, - "fastest-levenshtein": { - "version": "1.0.12", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fetch-cookie": { - "version": "0.7.3", - "requires": { - "es6-denodeify": "^0.1.1", - "tough-cookie": "^2.3.3" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "filename-reserved-regex": { - "version": "2.0.0", - "dev": true - }, - "filenamify": { - "version": "4.3.0", - "dev": true, - "requires": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - } - }, - "fill-range": { - "version": "7.0.1", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.2.0", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - } - } - }, - "find-cache-dir": { - "version": "3.3.2", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "2.1.0", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "flat-cache": { - "version": "3.0.4", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "dev": true - }, - "follow-redirects": { - "version": "1.15.0", - "dev": true - }, - "foreach": { - "version": "2.0.5", - "dev": true - }, - "forwarded": { - "version": "0.2.0", - "dev": true - }, - "fraction.js": { - "version": "4.2.0", - "dev": true - }, - "framebus": { - "version": "5.1.2", - "requires": { - "@braintree/uuid": "^0.1.0" - } - }, - "fresh": { - "version": "0.5.2", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-monkey": { - "version": "1.0.3", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "dev": true - }, - "function.prototype.name": { - "version": "1.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functional-red-black-tree": { - "version": "1.0.1", - "dev": true - }, - "functions-have-names": { - "version": "1.2.3", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.1", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1" - } - }, - "get-stream": { - "version": "6.0.1", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.0", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "gh-pages": { - "version": "3.2.3", - "dev": true, - "requires": { - "async": "^2.6.1", - "commander": "^2.18.0", - "email-addresses": "^3.0.1", - "filenamify": "^4.3.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", - "globby": "^6.1.0" - }, - "dependencies": { - "array-union": { - "version": "1.0.2", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "globby": { - "version": "6.1.0", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "dev": true - } - } - }, - "glob": { - "version": "7.2.0", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "dev": true - }, - "globals": { - "version": "11.12.0", - "dev": true - }, - "globby": { - "version": "11.1.0", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "dev": true - }, - "handle-thing": { - "version": "2.0.1", - "dev": true - }, - "has": { - "version": "1.0.3", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.0", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "he": { - "version": "1.2.0", - "dev": true - }, - "hpack.js": { - "version": "2.1.6", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "html-entities": { - "version": "2.3.3", - "dev": true - }, - "html-loader": { - "version": "3.1.0", - "dev": true, - "requires": { - "html-minifier-terser": "^6.0.2", - "parse5": "^6.0.1" - }, - "dependencies": { - "parse5": { - "version": "6.0.1", - "dev": true - } - } - }, - "html-minifier-terser": { - "version": "6.1.0", - "dev": true, - "requires": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "dependencies": { - "commander": { - "version": "8.3.0", - "dev": true - } - } - }, - "html-webpack-injector": { - "version": "1.1.4", - "dev": true - }, - "html-webpack-plugin": { - "version": "5.5.0", - "dev": true, - "requires": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - } - }, - "htmlparser2": { - "version": "6.1.0", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "http-deceiver": { - "version": "1.2.7", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - } - }, - "http-parser-js": { - "version": "0.5.6", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "2.0.6", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "human-signals": { - "version": "2.1.0", - "dev": true - }, - "husky": { - "version": "7.0.4", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "dev": true, - "requires": {} - }, - "ieee754": { - "version": "1.2.1", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "dev": true - }, - "immediate": { - "version": "3.0.6" - }, - "immutable": { - "version": "4.0.0", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "import-local": { - "version": "3.1.0", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4" - }, - "inject-stylesheet": { - "version": "5.0.0" - }, - "internal-slot": { - "version": "1.0.3", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "interpret": { - "version": "2.2.0", - "dev": true - }, - "ipaddr.js": { - "version": "2.0.1", - "dev": true - }, - "is-arguments": { - "version": "1.1.1", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-arrayish": { - "version": "0.2.1", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-callable": { - "version": "1.2.4", - "dev": true - }, - "is-core-module": { - "version": "2.9.0", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-docker": { - "version": "2.2.1", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "dev": true - }, - "is-generator-function": { - "version": "1.0.10", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-negative-zero": { - "version": "2.0.2", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-path-cwd": { - "version": "2.2.0", - "dev": true - }, - "is-path-in-cwd": { - "version": "2.1.0", - "dev": true, - "requires": { - "is-path-inside": "^2.1.0" - } - }, - "is-path-inside": { - "version": "2.1.0", - "dev": true, - "requires": { - "path-is-inside": "^1.0.2" - } - }, - "is-plain-obj": { - "version": "3.0.0", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.4", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "2.0.1", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-typed-array": { - "version": "1.1.8", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0" - } - }, - "is-weakref": { - "version": "1.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-wsl": { - "version": "2.2.0", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0" - }, - "isexe": { - "version": "2.0.0", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jquery": { - "version": "3.6.0" - }, - "js-tokens": { - "version": "4.0.0", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsesc": { - "version": "2.5.2", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true - }, - "json5": { - "version": "2.2.1", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jszip": { - "version": "3.9.1", - "requires": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "set-immediate-shim": "~1.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "dev": true - }, - "klona": { - "version": "2.0.5", - "dev": true - }, - "levn": { - "version": "0.4.1", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lie": { - "version": "3.3.0", - "requires": { - "immediate": "~3.0.5" - } - }, - "lilconfig": { - "version": "2.0.4", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "dev": true - }, - "lint-staged": { - "version": "12.4.1", - "dev": true, - "requires": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.16", - "commander": "^8.3.0", - "debug": "^4.3.3", - "execa": "^5.1.1", - "lilconfig": "2.0.4", - "listr2": "^4.0.1", - "micromatch": "^4.0.4", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.0", - "pidtree": "^0.5.0", - "string-argv": "^0.3.1", - "supports-color": "^9.2.1", - "yaml": "^1.10.2" - }, - "dependencies": { - "commander": { - "version": "8.3.0", - "dev": true - }, - "supports-color": { - "version": "9.2.2", - "dev": true - } - } - }, - "listr2": { - "version": "4.0.5", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.5", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cli-truncate": { - "version": "2.1.0", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "p-map": { - "version": "4.0.0", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "slice-ansi": { - "version": "3.0.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "loader-runner": { - "version": "4.3.0", - "dev": true - }, - "locate-path": { - "version": "2.0.0", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "dev": true - }, - "lodash.sortby": { - "version": "4.7.0", - "dev": true - }, - "log-update": { - "version": "4.0.0", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "lower-case": { - "version": "2.0.2", - "dev": true, - "requires": { - "tslib": "^2.0.3" - } - }, - "lru-cache": { - "version": "6.0.0", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "lunr": { - "version": "2.3.9" - }, - "magic-string": { - "version": "0.25.9", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-dir": { - "version": "3.1.0", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "dev": true - } - } - }, - "media-typer": { - "version": "0.3.0", - "dev": true - }, - "memfs": { - "version": "3.4.1", - "dev": true, - "requires": { - "fs-monkey": "1.0.3" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "dev": true - }, - "methods": { - "version": "1.1.2", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "1.6.0", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.6.0", - "dev": true, - "requires": { - "schema-utils": "^4.0.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "dev": true - }, - "ms": { - "version": "2.1.2", - "dev": true - }, - "msgpack5": { - "version": "4.5.1", - "requires": { - "bl": "^2.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.3.6", - "safe-buffer": "^5.1.2" - } - }, - "multicast-dns": { - "version": "7.2.4", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "nanoid": { - "version": "3.3.4", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "dev": true - }, - "negotiator": { - "version": "0.6.3", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "dev": true - }, - "ngx-infinite-scroll": { - "version": "10.0.1", - "requires": { - "@scarf/scarf": "^1.1.0", - "opencollective-postinstall": "^2.0.2" - } - }, - "ngx-toastr": { - "version": "14.1.4", - "requires": { - "tslib": "^2.2.0" - } - }, - "no-case": { - "version": "3.0.4", - "dev": true, - "requires": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node-fetch": { - "version": "2.6.7", - "requires": { - "whatwg-url": "^5.0.0" - }, - "dependencies": { - "tr46": { - "version": "0.0.3" - }, - "webidl-conversions": { - "version": "3.0.1" - }, - "whatwg-url": { - "version": "5.0.0", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, - "node-forge": { - "version": "1.3.1" - }, - "node-releases": { - "version": "2.0.4", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nth-check": { - "version": "2.0.1", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "dev": true - }, - "object-hash": { - "version": "3.0.0", - "dev": true - }, - "object-inspect": { - "version": "1.12.0", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "dev": true - }, - "object.assign": { - "version": "4.1.2", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.values": { - "version": "1.1.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - } - }, - "obuf": { - "version": "1.1.2", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "dev": true - }, - "once": { - "version": "1.4.0", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.0", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "opencollective-postinstall": { - "version": "2.0.3" - }, - "optionator": { - "version": "0.9.1", - "dev": true, - "requires": { - "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.3" - } - }, - "original": { - "version": "1.0.2", - "requires": { - "url-parse": "^1.4.3" - } - }, - "p-limit": { - "version": "1.3.0", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-map": { - "version": "2.1.0", - "dev": true - }, - "p-retry": { - "version": "4.6.2", - "dev": true, - "requires": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - } - }, - "p-try": { - "version": "1.0.0", - "dev": true - }, - "pako": { - "version": "1.0.11" - }, - "papaparse": { - "version": "5.3.2" - }, - "param-case": { - "version": "3.0.4", - "dev": true, - "requires": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "parent-module": { - "version": "1.0.1", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse5": { - "version": "5.1.1", - "optional": true - }, - "parseurl": { - "version": "1.3.3", - "dev": true - }, - "pascal-case": { - "version": "3.1.2", - "dev": true, - "requires": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "path-exists": { - "version": "3.0.0", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "dev": true - }, - "pidtree": { - "version": "0.5.0", - "dev": true - }, - "pify": { - "version": "4.0.1", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "4.2.0", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "dev": true - } - } - }, - "popper.js": { - "version": "1.16.1" - }, - "postcss": { - "version": "8.4.13", - "dev": true, - "requires": { - "nanoid": "^3.3.3", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-js": { - "version": "4.0.0", - "dev": true, - "requires": { - "camelcase-css": "^2.0.1" - } - }, - "postcss-load-config": { - "version": "3.1.4", - "dev": true, - "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "dependencies": { - "lilconfig": { - "version": "2.0.5", - "dev": true - } - } - }, - "postcss-loader": { - "version": "6.2.1", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - } - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.0", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-nested": { - "version": "5.0.6", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.6" - } - }, - "postcss-selector-parser": { - "version": "6.0.10", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "dev": true - }, - "prettier": { - "version": "2.5.1", - "dev": true - }, - "pretty-error": { - "version": "4.0.0", - "dev": true, - "requires": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "process": { - "version": "0.11.10", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1" - }, - "promise-polyfill": { - "version": "8.2.3" - }, - "proxy-addr": { - "version": "2.0.7", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "dev": true - } - } - }, - "psl": { - "version": "1.8.0" - }, - "punycode": { - "version": "2.1.1" - }, - "qrious": { - "version": "4.0.2" - }, - "qs": { - "version": "6.10.3", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystringify": { - "version": "2.2.0" - }, - "queue-microtask": { - "version": "1.2.3", - "dev": true - }, - "quick-lru": { - "version": "5.1.1", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.2", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "requires": { - "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" - } - }, - "readdirp": { - "version": "3.6.0", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "rechoir": { - "version": "0.7.1", - "dev": true, - "requires": { - "resolve": "^1.9.0" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1" - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "regexpp": { - "version": "3.2.0", - "dev": true - }, - "relateurl": { - "version": "0.2.7", - "dev": true - }, - "renderkid": { - "version": "3.0.0", - "dev": true, - "requires": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "require-directory": { - "version": "2.1.1", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "dev": true - }, - "requires-port": { - "version": "1.0.0" - }, - "resolve": { - "version": "1.22.0", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "dev": true - }, - "restore-cursor": { - "version": "3.1.0", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "restricted-input": { - "version": "3.0.5", - "requires": { - "@braintree/browser-detection": "^1.12.1" - } - }, - "retry": { - "version": "0.13.1", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-parallel": { - "version": "1.2.0", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.5.5", - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.1.2" - }, - "safer-buffer": { - "version": "2.1.2", - "dev": true - }, - "sass": { - "version": "1.51.0", - "dev": true, - "requires": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - } - }, - "sass-loader": { - "version": "12.6.0", - "dev": true, - "requires": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - } - }, - "schema-utils": { - "version": "4.0.0", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.11.0", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "dev": true - } - } - }, - "select-hose": { - "version": "2.0.0", - "dev": true - }, - "selfsigned": { - "version": "2.0.1", - "dev": true, - "requires": { - "node-forge": "^1" - } - }, - "semver": { - "version": "7.3.7", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, - "send": { - "version": "0.18.0", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "dev": true - } - } - }, - "ms": { - "version": "2.1.3", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "dev": true - }, - "ms": { - "version": "2.0.0", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "dev": true - } - } - }, - "serve-static": { - "version": "1.15.0", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "set-immediate-shim": { - "version": "1.0.1" - }, - "setprototypeof": { - "version": "1.2.0", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "dev": true - }, - "slash": { - "version": "3.0.0", - "dev": true - }, - "slice-ansi": { - "version": "5.0.0", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.1.0", - "dev": true - } - } - }, - "sockjs": { - "version": "0.3.24", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "source-map": { - "version": "0.6.1", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "statuses": { - "version": "2.0.1", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "string-argv": { - "version": "0.3.1", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "dev": true - }, - "strip-ansi": { - "version": "7.0.1", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "string.prototype.trimend": { - "version": "1.0.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.5", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" - } - }, - "strip-ansi": { - "version": "6.0.1", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "dev": true - }, - "strip-json-comments": { - "version": "3.1.1", - "dev": true - }, - "strip-outer": { - "version": "1.0.1", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "style-loader": { - "version": "3.3.1", - "dev": true, - "requires": {} - }, - "supports-color": { - "version": "5.5.0", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "dev": true - }, - "sweetalert2": { - "version": "10.16.9" - }, - "tailwindcss": { - "version": "3.0.24", - "dev": true, - "requires": { - "arg": "^5.0.1", - "chokidar": "^3.5.3", - "color-name": "^1.1.4", - "detective": "^5.2.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "lilconfig": "^2.0.5", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "postcss": "^8.4.12", - "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.4", - "postcss-nested": "5.0.6", - "postcss-selector-parser": "^6.0.10", - "postcss-value-parser": "^4.2.0", - "quick-lru": "^5.1.1", - "resolve": "^1.22.0" - }, - "dependencies": { - "color-name": { - "version": "1.1.4", - "dev": true - }, - "glob-parent": { - "version": "6.0.2", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "lilconfig": { - "version": "2.0.5", - "dev": true - } - } - }, - "tapable": { - "version": "2.2.1", - "dev": true - }, - "terser": { - "version": "5.13.1", - "dev": true, - "requires": { - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map": "~0.8.0-beta.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "source-map": { - "version": "0.8.0-beta.0", - "dev": true, - "requires": { - "whatwg-url": "^7.0.0" - } - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.1", - "dev": true, - "requires": { - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1", - "terser": "^5.7.2" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "dev": true - }, - "through": { - "version": "2.3.8", - "dev": true - }, - "thunky": { - "version": "1.1.0", - "dev": true - }, - "tldjs": { - "version": "2.3.1", - "requires": { - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1" - } - } - }, - "to-fast-properties": { - "version": "2.0.0", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "dev": true - }, - "tough-cookie": { - "version": "2.5.0", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "1.0.1", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "trim-repeated": { - "version": "1.0.0", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.2" - } - }, - "ts-loader": { - "version": "9.3.0", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "enhanced-resolve": "^5.0.0", - "micromatch": "^4.0.0", - "semver": "^7.3.4" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "tsconfig-paths": { - "version": "3.14.1", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "tslib": { - "version": "2.4.0" - }, - "tsutils": { - "version": "3.21.0", - "dev": true, - "requires": { - "tslib": "^1.8.1" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "dev": true - } - } - }, - "type-check": { - "version": "0.4.0", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.21.3", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typescript": { - "version": "4.3.5", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.2", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "universalify": { - "version": "0.1.2", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse": { - "version": "1.5.10", - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "util": { - "version": "0.12.4", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" - } - }, - "util-deprecate": { - "version": "1.0.2" - }, - "utila": { - "version": "0.4.0", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "dev": true - }, - "vary": { - "version": "1.1.2", - "dev": true - }, - "watchpack": { - "version": "2.3.1", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "webcrypto-shim": { - "version": "0.1.7" - }, - "webidl-conversions": { - "version": "4.0.2", - "dev": true - }, - "webpack": { - "version": "5.72.1", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.4.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.9.3", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.3.1", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "schema-utils": { - "version": "3.1.1", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "webpack-cli": { - "version": "4.9.2", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.5.0", - "@webpack-cli/configtest": "^1.1.1", - "@webpack-cli/info": "^1.4.1", - "@webpack-cli/serve": "^1.6.1", - "colorette": "^2.0.14", - "commander": "^7.0.0", - "execa": "^5.0.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^2.2.0", - "rechoir": "^0.7.0", - "webpack-merge": "^5.7.3" - }, - "dependencies": { - "commander": { - "version": "7.2.0", - "dev": true - } - } - }, - "webpack-dev-middleware": { - "version": "5.3.1", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.1", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - } - }, - "webpack-dev-server": { - "version": "4.9.0", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^1.6.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.21", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - } - }, - "webpack-merge": { - "version": "5.8.0", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "dev": true - }, - "websocket-driver": { - "version": "0.7.4", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "dev": true - }, - "whatwg-fetch": { - "version": "3.6.2" - }, - "whatwg-url": { - "version": "7.1.0", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "which": { - "version": "2.0.2", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-typed-array": { - "version": "1.1.7", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.18.5", - "foreach": "^2.0.5", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.7" - } - }, - "wildcard": { - "version": "2.0.0", - "dev": true - }, - "word-wrap": { - "version": "1.2.3", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "dev": true - }, - "ws": { - "version": "8.6.0", - "dev": true, - "requires": {} - }, - "xtend": { - "version": "4.0.2", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "dev": true - }, - "yargs": { - "version": "17.4.1", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "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.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "yargs-parser": { - "version": "21.0.1", - "dev": true - }, - "zone.js": { - "version": "0.11.4", - "requires": { - "tslib": "^2.0.0" - } - }, - "zxcvbn": { - "version": "4.4.2" - } - } -} diff --git a/apps/web/package.json b/apps/web/package.json index 9fe29fcd9c..17ca5bab1b 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -1,20 +1,11 @@ { "name": "@bitwarden/web-vault", "version": "2022.05.0", - "license": "GPL-3.0", - "repository": "https://github.com/bitwarden/web", "scripts": { - "sub:init": "git submodule update --init --recursive", - "sub:update": "git submodule update --remote", - "sub:pull": "git submodule foreach git pull origin master", - "preinstall": "npm run sub:init", - "symlink:win": "rm -rf ./jslib && cmd /c mklink /J .\\jslib ..\\jslib", - "symlink:mac": "npm run symlink:lin", - "symlink:lin": "rm -rf ./jslib && ln -s ../jslib ./jslib", "build:oss": "webpack", - "build:bit": "webpack -c bitwarden_license/webpack.config.js", + "build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js", "build:oss:watch": "webpack serve", - "build:bit:watch": "webpack serve -c bitwarden_license/webpack.config.js", + "build:bit:watch": "webpack serve -c ../../bitwarden_license/bit-web/webpack.config.js", "build:bit:dev": "cross-env ENV=development npm run build:bit", "build:bit:dev:watch": "cross-env ENV=development npm run build:bit:watch", "build:bit:qa": "cross-env NODE_ENV=production ENV=qa npm run build:bit", @@ -26,94 +17,6 @@ "clean:l10n": "git push origin --delete l10n_master", "dist:bit:cloud": "npm run build:bit:cloud", "dist:oss:selfhost": "npm run build:oss:selfhost:prod", - "dist:bit:selfhost": "npm run build:bit:selfhost:prod", - "deploy": "npm run dist:bit && gh-pages -d build", - "deploy:dev": "npm run dist:bit && gh-pages -d build -r git@github.com:kspearrin/bitwarden-web-dev.git", - "lint": "eslint . && prettier --check .", - "lint:fix": "eslint . --fix", - "prettier": "prettier --write .", - "prepare": "husky install" - }, - "devDependencies": { - "@angular/compiler-cli": "^12.2.13", - "@ngtools/webpack": "^12.2.13", - "@types/jquery": "^3.5.5", - "@types/node": "^16.11.12", - "@types/webcrypto": "^0.0.28", - "@types/webpack": "^5.28.0", - "@typescript-eslint/eslint-plugin": "^5.10.1", - "@typescript-eslint/parser": "^5.10.1", - "autoprefixer": "^10.4.2", - "buffer": "^6.0.3", - "clean-webpack-plugin": "^4.0.0", - "copy-webpack-plugin": "^10.0.0", - "cross-env": "^7.0.3", - "css-loader": "^6.5.1", - "eslint": "^8.7.0", - "eslint-config-prettier": "^8.3.0", - "eslint-import-resolver-typescript": "^2.5.0", - "eslint-plugin-import": "^2.25.4", - "gh-pages": "^3.1.0", - "html-loader": "^3.0.1", - "html-webpack-injector": "1.1.4", - "html-webpack-plugin": "^5.5.0", - "husky": "^7.0.4", - "lint-staged": "^12.1.2", - "mini-css-extract-plugin": "^2.4.5", - "postcss": "^8.4.6", - "postcss-loader": "^6.2.1", - "prettier": "2.5.1", - "process": "^0.11.10", - "rimraf": "^3.0.2", - "sass": "^1.32.10", - "sass-loader": "^12.4.0", - "style-loader": "^3.3.1", - "tailwindcss": "^3.0.18", - "terser-webpack-plugin": "^5.2.5", - "ts-loader": "^9.2.5", - "typescript": "4.3.5", - "util": "^0.12.4", - "webpack": "^5.64.4", - "webpack-cli": "^4.9.1", - "webpack-dev-server": "^4.6.0" - }, - "dependencies": { - "@angular/animations": "^12.2.13", - "@angular/cdk": "^12.2.13", - "@angular/common": "^12.2.13", - "@angular/compiler": "^12.2.13", - "@angular/core": "^12.2.13", - "@angular/forms": "^12.2.13", - "@angular/platform-browser": "^12.2.13", - "@angular/platform-browser-dynamic": "^12.2.13", - "@angular/router": "^12.2.13", - "@bitwarden/jslib-angular": "file:jslib/angular", - "@bitwarden/jslib-common": "file:jslib/common", - "bootstrap": "4.6.0", - "braintree-web-drop-in": "1.33.1", - "browser-hrtime": "^1.1.8", - "core-js": "^3.11.0", - "date-input-polyfill": "^2.14.0", - "jquery": "3.6.0", - "jszip": "^3.7.1", - "ngx-infinite-scroll": "^10.0.1", - "ngx-toastr": "14.1.4", - "node-forge": "^1.3.1", - "popper.js": "1.16.1", - "qrious": "4.0.2", - "rxjs": "^7.4.0", - "sweetalert2": "^10.16.6", - "webcrypto-shim": "0.1.7", - "whatwg-fetch": "3.6.2", - "zone.js": "0.11.4" - }, - "engines": { - "node": "~16", - "npm": "~8" - }, - "lint-staged": { - "./!(jslib)**": "prettier --ignore-unknown --write", - "*.ts": "eslint --fix", - "*.png": "node scripts/optimize.js" + "dist:bit:selfhost": "npm run build:bit:selfhost:prod" } } diff --git a/apps/web/src/app/app.component.ts b/apps/web/src/app/app.component.ts index 9e26f68078..6c462a73ed 100644 --- a/apps/web/src/app/app.component.ts +++ b/apps/web/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { Component, NgZone, OnDestroy, OnInit, SecurityContext } from "@angular/core"; +import { Component, Inject, NgZone, OnDestroy, OnInit, SecurityContext } from "@angular/core"; import { DomSanitizer } from "@angular/platform-browser"; import { NavigationEnd, Router } from "@angular/router"; import * as jq from "jquery"; @@ -36,6 +36,7 @@ import { SingleOrgPolicy } from "./organizations/policies/single-org.component"; import { TwoFactorAuthenticationPolicy } from "./organizations/policies/two-factor-authentication.component"; import { PolicyListService } from "./services/policy-list.service"; import { RouterService } from "./services/router.service"; +import { DOCUMENT } from "@angular/common"; const BroadcasterSubscriptionId = "AppComponent"; const IdleTimeout = 60000 * 10; // 10 minutes @@ -50,6 +51,7 @@ export class AppComponent implements OnDestroy, OnInit { private isIdle = false; constructor( + @Inject(DOCUMENT) private document: Document, private broadcasterService: BroadcasterService, private tokenService: TokenService, private folderService: FolderService, @@ -78,6 +80,8 @@ export class AppComponent implements OnDestroy, OnInit { ) {} ngOnInit() { + this.document.documentElement.lang = this.i18nService.locale; + this.ngZone.runOutsideAngular(() => { window.onmousemove = () => this.recordActivity(); window.onmousedown = () => this.recordActivity(); diff --git a/apps/web/src/scss/styles.scss b/apps/web/src/scss/styles.scss index 26c5e5c7d8..9b5c9e9060 100644 --- a/apps/web/src/scss/styles.scss +++ b/apps/web/src/scss/styles.scss @@ -1,7 +1,10 @@ -@import "../../jslib/angular/src/scss/webfonts.css"; +$icomoon-font-path: "../../../../libs/angular/src/scss/bwicons/fonts/"; +$card-icons-base: "../../../../libs/angular/src/images/cards/"; + +@import "../../../../libs/angular/src/scss/webfonts.css"; @import "./variables"; -@import "../../jslib/angular/src/scss/bwicons/styles/style.scss"; -@import "../../jslib/angular/src/scss/icons.scss"; +@import "../../../../libs/angular/src/scss/bwicons/styles/style.scss"; +@import "../../../../libs/angular/src/scss/icons.scss"; @import "@angular/cdk/overlay-prebuilt.css"; //@import "~bootstrap/scss/bootstrap"; diff --git a/apps/web/src/scss/tailwind.css b/apps/web/src/scss/tailwind.css index 58435b41e7..e58785aecb 100644 --- a/apps/web/src/scss/tailwind.css +++ b/apps/web/src/scss/tailwind.css @@ -2,4 +2,4 @@ @tailwind components; @tailwind utilities; -@import "../../jslib/components/src/tw-theme.css"; +@import "../../../../libs/components/src/tw-theme.css"; diff --git a/apps/web/tailwind.config.js b/apps/web/tailwind.config.js index 10bdee461c..380a5b8870 100644 --- a/apps/web/tailwind.config.js +++ b/apps/web/tailwind.config.js @@ -1,4 +1,4 @@ /* eslint-disable no-undef, @typescript-eslint/no-var-requires */ -const config = require("./jslib/components/tailwind.config.base"); +const config = require("../../libs/components/tailwind.config.base"); module.exports = config; diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index 47d772a2d5..de14b95f30 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -1,19 +1,23 @@ { - "extends": "./jslib/shared/tsconfig", + "extends": "../../libs/shared/tsconfig", "compilerOptions": { "baseUrl": ".", "paths": { - "tldjs": ["jslib/common/src/misc/tldjs.noop"], - "jslib-common/*": ["jslib/common/src/*"], - "jslib-angular/*": ["jslib/angular/src/*"], - "@bitwarden/components": ["jslib/components/src"], + "tldjs": ["../../libs/common/src/misc/tldjs.noop"], + "jslib-common/*": ["../../libs/common/src/*"], + "jslib-angular/*": ["../../libs/angular/src/*"], + "@bitwarden/components": ["../../libs/components/src"], "src/*": ["src/*"] } }, "angularCompilerOptions": { "preserveWhitespaces": true }, - "files": ["src/app/polyfills.ts", "src/app/main.ts"], + "files": [ + "src/app/polyfills.ts", + "src/app/main.ts", + "../../bitwarden_license/bit-web/src/app/main.ts" + ], "include": [ "src/connectors/*.ts", "src/models/*.ts", diff --git a/apps/web/webpack.config.js b/apps/web/webpack.config.js index 4a81e4dee3..c79a1fc29a 100644 --- a/apps/web/webpack.config.js +++ b/apps/web/webpack.config.js @@ -125,8 +125,8 @@ const plugins = [ { from: "./src/404", to: "404" }, { from: "./src/images", to: "images" }, { from: "./src/locales", to: "locales" }, - { from: "./node_modules/qrious/dist/qrious.min.js", to: "scripts" }, - { from: "./node_modules/braintree-web-drop-in/dist/browser/dropin.js", to: "scripts" }, + { from: "../../node_modules/qrious/dist/qrious.min.js", to: "scripts" }, + { from: "../../node_modules/braintree-web-drop-in/dist/browser/dropin.js", to: "scripts" }, { from: "./src/version.json", transform(content, path) { @@ -317,7 +317,7 @@ const webpackConfig = { resolve: { extensions: [".ts", ".js"], symlinks: false, - modules: [path.resolve("node_modules")], + modules: [path.resolve("../../node_modules")], alias: { sweetalert2: require.resolve("sweetalert2/dist/sweetalert2.js"), "#sweetalert2": require.resolve("sweetalert2/src/sweetalert2.scss"), diff --git a/bitwarden_license/README.md b/bitwarden_license/README.md new file mode 100644 index 0000000000..b3c416ee06 --- /dev/null +++ b/bitwarden_license/README.md @@ -0,0 +1,3 @@ +# Bitwarden Licensed Code + +All source code under this directory is licensed under the [Bitwarden License Agreement](../LICENSE_BITWARDEN.txt). diff --git a/bitwarden_license/bit-web/README.md b/bitwarden_license/bit-web/README.md deleted file mode 100644 index 52acca3cb4..0000000000 --- a/bitwarden_license/bit-web/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Bitwarden Licensed Code - -All source code under this directory is licensed under the [Bitwarden License Agreement](https://github.com/bitwarden/web/blob/master/LICENSE_BITWARDEN.txt). diff --git a/bitwarden_license/bit-web/src/app/app.component.ts b/bitwarden_license/bit-web/src/app/app.component.ts index 6bc853b6b9..5f7fd544a2 100644 --- a/bitwarden_license/bit-web/src/app/app.component.ts +++ b/bitwarden_license/bit-web/src/app/app.component.ts @@ -7,7 +7,7 @@ import { MaximumVaultTimeoutPolicy } from "./policies/maximum-vault-timeout.comp @Component({ selector: "app-root", - templateUrl: "../../../src/app/app.component.html", + templateUrl: "../../../../apps/web/src/app/app.component.html", }) export class AppComponent extends BaseAppComponent { ngOnInit() { diff --git a/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-confirm.component.ts b/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-confirm.component.ts index b984d3d35f..656793f22d 100644 --- a/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-confirm.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-confirm.component.ts @@ -8,7 +8,8 @@ import { BulkConfirmComponent as OrganizationBulkConfirmComponent } from "src/ap import { BulkUserDetails } from "src/app/organizations/manage/bulk/bulk-status.component"; @Component({ - templateUrl: "../../../../../../src/app/organizations/manage/bulk/bulk-confirm.component.html", + templateUrl: + "../../../../../../../apps/web/src/app/organizations/manage/bulk/bulk-confirm.component.html", }) export class BulkConfirmComponent extends OrganizationBulkConfirmComponent { @Input() providerId: string; diff --git a/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-remove.component.ts b/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-remove.component.ts index 44b0709572..b910f8f76c 100644 --- a/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-remove.component.ts +++ b/bitwarden_license/bit-web/src/app/providers/manage/bulk/bulk-remove.component.ts @@ -5,7 +5,8 @@ import { ProviderUserBulkRequest } from "jslib-common/models/request/provider/pr import { BulkRemoveComponent as OrganizationBulkRemoveComponent } from "src/app/organizations/manage/bulk/bulk-remove.component"; @Component({ - templateUrl: "../../../../../../src/app/organizations/manage/bulk/bulk-remove.component.html", + templateUrl: + "../../../../../../../apps/web/src/app/organizations/manage/bulk/bulk-remove.component.html", }) export class BulkRemoveComponent extends OrganizationBulkRemoveComponent { @Input() providerId: string; diff --git a/bitwarden_license/bit-web/tsconfig.json b/bitwarden_license/bit-web/tsconfig.json new file mode 100644 index 0000000000..2243c09fe0 --- /dev/null +++ b/bitwarden_license/bit-web/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "../../apps/web/jslib/shared/tsconfig", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "tldjs": ["../../apps/web/jslib/common/src/misc/tldjs.noop"], + "jslib-common/*": ["../../apps/web/jslib/common/src/*"], + "jslib-angular/*": ["../../apps/web/jslib/angular/src/*"], + "@bitwarden/components": ["../../apps/web/jslib/components/src"], + "src/*": ["../../apps/web/src/*"] + } + }, + "angularCompilerOptions": { + "preserveWhitespaces": true + }, + "files": [ + "../../apps/web/src/app/polyfills.ts", + "../../apps/web/src/app/main.ts", + "src/app/main.ts" + ], + "include": [ + "../../apps/web/src/connectors/*.ts", + "../../apps/web/src/models/*.ts", + "../../apps/web/src/services/*.ts", + "../../apps/web/src/abstractions/*.ts" + ] +} diff --git a/bitwarden_license/bit-web/webpack.config.js b/bitwarden_license/bit-web/webpack.config.js index bae0682f9d..2d60d20bb6 100644 --- a/bitwarden_license/bit-web/webpack.config.js +++ b/bitwarden_license/bit-web/webpack.config.js @@ -1,8 +1,8 @@ const { AngularWebpackPlugin } = require("@ngtools/webpack"); -const webpackConfig = require("../webpack.config"); +const webpackConfig = require("../../apps/web/webpack.config"); -webpackConfig.entry["app/main"] = "./bitwarden_license/src/app/main.ts"; +webpackConfig.entry["app/main"] = "../../bitwarden_license/bit-web/src/app/main.ts"; webpackConfig.plugins[webpackConfig.plugins.length - 1] = new AngularWebpackPlugin({ tsConfigPath: "tsconfig.json", entryModule: "bitwarden_license/src/app/app.module#AppModule", diff --git a/libs/.github/workflows/build.yml b/libs/.github/workflows/build.yml new file mode 100644 index 0000000000..6ee5ce6275 --- /dev/null +++ b/libs/.github/workflows/build.yml @@ -0,0 +1,107 @@ +--- +name: Build + +on: push + +jobs: + cloc: + name: CLOC + runs-on: ubuntu-20.04 + + steps: + - name: Checkout repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + + - name: Set up cloc + run: | + sudo apt-get update + sudo apt-get -y install cloc + + - name: Print lines of code + run: cloc --include-lang TypeScript,JavaScript,HTML,Sass,CSS --vcs git + + build: + name: Build jslib + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [windows-2019, macos-10.15, ubuntu-20.04] + + steps: + - name: Set up Node + uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea + with: + node-version: "16" + + - name: Install node-gyp + run: | + npm install -g node-gyp + node-gyp install $(node -v) + + - name: Print environment + run: | + node --version + npm --version + + - name: Checkout repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f + + - name: Install Node dependencies + run: npm install + + - name: Run linter + run: npm run lint + + - name: Run tests + if: runner.os != 'Linux' + run: npm run test + + - name: Upload test coverage artifact + if: runner.os != 'Linux' + uses: actions/upload-artifact@ee69f02b3dfdecd58bb31b4d133da38ba6fe3700 + with: + name: test-coverage + path: coverage/ + + check-failures: + name: Check for failures + if: always() + runs-on: ubuntu-20.04 + needs: + - cloc + - build + steps: + - name: Check if any job failed + if: ${{ (github.ref == 'refs/heads/master') || (github.ref == 'refs/heads/rc') }} + env: + CLOC_STATUS: ${{ needs.cloc.result }} + BUILD_STATUS: ${{ needs.build.result }} + run: | + if [ "$CLOC_STATUS" = "failure" ]; then + exit 1 + elif [ "$BUILD_STATUS" = "failure" ]; then + exit 1 + fi + + - name: Login to Azure - Prod Subscription + uses: Azure/login@77f1b2e3fb80c0e8645114159d17008b8a2e475a + if: failure() + with: + creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} + + - name: Retrieve secrets + id: retrieve-secrets + uses: Azure/get-keyvault-secrets@80ccd3fafe5662407cc2e55f202ee34bfff8c403 + if: failure() + with: + keyvault: "bitwarden-prod-kv" + secrets: "devops-alerts-slack-webhook-url" + + - name: Notify Slack on failure + uses: act10ns/slack@e4e71685b9b239384b0f676a63c32367f59c2522 # v1.2.2 + if: failure() + env: + SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} + with: + status: ${{ job.status }} diff --git a/libs/.github/workflows/chromatic.yml b/libs/.github/workflows/chromatic.yml new file mode 100644 index 0000000000..f149df6a2b --- /dev/null +++ b/libs/.github/workflows/chromatic.yml @@ -0,0 +1,41 @@ +--- +name: Chromatic + +on: push + +jobs: + chromatic: + name: Chromatic + runs-on: ubuntu-20.04 + + steps: + - name: Set up Node + uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5 + with: + node-version: "16" + + - name: Checkout repo + uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4 + with: + fetch-depth: 0 + + - name: Cache npm + id: npm-cache + uses: actions/cache@c64c572235d810460d0d6876e9c705ad5002b353 # v2.1.6 + with: + path: "~/.npm" + key: ${{ runner.os }}-npm-chromatic-${{ hashFiles('**/package-lock.json') }} + + - name: Install Node dependencies + run: npm ci + working-directory: ./components + + - name: Publish to Chromatic + uses: chromaui/action@c72f0b48c8887c0ef0abe18ad865a6c1e01e73c6 + with: + token: ${{ secrets.GITHUB_TOKEN }} + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + workingDir: ./components + exitOnceUploaded: true + onlyChanged: true + externals: "[\"components/**/*.scss\", \"components/tailwind.config*.js\"]" diff --git a/libs/.gitignore b/libs/.gitignore new file mode 100644 index 0000000000..20b786361b --- /dev/null +++ b/libs/.gitignore @@ -0,0 +1,9 @@ +.vs +.idea +node_modules +npm-debug.log +vwd.webinfo +*.crx +*.pem +dist +coverage diff --git a/libs/README.md b/libs/README.md new file mode 100644 index 0000000000..0614a6cfbc --- /dev/null +++ b/libs/README.md @@ -0,0 +1,42 @@ +[![Github Workflow build on master](https://github.com/bitwarden/jslib/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/bitwarden/jslib/actions/workflows/build.yml?query=branch:master) + +# Bitwarden JavaScript Library + +Common code referenced across Bitwarden JavaScript projects. + +## Requirements + +- [Node.js](https://nodejs.org) v16.13.1 or greater +- NPM v8 +- Git +- node-gyp + +### Windows + +- _Microsoft Build Tools 2015_ in Visual Studio Installer +- [Windows 10 SDK 17134](https://developer.microsoft.com/en-us/windows/downloads/sdk-archive/) + either by downloading it seperately or through the Visual Studio Installer. + +## We're Hiring! + +Interested in contributing in a big way? Consider joining our team! We're hiring for many positions. Please take a look at our [Careers page](https://bitwarden.com/careers/) to see what opportunities are currently open as well as what it's like to work at Bitwarden. + +## Prettier + +We recently migrated to using Prettier as code formatter. All previous branches will need to updated to avoid large merge conflicts using the following steps: + +1. Check out your local Branch +2. Run `git merge 8b2dfc6cdcb8ff5b604364c2ea6d343473aee7cd` +3. Resolve any merge conflicts, commit. +4. Run `npm run prettier` +5. Commit +6. Run `git merge -Xours 193434461dbd9c48fe5dcbad95693470aec422ac` +7. Push + +### Git blame + +We also recommend that you configure git to ignore the prettier revision using: + +```bash +git config blame.ignoreRevsFile .git-blame-ignore-revs +``` diff --git a/libs/angular/jest.config.js b/libs/angular/jest.config.js new file mode 100644 index 0000000000..0268a45054 --- /dev/null +++ b/libs/angular/jest.config.js @@ -0,0 +1,17 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + name: "angular", + displayName: "libs/angular tests", + preset: "jest-preset-angular", + testMatch: ["**/+(*.)+(spec).+(ts)"], + setupFilesAfterEnv: ["/spec/test.ts"], + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), +}; diff --git a/libs/angular/package.json b/libs/angular/package.json new file mode 100644 index 0000000000..b0eefd7bcd --- /dev/null +++ b/libs/angular/package.json @@ -0,0 +1,23 @@ +{ + "name": "@bitwarden/jslib-angular", + "version": "0.0.0", + "description": "Common code used across Bitwarden JavaScript projects.", + "keywords": [ + "bitwarden" + ], + "author": "Bitwarden Inc.", + "homepage": "https://bitwarden.com", + "repository": { + "type": "git", + "url": "https://github.com/bitwarden/jslib" + }, + "license": "GPL-3.0", + "scripts": { + "clean": "rimraf dist/**/*", + "build": "npm run clean && tsc", + "build:watch": "npm run clean && tsc -watch" + }, + "dependencies": { + "@bitwarden/jslib-common": "file:../common" + } +} diff --git a/libs/angular/spec/test.ts b/libs/angular/spec/test.ts new file mode 100644 index 0000000000..6be6e7b8dd --- /dev/null +++ b/libs/angular/spec/test.ts @@ -0,0 +1,28 @@ +import { webcrypto } from "crypto"; +import "jest-preset-angular/setup-jest"; + +Object.defineProperty(window, "CSS", { value: null }); +Object.defineProperty(window, "getComputedStyle", { + value: () => { + return { + display: "none", + appearance: ["-webkit-appearance"], + }; + }, +}); + +Object.defineProperty(document, "doctype", { + value: "", +}); +Object.defineProperty(document.body.style, "transform", { + value: () => { + return { + enumerable: true, + configurable: true, + }; + }, +}); + +Object.defineProperty(window, "crypto", { + value: webcrypto, +}); diff --git a/libs/angular/src/components/add-edit-custom-fields.component.ts b/libs/angular/src/components/add-edit-custom-fields.component.ts new file mode 100644 index 0000000000..e6dad6cde9 --- /dev/null +++ b/libs/angular/src/components/add-edit-custom-fields.component.ts @@ -0,0 +1,116 @@ +import { CdkDragDrop, moveItemInArray } from "@angular/cdk/drag-drop"; +import { Directive, Input, OnChanges, SimpleChanges } from "@angular/core"; + +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { EventType } from "jslib-common/enums/eventType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { Utils } from "jslib-common/misc/utils"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { FieldView } from "jslib-common/models/view/fieldView"; + +@Directive() +export class AddEditCustomFieldsComponent implements OnChanges { + @Input() cipher: CipherView; + @Input() thisCipherType: CipherType; + @Input() editMode: boolean; + + addFieldType: FieldType = FieldType.Text; + addFieldTypeOptions: any[]; + addFieldLinkedTypeOption: any; + linkedFieldOptions: any[] = []; + + cipherType = CipherType; + fieldType = FieldType; + eventType = EventType; + + constructor(private i18nService: I18nService, private eventService: EventService) { + this.addFieldTypeOptions = [ + { name: i18nService.t("cfTypeText"), value: FieldType.Text }, + { name: i18nService.t("cfTypeHidden"), value: FieldType.Hidden }, + { name: i18nService.t("cfTypeBoolean"), value: FieldType.Boolean }, + ]; + this.addFieldLinkedTypeOption = { + name: this.i18nService.t("cfTypeLinked"), + value: FieldType.Linked, + }; + } + + ngOnChanges(changes: SimpleChanges) { + if (changes.thisCipherType != null) { + this.setLinkedFieldOptions(); + + if (!changes.thisCipherType.firstChange) { + this.resetCipherLinkedFields(); + } + } + } + + addField() { + if (this.cipher.fields == null) { + this.cipher.fields = []; + } + + const f = new FieldView(); + f.type = this.addFieldType; + f.newField = true; + + if (f.type === FieldType.Linked) { + f.linkedId = this.linkedFieldOptions[0].value; + } + + this.cipher.fields.push(f); + } + + removeField(field: FieldView) { + const i = this.cipher.fields.indexOf(field); + if (i > -1) { + this.cipher.fields.splice(i, 1); + } + } + + toggleFieldValue(field: FieldView) { + const f = field as any; + f.showValue = !f.showValue; + if (this.editMode && f.showValue) { + this.eventService.collect(EventType.Cipher_ClientToggledHiddenFieldVisible, this.cipher.id); + } + } + + trackByFunction(index: number, item: any) { + return index; + } + + drop(event: CdkDragDrop) { + moveItemInArray(this.cipher.fields, event.previousIndex, event.currentIndex); + } + + private setLinkedFieldOptions() { + if (this.cipher.linkedFieldOptions == null) { + return; + } + + const options: any = []; + this.cipher.linkedFieldOptions.forEach((linkedFieldOption, id) => + options.push({ name: this.i18nService.t(linkedFieldOption.i18nKey), value: id }) + ); + this.linkedFieldOptions = options.sort(Utils.getSortFunction(this.i18nService, "name")); + } + + private resetCipherLinkedFields() { + if (this.cipher.fields == null || this.cipher.fields.length === 0) { + return; + } + + // Delete any Linked custom fields if the item type does not support them + if (this.cipher.linkedFieldOptions == null) { + this.cipher.fields = this.cipher.fields.filter((f) => f.type !== FieldType.Linked); + return; + } + + this.cipher.fields + .filter((f) => f.type === FieldType.Linked) + .forEach((f) => (f.linkedId = this.linkedFieldOptions[0].value)); + } +} diff --git a/libs/angular/src/components/add-edit.component.ts b/libs/angular/src/components/add-edit.component.ts new file mode 100644 index 0000000000..af57e70345 --- /dev/null +++ b/libs/angular/src/components/add-edit.component.ts @@ -0,0 +1,577 @@ +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; + +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { EventType } from "jslib-common/enums/eventType"; +import { OrganizationUserStatusType } from "jslib-common/enums/organizationUserStatusType"; +import { PolicyType } from "jslib-common/enums/policyType"; +import { SecureNoteType } from "jslib-common/enums/secureNoteType"; +import { UriMatchType } from "jslib-common/enums/uriMatchType"; +import { Utils } from "jslib-common/misc/utils"; +import { Cipher } from "jslib-common/models/domain/cipher"; +import { CardView } from "jslib-common/models/view/cardView"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; +import { IdentityView } from "jslib-common/models/view/identityView"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; +import { LoginView } from "jslib-common/models/view/loginView"; +import { SecureNoteView } from "jslib-common/models/view/secureNoteView"; + +@Directive() +export class AddEditComponent implements OnInit { + @Input() cloneMode = false; + @Input() folderId: string = null; + @Input() cipherId: string; + @Input() type: CipherType; + @Input() collectionIds: string[]; + @Input() organizationId: string = null; + @Output() onSavedCipher = new EventEmitter(); + @Output() onDeletedCipher = new EventEmitter(); + @Output() onRestoredCipher = new EventEmitter(); + @Output() onCancelled = new EventEmitter(); + @Output() onEditAttachments = new EventEmitter(); + @Output() onShareCipher = new EventEmitter(); + @Output() onEditCollections = new EventEmitter(); + @Output() onGeneratePassword = new EventEmitter(); + @Output() onGenerateUsername = new EventEmitter(); + + editMode = false; + cipher: CipherView; + folders: FolderView[]; + collections: CollectionView[] = []; + title: string; + formPromise: Promise; + deletePromise: Promise; + restorePromise: Promise; + checkPasswordPromise: Promise; + showPassword = false; + showCardNumber = false; + showCardCode = false; + cipherType = CipherType; + typeOptions: any[]; + cardBrandOptions: any[]; + cardExpMonthOptions: any[]; + identityTitleOptions: any[]; + uriMatchOptions: any[]; + ownershipOptions: any[] = []; + autofillOnPageLoadOptions: any[]; + currentDate = new Date(); + allowPersonal = true; + reprompt = false; + canUseReprompt = true; + + protected writeableCollections: CollectionView[]; + private previousCipherId: string; + + constructor( + protected cipherService: CipherService, + protected folderService: FolderService, + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected auditService: AuditService, + protected stateService: StateService, + protected collectionService: CollectionService, + protected messagingService: MessagingService, + protected eventService: EventService, + protected policyService: PolicyService, + private logService: LogService, + protected passwordRepromptService: PasswordRepromptService, + private organizationService: OrganizationService + ) { + this.typeOptions = [ + { name: i18nService.t("typeLogin"), value: CipherType.Login }, + { name: i18nService.t("typeCard"), value: CipherType.Card }, + { name: i18nService.t("typeIdentity"), value: CipherType.Identity }, + { name: i18nService.t("typeSecureNote"), value: CipherType.SecureNote }, + ]; + this.cardBrandOptions = [ + { name: "-- " + i18nService.t("select") + " --", value: null }, + { name: "Visa", value: "Visa" }, + { name: "Mastercard", value: "Mastercard" }, + { name: "American Express", value: "Amex" }, + { name: "Discover", value: "Discover" }, + { name: "Diners Club", value: "Diners Club" }, + { name: "JCB", value: "JCB" }, + { name: "Maestro", value: "Maestro" }, + { name: "UnionPay", value: "UnionPay" }, + { name: "RuPay", value: "RuPay" }, + { name: i18nService.t("other"), value: "Other" }, + ]; + this.cardExpMonthOptions = [ + { name: "-- " + i18nService.t("select") + " --", value: null }, + { name: "01 - " + i18nService.t("january"), value: "1" }, + { name: "02 - " + i18nService.t("february"), value: "2" }, + { name: "03 - " + i18nService.t("march"), value: "3" }, + { name: "04 - " + i18nService.t("april"), value: "4" }, + { name: "05 - " + i18nService.t("may"), value: "5" }, + { name: "06 - " + i18nService.t("june"), value: "6" }, + { name: "07 - " + i18nService.t("july"), value: "7" }, + { name: "08 - " + i18nService.t("august"), value: "8" }, + { name: "09 - " + i18nService.t("september"), value: "9" }, + { name: "10 - " + i18nService.t("october"), value: "10" }, + { name: "11 - " + i18nService.t("november"), value: "11" }, + { name: "12 - " + i18nService.t("december"), value: "12" }, + ]; + this.identityTitleOptions = [ + { name: "-- " + i18nService.t("select") + " --", value: null }, + { name: i18nService.t("mr"), value: i18nService.t("mr") }, + { name: i18nService.t("mrs"), value: i18nService.t("mrs") }, + { name: i18nService.t("ms"), value: i18nService.t("ms") }, + { name: i18nService.t("dr"), value: i18nService.t("dr") }, + ]; + this.uriMatchOptions = [ + { name: i18nService.t("defaultMatchDetection"), value: null }, + { name: i18nService.t("baseDomain"), value: UriMatchType.Domain }, + { name: i18nService.t("host"), value: UriMatchType.Host }, + { name: i18nService.t("startsWith"), value: UriMatchType.StartsWith }, + { name: i18nService.t("regEx"), value: UriMatchType.RegularExpression }, + { name: i18nService.t("exact"), value: UriMatchType.Exact }, + { name: i18nService.t("never"), value: UriMatchType.Never }, + ]; + this.autofillOnPageLoadOptions = [ + { name: i18nService.t("autoFillOnPageLoadUseDefault"), value: null }, + { name: i18nService.t("autoFillOnPageLoadYes"), value: true }, + { name: i18nService.t("autoFillOnPageLoadNo"), value: false }, + ]; + } + + async ngOnInit() { + await this.init(); + } + + async init() { + if (this.ownershipOptions.length) { + this.ownershipOptions = []; + } + if (await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership)) { + this.allowPersonal = false; + } else { + const myEmail = await this.stateService.getEmail(); + this.ownershipOptions.push({ name: myEmail, value: null }); + } + + const orgs = await this.organizationService.getAll(); + orgs.sort(Utils.getSortFunction(this.i18nService, "name")).forEach((o) => { + if (o.enabled && o.status === OrganizationUserStatusType.Confirmed) { + this.ownershipOptions.push({ name: o.name, value: o.id }); + } + }); + if (!this.allowPersonal) { + this.organizationId = this.ownershipOptions[0].value; + } + + this.writeableCollections = await this.loadCollections(); + + this.canUseReprompt = await this.passwordRepromptService.enabled(); + } + + async load() { + this.editMode = this.cipherId != null; + if (this.editMode) { + this.editMode = true; + if (this.cloneMode) { + this.cloneMode = true; + this.title = this.i18nService.t("addItem"); + } else { + this.title = this.i18nService.t("editItem"); + } + } else { + this.title = this.i18nService.t("addItem"); + } + + const addEditCipherInfo: any = await this.stateService.getAddEditCipherInfo(); + if (addEditCipherInfo != null) { + this.cipher = addEditCipherInfo.cipher; + this.collectionIds = addEditCipherInfo.collectionIds; + } + await this.stateService.setAddEditCipherInfo(null); + + if (this.cipher == null) { + if (this.editMode) { + const cipher = await this.loadCipher(); + this.cipher = await cipher.decrypt(); + + // Adjust Cipher Name if Cloning + if (this.cloneMode) { + this.cipher.name += " - " + this.i18nService.t("clone"); + // If not allowing personal ownership, update cipher's org Id to prompt downstream changes + if (this.cipher.organizationId == null && !this.allowPersonal) { + this.cipher.organizationId = this.organizationId; + } + } + } else { + this.cipher = new CipherView(); + this.cipher.organizationId = this.organizationId == null ? null : this.organizationId; + this.cipher.folderId = this.folderId; + this.cipher.type = this.type == null ? CipherType.Login : this.type; + this.cipher.login = new LoginView(); + this.cipher.login.uris = [new LoginUriView()]; + this.cipher.card = new CardView(); + this.cipher.identity = new IdentityView(); + this.cipher.secureNote = new SecureNoteView(); + this.cipher.secureNote.type = SecureNoteType.Generic; + this.cipher.reprompt = CipherRepromptType.None; + } + } + + if (this.cipher != null && (!this.editMode || addEditCipherInfo != null || this.cloneMode)) { + await this.organizationChanged(); + if ( + this.collectionIds != null && + this.collectionIds.length > 0 && + this.collections.length > 0 + ) { + this.collections.forEach((c) => { + if (this.collectionIds.indexOf(c.id) > -1) { + (c as any).checked = true; + } + }); + } + } + + this.folders = await this.folderService.getAllDecrypted(); + + if (this.editMode && this.previousCipherId !== this.cipherId) { + this.eventService.collect(EventType.Cipher_ClientViewed, this.cipherId); + } + this.previousCipherId = this.cipherId; + this.reprompt = this.cipher.reprompt !== CipherRepromptType.None; + } + + async submit(): Promise { + if (this.cipher.isDeleted) { + return this.restore(); + } + + if (this.cipher.name == null || this.cipher.name === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("nameRequired") + ); + return false; + } + + if ( + (!this.editMode || this.cloneMode) && + !this.allowPersonal && + this.cipher.organizationId == null + ) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("personalOwnershipSubmitError") + ); + return false; + } + + if ( + (!this.editMode || this.cloneMode) && + this.cipher.type === CipherType.Login && + this.cipher.login.uris != null && + this.cipher.login.uris.length === 1 && + (this.cipher.login.uris[0].uri == null || this.cipher.login.uris[0].uri === "") + ) { + this.cipher.login.uris = null; + } + + // Allows saving of selected collections during "Add" and "Clone" flows + if ((!this.editMode || this.cloneMode) && this.cipher.organizationId != null) { + this.cipher.collectionIds = + this.collections == null + ? [] + : this.collections.filter((c) => (c as any).checked).map((c) => c.id); + } + + // Clear current Cipher Id to trigger "Add" cipher flow + if (this.cloneMode) { + this.cipher.id = null; + } + + const cipher = await this.encryptCipher(); + try { + this.formPromise = this.saveCipher(cipher); + await this.formPromise; + this.cipher.id = cipher.id; + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t(this.editMode && !this.cloneMode ? "editedItem" : "addedItem") + ); + this.onSavedCipher.emit(this.cipher); + this.messagingService.send(this.editMode && !this.cloneMode ? "editedCipher" : "addedCipher"); + return true; + } catch (e) { + this.logService.error(e); + } + + return false; + } + + addUri() { + if (this.cipher.type !== CipherType.Login) { + return; + } + + if (this.cipher.login.uris == null) { + this.cipher.login.uris = []; + } + + this.cipher.login.uris.push(new LoginUriView()); + } + + removeUri(uri: LoginUriView) { + if (this.cipher.type !== CipherType.Login || this.cipher.login.uris == null) { + return; + } + + const i = this.cipher.login.uris.indexOf(uri); + if (i > -1) { + this.cipher.login.uris.splice(i, 1); + } + } + + trackByFunction(index: number, item: any) { + return index; + } + + cancel() { + this.onCancelled.emit(this.cipher); + } + + attachments() { + this.onEditAttachments.emit(this.cipher); + } + + share() { + this.onShareCipher.emit(this.cipher); + } + + editCollections() { + this.onEditCollections.emit(this.cipher); + } + + async delete(): Promise { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t( + this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" + ), + this.i18nService.t("deleteItem"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + this.deletePromise = this.deleteCipher(); + await this.deletePromise; + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t(this.cipher.isDeleted ? "permanentlyDeletedItem" : "deletedItem") + ); + this.onDeletedCipher.emit(this.cipher); + this.messagingService.send( + this.cipher.isDeleted ? "permanentlyDeletedCipher" : "deletedCipher" + ); + } catch (e) { + this.logService.error(e); + } + + return true; + } + + async restore(): Promise { + if (!this.cipher.isDeleted) { + return false; + } + + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("restoreItemConfirmation"), + this.i18nService.t("restoreItem"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + this.restorePromise = this.restoreCipher(); + await this.restorePromise; + this.platformUtilsService.showToast("success", null, this.i18nService.t("restoredItem")); + this.onRestoredCipher.emit(this.cipher); + this.messagingService.send("restoredCipher"); + } catch (e) { + this.logService.error(e); + } + + return true; + } + + async generateUsername(): Promise { + if (this.cipher.login?.username?.length) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("overwriteUsernameConfirmation"), + this.i18nService.t("overwriteUsername"), + this.i18nService.t("yes"), + this.i18nService.t("no") + ); + if (!confirmed) { + return false; + } + } + + this.onGenerateUsername.emit(); + return true; + } + + async generatePassword(): Promise { + if (this.cipher.login?.password?.length) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("overwritePasswordConfirmation"), + this.i18nService.t("overwritePassword"), + this.i18nService.t("yes"), + this.i18nService.t("no") + ); + if (!confirmed) { + return false; + } + } + + this.onGeneratePassword.emit(); + return true; + } + + togglePassword() { + this.showPassword = !this.showPassword; + document.getElementById("loginPassword").focus(); + if (this.editMode && this.showPassword) { + this.eventService.collect(EventType.Cipher_ClientToggledPasswordVisible, this.cipherId); + } + } + + async toggleCardNumber() { + this.showCardNumber = !this.showCardNumber; + if (this.showCardNumber) { + this.eventService.collect(EventType.Cipher_ClientToggledCardNumberVisible, this.cipherId); + } + } + + toggleCardCode() { + this.showCardCode = !this.showCardCode; + document.getElementById("cardCode").focus(); + if (this.editMode && this.showCardCode) { + this.eventService.collect(EventType.Cipher_ClientToggledCardCodeVisible, this.cipherId); + } + } + + toggleUriOptions(uri: LoginUriView) { + const u = uri as any; + u.showOptions = u.showOptions == null && uri.match != null ? false : !u.showOptions; + } + + loginUriMatchChanged(uri: LoginUriView) { + const u = uri as any; + u.showOptions = u.showOptions == null ? true : u.showOptions; + } + + async organizationChanged() { + if (this.writeableCollections != null) { + this.writeableCollections.forEach((c) => ((c as any).checked = false)); + } + if (this.cipher.organizationId != null) { + this.collections = this.writeableCollections.filter( + (c) => c.organizationId === this.cipher.organizationId + ); + const org = await this.organizationService.get(this.cipher.organizationId); + if (org != null) { + this.cipher.organizationUseTotp = org.useTotp; + } + } else { + this.collections = []; + } + } + + async checkPassword() { + if (this.checkPasswordPromise != null) { + return; + } + + if ( + this.cipher.login == null || + this.cipher.login.password == null || + this.cipher.login.password === "" + ) { + return; + } + + this.checkPasswordPromise = this.auditService.passwordLeaked(this.cipher.login.password); + const matches = await this.checkPasswordPromise; + this.checkPasswordPromise = null; + + if (matches > 0) { + this.platformUtilsService.showToast( + "warning", + null, + this.i18nService.t("passwordExposed", matches.toString()) + ); + } else { + this.platformUtilsService.showToast("success", null, this.i18nService.t("passwordSafe")); + } + } + + repromptChanged() { + this.reprompt = !this.reprompt; + if (this.reprompt) { + this.cipher.reprompt = CipherRepromptType.Password; + } else { + this.cipher.reprompt = CipherRepromptType.None; + } + } + + protected async loadCollections() { + const allCollections = await this.collectionService.getAllDecrypted(); + return allCollections.filter((c) => !c.readOnly); + } + + protected loadCipher() { + return this.cipherService.get(this.cipherId); + } + + protected encryptCipher() { + return this.cipherService.encrypt(this.cipher); + } + + protected saveCipher(cipher: Cipher) { + return this.cipherService.saveWithServer(cipher); + } + + protected deleteCipher() { + return this.cipher.isDeleted + ? this.cipherService.deleteWithServer(this.cipher.id) + : this.cipherService.softDeleteWithServer(this.cipher.id); + } + + protected restoreCipher() { + return this.cipherService.restoreWithServer(this.cipher.id); + } +} diff --git a/libs/angular/src/components/attachments.component.ts b/libs/angular/src/components/attachments.component.ts new file mode 100644 index 0000000000..ff76f6abd4 --- /dev/null +++ b/libs/angular/src/components/attachments.component.ts @@ -0,0 +1,289 @@ +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Cipher } from "jslib-common/models/domain/cipher"; +import { ErrorResponse } from "jslib-common/models/response/errorResponse"; +import { AttachmentView } from "jslib-common/models/view/attachmentView"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +@Directive() +export class AttachmentsComponent implements OnInit { + @Input() cipherId: string; + @Output() onUploadedAttachment = new EventEmitter(); + @Output() onDeletedAttachment = new EventEmitter(); + @Output() onReuploadedAttachment = new EventEmitter(); + + cipher: CipherView; + cipherDomain: Cipher; + hasUpdatedKey: boolean; + canAccessAttachments: boolean; + formPromise: Promise; + deletePromises: { [id: string]: Promise } = {}; + reuploadPromises: { [id: string]: Promise } = {}; + emergencyAccessId?: string = null; + + constructor( + protected cipherService: CipherService, + protected i18nService: I18nService, + protected cryptoService: CryptoService, + protected platformUtilsService: PlatformUtilsService, + protected apiService: ApiService, + protected win: Window, + protected logService: LogService, + protected stateService: StateService + ) {} + + async ngOnInit() { + await this.init(); + } + + async submit() { + if (!this.hasUpdatedKey) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("updateKey") + ); + return; + } + + const fileEl = document.getElementById("file") as HTMLInputElement; + const files = fileEl.files; + if (files == null || files.length === 0) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("selectFile") + ); + return; + } + + if (files[0].size > 524288000) { + // 500 MB + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("maxFileSize") + ); + return; + } + + try { + this.formPromise = this.saveCipherAttachment(files[0]); + this.cipherDomain = await this.formPromise; + this.cipher = await this.cipherDomain.decrypt(); + this.platformUtilsService.showToast("success", null, this.i18nService.t("attachmentSaved")); + this.onUploadedAttachment.emit(); + } catch (e) { + this.logService.error(e); + } + + // reset file input + // ref: https://stackoverflow.com/a/20552042 + fileEl.type = ""; + fileEl.type = "file"; + fileEl.value = ""; + } + + async delete(attachment: AttachmentView) { + if (this.deletePromises[attachment.id] != null) { + return; + } + + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("deleteAttachmentConfirmation"), + this.i18nService.t("deleteAttachment"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return; + } + + try { + this.deletePromises[attachment.id] = this.deleteCipherAttachment(attachment.id); + await this.deletePromises[attachment.id]; + this.platformUtilsService.showToast("success", null, this.i18nService.t("deletedAttachment")); + const i = this.cipher.attachments.indexOf(attachment); + if (i > -1) { + this.cipher.attachments.splice(i, 1); + } + } catch (e) { + this.logService.error(e); + } + + this.deletePromises[attachment.id] = null; + this.onDeletedAttachment.emit(); + } + + async download(attachment: AttachmentView) { + const a = attachment as any; + if (a.downloading) { + return; + } + + if (!this.canAccessAttachments) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("premiumRequired"), + this.i18nService.t("premiumRequiredDesc") + ); + return; + } + + let url: string; + try { + const attachmentDownloadResponse = await this.apiService.getAttachmentData( + this.cipher.id, + attachment.id, + this.emergencyAccessId + ); + url = attachmentDownloadResponse.url; + } catch (e) { + if (e instanceof ErrorResponse && (e as ErrorResponse).statusCode === 404) { + url = attachment.url; + } else if (e instanceof ErrorResponse) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } else { + throw e; + } + } + + a.downloading = true; + const response = await fetch(new Request(url, { cache: "no-store" })); + if (response.status !== 200) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + a.downloading = false; + return; + } + + try { + const buf = await response.arrayBuffer(); + const key = + attachment.key != null + ? attachment.key + : await this.cryptoService.getOrgKey(this.cipher.organizationId); + const decBuf = await this.cryptoService.decryptFromBytes(buf, key); + this.platformUtilsService.saveFile(this.win, decBuf, null, attachment.fileName); + } catch (e) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + } + + a.downloading = false; + } + + protected async init() { + this.cipherDomain = await this.loadCipher(); + this.cipher = await this.cipherDomain.decrypt(); + + this.hasUpdatedKey = await this.cryptoService.hasEncKey(); + const canAccessPremium = await this.stateService.getCanAccessPremium(); + this.canAccessAttachments = canAccessPremium || this.cipher.organizationId != null; + + if (!this.canAccessAttachments) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("premiumRequiredDesc"), + this.i18nService.t("premiumRequired"), + this.i18nService.t("learnMore"), + this.i18nService.t("cancel") + ); + if (confirmed) { + this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/?premium=purchase"); + } + } else if (!this.hasUpdatedKey) { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("updateKey"), + this.i18nService.t("featureUnavailable"), + this.i18nService.t("learnMore"), + this.i18nService.t("cancel"), + "warning" + ); + if (confirmed) { + this.platformUtilsService.launchUri( + "https://bitwarden.com/help/account-encryption-key/#rotate-your-encryption-key" + ); + } + } + } + + protected async reuploadCipherAttachment(attachment: AttachmentView, admin: boolean) { + const a = attachment as any; + if (attachment.key != null || a.downloading || this.reuploadPromises[attachment.id] != null) { + return; + } + + try { + this.reuploadPromises[attachment.id] = Promise.resolve().then(async () => { + // 1. Download + a.downloading = true; + const response = await fetch(new Request(attachment.url, { cache: "no-store" })); + if (response.status !== 200) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + a.downloading = false; + return; + } + + try { + // 2. Resave + const buf = await response.arrayBuffer(); + const key = + attachment.key != null + ? attachment.key + : await this.cryptoService.getOrgKey(this.cipher.organizationId); + const decBuf = await this.cryptoService.decryptFromBytes(buf, key); + this.cipherDomain = await this.cipherService.saveAttachmentRawWithServer( + this.cipherDomain, + attachment.fileName, + decBuf, + admin + ); + this.cipher = await this.cipherDomain.decrypt(); + + // 3. Delete old + this.deletePromises[attachment.id] = this.deleteCipherAttachment(attachment.id); + await this.deletePromises[attachment.id]; + const foundAttachment = this.cipher.attachments.filter((a2) => a2.id === attachment.id); + if (foundAttachment.length > 0) { + const i = this.cipher.attachments.indexOf(foundAttachment[0]); + if (i > -1) { + this.cipher.attachments.splice(i, 1); + } + } + + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("attachmentSaved") + ); + this.onReuploadedAttachment.emit(); + } catch (e) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + } + + a.downloading = false; + }); + await this.reuploadPromises[attachment.id]; + } catch (e) { + this.logService.error(e); + } + } + + protected loadCipher() { + return this.cipherService.get(this.cipherId); + } + + protected saveCipherAttachment(file: File) { + return this.cipherService.saveAttachmentWithServer(this.cipherDomain, file); + } + + protected deleteCipherAttachment(attachmentId: string) { + return this.cipherService.deleteAttachmentWithServer(this.cipher.id, attachmentId); + } +} diff --git a/libs/angular/src/components/avatar.component.ts b/libs/angular/src/components/avatar.component.ts new file mode 100644 index 0000000000..bc029ea461 --- /dev/null +++ b/libs/angular/src/components/avatar.component.ts @@ -0,0 +1,140 @@ +import { Component, Input, OnChanges, OnInit } from "@angular/core"; +import { DomSanitizer } from "@angular/platform-browser"; + +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; + +@Component({ + selector: "app-avatar", + template: + '", +}) +export class AvatarComponent implements OnChanges, OnInit { + @Input() data: string; + @Input() email: string; + @Input() size = 45; + @Input() charCount = 2; + @Input() textColor = "#ffffff"; + @Input() fontSize = 20; + @Input() fontWeight = 300; + @Input() dynamic = false; + @Input() circle = false; + + src: string; + + constructor( + public sanitizer: DomSanitizer, + private cryptoFunctionService: CryptoFunctionService, + private stateService: StateService + ) {} + + ngOnInit() { + if (!this.dynamic) { + this.generate(); + } + } + + ngOnChanges() { + if (this.dynamic) { + this.generate(); + } + } + + private async generate() { + const enableGravatars = await this.stateService.getEnableGravitars(); + if (enableGravatars && this.email != null) { + const hashBytes = await this.cryptoFunctionService.hash( + this.email.toLowerCase().trim(), + "md5" + ); + const hash = Utils.fromBufferToHex(hashBytes).toLowerCase(); + this.src = "https://www.gravatar.com/avatar/" + hash + "?s=" + this.size + "&r=pg&d=retro"; + } else { + let chars: string = null; + const upperData = this.data.toUpperCase(); + + if (this.charCount > 1) { + chars = this.getFirstLetters(upperData, this.charCount); + } + if (chars == null) { + chars = this.unicodeSafeSubstring(upperData, this.charCount); + } + + // If the chars contain an emoji, only show it. + if (chars.match(Utils.regexpEmojiPresentation)) { + chars = chars.match(Utils.regexpEmojiPresentation)[0]; + } + + const charObj = this.getCharText(chars); + const color = this.stringToColor(upperData); + const svg = this.getSvg(this.size, color); + svg.appendChild(charObj); + const html = window.document.createElement("div").appendChild(svg).outerHTML; + const svgHtml = window.btoa(unescape(encodeURIComponent(html))); + this.src = "data:image/svg+xml;base64," + svgHtml; + } + } + + private stringToColor(str: string): string { + let hash = 0; + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + let color = "#"; + for (let i = 0; i < 3; i++) { + const value = (hash >> (i * 8)) & 0xff; + color += ("00" + value.toString(16)).substr(-2); + } + return color; + } + + private getFirstLetters(data: string, count: number): string { + const parts = data.split(" "); + if (parts.length > 1) { + let text = ""; + for (let i = 0; i < count; i++) { + text += this.unicodeSafeSubstring(parts[i], 1); + } + return text; + } + return null; + } + + private getSvg(size: number, color: string): HTMLElement { + const svgTag = window.document.createElement("svg"); + svgTag.setAttribute("xmlns", "http://www.w3.org/2000/svg"); + svgTag.setAttribute("pointer-events", "none"); + svgTag.setAttribute("width", size.toString()); + svgTag.setAttribute("height", size.toString()); + svgTag.style.backgroundColor = color; + svgTag.style.width = size + "px"; + svgTag.style.height = size + "px"; + return svgTag; + } + + private getCharText(character: string): HTMLElement { + const textTag = window.document.createElement("text"); + textTag.setAttribute("text-anchor", "middle"); + textTag.setAttribute("y", "50%"); + textTag.setAttribute("x", "50%"); + textTag.setAttribute("dy", "0.35em"); + textTag.setAttribute("pointer-events", "auto"); + textTag.setAttribute("fill", this.textColor); + textTag.setAttribute( + "font-family", + '"Open Sans","Helvetica Neue",Helvetica,Arial,' + + 'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"' + ); + textTag.textContent = character; + textTag.style.fontWeight = this.fontWeight.toString(); + textTag.style.fontSize = this.fontSize + "px"; + return textTag; + } + + private unicodeSafeSubstring(str: string, count: number) { + const characters = str.match(/./gu); + return characters != null ? characters.slice(0, count).join("") : ""; + } +} diff --git a/libs/angular/src/components/callout.component.html b/libs/angular/src/components/callout.component.html new file mode 100644 index 0000000000..a049d5cb72 --- /dev/null +++ b/libs/angular/src/components/callout.component.html @@ -0,0 +1,35 @@ +
+

+ + {{ title }} +

+
+ {{ enforcedPolicyMessage }} +
    +
  • + {{ "policyInEffectMinComplexity" | i18n: getPasswordScoreAlertDisplay() }} +
  • +
  • + {{ "policyInEffectMinLength" | i18n: enforcedPolicyOptions?.minLength.toString() }} +
  • +
  • + {{ "policyInEffectUppercase" | i18n }} +
  • +
  • + {{ "policyInEffectLowercase" | i18n }} +
  • +
  • + {{ "policyInEffectNumbers" | i18n }} +
  • +
  • + {{ "policyInEffectSpecial" | i18n: "!@#$%^&*" }} +
  • +
+
+ +
diff --git a/libs/angular/src/components/callout.component.ts b/libs/angular/src/components/callout.component.ts new file mode 100644 index 0000000000..a1785fe515 --- /dev/null +++ b/libs/angular/src/components/callout.component.ts @@ -0,0 +1,78 @@ +import { Component, Input, OnInit } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MasterPasswordPolicyOptions } from "jslib-common/models/domain/masterPasswordPolicyOptions"; + +@Component({ + selector: "app-callout", + templateUrl: "callout.component.html", +}) +export class CalloutComponent implements OnInit { + @Input() type = "info"; + @Input() icon: string; + @Input() title: string; + @Input() clickable: boolean; + @Input() enforcedPolicyOptions: MasterPasswordPolicyOptions; + @Input() enforcedPolicyMessage: string; + @Input() useAlertRole = false; + + calloutStyle: string; + + constructor(private i18nService: I18nService) {} + + ngOnInit() { + this.calloutStyle = this.type; + + if (this.enforcedPolicyMessage === undefined) { + this.enforcedPolicyMessage = this.i18nService.t("masterPasswordPolicyInEffect"); + } + + if (this.type === "warning" || this.type === "danger") { + if (this.type === "danger") { + this.calloutStyle = "danger"; + } + if (this.title === undefined) { + this.title = this.i18nService.t("warning"); + } + if (this.icon === undefined) { + this.icon = "bwi-exclamation-triangle"; + } + } else if (this.type === "error") { + this.calloutStyle = "danger"; + if (this.title === undefined) { + this.title = this.i18nService.t("error"); + } + if (this.icon === undefined) { + this.icon = "bwi-error"; + } + } else if (this.type === "tip") { + this.calloutStyle = "success"; + if (this.title === undefined) { + this.title = this.i18nService.t("tip"); + } + if (this.icon === undefined) { + this.icon = "bwi-lightbulb"; + } + } + } + + getPasswordScoreAlertDisplay() { + if (this.enforcedPolicyOptions == null) { + return ""; + } + + let str: string; + switch (this.enforcedPolicyOptions.minComplexity) { + case 4: + str = this.i18nService.t("strong"); + break; + case 3: + str = this.i18nService.t("good"); + break; + default: + str = this.i18nService.t("weak"); + break; + } + return str + " (" + this.enforcedPolicyOptions.minComplexity + ")"; + } +} diff --git a/libs/angular/src/components/captchaProtected.component.ts b/libs/angular/src/components/captchaProtected.component.ts new file mode 100644 index 0000000000..998970e4fc --- /dev/null +++ b/libs/angular/src/components/captchaProtected.component.ts @@ -0,0 +1,53 @@ +import { Directive, Input } from "@angular/core"; + +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { CaptchaIFrame } from "jslib-common/misc/captcha_iframe"; +import { Utils } from "jslib-common/misc/utils"; + +@Directive() +export abstract class CaptchaProtectedComponent { + @Input() captchaSiteKey: string = null; + captchaToken: string = null; + captcha: CaptchaIFrame; + + constructor( + protected environmentService: EnvironmentService, + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService + ) {} + + async setupCaptcha() { + const webVaultUrl = this.environmentService.getWebVaultUrl(); + + this.captcha = new CaptchaIFrame( + window, + webVaultUrl, + this.i18nService, + (token: string) => { + this.captchaToken = token; + }, + (error: string) => { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), error); + }, + (info: string) => { + this.platformUtilsService.showToast("info", this.i18nService.t("info"), info); + } + ); + } + + showCaptcha() { + return !Utils.isNullOrWhitespace(this.captchaSiteKey); + } + + protected handleCaptchaRequired(response: { captchaSiteKey: string }): boolean { + if (Utils.isNullOrWhitespace(response.captchaSiteKey)) { + return false; + } + + this.captchaSiteKey = response.captchaSiteKey; + this.captcha.init(response.captchaSiteKey); + return true; + } +} diff --git a/libs/angular/src/components/change-password.component.ts b/libs/angular/src/components/change-password.component.ts new file mode 100644 index 0000000000..4b2ea6196d --- /dev/null +++ b/libs/angular/src/components/change-password.component.ts @@ -0,0 +1,195 @@ +import { Directive, OnInit } from "@angular/core"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { KdfType } from "jslib-common/enums/kdfType"; +import { EncString } from "jslib-common/models/domain/encString"; +import { MasterPasswordPolicyOptions } from "jslib-common/models/domain/masterPasswordPolicyOptions"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; + +@Directive() +export class ChangePasswordComponent implements OnInit { + masterPassword: string; + masterPasswordRetype: string; + formPromise: Promise; + masterPasswordScore: number; + enforcedPolicyOptions: MasterPasswordPolicyOptions; + + protected email: string; + protected kdf: KdfType; + protected kdfIterations: number; + + private masterPasswordStrengthTimeout: any; + + constructor( + protected i18nService: I18nService, + protected cryptoService: CryptoService, + protected messagingService: MessagingService, + protected passwordGenerationService: PasswordGenerationService, + protected platformUtilsService: PlatformUtilsService, + protected policyService: PolicyService, + protected stateService: StateService + ) {} + + async ngOnInit() { + this.email = await this.stateService.getEmail(); + this.enforcedPolicyOptions ??= await this.policyService.getMasterPasswordPolicyOptions(); + } + + async submit() { + if (!(await this.strongPassword())) { + return; + } + + if (!(await this.setupSubmitActions())) { + return; + } + + const email = await this.stateService.getEmail(); + if (this.kdf == null) { + this.kdf = await this.stateService.getKdfType(); + } + if (this.kdfIterations == null) { + this.kdfIterations = await this.stateService.getKdfIterations(); + } + const key = await this.cryptoService.makeKey( + this.masterPassword, + email.trim().toLowerCase(), + this.kdf, + this.kdfIterations + ); + const masterPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, key); + + let encKey: [SymmetricCryptoKey, EncString] = null; + const existingEncKey = await this.cryptoService.getEncKey(); + if (existingEncKey == null) { + encKey = await this.cryptoService.makeEncKey(key); + } else { + encKey = await this.cryptoService.remakeEncKey(key); + } + + await this.performSubmitActions(masterPasswordHash, key, encKey); + } + + async setupSubmitActions(): Promise { + // Override in sub-class + // Can be used for additional validation and/or other processes the should occur before changing passwords + return true; + } + + async performSubmitActions( + masterPasswordHash: string, + key: SymmetricCryptoKey, + encKey: [SymmetricCryptoKey, EncString] + ) { + // Override in sub-class + } + + async strongPassword(): Promise { + if (this.masterPassword == null || this.masterPassword === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassRequired") + ); + return false; + } + if (this.masterPassword.length < 8) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassLength") + ); + return false; + } + if (this.masterPassword !== this.masterPasswordRetype) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassDoesntMatch") + ); + return false; + } + + const strengthResult = this.passwordGenerationService.passwordStrength( + this.masterPassword, + this.getPasswordStrengthUserInput() + ); + + if ( + this.enforcedPolicyOptions != null && + !this.policyService.evaluateMasterPassword( + strengthResult.score, + this.masterPassword, + this.enforcedPolicyOptions + ) + ) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPasswordPolicyRequirementsNotMet") + ); + return false; + } + + if (strengthResult != null && strengthResult.score < 3) { + const result = await this.platformUtilsService.showDialog( + this.i18nService.t("weakMasterPasswordDesc"), + this.i18nService.t("weakMasterPassword"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!result) { + return false; + } + } + + return true; + } + + updatePasswordStrength() { + if (this.masterPasswordStrengthTimeout != null) { + clearTimeout(this.masterPasswordStrengthTimeout); + } + this.masterPasswordStrengthTimeout = setTimeout(() => { + const strengthResult = this.passwordGenerationService.passwordStrength( + this.masterPassword, + this.getPasswordStrengthUserInput() + ); + this.masterPasswordScore = strengthResult == null ? null : strengthResult.score; + }, 300); + } + + async logOut() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("logOutConfirmation"), + this.i18nService.t("logOut"), + this.i18nService.t("logOut"), + this.i18nService.t("cancel") + ); + if (confirmed) { + this.messagingService.send("logout"); + } + } + + private getPasswordStrengthUserInput() { + let userInput: string[] = []; + const atPosition = this.email.indexOf("@"); + if (atPosition > -1) { + userInput = userInput.concat( + this.email + .substr(0, atPosition) + .trim() + .toLowerCase() + .split(/[^A-Za-z0-9]/) + ); + } + return userInput; + } +} diff --git a/libs/angular/src/components/ciphers.component.ts b/libs/angular/src/components/ciphers.component.ts new file mode 100644 index 0000000000..62fe65a73b --- /dev/null +++ b/libs/angular/src/components/ciphers.component.ts @@ -0,0 +1,92 @@ +import { Directive, EventEmitter, Input, Output } from "@angular/core"; + +import { SearchService } from "jslib-common/abstractions/search.service"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +@Directive() +export class CiphersComponent { + @Input() activeCipherId: string = null; + @Output() onCipherClicked = new EventEmitter(); + @Output() onCipherRightClicked = new EventEmitter(); + @Output() onAddCipher = new EventEmitter(); + @Output() onAddCipherOptions = new EventEmitter(); + + loaded = false; + ciphers: CipherView[] = []; + searchText: string; + searchPlaceholder: string = null; + filter: (cipher: CipherView) => boolean = null; + deleted = false; + + protected searchPending = false; + + private searchTimeout: any = null; + + constructor(protected searchService: SearchService) {} + + async load(filter: (cipher: CipherView) => boolean = null, deleted = false) { + this.deleted = deleted || false; + await this.applyFilter(filter); + this.loaded = true; + } + + async reload(filter: (cipher: CipherView) => boolean = null, deleted = false) { + this.loaded = false; + await this.load(filter, deleted); + } + + async refresh() { + await this.reload(this.filter, this.deleted); + } + + async applyFilter(filter: (cipher: CipherView) => boolean = null) { + this.filter = filter; + await this.search(null); + } + + async search(timeout: number = null, indexedCiphers?: CipherView[]) { + this.searchPending = false; + if (this.searchTimeout != null) { + clearTimeout(this.searchTimeout); + } + if (timeout == null) { + await this.doSearch(indexedCiphers); + return; + } + this.searchPending = true; + this.searchTimeout = setTimeout(async () => { + await this.doSearch(indexedCiphers); + this.searchPending = false; + }, timeout); + } + + selectCipher(cipher: CipherView) { + this.onCipherClicked.emit(cipher); + } + + rightClickCipher(cipher: CipherView) { + this.onCipherRightClicked.emit(cipher); + } + + addCipher() { + this.onAddCipher.emit(); + } + + addCipherOptions() { + this.onAddCipherOptions.emit(); + } + + isSearching() { + return !this.searchPending && this.searchService.isSearchable(this.searchText); + } + + protected deletedFilter: (cipher: CipherView) => boolean = (c) => c.isDeleted === this.deleted; + + protected async doSearch(indexedCiphers?: CipherView[]) { + this.ciphers = await this.searchService.searchCiphers( + this.searchText, + [this.filter, this.deletedFilter], + indexedCiphers + ); + } +} diff --git a/libs/angular/src/components/collections.component.ts b/libs/angular/src/components/collections.component.ts new file mode 100644 index 0000000000..284b97db86 --- /dev/null +++ b/libs/angular/src/components/collections.component.ts @@ -0,0 +1,92 @@ +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; + +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { Cipher } from "jslib-common/models/domain/cipher"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { CollectionView } from "jslib-common/models/view/collectionView"; + +@Directive() +export class CollectionsComponent implements OnInit { + @Input() cipherId: string; + @Input() allowSelectNone = false; + @Output() onSavedCollections = new EventEmitter(); + + formPromise: Promise; + cipher: CipherView; + collectionIds: string[]; + collections: CollectionView[] = []; + + protected cipherDomain: Cipher; + + constructor( + protected collectionService: CollectionService, + protected platformUtilsService: PlatformUtilsService, + protected i18nService: I18nService, + protected cipherService: CipherService, + private logService: LogService + ) {} + + async ngOnInit() { + await this.load(); + } + + async load() { + this.cipherDomain = await this.loadCipher(); + this.collectionIds = this.loadCipherCollections(); + this.cipher = await this.cipherDomain.decrypt(); + this.collections = await this.loadCollections(); + + this.collections.forEach((c) => ((c as any).checked = false)); + if (this.collectionIds != null) { + this.collections.forEach((c) => { + (c as any).checked = this.collectionIds != null && this.collectionIds.indexOf(c.id) > -1; + }); + } + } + + async submit() { + const selectedCollectionIds = this.collections + .filter((c) => !!(c as any).checked) + .map((c) => c.id); + if (!this.allowSelectNone && selectedCollectionIds.length === 0) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("selectOneCollection") + ); + return; + } + this.cipherDomain.collectionIds = selectedCollectionIds; + try { + this.formPromise = this.saveCollections(); + await this.formPromise; + this.onSavedCollections.emit(); + this.platformUtilsService.showToast("success", null, this.i18nService.t("editedItem")); + } catch (e) { + this.logService.error(e); + } + } + + protected loadCipher() { + return this.cipherService.get(this.cipherId); + } + + protected loadCipherCollections() { + return this.cipherDomain.collectionIds; + } + + protected async loadCollections() { + const allCollections = await this.collectionService.getAllDecrypted(); + return allCollections.filter( + (c) => !c.readOnly && c.organizationId === this.cipher.organizationId + ); + } + + protected saveCollections() { + return this.cipherService.saveCollectionsWithServer(this.cipherDomain); + } +} diff --git a/libs/angular/src/components/environment.component.ts b/libs/angular/src/components/environment.component.ts new file mode 100644 index 0000000000..8b7689de36 --- /dev/null +++ b/libs/angular/src/components/environment.component.ts @@ -0,0 +1,63 @@ +import { Directive, EventEmitter, Output } from "@angular/core"; + +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Directive() +export class EnvironmentComponent { + @Output() onSaved = new EventEmitter(); + + iconsUrl: string; + identityUrl: string; + apiUrl: string; + webVaultUrl: string; + notificationsUrl: string; + baseUrl: string; + showCustom = false; + + constructor( + protected platformUtilsService: PlatformUtilsService, + protected environmentService: EnvironmentService, + protected i18nService: I18nService + ) { + const urls = this.environmentService.getUrls(); + + this.baseUrl = urls.base || ""; + this.webVaultUrl = urls.webVault || ""; + this.apiUrl = urls.api || ""; + this.identityUrl = urls.identity || ""; + this.iconsUrl = urls.icons || ""; + this.notificationsUrl = urls.notifications || ""; + } + + async submit() { + const resUrls = await this.environmentService.setUrls({ + base: this.baseUrl, + api: this.apiUrl, + identity: this.identityUrl, + webVault: this.webVaultUrl, + icons: this.iconsUrl, + notifications: this.notificationsUrl, + }); + + // re-set urls since service can change them, ex: prefixing https:// + this.baseUrl = resUrls.base; + this.apiUrl = resUrls.api; + this.identityUrl = resUrls.identity; + this.webVaultUrl = resUrls.webVault; + this.iconsUrl = resUrls.icons; + this.notificationsUrl = resUrls.notifications; + + this.platformUtilsService.showToast("success", null, this.i18nService.t("environmentSaved")); + this.saved(); + } + + toggleCustom() { + this.showCustom = !this.showCustom; + } + + protected saved() { + this.onSaved.emit(); + } +} diff --git a/libs/angular/src/components/export-scope-callout.component.html b/libs/angular/src/components/export-scope-callout.component.html new file mode 100644 index 0000000000..c6b5e1e852 --- /dev/null +++ b/libs/angular/src/components/export-scope-callout.component.html @@ -0,0 +1,5 @@ + + + {{ scopeConfig.description | i18n: scopeConfig.scopeIdentifier }} + + diff --git a/libs/angular/src/components/export-scope-callout.component.ts b/libs/angular/src/components/export-scope-callout.component.ts new file mode 100644 index 0000000000..a20118465e --- /dev/null +++ b/libs/angular/src/components/export-scope-callout.component.ts @@ -0,0 +1,43 @@ +import { Component, Input, OnInit } from "@angular/core"; + +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Component({ + selector: "app-export-scope-callout", + templateUrl: "export-scope-callout.component.html", +}) +export class ExportScopeCalloutComponent implements OnInit { + @Input() organizationId: string = null; + + show = false; + scopeConfig: { + title: string; + description: string; + scopeIdentifier: string; + }; + + constructor( + protected organizationService: OrganizationService, + protected stateService: StateService + ) {} + + async ngOnInit(): Promise { + if (!(await this.organizationService.hasOrganizations())) { + return; + } + this.scopeConfig = + this.organizationId != null + ? { + title: "exportingOrganizationVaultTitle", + description: "exportingOrganizationVaultDescription", + scopeIdentifier: (await this.organizationService.get(this.organizationId)).name, + } + : { + title: "exportingPersonalVaultTitle", + description: "exportingPersonalVaultDescription", + scopeIdentifier: await this.stateService.getEmail(), + }; + this.show = true; + } +} diff --git a/libs/angular/src/components/export.component.ts b/libs/angular/src/components/export.component.ts new file mode 100644 index 0000000000..8f892045ca --- /dev/null +++ b/libs/angular/src/components/export.component.ts @@ -0,0 +1,155 @@ +import { Directive, EventEmitter, OnInit, Output } from "@angular/core"; +import { FormBuilder } from "@angular/forms"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { ExportService } from "jslib-common/abstractions/export.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { UserVerificationService } from "jslib-common/abstractions/userVerification.service"; +import { EventType } from "jslib-common/enums/eventType"; +import { PolicyType } from "jslib-common/enums/policyType"; + +@Directive() +export class ExportComponent implements OnInit { + @Output() onSaved = new EventEmitter(); + + formPromise: Promise; + disabledByPolicy = false; + + exportForm = this.formBuilder.group({ + format: ["json"], + secret: [""], + }); + + formatOptions = [ + { name: ".json", value: "json" }, + { name: ".csv", value: "csv" }, + { name: ".json (Encrypted)", value: "encrypted_json" }, + ]; + + constructor( + protected cryptoService: CryptoService, + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected exportService: ExportService, + protected eventService: EventService, + private policyService: PolicyService, + protected win: Window, + private logService: LogService, + private userVerificationService: UserVerificationService, + private formBuilder: FormBuilder + ) {} + + async ngOnInit() { + await this.checkExportDisabled(); + } + + async checkExportDisabled() { + this.disabledByPolicy = await this.policyService.policyAppliesToUser( + PolicyType.DisablePersonalVaultExport + ); + if (this.disabledByPolicy) { + this.exportForm.disable(); + } + } + + get encryptedFormat() { + return this.format === "encrypted_json"; + } + + async submit() { + if (this.disabledByPolicy) { + this.platformUtilsService.showToast( + "error", + null, + this.i18nService.t("personalVaultExportPolicyInEffect") + ); + return; + } + + const acceptedWarning = await this.warningDialog(); + if (!acceptedWarning) { + return; + } + + const secret = this.exportForm.get("secret").value; + try { + await this.userVerificationService.verifyUser(secret); + } catch (e) { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), e.message); + return; + } + + try { + this.formPromise = this.getExportData(); + const data = await this.formPromise; + this.downloadFile(data); + this.saved(); + await this.collectEvent(); + this.exportForm.get("secret").setValue(""); + } catch (e) { + this.logService.error(e); + } + } + + async warningDialog() { + if (this.encryptedFormat) { + return await this.platformUtilsService.showDialog( + "

" + + this.i18nService.t("encExportKeyWarningDesc") + + "

" + + this.i18nService.t("encExportAccountWarningDesc"), + this.i18nService.t("confirmVaultExport"), + this.i18nService.t("exportVault"), + this.i18nService.t("cancel"), + "warning", + true + ); + } else { + return await this.platformUtilsService.showDialog( + this.i18nService.t("exportWarningDesc"), + this.i18nService.t("confirmVaultExport"), + this.i18nService.t("exportVault"), + this.i18nService.t("cancel"), + "warning" + ); + } + } + + protected saved() { + this.onSaved.emit(); + } + + protected getExportData() { + return this.exportService.getExport(this.format); + } + + protected getFileName(prefix?: string) { + let extension = this.format; + if (this.format === "encrypted_json") { + if (prefix == null) { + prefix = "encrypted"; + } else { + prefix = "encrypted_" + prefix; + } + extension = "json"; + } + return this.exportService.getFileName(prefix, extension); + } + + protected async collectEvent(): Promise { + await this.eventService.collect(EventType.User_ClientExportedVault); + } + + get format() { + return this.exportForm.get("format").value; + } + + private downloadFile(csv: string): void { + const fileName = this.getFileName(); + this.platformUtilsService.saveFile(this.win, csv, { type: "text/plain" }, fileName); + } +} diff --git a/libs/angular/src/components/folder-add-edit.component.ts b/libs/angular/src/components/folder-add-edit.component.ts new file mode 100644 index 0000000000..ef1fa11158 --- /dev/null +++ b/libs/angular/src/components/folder-add-edit.component.ts @@ -0,0 +1,96 @@ +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; + +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { FolderView } from "jslib-common/models/view/folderView"; + +@Directive() +export class FolderAddEditComponent implements OnInit { + @Input() folderId: string; + @Output() onSavedFolder = new EventEmitter(); + @Output() onDeletedFolder = new EventEmitter(); + + editMode = false; + folder: FolderView = new FolderView(); + title: string; + formPromise: Promise; + deletePromise: Promise; + + constructor( + protected folderService: FolderService, + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + private logService: LogService + ) {} + + async ngOnInit() { + await this.init(); + } + + async submit(): Promise { + if (this.folder.name == null || this.folder.name === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("nameRequired") + ); + return false; + } + + try { + const folder = await this.folderService.encrypt(this.folder); + this.formPromise = this.folderService.saveWithServer(folder); + await this.formPromise; + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t(this.editMode ? "editedFolder" : "addedFolder") + ); + this.onSavedFolder.emit(this.folder); + return true; + } catch (e) { + this.logService.error(e); + } + + return false; + } + + async delete(): Promise { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("deleteFolderConfirmation"), + this.i18nService.t("deleteFolder"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + this.deletePromise = this.folderService.deleteWithServer(this.folder.id); + await this.deletePromise; + this.platformUtilsService.showToast("success", null, this.i18nService.t("deletedFolder")); + this.onDeletedFolder.emit(this.folder); + } catch (e) { + this.logService.error(e); + } + + return true; + } + + protected async init() { + this.editMode = this.folderId != null; + + if (this.editMode) { + this.editMode = true; + this.title = this.i18nService.t("editFolder"); + const folder = await this.folderService.get(this.folderId); + this.folder = await folder.decrypt(); + } else { + this.title = this.i18nService.t("addFolder"); + } + } +} diff --git a/libs/angular/src/components/generator.component.ts b/libs/angular/src/components/generator.component.ts new file mode 100644 index 0000000000..9ef891099e --- /dev/null +++ b/libs/angular/src/components/generator.component.ts @@ -0,0 +1,240 @@ +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { UsernameGenerationService } from "jslib-common/abstractions/usernameGeneration.service"; +import { PasswordGeneratorPolicyOptions } from "jslib-common/models/domain/passwordGeneratorPolicyOptions"; + +@Directive() +export class GeneratorComponent implements OnInit { + @Input() comingFromAddEdit = false; + @Input() type: string; + @Output() onSelected = new EventEmitter(); + + usernameGeneratingPromise: Promise; + typeOptions: any[]; + passTypeOptions: any[]; + usernameTypeOptions: any[]; + subaddressOptions: any[]; + catchallOptions: any[]; + forwardOptions: any[]; + usernameOptions: any = {}; + passwordOptions: any = {}; + username = "-"; + password = "-"; + showOptions = false; + avoidAmbiguous = false; + enforcedPasswordPolicyOptions: PasswordGeneratorPolicyOptions; + usernameWebsite: string = null; + + constructor( + protected passwordGenerationService: PasswordGenerationService, + protected usernameGenerationService: UsernameGenerationService, + protected platformUtilsService: PlatformUtilsService, + protected stateService: StateService, + protected i18nService: I18nService, + protected logService: LogService, + protected route: ActivatedRoute, + private win: Window + ) { + this.typeOptions = [ + { name: i18nService.t("password"), value: "password" }, + { name: i18nService.t("username"), value: "username" }, + ]; + this.passTypeOptions = [ + { name: i18nService.t("password"), value: "password" }, + { name: i18nService.t("passphrase"), value: "passphrase" }, + ]; + this.usernameTypeOptions = [ + { + name: i18nService.t("plusAddressedEmail"), + value: "subaddress", + desc: i18nService.t("plusAddressedEmailDesc"), + }, + { + name: i18nService.t("catchallEmail"), + value: "catchall", + desc: i18nService.t("catchallEmailDesc"), + }, + { + name: i18nService.t("forwardedEmail"), + value: "forwarded", + desc: i18nService.t("forwardedEmailDesc"), + }, + { name: i18nService.t("randomWord"), value: "word" }, + ]; + this.subaddressOptions = [{ name: i18nService.t("random"), value: "random" }]; + this.catchallOptions = [{ name: i18nService.t("random"), value: "random" }]; + this.forwardOptions = [ + { name: "SimpleLogin", value: "simplelogin" }, + { name: "AnonAddy", value: "anonaddy" }, + { name: "Firefox Relay", value: "firefoxrelay" }, + // { name: "FastMail", value: "fastmail" }, + ]; + } + + async ngOnInit() { + this.route.queryParams.pipe(first()).subscribe(async (qParams) => { + const passwordOptionsResponse = await this.passwordGenerationService.getOptions(); + this.passwordOptions = passwordOptionsResponse[0]; + this.enforcedPasswordPolicyOptions = passwordOptionsResponse[1]; + this.avoidAmbiguous = !this.passwordOptions.ambiguous; + this.passwordOptions.type = + this.passwordOptions.type === "passphrase" ? "passphrase" : "password"; + + this.usernameOptions = await this.usernameGenerationService.getOptions(); + if (this.usernameOptions.type == null) { + this.usernameOptions.type = "word"; + } + if ( + this.usernameOptions.subaddressEmail == null || + this.usernameOptions.subaddressEmail === "" + ) { + this.usernameOptions.subaddressEmail = await this.stateService.getEmail(); + } + if (this.usernameWebsite == null) { + this.usernameOptions.subaddressType = this.usernameOptions.catchallType = "random"; + } else { + this.usernameOptions.website = this.usernameWebsite; + const websiteOption = { name: this.i18nService.t("websiteName"), value: "website-name" }; + this.subaddressOptions.push(websiteOption); + this.catchallOptions.push(websiteOption); + } + + if (this.type !== "username" && this.type !== "password") { + if (qParams.type === "username" || qParams.type === "password") { + this.type = qParams.type; + } else { + const generatorOptions = await this.stateService.getGeneratorOptions(); + this.type = generatorOptions?.type ?? "password"; + } + } + if (this.regenerateWithoutButtonPress()) { + await this.regenerate(); + } + }); + } + + async typeChanged() { + await this.stateService.setGeneratorOptions({ type: this.type }); + if (this.regenerateWithoutButtonPress()) { + await this.regenerate(); + } + } + + async regenerate() { + if (this.type === "password") { + await this.regeneratePassword(); + } else if (this.type === "username") { + await this.regenerateUsername(); + } + } + + async sliderChanged() { + this.savePasswordOptions(false); + await this.passwordGenerationService.addHistory(this.password); + } + + async sliderInput() { + this.normalizePasswordOptions(); + this.password = await this.passwordGenerationService.generatePassword(this.passwordOptions); + } + + async savePasswordOptions(regenerate = true) { + this.normalizePasswordOptions(); + await this.passwordGenerationService.saveOptions(this.passwordOptions); + + if (regenerate && this.regenerateWithoutButtonPress()) { + await this.regeneratePassword(); + } + } + + async saveUsernameOptions(regenerate = true) { + await this.usernameGenerationService.saveOptions(this.usernameOptions); + if (this.usernameOptions.type === "forwarded") { + this.username = "-"; + } + if (regenerate && this.regenerateWithoutButtonPress()) { + await this.regenerateUsername(); + } + } + + async regeneratePassword() { + this.password = await this.passwordGenerationService.generatePassword(this.passwordOptions); + await this.passwordGenerationService.addHistory(this.password); + } + + regenerateUsername() { + return this.generateUsername(); + } + + async generateUsername() { + try { + this.usernameGeneratingPromise = this.usernameGenerationService.generateUsername( + this.usernameOptions + ); + this.username = await this.usernameGeneratingPromise; + if (this.username === "" || this.username === null) { + this.username = "-"; + } + } catch (e) { + this.logService.error(e); + } + } + + copy() { + const password = this.type === "password"; + const copyOptions = this.win != null ? { window: this.win } : null; + this.platformUtilsService.copyToClipboard( + password ? this.password : this.username, + copyOptions + ); + this.platformUtilsService.showToast( + "info", + null, + this.i18nService.t("valueCopied", this.i18nService.t(password ? "password" : "username")) + ); + } + + select() { + this.onSelected.emit(this.type === "password" ? this.password : this.username); + } + + toggleOptions() { + this.showOptions = !this.showOptions; + } + + regenerateWithoutButtonPress() { + return this.type !== "username" || this.usernameOptions.type !== "forwarded"; + } + + private normalizePasswordOptions() { + // Application level normalize options depedent on class variables + this.passwordOptions.ambiguous = !this.avoidAmbiguous; + + if ( + !this.passwordOptions.uppercase && + !this.passwordOptions.lowercase && + !this.passwordOptions.number && + !this.passwordOptions.special + ) { + this.passwordOptions.lowercase = true; + if (this.win != null) { + const lowercase = this.win.document.querySelector("#lowercase") as HTMLInputElement; + if (lowercase) { + lowercase.checked = true; + } + } + } + + this.passwordGenerationService.normalizeOptions( + this.passwordOptions, + this.enforcedPasswordPolicyOptions + ); + } +} diff --git a/libs/angular/src/components/hint.component.ts b/libs/angular/src/components/hint.component.ts new file mode 100644 index 0000000000..6ee007e7df --- /dev/null +++ b/libs/angular/src/components/hint.component.ts @@ -0,0 +1,55 @@ +import { Router } from "@angular/router"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PasswordHintRequest } from "jslib-common/models/request/passwordHintRequest"; + +export class HintComponent { + email = ""; + formPromise: Promise; + + protected successRoute = "login"; + protected onSuccessfulSubmit: () => void; + + constructor( + protected router: Router, + protected i18nService: I18nService, + protected apiService: ApiService, + protected platformUtilsService: PlatformUtilsService, + private logService: LogService + ) {} + + async submit() { + if (this.email == null || this.email === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("emailRequired") + ); + return; + } + if (this.email.indexOf("@") === -1) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("invalidEmail") + ); + return; + } + + try { + this.formPromise = this.apiService.postPasswordHint(new PasswordHintRequest(this.email)); + await this.formPromise; + this.platformUtilsService.showToast("success", null, this.i18nService.t("masterPassSent")); + if (this.onSuccessfulSubmit != null) { + this.onSuccessfulSubmit(); + } else if (this.router != null) { + this.router.navigate([this.successRoute]); + } + } catch (e) { + this.logService.error(e); + } + } +} diff --git a/libs/angular/src/components/icon.component.html b/libs/angular/src/components/icon.component.html new file mode 100644 index 0000000000..27182fbb8a --- /dev/null +++ b/libs/angular/src/components/icon.component.html @@ -0,0 +1,11 @@ +

diff --git a/libs/angular/src/components/icon.component.ts b/libs/angular/src/components/icon.component.ts new file mode 100644 index 0000000000..c6a6c8a0b5 --- /dev/null +++ b/libs/angular/src/components/icon.component.ts @@ -0,0 +1,113 @@ +import { Component, Input, OnChanges } from "@angular/core"; + +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { Utils } from "jslib-common/misc/utils"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +/** + * Provides a mapping from supported card brands to + * the filenames of icon that should be present in images/cards folder of clients. + */ +const cardIcons: Record = { + Visa: "card-visa", + Mastercard: "card-mastercard", + Amex: "card-amex", + Discover: "card-discover", + "Diners Club": "card-diners-club", + JCB: "card-jcb", + Maestro: "card-maestro", + UnionPay: "card-union-pay", + RuPay: "card-ru-pay", +}; + +@Component({ + selector: "app-vault-icon", + templateUrl: "icon.component.html", +}) +export class IconComponent implements OnChanges { + @Input() cipher: CipherView; + icon: string; + image: string; + fallbackImage: string; + imageEnabled: boolean; + + private iconsUrl: string; + + constructor(environmentService: EnvironmentService, private stateService: StateService) { + this.iconsUrl = environmentService.getIconsUrl(); + } + + async ngOnChanges() { + // Components may be re-used when using cdk-virtual-scroll. Which puts the component in a weird state, + // to avoid this we reset all state variables. + this.image = null; + this.fallbackImage = null; + this.imageEnabled = !(await this.stateService.getDisableFavicon()); + this.load(); + } + + protected load() { + switch (this.cipher.type) { + case CipherType.Login: + this.icon = "bwi-globe"; + this.setLoginIcon(); + break; + case CipherType.SecureNote: + this.icon = "bwi-sticky-note"; + break; + case CipherType.Card: + this.icon = "bwi-credit-card"; + this.setCardIcon(); + break; + case CipherType.Identity: + this.icon = "bwi-id-card"; + break; + default: + break; + } + } + + private setLoginIcon() { + if (this.cipher.login.uri) { + let hostnameUri = this.cipher.login.uri; + let isWebsite = false; + + if (hostnameUri.indexOf("androidapp://") === 0) { + this.icon = "bwi-android"; + this.image = null; + } else if (hostnameUri.indexOf("iosapp://") === 0) { + this.icon = "bwi-apple"; + this.image = null; + } else if ( + this.imageEnabled && + hostnameUri.indexOf("://") === -1 && + hostnameUri.indexOf(".") > -1 + ) { + hostnameUri = "http://" + hostnameUri; + isWebsite = true; + } else if (this.imageEnabled) { + isWebsite = hostnameUri.indexOf("http") === 0 && hostnameUri.indexOf(".") > -1; + } + + if (this.imageEnabled && isWebsite) { + try { + this.image = this.iconsUrl + "/" + Utils.getHostname(hostnameUri) + "/icon.png"; + this.fallbackImage = "images/bwi-globe.png"; + } catch (e) { + // Ignore error since the fallback icon will be shown if image is null. + } + } + } else { + this.image = null; + } + } + + private setCardIcon() { + const brand = this.cipher.card.brand; + if (this.imageEnabled && brand in cardIcons) { + this.icon = "credit-card-icon " + cardIcons[brand]; + } + } +} diff --git a/libs/angular/src/components/lock.component.ts b/libs/angular/src/components/lock.component.ts new file mode 100644 index 0000000000..2411f5884b --- /dev/null +++ b/libs/angular/src/components/lock.component.ts @@ -0,0 +1,277 @@ +import { Directive, NgZone, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { take } from "rxjs/operators"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { VaultTimeoutService } from "jslib-common/abstractions/vaultTimeout.service"; +import { HashPurpose } from "jslib-common/enums/hashPurpose"; +import { KeySuffixOptions } from "jslib-common/enums/keySuffixOptions"; +import { Utils } from "jslib-common/misc/utils"; +import { EncString } from "jslib-common/models/domain/encString"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { SecretVerificationRequest } from "jslib-common/models/request/secretVerificationRequest"; + +@Directive() +export class LockComponent implements OnInit { + masterPassword = ""; + pin = ""; + showPassword = false; + email: string; + pinLock = false; + webVaultHostname = ""; + formPromise: Promise; + supportsBiometric: boolean; + biometricLock: boolean; + biometricText: string; + hideInput: boolean; + + protected successRoute = "vault"; + protected onSuccessfulSubmit: () => Promise; + + private invalidPinAttempts = 0; + private pinSet: [boolean, boolean]; + + constructor( + protected router: Router, + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected messagingService: MessagingService, + protected cryptoService: CryptoService, + protected vaultTimeoutService: VaultTimeoutService, + protected environmentService: EnvironmentService, + protected stateService: StateService, + protected apiService: ApiService, + protected logService: LogService, + private keyConnectorService: KeyConnectorService, + protected ngZone: NgZone + ) {} + + async ngOnInit() { + // Load the first and observe updates + await this.load(); + this.stateService.activeAccount.subscribe(async () => { + await this.load(); + }); + } + + async submit() { + if (this.pinLock && (this.pin == null || this.pin === "")) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("pinRequired") + ); + return; + } + if (!this.pinLock && (this.masterPassword == null || this.masterPassword === "")) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassRequired") + ); + return; + } + + const kdf = await this.stateService.getKdfType(); + const kdfIterations = await this.stateService.getKdfIterations(); + + if (this.pinLock) { + let failed = true; + try { + if (this.pinSet[0]) { + const key = await this.cryptoService.makeKeyFromPin( + this.pin, + this.email, + kdf, + kdfIterations, + await this.stateService.getDecryptedPinProtected() + ); + const encKey = await this.cryptoService.getEncKey(key); + const protectedPin = await this.stateService.getProtectedPin(); + const decPin = await this.cryptoService.decryptToUtf8( + new EncString(protectedPin), + encKey + ); + failed = decPin !== this.pin; + if (!failed) { + await this.setKeyAndContinue(key); + } + } else { + const key = await this.cryptoService.makeKeyFromPin( + this.pin, + this.email, + kdf, + kdfIterations + ); + failed = false; + await this.setKeyAndContinue(key); + } + } catch { + failed = true; + } + + if (failed) { + this.invalidPinAttempts++; + if (this.invalidPinAttempts >= 5) { + this.messagingService.send("logout"); + return; + } + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("invalidPin") + ); + } + } else { + const key = await this.cryptoService.makeKey( + this.masterPassword, + this.email, + kdf, + kdfIterations + ); + const storedKeyHash = await this.cryptoService.getKeyHash(); + + let passwordValid = false; + + if (storedKeyHash != null) { + passwordValid = await this.cryptoService.compareAndUpdateKeyHash(this.masterPassword, key); + } else { + const request = new SecretVerificationRequest(); + const serverKeyHash = await this.cryptoService.hashPassword( + this.masterPassword, + key, + HashPurpose.ServerAuthorization + ); + request.masterPasswordHash = serverKeyHash; + try { + this.formPromise = this.apiService.postAccountVerifyPassword(request); + await this.formPromise; + passwordValid = true; + const localKeyHash = await this.cryptoService.hashPassword( + this.masterPassword, + key, + HashPurpose.LocalAuthorization + ); + await this.cryptoService.setKeyHash(localKeyHash); + } catch (e) { + this.logService.error(e); + } + } + + if (passwordValid) { + if (this.pinSet[0]) { + const protectedPin = await this.stateService.getProtectedPin(); + const encKey = await this.cryptoService.getEncKey(key); + const decPin = await this.cryptoService.decryptToUtf8( + new EncString(protectedPin), + encKey + ); + const pinKey = await this.cryptoService.makePinKey( + decPin, + this.email, + kdf, + kdfIterations + ); + await this.stateService.setDecryptedPinProtected( + await this.cryptoService.encrypt(key.key, pinKey) + ); + } + await this.setKeyAndContinue(key); + } else { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("invalidMasterPassword") + ); + } + } + } + + async logOut() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("logOutConfirmation"), + this.i18nService.t("logOut"), + this.i18nService.t("logOut"), + this.i18nService.t("cancel") + ); + if (confirmed) { + this.messagingService.send("logout"); + } + } + + async unlockBiometric(): Promise { + if (!this.biometricLock) { + return; + } + + const success = (await this.cryptoService.getKey(KeySuffixOptions.Biometric)) != null; + + if (success) { + await this.doContinue(); + } + + return success; + } + + togglePassword() { + this.showPassword = !this.showPassword; + const input = document.getElementById(this.pinLock ? "pin" : "masterPassword"); + if (this.ngZone.isStable) { + input.focus(); + } else { + this.ngZone.onStable.pipe(take(1)).subscribe(() => input.focus()); + } + } + + private async setKeyAndContinue(key: SymmetricCryptoKey) { + await this.cryptoService.setKey(key); + await this.doContinue(); + } + + private async doContinue() { + await this.stateService.setBiometricLocked(false); + await this.stateService.setEverBeenUnlocked(true); + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); + this.messagingService.send("unlocked"); + if (this.onSuccessfulSubmit != null) { + await this.onSuccessfulSubmit(); + } else if (this.router != null) { + this.router.navigate([this.successRoute]); + } + } + + private async load() { + this.pinSet = await this.vaultTimeoutService.isPinLockSet(); + this.pinLock = + (this.pinSet[0] && (await this.stateService.getDecryptedPinProtected()) != null) || + this.pinSet[1]; + this.supportsBiometric = await this.platformUtilsService.supportsBiometric(); + this.biometricLock = + (await this.vaultTimeoutService.isBiometricLockSet()) && + ((await this.cryptoService.hasKeyStored(KeySuffixOptions.Biometric)) || + !this.platformUtilsService.supportsSecureStorage()); + this.biometricText = await this.stateService.getBiometricText(); + this.email = await this.stateService.getEmail(); + const usesKeyConnector = await this.keyConnectorService.getUsesKeyConnector(); + this.hideInput = usesKeyConnector && !this.pinLock; + + // Users with key connector and without biometric or pin has no MP to unlock using + if (usesKeyConnector && !(this.biometricLock || this.pinLock)) { + await this.vaultTimeoutService.logOut(); + } + + const webVaultUrl = this.environmentService.getWebVaultUrl(); + const vaultUrl = + webVaultUrl === "https://vault.bitwarden.com" ? "https://bitwarden.com" : webVaultUrl; + this.webVaultHostname = Utils.getHostname(vaultUrl); + } +} diff --git a/libs/angular/src/components/login.component.ts b/libs/angular/src/components/login.component.ts new file mode 100644 index 0000000000..5d3f7cfff8 --- /dev/null +++ b/libs/angular/src/components/login.component.ts @@ -0,0 +1,192 @@ +import { Directive, Input, NgZone, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { take } from "rxjs/operators"; + +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; +import { AuthResult } from "jslib-common/models/domain/authResult"; +import { PasswordLogInCredentials } from "jslib-common/models/domain/logInCredentials"; + +import { CaptchaProtectedComponent } from "./captchaProtected.component"; + +@Directive() +export class LoginComponent extends CaptchaProtectedComponent implements OnInit { + @Input() email = ""; + @Input() rememberEmail = true; + + masterPassword = ""; + showPassword = false; + formPromise: Promise; + onSuccessfulLogin: () => Promise; + onSuccessfulLoginNavigate: () => Promise; + onSuccessfulLoginTwoFactorNavigate: () => Promise; + onSuccessfulLoginForceResetNavigate: () => Promise; + + protected twoFactorRoute = "2fa"; + protected successRoute = "vault"; + protected forcePasswordResetRoute = "update-temp-password"; + protected alwaysRememberEmail = false; + + constructor( + protected authService: AuthService, + protected router: Router, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + protected stateService: StateService, + environmentService: EnvironmentService, + protected passwordGenerationService: PasswordGenerationService, + protected cryptoFunctionService: CryptoFunctionService, + protected logService: LogService, + protected ngZone: NgZone + ) { + super(environmentService, i18nService, platformUtilsService); + } + + async ngOnInit() { + if (this.email == null || this.email === "") { + this.email = await this.stateService.getRememberedEmail(); + if (this.email == null) { + this.email = ""; + } + } + if (!this.alwaysRememberEmail) { + this.rememberEmail = (await this.stateService.getRememberedEmail()) != null; + } + if (Utils.isBrowser && !Utils.isNode) { + this.focusInput(); + } + } + + async submit() { + await this.setupCaptcha(); + + if (this.email == null || this.email === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("emailRequired") + ); + return; + } + if (this.email.indexOf("@") === -1) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("invalidEmail") + ); + return; + } + if (this.masterPassword == null || this.masterPassword === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassRequired") + ); + return; + } + + try { + const credentials = new PasswordLogInCredentials( + this.email, + this.masterPassword, + this.captchaToken, + null + ); + this.formPromise = this.authService.logIn(credentials); + const response = await this.formPromise; + if (this.rememberEmail || this.alwaysRememberEmail) { + await this.stateService.setRememberedEmail(this.email); + } else { + await this.stateService.setRememberedEmail(null); + } + if (this.handleCaptchaRequired(response)) { + return; + } else if (response.requiresTwoFactor) { + if (this.onSuccessfulLoginTwoFactorNavigate != null) { + this.onSuccessfulLoginTwoFactorNavigate(); + } else { + this.router.navigate([this.twoFactorRoute]); + } + } else if (response.forcePasswordReset) { + if (this.onSuccessfulLoginForceResetNavigate != null) { + this.onSuccessfulLoginForceResetNavigate(); + } else { + this.router.navigate([this.forcePasswordResetRoute]); + } + } else { + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); + if (this.onSuccessfulLogin != null) { + this.onSuccessfulLogin(); + } + if (this.onSuccessfulLoginNavigate != null) { + this.onSuccessfulLoginNavigate(); + } else { + this.router.navigate([this.successRoute]); + } + } + } catch (e) { + this.logService.error(e); + } + } + + togglePassword() { + this.showPassword = !this.showPassword; + if (this.ngZone.isStable) { + document.getElementById("masterPassword").focus(); + } else { + this.ngZone.onStable + .pipe(take(1)) + .subscribe(() => document.getElementById("masterPassword").focus()); + } + } + + async launchSsoBrowser(clientId: string, ssoRedirectUri: string) { + // Generate necessary sso params + const passwordOptions: any = { + type: "password", + length: 64, + uppercase: true, + lowercase: true, + numbers: true, + special: false, + }; + const state = await this.passwordGenerationService.generatePassword(passwordOptions); + const ssoCodeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions); + const codeVerifierHash = await this.cryptoFunctionService.hash(ssoCodeVerifier, "sha256"); + const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); + + // Save sso params + await this.stateService.setSsoState(state); + await this.stateService.setSsoCodeVerifier(ssoCodeVerifier); + + // Build URI + const webUrl = this.environmentService.getWebVaultUrl(); + + // Launch browser + this.platformUtilsService.launchUri( + webUrl + + "/#/sso?clientId=" + + clientId + + "&redirectUri=" + + encodeURIComponent(ssoRedirectUri) + + "&state=" + + state + + "&codeChallenge=" + + codeChallenge + ); + } + + protected focusInput() { + document + .getElementById(this.email == null || this.email === "" ? "email" : "masterPassword") + .focus(); + } +} diff --git a/libs/angular/src/components/modal/dynamic-modal.component.ts b/libs/angular/src/components/modal/dynamic-modal.component.ts new file mode 100644 index 0000000000..46ad38c033 --- /dev/null +++ b/libs/angular/src/components/modal/dynamic-modal.component.ts @@ -0,0 +1,79 @@ +import { ConfigurableFocusTrap, ConfigurableFocusTrapFactory } from "@angular/cdk/a11y"; +import { + AfterViewInit, + ChangeDetectorRef, + Component, + ComponentRef, + ElementRef, + OnDestroy, + Type, + ViewChild, + ViewContainerRef, +} from "@angular/core"; + +import { ModalService } from "../../services/modal.service"; + +import { ModalRef } from "./modal.ref"; + +@Component({ + selector: "app-modal", + template: "", +}) +export class DynamicModalComponent implements AfterViewInit, OnDestroy { + componentRef: ComponentRef; + + @ViewChild("modalContent", { read: ViewContainerRef, static: true }) + modalContentRef: ViewContainerRef; + + childComponentType: Type; + setComponentParameters: (component: any) => void; + + private focusTrap: ConfigurableFocusTrap; + + constructor( + private modalService: ModalService, + private cd: ChangeDetectorRef, + private el: ElementRef, + private focusTrapFactory: ConfigurableFocusTrapFactory, + public modalRef: ModalRef + ) {} + + ngAfterViewInit() { + this.loadChildComponent(this.childComponentType); + if (this.setComponentParameters != null) { + this.setComponentParameters(this.componentRef.instance); + } + this.cd.detectChanges(); + + this.modalRef.created(this.el.nativeElement); + this.focusTrap = this.focusTrapFactory.create( + this.el.nativeElement.querySelector(".modal-dialog") + ); + if (this.el.nativeElement.querySelector("[appAutoFocus]") == null) { + this.focusTrap.focusFirstTabbableElementWhenReady(); + } + } + + loadChildComponent(componentType: Type) { + const componentFactory = this.modalService.resolveComponentFactory(componentType); + + this.modalContentRef.clear(); + this.componentRef = this.modalContentRef.createComponent(componentFactory); + } + + ngOnDestroy() { + if (this.componentRef) { + this.componentRef.destroy(); + } + this.focusTrap.destroy(); + } + + close() { + this.modalRef.close(); + } + + getFocus() { + const autoFocusEl = this.el.nativeElement.querySelector("[appAutoFocus]") as HTMLElement; + autoFocusEl?.focus(); + } +} diff --git a/libs/angular/src/components/modal/modal-injector.ts b/libs/angular/src/components/modal/modal-injector.ts new file mode 100644 index 0000000000..188e5584c5 --- /dev/null +++ b/libs/angular/src/components/modal/modal-injector.ts @@ -0,0 +1,10 @@ +import { InjectFlags, InjectionToken, Injector, Type } from "@angular/core"; + +export class ModalInjector implements Injector { + constructor(private _parentInjector: Injector, private _additionalTokens: WeakMap) {} + + get(token: Type | InjectionToken, notFoundValue?: T, flags?: InjectFlags): T; + get(token: any, notFoundValue?: any, flags?: any) { + return this._additionalTokens.get(token) ?? this._parentInjector.get(token, notFoundValue); + } +} diff --git a/libs/angular/src/components/modal/modal.ref.ts b/libs/angular/src/components/modal/modal.ref.ts new file mode 100644 index 0000000000..a80acebb69 --- /dev/null +++ b/libs/angular/src/components/modal/modal.ref.ts @@ -0,0 +1,50 @@ +import { Observable, Subject } from "rxjs"; +import { first } from "rxjs/operators"; + +export class ModalRef { + onCreated: Observable; // Modal added to the DOM. + onClose: Observable; // Initiated close. + onClosed: Observable; // Modal was closed (Remove element from DOM) + onShow: Observable; // Start showing modal + onShown: Observable; // Modal is fully visible + + private readonly _onCreated = new Subject(); + private readonly _onClose = new Subject(); + private readonly _onClosed = new Subject(); + private readonly _onShow = new Subject(); + private readonly _onShown = new Subject(); + private lastResult: any; + + constructor() { + this.onCreated = this._onCreated.asObservable(); + this.onClose = this._onClose.asObservable(); + this.onClosed = this._onClosed.asObservable(); + this.onShow = this._onShow.asObservable(); + this.onShown = this._onShow.asObservable(); + } + + show() { + this._onShow.next(); + } + + shown() { + this._onShown.next(); + } + + close(result?: any) { + this.lastResult = result; + this._onClose.next(result); + } + + closed() { + this._onClosed.next(this.lastResult); + } + + created(el: HTMLElement) { + this._onCreated.next(el); + } + + onClosedPromise(): Promise { + return this.onClosed.pipe(first()).toPromise(); + } +} diff --git a/libs/angular/src/components/password-generator-history.component.ts b/libs/angular/src/components/password-generator-history.component.ts new file mode 100644 index 0000000000..15e6c7e435 --- /dev/null +++ b/libs/angular/src/components/password-generator-history.component.ts @@ -0,0 +1,37 @@ +import { Directive, OnInit } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { GeneratedPasswordHistory } from "jslib-common/models/domain/generatedPasswordHistory"; + +@Directive() +export class PasswordGeneratorHistoryComponent implements OnInit { + history: GeneratedPasswordHistory[] = []; + + constructor( + protected passwordGenerationService: PasswordGenerationService, + protected platformUtilsService: PlatformUtilsService, + protected i18nService: I18nService, + private win: Window + ) {} + + async ngOnInit() { + this.history = await this.passwordGenerationService.getHistory(); + } + + clear() { + this.history = []; + this.passwordGenerationService.clear(); + } + + copy(password: string) { + const copyOptions = this.win != null ? { window: this.win } : null; + this.platformUtilsService.copyToClipboard(password, copyOptions); + this.platformUtilsService.showToast( + "info", + null, + this.i18nService.t("valueCopied", this.i18nService.t("password")) + ); + } +} diff --git a/libs/angular/src/components/password-history.component.ts b/libs/angular/src/components/password-history.component.ts new file mode 100644 index 0000000000..94eb2f7cc3 --- /dev/null +++ b/libs/angular/src/components/password-history.component.ts @@ -0,0 +1,39 @@ +import { Directive, OnInit } from "@angular/core"; + +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PasswordHistoryView } from "jslib-common/models/view/passwordHistoryView"; + +@Directive() +export class PasswordHistoryComponent implements OnInit { + cipherId: string; + history: PasswordHistoryView[] = []; + + constructor( + protected cipherService: CipherService, + protected platformUtilsService: PlatformUtilsService, + protected i18nService: I18nService, + private win: Window + ) {} + + async ngOnInit() { + await this.init(); + } + + copy(password: string) { + const copyOptions = this.win != null ? { window: this.win } : null; + this.platformUtilsService.copyToClipboard(password, copyOptions); + this.platformUtilsService.showToast( + "info", + null, + this.i18nService.t("valueCopied", this.i18nService.t("password")) + ); + } + + protected async init() { + const cipher = await this.cipherService.get(this.cipherId); + const decCipher = await cipher.decrypt(); + this.history = decCipher.passwordHistory == null ? [] : decCipher.passwordHistory; + } +} diff --git a/libs/angular/src/components/password-reprompt.component.ts b/libs/angular/src/components/password-reprompt.component.ts new file mode 100644 index 0000000000..03b4080277 --- /dev/null +++ b/libs/angular/src/components/password-reprompt.component.ts @@ -0,0 +1,41 @@ +import { Directive } from "@angular/core"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +import { ModalRef } from "./modal/modal.ref"; + +/** + * Used to verify the user's Master Password for the "Master Password Re-prompt" feature only. + * See UserVerificationComponent for any other situation where you need to verify the user's identity. + */ +@Directive() +export class PasswordRepromptComponent { + showPassword = false; + masterPassword = ""; + + constructor( + private modalRef: ModalRef, + private cryptoService: CryptoService, + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService + ) {} + + togglePassword() { + this.showPassword = !this.showPassword; + } + + async submit() { + if (!(await this.cryptoService.compareAndUpdateKeyHash(this.masterPassword, null))) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("invalidMasterPassword") + ); + return; + } + + this.modalRef.close(true); + } +} diff --git a/libs/angular/src/components/premium.component.ts b/libs/angular/src/components/premium.component.ts new file mode 100644 index 0000000000..efad4986b8 --- /dev/null +++ b/libs/angular/src/components/premium.component.ts @@ -0,0 +1,61 @@ +import { Directive, OnInit } from "@angular/core"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +@Directive() +export class PremiumComponent implements OnInit { + isPremium = false; + price = 10; + refreshPromise: Promise; + + constructor( + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected apiService: ApiService, + private logService: LogService, + protected stateService: StateService + ) {} + + async ngOnInit() { + this.isPremium = await this.stateService.getCanAccessPremium(); + } + + async refresh() { + try { + this.refreshPromise = this.apiService.refreshIdentityToken(); + await this.refreshPromise; + this.platformUtilsService.showToast("success", null, this.i18nService.t("refreshComplete")); + this.isPremium = await this.stateService.getCanAccessPremium(); + } catch (e) { + this.logService.error(e); + } + } + + async purchase() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("premiumPurchaseAlert"), + this.i18nService.t("premiumPurchase"), + this.i18nService.t("yes"), + this.i18nService.t("cancel") + ); + if (confirmed) { + this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/?premium=purchase"); + } + } + + async manage() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("premiumManageAlert"), + this.i18nService.t("premiumManage"), + this.i18nService.t("yes"), + this.i18nService.t("cancel") + ); + if (confirmed) { + this.platformUtilsService.launchUri("https://vault.bitwarden.com/#/?premium=manage"); + } + } +} diff --git a/libs/angular/src/components/register.component.ts b/libs/angular/src/components/register.component.ts new file mode 100644 index 0000000000..d4b99e17a2 --- /dev/null +++ b/libs/angular/src/components/register.component.ts @@ -0,0 +1,248 @@ +import { Directive, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { DEFAULT_KDF_ITERATIONS, DEFAULT_KDF_TYPE } from "jslib-common/enums/kdfType"; +import { KeysRequest } from "jslib-common/models/request/keysRequest"; +import { ReferenceEventRequest } from "jslib-common/models/request/referenceEventRequest"; +import { RegisterRequest } from "jslib-common/models/request/registerRequest"; + +import { CaptchaProtectedComponent } from "./captchaProtected.component"; + +@Directive() +export class RegisterComponent extends CaptchaProtectedComponent implements OnInit { + name = ""; + email = ""; + masterPassword = ""; + confirmMasterPassword = ""; + hint = ""; + showPassword = false; + formPromise: Promise; + masterPasswordScore: number; + referenceData: ReferenceEventRequest; + showTerms = true; + acceptPolicies = false; + + protected successRoute = "login"; + private masterPasswordStrengthTimeout: any; + + constructor( + protected authService: AuthService, + protected router: Router, + i18nService: I18nService, + protected cryptoService: CryptoService, + protected apiService: ApiService, + protected stateService: StateService, + platformUtilsService: PlatformUtilsService, + protected passwordGenerationService: PasswordGenerationService, + environmentService: EnvironmentService, + protected logService: LogService + ) { + super(environmentService, i18nService, platformUtilsService); + this.showTerms = !platformUtilsService.isSelfHost(); + } + + async ngOnInit() { + this.setupCaptcha(); + } + + get masterPasswordScoreWidth() { + return this.masterPasswordScore == null ? 0 : (this.masterPasswordScore + 1) * 20; + } + + get masterPasswordScoreColor() { + switch (this.masterPasswordScore) { + case 4: + return "success"; + case 3: + return "primary"; + case 2: + return "warning"; + default: + return "danger"; + } + } + + get masterPasswordScoreText() { + switch (this.masterPasswordScore) { + case 4: + return this.i18nService.t("strong"); + case 3: + return this.i18nService.t("good"); + case 2: + return this.i18nService.t("weak"); + default: + return this.masterPasswordScore != null ? this.i18nService.t("weak") : null; + } + } + + async submit() { + if (!this.acceptPolicies && this.showTerms) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("acceptPoliciesError") + ); + return; + } + + if (this.email == null || this.email === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("emailRequired") + ); + return; + } + if (this.email.indexOf("@") === -1) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("invalidEmail") + ); + return; + } + if (this.masterPassword == null || this.masterPassword === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassRequired") + ); + return; + } + if (this.masterPassword.length < 8) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassLength") + ); + return; + } + if (this.masterPassword !== this.confirmMasterPassword) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassDoesntMatch") + ); + return; + } + + const strengthResult = this.passwordGenerationService.passwordStrength( + this.masterPassword, + this.getPasswordStrengthUserInput() + ); + if (strengthResult != null && strengthResult.score < 3) { + const result = await this.platformUtilsService.showDialog( + this.i18nService.t("weakMasterPasswordDesc"), + this.i18nService.t("weakMasterPassword"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!result) { + return; + } + } + + if (this.hint === this.masterPassword) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("hintEqualsPassword") + ); + return; + } + + this.name = this.name === "" ? null : this.name; + this.email = this.email.trim().toLowerCase(); + const kdf = DEFAULT_KDF_TYPE; + const kdfIterations = DEFAULT_KDF_ITERATIONS; + const key = await this.cryptoService.makeKey( + this.masterPassword, + this.email, + kdf, + kdfIterations + ); + const encKey = await this.cryptoService.makeEncKey(key); + const hashedPassword = await this.cryptoService.hashPassword(this.masterPassword, key); + const keys = await this.cryptoService.makeKeyPair(encKey[0]); + const request = new RegisterRequest( + this.email, + this.name, + hashedPassword, + this.hint, + encKey[1].encryptedString, + kdf, + kdfIterations, + this.referenceData, + this.captchaToken + ); + request.keys = new KeysRequest(keys[0], keys[1].encryptedString); + const orgInvite = await this.stateService.getOrganizationInvitation(); + if (orgInvite != null && orgInvite.token != null && orgInvite.organizationUserId != null) { + request.token = orgInvite.token; + request.organizationUserId = orgInvite.organizationUserId; + } + + try { + this.formPromise = this.apiService.postRegister(request); + try { + await this.formPromise; + } catch (e) { + if (this.handleCaptchaRequired(e)) { + return; + } else { + throw e; + } + } + this.platformUtilsService.showToast("success", null, this.i18nService.t("newAccountCreated")); + this.router.navigate([this.successRoute], { queryParams: { email: this.email } }); + } catch (e) { + this.logService.error(e); + } + } + + togglePassword(confirmField: boolean) { + this.showPassword = !this.showPassword; + document.getElementById(confirmField ? "masterPasswordRetype" : "masterPassword").focus(); + } + + updatePasswordStrength() { + if (this.masterPasswordStrengthTimeout != null) { + clearTimeout(this.masterPasswordStrengthTimeout); + } + this.masterPasswordStrengthTimeout = setTimeout(() => { + const strengthResult = this.passwordGenerationService.passwordStrength( + this.masterPassword, + this.getPasswordStrengthUserInput() + ); + this.masterPasswordScore = strengthResult == null ? null : strengthResult.score; + }, 300); + } + + private getPasswordStrengthUserInput() { + let userInput: string[] = []; + const atPosition = this.email.indexOf("@"); + if (atPosition > -1) { + userInput = userInput.concat( + this.email + .substr(0, atPosition) + .trim() + .toLowerCase() + .split(/[^A-Za-z0-9]/) + ); + } + if (this.name != null && this.name !== "") { + userInput = userInput.concat(this.name.trim().toLowerCase().split(" ")); + } + return userInput; + } +} diff --git a/libs/angular/src/components/remove-password.component.ts b/libs/angular/src/components/remove-password.component.ts new file mode 100644 index 0000000000..bce481e50c --- /dev/null +++ b/libs/angular/src/components/remove-password.component.ts @@ -0,0 +1,82 @@ +import { Directive, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { Organization } from "jslib-common/models/domain/organization"; + +@Directive() +export class RemovePasswordComponent implements OnInit { + actionPromise: Promise; + continuing = false; + leaving = false; + + loading = true; + organization: Organization; + email: string; + + constructor( + private router: Router, + private stateService: StateService, + private apiService: ApiService, + private syncService: SyncService, + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService, + private keyConnectorService: KeyConnectorService + ) {} + + async ngOnInit() { + this.organization = await this.keyConnectorService.getManagingOrganization(); + this.email = await this.stateService.getEmail(); + await this.syncService.fullSync(false); + this.loading = false; + } + + async convert() { + this.continuing = true; + this.actionPromise = this.keyConnectorService.migrateUser(); + + try { + await this.actionPromise; + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("removedMasterPassword") + ); + await this.keyConnectorService.removeConvertAccountRequired(); + this.router.navigate([""]); + } catch (e) { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), e.message); + } + } + + async leave() { + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("leaveOrganizationConfirmation"), + this.organization.name, + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + this.leaving = true; + this.actionPromise = this.apiService.postLeaveOrganization(this.organization.id).then(() => { + return this.syncService.fullSync(true); + }); + await this.actionPromise; + this.platformUtilsService.showToast("success", null, this.i18nService.t("leftOrganization")); + await this.keyConnectorService.removeConvertAccountRequired(); + this.router.navigate([""]); + } catch (e) { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), e); + } + } +} diff --git a/libs/angular/src/components/send/add-edit.component.ts b/libs/angular/src/components/send/add-edit.component.ts new file mode 100644 index 0000000000..382adf354d --- /dev/null +++ b/libs/angular/src/components/send/add-edit.component.ts @@ -0,0 +1,293 @@ +import { DatePipe } from "@angular/common"; +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; + +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { PolicyType } from "jslib-common/enums/policyType"; +import { SendType } from "jslib-common/enums/sendType"; +import { EncArrayBuffer } from "jslib-common/models/domain/encArrayBuffer"; +import { Send } from "jslib-common/models/domain/send"; +import { SendFileView } from "jslib-common/models/view/sendFileView"; +import { SendTextView } from "jslib-common/models/view/sendTextView"; +import { SendView } from "jslib-common/models/view/sendView"; + +@Directive() +export class AddEditComponent implements OnInit { + @Input() sendId: string; + @Input() type: SendType; + + @Output() onSavedSend = new EventEmitter(); + @Output() onDeletedSend = new EventEmitter(); + @Output() onCancelled = new EventEmitter(); + + copyLink = false; + disableSend = false; + disableHideEmail = false; + send: SendView; + deletionDate: string; + expirationDate: string; + hasPassword: boolean; + password: string; + showPassword = false; + formPromise: Promise; + deletePromise: Promise; + sendType = SendType; + typeOptions: any[]; + canAccessPremium = true; + emailVerified = true; + alertShown = false; + showOptions = false; + + private sendLinkBaseUrl: string; + + constructor( + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected environmentService: EnvironmentService, + protected datePipe: DatePipe, + protected sendService: SendService, + protected messagingService: MessagingService, + protected policyService: PolicyService, + private logService: LogService, + protected stateService: StateService + ) { + this.typeOptions = [ + { name: i18nService.t("sendTypeFile"), value: SendType.File }, + { name: i18nService.t("sendTypeText"), value: SendType.Text }, + ]; + this.sendLinkBaseUrl = this.environmentService.getSendUrl(); + } + + get link(): string { + if (this.send.id != null && this.send.accessId != null) { + return this.sendLinkBaseUrl + this.send.accessId + "/" + this.send.urlB64Key; + } + return null; + } + + get isSafari() { + return this.platformUtilsService.isSafari(); + } + + get isDateTimeLocalSupported(): boolean { + return !(this.platformUtilsService.isFirefox() || this.platformUtilsService.isSafari()); + } + + async ngOnInit() { + await this.load(); + } + + get editMode(): boolean { + return this.sendId != null; + } + + get title(): string { + return this.i18nService.t(this.editMode ? "editSend" : "createSend"); + } + + setDates(event: { deletionDate: string; expirationDate: string }) { + this.deletionDate = event.deletionDate; + this.expirationDate = event.expirationDate; + } + + async load() { + this.disableSend = await this.policyService.policyAppliesToUser(PolicyType.DisableSend); + this.disableHideEmail = await this.policyService.policyAppliesToUser( + PolicyType.SendOptions, + (p) => p.data.disableHideEmail + ); + + this.canAccessPremium = await this.stateService.getCanAccessPremium(); + this.emailVerified = await this.stateService.getEmailVerified(); + if (!this.canAccessPremium || !this.emailVerified) { + this.type = SendType.Text; + } + + if (this.send == null) { + if (this.editMode) { + const send = await this.loadSend(); + this.send = await send.decrypt(); + } else { + this.send = new SendView(); + this.send.type = this.type == null ? SendType.File : this.type; + this.send.file = new SendFileView(); + this.send.text = new SendTextView(); + this.send.deletionDate = new Date(); + this.send.deletionDate.setDate(this.send.deletionDate.getDate() + 7); + } + } + + this.hasPassword = this.send.password != null && this.send.password.trim() !== ""; + } + + async submit(): Promise { + if (this.disableSend) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("sendDisabledWarning") + ); + return false; + } + + if (this.send.name == null || this.send.name === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("nameRequired") + ); + return false; + } + + let file: File = null; + if (this.send.type === SendType.File && !this.editMode) { + const fileEl = document.getElementById("file") as HTMLInputElement; + const files = fileEl.files; + if (files == null || files.length === 0) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("selectFile") + ); + return; + } + + file = files[0]; + if (files[0].size > 524288000) { + // 500 MB + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("maxFileSize") + ); + return; + } + } + + if (this.password != null && this.password.trim() === "") { + this.password = null; + } + + this.formPromise = this.encryptSend(file).then(async (encSend) => { + const uploadPromise = this.sendService.saveWithServer(encSend); + await uploadPromise; + if (this.send.id == null) { + this.send.id = encSend[0].id; + } + if (this.send.accessId == null) { + this.send.accessId = encSend[0].accessId; + } + this.onSavedSend.emit(this.send); + if (this.copyLink && this.link != null) { + const copySuccess = await this.copyLinkToClipboard(this.link); + if (copySuccess ?? true) { + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t(this.editMode ? "editedSend" : "createdSend") + ); + } else { + await this.platformUtilsService.showDialog( + this.i18nService.t(this.editMode ? "editedSend" : "createdSend"), + null, + this.i18nService.t("ok"), + null, + "success", + null + ); + await this.copyLinkToClipboard(this.link); + } + } + }); + try { + await this.formPromise; + return true; + } catch (e) { + this.logService.error(e); + } + return false; + } + + async copyLinkToClipboard(link: string): Promise { + return Promise.resolve(this.platformUtilsService.copyToClipboard(link)); + } + + async delete(): Promise { + if (this.deletePromise != null) { + return false; + } + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("deleteSendConfirmation"), + this.i18nService.t("deleteSend"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + this.deletePromise = this.sendService.deleteWithServer(this.send.id); + await this.deletePromise; + this.platformUtilsService.showToast("success", null, this.i18nService.t("deletedSend")); + await this.load(); + this.onDeletedSend.emit(this.send); + return true; + } catch (e) { + this.logService.error(e); + } + + return false; + } + + typeChanged() { + if (this.send.type === SendType.File && !this.alertShown) { + if (!this.canAccessPremium) { + this.alertShown = true; + this.messagingService.send("premiumRequired"); + } else if (!this.emailVerified) { + this.alertShown = true; + this.messagingService.send("emailVerificationRequired"); + } + } + } + + toggleOptions() { + this.showOptions = !this.showOptions; + } + + protected async loadSend(): Promise { + return this.sendService.get(this.sendId); + } + + protected async encryptSend(file: File): Promise<[Send, EncArrayBuffer]> { + const sendData = await this.sendService.encrypt(this.send, file, this.password, null); + + // Parse dates + try { + sendData[0].deletionDate = this.deletionDate == null ? null : new Date(this.deletionDate); + } catch { + sendData[0].deletionDate = null; + } + try { + sendData[0].expirationDate = + this.expirationDate == null ? null : new Date(this.expirationDate); + } catch { + sendData[0].expirationDate = null; + } + + return sendData; + } + + protected togglePasswordVisible() { + this.showPassword = !this.showPassword; + document.getElementById("password").focus(); + } +} diff --git a/libs/angular/src/components/send/efflux-dates.component.ts b/libs/angular/src/components/send/efflux-dates.component.ts new file mode 100644 index 0000000000..15aec8a0a9 --- /dev/null +++ b/libs/angular/src/components/send/efflux-dates.component.ts @@ -0,0 +1,356 @@ +import { DatePipe } from "@angular/common"; +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; +import { FormControl, FormGroup } from "@angular/forms"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +// Different BrowserPath = different controls. +enum BrowserPath { + // Native datetime-locale. + // We are happy. + Default = "default", + + // Native date and time inputs, but no datetime-locale. + // We use individual date and time inputs and create a datetime programatically on submit. + Firefox = "firefox", + + // No native date, time, or datetime-locale inputs. + // We use a polyfill for dates and a dropdown for times. + Safari = "safari", +} + +enum DateField { + DeletionDate = "deletion", + ExpriationDate = "expiration", +} + +// Value = hours +enum DatePreset { + OneHour = 1, + OneDay = 24, + TwoDays = 48, + ThreeDays = 72, + SevenDays = 168, + ThirtyDays = 720, + Custom = 0, + Never = null, +} + +// TimeOption is used for the dropdown implementation of custom times +// twelveHour = displayed time; twentyFourHour = time used in logic +interface TimeOption { + twelveHour: string; + twentyFourHour: string; +} + +@Directive() +export class EffluxDatesComponent implements OnInit { + @Input() readonly initialDeletionDate: Date; + @Input() readonly initialExpirationDate: Date; + @Input() readonly editMode: boolean; + @Input() readonly disabled: boolean; + + @Output() datesChanged = new EventEmitter<{ deletionDate: string; expirationDate: string }>(); + + get browserPath(): BrowserPath { + if (this.platformUtilsService.isFirefox()) { + return BrowserPath.Firefox; + } else if (this.platformUtilsService.isSafari()) { + return BrowserPath.Safari; + } + return BrowserPath.Default; + } + + datesForm = new FormGroup({ + selectedDeletionDatePreset: new FormControl(), + selectedExpirationDatePreset: new FormControl(), + defaultDeletionDateTime: new FormControl(), + defaultExpirationDateTime: new FormControl(), + fallbackDeletionDate: new FormControl(), + fallbackDeletionTime: new FormControl(), + fallbackExpirationDate: new FormControl(), + fallbackExpirationTime: new FormControl(), + }); + + deletionDatePresets: any[] = [ + { name: this.i18nService.t("oneHour"), value: DatePreset.OneHour }, + { name: this.i18nService.t("oneDay"), value: DatePreset.OneDay }, + { name: this.i18nService.t("days", "2"), value: DatePreset.TwoDays }, + { name: this.i18nService.t("days", "3"), value: DatePreset.ThreeDays }, + { name: this.i18nService.t("days", "7"), value: DatePreset.SevenDays }, + { name: this.i18nService.t("days", "30"), value: DatePreset.ThirtyDays }, + { name: this.i18nService.t("custom"), value: DatePreset.Custom }, + ]; + + expirationDatePresets: any[] = [ + { name: this.i18nService.t("never"), value: DatePreset.Never }, + ].concat([...this.deletionDatePresets]); + + get selectedDeletionDatePreset(): FormControl { + return this.datesForm.get("selectedDeletionDatePreset") as FormControl; + } + + get selectedExpirationDatePreset(): FormControl { + return this.datesForm.get("selectedExpirationDatePreset") as FormControl; + } + + get defaultDeletionDateTime(): FormControl { + return this.datesForm.get("defaultDeletionDateTime") as FormControl; + } + + get defaultExpirationDateTime(): FormControl { + return this.datesForm.get("defaultExpirationDateTime") as FormControl; + } + + get fallbackDeletionDate(): FormControl { + return this.datesForm.get("fallbackDeletionDate") as FormControl; + } + + get fallbackDeletionTime(): FormControl { + return this.datesForm.get("fallbackDeletionTime") as FormControl; + } + + get fallbackExpirationDate(): FormControl { + return this.datesForm.get("fallbackExpirationDate") as FormControl; + } + + get fallbackExpirationTime(): FormControl { + return this.datesForm.get("fallbackExpirationTime") as FormControl; + } + + // Should be able to call these at any time and compute a submitable value + get formattedDeletionDate(): string { + switch (this.selectedDeletionDatePreset.value as DatePreset) { + case DatePreset.Never: + this.selectedDeletionDatePreset.setValue(DatePreset.SevenDays); + return this.formattedDeletionDate; + case DatePreset.Custom: + switch (this.browserPath) { + case BrowserPath.Safari: + case BrowserPath.Firefox: + return this.fallbackDeletionDate.value + "T" + this.fallbackDeletionTime.value; + default: + return this.defaultDeletionDateTime.value; + } + default: { + const now = new Date(); + const miliseconds = now.setTime( + now.getTime() + (this.selectedDeletionDatePreset.value as number) * 60 * 60 * 1000 + ); + return new Date(miliseconds).toString(); + } + } + } + + get formattedExpirationDate(): string { + switch (this.selectedExpirationDatePreset.value as DatePreset) { + case DatePreset.Never: + return null; + case DatePreset.Custom: + switch (this.browserPath) { + case BrowserPath.Safari: + case BrowserPath.Firefox: + if ( + (!this.fallbackExpirationDate.value || !this.fallbackExpirationTime.value) && + this.editMode + ) { + return null; + } + return this.fallbackExpirationDate.value + "T" + this.fallbackExpirationTime.value; + default: + if (!this.defaultExpirationDateTime.value) { + return null; + } + return this.defaultExpirationDateTime.value; + } + default: { + const now = new Date(); + const miliseconds = now.setTime( + now.getTime() + (this.selectedExpirationDatePreset.value as number) * 60 * 60 * 1000 + ); + return new Date(miliseconds).toString(); + } + } + } + // + + get safariDeletionTimePresetOptions() { + return this.safariTimePresetOptions(DateField.DeletionDate); + } + + get safariExpirationTimePresetOptions() { + return this.safariTimePresetOptions(DateField.ExpriationDate); + } + + private get nextWeek(): Date { + const nextWeek = new Date(); + nextWeek.setDate(nextWeek.getDate() + 7); + return nextWeek; + } + + constructor( + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected datePipe: DatePipe + ) {} + + ngOnInit(): void { + this.setInitialFormValues(); + this.emitDates(); + this.datesForm.valueChanges.subscribe(() => { + this.emitDates(); + }); + } + + onDeletionDatePresetSelect(value: DatePreset) { + this.selectedDeletionDatePreset.setValue(value); + } + + clearExpiration() { + switch (this.browserPath) { + case BrowserPath.Safari: + case BrowserPath.Firefox: + this.fallbackExpirationDate.setValue(null); + this.fallbackExpirationTime.setValue(null); + break; + case BrowserPath.Default: + this.defaultExpirationDateTime.setValue(null); + break; + } + } + + protected emitDates() { + this.datesChanged.emit({ + deletionDate: this.formattedDeletionDate, + expirationDate: this.formattedExpirationDate, + }); + } + + protected setInitialFormValues() { + if (this.editMode) { + this.selectedDeletionDatePreset.setValue(DatePreset.Custom); + this.selectedExpirationDatePreset.setValue(DatePreset.Custom); + switch (this.browserPath) { + case BrowserPath.Safari: + case BrowserPath.Firefox: + this.fallbackDeletionDate.setValue(this.initialDeletionDate.toISOString().slice(0, 10)); + this.fallbackDeletionTime.setValue(this.initialDeletionDate.toTimeString().slice(0, 5)); + if (this.initialExpirationDate != null) { + this.fallbackExpirationDate.setValue( + this.initialExpirationDate.toISOString().slice(0, 10) + ); + this.fallbackExpirationTime.setValue( + this.initialExpirationDate.toTimeString().slice(0, 5) + ); + } + break; + case BrowserPath.Default: + if (this.initialExpirationDate) { + this.defaultExpirationDateTime.setValue( + this.datePipe.transform(new Date(this.initialExpirationDate), "yyyy-MM-ddTHH:mm") + ); + } + this.defaultDeletionDateTime.setValue( + this.datePipe.transform(new Date(this.initialDeletionDate), "yyyy-MM-ddTHH:mm") + ); + break; + } + } else { + this.selectedDeletionDatePreset.setValue(DatePreset.SevenDays); + this.selectedExpirationDatePreset.setValue(DatePreset.Never); + + switch (this.browserPath) { + case BrowserPath.Safari: + this.fallbackDeletionDate.setValue(this.nextWeek.toISOString().slice(0, 10)); + this.fallbackDeletionTime.setValue( + this.safariTimePresetOptions(DateField.DeletionDate)[1].twentyFourHour + ); + break; + default: + break; + } + } + } + + protected safariTimePresetOptions(field: DateField): TimeOption[] { + // init individual arrays for major sort groups + const noon: TimeOption[] = []; + const midnight: TimeOption[] = []; + const ams: TimeOption[] = []; + const pms: TimeOption[] = []; + + // determine minute skip (5 min, 10 min, 15 min, etc.) + const minuteIncrementer = 15; + + // loop through each hour on a 12 hour system + for (let h = 1; h <= 12; h++) { + // loop through each minute in the hour using the skip to incriment + for (let m = 0; m < 60; m += minuteIncrementer) { + // init the final strings that will be added to the lists + let hour = h.toString(); + let minutes = m.toString(); + + // add prepending 0s to single digit hours/minutes + if (h < 10) { + hour = "0" + hour; + } + if (m < 10) { + minutes = "0" + minutes; + } + + // build time strings and push to relevant sort groups + if (h === 12) { + const midnightOption: TimeOption = { + twelveHour: `${hour}:${minutes} AM`, + twentyFourHour: `00:${minutes}`, + }; + midnight.push(midnightOption); + + const noonOption: TimeOption = { + twelveHour: `${hour}:${minutes} PM`, + twentyFourHour: `${hour}:${minutes}`, + }; + noon.push(noonOption); + } else { + const amOption: TimeOption = { + twelveHour: `${hour}:${minutes} AM`, + twentyFourHour: `${hour}:${minutes}`, + }; + ams.push(amOption); + + const pmOption: TimeOption = { + twelveHour: `${hour}:${minutes} PM`, + twentyFourHour: `${h + 12}:${minutes}`, + }; + pms.push(pmOption); + } + } + } + + // bring all the arrays together in the right order + const validTimes = [...midnight, ...ams, ...noon, ...pms]; + + // determine if an unsupported value already exists on the send & add that to the top of the option list + // example: if the Send was created with a different client + if (field === DateField.ExpriationDate && this.initialExpirationDate != null && this.editMode) { + const previousValue: TimeOption = { + twelveHour: this.datePipe.transform(this.initialExpirationDate, "hh:mm a"), + twentyFourHour: this.datePipe.transform(this.initialExpirationDate, "HH:mm"), + }; + return [previousValue, { twelveHour: null, twentyFourHour: null }, ...validTimes]; + } else if ( + field === DateField.DeletionDate && + this.initialDeletionDate != null && + this.editMode + ) { + const previousValue: TimeOption = { + twelveHour: this.datePipe.transform(this.initialDeletionDate, "hh:mm a"), + twentyFourHour: this.datePipe.transform(this.initialDeletionDate, "HH:mm"), + }; + return [previousValue, ...validTimes]; + } else { + return [{ twelveHour: null, twentyFourHour: null }, ...validTimes]; + } + } +} diff --git a/libs/angular/src/components/send/send.component.ts b/libs/angular/src/components/send/send.component.ts new file mode 100644 index 0000000000..63831dcbd6 --- /dev/null +++ b/libs/angular/src/components/send/send.component.ts @@ -0,0 +1,210 @@ +import { Directive, NgZone, OnInit } from "@angular/core"; + +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SendService } from "jslib-common/abstractions/send.service"; +import { PolicyType } from "jslib-common/enums/policyType"; +import { SendType } from "jslib-common/enums/sendType"; +import { SendView } from "jslib-common/models/view/sendView"; + +@Directive() +export class SendComponent implements OnInit { + disableSend = false; + sendType = SendType; + loaded = false; + loading = true; + refreshing = false; + expired = false; + type: SendType = null; + sends: SendView[] = []; + filteredSends: SendView[] = []; + searchText: string; + selectedType: SendType; + selectedAll: boolean; + searchPlaceholder: string; + filter: (cipher: SendView) => boolean; + searchPending = false; + hasSearched = false; // search() function called - returns true if text qualifies for search + + actionPromise: any; + onSuccessfulRemovePassword: () => Promise; + onSuccessfulDelete: () => Promise; + onSuccessfulLoad: () => Promise; + + private searchTimeout: any; + + constructor( + protected sendService: SendService, + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected environmentService: EnvironmentService, + protected ngZone: NgZone, + protected searchService: SearchService, + protected policyService: PolicyService, + private logService: LogService + ) {} + + async ngOnInit() { + this.disableSend = await this.policyService.policyAppliesToUser(PolicyType.DisableSend); + } + + async load(filter: (send: SendView) => boolean = null) { + this.loading = true; + const sends = await this.sendService.getAllDecrypted(); + this.sends = sends; + if (this.onSuccessfulLoad != null) { + await this.onSuccessfulLoad(); + } else { + // Default action + this.selectAll(); + } + this.loading = false; + this.loaded = true; + } + + async reload(filter: (send: SendView) => boolean = null) { + this.loaded = false; + this.sends = []; + await this.load(filter); + } + + async refresh() { + try { + this.refreshing = true; + await this.reload(this.filter); + } finally { + this.refreshing = false; + } + } + + async applyFilter(filter: (send: SendView) => boolean = null) { + this.filter = filter; + await this.search(null); + } + + async search(timeout: number = null) { + this.searchPending = false; + if (this.searchTimeout != null) { + clearTimeout(this.searchTimeout); + } + if (timeout == null) { + this.hasSearched = this.searchService.isSearchable(this.searchText); + this.filteredSends = this.sends.filter((s) => this.filter == null || this.filter(s)); + this.applyTextSearch(); + return; + } + this.searchPending = true; + this.searchTimeout = setTimeout(async () => { + this.hasSearched = this.searchService.isSearchable(this.searchText); + this.filteredSends = this.sends.filter((s) => this.filter == null || this.filter(s)); + this.applyTextSearch(); + this.searchPending = false; + }, timeout); + } + + async removePassword(s: SendView): Promise { + if (this.actionPromise != null || s.password == null) { + return; + } + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("removePasswordConfirmation"), + this.i18nService.t("removePassword"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + this.actionPromise = this.sendService.removePasswordWithServer(s.id); + await this.actionPromise; + if (this.onSuccessfulRemovePassword != null) { + this.onSuccessfulRemovePassword(); + } else { + // Default actions + this.platformUtilsService.showToast("success", null, this.i18nService.t("removedPassword")); + await this.load(); + } + } catch (e) { + this.logService.error(e); + } + this.actionPromise = null; + } + + async delete(s: SendView): Promise { + if (this.actionPromise != null) { + return false; + } + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("deleteSendConfirmation"), + this.i18nService.t("deleteSend"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + this.actionPromise = this.sendService.deleteWithServer(s.id); + await this.actionPromise; + + if (this.onSuccessfulDelete != null) { + this.onSuccessfulDelete(); + } else { + // Default actions + this.platformUtilsService.showToast("success", null, this.i18nService.t("deletedSend")); + await this.refresh(); + } + } catch (e) { + this.logService.error(e); + } + this.actionPromise = null; + return true; + } + + copy(s: SendView) { + const sendLinkBaseUrl = this.environmentService.getSendUrl(); + const link = sendLinkBaseUrl + s.accessId + "/" + s.urlB64Key; + this.platformUtilsService.copyToClipboard(link); + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("valueCopied", this.i18nService.t("sendLink")) + ); + } + + searchTextChanged() { + this.search(200); + } + + selectAll() { + this.clearSelections(); + this.selectedAll = true; + this.applyFilter(null); + } + + selectType(type: SendType) { + this.clearSelections(); + this.selectedType = type; + this.applyFilter((s) => s.type === type); + } + + clearSelections() { + this.selectedAll = false; + this.selectedType = null; + } + + private applyTextSearch() { + if (this.searchText != null) { + this.filteredSends = this.searchService.searchSends(this.filteredSends, this.searchText); + } + } +} diff --git a/libs/angular/src/components/set-password.component.ts b/libs/angular/src/components/set-password.component.ts new file mode 100644 index 0000000000..4b996b5667 --- /dev/null +++ b/libs/angular/src/components/set-password.component.ts @@ -0,0 +1,180 @@ +import { Directive } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { HashPurpose } from "jslib-common/enums/hashPurpose"; +import { DEFAULT_KDF_ITERATIONS, DEFAULT_KDF_TYPE } from "jslib-common/enums/kdfType"; +import { Utils } from "jslib-common/misc/utils"; +import { EncString } from "jslib-common/models/domain/encString"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { KeysRequest } from "jslib-common/models/request/keysRequest"; +import { OrganizationUserResetPasswordEnrollmentRequest } from "jslib-common/models/request/organizationUserResetPasswordEnrollmentRequest"; +import { SetPasswordRequest } from "jslib-common/models/request/setPasswordRequest"; + +import { ChangePasswordComponent as BaseChangePasswordComponent } from "./change-password.component"; + +@Directive() +export class SetPasswordComponent extends BaseChangePasswordComponent { + syncLoading = true; + showPassword = false; + hint = ""; + identifier: string = null; + orgId: string; + resetPasswordAutoEnroll = false; + + onSuccessfulChangePassword: () => Promise; + successRoute = "vault"; + + constructor( + i18nService: I18nService, + cryptoService: CryptoService, + messagingService: MessagingService, + passwordGenerationService: PasswordGenerationService, + platformUtilsService: PlatformUtilsService, + policyService: PolicyService, + protected router: Router, + private apiService: ApiService, + private syncService: SyncService, + private route: ActivatedRoute, + stateService: StateService + ) { + super( + i18nService, + cryptoService, + messagingService, + passwordGenerationService, + platformUtilsService, + policyService, + stateService + ); + } + + async ngOnInit() { + await this.syncService.fullSync(true); + this.syncLoading = false; + + this.route.queryParams.pipe(first()).subscribe(async (qParams) => { + if (qParams.identifier != null) { + this.identifier = qParams.identifier; + } + }); + + // Automatic Enrollment Detection + if (this.identifier != null) { + try { + const response = await this.apiService.getOrganizationAutoEnrollStatus(this.identifier); + this.orgId = response.id; + this.resetPasswordAutoEnroll = response.resetPasswordEnabled; + this.enforcedPolicyOptions = + await this.policyService.getMasterPasswordPoliciesForInvitedUsers(this.orgId); + } catch { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + } + } + + super.ngOnInit(); + } + + async setupSubmitActions() { + this.kdf = DEFAULT_KDF_TYPE; + this.kdfIterations = DEFAULT_KDF_ITERATIONS; + return true; + } + + async performSubmitActions( + masterPasswordHash: string, + key: SymmetricCryptoKey, + encKey: [SymmetricCryptoKey, EncString] + ) { + const keys = await this.cryptoService.makeKeyPair(encKey[0]); + const request = new SetPasswordRequest( + masterPasswordHash, + encKey[1].encryptedString, + this.hint, + this.kdf, + this.kdfIterations, + this.identifier, + new KeysRequest(keys[0], keys[1].encryptedString) + ); + try { + if (this.resetPasswordAutoEnroll) { + this.formPromise = this.apiService + .setPassword(request) + .then(async () => { + await this.onSetPasswordSuccess(key, encKey, keys); + return this.apiService.getOrganizationKeys(this.orgId); + }) + .then(async (response) => { + if (response == null) { + throw new Error(this.i18nService.t("resetPasswordOrgKeysError")); + } + const userId = await this.stateService.getUserId(); + const publicKey = Utils.fromB64ToArray(response.publicKey); + + // RSA Encrypt user's encKey.key with organization public key + const userEncKey = await this.cryptoService.getEncKey(); + const encryptedKey = await this.cryptoService.rsaEncrypt( + userEncKey.key, + publicKey.buffer + ); + + const resetRequest = new OrganizationUserResetPasswordEnrollmentRequest(); + resetRequest.resetPasswordKey = encryptedKey.encryptedString; + + return this.apiService.putOrganizationUserResetPasswordEnrollment( + this.orgId, + userId, + resetRequest + ); + }); + } else { + this.formPromise = this.apiService.setPassword(request).then(async () => { + await this.onSetPasswordSuccess(key, encKey, keys); + }); + } + + await this.formPromise; + + if (this.onSuccessfulChangePassword != null) { + this.onSuccessfulChangePassword(); + } else { + this.router.navigate([this.successRoute]); + } + } catch { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + } + } + + togglePassword(confirmField: boolean) { + this.showPassword = !this.showPassword; + document.getElementById(confirmField ? "masterPasswordRetype" : "masterPassword").focus(); + } + + private async onSetPasswordSuccess( + key: SymmetricCryptoKey, + encKey: [SymmetricCryptoKey, EncString], + keys: [string, EncString] + ) { + await this.stateService.setKdfType(this.kdf); + await this.stateService.setKdfIterations(this.kdfIterations); + await this.cryptoService.setKey(key); + await this.cryptoService.setEncKey(encKey[1].encryptedString); + await this.cryptoService.setEncPrivateKey(keys[1].encryptedString); + + const localKeyHash = await this.cryptoService.hashPassword( + this.masterPassword, + key, + HashPurpose.LocalAuthorization + ); + await this.cryptoService.setKeyHash(localKeyHash); + } +} diff --git a/libs/angular/src/components/set-pin.component.ts b/libs/angular/src/components/set-pin.component.ts new file mode 100644 index 0000000000..dd10e99d24 --- /dev/null +++ b/libs/angular/src/components/set-pin.component.ts @@ -0,0 +1,54 @@ +import { Directive, OnInit } from "@angular/core"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; + +import { ModalRef } from "./modal/modal.ref"; + +@Directive() +export class SetPinComponent implements OnInit { + pin = ""; + showPin = false; + masterPassOnRestart = true; + showMasterPassOnRestart = true; + + constructor( + private modalRef: ModalRef, + private cryptoService: CryptoService, + private keyConnectorService: KeyConnectorService, + private stateService: StateService + ) {} + + async ngOnInit() { + this.showMasterPassOnRestart = this.masterPassOnRestart = + !(await this.keyConnectorService.getUsesKeyConnector()); + } + + toggleVisibility() { + this.showPin = !this.showPin; + } + + async submit() { + if (Utils.isNullOrWhitespace(this.pin)) { + this.modalRef.close(false); + } + + const kdf = await this.stateService.getKdfType(); + const kdfIterations = await this.stateService.getKdfIterations(); + const email = await this.stateService.getEmail(); + const pinKey = await this.cryptoService.makePinKey(this.pin, email, kdf, kdfIterations); + const key = await this.cryptoService.getKey(); + const pinProtectedKey = await this.cryptoService.encrypt(key.key, pinKey); + if (this.masterPassOnRestart) { + const encPin = await this.cryptoService.encrypt(this.pin); + await this.stateService.setProtectedPin(encPin.encryptedString); + await this.stateService.setDecryptedPinProtected(pinProtectedKey); + } else { + await this.stateService.setEncryptedPinProtected(pinProtectedKey.encryptedString); + } + + this.modalRef.close(true); + } +} diff --git a/libs/angular/src/components/settings/vault-timeout-input.component.ts b/libs/angular/src/components/settings/vault-timeout-input.component.ts new file mode 100644 index 0000000000..eb6057f275 --- /dev/null +++ b/libs/angular/src/components/settings/vault-timeout-input.component.ts @@ -0,0 +1,156 @@ +import { Directive, Input, OnInit } from "@angular/core"; +import { + AbstractControl, + ControlValueAccessor, + FormBuilder, + ValidationErrors, + Validator, +} from "@angular/forms"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { PolicyType } from "jslib-common/enums/policyType"; +import { Policy } from "jslib-common/models/domain/policy"; + +@Directive() +export class VaultTimeoutInputComponent implements ControlValueAccessor, Validator, OnInit { + get showCustom() { + return this.form.get("vaultTimeout").value === VaultTimeoutInputComponent.CUSTOM_VALUE; + } + + get exceedsMinimumTimout(): boolean { + return ( + !this.showCustom || this.customTimeInMinutes() > VaultTimeoutInputComponent.MIN_CUSTOM_MINUTES + ); + } + + static CUSTOM_VALUE = -100; + static MIN_CUSTOM_MINUTES = 0; + + form = this.formBuilder.group({ + vaultTimeout: [null], + custom: this.formBuilder.group({ + hours: [null], + minutes: [null], + }), + }); + + @Input() vaultTimeouts: { name: string; value: number }[]; + vaultTimeoutPolicy: Policy; + vaultTimeoutPolicyHours: number; + vaultTimeoutPolicyMinutes: number; + + private onChange: (vaultTimeout: number) => void; + private validatorChange: () => void; + + constructor( + private formBuilder: FormBuilder, + private policyService: PolicyService, + private i18nService: I18nService + ) {} + + async ngOnInit() { + if (await this.policyService.policyAppliesToUser(PolicyType.MaximumVaultTimeout)) { + const vaultTimeoutPolicy = await this.policyService.getAll(PolicyType.MaximumVaultTimeout); + + this.vaultTimeoutPolicy = vaultTimeoutPolicy[0]; + this.vaultTimeoutPolicyHours = Math.floor(this.vaultTimeoutPolicy.data.minutes / 60); + this.vaultTimeoutPolicyMinutes = this.vaultTimeoutPolicy.data.minutes % 60; + + this.vaultTimeouts = this.vaultTimeouts.filter( + (t) => + t.value <= this.vaultTimeoutPolicy.data.minutes && + (t.value > 0 || t.value === VaultTimeoutInputComponent.CUSTOM_VALUE) && + t.value != null + ); + this.validatorChange(); + } + + this.form.valueChanges.subscribe(async (value) => { + this.onChange(this.getVaultTimeout(value)); + }); + + // Assign the previous value to the custom fields + this.form.get("vaultTimeout").valueChanges.subscribe((value) => { + if (value !== VaultTimeoutInputComponent.CUSTOM_VALUE) { + return; + } + + const current = Math.max(this.form.value.vaultTimeout, 0); + this.form.patchValue({ + custom: { + hours: Math.floor(current / 60), + minutes: current % 60, + }, + }); + }); + } + + ngOnChanges() { + this.vaultTimeouts.push({ + name: this.i18nService.t("custom"), + value: VaultTimeoutInputComponent.CUSTOM_VALUE, + }); + } + + getVaultTimeout(value: any) { + if (value.vaultTimeout !== VaultTimeoutInputComponent.CUSTOM_VALUE) { + return value.vaultTimeout; + } + + return value.custom.hours * 60 + value.custom.minutes; + } + + writeValue(value: number): void { + if (value == null) { + return; + } + + if (this.vaultTimeouts.every((p) => p.value !== value)) { + this.form.setValue({ + vaultTimeout: VaultTimeoutInputComponent.CUSTOM_VALUE, + custom: { + hours: Math.floor(value / 60), + minutes: value % 60, + }, + }); + return; + } + + this.form.patchValue({ + vaultTimeout: value, + }); + } + + registerOnChange(onChange: any): void { + this.onChange = onChange; + } + + registerOnTouched(onTouched: any): void { + // Empty + } + + setDisabledState?(isDisabled: boolean): void { + // Empty + } + + validate(control: AbstractControl): ValidationErrors { + if (this.vaultTimeoutPolicy && this.vaultTimeoutPolicy?.data?.minutes < control.value) { + return { policyError: true }; + } + + if (!this.exceedsMinimumTimout) { + return { minTimeoutError: true }; + } + + return null; + } + + registerOnValidatorChange(fn: () => void): void { + this.validatorChange = fn; + } + + private customTimeInMinutes() { + return this.form.get("custom.hours")?.value * 60 + this.form.get("custom.minutes")?.value; + } +} diff --git a/libs/angular/src/components/share.component.ts b/libs/angular/src/components/share.component.ts new file mode 100644 index 0000000000..0b1b3577df --- /dev/null +++ b/libs/angular/src/components/share.component.ts @@ -0,0 +1,116 @@ +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; + +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { OrganizationUserStatusType } from "jslib-common/enums/organizationUserStatusType"; +import { Utils } from "jslib-common/misc/utils"; +import { Organization } from "jslib-common/models/domain/organization"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { CollectionView } from "jslib-common/models/view/collectionView"; + +@Directive() +export class ShareComponent implements OnInit { + @Input() cipherId: string; + @Input() organizationId: string; + @Output() onSharedCipher = new EventEmitter(); + + formPromise: Promise; + cipher: CipherView; + collections: CollectionView[] = []; + organizations: Organization[] = []; + + protected writeableCollections: CollectionView[] = []; + + constructor( + protected collectionService: CollectionService, + protected platformUtilsService: PlatformUtilsService, + protected i18nService: I18nService, + protected cipherService: CipherService, + private logService: LogService, + protected organizationService: OrganizationService + ) {} + + async ngOnInit() { + await this.load(); + } + + async load() { + const allCollections = await this.collectionService.getAllDecrypted(); + this.writeableCollections = allCollections.map((c) => c).filter((c) => !c.readOnly); + const orgs = await this.organizationService.getAll(); + this.organizations = orgs + .sort(Utils.getSortFunction(this.i18nService, "name")) + .filter((o) => o.enabled && o.status === OrganizationUserStatusType.Confirmed); + + const cipherDomain = await this.cipherService.get(this.cipherId); + this.cipher = await cipherDomain.decrypt(); + if (this.organizationId == null && this.organizations.length > 0) { + this.organizationId = this.organizations[0].id; + } + this.filterCollections(); + } + + filterCollections() { + this.writeableCollections.forEach((c) => ((c as any).checked = false)); + if (this.organizationId == null || this.writeableCollections.length === 0) { + this.collections = []; + } else { + this.collections = this.writeableCollections.filter( + (c) => c.organizationId === this.organizationId + ); + } + } + + async submit(): Promise { + const selectedCollectionIds = this.collections + .filter((c) => !!(c as any).checked) + .map((c) => c.id); + if (selectedCollectionIds.length === 0) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("selectOneCollection") + ); + return; + } + + const cipherDomain = await this.cipherService.get(this.cipherId); + const cipherView = await cipherDomain.decrypt(); + const orgName = + this.organizations.find((o) => o.id === this.organizationId)?.name ?? + this.i18nService.t("organization"); + + try { + this.formPromise = this.cipherService + .shareWithServer(cipherView, this.organizationId, selectedCollectionIds) + .then(async () => { + this.onSharedCipher.emit(); + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("movedItemToOrg", cipherView.name, orgName) + ); + }); + await this.formPromise; + return true; + } catch (e) { + this.logService.error(e); + } + return false; + } + + get canSave() { + if (this.collections != null) { + for (let i = 0; i < this.collections.length; i++) { + if ((this.collections[i] as any).checked) { + return true; + } + } + } + return false; + } +} diff --git a/libs/angular/src/components/sso.component.ts b/libs/angular/src/components/sso.component.ts new file mode 100644 index 0000000000..9732ce967e --- /dev/null +++ b/libs/angular/src/components/sso.component.ts @@ -0,0 +1,260 @@ +import { Directive } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { first } from "rxjs/operators"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; +import { AuthResult } from "jslib-common/models/domain/authResult"; +import { SsoLogInCredentials } from "jslib-common/models/domain/logInCredentials"; +import { SsoPreValidateResponse } from "jslib-common/models/response/ssoPreValidateResponse"; + +@Directive() +export class SsoComponent { + identifier: string; + loggingIn = false; + + formPromise: Promise; + initiateSsoFormPromise: Promise; + onSuccessfulLogin: () => Promise; + onSuccessfulLoginNavigate: () => Promise; + onSuccessfulLoginTwoFactorNavigate: () => Promise; + onSuccessfulLoginChangePasswordNavigate: () => Promise; + onSuccessfulLoginForceResetNavigate: () => Promise; + + protected twoFactorRoute = "2fa"; + protected successRoute = "lock"; + protected changePasswordRoute = "set-password"; + protected forcePasswordResetRoute = "update-temp-password"; + protected clientId: string; + protected redirectUri: string; + protected state: string; + protected codeChallenge: string; + + constructor( + protected authService: AuthService, + protected router: Router, + protected i18nService: I18nService, + protected route: ActivatedRoute, + protected stateService: StateService, + protected platformUtilsService: PlatformUtilsService, + protected apiService: ApiService, + protected cryptoFunctionService: CryptoFunctionService, + protected environmentService: EnvironmentService, + protected passwordGenerationService: PasswordGenerationService, + protected logService: LogService + ) {} + + async ngOnInit() { + this.route.queryParams.pipe(first()).subscribe(async (qParams) => { + if (qParams.code != null && qParams.state != null) { + const codeVerifier = await this.stateService.getSsoCodeVerifier(); + const state = await this.stateService.getSsoState(); + await this.stateService.setSsoCodeVerifier(null); + await this.stateService.setSsoState(null); + if ( + qParams.code != null && + codeVerifier != null && + state != null && + this.checkState(state, qParams.state) + ) { + await this.logIn( + qParams.code, + codeVerifier, + this.getOrgIdentifierFromState(qParams.state) + ); + } + } else if ( + qParams.clientId != null && + qParams.redirectUri != null && + qParams.state != null && + qParams.codeChallenge != null + ) { + this.redirectUri = qParams.redirectUri; + this.state = qParams.state; + this.codeChallenge = qParams.codeChallenge; + this.clientId = qParams.clientId; + } + }); + } + + async submit(returnUri?: string, includeUserIdentifier?: boolean) { + if (this.identifier == null || this.identifier === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("ssoValidationFailed"), + this.i18nService.t("ssoIdentifierRequired") + ); + return; + } + + this.initiateSsoFormPromise = this.apiService.preValidateSso(this.identifier); + const response = await this.initiateSsoFormPromise; + + const authorizeUrl = await this.buildAuthorizeUrl( + returnUri, + includeUserIdentifier, + response.token + ); + this.platformUtilsService.launchUri(authorizeUrl, { sameWindow: true }); + } + + protected async buildAuthorizeUrl( + returnUri?: string, + includeUserIdentifier?: boolean, + token?: string + ): Promise { + let codeChallenge = this.codeChallenge; + let state = this.state; + + const passwordOptions: any = { + type: "password", + length: 64, + uppercase: true, + lowercase: true, + numbers: true, + special: false, + }; + + if (codeChallenge == null) { + const codeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions); + const codeVerifierHash = await this.cryptoFunctionService.hash(codeVerifier, "sha256"); + codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); + await this.stateService.setSsoCodeVerifier(codeVerifier); + } + + if (state == null) { + state = await this.passwordGenerationService.generatePassword(passwordOptions); + if (returnUri) { + state += `_returnUri='${returnUri}'`; + } + } + + // Add Organization Identifier to state + state += `_identifier=${this.identifier}`; + + // Save state (regardless of new or existing) + await this.stateService.setSsoState(state); + + let authorizeUrl = + this.environmentService.getIdentityUrl() + + "/connect/authorize?" + + "client_id=" + + this.clientId + + "&redirect_uri=" + + encodeURIComponent(this.redirectUri) + + "&" + + "response_type=code&scope=api offline_access&" + + "state=" + + state + + "&code_challenge=" + + codeChallenge + + "&" + + "code_challenge_method=S256&response_mode=query&" + + "domain_hint=" + + encodeURIComponent(this.identifier) + + "&ssoToken=" + + encodeURIComponent(token); + + if (includeUserIdentifier) { + const userIdentifier = await this.apiService.getSsoUserIdentifier(); + authorizeUrl += `&user_identifier=${encodeURIComponent(userIdentifier)}`; + } + + return authorizeUrl; + } + + private async logIn(code: string, codeVerifier: string, orgIdFromState: string) { + this.loggingIn = true; + try { + const credentials = new SsoLogInCredentials( + code, + codeVerifier, + this.redirectUri, + orgIdFromState + ); + this.formPromise = this.authService.logIn(credentials); + const response = await this.formPromise; + if (response.requiresTwoFactor) { + if (this.onSuccessfulLoginTwoFactorNavigate != null) { + this.onSuccessfulLoginTwoFactorNavigate(); + } else { + this.router.navigate([this.twoFactorRoute], { + queryParams: { + identifier: orgIdFromState, + sso: "true", + }, + }); + } + } else if (response.resetMasterPassword) { + if (this.onSuccessfulLoginChangePasswordNavigate != null) { + this.onSuccessfulLoginChangePasswordNavigate(); + } else { + this.router.navigate([this.changePasswordRoute], { + queryParams: { + identifier: orgIdFromState, + }, + }); + } + } else if (response.forcePasswordReset) { + if (this.onSuccessfulLoginForceResetNavigate != null) { + this.onSuccessfulLoginForceResetNavigate(); + } else { + this.router.navigate([this.forcePasswordResetRoute]); + } + } else { + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); + if (this.onSuccessfulLogin != null) { + this.onSuccessfulLogin(); + } + if (this.onSuccessfulLoginNavigate != null) { + this.onSuccessfulLoginNavigate(); + } else { + this.router.navigate([this.successRoute]); + } + } + } catch (e) { + this.logService.error(e); + + // TODO: Key Connector Service should pass this error message to the logout callback instead of displaying here + if (e.message === "Key Connector error") { + this.platformUtilsService.showToast( + "error", + null, + this.i18nService.t("ssoKeyConnectorError") + ); + } + } + this.loggingIn = false; + } + + private getOrgIdentifierFromState(state: string): string { + if (state === null || state === undefined) { + return null; + } + + const stateSplit = state.split("_identifier="); + return stateSplit.length > 1 ? stateSplit[1] : null; + } + + private checkState(state: string, checkState: string): boolean { + if (state === null || state === undefined) { + return false; + } + if (checkState === null || checkState === undefined) { + return false; + } + + const stateSplit = state.split("_identifier="); + const checkStateSplit = checkState.split("_identifier="); + return stateSplit[0] === checkStateSplit[0]; + } +} diff --git a/libs/angular/src/components/toastr.component.ts b/libs/angular/src/components/toastr.component.ts new file mode 100644 index 0000000000..0e4ea4eae5 --- /dev/null +++ b/libs/angular/src/components/toastr.component.ts @@ -0,0 +1,95 @@ +import { animate, state, style, transition, trigger } from "@angular/animations"; +import { CommonModule } from "@angular/common"; +import { Component, ModuleWithProviders, NgModule } from "@angular/core"; +import { + DefaultNoComponentGlobalConfig, + GlobalConfig, + Toast as BaseToast, + ToastPackage, + ToastrService, + TOAST_CONFIG, +} from "ngx-toastr"; + +@Component({ + selector: "[toast-component2]", + template: ` + +
+ +
+
+
+ {{ title }} [{{ duplicatesCount + 1 }}] +
+
+
+ {{ message }} +
+
+
+
+
+ `, + animations: [ + trigger("flyInOut", [ + state("inactive", style({ opacity: 0 })), + state("active", style({ opacity: 1 })), + state("removed", style({ opacity: 0 })), + transition("inactive => active", animate("{{ easeTime }}ms {{ easing }}")), + transition("active => removed", animate("{{ easeTime }}ms {{ easing }}")), + ]), + ], + preserveWhitespaces: false, +}) +export class BitwardenToast extends BaseToast { + constructor(protected toastrService: ToastrService, public toastPackage: ToastPackage) { + super(toastrService, toastPackage); + } +} + +export const BitwardenToastGlobalConfig: GlobalConfig = { + ...DefaultNoComponentGlobalConfig, + toastComponent: BitwardenToast, +}; + +@NgModule({ + imports: [CommonModule], + declarations: [BitwardenToast], + exports: [BitwardenToast], +}) +export class BitwardenToastModule { + static forRoot(config: Partial = {}): ModuleWithProviders { + return { + ngModule: BitwardenToastModule, + providers: [ + { + provide: TOAST_CONFIG, + useValue: { + default: BitwardenToastGlobalConfig, + config: config, + }, + }, + ], + }; + } +} diff --git a/libs/angular/src/components/two-factor-options.component.ts b/libs/angular/src/components/two-factor-options.component.ts new file mode 100644 index 0000000000..a2aabc71ab --- /dev/null +++ b/libs/angular/src/components/two-factor-options.component.ts @@ -0,0 +1,36 @@ +import { Directive, EventEmitter, OnInit, Output } from "@angular/core"; +import { Router } from "@angular/router"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType"; + +@Directive() +export class TwoFactorOptionsComponent implements OnInit { + @Output() onProviderSelected = new EventEmitter(); + @Output() onRecoverSelected = new EventEmitter(); + + providers: any[] = []; + + constructor( + protected twoFactorService: TwoFactorService, + protected router: Router, + protected i18nService: I18nService, + protected platformUtilsService: PlatformUtilsService, + protected win: Window + ) {} + + ngOnInit() { + this.providers = this.twoFactorService.getSupportedProviders(this.win); + } + + choose(p: any) { + this.onProviderSelected.emit(p.type); + } + + recover() { + this.platformUtilsService.launchUri("https://bitwarden.com/help/lost-two-step-device/"); + this.onRecoverSelected.emit(); + } +} diff --git a/libs/angular/src/components/two-factor.component.ts b/libs/angular/src/components/two-factor.component.ts new file mode 100644 index 0000000000..2054c4dc40 --- /dev/null +++ b/libs/angular/src/components/two-factor.component.ts @@ -0,0 +1,284 @@ +import { Directive, OnDestroy, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import * as DuoWebSDK from "duo_web_sdk"; +import { first } from "rxjs/operators"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType"; +import { WebAuthnIFrame } from "jslib-common/misc/webauthn_iframe"; +import { AuthResult } from "jslib-common/models/domain/authResult"; +import { TokenRequestTwoFactor } from "jslib-common/models/request/identityToken/tokenRequestTwoFactor"; +import { TwoFactorEmailRequest } from "jslib-common/models/request/twoFactorEmailRequest"; +import { TwoFactorProviders } from "jslib-common/services/twoFactor.service"; + +import { CaptchaProtectedComponent } from "./captchaProtected.component"; + +@Directive() +export class TwoFactorComponent extends CaptchaProtectedComponent implements OnInit, OnDestroy { + token = ""; + remember = false; + webAuthnReady = false; + webAuthnNewTab = false; + providers = TwoFactorProviders; + providerType = TwoFactorProviderType; + selectedProviderType: TwoFactorProviderType = TwoFactorProviderType.Authenticator; + webAuthnSupported = false; + webAuthn: WebAuthnIFrame = null; + title = ""; + twoFactorEmail: string = null; + formPromise: Promise; + emailPromise: Promise; + identifier: string = null; + onSuccessfulLogin: () => Promise; + onSuccessfulLoginNavigate: () => Promise; + + get webAuthnAllow(): string { + return `publickey-credentials-get ${this.environmentService.getWebVaultUrl()}`; + } + + protected loginRoute = "login"; + protected successRoute = "vault"; + + constructor( + protected authService: AuthService, + protected router: Router, + protected i18nService: I18nService, + protected apiService: ApiService, + protected platformUtilsService: PlatformUtilsService, + protected win: Window, + protected environmentService: EnvironmentService, + protected stateService: StateService, + protected route: ActivatedRoute, + protected logService: LogService, + protected twoFactorService: TwoFactorService, + protected appIdService: AppIdService + ) { + super(environmentService, i18nService, platformUtilsService); + this.webAuthnSupported = this.platformUtilsService.supportsWebAuthn(win); + } + + async ngOnInit() { + if (!this.authing || this.twoFactorService.getProviders() == null) { + this.router.navigate([this.loginRoute]); + return; + } + + this.route.queryParams.pipe(first()).subscribe((qParams) => { + if (qParams.identifier != null) { + this.identifier = qParams.identifier; + } + }); + + if (this.needsLock) { + this.successRoute = "lock"; + } + + if (this.win != null && this.webAuthnSupported) { + const webVaultUrl = this.environmentService.getWebVaultUrl(); + this.webAuthn = new WebAuthnIFrame( + this.win, + webVaultUrl, + this.webAuthnNewTab, + this.platformUtilsService, + this.i18nService, + (token: string) => { + this.token = token; + this.submit(); + }, + (error: string) => { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), error); + }, + (info: string) => { + if (info === "ready") { + this.webAuthnReady = true; + } + } + ); + } + + this.selectedProviderType = this.twoFactorService.getDefaultProvider(this.webAuthnSupported); + await this.init(); + } + + ngOnDestroy(): void { + this.cleanupWebAuthn(); + this.webAuthn = null; + } + + async init() { + if (this.selectedProviderType == null) { + this.title = this.i18nService.t("loginUnavailable"); + return; + } + + this.cleanupWebAuthn(); + this.title = (TwoFactorProviders as any)[this.selectedProviderType].name; + const providerData = this.twoFactorService.getProviders().get(this.selectedProviderType); + switch (this.selectedProviderType) { + case TwoFactorProviderType.WebAuthn: + if (!this.webAuthnNewTab) { + setTimeout(() => { + this.authWebAuthn(); + }, 500); + } + break; + case TwoFactorProviderType.Duo: + case TwoFactorProviderType.OrganizationDuo: + setTimeout(() => { + DuoWebSDK.init({ + iframe: undefined, + host: providerData.Host, + sig_request: providerData.Signature, + submit_callback: async (f: HTMLFormElement) => { + const sig = f.querySelector('input[name="sig_response"]') as HTMLInputElement; + if (sig != null) { + this.token = sig.value; + await this.submit(); + } + }, + }); + }, 0); + break; + case TwoFactorProviderType.Email: + this.twoFactorEmail = providerData.Email; + if (this.twoFactorService.getProviders().size > 1) { + await this.sendEmail(false); + } + break; + default: + break; + } + } + + async submit() { + await this.setupCaptcha(); + + if (this.token == null || this.token === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("verificationCodeRequired") + ); + return; + } + + if (this.selectedProviderType === TwoFactorProviderType.WebAuthn) { + if (this.webAuthn != null) { + this.webAuthn.stop(); + } else { + return; + } + } else if ( + this.selectedProviderType === TwoFactorProviderType.Email || + this.selectedProviderType === TwoFactorProviderType.Authenticator + ) { + this.token = this.token.replace(" ", "").trim(); + } + + try { + await this.doSubmit(); + } catch { + if (this.selectedProviderType === TwoFactorProviderType.WebAuthn && this.webAuthn != null) { + this.webAuthn.start(); + } + } + } + + async doSubmit() { + this.formPromise = this.authService.logInTwoFactor( + new TokenRequestTwoFactor(this.selectedProviderType, this.token, this.remember), + this.captchaToken + ); + const response: AuthResult = await this.formPromise; + const disableFavicon = await this.stateService.getDisableFavicon(); + await this.stateService.setDisableFavicon(!!disableFavicon); + if (this.handleCaptchaRequired(response)) { + return; + } + if (this.onSuccessfulLogin != null) { + this.onSuccessfulLogin(); + } + if (response.resetMasterPassword) { + this.successRoute = "set-password"; + } + if (response.forcePasswordReset) { + this.successRoute = "update-temp-password"; + } + if (this.onSuccessfulLoginNavigate != null) { + this.onSuccessfulLoginNavigate(); + } else { + this.router.navigate([this.successRoute], { + queryParams: { + identifier: this.identifier, + }, + }); + } + } + + async sendEmail(doToast: boolean) { + if (this.selectedProviderType !== TwoFactorProviderType.Email) { + return; + } + + if (this.emailPromise != null) { + return; + } + + try { + const request = new TwoFactorEmailRequest(); + request.email = this.authService.email; + request.masterPasswordHash = this.authService.masterPasswordHash; + request.deviceIdentifier = await this.appIdService.getAppId(); + this.emailPromise = this.apiService.postTwoFactorEmail(request); + await this.emailPromise; + if (doToast) { + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("verificationCodeEmailSent", this.twoFactorEmail) + ); + } + } catch (e) { + this.logService.error(e); + } + + this.emailPromise = null; + } + + authWebAuthn() { + const providerData = this.twoFactorService.getProviders().get(this.selectedProviderType); + + if (!this.webAuthnSupported || this.webAuthn == null) { + return; + } + + this.webAuthn.init(providerData); + } + + private cleanupWebAuthn() { + if (this.webAuthn != null) { + this.webAuthn.stop(); + this.webAuthn.cleanup(); + } + } + + get authing(): boolean { + return ( + this.authService.authingWithPassword() || + this.authService.authingWithSso() || + this.authService.authingWithApiKey() + ); + } + + get needsLock(): boolean { + return this.authService.authingWithSso() || this.authService.authingWithApiKey(); + } +} diff --git a/libs/angular/src/components/update-password.component.ts b/libs/angular/src/components/update-password.component.ts new file mode 100644 index 0000000000..fb2697b4fc --- /dev/null +++ b/libs/angular/src/components/update-password.component.ts @@ -0,0 +1,126 @@ +import { Directive } from "@angular/core"; +import { Router } from "@angular/router"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { UserVerificationService } from "jslib-common/abstractions/userVerification.service"; +import { VerificationType } from "jslib-common/enums/verificationType"; +import { EncString } from "jslib-common/models/domain/encString"; +import { MasterPasswordPolicyOptions } from "jslib-common/models/domain/masterPasswordPolicyOptions"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { PasswordRequest } from "jslib-common/models/request/passwordRequest"; +import { Verification } from "jslib-common/types/verification"; + +import { ChangePasswordComponent as BaseChangePasswordComponent } from "./change-password.component"; + +@Directive() +export class UpdatePasswordComponent extends BaseChangePasswordComponent { + hint: string; + key: string; + enforcedPolicyOptions: MasterPasswordPolicyOptions; + showPassword = false; + currentMasterPassword: string; + + onSuccessfulChangePassword: () => Promise; + + constructor( + protected router: Router, + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + passwordGenerationService: PasswordGenerationService, + policyService: PolicyService, + cryptoService: CryptoService, + messagingService: MessagingService, + private apiService: ApiService, + stateService: StateService, + private userVerificationService: UserVerificationService, + private logService: LogService + ) { + super( + i18nService, + cryptoService, + messagingService, + passwordGenerationService, + platformUtilsService, + policyService, + stateService + ); + } + + togglePassword(confirmField: boolean) { + this.showPassword = !this.showPassword; + document.getElementById(confirmField ? "masterPasswordRetype" : "masterPassword").focus(); + } + + async cancel() { + await this.stateService.setOrganizationInvitation(null); + this.router.navigate(["/vault"]); + } + + async setupSubmitActions(): Promise { + if (this.currentMasterPassword == null || this.currentMasterPassword === "") { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("errorOccurred"), + this.i18nService.t("masterPassRequired") + ); + return false; + } + + const secret: Verification = { + type: VerificationType.MasterPassword, + secret: this.currentMasterPassword, + }; + try { + await this.userVerificationService.verifyUser(secret); + } catch (e) { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), e.message); + return false; + } + + this.kdf = await this.stateService.getKdfType(); + this.kdfIterations = await this.stateService.getKdfIterations(); + return true; + } + + async performSubmitActions( + masterPasswordHash: string, + key: SymmetricCryptoKey, + encKey: [SymmetricCryptoKey, EncString] + ) { + try { + // Create Request + const request = new PasswordRequest(); + request.masterPasswordHash = await this.cryptoService.hashPassword( + this.currentMasterPassword, + null + ); + request.newMasterPasswordHash = masterPasswordHash; + request.key = encKey[1].encryptedString; + + // Update user's password + this.apiService.postPassword(request); + + this.platformUtilsService.showToast( + "success", + this.i18nService.t("masterPasswordChanged"), + this.i18nService.t("logBackIn") + ); + + if (this.onSuccessfulChangePassword != null) { + this.onSuccessfulChangePassword(); + } else { + this.messagingService.send("logout"); + } + } catch (e) { + this.logService.error(e); + } + } +} diff --git a/libs/angular/src/components/update-temp-password.component.ts b/libs/angular/src/components/update-temp-password.component.ts new file mode 100644 index 0000000000..70f75cb8f4 --- /dev/null +++ b/libs/angular/src/components/update-temp-password.component.ts @@ -0,0 +1,132 @@ +import { Directive } from "@angular/core"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { SyncService } from "jslib-common/abstractions/sync.service"; +import { EncString } from "jslib-common/models/domain/encString"; +import { MasterPasswordPolicyOptions } from "jslib-common/models/domain/masterPasswordPolicyOptions"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { UpdateTempPasswordRequest } from "jslib-common/models/request/updateTempPasswordRequest"; + +import { ChangePasswordComponent as BaseChangePasswordComponent } from "./change-password.component"; + +@Directive() +export class UpdateTempPasswordComponent extends BaseChangePasswordComponent { + hint: string; + key: string; + enforcedPolicyOptions: MasterPasswordPolicyOptions; + showPassword = false; + + onSuccessfulChangePassword: () => Promise; + + constructor( + i18nService: I18nService, + platformUtilsService: PlatformUtilsService, + passwordGenerationService: PasswordGenerationService, + policyService: PolicyService, + cryptoService: CryptoService, + messagingService: MessagingService, + private apiService: ApiService, + stateService: StateService, + private syncService: SyncService, + private logService: LogService + ) { + super( + i18nService, + cryptoService, + messagingService, + passwordGenerationService, + platformUtilsService, + policyService, + stateService + ); + } + + async ngOnInit() { + await this.syncService.fullSync(true); + super.ngOnInit(); + } + + togglePassword(confirmField: boolean) { + this.showPassword = !this.showPassword; + document.getElementById(confirmField ? "masterPasswordRetype" : "masterPassword").focus(); + } + + async setupSubmitActions(): Promise { + this.enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions(); + this.email = await this.stateService.getEmail(); + this.kdf = await this.stateService.getKdfType(); + this.kdfIterations = await this.stateService.getKdfIterations(); + return true; + } + + async submit() { + // Validation + if (!(await this.strongPassword())) { + return; + } + + if (!(await this.setupSubmitActions())) { + return; + } + + try { + // Create new key and hash new password + const newKey = await this.cryptoService.makeKey( + this.masterPassword, + this.email.trim().toLowerCase(), + this.kdf, + this.kdfIterations + ); + const newPasswordHash = await this.cryptoService.hashPassword(this.masterPassword, newKey); + + // Grab user's current enc key + const userEncKey = await this.cryptoService.getEncKey(); + + // Create new encKey for the User + const newEncKey = await this.cryptoService.remakeEncKey(newKey, userEncKey); + + await this.performSubmitActions(newPasswordHash, newKey, newEncKey); + } catch (e) { + this.logService.error(e); + } + } + + async performSubmitActions( + masterPasswordHash: string, + key: SymmetricCryptoKey, + encKey: [SymmetricCryptoKey, EncString] + ) { + try { + // Create request + const request = new UpdateTempPasswordRequest(); + request.key = encKey[1].encryptedString; + request.newMasterPasswordHash = masterPasswordHash; + request.masterPasswordHint = this.hint; + + // Update user's password + this.formPromise = this.apiService.putUpdateTempPassword(request); + await this.formPromise; + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t("updatedMasterPassword") + ); + + if (this.onSuccessfulChangePassword != null) { + this.onSuccessfulChangePassword(); + } else { + this.messagingService.send("logout"); + } + } catch (e) { + this.logService.error(e); + } + } +} diff --git a/libs/angular/src/components/user-verification.component.html b/libs/angular/src/components/user-verification.component.html new file mode 100644 index 0000000000..b90c6074d8 --- /dev/null +++ b/libs/angular/src/components/user-verification.component.html @@ -0,0 +1,46 @@ + + + + {{ "confirmIdentity" | i18n }} + + +
+ + + + + {{ "codeSent" | i18n }} + +
+ +
+ + + {{ "confirmIdentity" | i18n }} +
+
diff --git a/libs/angular/src/components/user-verification.component.ts b/libs/angular/src/components/user-verification.component.ts new file mode 100644 index 0000000000..5504796e4b --- /dev/null +++ b/libs/angular/src/components/user-verification.component.ts @@ -0,0 +1,96 @@ +import { animate, style, transition, trigger } from "@angular/animations"; +import { Component, OnInit } from "@angular/core"; +import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from "@angular/forms"; + +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { UserVerificationService } from "jslib-common/abstractions/userVerification.service"; +import { VerificationType } from "jslib-common/enums/verificationType"; +import { Verification } from "jslib-common/types/verification"; + +/** + * Used for general-purpose user verification throughout the app. + * Collects the user's master password, or if they are using Key Connector, prompts for an OTP via email. + * This is exposed to the parent component via the ControlValueAccessor interface (e.g. bind it to a FormControl). + * Use UserVerificationService to verify the user's input. + */ +@Component({ + selector: "app-user-verification", + templateUrl: "user-verification.component.html", + providers: [ + { + provide: NG_VALUE_ACCESSOR, + multi: true, + useExisting: UserVerificationComponent, + }, + ], + animations: [ + trigger("sent", [ + transition(":enter", [style({ opacity: 0 }), animate("100ms", style({ opacity: 1 }))]), + ]), + ], +}) +export class UserVerificationComponent implements ControlValueAccessor, OnInit { + usesKeyConnector = false; + disableRequestOTP = false; + sentCode = false; + + secret = new FormControl(""); + + private onChange: (value: Verification) => void; + + constructor( + private keyConnectorService: KeyConnectorService, + private userVerificationService: UserVerificationService + ) {} + + async ngOnInit() { + this.usesKeyConnector = await this.keyConnectorService.getUsesKeyConnector(); + this.processChanges(this.secret.value); + + this.secret.valueChanges.subscribe((secret: string) => this.processChanges(secret)); + } + + async requestOTP() { + if (this.usesKeyConnector) { + this.disableRequestOTP = true; + try { + await this.userVerificationService.requestOTP(); + this.sentCode = true; + } finally { + this.disableRequestOTP = false; + } + } + } + + writeValue(obj: any): void { + this.secret.setValue(obj); + } + + registerOnChange(fn: any): void { + this.onChange = fn; + } + + registerOnTouched(fn: any): void { + // Not implemented + } + + setDisabledState?(isDisabled: boolean): void { + this.disableRequestOTP = isDisabled; + if (isDisabled) { + this.secret.disable(); + } else { + this.secret.enable(); + } + } + + private processChanges(secret: string) { + if (this.onChange == null) { + return; + } + + this.onChange({ + type: this.usesKeyConnector ? VerificationType.OTP : VerificationType.MasterPassword, + secret: secret, + }); + } +} diff --git a/libs/angular/src/components/view-custom-fields.component.ts b/libs/angular/src/components/view-custom-fields.component.ts new file mode 100644 index 0000000000..8439ed67b7 --- /dev/null +++ b/libs/angular/src/components/view-custom-fields.component.ts @@ -0,0 +1,39 @@ +import { Directive, Input } from "@angular/core"; + +import { EventService } from "jslib-common/abstractions/event.service"; +import { EventType } from "jslib-common/enums/eventType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { FieldView } from "jslib-common/models/view/fieldView"; + +@Directive() +export class ViewCustomFieldsComponent { + @Input() cipher: CipherView; + @Input() promptPassword: () => Promise; + @Input() copy: (value: string, typeI18nKey: string, aType: string) => void; + + fieldType = FieldType; + + constructor(private eventService: EventService) {} + + async toggleFieldValue(field: FieldView) { + if (!(await this.promptPassword())) { + return; + } + + const f = field as any; + f.showValue = !f.showValue; + f.showCount = false; + if (f.showValue) { + this.eventService.collect(EventType.Cipher_ClientToggledHiddenFieldVisible, this.cipher.id); + } + } + + async toggleFieldCount(field: FieldView) { + if (!field.showValue) { + return; + } + + field.showCount = !field.showCount; + } +} diff --git a/libs/angular/src/components/view.component.ts b/libs/angular/src/components/view.component.ts new file mode 100644 index 0000000000..d1e949677b --- /dev/null +++ b/libs/angular/src/components/view.component.ts @@ -0,0 +1,454 @@ +import { + ChangeDetectorRef, + Directive, + EventEmitter, + Input, + NgZone, + OnDestroy, + OnInit, + Output, +} from "@angular/core"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuditService } from "jslib-common/abstractions/audit.service"; +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EventService } from "jslib-common/abstractions/event.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PasswordRepromptService } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TotpService } from "jslib-common/abstractions/totp.service"; +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { EventType } from "jslib-common/enums/eventType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { ErrorResponse } from "jslib-common/models/response/errorResponse"; +import { AttachmentView } from "jslib-common/models/view/attachmentView"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; + +const BroadcasterSubscriptionId = "ViewComponent"; + +@Directive() +export class ViewComponent implements OnDestroy, OnInit { + @Input() cipherId: string; + @Output() onEditCipher = new EventEmitter(); + @Output() onCloneCipher = new EventEmitter(); + @Output() onShareCipher = new EventEmitter(); + @Output() onDeletedCipher = new EventEmitter(); + @Output() onRestoredCipher = new EventEmitter(); + + cipher: CipherView; + showPassword: boolean; + showPasswordCount: boolean; + showCardNumber: boolean; + showCardCode: boolean; + canAccessPremium: boolean; + totpCode: string; + totpCodeFormatted: string; + totpDash: number; + totpSec: number; + totpLow: boolean; + fieldType = FieldType; + checkPasswordPromise: Promise; + + private totpInterval: any; + private previousCipherId: string; + private passwordReprompted = false; + + constructor( + protected cipherService: CipherService, + protected totpService: TotpService, + protected tokenService: TokenService, + protected i18nService: I18nService, + protected cryptoService: CryptoService, + protected platformUtilsService: PlatformUtilsService, + protected auditService: AuditService, + protected win: Window, + protected broadcasterService: BroadcasterService, + protected ngZone: NgZone, + protected changeDetectorRef: ChangeDetectorRef, + protected eventService: EventService, + protected apiService: ApiService, + protected passwordRepromptService: PasswordRepromptService, + private logService: LogService, + protected stateService: StateService + ) {} + + ngOnInit() { + this.broadcasterService.subscribe(BroadcasterSubscriptionId, (message: any) => { + this.ngZone.run(async () => { + switch (message.command) { + case "syncCompleted": + if (message.successfully) { + await this.load(); + this.changeDetectorRef.detectChanges(); + } + break; + } + }); + }); + } + + ngOnDestroy() { + this.broadcasterService.unsubscribe(BroadcasterSubscriptionId); + this.cleanUp(); + } + + async load() { + this.cleanUp(); + + const cipher = await this.cipherService.get(this.cipherId); + this.cipher = await cipher.decrypt(); + this.canAccessPremium = await this.stateService.getCanAccessPremium(); + + if ( + this.cipher.type === CipherType.Login && + this.cipher.login.totp && + (cipher.organizationUseTotp || this.canAccessPremium) + ) { + await this.totpUpdateCode(); + const interval = this.totpService.getTimeInterval(this.cipher.login.totp); + await this.totpTick(interval); + + this.totpInterval = setInterval(async () => { + await this.totpTick(interval); + }, 1000); + } + + if (this.previousCipherId !== this.cipherId) { + this.eventService.collect(EventType.Cipher_ClientViewed, this.cipherId); + } + this.previousCipherId = this.cipherId; + } + + async edit() { + if (await this.promptPassword()) { + this.onEditCipher.emit(this.cipher); + return true; + } + + return false; + } + + async clone() { + if (await this.promptPassword()) { + this.onCloneCipher.emit(this.cipher); + return true; + } + + return false; + } + + async share() { + if (await this.promptPassword()) { + this.onShareCipher.emit(this.cipher); + return true; + } + + return false; + } + + async delete(): Promise { + if (!(await this.promptPassword())) { + return; + } + + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t( + this.cipher.isDeleted ? "permanentlyDeleteItemConfirmation" : "deleteItemConfirmation" + ), + this.i18nService.t("deleteItem"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + await this.deleteCipher(); + this.platformUtilsService.showToast( + "success", + null, + this.i18nService.t(this.cipher.isDeleted ? "permanentlyDeletedItem" : "deletedItem") + ); + this.onDeletedCipher.emit(this.cipher); + } catch (e) { + this.logService.error(e); + } + + return true; + } + + async restore(): Promise { + if (!this.cipher.isDeleted) { + return false; + } + + const confirmed = await this.platformUtilsService.showDialog( + this.i18nService.t("restoreItemConfirmation"), + this.i18nService.t("restoreItem"), + this.i18nService.t("yes"), + this.i18nService.t("no"), + "warning" + ); + if (!confirmed) { + return false; + } + + try { + await this.restoreCipher(); + this.platformUtilsService.showToast("success", null, this.i18nService.t("restoredItem")); + this.onRestoredCipher.emit(this.cipher); + } catch (e) { + this.logService.error(e); + } + + return true; + } + + async togglePassword() { + if (!(await this.promptPassword())) { + return; + } + + this.showPassword = !this.showPassword; + this.showPasswordCount = false; + if (this.showPassword) { + this.eventService.collect(EventType.Cipher_ClientToggledPasswordVisible, this.cipherId); + } + } + + async togglePasswordCount() { + if (!this.showPassword) { + return; + } + + this.showPasswordCount = !this.showPasswordCount; + } + + async toggleCardNumber() { + if (!(await this.promptPassword())) { + return; + } + + this.showCardNumber = !this.showCardNumber; + if (this.showCardNumber) { + this.eventService.collect(EventType.Cipher_ClientToggledCardCodeVisible, this.cipherId); + } + } + + async toggleCardCode() { + if (!(await this.promptPassword())) { + return; + } + + this.showCardCode = !this.showCardCode; + if (this.showCardCode) { + this.eventService.collect(EventType.Cipher_ClientToggledCardCodeVisible, this.cipherId); + } + } + + async checkPassword() { + if ( + this.cipher.login == null || + this.cipher.login.password == null || + this.cipher.login.password === "" + ) { + return; + } + + this.checkPasswordPromise = this.auditService.passwordLeaked(this.cipher.login.password); + const matches = await this.checkPasswordPromise; + + if (matches > 0) { + this.platformUtilsService.showToast( + "warning", + null, + this.i18nService.t("passwordExposed", matches.toString()) + ); + } else { + this.platformUtilsService.showToast("success", null, this.i18nService.t("passwordSafe")); + } + } + + launch(uri: LoginUriView, cipherId?: string) { + if (!uri.canLaunch) { + return; + } + + if (cipherId) { + this.cipherService.updateLastLaunchedDate(cipherId); + } + + this.platformUtilsService.launchUri(uri.launchUri); + } + + async copy(value: string, typeI18nKey: string, aType: string) { + if (value == null) { + return; + } + + if ( + this.passwordRepromptService.protectedFields().includes(aType) && + !(await this.promptPassword()) + ) { + return; + } + + const copyOptions = this.win != null ? { window: this.win } : null; + this.platformUtilsService.copyToClipboard(value, copyOptions); + this.platformUtilsService.showToast( + "info", + null, + this.i18nService.t("valueCopied", this.i18nService.t(typeI18nKey)) + ); + + if (typeI18nKey === "password") { + this.eventService.collect(EventType.Cipher_ClientToggledHiddenFieldVisible, this.cipherId); + } else if (typeI18nKey === "securityCode") { + this.eventService.collect(EventType.Cipher_ClientCopiedCardCode, this.cipherId); + } else if (aType === "H_Field") { + this.eventService.collect(EventType.Cipher_ClientCopiedHiddenField, this.cipherId); + } + } + + setTextDataOnDrag(event: DragEvent, data: string) { + event.dataTransfer.setData("text", data); + } + + async downloadAttachment(attachment: AttachmentView) { + if (!(await this.promptPassword())) { + return; + } + const a = attachment as any; + if (a.downloading) { + return; + } + + if (this.cipher.organizationId == null && !this.canAccessPremium) { + this.platformUtilsService.showToast( + "error", + this.i18nService.t("premiumRequired"), + this.i18nService.t("premiumRequiredDesc") + ); + return; + } + + let url: string; + try { + const attachmentDownloadResponse = await this.apiService.getAttachmentData( + this.cipher.id, + attachment.id + ); + url = attachmentDownloadResponse.url; + } catch (e) { + if (e instanceof ErrorResponse && (e as ErrorResponse).statusCode === 404) { + url = attachment.url; + } else if (e instanceof ErrorResponse) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } else { + throw e; + } + } + + a.downloading = true; + const response = await fetch(new Request(url, { cache: "no-store" })); + if (response.status !== 200) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + a.downloading = false; + return; + } + + try { + const buf = await response.arrayBuffer(); + const key = + attachment.key != null + ? attachment.key + : await this.cryptoService.getOrgKey(this.cipher.organizationId); + const decBuf = await this.cryptoService.decryptFromBytes(buf, key); + this.platformUtilsService.saveFile(this.win, decBuf, null, attachment.fileName); + } catch (e) { + this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred")); + } + + a.downloading = false; + } + + protected deleteCipher() { + return this.cipher.isDeleted + ? this.cipherService.deleteWithServer(this.cipher.id) + : this.cipherService.softDeleteWithServer(this.cipher.id); + } + + protected restoreCipher() { + return this.cipherService.restoreWithServer(this.cipher.id); + } + + protected async promptPassword() { + if (this.cipher.reprompt === CipherRepromptType.None || this.passwordReprompted) { + return true; + } + + return (this.passwordReprompted = await this.passwordRepromptService.showPasswordPrompt()); + } + + private cleanUp() { + this.totpCode = null; + this.cipher = null; + this.showPassword = false; + this.showCardNumber = false; + this.showCardCode = false; + this.passwordReprompted = false; + if (this.totpInterval) { + clearInterval(this.totpInterval); + } + } + + private async totpUpdateCode() { + if ( + this.cipher == null || + this.cipher.type !== CipherType.Login || + this.cipher.login.totp == null + ) { + if (this.totpInterval) { + clearInterval(this.totpInterval); + } + return; + } + + this.totpCode = await this.totpService.getCode(this.cipher.login.totp); + if (this.totpCode != null) { + if (this.totpCode.length > 4) { + const half = Math.floor(this.totpCode.length / 2); + this.totpCodeFormatted = + this.totpCode.substring(0, half) + " " + this.totpCode.substring(half); + } else { + this.totpCodeFormatted = this.totpCode; + } + } else { + this.totpCodeFormatted = null; + if (this.totpInterval) { + clearInterval(this.totpInterval); + } + } + } + + private async totpTick(intervalSeconds: number) { + const epoch = Math.round(new Date().getTime() / 1000.0); + const mod = epoch % intervalSeconds; + + this.totpSec = intervalSeconds - mod; + this.totpDash = +(Math.round(((78.6 / intervalSeconds) * mod + "e+2") as any) + "e-2"); + this.totpLow = this.totpSec <= 7; + if (mod === 0) { + await this.totpUpdateCode(); + } + } +} diff --git a/libs/angular/src/directives/a11y-invalid.directive.ts b/libs/angular/src/directives/a11y-invalid.directive.ts new file mode 100644 index 0000000000..c5f0e40658 --- /dev/null +++ b/libs/angular/src/directives/a11y-invalid.directive.ts @@ -0,0 +1,26 @@ +import { Directive, ElementRef, OnDestroy, OnInit } from "@angular/core"; +import { NgControl } from "@angular/forms"; +import { Subscription } from "rxjs"; + +@Directive({ + selector: "[appA11yInvalid]", +}) +export class A11yInvalidDirective implements OnDestroy, OnInit { + private sub: Subscription; + + constructor(private el: ElementRef, private formControlDirective: NgControl) {} + + ngOnInit() { + this.sub = this.formControlDirective.control.statusChanges.subscribe((status) => { + if (status === "INVALID") { + this.el.nativeElement.setAttribute("aria-invalid", "true"); + } else if (status === "VALID") { + this.el.nativeElement.setAttribute("aria-invalid", "false"); + } + }); + } + + ngOnDestroy() { + this.sub?.unsubscribe(); + } +} diff --git a/libs/angular/src/directives/a11y-title.directive.ts b/libs/angular/src/directives/a11y-title.directive.ts new file mode 100644 index 0000000000..20e53a55fb --- /dev/null +++ b/libs/angular/src/directives/a11y-title.directive.ts @@ -0,0 +1,23 @@ +import { Directive, ElementRef, Input, Renderer2 } from "@angular/core"; + +@Directive({ + selector: "[appA11yTitle]", +}) +export class A11yTitleDirective { + @Input() set appA11yTitle(title: string) { + this.title = title; + } + + private title: string; + + constructor(private el: ElementRef, private renderer: Renderer2) {} + + ngOnInit() { + if (!this.el.nativeElement.hasAttribute("title")) { + this.renderer.setAttribute(this.el.nativeElement, "title", this.title); + } + if (!this.el.nativeElement.hasAttribute("aria-label")) { + this.renderer.setAttribute(this.el.nativeElement, "aria-label", this.title); + } + } +} diff --git a/libs/angular/src/directives/api-action.directive.ts b/libs/angular/src/directives/api-action.directive.ts new file mode 100644 index 0000000000..3d12172603 --- /dev/null +++ b/libs/angular/src/directives/api-action.directive.ts @@ -0,0 +1,49 @@ +import { Directive, ElementRef, Input, OnChanges } from "@angular/core"; + +import { LogService } from "jslib-common/abstractions/log.service"; +import { ErrorResponse } from "jslib-common/models/response/errorResponse"; + +import { ValidationService } from "../services/validation.service"; + +/** + * Provides error handling, in particular for any error returned by the server in an api call. + * Attach it to a
element and provide the name of the class property that will hold the api call promise. + * e.g. + * Any errors/rejections that occur will be intercepted and displayed as error toasts. + */ +@Directive({ + selector: "[appApiAction]", +}) +export class ApiActionDirective implements OnChanges { + @Input() appApiAction: Promise; + + constructor( + private el: ElementRef, + private validationService: ValidationService, + private logService: LogService + ) {} + + ngOnChanges(changes: any) { + if (this.appApiAction == null || this.appApiAction.then == null) { + return; + } + + this.el.nativeElement.loading = true; + + this.appApiAction.then( + (response: any) => { + this.el.nativeElement.loading = false; + }, + (e: any) => { + this.el.nativeElement.loading = false; + + if ((e as ErrorResponse).captchaRequired) { + this.logService.error("Captcha required error response: " + e.getSingleMessage()); + return; + } + this.logService?.error(`Received API exception: ${e}`); + this.validationService.showError(e); + } + ); + } +} diff --git a/libs/angular/src/directives/autofocus.directive.ts b/libs/angular/src/directives/autofocus.directive.ts new file mode 100644 index 0000000000..5c5997fa1b --- /dev/null +++ b/libs/angular/src/directives/autofocus.directive.ts @@ -0,0 +1,27 @@ +import { Directive, ElementRef, Input, NgZone } from "@angular/core"; +import { take } from "rxjs/operators"; + +import { Utils } from "jslib-common/misc/utils"; + +@Directive({ + selector: "[appAutofocus]", +}) +export class AutofocusDirective { + @Input() set appAutofocus(condition: boolean | string) { + this.autofocus = condition === "" || condition === true; + } + + private autofocus: boolean; + + constructor(private el: ElementRef, private ngZone: NgZone) {} + + ngOnInit() { + if (!Utils.isMobileBrowser && this.autofocus) { + if (this.ngZone.isStable) { + this.el.nativeElement.focus(); + } else { + this.ngZone.onStable.pipe(take(1)).subscribe(() => this.el.nativeElement.focus()); + } + } + } +} diff --git a/libs/angular/src/directives/blur-click.directive.ts b/libs/angular/src/directives/blur-click.directive.ts new file mode 100644 index 0000000000..2fc1d36713 --- /dev/null +++ b/libs/angular/src/directives/blur-click.directive.ts @@ -0,0 +1,12 @@ +import { Directive, ElementRef, HostListener } from "@angular/core"; + +@Directive({ + selector: "[appBlurClick]", +}) +export class BlurClickDirective { + constructor(private el: ElementRef) {} + + @HostListener("click") onClick() { + this.el.nativeElement.blur(); + } +} diff --git a/libs/angular/src/directives/box-row.directive.ts b/libs/angular/src/directives/box-row.directive.ts new file mode 100644 index 0000000000..9ae94314ef --- /dev/null +++ b/libs/angular/src/directives/box-row.directive.ts @@ -0,0 +1,59 @@ +import { Directive, ElementRef, HostListener, OnInit } from "@angular/core"; + +@Directive({ + selector: "[appBoxRow]", +}) +export class BoxRowDirective implements OnInit { + el: HTMLElement = null; + formEls: Element[]; + + constructor(elRef: ElementRef) { + this.el = elRef.nativeElement; + } + + ngOnInit(): void { + this.formEls = Array.from( + this.el.querySelectorAll('input:not([type="hidden"]), select, textarea') + ); + this.formEls.forEach((formEl) => { + formEl.addEventListener( + "focus", + () => { + this.el.classList.add("active"); + }, + false + ); + + formEl.addEventListener( + "blur", + () => { + this.el.classList.remove("active"); + }, + false + ); + }); + } + + @HostListener("click", ["$event"]) onClick(event: Event) { + const target = event.target as HTMLElement; + if ( + target !== this.el && + !target.classList.contains("progress") && + !target.classList.contains("progress-bar") + ) { + return; + } + + if (this.formEls.length > 0) { + const formEl = this.formEls[0] as HTMLElement; + if (formEl.tagName.toLowerCase() === "input") { + const inputEl = formEl as HTMLInputElement; + if (inputEl.type != null && inputEl.type.toLowerCase() === "checkbox") { + inputEl.click(); + return; + } + } + formEl.focus(); + } + } +} diff --git a/libs/angular/src/directives/cipherListVirtualScroll.directive.ts b/libs/angular/src/directives/cipherListVirtualScroll.directive.ts new file mode 100644 index 0000000000..7b906b53c8 --- /dev/null +++ b/libs/angular/src/directives/cipherListVirtualScroll.directive.ts @@ -0,0 +1,76 @@ +import { + CdkFixedSizeVirtualScroll, + FixedSizeVirtualScrollStrategy, + VIRTUAL_SCROLL_STRATEGY, +} from "@angular/cdk/scrolling"; +import { Directive, forwardRef } from "@angular/core"; + +// Custom virtual scroll strategy for cdk-virtual-scroll +// Uses a sample list item to set the itemSize for FixedSizeVirtualScrollStrategy +// The use case is the same as FixedSizeVirtualScrollStrategy, but it avoids locking in pixel sizes in the template. +export class CipherListVirtualScrollStrategy extends FixedSizeVirtualScrollStrategy { + private checkItemSizeCallback: any; + private timeout: any; + + constructor( + itemSize: number, + minBufferPx: number, + maxBufferPx: number, + checkItemSizeCallback: any + ) { + super(itemSize, minBufferPx, maxBufferPx); + this.checkItemSizeCallback = checkItemSizeCallback; + } + + onContentRendered() { + if (this.timeout != null) { + clearTimeout(this.timeout); + } + + this.timeout = setTimeout(this.checkItemSizeCallback, 500); + } +} + +export function _cipherListVirtualScrollStrategyFactory(cipherListDir: CipherListVirtualScroll) { + return cipherListDir._scrollStrategy; +} + +@Directive({ + selector: "cdk-virtual-scroll-viewport[itemSize]", + providers: [ + { + provide: VIRTUAL_SCROLL_STRATEGY, + useFactory: _cipherListVirtualScrollStrategyFactory, + deps: [forwardRef(() => CipherListVirtualScroll)], + }, + ], +}) +export class CipherListVirtualScroll extends CdkFixedSizeVirtualScroll { + _scrollStrategy: CipherListVirtualScrollStrategy; + + constructor() { + super(); + this._scrollStrategy = new CipherListVirtualScrollStrategy( + this.itemSize, + this.minBufferPx, + this.maxBufferPx, + this.checkAndUpdateItemSize + ); + } + + checkAndUpdateItemSize = () => { + const sampleItem = document.querySelector( + "cdk-virtual-scroll-viewport .virtual-scroll-item" + ) as HTMLElement; + const newItemSize = sampleItem?.offsetHeight; + + if (newItemSize != null && newItemSize !== this.itemSize) { + this.itemSize = newItemSize; + this._scrollStrategy.updateItemAndBufferSize( + this.itemSize, + this.minBufferPx, + this.maxBufferPx + ); + } + }; +} diff --git a/libs/angular/src/directives/fallback-src.directive.ts b/libs/angular/src/directives/fallback-src.directive.ts new file mode 100644 index 0000000000..11bce2052b --- /dev/null +++ b/libs/angular/src/directives/fallback-src.directive.ts @@ -0,0 +1,14 @@ +import { Directive, ElementRef, HostListener, Input } from "@angular/core"; + +@Directive({ + selector: "[appFallbackSrc]", +}) +export class FallbackSrcDirective { + @Input("appFallbackSrc") appFallbackSrc: string; + + constructor(private el: ElementRef) {} + + @HostListener("error") onError() { + this.el.nativeElement.src = this.appFallbackSrc; + } +} diff --git a/libs/angular/src/directives/input-strip-spaces.directive.ts b/libs/angular/src/directives/input-strip-spaces.directive.ts new file mode 100644 index 0000000000..598281b85c --- /dev/null +++ b/libs/angular/src/directives/input-strip-spaces.directive.ts @@ -0,0 +1,12 @@ +import { Directive, ElementRef, HostListener } from "@angular/core"; + +@Directive({ + selector: "input[appInputStripSpaces]", +}) +export class InputStripSpacesDirective { + constructor(private el: ElementRef) {} + + @HostListener("input") onInput() { + this.el.nativeElement.value = this.el.nativeElement.value.replace(/ /g, ""); + } +} diff --git a/libs/angular/src/directives/input-verbatim.directive.ts b/libs/angular/src/directives/input-verbatim.directive.ts new file mode 100644 index 0000000000..3dd1975ae3 --- /dev/null +++ b/libs/angular/src/directives/input-verbatim.directive.ts @@ -0,0 +1,32 @@ +import { Directive, ElementRef, Input, Renderer2 } from "@angular/core"; + +@Directive({ + selector: "[appInputVerbatim]", +}) +export class InputVerbatimDirective { + @Input() set appInputVerbatim(condition: boolean | string) { + this.disableComplete = condition === "" || condition === true; + } + + private disableComplete: boolean; + + constructor(private el: ElementRef, private renderer: Renderer2) {} + + ngOnInit() { + if (this.disableComplete && !this.el.nativeElement.hasAttribute("autocomplete")) { + this.renderer.setAttribute(this.el.nativeElement, "autocomplete", "off"); + } + if (!this.el.nativeElement.hasAttribute("autocapitalize")) { + this.renderer.setAttribute(this.el.nativeElement, "autocapitalize", "none"); + } + if (!this.el.nativeElement.hasAttribute("autocorrect")) { + this.renderer.setAttribute(this.el.nativeElement, "autocorrect", "none"); + } + if (!this.el.nativeElement.hasAttribute("spellcheck")) { + this.renderer.setAttribute(this.el.nativeElement, "spellcheck", "false"); + } + if (!this.el.nativeElement.hasAttribute("inputmode")) { + this.renderer.setAttribute(this.el.nativeElement, "inputmode", "verbatim"); + } + } +} diff --git a/libs/angular/src/directives/not-premium.directive.ts b/libs/angular/src/directives/not-premium.directive.ts new file mode 100644 index 0000000000..15a01f7146 --- /dev/null +++ b/libs/angular/src/directives/not-premium.directive.ts @@ -0,0 +1,27 @@ +import { Directive, OnInit, TemplateRef, ViewContainerRef } from "@angular/core"; + +import { StateService } from "jslib-common/abstractions/state.service"; + +/** + * Hides the element if the user has premium. + */ +@Directive({ + selector: "[appNotPremium]", +}) +export class NotPremiumDirective implements OnInit { + constructor( + private templateRef: TemplateRef, + private viewContainer: ViewContainerRef, + private stateService: StateService + ) {} + + async ngOnInit(): Promise { + const premium = await this.stateService.getCanAccessPremium(); + + if (premium) { + this.viewContainer.clear(); + } else { + this.viewContainer.createEmbeddedView(this.templateRef); + } + } +} diff --git a/libs/angular/src/directives/premium.directive.ts b/libs/angular/src/directives/premium.directive.ts new file mode 100644 index 0000000000..c403f5b9b6 --- /dev/null +++ b/libs/angular/src/directives/premium.directive.ts @@ -0,0 +1,27 @@ +import { Directive, OnInit, TemplateRef, ViewContainerRef } from "@angular/core"; + +import { StateService } from "jslib-common/abstractions/state.service"; + +/** + * Only shows the element if the user has premium. + */ +@Directive({ + selector: "[appPremium]", +}) +export class PremiumDirective implements OnInit { + constructor( + private templateRef: TemplateRef, + private viewContainer: ViewContainerRef, + private stateService: StateService + ) {} + + async ngOnInit(): Promise { + const premium = await this.stateService.getCanAccessPremium(); + + if (premium) { + this.viewContainer.createEmbeddedView(this.templateRef); + } else { + this.viewContainer.clear(); + } + } +} diff --git a/libs/angular/src/directives/select-copy.directive.ts b/libs/angular/src/directives/select-copy.directive.ts new file mode 100644 index 0000000000..81d4928b4b --- /dev/null +++ b/libs/angular/src/directives/select-copy.directive.ts @@ -0,0 +1,37 @@ +import { Directive, ElementRef, HostListener } from "@angular/core"; + +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +@Directive({ + selector: "[appSelectCopy]", +}) +export class SelectCopyDirective { + constructor(private el: ElementRef, private platformUtilsService: PlatformUtilsService) {} + + @HostListener("copy") onCopy() { + if (window == null) { + return; + } + let copyText = ""; + const selection = window.getSelection(); + for (let i = 0; i < selection.rangeCount; i++) { + const range = selection.getRangeAt(i); + const text = range.toString(); + + // The selection should only contain one line of text. In some cases however, the + // selection contains newlines and space characters from the indentation of following + // sibling nodes. To avoid copying passwords containing trailing newlines and spaces + // that aren't part of the password, the selection has to be trimmed. + let stringEndPos = text.length; + const newLinePos = text.search(/(?:\r\n|\r|\n)/); + if (newLinePos > -1) { + const otherPart = text.substr(newLinePos).trim(); + if (otherPart === "") { + stringEndPos = newLinePos; + } + } + copyText += text.substring(0, stringEndPos); + } + this.platformUtilsService.copyToClipboard(copyText, { window: window }); + } +} diff --git a/libs/angular/src/directives/stop-click.directive.ts b/libs/angular/src/directives/stop-click.directive.ts new file mode 100644 index 0000000000..0e88dde33a --- /dev/null +++ b/libs/angular/src/directives/stop-click.directive.ts @@ -0,0 +1,10 @@ +import { Directive, HostListener } from "@angular/core"; + +@Directive({ + selector: "[appStopClick]", +}) +export class StopClickDirective { + @HostListener("click", ["$event"]) onClick($event: MouseEvent) { + $event.preventDefault(); + } +} diff --git a/libs/angular/src/directives/stop-prop.directive.ts b/libs/angular/src/directives/stop-prop.directive.ts new file mode 100644 index 0000000000..8393e79903 --- /dev/null +++ b/libs/angular/src/directives/stop-prop.directive.ts @@ -0,0 +1,10 @@ +import { Directive, HostListener } from "@angular/core"; + +@Directive({ + selector: "[appStopProp]", +}) +export class StopPropDirective { + @HostListener("click", ["$event"]) onClick($event: MouseEvent) { + $event.stopPropagation(); + } +} diff --git a/libs/angular/src/directives/true-false-value.directive.ts b/libs/angular/src/directives/true-false-value.directive.ts new file mode 100644 index 0000000000..9e35e77ea5 --- /dev/null +++ b/libs/angular/src/directives/true-false-value.directive.ts @@ -0,0 +1,49 @@ +import { Directive, ElementRef, forwardRef, HostListener, Input, Renderer2 } from "@angular/core"; +import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms"; + +// ref: https://juristr.com/blog/2018/02/ng-true-value-directive/ +@Directive({ + selector: "input[type=checkbox][appTrueFalseValue]", + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TrueFalseValueDirective), + multi: true, + }, + ], +}) +export class TrueFalseValueDirective implements ControlValueAccessor { + @Input() trueValue = true; + @Input() falseValue = false; + + constructor(private elementRef: ElementRef, private renderer: Renderer2) {} + + @HostListener("change", ["$event"]) + onHostChange(ev: any) { + this.propagateChange(ev.target.checked ? this.trueValue : this.falseValue); + } + + writeValue(obj: any): void { + if (obj === this.trueValue) { + this.renderer.setProperty(this.elementRef.nativeElement, "checked", true); + } else { + this.renderer.setProperty(this.elementRef.nativeElement, "checked", false); + } + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + /* nothing */ + } + + setDisabledState?(isDisabled: boolean): void { + /* nothing */ + } + + private propagateChange = (_: any) => { + /* nothing */ + }; +} diff --git a/libs/angular/src/guards/auth.guard.ts b/libs/angular/src/guards/auth.guard.ts new file mode 100644 index 0000000000..355f797bf3 --- /dev/null +++ b/libs/angular/src/guards/auth.guard.ts @@ -0,0 +1,42 @@ +import { Injectable } from "@angular/core"; +import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from "@angular/router"; + +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; + +@Injectable() +export class AuthGuard implements CanActivate { + constructor( + private authService: AuthService, + private router: Router, + private messagingService: MessagingService, + private keyConnectorService: KeyConnectorService + ) {} + + async canActivate(route: ActivatedRouteSnapshot, routerState: RouterStateSnapshot) { + const authStatus = await this.authService.getAuthStatus(); + + if (authStatus === AuthenticationStatus.LoggedOut) { + this.messagingService.send("authBlocked", { url: routerState.url }); + return false; + } + + if (authStatus === AuthenticationStatus.Locked) { + if (routerState != null) { + this.messagingService.send("lockedUrl", { url: routerState.url }); + } + return this.router.createUrlTree(["lock"], { queryParams: { promptBiometric: true } }); + } + + if ( + !routerState.url.includes("remove-password") && + (await this.keyConnectorService.getConvertAccountRequired()) + ) { + return this.router.createUrlTree(["/remove-password"]); + } + + return true; + } +} diff --git a/libs/angular/src/guards/lock.guard.ts b/libs/angular/src/guards/lock.guard.ts new file mode 100644 index 0000000000..262158528e --- /dev/null +++ b/libs/angular/src/guards/lock.guard.ts @@ -0,0 +1,25 @@ +import { Injectable } from "@angular/core"; +import { CanActivate, Router } from "@angular/router"; + +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; + +@Injectable() +export class LockGuard implements CanActivate { + protected homepage = "vault"; + protected loginpage = "login"; + constructor(private authService: AuthService, private router: Router) {} + + async canActivate() { + const authStatus = await this.authService.getAuthStatus(); + + if (authStatus === AuthenticationStatus.Locked) { + return true; + } + + const redirectUrl = + authStatus === AuthenticationStatus.LoggedOut ? this.loginpage : this.homepage; + + return this.router.createUrlTree([redirectUrl]); + } +} diff --git a/libs/angular/src/guards/unauth.guard.ts b/libs/angular/src/guards/unauth.guard.ts new file mode 100644 index 0000000000..3335d636d4 --- /dev/null +++ b/libs/angular/src/guards/unauth.guard.ts @@ -0,0 +1,25 @@ +import { Injectable } from "@angular/core"; +import { CanActivate, Router } from "@angular/router"; + +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { AuthenticationStatus } from "jslib-common/enums/authenticationStatus"; + +@Injectable() +export class UnauthGuard implements CanActivate { + protected homepage = "vault"; + constructor(private authService: AuthService, private router: Router) {} + + async canActivate() { + const authStatus = await this.authService.getAuthStatus(); + + if (authStatus === AuthenticationStatus.LoggedOut) { + return true; + } + + if (authStatus === AuthenticationStatus.Locked) { + return this.router.createUrlTree(["lock"]); + } + + return this.router.createUrlTree([this.homepage]); + } +} diff --git a/libs/angular/src/images/cards/amex-dark.png b/libs/angular/src/images/cards/amex-dark.png new file mode 100644 index 0000000000..ac1b075975 Binary files /dev/null and b/libs/angular/src/images/cards/amex-dark.png differ diff --git a/libs/angular/src/images/cards/amex-light.png b/libs/angular/src/images/cards/amex-light.png new file mode 100644 index 0000000000..ac1b075975 Binary files /dev/null and b/libs/angular/src/images/cards/amex-light.png differ diff --git a/libs/angular/src/images/cards/diners_club-dark.png b/libs/angular/src/images/cards/diners_club-dark.png new file mode 100644 index 0000000000..a5d23233eb Binary files /dev/null and b/libs/angular/src/images/cards/diners_club-dark.png differ diff --git a/libs/angular/src/images/cards/diners_club-light.png b/libs/angular/src/images/cards/diners_club-light.png new file mode 100644 index 0000000000..e2e33a24ac Binary files /dev/null and b/libs/angular/src/images/cards/diners_club-light.png differ diff --git a/libs/angular/src/images/cards/discover-dark.png b/libs/angular/src/images/cards/discover-dark.png new file mode 100644 index 0000000000..2ed6f6f942 Binary files /dev/null and b/libs/angular/src/images/cards/discover-dark.png differ diff --git a/libs/angular/src/images/cards/discover-light.png b/libs/angular/src/images/cards/discover-light.png new file mode 100644 index 0000000000..755c6957c6 Binary files /dev/null and b/libs/angular/src/images/cards/discover-light.png differ diff --git a/libs/angular/src/images/cards/jcb-dark.png b/libs/angular/src/images/cards/jcb-dark.png new file mode 100644 index 0000000000..1cb484d91e Binary files /dev/null and b/libs/angular/src/images/cards/jcb-dark.png differ diff --git a/libs/angular/src/images/cards/jcb-light.png b/libs/angular/src/images/cards/jcb-light.png new file mode 100644 index 0000000000..2b89f5b9af Binary files /dev/null and b/libs/angular/src/images/cards/jcb-light.png differ diff --git a/libs/angular/src/images/cards/maestro-dark.png b/libs/angular/src/images/cards/maestro-dark.png new file mode 100644 index 0000000000..4a4879b56f Binary files /dev/null and b/libs/angular/src/images/cards/maestro-dark.png differ diff --git a/libs/angular/src/images/cards/maestro-light.png b/libs/angular/src/images/cards/maestro-light.png new file mode 100644 index 0000000000..2329738a19 Binary files /dev/null and b/libs/angular/src/images/cards/maestro-light.png differ diff --git a/libs/angular/src/images/cards/mastercard-dark.png b/libs/angular/src/images/cards/mastercard-dark.png new file mode 100644 index 0000000000..cd8062635d Binary files /dev/null and b/libs/angular/src/images/cards/mastercard-dark.png differ diff --git a/libs/angular/src/images/cards/mastercard-light.png b/libs/angular/src/images/cards/mastercard-light.png new file mode 100644 index 0000000000..f87ae25911 Binary files /dev/null and b/libs/angular/src/images/cards/mastercard-light.png differ diff --git a/libs/angular/src/images/cards/ru_pay-dark.png b/libs/angular/src/images/cards/ru_pay-dark.png new file mode 100644 index 0000000000..6bd6d039b8 Binary files /dev/null and b/libs/angular/src/images/cards/ru_pay-dark.png differ diff --git a/libs/angular/src/images/cards/ru_pay-light.png b/libs/angular/src/images/cards/ru_pay-light.png new file mode 100644 index 0000000000..321938ed71 Binary files /dev/null and b/libs/angular/src/images/cards/ru_pay-light.png differ diff --git a/libs/angular/src/images/cards/union_pay-dark.png b/libs/angular/src/images/cards/union_pay-dark.png new file mode 100644 index 0000000000..248be7c330 Binary files /dev/null and b/libs/angular/src/images/cards/union_pay-dark.png differ diff --git a/libs/angular/src/images/cards/union_pay-light.png b/libs/angular/src/images/cards/union_pay-light.png new file mode 100644 index 0000000000..2d75aa9070 Binary files /dev/null and b/libs/angular/src/images/cards/union_pay-light.png differ diff --git a/libs/angular/src/images/cards/visa-dark.png b/libs/angular/src/images/cards/visa-dark.png new file mode 100644 index 0000000000..0705b68e7d Binary files /dev/null and b/libs/angular/src/images/cards/visa-dark.png differ diff --git a/libs/angular/src/images/cards/visa-light.png b/libs/angular/src/images/cards/visa-light.png new file mode 100644 index 0000000000..3dc8ae5093 Binary files /dev/null and b/libs/angular/src/images/cards/visa-light.png differ diff --git a/libs/angular/src/interfaces/selectOptions.ts b/libs/angular/src/interfaces/selectOptions.ts new file mode 100644 index 0000000000..19da14d9f3 --- /dev/null +++ b/libs/angular/src/interfaces/selectOptions.ts @@ -0,0 +1,5 @@ +export interface SelectOptions { + name: string; + value: any; + disabled?: boolean; +} diff --git a/libs/angular/src/jslib.module.ts b/libs/angular/src/jslib.module.ts new file mode 100644 index 0000000000..f8dc5d0fea --- /dev/null +++ b/libs/angular/src/jslib.module.ts @@ -0,0 +1,103 @@ +import { CommonModule, DatePipe } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { FormsModule, ReactiveFormsModule } from "@angular/forms"; + +import { AvatarComponent } from "./components/avatar.component"; +import { CalloutComponent } from "./components/callout.component"; +import { ExportScopeCalloutComponent } from "./components/export-scope-callout.component"; +import { IconComponent } from "./components/icon.component"; +import { BitwardenToastModule } from "./components/toastr.component"; +import { A11yInvalidDirective } from "./directives/a11y-invalid.directive"; +import { A11yTitleDirective } from "./directives/a11y-title.directive"; +import { ApiActionDirective } from "./directives/api-action.directive"; +import { AutofocusDirective } from "./directives/autofocus.directive"; +import { BlurClickDirective } from "./directives/blur-click.directive"; +import { BoxRowDirective } from "./directives/box-row.directive"; +import { FallbackSrcDirective } from "./directives/fallback-src.directive"; +import { InputStripSpacesDirective } from "./directives/input-strip-spaces.directive"; +import { InputVerbatimDirective } from "./directives/input-verbatim.directive"; +import { NotPremiumDirective } from "./directives/not-premium.directive"; +import { SelectCopyDirective } from "./directives/select-copy.directive"; +import { StopClickDirective } from "./directives/stop-click.directive"; +import { StopPropDirective } from "./directives/stop-prop.directive"; +import { TrueFalseValueDirective } from "./directives/true-false-value.directive"; +import { ColorPasswordCountPipe } from "./pipes/color-password-count.pipe"; +import { ColorPasswordPipe } from "./pipes/color-password.pipe"; +import { CreditCardNumberPipe } from "./pipes/credit-card-number.pipe"; +import { EllipsisPipe } from "./pipes/ellipsis.pipe"; +import { I18nPipe } from "./pipes/i18n.pipe"; +import { SearchCiphersPipe } from "./pipes/search-ciphers.pipe"; +import { SearchPipe } from "./pipes/search.pipe"; +import { UserNamePipe } from "./pipes/user-name.pipe"; + +@NgModule({ + imports: [ + BitwardenToastModule.forRoot({ + maxOpened: 5, + autoDismiss: true, + closeButton: true, + }), + CommonModule, + FormsModule, + ReactiveFormsModule, + ], + declarations: [ + A11yInvalidDirective, + A11yTitleDirective, + ApiActionDirective, + AutofocusDirective, + AvatarComponent, + BlurClickDirective, + BoxRowDirective, + CalloutComponent, + ColorPasswordCountPipe, + ColorPasswordPipe, + CreditCardNumberPipe, + EllipsisPipe, + ExportScopeCalloutComponent, + FallbackSrcDirective, + I18nPipe, + IconComponent, + InputStripSpacesDirective, + InputVerbatimDirective, + NotPremiumDirective, + SearchCiphersPipe, + SearchPipe, + SelectCopyDirective, + StopClickDirective, + StopPropDirective, + TrueFalseValueDirective, + UserNamePipe, + ], + exports: [ + A11yInvalidDirective, + A11yTitleDirective, + ApiActionDirective, + AutofocusDirective, + AvatarComponent, + BitwardenToastModule, + BlurClickDirective, + BoxRowDirective, + CalloutComponent, + ColorPasswordCountPipe, + ColorPasswordPipe, + CreditCardNumberPipe, + EllipsisPipe, + ExportScopeCalloutComponent, + FallbackSrcDirective, + I18nPipe, + IconComponent, + InputStripSpacesDirective, + InputVerbatimDirective, + NotPremiumDirective, + SearchCiphersPipe, + SearchPipe, + SelectCopyDirective, + StopClickDirective, + StopPropDirective, + TrueFalseValueDirective, + UserNamePipe, + ], + providers: [CreditCardNumberPipe, DatePipe, I18nPipe, SearchPipe, UserNamePipe], +}) +export class JslibModule {} diff --git a/libs/angular/src/modules/vault-filter/components/collection-filter.component.ts b/libs/angular/src/modules/vault-filter/components/collection-filter.component.ts new file mode 100644 index 0000000000..67a21200a5 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/components/collection-filter.component.ts @@ -0,0 +1,51 @@ +import { Directive, EventEmitter, Input, Output } from "@angular/core"; + +import { ITreeNodeObject } from "jslib-common/models/domain/treeNode"; +import { CollectionView } from "jslib-common/models/view/collectionView"; + +import { DynamicTreeNode } from "../models/dynamic-tree-node.model"; +import { TopLevelTreeNode } from "../models/top-level-tree-node.model"; +import { VaultFilter } from "../models/vault-filter.model"; + +@Directive() +export class CollectionFilterComponent { + @Input() hide = false; + @Input() collapsedFilterNodes: Set; + @Input() collectionNodes: DynamicTreeNode; + @Input() activeFilter: VaultFilter; + + @Output() onNodeCollapseStateChange: EventEmitter = + new EventEmitter(); + @Output() onFilterChange: EventEmitter = new EventEmitter(); + + readonly collectionsGrouping: TopLevelTreeNode = { + id: "collections", + name: "collections", + }; + + get collections() { + return this.collectionNodes?.fullList; + } + + get nestedCollections() { + return this.collectionNodes?.nestedList; + } + + get show() { + return !this.hide && this.collections != null && this.collections.length > 0; + } + + isCollapsed(node: ITreeNodeObject) { + return this.collapsedFilterNodes.has(node.id); + } + + applyFilter(collection: CollectionView) { + this.activeFilter.resetFilter(); + this.activeFilter.selectedCollectionId = collection.id; + this.onFilterChange.emit(this.activeFilter); + } + + async toggleCollapse(node: ITreeNodeObject) { + this.onNodeCollapseStateChange.emit(node); + } +} diff --git a/libs/angular/src/modules/vault-filter/components/folder-filter.component.ts b/libs/angular/src/modules/vault-filter/components/folder-filter.component.ts new file mode 100644 index 0000000000..fe9537a705 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/components/folder-filter.component.ts @@ -0,0 +1,58 @@ +import { Directive, EventEmitter, Input, Output } from "@angular/core"; + +import { ITreeNodeObject } from "jslib-common/models/domain/treeNode"; +import { FolderView } from "jslib-common/models/view/folderView"; + +import { DynamicTreeNode } from "../models/dynamic-tree-node.model"; +import { TopLevelTreeNode } from "../models/top-level-tree-node.model"; +import { VaultFilter } from "../models/vault-filter.model"; + +@Directive() +export class FolderFilterComponent { + @Input() hide = false; + @Input() collapsedFilterNodes: Set; + @Input() folderNodes: DynamicTreeNode; + @Input() activeFilter: VaultFilter; + + @Output() onNodeCollapseStateChange: EventEmitter = + new EventEmitter(); + @Output() onFilterChange: EventEmitter = new EventEmitter(); + @Output() onAddFolder = new EventEmitter(); + @Output() onEditFolder = new EventEmitter(); + + get folders() { + return this.folderNodes?.fullList; + } + + get nestedFolders() { + return this.folderNodes?.nestedList; + } + + readonly foldersGrouping: TopLevelTreeNode = { + id: "folders", + name: "folders", + }; + + applyFilter(folder: FolderView) { + this.activeFilter.resetFilter(); + this.activeFilter.selectedFolder = true; + this.activeFilter.selectedFolderId = folder.id; + this.onFilterChange.emit(this.activeFilter); + } + + addFolder() { + this.onAddFolder.emit(); + } + + editFolder(folder: FolderView) { + this.onEditFolder.emit(folder); + } + + isCollapsed(node: ITreeNodeObject) { + return this.collapsedFilterNodes.has(node.id); + } + + async toggleCollapse(node: ITreeNodeObject) { + this.onNodeCollapseStateChange.emit(node); + } +} diff --git a/libs/angular/src/modules/vault-filter/components/organization-filter.component.ts b/libs/angular/src/modules/vault-filter/components/organization-filter.component.ts new file mode 100644 index 0000000000..79c2c95516 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/components/organization-filter.component.ts @@ -0,0 +1,78 @@ +import { Directive, EventEmitter, Input, Output } from "@angular/core"; + +import { Organization } from "jslib-common/models/domain/organization"; +import { ITreeNodeObject } from "jslib-common/models/domain/treeNode"; + +import { DisplayMode } from "../models/display-mode"; +import { TopLevelTreeNode } from "../models/top-level-tree-node.model"; +import { VaultFilter } from "../models/vault-filter.model"; + +@Directive() +export class OrganizationFilterComponent { + @Input() hide = false; + @Input() collapsedFilterNodes: Set; + @Input() organizations: Organization[]; + @Input() activeFilter: VaultFilter; + @Input() activePersonalOwnershipPolicy: boolean; + @Input() activeSingleOrganizationPolicy: boolean; + + @Output() onNodeCollapseStateChange: EventEmitter = + new EventEmitter(); + @Output() onFilterChange: EventEmitter = new EventEmitter(); + + get displayMode(): DisplayMode { + let displayMode: DisplayMode = "organizationMember"; + if (this.organizations == null || this.organizations.length < 1) { + displayMode = "noOrganizations"; + } else if (this.activePersonalOwnershipPolicy && !this.activeSingleOrganizationPolicy) { + displayMode = "personalOwnershipPolicy"; + } else if (!this.activePersonalOwnershipPolicy && this.activeSingleOrganizationPolicy) { + displayMode = "singleOrganizationPolicy"; + } else if (this.activePersonalOwnershipPolicy && this.activeSingleOrganizationPolicy) { + displayMode = "singleOrganizationAndPersonalOwnershipPolicies"; + } + + return displayMode; + } + + get hasActiveFilter() { + return this.activeFilter.myVaultOnly || this.activeFilter.selectedOrganizationId != null; + } + + readonly organizationGrouping: TopLevelTreeNode = { + id: "vaults", + name: "allVaults", + }; + + async applyOrganizationFilter(organization: Organization) { + this.activeFilter.selectedOrganizationId = organization.id; + this.activeFilter.myVaultOnly = false; + this.activeFilter.refreshCollectionsAndFolders = true; + this.applyFilter(this.activeFilter); + } + + async applyMyVaultFilter() { + this.activeFilter.selectedOrganizationId = null; + this.activeFilter.myVaultOnly = true; + this.activeFilter.refreshCollectionsAndFolders = true; + this.applyFilter(this.activeFilter); + } + + clearFilter() { + this.activeFilter.myVaultOnly = false; + this.activeFilter.selectedOrganizationId = null; + this.applyFilter(new VaultFilter(this.activeFilter)); + } + + private applyFilter(filter: VaultFilter) { + this.onFilterChange.emit(filter); + } + + async toggleCollapse() { + this.onNodeCollapseStateChange.emit(this.organizationGrouping); + } + + get isCollapsed() { + return this.collapsedFilterNodes.has(this.organizationGrouping.id); + } +} diff --git a/libs/angular/src/modules/vault-filter/components/status-filter.component.ts b/libs/angular/src/modules/vault-filter/components/status-filter.component.ts new file mode 100644 index 0000000000..db77382543 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/components/status-filter.component.ts @@ -0,0 +1,22 @@ +import { Directive, EventEmitter, Input, Output } from "@angular/core"; + +import { CipherStatus } from "../models/cipher-status.model"; +import { VaultFilter } from "../models/vault-filter.model"; + +@Directive() +export class StatusFilterComponent { + @Input() hideFavorites = false; + @Input() hideTrash = false; + @Output() onFilterChange: EventEmitter = new EventEmitter(); + @Input() activeFilter: VaultFilter; + + get show() { + return !(this.hideFavorites && this.hideTrash); + } + + applyFilter(cipherStatus: CipherStatus) { + this.activeFilter.resetFilter(); + this.activeFilter.status = cipherStatus; + this.onFilterChange.emit(this.activeFilter); + } +} diff --git a/libs/angular/src/modules/vault-filter/components/type-filter.component.ts b/libs/angular/src/modules/vault-filter/components/type-filter.component.ts new file mode 100644 index 0000000000..49aeaa81ff --- /dev/null +++ b/libs/angular/src/modules/vault-filter/components/type-filter.component.ts @@ -0,0 +1,40 @@ +import { Directive, EventEmitter, Input, Output } from "@angular/core"; + +import { CipherType } from "jslib-common/enums/cipherType"; +import { ITreeNodeObject } from "jslib-common/models/domain/treeNode"; + +import { TopLevelTreeNode } from "../models/top-level-tree-node.model"; +import { VaultFilter } from "../models/vault-filter.model"; + +@Directive() +export class TypeFilterComponent { + @Input() hide = false; + @Input() collapsedFilterNodes: Set; + @Input() selectedCipherType: CipherType = null; + @Input() activeFilter: VaultFilter; + + @Output() onNodeCollapseStateChange: EventEmitter = + new EventEmitter(); + @Output() onFilterChange: EventEmitter = new EventEmitter(); + + readonly typesNode: TopLevelTreeNode = { + id: "types", + name: "types", + }; + + cipherTypeEnum = CipherType; // used in the template + + get isCollapsed() { + return this.collapsedFilterNodes.has(this.typesNode.id); + } + + applyFilter(cipherType: CipherType) { + this.activeFilter.resetFilter(); + this.activeFilter.cipherType = cipherType; + this.onFilterChange.emit(this.activeFilter); + } + + async toggleCollapse() { + this.onNodeCollapseStateChange.emit(this.typesNode); + } +} diff --git a/libs/angular/src/modules/vault-filter/models/cipher-status.model.ts b/libs/angular/src/modules/vault-filter/models/cipher-status.model.ts new file mode 100644 index 0000000000..f93cd8b210 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/models/cipher-status.model.ts @@ -0,0 +1 @@ +export type CipherStatus = "all" | "favorites" | "trash"; diff --git a/libs/angular/src/modules/vault-filter/models/display-mode.ts b/libs/angular/src/modules/vault-filter/models/display-mode.ts new file mode 100644 index 0000000000..3395df4fbe --- /dev/null +++ b/libs/angular/src/modules/vault-filter/models/display-mode.ts @@ -0,0 +1,6 @@ +export type DisplayMode = + | "noOrganizations" + | "organizationMember" + | "singleOrganizationPolicy" + | "personalOwnershipPolicy" + | "singleOrganizationAndPersonalOwnershipPolicies"; diff --git a/libs/angular/src/modules/vault-filter/models/dynamic-tree-node.model.ts b/libs/angular/src/modules/vault-filter/models/dynamic-tree-node.model.ts new file mode 100644 index 0000000000..d63a518f7c --- /dev/null +++ b/libs/angular/src/modules/vault-filter/models/dynamic-tree-node.model.ts @@ -0,0 +1,16 @@ +import { TreeNode } from "jslib-common/models/domain/treeNode"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; + +export class DynamicTreeNode { + fullList: T[]; + nestedList: TreeNode[]; + + hasId(id: string): boolean { + return this.fullList != null && this.fullList.filter((i: T) => i.id === id).length > 0; + } + + constructor(init?: Partial>) { + Object.assign(this, init); + } +} diff --git a/libs/angular/src/modules/vault-filter/models/top-level-tree-node.model.ts b/libs/angular/src/modules/vault-filter/models/top-level-tree-node.model.ts new file mode 100644 index 0000000000..3e9870de2d --- /dev/null +++ b/libs/angular/src/modules/vault-filter/models/top-level-tree-node.model.ts @@ -0,0 +1,7 @@ +import { ITreeNodeObject } from "jslib-common/models/domain/treeNode"; + +export type TopLevelTreeNodeId = "vaults" | "types" | "collections" | "folders"; +export class TopLevelTreeNode implements ITreeNodeObject { + id: TopLevelTreeNodeId; + name: string; // localizationString +} diff --git a/libs/angular/src/modules/vault-filter/models/vault-filter.model.ts b/libs/angular/src/modules/vault-filter/models/vault-filter.model.ts new file mode 100644 index 0000000000..b65729c583 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/models/vault-filter.model.ts @@ -0,0 +1,32 @@ +import { CipherType } from "jslib-common/enums/cipherType"; + +import { CipherStatus } from "./cipher-status.model"; + +export class VaultFilter { + cipherType?: CipherType; + selectedCollectionId?: string; + status?: CipherStatus; + selectedFolder = false; // This is needed because of how the "No Folder" folder works. It has a null id. + selectedFolderId?: string; + selectedOrganizationId?: string; + myVaultOnly = false; + refreshCollectionsAndFolders = false; + + constructor(init?: Partial) { + Object.assign(this, init); + } + + resetFilter() { + this.cipherType = null; + this.status = null; + this.selectedCollectionId = null; + this.selectedFolder = false; + this.selectedFolderId = null; + } + + resetOrganization() { + this.myVaultOnly = false; + this.selectedOrganizationId = null; + this.resetFilter(); + } +} diff --git a/libs/angular/src/modules/vault-filter/vault-filter.component.ts b/libs/angular/src/modules/vault-filter/vault-filter.component.ts new file mode 100644 index 0000000000..e717f5c975 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/vault-filter.component.ts @@ -0,0 +1,121 @@ +import { Directive, EventEmitter, Input, OnInit, Output } from "@angular/core"; + +import { Organization } from "jslib-common/models/domain/organization"; +import { ITreeNodeObject } from "jslib-common/models/domain/treeNode"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; + +import { DynamicTreeNode } from "./models/dynamic-tree-node.model"; +import { VaultFilter } from "./models/vault-filter.model"; +import { VaultFilterService } from "./vault-filter.service"; + +@Directive() +export class VaultFilterComponent implements OnInit { + @Input() activeFilter: VaultFilter = new VaultFilter(); + @Input() hideFolders = false; + @Input() hideCollections = false; + @Input() hideFavorites = false; + @Input() hideTrash = false; + @Input() hideOrganizations = false; + + @Output() onFilterChange = new EventEmitter(); + @Output() onAddFolder = new EventEmitter(); + @Output() onEditFolder = new EventEmitter(); + + isLoaded = false; + collapsedFilterNodes: Set; + organizations: Organization[]; + activePersonalOwnershipPolicy: boolean; + activeSingleOrganizationPolicy: boolean; + collections: DynamicTreeNode; + folders: DynamicTreeNode; + + constructor(protected vaultFilterService: VaultFilterService) {} + + get displayCollections() { + return this.collections?.fullList != null && this.collections.fullList.length > 0; + } + + async ngOnInit(): Promise { + this.collapsedFilterNodes = await this.vaultFilterService.buildCollapsedFilterNodes(); + this.organizations = await this.vaultFilterService.buildOrganizations(); + if (this.organizations != null && this.organizations.length > 0) { + this.activePersonalOwnershipPolicy = + await this.vaultFilterService.checkForPersonalOwnershipPolicy(); + this.activeSingleOrganizationPolicy = + await this.vaultFilterService.checkForSingleOrganizationPolicy(); + } + this.folders = await this.vaultFilterService.buildFolders(); + this.collections = await this.initCollections(); + this.isLoaded = true; + } + + // overwritten in web for organization vaults + async initCollections() { + return await this.vaultFilterService.buildCollections(); + } + + async toggleFilterNodeCollapseState(node: ITreeNodeObject) { + if (this.collapsedFilterNodes.has(node.id)) { + this.collapsedFilterNodes.delete(node.id); + } else { + this.collapsedFilterNodes.add(node.id); + } + await this.vaultFilterService.storeCollapsedFilterNodes(this.collapsedFilterNodes); + } + + async applyFilter(filter: VaultFilter) { + if (filter.refreshCollectionsAndFolders) { + await this.reloadCollectionsAndFolders(filter); + filter = this.pruneInvalidatedFilterSelections(filter); + } + this.onFilterChange.emit(filter); + } + + async reloadCollectionsAndFolders(filter: VaultFilter) { + this.folders = await this.vaultFilterService.buildFolders(filter.selectedOrganizationId); + this.collections = filter.myVaultOnly + ? null + : await this.vaultFilterService.buildCollections(filter.selectedOrganizationId); + } + + async reloadOrganizations() { + this.organizations = await this.vaultFilterService.buildOrganizations(); + this.activePersonalOwnershipPolicy = + await this.vaultFilterService.checkForPersonalOwnershipPolicy(); + this.activeSingleOrganizationPolicy = + await this.vaultFilterService.checkForSingleOrganizationPolicy(); + } + + addFolder() { + this.onAddFolder.emit(); + } + + editFolder(folder: FolderView) { + this.onEditFolder.emit(folder); + } + + protected pruneInvalidatedFilterSelections(filter: VaultFilter): VaultFilter { + filter = this.pruneInvalidFolderSelection(filter); + filter = this.pruneInvalidCollectionSelection(filter); + return filter; + } + + protected pruneInvalidFolderSelection(filter: VaultFilter): VaultFilter { + if (filter.selectedFolder && !this.folders?.hasId(filter.selectedFolderId)) { + filter.selectedFolder = false; + filter.selectedFolderId = null; + } + return filter; + } + + protected pruneInvalidCollectionSelection(filter: VaultFilter): VaultFilter { + if ( + filter.selectedCollectionId != null && + !this.collections?.hasId(filter.selectedCollectionId) + ) { + filter.selectedCollectionId = null; + } + return filter; + } +} diff --git a/libs/angular/src/modules/vault-filter/vault-filter.service.ts b/libs/angular/src/modules/vault-filter/vault-filter.service.ts new file mode 100644 index 0000000000..b05cce1742 --- /dev/null +++ b/libs/angular/src/modules/vault-filter/vault-filter.service.ts @@ -0,0 +1,82 @@ +import { Injectable } from "@angular/core"; + +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { OrganizationService } from "jslib-common/abstractions/organization.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { PolicyType } from "jslib-common/enums/policyType"; +import { Organization } from "jslib-common/models/domain/organization"; +import { CollectionView } from "jslib-common/models/view/collectionView"; +import { FolderView } from "jslib-common/models/view/folderView"; + +import { DynamicTreeNode } from "./models/dynamic-tree-node.model"; + +@Injectable() +export class VaultFilterService { + constructor( + protected stateService: StateService, + protected organizationService: OrganizationService, + protected folderService: FolderService, + protected cipherService: CipherService, + protected collectionService: CollectionService, + protected policyService: PolicyService + ) {} + + async storeCollapsedFilterNodes(collapsedFilterNodes: Set): Promise { + await this.stateService.setCollapsedGroupings(Array.from(collapsedFilterNodes)); + } + + async buildCollapsedFilterNodes(): Promise> { + return new Set(await this.stateService.getCollapsedGroupings()); + } + + async buildOrganizations(): Promise { + return await this.organizationService.getAll(); + } + + async buildFolders(organizationId?: string): Promise> { + const storedFolders = await this.folderService.getAllDecrypted(); + let folders: FolderView[]; + if (organizationId != null) { + const ciphers = await this.cipherService.getAllDecrypted(); + const orgCiphers = ciphers.filter((c) => c.organizationId == organizationId); + folders = storedFolders.filter( + (f) => + orgCiphers.filter((oc) => oc.folderId == f.id).length > 0 || + ciphers.filter((c) => c.folderId == f.id).length < 1 + ); + } else { + folders = storedFolders; + } + const nestedFolders = await this.folderService.getAllNested(folders); + return new DynamicTreeNode({ + fullList: folders, + nestedList: nestedFolders, + }); + } + + async buildCollections(organizationId?: string): Promise> { + const storedCollections = await this.collectionService.getAllDecrypted(); + let collections: CollectionView[]; + if (organizationId != null) { + collections = storedCollections.filter((c) => c.organizationId === organizationId); + } else { + collections = storedCollections; + } + const nestedCollections = await this.collectionService.getAllNested(collections); + return new DynamicTreeNode({ + fullList: collections, + nestedList: nestedCollections, + }); + } + + async checkForSingleOrganizationPolicy(): Promise { + return await this.policyService.policyAppliesToUser(PolicyType.SingleOrg); + } + + async checkForPersonalOwnershipPolicy(): Promise { + return await this.policyService.policyAppliesToUser(PolicyType.PersonalOwnership); + } +} diff --git a/libs/angular/src/pipes/color-password-count.pipe.ts b/libs/angular/src/pipes/color-password-count.pipe.ts new file mode 100644 index 0000000000..9890a3408c --- /dev/null +++ b/libs/angular/src/pipes/color-password-count.pipe.ts @@ -0,0 +1,19 @@ +import { Pipe } from "@angular/core"; + +import { ColorPasswordPipe } from "./color-password.pipe"; + +/* + An updated pipe that extends ColourPasswordPipe to include a character count +*/ +@Pipe({ name: "colorPasswordCount" }) +export class ColorPasswordCountPipe extends ColorPasswordPipe { + transform(password: string) { + const template = (character: string, type: string, index: number) => + ` + ${character}${index + 1} + `; + const colorizedPasswordCount = this.generateTemplate(password, template); + + return colorizedPasswordCount; + } +} diff --git a/libs/angular/src/pipes/color-password.pipe.ts b/libs/angular/src/pipes/color-password.pipe.ts new file mode 100644 index 0000000000..1b3d607203 --- /dev/null +++ b/libs/angular/src/pipes/color-password.pipe.ts @@ -0,0 +1,61 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +import { Utils } from "jslib-common/misc/utils"; + +/* + An updated pipe that sanitizes HTML, highlights numbers and special characters (in different colors each) + and handles Unicode / Emoji characters correctly. +*/ +@Pipe({ name: "colorPassword" }) +export class ColorPasswordPipe implements PipeTransform { + transform(password: string) { + const template = (character: string, type: string) => + `${character}`; + const colorizedPassword = this.generateTemplate(password, template); + return colorizedPassword; + } + + protected generateTemplate( + password: string, + templateGenerator: (chararacter: string, type: string, index?: number) => string + ) { + // Convert to an array to handle cases that stings have special characters, ie: emoji. + const passwordArray = Array.from(password); + let colorizedPassword = ""; + for (let i = 0; i < passwordArray.length; i++) { + let character = passwordArray[i]; + let isSpecial = false; + // Sanitize HTML first. + switch (character) { + case "&": + character = "&"; + isSpecial = true; + break; + case "<": + character = "<"; + isSpecial = true; + break; + case ">": + character = ">"; + isSpecial = true; + break; + case " ": + character = " "; + isSpecial = true; + break; + default: + break; + } + let type = "letter"; + if (character.match(Utils.regexpEmojiPresentation)) { + type = "emoji"; + } else if (isSpecial || character.match(/[^\w ]/)) { + type = "special"; + } else if (character.match(/\d/)) { + type = "number"; + } + colorizedPassword += templateGenerator(character, type, i); + } + return colorizedPassword; + } +} diff --git a/libs/angular/src/pipes/credit-card-number.pipe.ts b/libs/angular/src/pipes/credit-card-number.pipe.ts new file mode 100644 index 0000000000..11500ef951 --- /dev/null +++ b/libs/angular/src/pipes/credit-card-number.pipe.ts @@ -0,0 +1,64 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +interface CardRuleEntry { + cardLength: number; + blocks: number[]; +} + +// See https://baymard.com/checkout-usability/credit-card-patterns for +// all possible credit card spacing patterns. For now, we just handle +// the below. +const numberFormats: Record = { + Visa: [{ cardLength: 16, blocks: [4, 4, 4, 4] }], + Mastercard: [{ cardLength: 16, blocks: [4, 4, 4, 4] }], + Maestro: [ + { cardLength: 16, blocks: [4, 4, 4, 4] }, + { cardLength: 13, blocks: [4, 4, 5] }, + { cardLength: 15, blocks: [4, 6, 5] }, + { cardLength: 19, blocks: [4, 4, 4, 4, 3] }, + ], + Discover: [{ cardLength: 16, blocks: [4, 4, 4, 4] }], + "Diners Club": [{ cardLength: 14, blocks: [4, 6, 4] }], + JCB: [{ cardLength: 16, blocks: [4, 4, 4, 4] }], + UnionPay: [ + { cardLength: 16, blocks: [4, 4, 4, 4] }, + { cardLength: 19, blocks: [6, 13] }, + ], + Amex: [{ cardLength: 15, blocks: [4, 6, 5] }], + Other: [{ cardLength: 16, blocks: [4, 4, 4, 4] }], +}; + +@Pipe({ name: "creditCardNumber" }) +export class CreditCardNumberPipe implements PipeTransform { + transform(creditCardNumber: string, brand: string): string { + let rules = numberFormats[brand]; + + if (rules == null) { + rules = numberFormats["Other"]; + } + + const cardLength = creditCardNumber.length; + + let matchingRule = rules.find((r) => r.cardLength == cardLength); + if (matchingRule == null) { + matchingRule = rules[0]; + } + + const blocks = matchingRule.blocks; + + const chunks: string[] = []; + let total = 0; + + blocks.forEach((c) => { + chunks.push(creditCardNumber.slice(total, total + c)); + total += c; + }); + + // Append the remaining part + if (cardLength > total) { + chunks.push(creditCardNumber.slice(total)); + } + + return chunks.join(" "); + } +} diff --git a/libs/angular/src/pipes/ellipsis.pipe.ts b/libs/angular/src/pipes/ellipsis.pipe.ts new file mode 100644 index 0000000000..081dba11ab --- /dev/null +++ b/libs/angular/src/pipes/ellipsis.pipe.ts @@ -0,0 +1,17 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +@Pipe({ + name: "ellipsis", +}) +export class EllipsisPipe implements PipeTransform { + transform(value: string, limit = 25, completeWords = false, ellipsis = "...") { + if (value.length <= limit) { + return value; + } + limit -= ellipsis.length; + if (completeWords && value.length > limit && value.indexOf(" ") > 0) { + limit = value.substring(0, limit).lastIndexOf(" "); + } + return value.substring(0, limit) + ellipsis; + } +} diff --git a/libs/angular/src/pipes/i18n.pipe.ts b/libs/angular/src/pipes/i18n.pipe.ts new file mode 100644 index 0000000000..8fc09434c4 --- /dev/null +++ b/libs/angular/src/pipes/i18n.pipe.ts @@ -0,0 +1,14 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +@Pipe({ + name: "i18n", +}) +export class I18nPipe implements PipeTransform { + constructor(private i18nService: I18nService) {} + + transform(id: string, p1?: string, p2?: string, p3?: string): string { + return this.i18nService.t(id, p1, p2, p3); + } +} diff --git a/libs/angular/src/pipes/search-ciphers.pipe.ts b/libs/angular/src/pipes/search-ciphers.pipe.ts new file mode 100644 index 0000000000..e8bdd13e68 --- /dev/null +++ b/libs/angular/src/pipes/search-ciphers.pipe.ts @@ -0,0 +1,41 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +import { CipherView } from "jslib-common/models/view/cipherView"; + +@Pipe({ + name: "searchCiphers", +}) +export class SearchCiphersPipe implements PipeTransform { + transform(ciphers: CipherView[], searchText: string, deleted = false): CipherView[] { + if (ciphers == null || ciphers.length === 0) { + return []; + } + + if (searchText == null || searchText.length < 2) { + return ciphers.filter((c) => { + return deleted !== c.isDeleted; + }); + } + + searchText = searchText.trim().toLowerCase(); + return ciphers.filter((c) => { + if (deleted !== c.isDeleted) { + return false; + } + if (c.name != null && c.name.toLowerCase().indexOf(searchText) > -1) { + return true; + } + if (searchText.length >= 8 && c.id.startsWith(searchText)) { + return true; + } + if (c.subTitle != null && c.subTitle.toLowerCase().indexOf(searchText) > -1) { + return true; + } + if (c.login && c.login.uri != null && c.login.uri.toLowerCase().indexOf(searchText) > -1) { + return true; + } + + return false; + }); + } +} diff --git a/libs/angular/src/pipes/search.pipe.ts b/libs/angular/src/pipes/search.pipe.ts new file mode 100644 index 0000000000..bf09d2def8 --- /dev/null +++ b/libs/angular/src/pipes/search.pipe.ts @@ -0,0 +1,48 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +@Pipe({ + name: "search", +}) +export class SearchPipe implements PipeTransform { + transform( + items: any[], + searchText: string, + prop1?: string, + prop2?: string, + prop3?: string + ): any[] { + if (items == null || items.length === 0) { + return []; + } + + if (searchText == null || searchText.length < 2) { + return items; + } + + searchText = searchText.trim().toLowerCase(); + return items.filter((i) => { + if ( + prop1 != null && + i[prop1] != null && + i[prop1].toString().toLowerCase().indexOf(searchText) > -1 + ) { + return true; + } + if ( + prop2 != null && + i[prop2] != null && + i[prop2].toString().toLowerCase().indexOf(searchText) > -1 + ) { + return true; + } + if ( + prop3 != null && + i[prop3] != null && + i[prop3].toString().toLowerCase().indexOf(searchText) > -1 + ) { + return true; + } + return false; + }); + } +} diff --git a/libs/angular/src/pipes/user-name.pipe.ts b/libs/angular/src/pipes/user-name.pipe.ts new file mode 100644 index 0000000000..22c214e41e --- /dev/null +++ b/libs/angular/src/pipes/user-name.pipe.ts @@ -0,0 +1,19 @@ +import { Pipe, PipeTransform } from "@angular/core"; + +interface User { + name?: string; + email: string; +} + +@Pipe({ + name: "userName", +}) +export class UserNamePipe implements PipeTransform { + transform(user?: User): string { + if (user == null) { + return null; + } + + return user.name == null || user.name.trim() === "" ? user.email : user.name; + } +} diff --git a/libs/angular/src/scss/bwicons/fonts/bwi-font.svg b/libs/angular/src/scss/bwicons/fonts/bwi-font.svg new file mode 100644 index 0000000000..f92a4df342 --- /dev/null +++ b/libs/angular/src/scss/bwicons/fonts/bwi-font.svg @@ -0,0 +1,178 @@ + + + + + + +{ + "fontFamily": "bwi-font", + "designer": "Bitwarden, Inc.", + "designerURL": "", + "description": "Font generated by IcoMoon.", + "copyright": "Bitwarden, Inc.", + "majorVersion": 1, + "minorVersion": 0, + "version": "Version 1.0", + "fontId": "bwi-font", + "psName": "bwi-font", + "subFamily": "Regular", + "fullName": "bwi-font" +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/angular/src/scss/bwicons/fonts/bwi-font.ttf b/libs/angular/src/scss/bwicons/fonts/bwi-font.ttf new file mode 100644 index 0000000000..7c7afd4cdb Binary files /dev/null and b/libs/angular/src/scss/bwicons/fonts/bwi-font.ttf differ diff --git a/libs/angular/src/scss/bwicons/fonts/bwi-font.woff b/libs/angular/src/scss/bwicons/fonts/bwi-font.woff new file mode 100644 index 0000000000..b5e524cd57 Binary files /dev/null and b/libs/angular/src/scss/bwicons/fonts/bwi-font.woff differ diff --git a/libs/angular/src/scss/bwicons/fonts/bwi-font.woff2 b/libs/angular/src/scss/bwicons/fonts/bwi-font.woff2 new file mode 100644 index 0000000000..fee96f92cc Binary files /dev/null and b/libs/angular/src/scss/bwicons/fonts/bwi-font.woff2 differ diff --git a/libs/angular/src/scss/bwicons/styles/style.scss b/libs/angular/src/scss/bwicons/styles/style.scss new file mode 100644 index 0000000000..86c99f5911 --- /dev/null +++ b/libs/angular/src/scss/bwicons/styles/style.scss @@ -0,0 +1,255 @@ +$icomoon-font-family: "bwi-font" !default; +$icomoon-font-path: "~@bitwarden/jslib-angular/src/scss/bwicons/fonts/" !default; + +// New font sheet? Update the font-face information below +@font-face { + font-family: "#{$icomoon-font-family}"; + src: url($icomoon-font-path + "bwi-font.svg") format("svg"), + url($icomoon-font-path + "bwi-font.ttf") format("truetype"), + url($icomoon-font-path + "bwi-font.woff") format("woff"), + url($icomoon-font-path + "bwi-font.woff2") format("woff2"); + font-weight: normal; + font-style: normal; + font-display: block; +} + +// Base Class +.bwi { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: "#{$icomoon-font-family}" !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + display: inline-block; + /* Better Font Rendering */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +// Fixed Width Icons +.bwi-fw { + width: calc(18em / 14); + text-align: center; +} + +// Sizing Changes +.bwi-sm { + font-size: 0.875em; +} + +.bwi-lg { + font-size: calc(4em / 3); + line-height: calc(3em / 4); + vertical-align: -15%; +} + +.bwi-2x { + font-size: 2em; +} + +.bwi-3x { + font-size: 3em; +} + +.bwi-4x { + font-size: 4em; +} + +// Spin Animations +.bwi-spin { + animation: bwi-spin 2s infinite linear; +} + +@keyframes bwi-spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(359deg); + } +} + +// List Icons +.bwi-ul { + padding-left: 0; + margin-left: calc(30em / 14); + list-style-type: none; + > li { + position: relative; + } +} + +.bwi-li { + position: absolute; + left: calc(-30em / 14); + width: calc(30em / 14); + top: calc(2em / 14); + text-align: center; + &.bwi-lg { + left: calc(-30em / 14) + calc(4em / 14); + } +} + +// Rotation +.bwi-rotate-270 { + transform: rotate(270deg); +} + +// For new icons - add their glyph name and value to the map below +$icons: ( + "universal-access": "\e991", + "save-changes": "\e988", + "browser": "\e985", + "mobile": "\e986", + "cli": "\e987", + "providers": "\e983", + "vault": "\e984", + "folder-closed-f": "\e982", + "rocket": "\e9ee", + "ellipsis-h": "\e9ef", + "ellipsis-v": "\e9f0", + "safari": "\e974", + "opera": "\e975", + "firefox": "\e976", + "edge": "\e977", + "chrome": "\e978", + "star-f": "\e979", + "arrow-circle-up": "\e97a", + "arrow-circle-right": "\e97b", + "arrow-circle-left": "\e97c", + "arrow-circle-down": "\e97d", + "undo": "\e97e", + "bolt": "\e97f", + "puzzle": "\e980", + "rss": "\e973", + "dbl-angle-left": "\e970", + "dbl-angle-right": "\e971", + "hamburger": "\e972", + "bw-folder-open-f": "\e93e", + "desktop": "\e96a", + "angle-left": "\e96b", + "user": "\e900", + "user-f": "\e901", + "key": "\e902", + "share-square": "\e903", + "hashtag": "\e904", + "clone": "\e905", + "list-alt": "\e906", + "id-card": "\e907", + "credit-card": "\e908", + "globe": "\e909", + "sticky-note": "\e90a", + "folder": "\e90b", + "lock": "\e90c", + "lock-f": "\e90d", + "generate": "\e90e", + "generate-f": "\e90f", + "cog": "\e910", + "cog-f": "\e911", + "check-circle": "\e912", + "eye": "\e913", + "pencil-square": "\e914", + "bookmark": "\e915", + "files": "\e916", + "trash": "\e917", + "plus": "\e918", + "star": "\e919", + "list": "\e91a", + "angle-right": "\e91b", + "external-link": "\e91c", + "refresh": "\e91d", + "search": "\e91f", + "filter": "\e920", + "plus-circle": "\e921", + "user-circle": "\e922", + "question-circle": "\e923", + "cogs": "\e924", + "minus-circle": "\e925", + "send": "\e926", + "send-f": "\e927", + "download": "\e928", + "pencil": "\e929", + "sign-out": "\e92a", + "share": "\e92b", + "clock": "\e92c", + "angle-down": "\e92d", + "caret-down": "\e92e", + "square": "\e92f", + "collection": "\e930", + "bank": "\e931", + "shield": "\e932", + "stop": "\e933", + "plus-square": "\e934", + "save": "\e935", + "sign-in": "\e936", + "spinner": "\e937", + "dollar": "\e939", + "check": "\e93a", + "check-square": "\e93b", + "minus-square": "\e93c", + "close": "\e93d", + "share-arrow": "\e96c", + "paperclip": "\e93f", + "bitcoin": "\e940", + "cut": "\e941", + "frown": "\e942", + "folder-open": "\e943", + "bug": "\e946", + "chain-broken": "\e947", + "dashboard": "\e948", + "envelope": "\e949", + "exclamation-circle": "\e94a", + "exclamation-triangle": "\e94b", + "caret-right": "\e94c", + "file-pdf": "\e94e", + "file-text": "\e94f", + "info-circle": "\e952", + "lightbulb": "\e953", + "link": "\e954", + "linux": "\e956", + "long-arrow-right": "\e957", + "money": "\e958", + "play": "\e959", + "reddit": "\e95a", + "refresh-tab": "\e95b", + "sitemap": "\e95c", + "sliders": "\e95d", + "tag": "\e95e", + "thumb-tack": "\e95f", + "thumbs-up": "\e960", + "unlock": "\e962", + "users": "\e963", + "wrench": "\e965", + "ban": "\e967", + "camera": "\e968", + "chevron-up": "\e969", + "eye-slash": "\e96d", + "file": "\e96e", + "paste": "\e96f", + "github": "\e950", + "facebook": "\e94d", + "paypal": "\e938", + "google": "\e951", + "linkedin": "\e955", + "discourse": "\e91e", + "twitter": "\e961", + "youtube": "\e966", + "windows": "\e964", + "apple": "\e945", + "android": "\e944", + "error": "\e981", + "numbered-list": "\e989", + "billing": "\e98a", + "family": "\e98b", + "provider": "\e98c", + "business": "\e98d", +); + +@each $name, $glyph in $icons { + .bwi-#{$name}:before { + content: $glyph; + } +} diff --git a/libs/angular/src/scss/icons.scss b/libs/angular/src/scss/icons.scss new file mode 100644 index 0000000000..88e9c5af54 --- /dev/null +++ b/libs/angular/src/scss/icons.scss @@ -0,0 +1,46 @@ +$card-icons-base: "~@bitwarden/jslib-angular/src/images/cards/" !default; +$card-icons: ( + "visa": $card-icons-base + "visa-light.png", + "amex": $card-icons-base + "amex-light.png", + "diners-club": $card-icons-base + "diners_club-light.png", + "discover": $card-icons-base + "discover-light.png", + "jcb": $card-icons-base + "jcb-light.png", + "maestro": $card-icons-base + "maestro-light.png", + "mastercard": $card-icons-base + "mastercard-light.png", + "union-pay": $card-icons-base + "union_pay-light.png", + "ru-pay": $card-icons-base + "ru_pay-light.png", +); + +$card-icons-dark: ( + "visa": $card-icons-base + "visa-dark.png", + "amex": $card-icons-base + "amex-dark.png", + "diners-club": $card-icons-base + "diners_club-dark.png", + "discover": $card-icons-base + "discover-dark.png", + "jcb": $card-icons-base + "jcb-dark.png", + "maestro": $card-icons-base + "maestro-dark.png", + "mastercard": $card-icons-base + "mastercard-dark.png", + "union-pay": $card-icons-base + "union_pay-dark.png", + "ru-pay": $card-icons-base + "ru_pay-dark.png", +); + +.credit-card-icon { + display: block; // Resolves the parent container being slighly to big + height: 19px; + width: 24px; + background-size: contain; + background-repeat: no-repeat; +} + +@each $name, $url in $card-icons { + .card-#{$name} { + background-image: url("#{$url}"); + } +} + +@each $theme in $dark-icon-themes { + @each $name, $url in $card-icons-dark { + .#{$theme} .card-#{$name} { + background-image: url("#{$url}"); + } + } +} diff --git a/libs/angular/src/scss/webfonts.css b/libs/angular/src/scss/webfonts.css new file mode 100644 index 0000000000..fe9bb7e167 --- /dev/null +++ b/libs/angular/src/scss/webfonts.css @@ -0,0 +1,89 @@ +@font-face { + font-family: "Open Sans"; + font-style: italic; + font-weight: 300; + font-display: auto; + src: url(webfonts/Open_Sans-italic-300.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: italic; + font-weight: 400; + font-display: auto; + src: url(webfonts/Open_Sans-italic-400.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: italic; + font-weight: 600; + font-display: auto; + src: url(webfonts/Open_Sans-italic-600.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: italic; + font-weight: 700; + font-display: auto; + src: url(webfonts/Open_Sans-italic-700.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: italic; + font-weight: 800; + font-display: auto; + src: url(webfonts/Open_Sans-italic-800.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 300; + font-display: auto; + src: url(webfonts/Open_Sans-normal-300.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 400; + font-display: auto; + src: url(webfonts/Open_Sans-normal-400.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 600; + font-display: auto; + src: url(webfonts/Open_Sans-normal-600.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 700; + font-display: auto; + src: url(webfonts/Open_Sans-normal-700.woff) format("woff"); + unicode-range: U+0-10FFFF; +} + +@font-face { + font-family: "Open Sans"; + font-style: normal; + font-weight: 800; + font-display: auto; + src: url(webfonts/Open_Sans-normal-800.woff) format("woff"); + unicode-range: U+0-10FFFF; +} diff --git a/libs/angular/src/scss/webfonts/Open_Sans-italic-300.woff b/libs/angular/src/scss/webfonts/Open_Sans-italic-300.woff new file mode 100644 index 0000000000..8f8e97cfe0 Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-italic-300.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-italic-400.woff b/libs/angular/src/scss/webfonts/Open_Sans-italic-400.woff new file mode 100644 index 0000000000..f90b996086 Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-italic-400.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-italic-600.woff b/libs/angular/src/scss/webfonts/Open_Sans-italic-600.woff new file mode 100644 index 0000000000..c262a9c88f Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-italic-600.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff b/libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff new file mode 100644 index 0000000000..8526ac3d14 Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-italic-700.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-italic-800.woff b/libs/angular/src/scss/webfonts/Open_Sans-italic-800.woff new file mode 100644 index 0000000000..c389a1256c Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-italic-800.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-normal-300.woff b/libs/angular/src/scss/webfonts/Open_Sans-normal-300.woff new file mode 100644 index 0000000000..9f56d335b1 Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-normal-300.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-normal-400.woff b/libs/angular/src/scss/webfonts/Open_Sans-normal-400.woff new file mode 100644 index 0000000000..153a1d63a4 Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-normal-400.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-normal-600.woff b/libs/angular/src/scss/webfonts/Open_Sans-normal-600.woff new file mode 100644 index 0000000000..8271bb4a7a Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-normal-600.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-normal-700.woff b/libs/angular/src/scss/webfonts/Open_Sans-normal-700.woff new file mode 100644 index 0000000000..101c0be6e4 Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-normal-700.woff differ diff --git a/libs/angular/src/scss/webfonts/Open_Sans-normal-800.woff b/libs/angular/src/scss/webfonts/Open_Sans-normal-800.woff new file mode 100644 index 0000000000..724c2e64bd Binary files /dev/null and b/libs/angular/src/scss/webfonts/Open_Sans-normal-800.woff differ diff --git a/libs/angular/src/services/broadcaster.service.ts b/libs/angular/src/services/broadcaster.service.ts new file mode 100644 index 0000000000..362184059d --- /dev/null +++ b/libs/angular/src/services/broadcaster.service.ts @@ -0,0 +1,6 @@ +import { Injectable } from "@angular/core"; + +import { BroadcasterService as BaseBroadcasterService } from "jslib-common/services/broadcaster.service"; + +@Injectable() +export class BroadcasterService extends BaseBroadcasterService {} diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts new file mode 100644 index 0000000000..ab4ca41eb2 --- /dev/null +++ b/libs/angular/src/services/jslib-services.module.ts @@ -0,0 +1,428 @@ +import { InjectionToken, Injector, LOCALE_ID, NgModule } from "@angular/core"; + +import { ApiService as ApiServiceAbstraction } from "jslib-common/abstractions/api.service"; +import { AppIdService as AppIdServiceAbstraction } from "jslib-common/abstractions/appId.service"; +import { AuditService as AuditServiceAbstraction } from "jslib-common/abstractions/audit.service"; +import { AuthService as AuthServiceAbstraction } from "jslib-common/abstractions/auth.service"; +import { BroadcasterService as BroadcasterServiceAbstraction } from "jslib-common/abstractions/broadcaster.service"; +import { CipherService as CipherServiceAbstraction } from "jslib-common/abstractions/cipher.service"; +import { CollectionService as CollectionServiceAbstraction } from "jslib-common/abstractions/collection.service"; +import { CryptoService as CryptoServiceAbstraction } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService as EnvironmentServiceAbstraction } from "jslib-common/abstractions/environment.service"; +import { EventService as EventServiceAbstraction } from "jslib-common/abstractions/event.service"; +import { ExportService as ExportServiceAbstraction } from "jslib-common/abstractions/export.service"; +import { FileUploadService as FileUploadServiceAbstraction } from "jslib-common/abstractions/fileUpload.service"; +import { FolderService as FolderServiceAbstraction } from "jslib-common/abstractions/folder.service"; +import { I18nService as I18nServiceAbstraction } from "jslib-common/abstractions/i18n.service"; +import { KeyConnectorService as KeyConnectorServiceAbstraction } from "jslib-common/abstractions/keyConnector.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService as MessagingServiceAbstraction } from "jslib-common/abstractions/messaging.service"; +import { NotificationsService as NotificationsServiceAbstraction } from "jslib-common/abstractions/notifications.service"; +import { OrganizationService as OrganizationServiceAbstraction } from "jslib-common/abstractions/organization.service"; +import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from "jslib-common/abstractions/passwordGeneration.service"; +import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; +import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService as PolicyServiceAbstraction } from "jslib-common/abstractions/policy.service"; +import { ProviderService as ProviderServiceAbstraction } from "jslib-common/abstractions/provider.service"; +import { SearchService as SearchServiceAbstraction } from "jslib-common/abstractions/search.service"; +import { SendService as SendServiceAbstraction } from "jslib-common/abstractions/send.service"; +import { SettingsService as SettingsServiceAbstraction } from "jslib-common/abstractions/settings.service"; +import { StateService as StateServiceAbstraction } from "jslib-common/abstractions/state.service"; +import { StateMigrationService as StateMigrationServiceAbstraction } from "jslib-common/abstractions/stateMigration.service"; +import { StorageService as StorageServiceAbstraction } from "jslib-common/abstractions/storage.service"; +import { SyncService as SyncServiceAbstraction } from "jslib-common/abstractions/sync.service"; +import { TokenService as TokenServiceAbstraction } from "jslib-common/abstractions/token.service"; +import { TotpService as TotpServiceAbstraction } from "jslib-common/abstractions/totp.service"; +import { TwoFactorService as TwoFactorServiceAbstraction } from "jslib-common/abstractions/twoFactor.service"; +import { UserVerificationService as UserVerificationServiceAbstraction } from "jslib-common/abstractions/userVerification.service"; +import { UsernameGenerationService as UsernameGenerationServiceAbstraction } from "jslib-common/abstractions/usernameGeneration.service"; +import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "jslib-common/abstractions/vaultTimeout.service"; +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { Account } from "jslib-common/models/domain/account"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { ApiService } from "jslib-common/services/api.service"; +import { AppIdService } from "jslib-common/services/appId.service"; +import { AuditService } from "jslib-common/services/audit.service"; +import { AuthService } from "jslib-common/services/auth.service"; +import { CipherService } from "jslib-common/services/cipher.service"; +import { CollectionService } from "jslib-common/services/collection.service"; +import { ConsoleLogService } from "jslib-common/services/consoleLog.service"; +import { CryptoService } from "jslib-common/services/crypto.service"; +import { EnvironmentService } from "jslib-common/services/environment.service"; +import { EventService } from "jslib-common/services/event.service"; +import { ExportService } from "jslib-common/services/export.service"; +import { FileUploadService } from "jslib-common/services/fileUpload.service"; +import { FolderService } from "jslib-common/services/folder.service"; +import { KeyConnectorService } from "jslib-common/services/keyConnector.service"; +import { NotificationsService } from "jslib-common/services/notifications.service"; +import { OrganizationService } from "jslib-common/services/organization.service"; +import { PasswordGenerationService } from "jslib-common/services/passwordGeneration.service"; +import { PolicyService } from "jslib-common/services/policy.service"; +import { ProviderService } from "jslib-common/services/provider.service"; +import { SearchService } from "jslib-common/services/search.service"; +import { SendService } from "jslib-common/services/send.service"; +import { SettingsService } from "jslib-common/services/settings.service"; +import { StateService } from "jslib-common/services/state.service"; +import { StateMigrationService } from "jslib-common/services/stateMigration.service"; +import { SyncService } from "jslib-common/services/sync.service"; +import { TokenService } from "jslib-common/services/token.service"; +import { TotpService } from "jslib-common/services/totp.service"; +import { TwoFactorService } from "jslib-common/services/twoFactor.service"; +import { UserVerificationService } from "jslib-common/services/userVerification.service"; +import { UsernameGenerationService } from "jslib-common/services/usernameGeneration.service"; +import { VaultTimeoutService } from "jslib-common/services/vaultTimeout.service"; +import { WebCryptoFunctionService } from "jslib-common/services/webCryptoFunction.service"; + +import { AuthGuard } from "../guards/auth.guard"; +import { LockGuard } from "../guards/lock.guard"; +import { UnauthGuard } from "../guards/unauth.guard"; + +import { BroadcasterService } from "./broadcaster.service"; +import { ModalService } from "./modal.service"; +import { PasswordRepromptService } from "./passwordReprompt.service"; +import { ValidationService } from "./validation.service"; + +export const WINDOW = new InjectionToken("WINDOW"); +export const SECURE_STORAGE = new InjectionToken("SECURE_STORAGE"); +export const STATE_FACTORY = new InjectionToken("STATE_FACTORY"); +export const STATE_SERVICE_USE_CACHE = new InjectionToken("STATE_SERVICE_USE_CACHE"); +export const LOGOUT_CALLBACK = new InjectionToken<(expired: boolean, userId?: string) => void>( + "LOGOUT_CALLBACK" +); +export const LOCKED_CALLBACK = new InjectionToken<() => void>("LOCKED_CALLBACK"); +export const CLIENT_TYPE = new InjectionToken("CLIENT_TYPE"); +export const LOCALES_DIRECTORY = new InjectionToken("LOCALES_DIRECTORY"); +export const SYSTEM_LANGUAGE = new InjectionToken("SYSTEM_LANGUAGE"); + +@NgModule({ + declarations: [], + providers: [ + ValidationService, + AuthGuard, + UnauthGuard, + LockGuard, + ModalService, + { provide: WINDOW, useValue: window }, + { + provide: LOCALE_ID, + useFactory: (i18nService: I18nServiceAbstraction) => i18nService.translationLocale, + deps: [I18nServiceAbstraction], + }, + { + provide: LOCALES_DIRECTORY, + useValue: "./locales", + }, + { + provide: SYSTEM_LANGUAGE, + useFactory: (window: Window) => window.navigator.language, + deps: [WINDOW], + }, + { + provide: STATE_FACTORY, + useValue: new StateFactory(GlobalState, Account), + }, + { + provide: STATE_SERVICE_USE_CACHE, + useValue: true, + }, + { + provide: LOGOUT_CALLBACK, + useFactory: + (messagingService: MessagingServiceAbstraction) => (expired: boolean, userId?: string) => + messagingService.send("logout", { expired: expired, userId: userId }), + deps: [MessagingServiceAbstraction], + }, + { + provide: LOCKED_CALLBACK, + useValue: null, + }, + { + provide: AppIdServiceAbstraction, + useClass: AppIdService, + deps: [StorageServiceAbstraction], + }, + { + provide: AuditServiceAbstraction, + useClass: AuditService, + deps: [CryptoFunctionServiceAbstraction, ApiServiceAbstraction], + }, + { + provide: AuthServiceAbstraction, + useClass: AuthService, + deps: [ + CryptoServiceAbstraction, + ApiServiceAbstraction, + TokenServiceAbstraction, + AppIdServiceAbstraction, + PlatformUtilsServiceAbstraction, + MessagingServiceAbstraction, + LogService, + KeyConnectorServiceAbstraction, + EnvironmentServiceAbstraction, + StateServiceAbstraction, + TwoFactorServiceAbstraction, + I18nServiceAbstraction, + ], + }, + { + provide: CipherServiceAbstraction, + useFactory: ( + cryptoService: CryptoServiceAbstraction, + settingsService: SettingsServiceAbstraction, + apiService: ApiServiceAbstraction, + fileUploadService: FileUploadServiceAbstraction, + i18nService: I18nServiceAbstraction, + injector: Injector, + logService: LogService, + stateService: StateServiceAbstraction + ) => + new CipherService( + cryptoService, + settingsService, + apiService, + fileUploadService, + i18nService, + () => injector.get(SearchServiceAbstraction), + logService, + stateService + ), + deps: [ + CryptoServiceAbstraction, + SettingsServiceAbstraction, + ApiServiceAbstraction, + FileUploadServiceAbstraction, + I18nServiceAbstraction, + Injector, // TODO: Get rid of this circular dependency! + LogService, + StateServiceAbstraction, + ], + }, + { + provide: FolderServiceAbstraction, + useClass: FolderService, + deps: [ + CryptoServiceAbstraction, + ApiServiceAbstraction, + I18nServiceAbstraction, + CipherServiceAbstraction, + StateServiceAbstraction, + ], + }, + { provide: LogService, useFactory: () => new ConsoleLogService(false) }, + { + provide: CollectionServiceAbstraction, + useClass: CollectionService, + deps: [CryptoServiceAbstraction, I18nServiceAbstraction, StateServiceAbstraction], + }, + { + provide: EnvironmentServiceAbstraction, + useClass: EnvironmentService, + deps: [StateServiceAbstraction], + }, + { + provide: TotpServiceAbstraction, + useClass: TotpService, + deps: [CryptoFunctionServiceAbstraction, LogService, StateServiceAbstraction], + }, + { provide: TokenServiceAbstraction, useClass: TokenService, deps: [StateServiceAbstraction] }, + { + provide: CryptoServiceAbstraction, + useClass: CryptoService, + deps: [ + CryptoFunctionServiceAbstraction, + PlatformUtilsServiceAbstraction, + LogService, + StateServiceAbstraction, + ], + }, + { + provide: PasswordGenerationServiceAbstraction, + useClass: PasswordGenerationService, + deps: [CryptoServiceAbstraction, PolicyServiceAbstraction, StateServiceAbstraction], + }, + { + provide: UsernameGenerationServiceAbstraction, + useClass: UsernameGenerationService, + deps: [CryptoServiceAbstraction, StateServiceAbstraction, ApiServiceAbstraction], + }, + { + provide: ApiServiceAbstraction, + useClass: ApiService, + deps: [ + TokenServiceAbstraction, + PlatformUtilsServiceAbstraction, + EnvironmentServiceAbstraction, + AppIdServiceAbstraction, + LOGOUT_CALLBACK, + ], + }, + { + provide: FileUploadServiceAbstraction, + useClass: FileUploadService, + deps: [LogService, ApiServiceAbstraction], + }, + { + provide: SyncServiceAbstraction, + useClass: SyncService, + deps: [ + ApiServiceAbstraction, + SettingsServiceAbstraction, + FolderServiceAbstraction, + CipherServiceAbstraction, + CryptoServiceAbstraction, + CollectionServiceAbstraction, + MessagingServiceAbstraction, + PolicyServiceAbstraction, + SendServiceAbstraction, + LogService, + KeyConnectorServiceAbstraction, + StateServiceAbstraction, + OrganizationServiceAbstraction, + ProviderServiceAbstraction, + LOGOUT_CALLBACK, + ], + }, + { provide: BroadcasterServiceAbstraction, useClass: BroadcasterService }, + { + provide: SettingsServiceAbstraction, + useClass: SettingsService, + deps: [StateServiceAbstraction], + }, + { + provide: VaultTimeoutServiceAbstraction, + useClass: VaultTimeoutService, + deps: [ + CipherServiceAbstraction, + FolderServiceAbstraction, + CollectionServiceAbstraction, + CryptoServiceAbstraction, + PlatformUtilsServiceAbstraction, + MessagingServiceAbstraction, + SearchServiceAbstraction, + TokenServiceAbstraction, + PolicyServiceAbstraction, + KeyConnectorServiceAbstraction, + StateServiceAbstraction, + AuthServiceAbstraction, + LOCKED_CALLBACK, + LOGOUT_CALLBACK, + ], + }, + { + provide: StateServiceAbstraction, + useClass: StateService, + deps: [ + StorageServiceAbstraction, + SECURE_STORAGE, + LogService, + StateMigrationServiceAbstraction, + STATE_FACTORY, + STATE_SERVICE_USE_CACHE, + ], + }, + { + provide: StateMigrationServiceAbstraction, + useClass: StateMigrationService, + deps: [StorageServiceAbstraction, SECURE_STORAGE, STATE_FACTORY], + }, + { + provide: ExportServiceAbstraction, + useClass: ExportService, + deps: [ + FolderServiceAbstraction, + CipherServiceAbstraction, + ApiServiceAbstraction, + CryptoServiceAbstraction, + ], + }, + { + provide: SearchServiceAbstraction, + useClass: SearchService, + deps: [CipherServiceAbstraction, LogService, I18nServiceAbstraction], + }, + { + provide: NotificationsServiceAbstraction, + useClass: NotificationsService, + deps: [ + SyncServiceAbstraction, + AppIdServiceAbstraction, + ApiServiceAbstraction, + EnvironmentServiceAbstraction, + LOGOUT_CALLBACK, + LogService, + StateServiceAbstraction, + AuthServiceAbstraction, + ], + }, + { + provide: CryptoFunctionServiceAbstraction, + useClass: WebCryptoFunctionService, + deps: [WINDOW], + }, + { + provide: EventServiceAbstraction, + useClass: EventService, + deps: [ + ApiServiceAbstraction, + CipherServiceAbstraction, + StateServiceAbstraction, + LogService, + OrganizationServiceAbstraction, + ], + }, + { + provide: PolicyServiceAbstraction, + useClass: PolicyService, + deps: [StateServiceAbstraction, OrganizationServiceAbstraction, ApiServiceAbstraction], + }, + { + provide: SendServiceAbstraction, + useClass: SendService, + deps: [ + CryptoServiceAbstraction, + ApiServiceAbstraction, + FileUploadServiceAbstraction, + I18nServiceAbstraction, + CryptoFunctionServiceAbstraction, + StateServiceAbstraction, + ], + }, + { + provide: KeyConnectorServiceAbstraction, + useClass: KeyConnectorService, + deps: [ + StateServiceAbstraction, + CryptoServiceAbstraction, + ApiServiceAbstraction, + TokenServiceAbstraction, + LogService, + OrganizationServiceAbstraction, + CryptoFunctionServiceAbstraction, + LOGOUT_CALLBACK, + ], + }, + { + provide: UserVerificationServiceAbstraction, + useClass: UserVerificationService, + deps: [CryptoServiceAbstraction, I18nServiceAbstraction, ApiServiceAbstraction], + }, + { provide: PasswordRepromptServiceAbstraction, useClass: PasswordRepromptService }, + { + provide: OrganizationServiceAbstraction, + useClass: OrganizationService, + deps: [StateServiceAbstraction], + }, + { + provide: ProviderServiceAbstraction, + useClass: ProviderService, + deps: [StateServiceAbstraction], + }, + { + provide: TwoFactorServiceAbstraction, + useClass: TwoFactorService, + deps: [I18nServiceAbstraction, PlatformUtilsServiceAbstraction], + }, + ], +}) +export class JslibServicesModule {} diff --git a/libs/angular/src/services/modal.service.ts b/libs/angular/src/services/modal.service.ts new file mode 100644 index 0000000000..aecc84c64a --- /dev/null +++ b/libs/angular/src/services/modal.service.ts @@ -0,0 +1,180 @@ +import { + ApplicationRef, + ComponentFactory, + ComponentFactoryResolver, + ComponentRef, + EmbeddedViewRef, + Injectable, + Injector, + Type, + ViewContainerRef, +} from "@angular/core"; +import { first } from "rxjs/operators"; + +import { DynamicModalComponent } from "../components/modal/dynamic-modal.component"; +import { ModalInjector } from "../components/modal/modal-injector"; +import { ModalRef } from "../components/modal/modal.ref"; + +export class ModalConfig { + data?: D; + allowMultipleModals = false; +} + +@Injectable() +export class ModalService { + protected modalList: ComponentRef[] = []; + + // Lazy loaded modules are not available in componentFactoryResolver, + // therefore modules needs to manually initialize their resolvers. + private factoryResolvers: Map, ComponentFactoryResolver> = new Map(); + + constructor( + private componentFactoryResolver: ComponentFactoryResolver, + private applicationRef: ApplicationRef, + private injector: Injector + ) { + document.addEventListener("keyup", (event) => { + if (event.key === "Escape" && this.modalCount > 0) { + this.topModal.instance.close(); + } + }); + } + + get modalCount() { + return this.modalList.length; + } + + private get topModal() { + return this.modalList[this.modalCount - 1]; + } + + async openViewRef( + componentType: Type, + viewContainerRef: ViewContainerRef, + setComponentParameters: (component: T) => void = null + ): Promise<[ModalRef, T]> { + const [modalRef, modalComponentRef] = this.openInternal(componentType, null, false); + modalComponentRef.instance.setComponentParameters = setComponentParameters; + + viewContainerRef.insert(modalComponentRef.hostView); + + await modalRef.onCreated.pipe(first()).toPromise(); + + return [modalRef, modalComponentRef.instance.componentRef.instance]; + } + + open(componentType: Type, config?: ModalConfig) { + if (!(config?.allowMultipleModals ?? false) && this.modalCount > 0) { + return; + } + + // eslint-disable-next-line + const [modalRef, _] = this.openInternal(componentType, config, true); + + return modalRef; + } + + registerComponentFactoryResolver( + componentType: Type, + componentFactoryResolver: ComponentFactoryResolver + ): void { + this.factoryResolvers.set(componentType, componentFactoryResolver); + } + + resolveComponentFactory(componentType: Type): ComponentFactory { + if (this.factoryResolvers.has(componentType)) { + return this.factoryResolvers.get(componentType).resolveComponentFactory(componentType); + } + + return this.componentFactoryResolver.resolveComponentFactory(componentType); + } + + protected openInternal( + componentType: Type, + config?: ModalConfig, + attachToDom?: boolean + ): [ModalRef, ComponentRef] { + const [modalRef, componentRef] = this.createModalComponent(config); + componentRef.instance.childComponentType = componentType; + + if (attachToDom) { + this.applicationRef.attachView(componentRef.hostView); + const domElem = (componentRef.hostView as EmbeddedViewRef).rootNodes[0] as HTMLElement; + document.body.appendChild(domElem); + } + + modalRef.onClosed.pipe(first()).subscribe(() => { + if (attachToDom) { + this.applicationRef.detachView(componentRef.hostView); + } + componentRef.destroy(); + + this.modalList.pop(); + if (this.modalCount > 0) { + this.topModal.instance.getFocus(); + } + }); + + this.setupHandlers(modalRef); + + this.modalList.push(componentRef); + + return [modalRef, componentRef]; + } + + protected setupHandlers(modalRef: ModalRef) { + let backdrop: HTMLElement = null; + + // Add backdrop, setup [data-dismiss] handler. + modalRef.onCreated.pipe(first()).subscribe((el) => { + document.body.classList.add("modal-open"); + + const modalEl: HTMLElement = el.querySelector(".modal"); + const dialogEl = modalEl.querySelector(".modal-dialog") as HTMLElement; + + backdrop = document.createElement("div"); + backdrop.className = "modal-backdrop fade"; + backdrop.style.zIndex = `${this.modalCount}040`; + modalEl.prepend(backdrop); + + dialogEl.addEventListener("click", (e: Event) => { + e.stopPropagation(); + }); + dialogEl.style.zIndex = `${this.modalCount}050`; + + const modals = Array.from( + el.querySelectorAll('.modal-backdrop, .modal *[data-dismiss="modal"]') + ); + for (const closeElement of modals) { + closeElement.addEventListener("click", () => { + modalRef.close(); + }); + } + }); + + // onClose is used in Web to hook into bootstrap. On other projects we pipe it directly to closed. + modalRef.onClose.pipe(first()).subscribe(() => { + modalRef.closed(); + + if (this.modalCount === 0) { + document.body.classList.remove("modal-open"); + } + }); + } + + protected createModalComponent( + config: ModalConfig + ): [ModalRef, ComponentRef] { + const modalRef = new ModalRef(); + + const map = new WeakMap(); + map.set(ModalConfig, config); + map.set(ModalRef, modalRef); + + const componentFactory = + this.componentFactoryResolver.resolveComponentFactory(DynamicModalComponent); + const componentRef = componentFactory.create(new ModalInjector(this.injector, map)); + + return [modalRef, componentRef]; + } +} diff --git a/libs/angular/src/services/passwordReprompt.service.ts b/libs/angular/src/services/passwordReprompt.service.ts new file mode 100644 index 0000000000..723c41f78b --- /dev/null +++ b/libs/angular/src/services/passwordReprompt.service.ts @@ -0,0 +1,45 @@ +import { Injectable } from "@angular/core"; + +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "jslib-common/abstractions/passwordReprompt.service"; + +import { PasswordRepromptComponent } from "../components/password-reprompt.component"; + +import { ModalService } from "./modal.service"; + +/** + * Used to verify the user's Master Password for the "Master Password Re-prompt" feature only. + * See UserVerificationService for any other situation where you need to verify the user's identity. + */ +@Injectable() +export class PasswordRepromptService implements PasswordRepromptServiceAbstraction { + protected component = PasswordRepromptComponent; + + constructor( + private modalService: ModalService, + private keyConnectorService: KeyConnectorService + ) {} + + protectedFields() { + return ["TOTP", "Password", "H_Field", "Card Number", "Security Code"]; + } + + async showPasswordPrompt() { + if (!(await this.enabled())) { + return true; + } + + const ref = this.modalService.open(this.component, { allowMultipleModals: true }); + + if (ref == null) { + return false; + } + + const result = await ref.onClosedPromise(); + return result === true; + } + + async enabled() { + return !(await this.keyConnectorService.getUsesKeyConnector()); + } +} diff --git a/libs/angular/src/services/validation.service.ts b/libs/angular/src/services/validation.service.ts new file mode 100644 index 0000000000..865f6458a0 --- /dev/null +++ b/libs/angular/src/services/validation.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { ErrorResponse } from "jslib-common/models/response/errorResponse"; + +@Injectable() +export class ValidationService { + constructor( + private i18nService: I18nService, + private platformUtilsService: PlatformUtilsService + ) {} + + showError(data: any): string[] { + const defaultErrorMessage = this.i18nService.t("unexpectedError"); + let errors: string[] = []; + + if (data != null && typeof data === "string") { + errors.push(data); + } else if (data == null || typeof data !== "object") { + errors.push(defaultErrorMessage); + } else if (data.validationErrors != null) { + errors = errors.concat((data as ErrorResponse).getAllMessages()); + } else { + errors.push(data.message ? data.message : defaultErrorMessage); + } + + if (errors.length === 1) { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errors[0]); + } else if (errors.length > 1) { + this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), errors, { + timeout: 5000 * errors.length, + }); + } + + return errors; + } +} diff --git a/libs/angular/src/validators/dirty.validator.ts b/libs/angular/src/validators/dirty.validator.ts new file mode 100644 index 0000000000..66ba2be091 --- /dev/null +++ b/libs/angular/src/validators/dirty.validator.ts @@ -0,0 +1,9 @@ +import { AbstractControl, ValidationErrors, Validators } from "@angular/forms"; + +/** + * Runs Validators.required on a field only if it's dirty. This prevents error messages from being displayed + * to the user prematurely. + */ +export function dirtyRequired(control: AbstractControl): ValidationErrors | null { + return control.dirty ? Validators.required(control) : null; +} diff --git a/libs/angular/src/validators/notAllowedValueAsync.validator.ts b/libs/angular/src/validators/notAllowedValueAsync.validator.ts new file mode 100644 index 0000000000..ae2be86542 --- /dev/null +++ b/libs/angular/src/validators/notAllowedValueAsync.validator.ts @@ -0,0 +1,21 @@ +import { AbstractControl, AsyncValidatorFn, ValidationErrors } from "@angular/forms"; + +export function notAllowedValueAsync( + valueGetter: () => Promise, + caseInsensitive = false +): AsyncValidatorFn { + return async (control: AbstractControl): Promise => { + let notAllowedValue = await valueGetter(); + let controlValue = control.value; + if (caseInsensitive) { + notAllowedValue = notAllowedValue.toLowerCase(); + controlValue = controlValue.toLowerCase(); + } + + if (controlValue === notAllowedValue) { + return { + notAllowedValue: true, + }; + } + }; +} diff --git a/libs/angular/tsconfig.json b/libs/angular/tsconfig.json new file mode 100644 index 0000000000..c2fd662cfe --- /dev/null +++ b/libs/angular/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../shared/tsconfig", + "compilerOptions": { + "paths": { + "jslib-common/*": ["../common/src/*"], + "jslib-angular/*": ["./src/"] + } + }, + "include": ["src", "spec"], + "exclude": ["node_modules", "dist"] +} diff --git a/libs/angular/tsconfig.spec.json b/libs/angular/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/libs/angular/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/libs/common/jest.config.js b/libs/common/jest.config.js new file mode 100644 index 0000000000..9e8c9211c0 --- /dev/null +++ b/libs/common/jest.config.js @@ -0,0 +1,18 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + name: "common", + displayName: "libs/common tests", + preset: "ts-jest", + testEnvironment: "jsdom", + testMatch: ["**/+(*.)+(spec).+(ts)"], + setupFilesAfterEnv: ["/spec/test.ts"], + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), +}; diff --git a/libs/common/package.json b/libs/common/package.json new file mode 100644 index 0000000000..1c03329a7b --- /dev/null +++ b/libs/common/package.json @@ -0,0 +1,20 @@ +{ + "name": "@bitwarden/jslib-common", + "version": "0.0.0", + "description": "Common code used across Bitwarden JavaScript projects.", + "keywords": [ + "bitwarden" + ], + "author": "Bitwarden Inc.", + "homepage": "https://bitwarden.com", + "repository": { + "type": "git", + "url": "https://github.com/bitwarden/jslib" + }, + "license": "GPL-3.0", + "scripts": { + "clean": "rimraf dist/**/*", + "build": "npm run clean && tsc", + "build:watch": "npm run clean && tsc -watch" + } +} diff --git a/libs/common/spec/domain/attachment.spec.ts b/libs/common/spec/domain/attachment.spec.ts new file mode 100644 index 0000000000..f625adbfff --- /dev/null +++ b/libs/common/spec/domain/attachment.spec.ts @@ -0,0 +1,83 @@ +import Substitute, { Arg } from "@fluffy-spoon/substitute"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { AttachmentData } from "jslib-common/models/data/attachmentData"; +import { Attachment } from "jslib-common/models/domain/attachment"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { ContainerService } from "jslib-common/services/container.service"; + +import { makeStaticByteArray, mockEnc } from "../utils"; + +describe("Attachment", () => { + let data: AttachmentData; + + beforeEach(() => { + data = { + id: "id", + url: "url", + fileName: "fileName", + key: "key", + size: "1100", + sizeName: "1.1 KB", + }; + }); + + it("Convert from empty", () => { + const data = new AttachmentData(); + const attachment = new Attachment(data); + + expect(attachment).toEqual({ + id: null, + url: null, + size: undefined, + sizeName: null, + key: null, + fileName: null, + }); + }); + + it("Convert", () => { + const attachment = new Attachment(data); + + expect(attachment).toEqual({ + size: "1100", + id: "id", + url: "url", + sizeName: "1.1 KB", + fileName: { encryptedString: "fileName", encryptionType: 0 }, + key: { encryptedString: "key", encryptionType: 0 }, + }); + }); + + it("toAttachmentData", () => { + const attachment = new Attachment(data); + expect(attachment.toAttachmentData()).toEqual(data); + }); + + it("Decrypt", async () => { + const attachment = new Attachment(); + attachment.id = "id"; + attachment.url = "url"; + attachment.size = "1100"; + attachment.sizeName = "1.1 KB"; + attachment.key = mockEnc("key"); + attachment.fileName = mockEnc("fileName"); + + const cryptoService = Substitute.for(); + cryptoService.getOrgKey(null).resolves(null); + cryptoService.decryptToBytes(Arg.any(), Arg.any()).resolves(makeStaticByteArray(32)); + + (window as any).bitwardenContainerService = new ContainerService(cryptoService); + + const view = await attachment.decrypt(null); + + expect(view).toEqual({ + id: "id", + url: "url", + size: "1100", + sizeName: "1.1 KB", + fileName: "fileName", + key: expect.any(SymmetricCryptoKey), + }); + }); +}); diff --git a/libs/common/spec/domain/card.spec.ts b/libs/common/spec/domain/card.spec.ts new file mode 100644 index 0000000000..f4709bccf9 --- /dev/null +++ b/libs/common/spec/domain/card.spec.ts @@ -0,0 +1,73 @@ +import { CardData } from "jslib-common/models/data/cardData"; +import { Card } from "jslib-common/models/domain/card"; + +import { mockEnc } from "../utils"; + +describe("Card", () => { + let data: CardData; + + beforeEach(() => { + data = { + cardholderName: "encHolder", + brand: "encBrand", + number: "encNumber", + expMonth: "encMonth", + expYear: "encYear", + code: "encCode", + }; + }); + + it("Convert from empty", () => { + const data = new CardData(); + const card = new Card(data); + + expect(card).toEqual({ + cardholderName: null, + brand: null, + number: null, + expMonth: null, + expYear: null, + code: null, + }); + }); + + it("Convert", () => { + const card = new Card(data); + + expect(card).toEqual({ + cardholderName: { encryptedString: "encHolder", encryptionType: 0 }, + brand: { encryptedString: "encBrand", encryptionType: 0 }, + number: { encryptedString: "encNumber", encryptionType: 0 }, + expMonth: { encryptedString: "encMonth", encryptionType: 0 }, + expYear: { encryptedString: "encYear", encryptionType: 0 }, + code: { encryptedString: "encCode", encryptionType: 0 }, + }); + }); + + it("toCardData", () => { + const card = new Card(data); + expect(card.toCardData()).toEqual(data); + }); + + it("Decrypt", async () => { + const card = new Card(); + card.cardholderName = mockEnc("cardHolder"); + card.brand = mockEnc("brand"); + card.number = mockEnc("number"); + card.expMonth = mockEnc("expMonth"); + card.expYear = mockEnc("expYear"); + card.code = mockEnc("code"); + + const view = await card.decrypt(null); + + expect(view).toEqual({ + _brand: "brand", + _number: "number", + _subTitle: null, + cardholderName: "cardHolder", + code: "code", + expMonth: "expMonth", + expYear: "expYear", + }); + }); +}); diff --git a/libs/common/spec/domain/cipher.spec.ts b/libs/common/spec/domain/cipher.spec.ts new file mode 100644 index 0000000000..0eff1b85d8 --- /dev/null +++ b/libs/common/spec/domain/cipher.spec.ts @@ -0,0 +1,590 @@ +import Substitute, { Arg } from "@fluffy-spoon/substitute"; + +import { CipherRepromptType } from "jslib-common/enums/cipherRepromptType"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { SecureNoteType } from "jslib-common/enums/secureNoteType"; +import { UriMatchType } from "jslib-common/enums/uriMatchType"; +import { CipherData } from "jslib-common/models/data/cipherData"; +import { Card } from "jslib-common/models/domain/card"; +import { Cipher } from "jslib-common/models/domain/cipher"; +import { Identity } from "jslib-common/models/domain/identity"; +import { Login } from "jslib-common/models/domain/login"; +import { SecureNote } from "jslib-common/models/domain/secureNote"; +import { CardView } from "jslib-common/models/view/cardView"; +import { IdentityView } from "jslib-common/models/view/identityView"; +import { LoginView } from "jslib-common/models/view/loginView"; + +import { mockEnc } from "../utils"; + +describe("Cipher DTO", () => { + it("Convert from empty CipherData", () => { + const data = new CipherData(); + const cipher = new Cipher(data); + + expect(cipher).toEqual({ + id: null, + organizationId: null, + folderId: null, + name: null, + notes: null, + type: undefined, + favorite: undefined, + organizationUseTotp: undefined, + edit: undefined, + viewPassword: true, + revisionDate: null, + collectionIds: undefined, + localData: null, + deletedDate: null, + reprompt: undefined, + attachments: null, + fields: null, + passwordHistory: null, + }); + }); + + describe("LoginCipher", () => { + let cipherData: CipherData; + + beforeEach(() => { + cipherData = { + id: "id", + organizationId: "orgId", + folderId: "folderId", + edit: true, + viewPassword: true, + organizationUseTotp: true, + favorite: false, + revisionDate: "2022-01-31T12:00:00.000Z", + type: CipherType.Login, + name: "EncryptedString", + notes: "EncryptedString", + deletedDate: null, + reprompt: CipherRepromptType.None, + login: { + uris: [{ uri: "EncryptedString", match: UriMatchType.Domain }], + username: "EncryptedString", + password: "EncryptedString", + passwordRevisionDate: "2022-01-31T12:00:00.000Z", + totp: "EncryptedString", + autofillOnPageLoad: false, + }, + passwordHistory: [ + { password: "EncryptedString", lastUsedDate: "2022-01-31T12:00:00.000Z" }, + ], + attachments: [ + { + id: "a1", + url: "url", + size: "1100", + sizeName: "1.1 KB", + fileName: "file", + key: "EncKey", + }, + { + id: "a2", + url: "url", + size: "1100", + sizeName: "1.1 KB", + fileName: "file", + key: "EncKey", + }, + ], + fields: [ + { + name: "EncryptedString", + value: "EncryptedString", + type: FieldType.Text, + linkedId: null, + }, + { + name: "EncryptedString", + value: "EncryptedString", + type: FieldType.Hidden, + linkedId: null, + }, + ], + }; + }); + + it("Convert", () => { + const cipher = new Cipher(cipherData); + + expect(cipher).toEqual({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: { encryptedString: "EncryptedString", encryptionType: 0 }, + notes: { encryptedString: "EncryptedString", encryptionType: 0 }, + type: 1, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + collectionIds: undefined, + localData: null, + deletedDate: null, + reprompt: 0, + login: { + passwordRevisionDate: new Date("2022-01-31T12:00:00.000Z"), + autofillOnPageLoad: false, + username: { encryptedString: "EncryptedString", encryptionType: 0 }, + password: { encryptedString: "EncryptedString", encryptionType: 0 }, + totp: { encryptedString: "EncryptedString", encryptionType: 0 }, + uris: [{ match: 0, uri: { encryptedString: "EncryptedString", encryptionType: 0 } }], + }, + attachments: [ + { + fileName: { encryptedString: "file", encryptionType: 0 }, + id: "a1", + key: { encryptedString: "EncKey", encryptionType: 0 }, + size: "1100", + sizeName: "1.1 KB", + url: "url", + }, + { + fileName: { encryptedString: "file", encryptionType: 0 }, + id: "a2", + key: { encryptedString: "EncKey", encryptionType: 0 }, + size: "1100", + sizeName: "1.1 KB", + url: "url", + }, + ], + fields: [ + { + linkedId: null, + name: { encryptedString: "EncryptedString", encryptionType: 0 }, + type: 0, + value: { encryptedString: "EncryptedString", encryptionType: 0 }, + }, + { + linkedId: null, + name: { encryptedString: "EncryptedString", encryptionType: 0 }, + type: 1, + value: { encryptedString: "EncryptedString", encryptionType: 0 }, + }, + ], + passwordHistory: [ + { + lastUsedDate: new Date("2022-01-31T12:00:00.000Z"), + password: { encryptedString: "EncryptedString", encryptionType: 0 }, + }, + ], + }); + }); + + it("toCipherData", () => { + const cipher = new Cipher(cipherData); + expect(cipher.toCipherData()).toEqual(cipherData); + }); + + it("Decrypt", async () => { + const cipher = new Cipher(); + cipher.id = "id"; + cipher.organizationId = "orgId"; + cipher.folderId = "folderId"; + cipher.edit = true; + cipher.viewPassword = true; + cipher.organizationUseTotp = true; + cipher.favorite = false; + cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z"); + cipher.type = CipherType.Login; + cipher.name = mockEnc("EncryptedString"); + cipher.notes = mockEnc("EncryptedString"); + cipher.deletedDate = null; + cipher.reprompt = CipherRepromptType.None; + + const loginView = new LoginView(); + loginView.username = "username"; + loginView.password = "password"; + + const login = Substitute.for(); + login.decrypt(Arg.any(), Arg.any()).resolves(loginView); + cipher.login = login; + + const cipherView = await cipher.decrypt(); + + expect(cipherView).toMatchObject({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: "EncryptedString", + notes: "EncryptedString", + type: 1, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + login: loginView, + attachments: null, + fields: null, + passwordHistory: null, + collectionIds: undefined, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + deletedDate: null, + reprompt: 0, + localData: undefined, + }); + }); + }); + + describe("SecureNoteCipher", () => { + let cipherData: CipherData; + + beforeEach(() => { + cipherData = { + id: "id", + organizationId: "orgId", + folderId: "folderId", + edit: true, + viewPassword: true, + organizationUseTotp: true, + favorite: false, + revisionDate: "2022-01-31T12:00:00.000Z", + type: CipherType.SecureNote, + name: "EncryptedString", + notes: "EncryptedString", + deletedDate: null, + reprompt: CipherRepromptType.None, + secureNote: { + type: SecureNoteType.Generic, + }, + }; + }); + + it("Convert", () => { + const cipher = new Cipher(cipherData); + + expect(cipher).toEqual({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: { encryptedString: "EncryptedString", encryptionType: 0 }, + notes: { encryptedString: "EncryptedString", encryptionType: 0 }, + type: 2, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + collectionIds: undefined, + localData: null, + deletedDate: null, + reprompt: 0, + secureNote: { type: SecureNoteType.Generic }, + attachments: null, + fields: null, + passwordHistory: null, + }); + }); + + it("toCipherData", () => { + const cipher = new Cipher(cipherData); + expect(cipher.toCipherData()).toEqual(cipherData); + }); + + it("Decrypt", async () => { + const cipher = new Cipher(); + cipher.id = "id"; + cipher.organizationId = "orgId"; + cipher.folderId = "folderId"; + cipher.edit = true; + cipher.viewPassword = true; + cipher.organizationUseTotp = true; + cipher.favorite = false; + cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z"); + cipher.type = CipherType.SecureNote; + cipher.name = mockEnc("EncryptedString"); + cipher.notes = mockEnc("EncryptedString"); + cipher.deletedDate = null; + cipher.reprompt = CipherRepromptType.None; + cipher.secureNote = new SecureNote(); + cipher.secureNote.type = SecureNoteType.Generic; + + const cipherView = await cipher.decrypt(); + + expect(cipherView).toMatchObject({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: "EncryptedString", + notes: "EncryptedString", + type: 2, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + secureNote: { type: 0 }, + attachments: null, + fields: null, + passwordHistory: null, + collectionIds: undefined, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + deletedDate: null, + reprompt: 0, + localData: undefined, + }); + }); + }); + + describe("CardCipher", () => { + let cipherData: CipherData; + + beforeEach(() => { + cipherData = { + id: "id", + organizationId: "orgId", + folderId: "folderId", + edit: true, + viewPassword: true, + organizationUseTotp: true, + favorite: false, + revisionDate: "2022-01-31T12:00:00.000Z", + type: CipherType.Card, + name: "EncryptedString", + notes: "EncryptedString", + deletedDate: null, + reprompt: CipherRepromptType.None, + card: { + cardholderName: "EncryptedString", + brand: "EncryptedString", + number: "EncryptedString", + expMonth: "EncryptedString", + expYear: "EncryptedString", + code: "EncryptedString", + }, + }; + }); + + it("Convert", () => { + const cipher = new Cipher(cipherData); + + expect(cipher).toEqual({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: { encryptedString: "EncryptedString", encryptionType: 0 }, + notes: { encryptedString: "EncryptedString", encryptionType: 0 }, + type: 3, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + collectionIds: undefined, + localData: null, + deletedDate: null, + reprompt: 0, + card: { + cardholderName: { encryptedString: "EncryptedString", encryptionType: 0 }, + brand: { encryptedString: "EncryptedString", encryptionType: 0 }, + number: { encryptedString: "EncryptedString", encryptionType: 0 }, + expMonth: { encryptedString: "EncryptedString", encryptionType: 0 }, + expYear: { encryptedString: "EncryptedString", encryptionType: 0 }, + code: { encryptedString: "EncryptedString", encryptionType: 0 }, + }, + attachments: null, + fields: null, + passwordHistory: null, + }); + }); + + it("toCipherData", () => { + const cipher = new Cipher(cipherData); + expect(cipher.toCipherData()).toEqual(cipherData); + }); + + it("Decrypt", async () => { + const cipher = new Cipher(); + cipher.id = "id"; + cipher.organizationId = "orgId"; + cipher.folderId = "folderId"; + cipher.edit = true; + cipher.viewPassword = true; + cipher.organizationUseTotp = true; + cipher.favorite = false; + cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z"); + cipher.type = CipherType.Card; + cipher.name = mockEnc("EncryptedString"); + cipher.notes = mockEnc("EncryptedString"); + cipher.deletedDate = null; + cipher.reprompt = CipherRepromptType.None; + + const cardView = new CardView(); + cardView.cardholderName = "cardholderName"; + cardView.number = "4111111111111111"; + + const card = Substitute.for(); + card.decrypt(Arg.any(), Arg.any()).resolves(cardView); + cipher.card = card; + + const cipherView = await cipher.decrypt(); + + expect(cipherView).toMatchObject({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: "EncryptedString", + notes: "EncryptedString", + type: 3, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + card: cardView, + attachments: null, + fields: null, + passwordHistory: null, + collectionIds: undefined, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + deletedDate: null, + reprompt: 0, + localData: undefined, + }); + }); + }); + + describe("IdentityCipher", () => { + let cipherData: CipherData; + + beforeEach(() => { + cipherData = { + id: "id", + organizationId: "orgId", + folderId: "folderId", + edit: true, + viewPassword: true, + organizationUseTotp: true, + favorite: false, + revisionDate: "2022-01-31T12:00:00.000Z", + type: CipherType.Identity, + name: "EncryptedString", + notes: "EncryptedString", + deletedDate: null, + reprompt: CipherRepromptType.None, + identity: { + title: "EncryptedString", + firstName: "EncryptedString", + middleName: "EncryptedString", + lastName: "EncryptedString", + address1: "EncryptedString", + address2: "EncryptedString", + address3: "EncryptedString", + city: "EncryptedString", + state: "EncryptedString", + postalCode: "EncryptedString", + country: "EncryptedString", + company: "EncryptedString", + email: "EncryptedString", + phone: "EncryptedString", + ssn: "EncryptedString", + username: "EncryptedString", + passportNumber: "EncryptedString", + licenseNumber: "EncryptedString", + }, + }; + }); + + it("Convert", () => { + const cipher = new Cipher(cipherData); + + expect(cipher).toEqual({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: { encryptedString: "EncryptedString", encryptionType: 0 }, + notes: { encryptedString: "EncryptedString", encryptionType: 0 }, + type: 4, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + collectionIds: undefined, + localData: null, + deletedDate: null, + reprompt: 0, + identity: { + title: { encryptedString: "EncryptedString", encryptionType: 0 }, + firstName: { encryptedString: "EncryptedString", encryptionType: 0 }, + middleName: { encryptedString: "EncryptedString", encryptionType: 0 }, + lastName: { encryptedString: "EncryptedString", encryptionType: 0 }, + address1: { encryptedString: "EncryptedString", encryptionType: 0 }, + address2: { encryptedString: "EncryptedString", encryptionType: 0 }, + address3: { encryptedString: "EncryptedString", encryptionType: 0 }, + city: { encryptedString: "EncryptedString", encryptionType: 0 }, + state: { encryptedString: "EncryptedString", encryptionType: 0 }, + postalCode: { encryptedString: "EncryptedString", encryptionType: 0 }, + country: { encryptedString: "EncryptedString", encryptionType: 0 }, + company: { encryptedString: "EncryptedString", encryptionType: 0 }, + email: { encryptedString: "EncryptedString", encryptionType: 0 }, + phone: { encryptedString: "EncryptedString", encryptionType: 0 }, + ssn: { encryptedString: "EncryptedString", encryptionType: 0 }, + username: { encryptedString: "EncryptedString", encryptionType: 0 }, + passportNumber: { encryptedString: "EncryptedString", encryptionType: 0 }, + licenseNumber: { encryptedString: "EncryptedString", encryptionType: 0 }, + }, + attachments: null, + fields: null, + passwordHistory: null, + }); + }); + + it("toCipherData", () => { + const cipher = new Cipher(cipherData); + expect(cipher.toCipherData()).toEqual(cipherData); + }); + + it("Decrypt", async () => { + const cipher = new Cipher(); + cipher.id = "id"; + cipher.organizationId = "orgId"; + cipher.folderId = "folderId"; + cipher.edit = true; + cipher.viewPassword = true; + cipher.organizationUseTotp = true; + cipher.favorite = false; + cipher.revisionDate = new Date("2022-01-31T12:00:00.000Z"); + cipher.type = CipherType.Identity; + cipher.name = mockEnc("EncryptedString"); + cipher.notes = mockEnc("EncryptedString"); + cipher.deletedDate = null; + cipher.reprompt = CipherRepromptType.None; + + const identityView = new IdentityView(); + identityView.firstName = "firstName"; + identityView.lastName = "lastName"; + + const identity = Substitute.for(); + identity.decrypt(Arg.any(), Arg.any()).resolves(identityView); + cipher.identity = identity; + + const cipherView = await cipher.decrypt(); + + expect(cipherView).toMatchObject({ + id: "id", + organizationId: "orgId", + folderId: "folderId", + name: "EncryptedString", + notes: "EncryptedString", + type: 4, + favorite: false, + organizationUseTotp: true, + edit: true, + viewPassword: true, + identity: identityView, + attachments: null, + fields: null, + passwordHistory: null, + collectionIds: undefined, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + deletedDate: null, + reprompt: 0, + localData: undefined, + }); + }); + }); +}); diff --git a/libs/common/spec/domain/collection.spec.ts b/libs/common/spec/domain/collection.spec.ts new file mode 100644 index 0000000000..713bf2eba2 --- /dev/null +++ b/libs/common/spec/domain/collection.spec.ts @@ -0,0 +1,66 @@ +import { CollectionData } from "jslib-common/models/data/collectionData"; +import { Collection } from "jslib-common/models/domain/collection"; + +import { mockEnc } from "../utils"; + +describe("Collection", () => { + let data: CollectionData; + + beforeEach(() => { + data = { + id: "id", + organizationId: "orgId", + name: "encName", + externalId: "extId", + readOnly: true, + }; + }); + + it("Convert from empty", () => { + const data = new CollectionData({} as any); + const card = new Collection(data); + + expect(card).toEqual({ + externalId: null, + hidePasswords: null, + id: null, + name: null, + organizationId: null, + readOnly: null, + }); + }); + + it("Convert", () => { + const collection = new Collection(data); + + expect(collection).toEqual({ + id: "id", + organizationId: "orgId", + name: { encryptedString: "encName", encryptionType: 0 }, + externalId: "extId", + readOnly: true, + hidePasswords: null, + }); + }); + + it("Decrypt", async () => { + const collection = new Collection(); + collection.id = "id"; + collection.organizationId = "orgId"; + collection.name = mockEnc("encName"); + collection.externalId = "extId"; + collection.readOnly = false; + collection.hidePasswords = false; + + const view = await collection.decrypt(); + + expect(view).toEqual({ + externalId: "extId", + hidePasswords: false, + id: "id", + name: "encName", + organizationId: "orgId", + readOnly: false, + }); + }); +}); diff --git a/libs/common/spec/domain/encString.spec.ts b/libs/common/spec/domain/encString.spec.ts new file mode 100644 index 0000000000..e2477447d6 --- /dev/null +++ b/libs/common/spec/domain/encString.spec.ts @@ -0,0 +1,195 @@ +import Substitute, { Arg } from "@fluffy-spoon/substitute"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EncryptionType } from "jslib-common/enums/encryptionType"; +import { EncString } from "jslib-common/models/domain/encString"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { ContainerService } from "jslib-common/services/container.service"; + +describe("EncString", () => { + afterEach(() => { + (window as any).bitwardenContainerService = undefined; + }); + + describe("Rsa2048_OaepSha256_B64", () => { + it("constructor", () => { + const encString = new EncString(EncryptionType.Rsa2048_OaepSha256_B64, "data"); + + expect(encString).toEqual({ + data: "data", + encryptedString: "3.data", + encryptionType: 3, + }); + }); + + describe("parse existing", () => { + it("valid", () => { + const encString = new EncString("3.data"); + + expect(encString).toEqual({ + data: "data", + encryptedString: "3.data", + encryptionType: 3, + }); + }); + + it("invalid", () => { + const encString = new EncString("3.data|test"); + + expect(encString).toEqual({ + encryptedString: "3.data|test", + encryptionType: 3, + }); + }); + }); + + describe("decrypt", () => { + const encString = new EncString(EncryptionType.Rsa2048_OaepSha256_B64, "data"); + + const cryptoService = Substitute.for(); + cryptoService.getOrgKey(null).resolves(null); + cryptoService.decryptToUtf8(encString, Arg.any()).resolves("decrypted"); + + beforeEach(() => { + (window as any).bitwardenContainerService = new ContainerService(cryptoService); + }); + + it("decrypts correctly", async () => { + const decrypted = await encString.decrypt(null); + + expect(decrypted).toBe("decrypted"); + }); + + it("result should be cached", async () => { + const decrypted = await encString.decrypt(null); + cryptoService.received(1).decryptToUtf8(Arg.any(), Arg.any()); + + expect(decrypted).toBe("decrypted"); + }); + }); + }); + + describe("AesCbc256_B64", () => { + it("constructor", () => { + const encString = new EncString(EncryptionType.AesCbc256_B64, "data", "iv"); + + expect(encString).toEqual({ + data: "data", + encryptedString: "0.iv|data", + encryptionType: 0, + iv: "iv", + }); + }); + + describe("parse existing", () => { + it("valid", () => { + const encString = new EncString("0.iv|data"); + + expect(encString).toEqual({ + data: "data", + encryptedString: "0.iv|data", + encryptionType: 0, + iv: "iv", + }); + }); + + it("invalid", () => { + const encString = new EncString("0.iv|data|mac"); + + expect(encString).toEqual({ + encryptedString: "0.iv|data|mac", + encryptionType: 0, + }); + }); + }); + }); + + describe("AesCbc256_HmacSha256_B64", () => { + it("constructor", () => { + const encString = new EncString(EncryptionType.AesCbc256_HmacSha256_B64, "data", "iv", "mac"); + + expect(encString).toEqual({ + data: "data", + encryptedString: "2.iv|data|mac", + encryptionType: 2, + iv: "iv", + mac: "mac", + }); + }); + + it("valid", () => { + const encString = new EncString("2.iv|data|mac"); + + expect(encString).toEqual({ + data: "data", + encryptedString: "2.iv|data|mac", + encryptionType: 2, + iv: "iv", + mac: "mac", + }); + }); + + it("invalid", () => { + const encString = new EncString("2.iv|data"); + + expect(encString).toEqual({ + encryptedString: "2.iv|data", + encryptionType: 2, + }); + }); + }); + + it("Exit early if null", () => { + const encString = new EncString(null); + + expect(encString).toEqual({ + encryptedString: null, + }); + }); + + describe("decrypt", () => { + it("throws exception when bitwarden container not initialized", async () => { + const encString = new EncString(null); + + expect.assertions(1); + try { + await encString.decrypt(null); + } catch (e) { + expect(e.message).toEqual("global bitwardenContainerService not initialized."); + } + }); + + it("handles value it can't decrypt", async () => { + const encString = new EncString(null); + + const cryptoService = Substitute.for(); + cryptoService.getOrgKey(null).resolves(null); + cryptoService.decryptToUtf8(encString, Arg.any()).throws("error"); + + (window as any).bitwardenContainerService = new ContainerService(cryptoService); + + const decrypted = await encString.decrypt(null); + + expect(decrypted).toBe("[error: cannot decrypt]"); + + expect(encString).toEqual({ + decryptedValue: "[error: cannot decrypt]", + encryptedString: null, + }); + }); + + it("passes along key", async () => { + const encString = new EncString(null); + const key = Substitute.for(); + + const cryptoService = Substitute.for(); + cryptoService.getOrgKey(null).resolves(null); + + (window as any).bitwardenContainerService = new ContainerService(cryptoService); + + await encString.decrypt(null, key); + + cryptoService.received().decryptToUtf8(encString, key); + }); + }); +}); diff --git a/libs/common/spec/domain/field.spec.ts b/libs/common/spec/domain/field.spec.ts new file mode 100644 index 0000000000..40ceb710a4 --- /dev/null +++ b/libs/common/spec/domain/field.spec.ts @@ -0,0 +1,64 @@ +import { FieldType } from "jslib-common/enums/fieldType"; +import { FieldData } from "jslib-common/models/data/fieldData"; +import { Field } from "jslib-common/models/domain/field"; + +import { mockEnc } from "../utils"; + +describe("Field", () => { + let data: FieldData; + + beforeEach(() => { + data = { + type: FieldType.Text, + name: "encName", + value: "encValue", + linkedId: null, + }; + }); + + it("Convert from empty", () => { + const data = new FieldData(); + const field = new Field(data); + + expect(field).toEqual({ + type: undefined, + name: null, + value: null, + linkedId: undefined, + }); + }); + + it("Convert", () => { + const field = new Field(data); + + expect(field).toEqual({ + type: FieldType.Text, + name: { encryptedString: "encName", encryptionType: 0 }, + value: { encryptedString: "encValue", encryptionType: 0 }, + linkedId: null, + }); + }); + + it("toFieldData", () => { + const field = new Field(data); + expect(field.toFieldData()).toEqual(data); + }); + + it("Decrypt", async () => { + const field = new Field(); + field.type = FieldType.Text; + field.name = mockEnc("encName"); + field.value = mockEnc("encValue"); + + const view = await field.decrypt(null); + + expect(view).toEqual({ + type: 0, + name: "encName", + value: "encValue", + newField: false, + showCount: false, + showValue: false, + }); + }); +}); diff --git a/libs/common/spec/domain/folder.spec.ts b/libs/common/spec/domain/folder.spec.ts new file mode 100644 index 0000000000..20ca6b9523 --- /dev/null +++ b/libs/common/spec/domain/folder.spec.ts @@ -0,0 +1,41 @@ +import { FolderData } from "jslib-common/models/data/folderData"; +import { Folder } from "jslib-common/models/domain/folder"; + +import { mockEnc } from "../utils"; + +describe("Folder", () => { + let data: FolderData; + + beforeEach(() => { + data = { + id: "id", + name: "encName", + revisionDate: "2022-01-31T12:00:00.000Z", + }; + }); + + it("Convert", () => { + const field = new Folder(data); + + expect(field).toEqual({ + id: "id", + name: { encryptedString: "encName", encryptionType: 0 }, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + }); + }); + + it("Decrypt", async () => { + const folder = new Folder(); + folder.id = "id"; + folder.name = mockEnc("encName"); + folder.revisionDate = new Date("2022-01-31T12:00:00.000Z"); + + const view = await folder.decrypt(); + + expect(view).toEqual({ + id: "id", + name: "encName", + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + }); + }); +}); diff --git a/libs/common/spec/domain/identity.spec.ts b/libs/common/spec/domain/identity.spec.ts new file mode 100644 index 0000000000..ffaf504925 --- /dev/null +++ b/libs/common/spec/domain/identity.spec.ts @@ -0,0 +1,134 @@ +import { IdentityData } from "jslib-common/models/data/identityData"; +import { Identity } from "jslib-common/models/domain/identity"; + +import { mockEnc } from "../utils"; + +describe("Identity", () => { + let data: IdentityData; + + beforeEach(() => { + data = { + title: "enctitle", + firstName: "encfirstName", + middleName: "encmiddleName", + lastName: "enclastName", + address1: "encaddress1", + address2: "encaddress2", + address3: "encaddress3", + city: "enccity", + state: "encstate", + postalCode: "encpostalCode", + country: "enccountry", + company: "enccompany", + email: "encemail", + phone: "encphone", + ssn: "encssn", + username: "encusername", + passportNumber: "encpassportNumber", + licenseNumber: "enclicenseNumber", + }; + }); + + it("Convert from empty", () => { + const data = new IdentityData(); + const identity = new Identity(data); + + expect(identity).toEqual({ + address1: null, + address2: null, + address3: null, + city: null, + company: null, + country: null, + email: null, + firstName: null, + lastName: null, + licenseNumber: null, + middleName: null, + passportNumber: null, + phone: null, + postalCode: null, + ssn: null, + state: null, + title: null, + username: null, + }); + }); + + it("Convert", () => { + const identity = new Identity(data); + + expect(identity).toEqual({ + title: { encryptedString: "enctitle", encryptionType: 0 }, + firstName: { encryptedString: "encfirstName", encryptionType: 0 }, + middleName: { encryptedString: "encmiddleName", encryptionType: 0 }, + lastName: { encryptedString: "enclastName", encryptionType: 0 }, + address1: { encryptedString: "encaddress1", encryptionType: 0 }, + address2: { encryptedString: "encaddress2", encryptionType: 0 }, + address3: { encryptedString: "encaddress3", encryptionType: 0 }, + city: { encryptedString: "enccity", encryptionType: 0 }, + state: { encryptedString: "encstate", encryptionType: 0 }, + postalCode: { encryptedString: "encpostalCode", encryptionType: 0 }, + country: { encryptedString: "enccountry", encryptionType: 0 }, + company: { encryptedString: "enccompany", encryptionType: 0 }, + email: { encryptedString: "encemail", encryptionType: 0 }, + phone: { encryptedString: "encphone", encryptionType: 0 }, + ssn: { encryptedString: "encssn", encryptionType: 0 }, + username: { encryptedString: "encusername", encryptionType: 0 }, + passportNumber: { encryptedString: "encpassportNumber", encryptionType: 0 }, + licenseNumber: { encryptedString: "enclicenseNumber", encryptionType: 0 }, + }); + }); + + it("toIdentityData", () => { + const identity = new Identity(data); + expect(identity.toIdentityData()).toEqual(data); + }); + + it("Decrypt", async () => { + const identity = new Identity(); + + identity.title = mockEnc("mockTitle"); + identity.firstName = mockEnc("mockFirstName"); + identity.middleName = mockEnc("mockMiddleName"); + identity.lastName = mockEnc("mockLastName"); + identity.address1 = mockEnc("mockAddress1"); + identity.address2 = mockEnc("mockAddress2"); + identity.address3 = mockEnc("mockAddress3"); + identity.city = mockEnc("mockCity"); + identity.state = mockEnc("mockState"); + identity.postalCode = mockEnc("mockPostalCode"); + identity.country = mockEnc("mockCountry"); + identity.company = mockEnc("mockCompany"); + identity.email = mockEnc("mockEmail"); + identity.phone = mockEnc("mockPhone"); + identity.ssn = mockEnc("mockSsn"); + identity.username = mockEnc("mockUsername"); + identity.passportNumber = mockEnc("mockPassportNumber"); + identity.licenseNumber = mockEnc("mockLicenseNumber"); + + const view = await identity.decrypt(null); + + expect(view).toEqual({ + _firstName: "mockFirstName", + _lastName: "mockLastName", + _subTitle: null, + address1: "mockAddress1", + address2: "mockAddress2", + address3: "mockAddress3", + city: "mockCity", + company: "mockCompany", + country: "mockCountry", + email: "mockEmail", + licenseNumber: "mockLicenseNumber", + middleName: "mockMiddleName", + passportNumber: "mockPassportNumber", + phone: "mockPhone", + postalCode: "mockPostalCode", + ssn: "mockSsn", + state: "mockState", + title: "mockTitle", + username: "mockUsername", + }); + }); +}); diff --git a/libs/common/spec/domain/login.spec.ts b/libs/common/spec/domain/login.spec.ts new file mode 100644 index 0000000000..88c31a5f7a --- /dev/null +++ b/libs/common/spec/domain/login.spec.ts @@ -0,0 +1,101 @@ +import Substitute, { Arg } from "@fluffy-spoon/substitute"; + +import { UriMatchType } from "jslib-common/enums/uriMatchType"; +import { LoginData } from "jslib-common/models/data/loginData"; +import { Login } from "jslib-common/models/domain/login"; +import { LoginUri } from "jslib-common/models/domain/loginUri"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; + +import { mockEnc } from "../utils"; + +describe("Login DTO", () => { + it("Convert from empty LoginData", () => { + const data = new LoginData(); + const login = new Login(data); + + expect(login).toEqual({ + passwordRevisionDate: null, + autofillOnPageLoad: undefined, + username: null, + password: null, + totp: null, + }); + }); + + it("Convert from full LoginData", () => { + const data: LoginData = { + uris: [{ uri: "uri", match: UriMatchType.Domain }], + username: "username", + password: "password", + passwordRevisionDate: "2022-01-31T12:00:00.000Z", + totp: "123", + autofillOnPageLoad: false, + }; + const login = new Login(data); + + expect(login).toEqual({ + passwordRevisionDate: new Date("2022-01-31T12:00:00.000Z"), + autofillOnPageLoad: false, + username: { encryptedString: "username", encryptionType: 0 }, + password: { encryptedString: "password", encryptionType: 0 }, + totp: { encryptedString: "123", encryptionType: 0 }, + uris: [{ match: 0, uri: { encryptedString: "uri", encryptionType: 0 } }], + }); + }); + + it("Initialize without LoginData", () => { + const login = new Login(); + + expect(login).toEqual({}); + }); + + it("Decrypts correctly", async () => { + const loginUri = Substitute.for(); + const loginUriView = new LoginUriView(); + loginUriView.uri = "decrypted uri"; + loginUri.decrypt(Arg.any()).resolves(loginUriView); + + const login = new Login(); + login.uris = [loginUri]; + login.username = mockEnc("encrypted username"); + login.password = mockEnc("encrypted password"); + login.passwordRevisionDate = new Date("2022-01-31T12:00:00.000Z"); + login.totp = mockEnc("encrypted totp"); + login.autofillOnPageLoad = true; + + const loginView = await login.decrypt(null); + expect(loginView).toEqual({ + username: "encrypted username", + password: "encrypted password", + passwordRevisionDate: new Date("2022-01-31T12:00:00.000Z"), + totp: "encrypted totp", + uris: [ + { + match: null, + _uri: "decrypted uri", + _domain: null, + _hostname: null, + _host: null, + _canLaunch: null, + }, + ], + autofillOnPageLoad: true, + }); + }); + + it("Converts from LoginData and back", () => { + const data: LoginData = { + uris: [{ uri: "uri", match: UriMatchType.Domain }], + username: "username", + password: "password", + passwordRevisionDate: "2022-01-31T12:00:00.000Z", + totp: "123", + autofillOnPageLoad: false, + }; + const login = new Login(data); + + const loginData = login.toLoginData(); + + expect(loginData).toEqual(data); + }); +}); diff --git a/libs/common/spec/domain/loginUri.spec.ts b/libs/common/spec/domain/loginUri.spec.ts new file mode 100644 index 0000000000..2ea5ab59ad --- /dev/null +++ b/libs/common/spec/domain/loginUri.spec.ts @@ -0,0 +1,57 @@ +import { UriMatchType } from "jslib-common/enums/uriMatchType"; +import { LoginUriData } from "jslib-common/models/data/loginUriData"; +import { LoginUri } from "jslib-common/models/domain/loginUri"; + +import { mockEnc } from "../utils"; + +describe("LoginUri", () => { + let data: LoginUriData; + + beforeEach(() => { + data = { + uri: "encUri", + match: UriMatchType.Domain, + }; + }); + + it("Convert from empty", () => { + const data = new LoginUriData(); + const loginUri = new LoginUri(data); + + expect(loginUri).toEqual({ + match: null, + uri: null, + }); + }); + + it("Convert", () => { + const loginUri = new LoginUri(data); + + expect(loginUri).toEqual({ + match: 0, + uri: { encryptedString: "encUri", encryptionType: 0 }, + }); + }); + + it("toLoginUriData", () => { + const loginUri = new LoginUri(data); + expect(loginUri.toLoginUriData()).toEqual(data); + }); + + it("Decrypt", async () => { + const loginUri = new LoginUri(); + loginUri.match = UriMatchType.Exact; + loginUri.uri = mockEnc("uri"); + + const view = await loginUri.decrypt(null); + + expect(view).toEqual({ + _canLaunch: null, + _domain: null, + _host: null, + _hostname: null, + _uri: "uri", + match: 3, + }); + }); +}); diff --git a/libs/common/spec/domain/password.spec.ts b/libs/common/spec/domain/password.spec.ts new file mode 100644 index 0000000000..4054c9510a --- /dev/null +++ b/libs/common/spec/domain/password.spec.ts @@ -0,0 +1,51 @@ +import { PasswordHistoryData } from "jslib-common/models/data/passwordHistoryData"; +import { Password } from "jslib-common/models/domain/password"; + +import { mockEnc } from "../utils"; + +describe("Password", () => { + let data: PasswordHistoryData; + + beforeEach(() => { + data = { + password: "encPassword", + lastUsedDate: "2022-01-31T12:00:00.000Z", + }; + }); + + it("Convert from empty", () => { + const data = new PasswordHistoryData(); + const password = new Password(data); + + expect(password).toMatchObject({ + password: null, + }); + }); + + it("Convert", () => { + const password = new Password(data); + + expect(password).toEqual({ + password: { encryptedString: "encPassword", encryptionType: 0 }, + lastUsedDate: new Date("2022-01-31T12:00:00.000Z"), + }); + }); + + it("toPasswordHistoryData", () => { + const password = new Password(data); + expect(password.toPasswordHistoryData()).toEqual(data); + }); + + it("Decrypt", async () => { + const password = new Password(); + password.password = mockEnc("password"); + password.lastUsedDate = new Date("2022-01-31T12:00:00.000Z"); + + const view = await password.decrypt(null); + + expect(view).toEqual({ + password: "password", + lastUsedDate: new Date("2022-01-31T12:00:00.000Z"), + }); + }); +}); diff --git a/libs/common/spec/domain/secureNote.spec.ts b/libs/common/spec/domain/secureNote.spec.ts new file mode 100644 index 0000000000..50ca67ed26 --- /dev/null +++ b/libs/common/spec/domain/secureNote.spec.ts @@ -0,0 +1,46 @@ +import { SecureNoteType } from "jslib-common/enums/secureNoteType"; +import { SecureNoteData } from "jslib-common/models/data/secureNoteData"; +import { SecureNote } from "jslib-common/models/domain/secureNote"; + +describe("SecureNote", () => { + let data: SecureNoteData; + + beforeEach(() => { + data = { + type: SecureNoteType.Generic, + }; + }); + + it("Convert from empty", () => { + const data = new SecureNoteData(); + const secureNote = new SecureNote(data); + + expect(secureNote).toEqual({ + type: undefined, + }); + }); + + it("Convert", () => { + const secureNote = new SecureNote(data); + + expect(secureNote).toEqual({ + type: 0, + }); + }); + + it("toSecureNoteData", () => { + const secureNote = new SecureNote(data); + expect(secureNote.toSecureNoteData()).toEqual(data); + }); + + it("Decrypt", async () => { + const secureNote = new SecureNote(); + secureNote.type = SecureNoteType.Generic; + + const view = await secureNote.decrypt(null); + + expect(view).toEqual({ + type: 0, + }); + }); +}); diff --git a/libs/common/spec/domain/send.spec.ts b/libs/common/spec/domain/send.spec.ts new file mode 100644 index 0000000000..c97f1be64e --- /dev/null +++ b/libs/common/spec/domain/send.spec.ts @@ -0,0 +1,140 @@ +import Substitute, { Arg, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { SendType } from "jslib-common/enums/sendType"; +import { SendData } from "jslib-common/models/data/sendData"; +import { EncString } from "jslib-common/models/domain/encString"; +import { Send } from "jslib-common/models/domain/send"; +import { SendText } from "jslib-common/models/domain/sendText"; +import { ContainerService } from "jslib-common/services/container.service"; + +import { makeStaticByteArray, mockEnc } from "../utils"; + +describe("Send", () => { + let data: SendData; + + beforeEach(() => { + data = { + id: "id", + accessId: "accessId", + type: SendType.Text, + name: "encName", + notes: "encNotes", + text: { + text: "encText", + hidden: true, + }, + file: null, + key: "encKey", + maxAccessCount: null, + accessCount: 10, + revisionDate: "2022-01-31T12:00:00.000Z", + expirationDate: "2022-01-31T12:00:00.000Z", + deletionDate: "2022-01-31T12:00:00.000Z", + password: "password", + disabled: false, + hideEmail: true, + }; + }); + + it("Convert from empty", () => { + const data = new SendData(); + const send = new Send(data); + + expect(send).toEqual({ + id: null, + accessId: null, + type: undefined, + name: null, + notes: null, + text: undefined, + file: undefined, + key: null, + maxAccessCount: undefined, + accessCount: undefined, + revisionDate: null, + expirationDate: null, + deletionDate: null, + password: undefined, + disabled: undefined, + hideEmail: undefined, + }); + }); + + it("Convert", () => { + const send = new Send(data); + + expect(send).toEqual({ + id: "id", + accessId: "accessId", + type: SendType.Text, + name: { encryptedString: "encName", encryptionType: 0 }, + notes: { encryptedString: "encNotes", encryptionType: 0 }, + text: { + text: { encryptedString: "encText", encryptionType: 0 }, + hidden: true, + }, + key: { encryptedString: "encKey", encryptionType: 0 }, + maxAccessCount: null, + accessCount: 10, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + expirationDate: new Date("2022-01-31T12:00:00.000Z"), + deletionDate: new Date("2022-01-31T12:00:00.000Z"), + password: "password", + disabled: false, + hideEmail: true, + }); + }); + + it("Decrypt", async () => { + const text = Substitute.for(); + text.decrypt(Arg.any()).resolves("textView" as any); + + const send = new Send(); + send.id = "id"; + send.accessId = "accessId"; + send.type = SendType.Text; + send.name = mockEnc("name"); + send.notes = mockEnc("notes"); + send.text = text; + send.key = mockEnc("key"); + send.accessCount = 10; + send.revisionDate = new Date("2022-01-31T12:00:00.000Z"); + send.expirationDate = new Date("2022-01-31T12:00:00.000Z"); + send.deletionDate = new Date("2022-01-31T12:00:00.000Z"); + send.password = "password"; + send.disabled = false; + send.hideEmail = true; + + const cryptoService = Substitute.for(); + cryptoService.decryptToBytes(send.key, null).resolves(makeStaticByteArray(32)); + cryptoService.makeSendKey(Arg.any()).resolves("cryptoKey" as any); + + (window as any).bitwardenContainerService = new ContainerService(cryptoService); + + const view = await send.decrypt(); + + text.received(1).decrypt("cryptoKey" as any); + (send.name as SubstituteOf).received(1).decrypt(null, "cryptoKey" as any); + + expect(view).toMatchObject({ + id: "id", + accessId: "accessId", + name: "name", + notes: "notes", + type: 0, + key: expect.anything(), + cryptoKey: "cryptoKey", + file: expect.anything(), + text: "textView", + maxAccessCount: undefined, + accessCount: 10, + revisionDate: new Date("2022-01-31T12:00:00.000Z"), + expirationDate: new Date("2022-01-31T12:00:00.000Z"), + deletionDate: new Date("2022-01-31T12:00:00.000Z"), + password: "password", + disabled: false, + hideEmail: true, + }); + }); +}); diff --git a/libs/common/spec/domain/sendAccess.spec.ts b/libs/common/spec/domain/sendAccess.spec.ts new file mode 100644 index 0000000000..fc3001a5b9 --- /dev/null +++ b/libs/common/spec/domain/sendAccess.spec.ts @@ -0,0 +1,84 @@ +import Substitute, { Arg } from "@fluffy-spoon/substitute"; + +import { SendType } from "jslib-common/enums/sendType"; +import { SendAccess } from "jslib-common/models/domain/sendAccess"; +import { SendText } from "jslib-common/models/domain/sendText"; +import { SendAccessResponse } from "jslib-common/models/response/sendAccessResponse"; + +import { mockEnc } from "../utils"; + +describe("SendAccess", () => { + let request: SendAccessResponse; + + beforeEach(() => { + request = { + id: "id", + type: SendType.Text, + name: "encName", + file: null, + text: { + text: "encText", + hidden: true, + }, + expirationDate: new Date("2022-01-31T12:00:00.000Z"), + creatorIdentifier: "creatorIdentifier", + } as SendAccessResponse; + }); + + it("Convert from empty", () => { + const request = new SendAccessResponse({}); + const sendAccess = new SendAccess(request); + + expect(sendAccess).toEqual({ + id: null, + type: undefined, + name: null, + creatorIdentifier: null, + expirationDate: null, + }); + }); + + it("Convert", () => { + const sendAccess = new SendAccess(request); + + expect(sendAccess).toEqual({ + id: "id", + type: 0, + name: { encryptedString: "encName", encryptionType: 0 }, + text: { + hidden: true, + text: { encryptedString: "encText", encryptionType: 0 }, + }, + expirationDate: new Date("2022-01-31T12:00:00.000Z"), + creatorIdentifier: "creatorIdentifier", + }); + }); + + it("Decrypt", async () => { + const sendAccess = new SendAccess(); + sendAccess.id = "id"; + sendAccess.type = SendType.Text; + sendAccess.name = mockEnc("name"); + + const text = Substitute.for(); + text.decrypt(Arg.any()).resolves({} as any); + sendAccess.text = text; + + sendAccess.expirationDate = new Date("2022-01-31T12:00:00.000Z"); + sendAccess.creatorIdentifier = "creatorIdentifier"; + + const view = await sendAccess.decrypt(null); + + text.received(1).decrypt(Arg.any()); + + expect(view).toEqual({ + id: "id", + type: 0, + name: "name", + text: {}, + file: expect.anything(), + expirationDate: new Date("2022-01-31T12:00:00.000Z"), + creatorIdentifier: "creatorIdentifier", + }); + }); +}); diff --git a/libs/common/spec/domain/sendFile.spec.ts b/libs/common/spec/domain/sendFile.spec.ts new file mode 100644 index 0000000000..9fde0b76df --- /dev/null +++ b/libs/common/spec/domain/sendFile.spec.ts @@ -0,0 +1,57 @@ +import { SendFileData } from "jslib-common/models/data/sendFileData"; +import { SendFile } from "jslib-common/models/domain/sendFile"; + +import { mockEnc } from "../utils"; + +describe("SendFile", () => { + let data: SendFileData; + + beforeEach(() => { + data = { + id: "id", + size: "1100", + sizeName: "1.1 KB", + fileName: "encFileName", + }; + }); + + it("Convert from empty", () => { + const data = new SendFileData(); + const sendFile = new SendFile(data); + + expect(sendFile).toEqual({ + fileName: null, + id: null, + size: undefined, + sizeName: null, + }); + }); + + it("Convert", () => { + const sendFile = new SendFile(data); + + expect(sendFile).toEqual({ + id: "id", + size: "1100", + sizeName: "1.1 KB", + fileName: { encryptedString: "encFileName", encryptionType: 0 }, + }); + }); + + it("Decrypt", async () => { + const sendFile = new SendFile(); + sendFile.id = "id"; + sendFile.size = "1100"; + sendFile.sizeName = "1.1 KB"; + sendFile.fileName = mockEnc("fileName"); + + const view = await sendFile.decrypt(null); + + expect(view).toEqual({ + fileName: "fileName", + id: "id", + size: "1100", + sizeName: "1.1 KB", + }); + }); +}); diff --git a/libs/common/spec/domain/sendText.spec.ts b/libs/common/spec/domain/sendText.spec.ts new file mode 100644 index 0000000000..776a4c5705 --- /dev/null +++ b/libs/common/spec/domain/sendText.spec.ts @@ -0,0 +1,47 @@ +import { SendTextData } from "jslib-common/models/data/sendTextData"; +import { SendText } from "jslib-common/models/domain/sendText"; + +import { mockEnc } from "../utils"; + +describe("SendText", () => { + let data: SendTextData; + + beforeEach(() => { + data = { + text: "encText", + hidden: false, + }; + }); + + it("Convert from empty", () => { + const data = new SendTextData(); + const secureNote = new SendText(data); + + expect(secureNote).toEqual({ + hidden: undefined, + text: null, + }); + }); + + it("Convert", () => { + const secureNote = new SendText(data); + + expect(secureNote).toEqual({ + hidden: false, + text: { encryptedString: "encText", encryptionType: 0 }, + }); + }); + + it("Decrypt", async () => { + const secureNote = new SendText(); + secureNote.text = mockEnc("text"); + secureNote.hidden = true; + + const view = await secureNote.decrypt(null); + + expect(view).toEqual({ + text: "text", + hidden: true, + }); + }); +}); diff --git a/libs/common/spec/domain/symmetricCryptoKey.spec.ts b/libs/common/spec/domain/symmetricCryptoKey.spec.ts new file mode 100644 index 0000000000..62f096c1ec --- /dev/null +++ b/libs/common/spec/domain/symmetricCryptoKey.spec.ts @@ -0,0 +1,69 @@ +import { EncryptionType } from "jslib-common/enums/encryptionType"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; + +import { makeStaticByteArray } from "../utils"; + +describe("SymmetricCryptoKey", () => { + it("errors if no key", () => { + const t = () => { + new SymmetricCryptoKey(null); + }; + + expect(t).toThrowError("Must provide key"); + }); + + describe("guesses encKey from key length", () => { + it("AesCbc256_B64", () => { + const key = makeStaticByteArray(32); + const cryptoKey = new SymmetricCryptoKey(key); + + expect(cryptoKey).toEqual({ + encKey: key, + encKeyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=", + encType: 0, + key: key, + keyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=", + macKey: null, + }); + }); + + it("AesCbc128_HmacSha256_B64", () => { + const key = makeStaticByteArray(32); + const cryptoKey = new SymmetricCryptoKey(key, EncryptionType.AesCbc128_HmacSha256_B64); + + expect(cryptoKey).toEqual({ + encKey: key.slice(0, 16), + encKeyB64: "AAECAwQFBgcICQoLDA0ODw==", + encType: 1, + key: key, + keyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=", + macKey: key.slice(16, 32), + macKeyB64: "EBESExQVFhcYGRobHB0eHw==", + }); + }); + + it("AesCbc256_HmacSha256_B64", () => { + const key = makeStaticByteArray(64); + const cryptoKey = new SymmetricCryptoKey(key); + + expect(cryptoKey).toEqual({ + encKey: key.slice(0, 32), + encKeyB64: "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8=", + encType: 2, + key: key, + keyB64: + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+Pw==", + macKey: key.slice(32, 64), + macKeyB64: "ICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8=", + }); + }); + + it("unknown length", () => { + const t = () => { + new SymmetricCryptoKey(makeStaticByteArray(30)); + }; + + expect(t).toThrowError("Unable to determine encType."); + }); + }); +}); diff --git a/libs/common/spec/importers/bitwardenJsonImporter.spec.ts b/libs/common/spec/importers/bitwardenJsonImporter.spec.ts new file mode 100644 index 0000000000..94b035286b --- /dev/null +++ b/libs/common/spec/importers/bitwardenJsonImporter.spec.ts @@ -0,0 +1,31 @@ +import { Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { BitwardenJsonImporter } from "jslib-common/importers/bitwardenJsonImporter"; + +import { data as passwordProtectedData } from "./testData/bitwardenJson/passwordProtected.json"; + +describe("bitwarden json importer", () => { + let sut: BitwardenJsonImporter; + let cryptoService: SubstituteOf; + let i18nService: SubstituteOf; + + beforeEach(() => { + cryptoService = Substitute.for(); + i18nService = Substitute.for(); + + sut = new BitwardenJsonImporter(cryptoService, i18nService); + }); + + it("should fail if password is needed", async () => { + expect((await sut.parse(passwordProtectedData)).success).toBe(false); + }); + + it("should return password needed error message", async () => { + const expected = "Password required error message"; + i18nService.t("importPasswordRequired").returns(expected); + + expect((await sut.parse(passwordProtectedData)).errorMessage).toEqual(expected); + }); +}); diff --git a/libs/common/spec/importers/bitwardenPasswordProtectedImporter.spec.ts b/libs/common/spec/importers/bitwardenPasswordProtectedImporter.spec.ts new file mode 100644 index 0000000000..ed2434ee53 --- /dev/null +++ b/libs/common/spec/importers/bitwardenPasswordProtectedImporter.spec.ts @@ -0,0 +1,113 @@ +import Substitute, { Arg, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { KdfType } from "jslib-common/enums/kdfType"; +import { BitwardenPasswordProtectedImporter } from "jslib-common/importers/bitwardenPasswordProtectedImporter"; +import { Utils } from "jslib-common/misc/utils"; +import { ImportResult } from "jslib-common/models/domain/importResult"; + +import { data as emptyDecryptedData } from "./testData/bitwardenJson/empty.json"; + +describe("BitwardenPasswordProtectedImporter", () => { + let importer: BitwardenPasswordProtectedImporter; + let cryptoService: SubstituteOf; + let i18nService: SubstituteOf; + const password = Utils.newGuid(); + const result = new ImportResult(); + let jDoc: { + encrypted?: boolean; + passwordProtected?: boolean; + salt?: string; + kdfIterations?: any; + kdfType?: any; + encKeyValidation_DO_NOT_EDIT?: string; + data?: string; + }; + + beforeEach(() => { + cryptoService = Substitute.for(); + i18nService = Substitute.for(); + + jDoc = { + encrypted: true, + passwordProtected: true, + salt: "c2FsdA==", + kdfIterations: 100000, + kdfType: KdfType.PBKDF2_SHA256, + encKeyValidation_DO_NOT_EDIT: Utils.newGuid(), + data: Utils.newGuid(), + }; + + result.success = true; + importer = new BitwardenPasswordProtectedImporter(cryptoService, i18nService, password); + }); + + describe("Required Json Data", () => { + it("succeeds with default jdoc", async () => { + cryptoService.decryptToUtf8(Arg.any(), Arg.any()).resolves(emptyDecryptedData); + + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(true); + }); + + it("fails if encrypted === false", async () => { + jDoc.encrypted = false; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if encrypted === null", async () => { + jDoc.encrypted = null; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if passwordProtected === false", async () => { + jDoc.passwordProtected = false; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if passwordProtected === null", async () => { + jDoc.passwordProtected = null; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if salt === null", async () => { + jDoc.salt = null; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if kdfIterations === null", async () => { + jDoc.kdfIterations = null; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if kdfIterations is not a number", async () => { + jDoc.kdfIterations = "not a number"; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if kdfType === null", async () => { + jDoc.kdfType = null; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if kdfType is not a string", async () => { + jDoc.kdfType = "not a valid kdf type"; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if kdfType is not a known kdfType", async () => { + jDoc.kdfType = -1; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if encKeyValidation_DO_NOT_EDIT === null", async () => { + jDoc.encKeyValidation_DO_NOT_EDIT = null; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + + it("fails if data === null", async () => { + jDoc.data = null; + expect((await importer.parse(JSON.stringify(jDoc))).success).toEqual(false); + }); + }); +}); diff --git a/libs/common/spec/importers/dashlaneCsvImporter.spec.ts b/libs/common/spec/importers/dashlaneCsvImporter.spec.ts new file mode 100644 index 0000000000..666e32323b --- /dev/null +++ b/libs/common/spec/importers/dashlaneCsvImporter.spec.ts @@ -0,0 +1,367 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { DashlaneCsvImporter as Importer } from "jslib-common/importers/dashlaneImporters/dashlaneCsvImporter"; + +import { credentialsData } from "./testData/dashlaneCsv/credentials.csv"; +import { identityData } from "./testData/dashlaneCsv/id.csv"; +import { multiplePersonalInfoData } from "./testData/dashlaneCsv/multiplePersonalInfo.csv"; +import { paymentsData } from "./testData/dashlaneCsv/payments.csv"; +import { personalInfoData } from "./testData/dashlaneCsv/personalInfo.csv"; +import { secureNoteData } from "./testData/dashlaneCsv/securenotes.csv"; + +describe("Dashlane CSV Importer", () => { + let importer: Importer; + beforeEach(() => { + importer = new Importer(); + }); + + it("should parse login records", async () => { + const result = await importer.parse(credentialsData); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("example.com"); + expect(cipher.login.username).toEqual("jdoe"); + expect(cipher.login.password).toEqual("somePassword"); + expect(cipher.login.totp).toEqual("someTOTPSeed"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("https://www.example.com"); + expect(cipher.notes).toEqual("some note for example.com"); + }); + + it("should parse an item and create a folder", async () => { + const result = await importer.parse(credentialsData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.folders.length).toBe(1); + expect(result.folders[0].name).toBe("Entertainment"); + expect(result.folderRelationships[0]).toEqual([0, 0]); + }); + + it("should parse payment records", async () => { + const result = await importer.parse(paymentsData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(2); + + // Account + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.Card); + expect(cipher.name).toBe("John's savings account"); + expect(cipher.card.brand).toBeNull(); + expect(cipher.card.cardholderName).toBe("John Doe"); + expect(cipher.card.number).toBe("accountNumber"); + expect(cipher.card.code).toBeNull(); + expect(cipher.card.expMonth).toBeNull(); + expect(cipher.card.expYear).toBeNull(); + + expect(cipher.fields.length).toBe(4); + + expect(cipher.fields[0].name).toBe("type"); + expect(cipher.fields[0].value).toBe("bank"); + + expect(cipher.fields[1].name).toBe("routing_number"); + expect(cipher.fields[1].value).toBe("routingNumber"); + + expect(cipher.fields[2].name).toBe("country"); + expect(cipher.fields[2].value).toBe("US"); + + expect(cipher.fields[3].name).toBe("issuing_bank"); + expect(cipher.fields[3].value).toBe("US-ALLY"); + + // CreditCard + const cipher2 = result.ciphers.shift(); + expect(cipher2.type).toBe(CipherType.Card); + expect(cipher2.name).toBe("John Doe"); + expect(cipher2.card.brand).toBe("Visa"); + expect(cipher2.card.cardholderName).toBe("John Doe"); + expect(cipher2.card.number).toBe("41111111111111111"); + expect(cipher2.card.code).toBe("123"); + expect(cipher2.card.expMonth).toBe("01"); + expect(cipher2.card.expYear).toBe("23"); + + expect(cipher2.fields.length).toBe(2); + + expect(cipher2.fields[0].name).toBe("type"); + expect(cipher2.fields[0].value).toBe("credit_card"); + + expect(cipher2.fields[1].name).toBe("country"); + expect(cipher2.fields[1].value).toBe("US"); + }); + + it("should parse ids records", async () => { + const result = await importer.parse(identityData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + + // Type card + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("John Doe card"); + expect(cipher.identity.fullName).toBe("John Doe"); + expect(cipher.identity.firstName).toBe("John"); + expect(cipher.identity.middleName).toBeNull(); + expect(cipher.identity.lastName).toBe("Doe"); + expect(cipher.identity.licenseNumber).toBe("123123123"); + + expect(cipher.fields.length).toBe(3); + + expect(cipher.fields[0].name).toEqual("type"); + expect(cipher.fields[0].value).toEqual("card"); + + expect(cipher.fields[1].name).toEqual("issue_date"); + expect(cipher.fields[1].value).toEqual("2022-1-30"); + + expect(cipher.fields[2].name).toEqual("expiration_date"); + expect(cipher.fields[2].value).toEqual("2032-1-30"); + + // Type passport + const cipher2 = result.ciphers.shift(); + expect(cipher2.type).toBe(CipherType.Identity); + expect(cipher2.name).toBe("John Doe passport"); + expect(cipher2.identity.fullName).toBe("John Doe"); + expect(cipher2.identity.firstName).toBe("John"); + expect(cipher2.identity.middleName).toBeNull(); + expect(cipher2.identity.lastName).toBe("Doe"); + expect(cipher2.identity.passportNumber).toBe("123123123"); + + expect(cipher2.fields.length).toBe(4); + + expect(cipher2.fields[0].name).toEqual("type"); + expect(cipher2.fields[0].value).toEqual("passport"); + expect(cipher2.fields[1].name).toEqual("issue_date"); + expect(cipher2.fields[1].value).toEqual("2022-1-30"); + expect(cipher2.fields[2].name).toEqual("expiration_date"); + expect(cipher2.fields[2].value).toEqual("2032-1-30"); + expect(cipher2.fields[3].name).toEqual("place_of_issue"); + expect(cipher2.fields[3].value).toEqual("somewhere in Germany"); + + // Type license + const cipher3 = result.ciphers.shift(); + expect(cipher3.type).toBe(CipherType.Identity); + expect(cipher3.name).toBe("John Doe license"); + expect(cipher3.identity.fullName).toBe("John Doe"); + expect(cipher3.identity.firstName).toBe("John"); + expect(cipher3.identity.middleName).toBeNull(); + expect(cipher3.identity.lastName).toBe("Doe"); + expect(cipher3.identity.licenseNumber).toBe("1234556"); + expect(cipher3.identity.state).toBe("DC"); + + expect(cipher3.fields.length).toBe(3); + expect(cipher3.fields[0].name).toEqual("type"); + expect(cipher3.fields[0].value).toEqual("license"); + expect(cipher3.fields[1].name).toEqual("issue_date"); + expect(cipher3.fields[1].value).toEqual("2022-8-10"); + expect(cipher3.fields[2].name).toEqual("expiration_date"); + expect(cipher3.fields[2].value).toEqual("2022-10-10"); + + // Type social_security + const cipher4 = result.ciphers.shift(); + expect(cipher4.type).toBe(CipherType.Identity); + expect(cipher4.name).toBe("John Doe social_security"); + expect(cipher4.identity.fullName).toBe("John Doe"); + expect(cipher4.identity.firstName).toBe("John"); + expect(cipher4.identity.middleName).toBeNull(); + expect(cipher4.identity.lastName).toBe("Doe"); + expect(cipher4.identity.ssn).toBe("123123123"); + + expect(cipher4.fields.length).toBe(1); + expect(cipher4.fields[0].name).toEqual("type"); + expect(cipher4.fields[0].value).toEqual("social_security"); + + // Type tax_number + const cipher5 = result.ciphers.shift(); + expect(cipher5.type).toBe(CipherType.Identity); + expect(cipher5.name).toBe("tax_number"); + expect(cipher5.identity.licenseNumber).toBe("123123123"); + + expect(cipher5.fields.length).toBe(1); + expect(cipher5.fields[0].name).toEqual("type"); + expect(cipher5.fields[0].value).toEqual("tax_number"); + }); + + it("should parse secureNote records", async () => { + const result = await importer.parse(secureNoteData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.SecureNote); + expect(cipher.name).toBe("01"); + expect(cipher.notes).toBe("test"); + }); + + it("should parse personal information records (multiple identities)", async () => { + const result = await importer.parse(multiplePersonalInfoData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(6); + + // name + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.SecureNote); + expect(cipher.name).toBe("MR John Doe"); + + expect(cipher.fields.length).toBe(7); + expect(cipher.fields[0].name).toEqual("type"); + expect(cipher.fields[0].value).toEqual("name"); + expect(cipher.fields[1].name).toEqual("title"); + expect(cipher.fields[1].value).toEqual("MR"); + expect(cipher.fields[2].name).toEqual("first_name"); + expect(cipher.fields[2].value).toEqual("John"); + expect(cipher.fields[3].name).toEqual("last_name"); + expect(cipher.fields[3].value).toEqual("Doe"); + expect(cipher.fields[4].name).toEqual("login"); + expect(cipher.fields[4].value).toEqual("jdoe"); + expect(cipher.fields[5].name).toEqual("date_of_birth"); + expect(cipher.fields[5].value).toEqual("2022-01-30"); + expect(cipher.fields[6].name).toEqual("place_of_birth"); + expect(cipher.fields[6].value).toEqual("world"); + + // email + const cipher2 = result.ciphers.shift(); + expect(cipher2.type).toBe(CipherType.SecureNote); + expect(cipher2.name).toBe("Johns email"); + + expect(cipher2.fields.length).toBe(4); + expect(cipher2.fields[0].name).toEqual("type"); + expect(cipher2.fields[0].value).toEqual("email"); + expect(cipher2.fields[1].name).toEqual("email"); + expect(cipher2.fields[1].value).toEqual("jdoe@example.com"); + expect(cipher2.fields[2].name).toEqual("email_type"); + expect(cipher2.fields[2].value).toEqual("personal"); + expect(cipher2.fields[3].name).toEqual("item_name"); + expect(cipher2.fields[3].value).toEqual("Johns email"); + + // number + const cipher3 = result.ciphers.shift(); + expect(cipher3.type).toBe(CipherType.SecureNote); + expect(cipher3.name).toBe("John's number"); + + expect(cipher3.fields.length).toBe(3); + expect(cipher3.fields[0].name).toEqual("type"); + expect(cipher3.fields[0].value).toEqual("number"); + expect(cipher3.fields[1].name).toEqual("item_name"); + expect(cipher3.fields[1].value).toEqual("John's number"); + expect(cipher3.fields[2].name).toEqual("phone_number"); + expect(cipher3.fields[2].value).toEqual("+49123123123"); + + // address + const cipher4 = result.ciphers.shift(); + expect(cipher4.type).toBe(CipherType.SecureNote); + expect(cipher4.name).toBe("John's home address"); + + expect(cipher4.fields.length).toBe(12); + expect(cipher4.fields[0].name).toEqual("type"); + expect(cipher4.fields[0].value).toEqual("address"); + expect(cipher4.fields[1].name).toEqual("item_name"); + expect(cipher4.fields[1].value).toEqual("John's home address"); + expect(cipher4.fields[2].name).toEqual("address"); + expect(cipher4.fields[2].value).toEqual("1 some street"); + expect(cipher4.fields[3].name).toEqual("country"); + expect(cipher4.fields[3].value).toEqual("de"); + expect(cipher4.fields[4].name).toEqual("state"); + expect(cipher4.fields[4].value).toEqual("DE-0-NW"); + expect(cipher4.fields[5].name).toEqual("city"); + expect(cipher4.fields[5].value).toEqual("some city"); + expect(cipher4.fields[6].name).toEqual("zip"); + expect(cipher4.fields[6].value).toEqual("123123"); + expect(cipher4.fields[7].name).toEqual("address_recipient"); + expect(cipher4.fields[7].value).toEqual("John"); + expect(cipher4.fields[8].name).toEqual("address_building"); + expect(cipher4.fields[8].value).toEqual("1"); + expect(cipher4.fields[9].name).toEqual("address_apartment"); + expect(cipher4.fields[9].value).toEqual("1"); + expect(cipher4.fields[10].name).toEqual("address_floor"); + expect(cipher4.fields[10].value).toEqual("1"); + expect(cipher4.fields[11].name).toEqual("address_door_code"); + expect(cipher4.fields[11].value).toEqual("123"); + + // website + const cipher5 = result.ciphers.shift(); + expect(cipher5.type).toBe(CipherType.SecureNote); + expect(cipher5.name).toBe("Website"); + + expect(cipher5.fields.length).toBe(3); + expect(cipher5.fields[0].name).toEqual("type"); + expect(cipher5.fields[0].value).toEqual("website"); + expect(cipher5.fields[1].name).toEqual("item_name"); + expect(cipher5.fields[1].value).toEqual("Website"); + expect(cipher5.fields[2].name).toEqual("url"); + expect(cipher5.fields[2].value).toEqual("website.com"); + + // 2nd name/identity + const cipher6 = result.ciphers.shift(); + expect(cipher6.type).toBe(CipherType.SecureNote); + expect(cipher6.name).toBe("Mrs Jane Doe"); + + expect(cipher6.fields.length).toBe(7); + expect(cipher6.fields[0].name).toEqual("type"); + expect(cipher6.fields[0].value).toEqual("name"); + expect(cipher6.fields[1].name).toEqual("title"); + expect(cipher6.fields[1].value).toEqual("Mrs"); + expect(cipher6.fields[2].name).toEqual("first_name"); + expect(cipher6.fields[2].value).toEqual("Jane"); + expect(cipher6.fields[3].name).toEqual("last_name"); + expect(cipher6.fields[3].value).toEqual("Doe"); + expect(cipher6.fields[4].name).toEqual("login"); + expect(cipher6.fields[4].value).toEqual("jdoe"); + expect(cipher6.fields[5].name).toEqual("date_of_birth"); + expect(cipher6.fields[5].value).toEqual("2022-01-30"); + expect(cipher6.fields[6].name).toEqual("place_of_birth"); + expect(cipher6.fields[6].value).toEqual("earth"); + }); + + it("should combine personal information records to one identity if only one identity present", async () => { + const result = await importer.parse(personalInfoData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("MR John Doe"); + expect(cipher.identity.fullName).toBe("MR John Doe"); + expect(cipher.identity.title).toBe("MR"); + expect(cipher.identity.firstName).toBe("John"); + expect(cipher.identity.middleName).toBeNull(); + expect(cipher.identity.lastName).toBe("Doe"); + expect(cipher.identity.username).toBe("jdoe"); + expect(cipher.identity.email).toBe("jdoe@example.com"); + expect(cipher.identity.phone).toBe("+49123123123"); + + expect(cipher.fields.length).toBe(9); + expect(cipher.fields[0].name).toBe("date_of_birth"); + expect(cipher.fields[0].value).toBe("2022-01-30"); + + expect(cipher.fields[1].name).toBe("place_of_birth"); + expect(cipher.fields[1].value).toBe("world"); + + expect(cipher.fields[2].name).toBe("email_type"); + expect(cipher.fields[2].value).toBe("personal"); + + expect(cipher.fields[3].name).toBe("address_recipient"); + expect(cipher.fields[3].value).toBe("John"); + + expect(cipher.fields[4].name).toBe("address_building"); + expect(cipher.fields[4].value).toBe("1"); + + expect(cipher.fields[5].name).toBe("address_apartment"); + expect(cipher.fields[5].value).toBe("1"); + + expect(cipher.fields[6].name).toBe("address_floor"); + expect(cipher.fields[6].value).toBe("1"); + + expect(cipher.fields[7].name).toBe("address_door_code"); + expect(cipher.fields[7].value).toBe("123"); + + expect(cipher.fields[8].name).toBe("url"); + expect(cipher.fields[8].value).toBe("website.com"); + }); +}); diff --git a/libs/common/spec/importers/firefoxCsvImporter.spec.ts b/libs/common/spec/importers/firefoxCsvImporter.spec.ts new file mode 100644 index 0000000000..e15b86e9ff --- /dev/null +++ b/libs/common/spec/importers/firefoxCsvImporter.spec.ts @@ -0,0 +1,74 @@ +import { FirefoxCsvImporter as Importer } from "jslib-common/importers/firefoxCsvImporter"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; +import { LoginView } from "jslib-common/models/view/loginView"; + +import { data as firefoxAccountsData } from "./testData/firefoxCsv/firefoxAccountsData.csv"; +import { data as simplePasswordData } from "./testData/firefoxCsv/simplePasswordData.csv"; + +const CipherData = [ + { + title: "should parse password", + csv: simplePasswordData, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "example.com", + login: Object.assign(new LoginView(), { + username: "foo", + password: "bar", + uris: [ + Object.assign(new LoginUriView(), { + uri: "https://example.com", + }), + ], + }), + notes: null, + type: 1, + }), + }, + { + title: 'should skip "chrome://FirefoxAccounts"', + csv: firefoxAccountsData, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "example.com", + login: Object.assign(new LoginView(), { + username: "foo", + password: "bar", + uris: [ + Object.assign(new LoginUriView(), { + uri: "https://example.com", + }), + ], + }), + notes: null, + type: 1, + }), + }, +]; + +describe("Firefox CSV Importer", () => { + CipherData.forEach((data) => { + it(data.title, async () => { + const importer = new Importer(); + const result = await importer.parse(data.csv); + expect(result != null).toBe(true); + expect(result.ciphers.length).toBeGreaterThan(0); + + const cipher = result.ciphers.shift(); + let property: keyof typeof data.expected; + for (property in data.expected) { + // eslint-disable-next-line + if (data.expected.hasOwnProperty(property)) { + // eslint-disable-next-line + expect(cipher.hasOwnProperty(property)).toBe(true); + expect(cipher[property]).toEqual(data.expected[property]); + } + } + }); + }); +}); diff --git a/libs/common/spec/importers/fsecureFskImporter.spec.ts b/libs/common/spec/importers/fsecureFskImporter.spec.ts new file mode 100644 index 0000000000..63d082df34 --- /dev/null +++ b/libs/common/spec/importers/fsecureFskImporter.spec.ts @@ -0,0 +1,77 @@ +import { FSecureFskImporter as Importer } from "jslib-common/importers/fsecureFskImporter"; + +const TestDataWithStyleSetToWebsite: string = JSON.stringify({ + data: { + "8d58b5cf252dd06fbd98f5289e918ab1": { + color: "#00baff", + reatedDate: 1609302913, + creditCvv: "", + creditExpiry: "", + creditNumber: "", + favorite: 0, + modifiedDate: 1609302913, + notes: "note", + password: "word", + passwordList: [], + passwordModifiedDate: 1609302913, + rev: 1, + service: "My first pass", + style: "website", + type: 1, + url: "https://bitwarden.com", + username: "pass", + }, + }, +}); + +const TestDataWithStyleSetToGlobe: string = JSON.stringify({ + data: { + "8d58b5cf252dd06fbd98f5289e918ab1": { + color: "#00baff", + reatedDate: 1609302913, + creditCvv: "", + creditExpiry: "", + creditNumber: "", + favorite: 0, + modifiedDate: 1609302913, + notes: "note", + password: "word", + passwordList: [], + passwordModifiedDate: 1609302913, + rev: 1, + service: "My first pass", + style: "globe", + type: 1, + url: "https://bitwarden.com", + username: "pass", + }, + }, +}); + +describe("FSecure FSK Importer", () => { + it("should parse data with style set to website", async () => { + const importer = new Importer(); + const result = await importer.parse(TestDataWithStyleSetToWebsite); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.login.username).toEqual("pass"); + expect(cipher.login.password).toEqual("word"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("https://bitwarden.com"); + }); + + it("should parse data with style set to globe", async () => { + const importer = new Importer(); + const result = await importer.parse(TestDataWithStyleSetToGlobe); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.login.username).toEqual("pass"); + expect(cipher.login.password).toEqual("word"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("https://bitwarden.com"); + }); +}); diff --git a/libs/common/spec/importers/keepass2XmlImporter.spec.ts b/libs/common/spec/importers/keepass2XmlImporter.spec.ts new file mode 100644 index 0000000000..6b53946884 --- /dev/null +++ b/libs/common/spec/importers/keepass2XmlImporter.spec.ts @@ -0,0 +1,189 @@ +import { KeePass2XmlImporter as Importer } from "jslib-common/importers/keepass2XmlImporter"; + +const TestData = ` + + + KeePass + + 2016-12-31T21:33:52Z + + 2016-12-31T21:33:52Z + + 2016-12-31T21:33:52Z + 365 + + 2016-12-31T21:33:59Z + -1 + -1 + + False + False + True + False + False + + True + AAAAAAAAAAAAAAAAAAAAAA== + 2016-12-31T21:33:52Z + AAAAAAAAAAAAAAAAAAAAAA== + 2016-12-31T21:33:52Z + 10 + 6291456 + AAAAAAAAAAAAAAAAAAAAAA== + AAAAAAAAAAAAAAAAAAAAAA== + + + + + + KvS57lVwl13AfGFLwkvq4Q== + Root + + 48 + + 2016-12-31T21:33:52Z + 2016-12-31T21:33:52Z + 2017-01-01T22:58:00Z + 2016-12-31T21:33:52Z + False + 1 + 2016-12-31T21:33:52Z + + True + + null + null + AAAAAAAAAAAAAAAAAAAAAA== + + P0ParXgGMBW6caOL2YrhqQ== + Folder2 + a note about the folder + 48 + + 2016-12-31T21:43:30Z + 2016-12-31T21:43:43Z + 2017-01-01T22:58:00Z + 2016-12-31T21:43:30Z + False + 1 + 2016-12-31T21:43:43Z + + True + + null + null + AAAAAAAAAAAAAAAAAAAAAA== + + fAa543oYlgnJKkhKag5HLw== + 1 + + + + + + 2016-12-31T21:34:13Z + 2016-12-31T21:40:23Z + 2016-12-31T21:40:23Z + 2016-12-31T21:34:13Z + False + 0 + 2016-12-31T21:43:48Z + + + att2 + att2value + + + attr1 + att1value + +line1 +line2 + + + Notes + This is a note!!! + +line1 +line2 + + + Password + googpass + + + Title + Google + + + URL + google.com + + + UserName + googleuser + + + True + 0 + + + + fAa543oYlgnJKkhKag5HLw== + 0 + + + + + + 2016-12-31T21:34:13Z + 2016-12-31T21:34:40Z + 2016-12-31T21:34:40Z + 2016-12-31T21:34:13Z + False + 0 + 2016-12-31T21:34:40Z + + + Notes + This is a note!!! + +line1 +line2 + + + Password + googpass + + + Title + Google + + + URL + google.com + + + UserName + googleuser + + + True + 0 + + + + + + + + +`; + +describe("KeePass2 Xml Importer", () => { + it("should parse XML data", async () => { + const importer = new Importer(); + const result = await importer.parse(TestData); + expect(result != null).toBe(true); + }); +}); diff --git a/libs/common/spec/importers/keeperJsonImporter.spec.ts b/libs/common/spec/importers/keeperJsonImporter.spec.ts new file mode 100644 index 0000000000..3da6ac4860 --- /dev/null +++ b/libs/common/spec/importers/keeperJsonImporter.spec.ts @@ -0,0 +1,108 @@ +import { KeeperJsonImporter as Importer } from "jslib-common/importers/keeperImporters/keeperJsonImporter"; +import { Utils } from "jslib-common/misc/utils"; + +import { testData as TestData } from "./testData/keeperJson/testData"; + +describe("Keeper Json Importer", () => { + const testDataJson = JSON.stringify(TestData); + + let importer: Importer; + beforeEach(() => { + importer = new Importer(); + }); + + it("should parse login data", async () => { + const result = await importer.parse(testDataJson); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("Bank Account 1"); + expect(cipher.login.username).toEqual("customer1234"); + expect(cipher.login.password).toEqual("4813fJDHF4239fdk"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("https://chase.com"); + expect(cipher.notes).toEqual("These are some notes."); + + const cipher2 = result.ciphers.shift(); + expect(cipher2.name).toEqual("Bank Account 2"); + expect(cipher2.login.username).toEqual("mybankusername"); + expect(cipher2.login.password).toEqual("w4k4k193f$^&@#*%2"); + expect(cipher2.login.uris.length).toEqual(1); + const uriView2 = cipher2.login.uris.shift(); + expect(uriView2.uri).toEqual("https://amex.com"); + expect(cipher2.notes).toEqual("Some great information here."); + + const cipher3 = result.ciphers.shift(); + expect(cipher3.name).toEqual("Some Account"); + expect(cipher3.login.username).toEqual("someUserName"); + expect(cipher3.login.password).toEqual("w4k4k1wergf$^&@#*%2"); + expect(cipher3.notes).toBeNull(); + expect(cipher3.fields).toBeNull(); + expect(cipher3.login.uris.length).toEqual(1); + const uriView3 = cipher3.login.uris.shift(); + expect(uriView3.uri).toEqual("https://example.com"); + }); + + it("should import TOTP when present", async () => { + const result = await importer.parse(testDataJson); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.login.totp).toBeNull(); + + // 2nd Cipher + const cipher2 = result.ciphers.shift(); + expect(cipher2.login.totp).toEqual( + "otpauth://totp/Amazon:me@company.com?secret=JBSWY3DPEHPK3PXP&issuer=Amazon&algorithm=SHA1&digits=6&period=30" + ); + }); + + it("should parse custom fields", async () => { + const result = await importer.parse(testDataJson); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.fields.length).toBe(1); + expect(cipher.fields[0].name).toEqual("Account Number"); + expect(cipher.fields[0].value).toEqual("123-456-789"); + + // 2nd Cipher + const cipher2 = result.ciphers.shift(); + expect(cipher2.fields.length).toBe(2); + expect(cipher2.fields[0].name).toEqual("Security Group"); + expect(cipher2.fields[0].value).toEqual("Public"); + + expect(cipher2.fields[1].name).toEqual("IP Address"); + expect(cipher2.fields[1].value).toEqual("12.45.67.8"); + }); + + it("should create folders and assigned ciphers to them", async () => { + const result = await importer.parse(testDataJson); + expect(result != null).toBe(true); + + const folders = result.folders; + expect(folders.length).toBe(2); + expect(folders[0].name).toBe("Optional Private Folder 1"); + expect(folders[1].name).toBe("My Customer 1"); + + expect(result.folderRelationships[0]).toEqual([0, 0]); + expect(result.folderRelationships[1]).toEqual([1, 0]); + expect(result.folderRelationships[2]).toEqual([1, 1]); + }); + + it("should create collections if part of an organization", async () => { + importer.organizationId = Utils.newGuid(); + const result = await importer.parse(testDataJson); + expect(result != null).toBe(true); + + const collections = result.collections; + expect(collections.length).toBe(2); + expect(collections[0].name).toBe("Optional Private Folder 1"); + expect(collections[1].name).toBe("My Customer 1"); + + expect(result.collectionRelationships[0]).toEqual([0, 0]); + expect(result.collectionRelationships[1]).toEqual([1, 0]); + expect(result.collectionRelationships[2]).toEqual([1, 1]); + }); +}); diff --git a/libs/common/spec/importers/lastpassCsvImporter.spec.ts b/libs/common/spec/importers/lastpassCsvImporter.spec.ts new file mode 100644 index 0000000000..9cca6c4fbb --- /dev/null +++ b/libs/common/spec/importers/lastpassCsvImporter.spec.ts @@ -0,0 +1,202 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { LastPassCsvImporter as Importer } from "jslib-common/importers/lastpassCsvImporter"; +import { ImportResult } from "jslib-common/models/domain/importResult"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { FieldView } from "jslib-common/models/view/fieldView"; + +function baseExcept(result: ImportResult) { + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); +} + +function expectLogin(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Login); + + expect(cipher.name).toBe("example.com"); + expect(cipher.notes).toBe("super secure notes"); + expect(cipher.login.uri).toBe("http://example.com"); + expect(cipher.login.username).toBe("someUser"); + expect(cipher.login.password).toBe("myPassword"); + expect(cipher.login.totp).toBe("Y64VEVMBTSXCYIWRSHRNDZW62MPGVU2G"); +} + +const CipherData = [ + { + title: "should parse expiration date", + csv: `url,username,password,extra,name,grouping,fav +http://sn,,,"NoteType:Credit Card +Name on Card:John Doe +Type: +Number:1234567812345678 +Security Code:123 +Start Date:October,2017 +Expiration Date:June,2020 +Notes:some text +",Credit-card,,0`, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "Credit-card", + notes: "some text\n", + type: 3, + card: { + cardholderName: "John Doe", + number: "1234567812345678", + code: "123", + expYear: "2020", + expMonth: "6", + }, + fields: [ + Object.assign(new FieldView(), { + name: "Start Date", + value: "October,2017", + type: FieldType.Text, + }), + ], + }), + }, + { + title: "should parse blank card note", + csv: `url,username,password,extra,name,grouping,fav +http://sn,,,"NoteType:Credit Card +Name on Card: +Type: +Number: +Security Code: +Start Date:, +Expiration Date:, +Notes:",empty,,0`, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "empty", + notes: null, + type: 3, + card: { + expMonth: undefined, + }, + fields: [ + Object.assign(new FieldView(), { + name: "Start Date", + value: ",", + type: FieldType.Text, + }), + ], + }), + }, + { + title: "should parse card expiration date w/ no exp year", + csv: `url,username,password,extra,name,grouping,fav +http://sn,,,"NoteType:Credit Card +Name on Card:John Doe +Type:Visa +Number:1234567887654321 +Security Code:321 +Start Date:, +Expiration Date:January, +Notes:",noyear,,0`, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "noyear", + notes: null, + type: 3, + card: { + cardholderName: "John Doe", + number: "1234567887654321", + code: "321", + expMonth: "1", + }, + fields: [ + Object.assign(new FieldView(), { + name: "Type", + value: "Visa", + type: FieldType.Text, + }), + Object.assign(new FieldView(), { + name: "Start Date", + value: ",", + type: FieldType.Text, + }), + ], + }), + }, + { + title: "should parse card expiration date w/ no month", + csv: `url,username,password,extra,name,grouping,fav +http://sn,,,"NoteType:Credit Card +Name on Card:John Doe +Type:Mastercard +Number:8765432112345678 +Security Code:987 +Start Date:, +Expiration Date:,2020 +Notes:",nomonth,,0`, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "nomonth", + notes: null, + type: 3, + card: { + cardholderName: "John Doe", + number: "8765432112345678", + code: "987", + expYear: "2020", + expMonth: undefined, + }, + fields: [ + Object.assign(new FieldView(), { + name: "Type", + value: "Mastercard", + type: FieldType.Text, + }), + Object.assign(new FieldView(), { + name: "Start Date", + value: ",", + type: FieldType.Text, + }), + ], + }), + }, +]; + +describe("Lastpass CSV Importer", () => { + CipherData.forEach((data) => { + it(data.title, async () => { + const importer = new Importer(); + const result = await importer.parse(data.csv); + expect(result != null).toBe(true); + expect(result.ciphers.length).toBeGreaterThan(0); + + const cipher = result.ciphers.shift(); + let property: keyof typeof data.expected; + for (property in data.expected) { + // eslint-disable-next-line + if (data.expected.hasOwnProperty(property)) { + // eslint-disable-next-line + expect(cipher.hasOwnProperty(property)).toBe(true); + expect(cipher[property]).toEqual(data.expected[property]); + } + } + }); + }); + + it("should parse login with totp", async () => { + const input = `url,username,password,totp,extra,name,grouping,fav + http://example.com,someUser,myPassword,Y64VEVMBTSXCYIWRSHRNDZW62MPGVU2G,super secure notes,example.com,,0`; + + const importer = new Importer(); + const result = await importer.parse(input); + baseExcept(result); + + const cipher = result.ciphers[0]; + expectLogin(cipher); + }); +}); diff --git a/libs/common/spec/importers/mykiCsvImporter.spec.ts b/libs/common/spec/importers/mykiCsvImporter.spec.ts new file mode 100644 index 0000000000..d9538ee765 --- /dev/null +++ b/libs/common/spec/importers/mykiCsvImporter.spec.ts @@ -0,0 +1,633 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { MykiCsvImporter as Importer } from "jslib-common/importers/mykiCsvImporter"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +import { userAccountData } from "./testData/mykiCsv/UserAccount.csv"; +import { userCreditCardData } from "./testData/mykiCsv/UserCreditCard.csv"; +import { userIdCardData } from "./testData/mykiCsv/UserIdCard.csv"; +import { userIdentityData } from "./testData/mykiCsv/UserIdentity.csv"; +import { userNoteData } from "./testData/mykiCsv/UserNote.csv"; +import { userTwoFaData } from "./testData/mykiCsv/UserTwofa.csv"; + +function expectDriversLicense(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Joe User's nickname"); + expect(cipher.notes).toBe("Additional information"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("123456"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Driver's License"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("02/02/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("02/02/2024"); +} + +function expectPassport(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Passport ID card"); + expect(cipher.notes).toBe("Additional information field"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.passportNumber).toBe("1234567"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Passport"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectSocialSecurity(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Social Security ID card"); + expect(cipher.notes).toBe("Additional information field text"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.ssn).toBe("123455678"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Social Security"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectIdCard(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("ID card type ID card"); + expect(cipher.notes).toBe("Additional Information field text"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("1234566"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("ID Card"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectTaxNumber(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Tax number ID card"); + expect(cipher.notes).toBe("Additinoal information text field"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("12345678"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Tax Number"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectBankAccount(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Bank account ID card"); + expect(cipher.notes).toBe("Additional text information here"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("12344556677"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Bank Account"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectInsuranceCard(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Insurance card ID card"); + expect(cipher.notes).toBe("Additional information text goes here"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("123456677"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Insurance Card"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2022"); +} + +function expectHealthCard(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Health card Id card"); + expect(cipher.notes).toBe("More info"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("1234670"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Health Card"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectMembershipCard(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Membership ID card"); + expect(cipher.notes).toBe("Add'l info"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("12345709"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Membership"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectDatabase(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Database ID card"); + expect(cipher.notes).toBe("Addin't info"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("12345089u"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Database"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectOutdoorLicense(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Outdoor license ID card"); + expect(cipher.notes).toBe("Additional info"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("123890090"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Outdoor License"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectRewardProgram(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Reward program Id card"); + expect(cipher.notes).toBe("1234890"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("12345890b"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Reward Program"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectSoftwareLicense(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Software license ID card"); + expect(cipher.notes).toBe( + "It seems like the fields don't change, which makes it pretty useless that they have so many ID card types." + ); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("1234567c"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Software License"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +function expectTourVisa(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Tour visa ID card"); + expect(cipher.notes).toBe("Additional Informaion text"); + + expect(cipher.identity.fullName).toBe("Joe M User"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.licenseNumber).toBe("123456lkhj"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(5); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toEqual("tags"); + expect(cipher.fields[1].value).toEqual("someTag"); + + expect(cipher.fields[2].name).toEqual("idType"); + expect(cipher.fields[2].value).toEqual("Tour Visa"); + + expect(cipher.fields[3].name).toEqual("idIssuanceDate"); + expect(cipher.fields[3].value).toEqual("03/07/2022"); + + expect(cipher.fields[4].name).toEqual("idExpirationDate"); + expect(cipher.fields[4].value).toEqual("03/07/2028"); +} + +describe("Myki CSV Importer", () => { + let importer: Importer; + beforeEach(() => { + importer = new Importer(); + }); + + it("should parse userAccount records", async () => { + const result = await importer.parse(userAccountData); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + + expect(cipher.name).toEqual("PasswordNickname"); + expect(cipher.login.username).toEqual("user.name@email.com"); + expect(cipher.login.password).toEqual("abc123"); + expect(cipher.login.totp).toEqual("someTOTPSeed"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("http://www.google.com"); + expect(cipher.notes).toEqual("This is the additional information text."); + + expect(cipher.fields.length).toBe(2); + + expect(cipher.fields[0].name).toBe("status"); + expect(cipher.fields[0].value).toBe("active"); + + expect(cipher.fields[1].name).toBe("tags"); + expect(cipher.fields[1].value).toBe("someTag"); + }); + + it("should parse userTwoFa records", async () => { + const result = await importer.parse(userTwoFaData); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + + expect(cipher.name).toEqual("2FA nickname"); + expect(cipher.login.username).toBeNull(); + expect(cipher.login.password).toBeNull(); + expect(cipher.login.totp).toBe("someTOTPSeed"); + expect(cipher.notes).toEqual("Additional information field content."); + + expect(cipher.fields.length).toBe(2); + + expect(cipher.fields[0].name).toBe("status"); + expect(cipher.fields[0].value).toBe("active"); + + expect(cipher.fields[1].name).toBe("tags"); + expect(cipher.fields[1].value).toBe("someTag"); + }); + + it("should parse creditCard records", async () => { + const result = await importer.parse(userCreditCardData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.Card); + expect(cipher.name).toBe("Visa test card"); + expect(cipher.card.brand).toBe("Visa"); + expect(cipher.card.cardholderName).toBe("Joe User"); + expect(cipher.card.number).toBe("4111111111111111"); + expect(cipher.card.code).toBe("222"); + expect(cipher.card.expMonth).toBe("04"); + expect(cipher.card.expYear).toBe("24"); + + expect(cipher.notes).toBe("This is the additional information field"); + + expect(cipher.fields.length).toBe(2); + + expect(cipher.fields[0].name).toBe("status"); + expect(cipher.fields[0].value).toBe("active"); + + expect(cipher.fields[1].name).toBe("tags"); + expect(cipher.fields[1].value).toBe("someTag"); + }); + + it("should parse identity records", async () => { + const result = await importer.parse(userIdentityData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.Identity); + expect(cipher.name).toBe("Joe User's nickname"); + expect(cipher.identity.fullName).toBe("Mr Joe M User"); + expect(cipher.identity.title).toBe("Mr"); + expect(cipher.identity.firstName).toBe("Joe"); + expect(cipher.identity.middleName).toBe("M"); + expect(cipher.identity.lastName).toBe("User"); + expect(cipher.identity.email).toBe("joe.user@email.com"); + + expect(cipher.identity.address1).toBe("1 Example House"); + expect(cipher.identity.address2).toBe("Suite 300"); + + expect(cipher.identity.city).toBe("Portland"); + expect(cipher.identity.postalCode).toBe("04101"); + expect(cipher.identity.country).toBe("United States"); + + expect(cipher.fields.length).toBe(4); + + expect(cipher.fields[0].name).toEqual("status"); + expect(cipher.fields[0].value).toEqual("active"); + + expect(cipher.fields[1].name).toBe("tags"); + expect(cipher.fields[1].value).toBe("someTag"); + + expect(cipher.fields[2].name).toEqual("gender"); + expect(cipher.fields[2].value).toEqual("Male"); + + expect(cipher.fields[3].name).toEqual("number"); + expect(cipher.fields[3].value).toEqual("2223334444"); + }); + + it("should parse secureNote records", async () => { + const result = await importer.parse(userNoteData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + + const cipher = result.ciphers.shift(); + expect(cipher.type).toBe(CipherType.SecureNote); + expect(cipher.name).toBe("The title of a secure note"); + expect(cipher.notes).toBe("The content of a secure note. Lorem ipsum, etc."); + + expect(cipher.fields.length).toBe(1); + + expect(cipher.fields[0].name).toBe("status"); + expect(cipher.fields[0].value).toBe("active"); + }); + + it("should parse idCard records", async () => { + const result = await importer.parse(userIdCardData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + + expect(result.ciphers.length).toBe(14); + + // Driver's license + const cipher = result.ciphers.shift(); + expectDriversLicense(cipher); + + // Passport + const cipher2 = result.ciphers.shift(); + expectPassport(cipher2); + + // Social Security + const cipher3 = result.ciphers.shift(); + expectSocialSecurity(cipher3); + + // Id Card + const cipher4 = result.ciphers.shift(); + expectIdCard(cipher4); + + // Tax Number + const cipher5 = result.ciphers.shift(); + expectTaxNumber(cipher5); + + // Bank Account + const cipher6 = result.ciphers.shift(); + expectBankAccount(cipher6); + + // Insurance card + const cipher7 = result.ciphers.shift(); + expectInsuranceCard(cipher7); + + // Health card + const cipher8 = result.ciphers.shift(); + expectHealthCard(cipher8); + + // Membership card + const cipher9 = result.ciphers.shift(); + expectMembershipCard(cipher9); + + // Database card + const cipher10 = result.ciphers.shift(); + expectDatabase(cipher10); + + // Outdoor license + const cipher11 = result.ciphers.shift(); + expectOutdoorLicense(cipher11); + + // Reward program + const cipher12 = result.ciphers.shift(); + expectRewardProgram(cipher12); + + // Software license + const cipher13 = result.ciphers.shift(); + expectSoftwareLicense(cipher13); + + // Tour visa + const cipher14 = result.ciphers.shift(); + expectTourVisa(cipher14); + }); +}); diff --git a/libs/common/spec/importers/nordpassCsvImporter.spec.ts b/libs/common/spec/importers/nordpassCsvImporter.spec.ts new file mode 100644 index 0000000000..4022b7e35d --- /dev/null +++ b/libs/common/spec/importers/nordpassCsvImporter.spec.ts @@ -0,0 +1,181 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { SecureNoteType } from "jslib-common/enums/secureNoteType"; +import { NordPassCsvImporter as Importer } from "jslib-common/importers/nordpassCsvImporter"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { IdentityView } from "jslib-common/models/view/identityView"; + +import { data as creditCardData } from "./testData/nordpassCsv/nordpass.card.csv"; +import { data as identityData } from "./testData/nordpassCsv/nordpass.identity.csv"; +import { data as loginData } from "./testData/nordpassCsv/nordpass.login.csv"; +import { data as secureNoteData } from "./testData/nordpassCsv/nordpass.secureNote.csv"; + +const namesTestData = [ + { + title: "Given #fullName should set firstName", + fullName: "MyFirstName", + expected: Object.assign(new IdentityView(), { + firstName: "MyFirstName", + middleName: null, + lastName: null, + }), + }, + { + title: "Given #fullName should set first- and lastName", + fullName: "MyFirstName MyLastName", + expected: Object.assign(new IdentityView(), { + firstName: "MyFirstName", + middleName: null, + lastName: "MyLastName", + }), + }, + { + title: "Given #fullName should set first-, middle and lastName", + fullName: "MyFirstName MyMiddleName MyLastName", + expected: Object.assign(new IdentityView(), { + firstName: "MyFirstName", + middleName: "MyMiddleName", + lastName: "MyLastName", + }), + }, + { + title: "Given #fullName should set first-, middle and lastName with Jr", + fullName: "MyFirstName MyMiddleName MyLastName Jr", + expected: Object.assign(new IdentityView(), { + firstName: "MyFirstName", + middleName: "MyMiddleName", + lastName: "MyLastName Jr", + }), + }, + { + title: "Given #fullName should set first-, middle and lastName with Jr and III", + fullName: "MyFirstName MyMiddleName MyLastName Jr III", + expected: Object.assign(new IdentityView(), { + firstName: "MyFirstName", + middleName: "MyMiddleName", + lastName: "MyLastName Jr III", + }), + }, +]; + +function expectLogin(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Login); + + expect(cipher.name).toBe("SomeVaultItemName"); + expect(cipher.notes).toBe("Some note for the VaultItem"); + expect(cipher.login.uri).toBe("https://example.com"); + expect(cipher.login.username).toBe("hello@bitwarden.com"); + expect(cipher.login.password).toBe("someStrongPassword"); +} + +function expectCreditCard(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Card); + + expect(cipher.name).toBe("SomeVisa"); + expect(cipher.card.brand).toBe("Visa"); + expect(cipher.card.cardholderName).toBe("SomeHolder"); + expect(cipher.card.number).toBe("4024007103939509"); + expect(cipher.card.code).toBe("123"); + expect(cipher.card.expMonth).toBe("1"); + expect(cipher.card.expYear).toBe("22"); +} + +function expectIdentity(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + + expect(cipher.name).toBe("SomeTitle"); + expect(cipher.identity.fullName).toBe("MyFirstName MyMiddleName MyLastName"); + expect(cipher.identity.firstName).toBe("MyFirstName"); + expect(cipher.identity.middleName).toBe("MyMiddleName"); + expect(cipher.identity.lastName).toBe("MyLastName"); + expect(cipher.identity.email).toBe("hello@bitwarden.com"); + expect(cipher.identity.phone).toBe("123456789"); + + expect(cipher.identity.address1).toBe("Test street 123"); + expect(cipher.identity.address2).toBe("additional addressinfo"); + expect(cipher.identity.postalCode).toBe("123456"); + expect(cipher.identity.city).toBe("Cologne"); + expect(cipher.identity.state).toBe("North-Rhine-Westphalia"); + expect(cipher.identity.country).toBe("GERMANY"); + expect(cipher.notes).toBe("SomeNoteToMyIdentity"); +} + +function expectSecureNote(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.SecureNote); + + expect(cipher.name).toBe("MySuperSecureNoteTitle"); + expect(cipher.secureNote.type).toBe(SecureNoteType.Generic); + expect(cipher.notes).toBe("MySuperSecureNote"); +} + +describe("NordPass CSV Importer", () => { + let importer: Importer; + beforeEach(() => { + importer = new Importer(); + }); + + it("should parse login records", async () => { + const result = await importer.parse(loginData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectLogin(cipher); + }); + + it("should parse credit card records", async () => { + const result = await importer.parse(creditCardData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectCreditCard(cipher); + }); + + it("should parse identity records", async () => { + const result = await importer.parse( + identityData.replace("#fullName", "MyFirstName MyMiddleName MyLastName") + ); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectIdentity(cipher); + }); + + namesTestData.forEach((data) => { + it(data.title.replace("#fullName", data.fullName), async () => { + const result = await importer.parse(identityData.replace("#fullName", data.fullName)); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expect(cipher.identity.firstName).toBe(data.expected.firstName); + expect(cipher.identity.middleName).toBe(data.expected.middleName); + expect(cipher.identity.lastName).toBe(data.expected.lastName); + }); + }); + + it("should parse secureNote records", async () => { + const result = await importer.parse(secureNoteData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectSecureNote(cipher); + }); + + it("should parse an item and create a folder", async () => { + const result = await importer.parse(secureNoteData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.folders.length).toBe(1); + const folder = result.folders[0]; + expect(folder.name).toBe("notesFolder"); + }); +}); diff --git a/libs/common/spec/importers/onepassword1PifImporter.spec.ts b/libs/common/spec/importers/onepassword1PifImporter.spec.ts new file mode 100644 index 0000000000..ffa2417a10 --- /dev/null +++ b/libs/common/spec/importers/onepassword1PifImporter.spec.ts @@ -0,0 +1,527 @@ +import { FieldType } from "jslib-common/enums/fieldType"; +import { OnePassword1PifImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepassword1PifImporter"; + +const TestData: string = + "***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n" + + JSON.stringify({ + uuid: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + updatedAt: 1486071244, + securityLevel: "SL5", + contentsHash: "aaaaaaaa", + title: "Imported Entry", + location: "https://www.google.com", + secureContents: { + fields: [ + { + value: "user@test.net", + id: "email-input", + name: "email", + type: "T", + designation: "username", + }, + { + value: "myservicepassword", + id: "password-input", + name: "password", + type: "P", + designation: "password", + }, + ], + sections: [ + { + fields: [ + { + k: "concealed", + n: "AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC", + v: "console-password-123", + t: "console password", + }, + ], + title: "Admin Console", + name: "admin_console", + }, + ], + passwordHistory: [ + { + value: "old-password", + time: 1447791421, + }, + ], + }, + URLs: [ + { + label: "website", + url: "https://www.google.com", + }, + ], + txTimestamp: 1508941334, + createdAt: 1390426636, + typeName: "webforms.WebForm", + }); + +const WindowsOpVaultTestData = JSON.stringify({ + category: "001", + created: 1544823719, + hmac: "NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=", + k: "**REMOVED LONG LINE FOR LINTER** -Kyle", + tx: 1553395669, + updated: 1553395669, + uuid: "528AB076FB5F4FBF960884B8E01619AC", + overview: { + title: "Google", + URLs: [ + { + u: "google.com", + }, + ], + url: "google.com", + ps: 26, + ainfo: "googluser", + }, + details: { + passwordHistory: [ + { + value: "oldpass1", + time: 1553394449, + }, + { + value: "oldpass2", + time: 1553394457, + }, + { + value: "oldpass3", + time: 1553394458, + }, + { + value: "oldpass4", + time: 1553394459, + }, + { + value: "oldpass5", + time: 1553394460, + }, + { + value: "oldpass6", + time: 1553394461, + }, + ], + fields: [ + { + type: "T", + id: "username", + name: "username", + value: "googluser", + designation: "username", + }, + { + type: "P", + id: "password", + name: "password", + value: "12345678901", + designation: "password", + }, + ], + notesPlain: "This is a note\r\n\r\nline1\r\nline2", + sections: [ + { + title: "test", + name: "1214FD88CD30405D9EED14BEB4D61B60", + fields: [ + { + k: "string", + n: "6CC3BD77482D4559A4B8BB2D360F821B", + v: "fgfg", + t: "fgggf", + }, + { + k: "concealed", + n: "5CFE7BCAA1DF4578BBF7EB508959BFF3", + v: "dfgdfgfdg", + t: "pwfield", + }, + ], + }, + ], + }, +}); + +const IdentityTestData = JSON.stringify({ + uuid: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + updatedAt: 1553365894, + securityLevel: "SL5", + contentsHash: "eeeeeeee", + title: "Test Identity", + secureContents: { + lastname: "Fritzenberger", + zip: "223344", + birthdate_dd: "11", + homephone: "+49 333 222 111", + company: "Web Inc.", + firstname: "Frank", + birthdate_mm: "3", + country: "de", + sex: "male", + sections: [ + { + fields: [ + { + k: "string", + inputTraits: { + autocapitalization: "Words", + }, + n: "firstname", + v: "Frank", + a: { + guarded: "yes", + }, + t: "first name", + }, + { + k: "string", + inputTraits: { + autocapitalization: "Words", + }, + n: "initial", + v: "MD", + a: { + guarded: "yes", + }, + t: "initial", + }, + { + k: "string", + inputTraits: { + autocapitalization: "Words", + }, + n: "lastname", + v: "Fritzenberger", + a: { + guarded: "yes", + }, + t: "last name", + }, + { + k: "menu", + v: "male", + n: "sex", + a: { + guarded: "yes", + }, + t: "sex", + }, + { + k: "date", + v: 1552305660, + n: "birthdate", + a: { + guarded: "yes", + }, + t: "birth date", + }, + { + k: "string", + inputTraits: { + autocapitalization: "Words", + }, + n: "occupation", + v: "Engineer", + a: { + guarded: "yes", + }, + t: "occupation", + }, + { + k: "string", + inputTraits: { + autocapitalization: "Words", + }, + n: "company", + v: "Web Inc.", + a: { + guarded: "yes", + }, + t: "company", + }, + { + k: "string", + inputTraits: { + autocapitalization: "Words", + }, + n: "department", + v: "IT", + a: { + guarded: "yes", + }, + t: "department", + }, + { + k: "string", + inputTraits: { + autocapitalization: "Words", + }, + n: "jobtitle", + v: "Developer", + a: { + guarded: "yes", + }, + t: "job title", + }, + ], + title: "Identification", + name: "name", + }, + { + fields: [ + { + k: "address", + inputTraits: { + autocapitalization: "Sentences", + }, + n: "address", + v: { + street: "Mainstreet 1", + city: "Berlin", + country: "de", + zip: "223344", + }, + a: { + guarded: "yes", + }, + t: "address", + }, + { + k: "phone", + v: "+49 001 222 333 44", + n: "defphone", + a: { + guarded: "yes", + }, + t: "default phone", + }, + { + k: "phone", + v: "+49 333 222 111", + n: "homephone", + a: { + guarded: "yes", + }, + t: "home", + }, + { + k: "phone", + n: "cellphone", + a: { + guarded: "yes", + }, + t: "mobile", + }, + { + k: "phone", + n: "busphone", + a: { + guarded: "yes", + }, + t: "business", + }, + ], + title: "Address", + name: "address", + }, + { + fields: [ + { + k: "string", + n: "username", + a: { + guarded: "yes", + }, + t: "username", + }, + { + k: "string", + n: "reminderq", + t: "reminder question", + }, + { + k: "string", + n: "remindera", + t: "reminder answer", + }, + { + k: "string", + inputTraits: { + keyboard: "EmailAddress", + }, + n: "email", + v: "test@web.de", + a: { + guarded: "yes", + }, + t: "email", + }, + { + k: "string", + n: "website", + inputTraits: { + keyboard: "URL", + }, + t: "website", + }, + { + k: "string", + n: "icq", + t: "ICQ", + }, + { + k: "string", + n: "skype", + t: "skype", + }, + { + k: "string", + n: "aim", + t: "AOL/AIM", + }, + { + k: "string", + n: "yahoo", + t: "Yahoo", + }, + { + k: "string", + n: "msn", + t: "MSN", + }, + { + k: "string", + n: "forumsig", + t: "forum signature", + }, + ], + title: "Internet Details", + name: "internet", + }, + { + title: "Related Items", + name: "linked items", + }, + ], + initial: "MD", + address1: "Mainstreet 1", + city: "Berlin", + jobtitle: "Developer", + occupation: "Engineer", + department: "IT", + email: "test@web.de", + birthdate_yy: "2019", + homephone_local: "+49 333 222 111", + defphone_local: "+49 001 222 333 44", + defphone: "+49 001 222 333 44", + }, + txTimestamp: 1553365894, + createdAt: 1553364679, + typeName: "identities.Identity", +}); + +describe("1Password 1Pif Importer", () => { + it("should parse data", async () => { + const importer = new Importer(); + const result = await importer.parse(TestData); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.login.username).toEqual("user@test.net"); + expect(cipher.login.password).toEqual("myservicepassword"); + expect(cipher.login.uris.length).toEqual(1); + const uriView = cipher.login.uris.shift(); + expect(uriView.uri).toEqual("https://www.google.com"); + }); + + it('should create concealed field as "hidden" type', async () => { + const importer = new Importer(); + const result = await importer.parse(TestData); + expect(result != null).toBe(true); + + const ciphers = result.ciphers; + expect(ciphers.length).toEqual(1); + + const cipher = ciphers.shift(); + const fields = cipher.fields; + expect(fields.length).toEqual(1); + + const field = fields.shift(); + expect(field.name).toEqual("console password"); + expect(field.value).toEqual("console-password-123"); + expect(field.type).toEqual(FieldType.Hidden); + }); + + it("should create identity records", async () => { + const importer = new Importer(); + const result = await importer.parse(IdentityTestData); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("Test Identity"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("Frank"); + expect(identity.middleName).toEqual("MD"); + expect(identity.lastName).toEqual("Fritzenberger"); + expect(identity.company).toEqual("Web Inc."); + expect(identity.address1).toEqual("Mainstreet 1"); + expect(identity.country).toEqual("DE"); + expect(identity.city).toEqual("Berlin"); + expect(identity.postalCode).toEqual("223344"); + expect(identity.phone).toEqual("+49 001 222 333 44"); + expect(identity.email).toEqual("test@web.de"); + + // remaining fields as custom fields + expect(cipher.fields.length).toEqual(6); + const fields = cipher.fields; + expect(fields[0].name).toEqual("sex"); + expect(fields[0].value).toEqual("male"); + expect(fields[1].name).toEqual("birth date"); + expect(fields[1].value).toEqual("Mon, 11 Mar 2019 12:01:00 GMT"); + expect(fields[2].name).toEqual("occupation"); + expect(fields[2].value).toEqual("Engineer"); + expect(fields[3].name).toEqual("department"); + expect(fields[3].value).toEqual("IT"); + expect(fields[4].name).toEqual("job title"); + expect(fields[4].value).toEqual("Developer"); + expect(fields[5].name).toEqual("home"); + expect(fields[5].value).toEqual("+49 333 222 111"); + }); + + it("should create password history", async () => { + const importer = new Importer(); + const result = await importer.parse(TestData); + const cipher = result.ciphers.shift(); + + expect(cipher.passwordHistory.length).toEqual(1); + const ph = cipher.passwordHistory.shift(); + expect(ph.password).toEqual("old-password"); + expect(ph.lastUsedDate.toISOString()).toEqual("2015-11-17T20:17:01.000Z"); + }); + + it("should create password history from windows opvault 1pif format", async () => { + const importer = new Importer(); + const result = await importer.parse(WindowsOpVaultTestData); + const cipher = result.ciphers.shift(); + + expect(cipher.passwordHistory.length).toEqual(5); + let ph = cipher.passwordHistory.shift(); + expect(ph.password).toEqual("oldpass6"); + expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:41.000Z"); + ph = cipher.passwordHistory.shift(); + expect(ph.password).toEqual("oldpass5"); + expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:40.000Z"); + ph = cipher.passwordHistory.shift(); + expect(ph.password).toEqual("oldpass4"); + expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:39.000Z"); + ph = cipher.passwordHistory.shift(); + expect(ph.password).toEqual("oldpass3"); + expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:38.000Z"); + ph = cipher.passwordHistory.shift(); + expect(ph.password).toEqual("oldpass2"); + expect(ph.lastUsedDate.toISOString()).toEqual("2019-03-24T02:27:37.000Z"); + }); +}); diff --git a/libs/common/spec/importers/onepassword1PuxImporter.spec.ts b/libs/common/spec/importers/onepassword1PuxImporter.spec.ts new file mode 100644 index 0000000000..a56e080a96 --- /dev/null +++ b/libs/common/spec/importers/onepassword1PuxImporter.spec.ts @@ -0,0 +1,689 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { SecureNoteType } from "jslib-common/enums/secureNoteType"; +import { OnePassword1PuxImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepassword1PuxImporter"; +import { Utils } from "jslib-common/misc/utils"; +import { FieldView } from "jslib-common/models/view/fieldView"; + +import { APICredentialsData } from "./testData/onePassword1Pux/APICredentials"; +import { BankAccountData } from "./testData/onePassword1Pux/BankAccount"; +import { CreditCardData } from "./testData/onePassword1Pux/CreditCard"; +import { DatabaseData } from "./testData/onePassword1Pux/Database"; +import { DriversLicenseData } from "./testData/onePassword1Pux/DriversLicense"; +import { EmailAccountData } from "./testData/onePassword1Pux/EmailAccount"; +import { EmailFieldData } from "./testData/onePassword1Pux/Emailfield"; +import { EmailFieldOnIdentityData } from "./testData/onePassword1Pux/EmailfieldOnIdentity"; +import { EmailFieldOnIdentityPrefilledData } from "./testData/onePassword1Pux/EmailfieldOnIdentity_Prefilled"; +import { IdentityData } from "./testData/onePassword1Pux/IdentityData"; +import { LoginData } from "./testData/onePassword1Pux/LoginData"; +import { MedicalRecordData } from "./testData/onePassword1Pux/MedicalRecord"; +import { MembershipData } from "./testData/onePassword1Pux/Membership"; +import { OnePuxExampleFile } from "./testData/onePassword1Pux/Onepux_example"; +import { OutdoorLicenseData } from "./testData/onePassword1Pux/OutdoorLicense"; +import { PassportData } from "./testData/onePassword1Pux/Passport"; +import { PasswordData } from "./testData/onePassword1Pux/Password"; +import { RewardsProgramData } from "./testData/onePassword1Pux/RewardsProgram"; +import { SSNData } from "./testData/onePassword1Pux/SSN"; +import { SanitizedExport } from "./testData/onePassword1Pux/SanitizedExport"; +import { SecureNoteData } from "./testData/onePassword1Pux/SecureNote"; +import { ServerData } from "./testData/onePassword1Pux/Server"; +import { SoftwareLicenseData } from "./testData/onePassword1Pux/SoftwareLicense"; +import { WirelessRouterData } from "./testData/onePassword1Pux/WirelessRouter"; + +function validateCustomField(fields: FieldView[], fieldName: string, expectedValue: any) { + expect(fields).toBeDefined(); + const customField = fields.find((f) => f.name === fieldName); + expect(customField).toBeDefined(); + + expect(customField.value).toEqual(expectedValue); +} + +describe("1Password 1Pux Importer", () => { + const OnePuxExampleFileJson = JSON.stringify(OnePuxExampleFile); + const LoginDataJson = JSON.stringify(LoginData); + const CreditCardDataJson = JSON.stringify(CreditCardData); + const IdentityDataJson = JSON.stringify(IdentityData); + const SecureNoteDataJson = JSON.stringify(SecureNoteData); + const SanitizedExportJson = JSON.stringify(SanitizedExport); + + it("should parse login data", async () => { + const importer = new Importer(); + const result = await importer.parse(LoginDataJson); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Login); + expect(cipher.name).toEqual("eToro"); + + expect(cipher.login.username).toEqual("username123123123@gmail.com"); + expect(cipher.login.password).toEqual("password!"); + expect(cipher.login.uris.length).toEqual(1); + expect(cipher.login.uri).toEqual("https://www.fakesite.com"); + expect(cipher.login.totp).toEqual("otpseed777"); + + // remaining fields as custom fields + expect(cipher.fields.length).toEqual(3); + validateCustomField(cipher.fields, "terms", "false"); + validateCustomField(cipher.fields, "policies", "true"); + validateCustomField(cipher.fields, "cyqyggt2otns6tbbqtsl6w2ceu", "username123123"); + }); + + it("should parse notes", async () => { + const importer = new Importer(); + const result = await importer.parse(OnePuxExampleFileJson); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.notes).toEqual("This is a note. *bold*! _italic_!"); + }); + + it("should set favourite if favIndex equals 1", async () => { + const importer = new Importer(); + const result = await importer.parse(OnePuxExampleFileJson); + expect(result != null).toBe(true); + + const cipher = result.ciphers.shift(); + expect(cipher.favorite).toBe(true); + }); + + it("should handle custom boolean fields", async () => { + const importer = new Importer(); + const result = await importer.parse(LoginDataJson); + expect(result != null).toBe(true); + + const ciphers = result.ciphers; + expect(ciphers.length).toEqual(1); + + const cipher = ciphers.shift(); + expect(cipher.fields[0].name).toEqual("terms"); + expect(cipher.fields[0].value).toEqual("false"); + expect(cipher.fields[0].type).toBe(FieldType.Boolean); + + expect(cipher.fields[1].name).toEqual("policies"); + expect(cipher.fields[1].value).toEqual("true"); + expect(cipher.fields[1].type).toBe(FieldType.Boolean); + }); + + it("should add fields of type email as custom fields", async () => { + const importer = new Importer(); + const EmailFieldDataJson = JSON.stringify(EmailFieldData); + const result = await importer.parse(EmailFieldDataJson); + expect(result != null).toBe(true); + + const ciphers = result.ciphers; + expect(ciphers.length).toEqual(1); + const cipher = ciphers.shift(); + + expect(cipher.fields[0].name).toEqual("reg_email"); + expect(cipher.fields[0].value).toEqual("kriddler@nullvalue.test"); + expect(cipher.fields[0].type).toBe(FieldType.Text); + + expect(cipher.fields[1].name).toEqual("provider"); + expect(cipher.fields[1].value).toEqual("myEmailProvider"); + expect(cipher.fields[1].type).toBe(FieldType.Text); + }); + + it('should create concealed field as "hidden" type', async () => { + const importer = new Importer(); + const result = await importer.parse(OnePuxExampleFileJson); + expect(result != null).toBe(true); + + const ciphers = result.ciphers; + expect(ciphers.length).toEqual(1); + + const cipher = ciphers.shift(); + const fields = cipher.fields; + expect(fields.length).toEqual(1); + + const field = fields.shift(); + expect(field.name).toEqual("PIN"); + expect(field.value).toEqual("12345"); + expect(field.type).toEqual(FieldType.Hidden); + }); + + it("should create password history", async () => { + const importer = new Importer(); + const result = await importer.parse(OnePuxExampleFileJson); + const cipher = result.ciphers.shift(); + + expect(cipher.passwordHistory.length).toEqual(1); + const ph = cipher.passwordHistory.shift(); + expect(ph.password).toEqual("12345password"); + expect(ph.lastUsedDate.toISOString()).toEqual("2016-03-18T17:32:35.000Z"); + }); + + it("should create credit card records", async () => { + const importer = new Importer(); + const result = await importer.parse(CreditCardDataJson); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("Parent's Credit Card"); + expect(cipher.notes).toEqual("My parents' credit card."); + + const card = cipher.card; + expect(card.cardholderName).toEqual("Fred Engels"); + expect(card.number).toEqual("6011111111111117"); + expect(card.code).toEqual("1312"); + expect(card.brand).toEqual("Discover"); + expect(card.expMonth).toEqual("12"); + expect(card.expYear).toEqual("2099"); + + // remaining fields as custom fields + expect(cipher.fields.length).toEqual(12); + validateCustomField(cipher.fields, "txbzvwzpck7ejhfres3733rbpm", "card"); + validateCustomField(cipher.fields, "cashLimit", "$500"); + validateCustomField(cipher.fields, "creditLimit", "$1312"); + validateCustomField(cipher.fields, "validFrom", "200101"); + validateCustomField(cipher.fields, "bank", "Some bank"); + validateCustomField(cipher.fields, "phoneLocal", "123456"); + validateCustomField(cipher.fields, "phoneTollFree", "0800123456"); + validateCustomField(cipher.fields, "phoneIntl", "+49123456"); + validateCustomField(cipher.fields, "website", "somebank.com"); + validateCustomField(cipher.fields, "pin", "1234"); + validateCustomField(cipher.fields, "interest", "1%"); + validateCustomField(cipher.fields, "issuenumber", "123456"); + }); + + it("should create identity records", async () => { + const importer = new Importer(); + const result = await importer.parse(IdentityDataJson); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("George Engels"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("George"); + expect(identity.middleName).toEqual("S"); + expect(identity.lastName).toEqual("Engels"); + expect(identity.company).toEqual("Acme Inc."); + expect(identity.address1).toEqual("1312 Main St."); + expect(identity.country).toEqual("US"); + expect(identity.state).toEqual("California"); + expect(identity.city).toEqual("Atlantis"); + expect(identity.postalCode).toEqual("90210"); + expect(identity.phone).toEqual("4565555555"); + expect(identity.email).toEqual("gengels@nullvalue.test"); + expect(identity.username).toEqual("gengels"); + + // remaining fields as custom fields + expect(cipher.fields.length).toEqual(17); + validateCustomField(cipher.fields, "sex", "male"); + validateCustomField(cipher.fields, "birthdate", "Thu, 01 Jan 1981 12:01:00 GMT"); + validateCustomField(cipher.fields, "occupation", "Steel Worker"); + validateCustomField(cipher.fields, "department", "QA"); + validateCustomField(cipher.fields, "jobtitle", "Quality Assurance Manager"); + validateCustomField(cipher.fields, "homephone", "4575555555"); + validateCustomField(cipher.fields, "cellphone", "4585555555"); + validateCustomField(cipher.fields, "busphone", "4595555555"); + validateCustomField(cipher.fields, "reminderq", "Who's a super cool guy?"); + validateCustomField(cipher.fields, "remindera", "Me, buddy."); + validateCustomField(cipher.fields, "website", "cv.gengels.nullvalue.test"); + validateCustomField(cipher.fields, "icq", "12345678"); + validateCustomField(cipher.fields, "skype", "skypeisbad1619"); + validateCustomField(cipher.fields, "aim", "aollol@lololol.aol.com"); + validateCustomField(cipher.fields, "yahoo", "sk8rboi13@yah00.com"); + validateCustomField(cipher.fields, "msn", "msnothankyou@msn&m&m.com"); + validateCustomField(cipher.fields, "forumsig", "super cool guy"); + }); + + it("emails fields on identity types should be added to the identity email field", async () => { + const importer = new Importer(); + const EmailFieldOnIdentityDataJson = JSON.stringify(EmailFieldOnIdentityData); + const result = await importer.parse(EmailFieldOnIdentityDataJson); + expect(result != null).toBe(true); + + const ciphers = result.ciphers; + expect(ciphers.length).toEqual(1); + const cipher = ciphers.shift(); + + const identity = cipher.identity; + expect(identity.email).toEqual("gengels@nullvalue.test"); + + expect(cipher.fields[0].name).toEqual("provider"); + expect(cipher.fields[0].value).toEqual("myEmailProvider"); + expect(cipher.fields[0].type).toBe(FieldType.Text); + }); + + it("emails fields on identity types should be added to custom fields if identity.email has been filled", async () => { + const importer = new Importer(); + const EmailFieldOnIdentityPrefilledDataJson = JSON.stringify(EmailFieldOnIdentityPrefilledData); + const result = await importer.parse(EmailFieldOnIdentityPrefilledDataJson); + expect(result != null).toBe(true); + + const ciphers = result.ciphers; + expect(ciphers.length).toEqual(1); + const cipher = ciphers.shift(); + + const identity = cipher.identity; + expect(identity.email).toEqual("gengels@nullvalue.test"); + + expect(cipher.fields[0].name).toEqual("2nd_email"); + expect(cipher.fields[0].value).toEqual("kriddler@nullvalue.test"); + expect(cipher.fields[0].type).toBe(FieldType.Text); + + expect(cipher.fields[1].name).toEqual("provider"); + expect(cipher.fields[1].value).toEqual("myEmailProvider"); + expect(cipher.fields[1].type).toBe(FieldType.Text); + }); + + it("should parse category 005 - Password (Legacy)", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(PasswordData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.type).toEqual(CipherType.Login); + expect(cipher.name).toEqual("SuperSecret Password"); + expect(cipher.notes).toEqual("SuperSecret Password Notes"); + + expect(cipher.login.password).toEqual("GBq[AGb]4*Si3tjwuab^"); + expect(cipher.login.uri).toEqual("https://n0t.y0ur.n0rm4l.w3bs1t3"); + }); + + it("should parse category 100 - SoftwareLicense", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(SoftwareLicenseData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.type).toEqual(CipherType.SecureNote); + expect(cipher.name).toEqual("Limux Product Key"); + expect(cipher.notes).toEqual("My Software License"); + + expect(cipher.fields.length).toEqual(13); + validateCustomField(cipher.fields, "product_version", "5.10.1000"); + validateCustomField(cipher.fields, "reg_code", "265453-13457355-847327"); + validateCustomField(cipher.fields, "reg_name", "Kay Riddler"); + validateCustomField(cipher.fields, "reg_email", "kriddler@nullvalue.test"); + validateCustomField(cipher.fields, "company", "Riddles and Jigsaw Puzzles GmbH"); + validateCustomField( + cipher.fields, + "download_link", + "https://limuxcompany.nullvalue.test/5.10.1000/isos" + ); + validateCustomField(cipher.fields, "publisher_name", "Limux Software and Hardware"); + validateCustomField(cipher.fields, "publisher_website", "https://limuxcompany.nullvalue.test/"); + validateCustomField(cipher.fields, "retail_price", "$999"); + validateCustomField(cipher.fields, "support_email", "support@nullvalue.test"); + validateCustomField(cipher.fields, "order_date", "Thu, 01 Apr 2021 12:01:00 GMT"); + validateCustomField(cipher.fields, "order_number", "594839"); + validateCustomField(cipher.fields, "order_total", "$1086.59"); + }); + + it("should parse category 101 - BankAccount", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(BankAccountData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.type).toEqual(CipherType.Card); + expect(cipher.name).toEqual("Bank Account"); + expect(cipher.notes).toEqual("My Bank Account"); + + expect(cipher.card.cardholderName).toEqual("Cool Guy"); + + expect(cipher.fields.length).toEqual(9); + validateCustomField(cipher.fields, "bankName", "Super Credit Union"); + validateCustomField(cipher.fields, "accountType", "checking"); + validateCustomField(cipher.fields, "routingNo", "111000999"); + validateCustomField(cipher.fields, "accountNo", "192837465918273645"); + validateCustomField(cipher.fields, "swift", "123456"); + validateCustomField(cipher.fields, "iban", "DE12 123456"); + validateCustomField(cipher.fields, "telephonePin", "5555"); + validateCustomField(cipher.fields, "branchPhone", "9399399933"); + validateCustomField(cipher.fields, "branchAddress", "1 Fifth Avenue"); + }); + + it("should parse category 102 - Database", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(DatabaseData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Login); + expect(cipher.name).toEqual("Database"); + expect(cipher.notes).toEqual("My Database"); + + const login = cipher.login; + expect(login.username).toEqual("cooldbuser"); + expect(login.password).toEqual("^+kTjhLaN7wVPAhGU)*J"); + + expect(cipher.fields.length).toEqual(7); + validateCustomField(cipher.fields, "database_type", "postgresql"); + validateCustomField(cipher.fields, "hostname", "my.secret.db.server"); + validateCustomField(cipher.fields, "port", "1337"); + validateCustomField(cipher.fields, "database", "user_database"); + validateCustomField(cipher.fields, "sid", "ASDIUFU-283234"); + validateCustomField(cipher.fields, "alias", "cdbu"); + validateCustomField(cipher.fields, "options", "ssh"); + }); + + it("should parse category 103 - Drivers license", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(DriversLicenseData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("Michael Scarn"); + expect(cipher.subTitle).toEqual("Michael Scarn"); + expect(cipher.notes).toEqual("My Driver's License"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("Michael"); + expect(identity.middleName).toBeNull(); + expect(identity.lastName).toEqual("Scarn"); + expect(identity.address1).toEqual("2120 Mifflin Rd."); + expect(identity.state).toEqual("Pennsylvania"); + expect(identity.country).toEqual("United States"); + expect(identity.licenseNumber).toEqual("12345678901"); + + expect(cipher.fields.length).toEqual(6); + validateCustomField(cipher.fields, "birthdate", "Sun, 01 Jan 1978 12:01:00 GMT"); + validateCustomField(cipher.fields, "sex", "male"); + validateCustomField(cipher.fields, "height", "5'11\""); + validateCustomField(cipher.fields, "class", "C"); + validateCustomField(cipher.fields, "conditions", "B"); + validateCustomField(cipher.fields, "expiry_date", "203012"); + }); + + it("should parse category 104 - Outdoor License", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(OutdoorLicenseData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Identity); + expect(cipher.name).toEqual("Harvest License"); + expect(cipher.subTitle).toEqual("Cash Bandit"); + expect(cipher.notes).toEqual("My Outdoor License"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("Cash"); + expect(identity.middleName).toBeNull(); + expect(identity.lastName).toEqual("Bandit"); + expect(identity.state).toEqual("Washington"); + expect(identity.country).toEqual("United States of America"); + + expect(cipher.fields.length).toEqual(4); + validateCustomField(cipher.fields, "valid_from", "Thu, 01 Apr 2021 12:01:00 GMT"); + validateCustomField(cipher.fields, "expires", "Fri, 01 Apr 2044 12:01:00 GMT"); + validateCustomField(cipher.fields, "game", "Bananas,blueberries,corn"); + validateCustomField(cipher.fields, "quota", "100/each"); + }); + + it("should parse category 105 - Membership", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(MembershipData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Identity); + expect(cipher.name).toEqual("Library Card"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("George"); + expect(identity.middleName).toBeNull(); + expect(identity.lastName).toEqual("Engels"); + expect(identity.company).toEqual("National Public Library"); + expect(identity.phone).toEqual("9995555555"); + + expect(cipher.fields.length).toEqual(5); + validateCustomField(cipher.fields, "website", "https://npl.nullvalue.gov.test"); + validateCustomField(cipher.fields, "member_since", "199901"); + validateCustomField(cipher.fields, "expiry_date", "203412"); + validateCustomField(cipher.fields, "membership_no", "64783862"); + validateCustomField(cipher.fields, "pin", "19191"); + }); + + it("should parse category 106 - Passport", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(PassportData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Identity); + expect(cipher.name).toEqual("Mr. Globewide"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("David"); + expect(identity.middleName).toBeNull(); + expect(identity.lastName).toEqual("Global"); + expect(identity.passportNumber).toEqual("76436847"); + + expect(cipher.fields.length).toEqual(8); + validateCustomField(cipher.fields, "type", "US Passport"); + validateCustomField(cipher.fields, "sex", "female"); + validateCustomField(cipher.fields, "nationality", "International"); + validateCustomField(cipher.fields, "issuing_authority", "Department of State"); + validateCustomField(cipher.fields, "birthdate", "Fri, 01 Apr 1983 12:01:00 GMT"); + validateCustomField(cipher.fields, "birthplace", "A cave somewhere in Maine"); + validateCustomField(cipher.fields, "issue_date", "Wed, 01 Jan 2020 12:01:00 GMT"); + validateCustomField(cipher.fields, "expiry_date", "Sat, 01 Jan 2050 12:01:00 GMT"); + }); + + it("should parse category 107 - RewardsProgram", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(RewardsProgramData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Identity); + expect(cipher.name).toEqual("Retail Reward Thing"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("Chef"); + expect(identity.middleName).toBeNull(); + expect(identity.lastName).toEqual("Coldroom"); + expect(identity.company).toEqual("Super Cool Store Co."); + + expect(cipher.fields.length).toEqual(7); + validateCustomField(cipher.fields, "membership_no", "member-29813569"); + validateCustomField(cipher.fields, "pin", "99913"); + validateCustomField(cipher.fields, "additional_no", "additional member id"); + validateCustomField(cipher.fields, "member_since", "202101"); + validateCustomField(cipher.fields, "customer_service_phone", "123456"); + validateCustomField(cipher.fields, "reservations_phone", "123456"); + validateCustomField(cipher.fields, "website", "supercoolstore.com"); + }); + + it("should parse category 108 - SSN", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(SSNData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.name).toEqual("SSN"); + + const identity = cipher.identity; + expect(identity.firstName).toEqual("Jack"); + expect(identity.middleName).toBeNull(); + expect(identity.lastName).toEqual("Judd"); + expect(identity.ssn).toEqual("131-216-1900"); + }); + + it("should parse category 109 - WirelessRouter", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(WirelessRouterData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Login); + expect(cipher.name).toEqual("Wireless Router"); + expect(cipher.notes).toEqual("My Wifi Router Config"); + + expect(cipher.login.password).toEqual("BqatGTVQ9TCN72tLbjrsHqkb"); + + expect(cipher.fields.length).toEqual(7); + validateCustomField(cipher.fields, "name", "pixel 2Xl"); + validateCustomField(cipher.fields, "server", "127.0.0.1"); + validateCustomField(cipher.fields, "airport_id", "some airportId"); + validateCustomField(cipher.fields, "network_name", "some network name"); + validateCustomField(cipher.fields, "wireless_security", "WPA"); + validateCustomField(cipher.fields, "wireless_password", "wifipassword"); + validateCustomField(cipher.fields, "disk_password", "diskpassword"); + }); + + it("should parse category 110 - Server", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(ServerData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Login); + expect(cipher.name).toEqual("Super Cool Server"); + expect(cipher.notes).toEqual("My Server"); + + expect(cipher.login.username).toEqual("frankly-notsure"); + expect(cipher.login.password).toEqual("*&YHJI87yjy78u"); + expect(cipher.login.uri).toEqual("https://coolserver.nullvalue.test"); + + expect(cipher.fields.length).toEqual(7); + validateCustomField( + cipher.fields, + "admin_console_url", + "https://coolserver.nullvalue.test/admin" + ); + validateCustomField(cipher.fields, "admin_console_username", "frankly-idontknowwhatimdoing"); + validateCustomField(cipher.fields, "admin_console_password", "^%RY&^YUiju8iUYHJI(U"); + validateCustomField(cipher.fields, "name", "Private Hosting Provider Inc."); + validateCustomField(cipher.fields, "website", "https://phpi.nullvalue.test"); + validateCustomField( + cipher.fields, + "support_contact_url", + "https://phpi.nullvalue.test/support" + ); + validateCustomField(cipher.fields, "support_contact_phone", "8882569382"); + }); + + it("should parse category 111 - EmailAccount", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(EmailAccountData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.SecureNote); + expect(cipher.name).toEqual("Email Config"); + expect(cipher.notes).toEqual("My Email Config"); + + expect(cipher.fields.length).toEqual(17); + validateCustomField(cipher.fields, "pop_type", "either"); + validateCustomField(cipher.fields, "pop_username", "someuser@nullvalue.test"); + validateCustomField(cipher.fields, "pop_server", "mailserver.nullvalue.test"); + validateCustomField(cipher.fields, "pop_port", "587"); + validateCustomField(cipher.fields, "pop_password", "u1jsf { + const importer = new Importer(); + const jsonString = JSON.stringify(APICredentialsData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.type).toEqual(CipherType.Login); + expect(cipher.name).toEqual("API Credential"); + expect(cipher.notes).toEqual("My API Credential"); + + expect(cipher.login.username).toEqual("apiuser@nullvalue.test"); + expect(cipher.login.password).toEqual("apiapiapiapiapiapiappy"); + expect(cipher.login.uri).toEqual("http://not.your.everyday.hostname"); + + expect(cipher.fields.length).toEqual(4); + validateCustomField(cipher.fields, "type", "jwt"); + validateCustomField(cipher.fields, "filename", "filename.jwt"); + validateCustomField(cipher.fields, "validFrom", "Mon, 04 Apr 2011 12:01:00 GMT"); + validateCustomField(cipher.fields, "expires", "Tue, 01 Apr 2031 12:01:00 GMT"); + }); + + it("should create secure notes", async () => { + const importer = new Importer(); + const result = await importer.parse(SecureNoteDataJson); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + + expect(cipher.name).toEqual("Secure Note #1"); + expect(cipher.notes).toEqual( + "This is my secure note. \n\nLorem ipsum expecto patronum. \nThe quick brown fox jumped over the lazy dog." + ); + expect(cipher.secureNote.type).toEqual(SecureNoteType.Generic); + }); + + it("should parse category 113 - Medical Record", async () => { + const importer = new Importer(); + const jsonString = JSON.stringify(MedicalRecordData); + const result = await importer.parse(jsonString); + expect(result != null).toBe(true); + const cipher = result.ciphers.shift(); + expect(cipher.type).toEqual(CipherType.SecureNote); + expect(cipher.name).toEqual("Some Health Record"); + expect(cipher.notes).toEqual("Some notes about my medical history"); + expect(cipher.secureNote.type).toEqual(SecureNoteType.Generic); + + expect(cipher.fields.length).toEqual(8); + validateCustomField(cipher.fields, "date", "Sat, 01 Jan 2022 12:01:00 GMT"); + validateCustomField(cipher.fields, "location", "some hospital/clinic"); + validateCustomField(cipher.fields, "healthcareprofessional", "Some Doctor"); + validateCustomField(cipher.fields, "patient", "Me"); + validateCustomField(cipher.fields, "reason", "unwell"); + validateCustomField(cipher.fields, "medication", "Insuline"); + validateCustomField(cipher.fields, "dosage", "1"); + validateCustomField(cipher.fields, "notes", "multiple times a day"); + }); + + it("should create folders", async () => { + const importer = new Importer(); + const result = await importer.parse(SanitizedExportJson); + expect(result != null).toBe(true); + + const folders = result.folders; + expect(folders.length).toBe(5); + expect(folders[0].name).toBe("Movies"); + expect(folders[1].name).toBe("Finance"); + expect(folders[2].name).toBe("Travel"); + expect(folders[3].name).toBe("Education"); + expect(folders[4].name).toBe("Starter Kit"); + + // Check that ciphers have a folder assigned to them + expect(result.ciphers.filter((c) => c.folderId === folders[0].id).length).toBeGreaterThan(0); + expect(result.ciphers.filter((c) => c.folderId === folders[1].id).length).toBeGreaterThan(0); + expect(result.ciphers.filter((c) => c.folderId === folders[2].id).length).toBeGreaterThan(0); + expect(result.ciphers.filter((c) => c.folderId === folders[3].id).length).toBeGreaterThan(0); + expect(result.ciphers.filter((c) => c.folderId === folders[4].id).length).toBeGreaterThan(0); + }); + + it("should create collections if part of an organization", async () => { + const importer = new Importer(); + importer.organizationId = Utils.newGuid(); + const result = await importer.parse(SanitizedExportJson); + expect(result != null).toBe(true); + + const collections = result.collections; + expect(collections.length).toBe(5); + expect(collections[0].name).toBe("Movies"); + expect(collections[1].name).toBe("Finance"); + expect(collections[2].name).toBe("Travel"); + expect(collections[3].name).toBe("Education"); + expect(collections[4].name).toBe("Starter Kit"); + }); +}); diff --git a/libs/common/spec/importers/onepasswordMacCsvImporter.spec.ts b/libs/common/spec/importers/onepasswordMacCsvImporter.spec.ts new file mode 100644 index 0000000000..73569fc6ea --- /dev/null +++ b/libs/common/spec/importers/onepasswordMacCsvImporter.spec.ts @@ -0,0 +1,74 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { OnePasswordMacCsvImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepasswordMacCsvImporter"; +import { CipherView } from "jslib-common/models/view/cipherView"; + +import { data as creditCardData } from "./testData/onePasswordCsv/creditCard.mac.csv"; +import { data as identityData } from "./testData/onePasswordCsv/identity.mac.csv"; +import { data as multiTypeData } from "./testData/onePasswordCsv/multipleItems.mac.csv"; + +function expectIdentity(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + + expect(cipher.identity).toEqual( + expect.objectContaining({ + firstName: "first name", + middleName: "mi", + lastName: "last name", + username: "userNam3", + company: "bitwarden", + phone: "8005555555", + email: "email@bitwarden.com", + }) + ); + + expect(cipher.notes).toContain("address\ncity state zip\nUnited States"); +} + +function expectCreditCard(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Card); + + expect(cipher.card).toEqual( + expect.objectContaining({ + number: "4111111111111111", + code: "111", + cardholderName: "test", + expMonth: "1", + expYear: "2030", + }) + ); +} + +describe("1Password mac CSV Importer", () => { + it("should parse identity records", async () => { + const importer = new Importer(); + const result = await importer.parse(identityData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectIdentity(cipher); + }); + + it("should parse credit card records", async () => { + const importer = new Importer(); + const result = await importer.parse(creditCardData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectCreditCard(cipher); + }); + + it("should parse csv's with multiple record type", async () => { + const importer = new Importer(); + const result = await importer.parse(multiTypeData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(4); + expectIdentity(result.ciphers[1]); + expectCreditCard(result.ciphers[2]); + }); +}); diff --git a/libs/common/spec/importers/onepasswordWinCsvImporter.spec.ts b/libs/common/spec/importers/onepasswordWinCsvImporter.spec.ts new file mode 100644 index 0000000000..bfc1044a16 --- /dev/null +++ b/libs/common/spec/importers/onepasswordWinCsvImporter.spec.ts @@ -0,0 +1,87 @@ +import { CipherType } from "jslib-common/enums/cipherType"; +import { FieldType } from "jslib-common/enums/fieldType"; +import { OnePasswordWinCsvImporter as Importer } from "jslib-common/importers/onepasswordImporters/onepasswordWinCsvImporter"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { FieldView } from "jslib-common/models/view/fieldView"; + +import { data as creditCardData } from "./testData/onePasswordCsv/creditCard.windows.csv"; +import { data as identityData } from "./testData/onePasswordCsv/identity.windows.csv"; +import { data as multiTypeData } from "./testData/onePasswordCsv/multipleItems.windows.csv"; + +function expectIdentity(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Identity); + + expect(cipher.identity).toEqual( + expect.objectContaining({ + firstName: "first name", + middleName: "mi", + lastName: "last name", + username: "userNam3", + company: "bitwarden", + phone: "8005555555", + email: "email@bitwarden.com", + }) + ); + + expect(cipher.fields).toEqual( + expect.arrayContaining([ + Object.assign(new FieldView(), { + type: FieldType.Text, + name: "address", + value: "address city state zip us", + }), + ]) + ); +} + +function expectCreditCard(cipher: CipherView) { + expect(cipher.type).toBe(CipherType.Card); + + expect(cipher.card).toEqual( + expect.objectContaining({ + number: "4111111111111111", + code: "111", + cardholderName: "test", + expMonth: "1", + expYear: "1970", + }) + ); +} + +describe("1Password windows CSV Importer", () => { + let importer: Importer; + beforeEach(() => { + importer = new Importer(); + }); + + it("should parse identity records", async () => { + const result = await importer.parse(identityData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectIdentity(cipher); + }); + + it("should parse credit card records", async () => { + const result = await importer.parse(creditCardData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(1); + const cipher = result.ciphers[0]; + expectCreditCard(cipher); + }); + + it("should parse csv's with multiple record types", async () => { + const result = await importer.parse(multiTypeData); + + expect(result).not.toBeNull(); + expect(result.success).toBe(true); + expect(result.ciphers.length).toBe(4); + + expectIdentity(result.ciphers[1]); + expectCreditCard(result.ciphers[2]); + }); +}); diff --git a/libs/common/spec/importers/safariCsvImporter.spec.ts b/libs/common/spec/importers/safariCsvImporter.spec.ts new file mode 100644 index 0000000000..f1e1186fe8 --- /dev/null +++ b/libs/common/spec/importers/safariCsvImporter.spec.ts @@ -0,0 +1,74 @@ +import { SafariCsvImporter as Importer } from "jslib-common/importers/safariCsvImporter"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { LoginUriView } from "jslib-common/models/view/loginUriView"; +import { LoginView } from "jslib-common/models/view/loginView"; + +import { data as oldSimplePasswordData } from "./testData/safariCsv/oldSimplePasswordData.csv"; +import { data as simplePasswordData } from "./testData/safariCsv/simplePasswordData.csv"; + +const CipherData = [ + { + title: "should parse URLs in new CSV format", + csv: simplePasswordData, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "example.com (example_user)", + login: Object.assign(new LoginView(), { + username: "example_user", + password: "example_p@ssword", + uris: [ + Object.assign(new LoginUriView(), { + uri: "https://example.com", + }), + ], + totp: "otpauth://totp/test?secret=examplesecret", + }), + notes: "Example note\nMore notes on new line", + type: 1, + }), + }, + { + title: "should parse URLs in old CSV format", + csv: oldSimplePasswordData, + expected: Object.assign(new CipherView(), { + id: null, + organizationId: null, + folderId: null, + name: "example.com (example_user)", + login: Object.assign(new LoginView(), { + username: "example_user", + password: "example_p@ssword", + uris: [ + Object.assign(new LoginUriView(), { + uri: "https://example.com", + }), + ], + }), + type: 1, + }), + }, +]; + +describe("Safari CSV Importer", () => { + CipherData.forEach((data) => { + it(data.title, async () => { + const importer = new Importer(); + const result = await importer.parse(data.csv); + expect(result != null).toBe(true); + expect(result.ciphers.length).toBeGreaterThan(0); + + const cipher = result.ciphers.shift(); + let property: keyof typeof data.expected; + for (property in data.expected) { + // eslint-disable-next-line + if (data.expected.hasOwnProperty(property)) { + // eslint-disable-next-line + expect(cipher.hasOwnProperty(property)).toBe(true); + expect(cipher[property]).toEqual(data.expected[property]); + } + } + }); + }); +}); diff --git a/libs/common/spec/importers/testData/bitwardenJson/empty.json.ts b/libs/common/spec/importers/testData/bitwardenJson/empty.json.ts new file mode 100644 index 0000000000..43ab8c763a --- /dev/null +++ b/libs/common/spec/importers/testData/bitwardenJson/empty.json.ts @@ -0,0 +1 @@ +export const data = '{"encrypted":false,"folders":[],"items":[]}'; diff --git a/libs/common/spec/importers/testData/bitwardenJson/passwordProtected.json.ts b/libs/common/spec/importers/testData/bitwardenJson/passwordProtected.json.ts new file mode 100644 index 0000000000..0462e83423 --- /dev/null +++ b/libs/common/spec/importers/testData/bitwardenJson/passwordProtected.json.ts @@ -0,0 +1,9 @@ +export const data = `{ + "encrypted": true, + "passwordProtected": true, + "salt": "Oy0xcgVRzxQ+9NpB5GLehw==", + "kdfIterations": 100000, + "kdfType": 0, + "encKeyValidation_DO_NOT_EDIT": "2.sZs4Jc1HW9rhABzRRYR/gQ==|8kTDaDxafulnybpWoqVX8RAybhVRTr+dffNjms271Y7amQmIE1VSMwLbk+b2vxZb|IqOo6oXQtmv/Xb/GHDi42XG9c9ILePYtP5qq584VWcg=", + "data": "2.D0AXAf7G/XIwq6EC7A0Suw==|4w+m0wHRo25y1T1Syh5wdAUyF8voqEy54waMEsbnK0Nzee959w54ru5D1NntvxZL4HFqkQLyR6jCFkn5g40f+MGJgihS/wvf4NcJJfLiiFo6MEDOQNBkxw7ZBGuHiKfVuBO5u36JgzQtZ8lyFaduGxFszuF5c+URiE9PDh9jY0//poVgHKwuLZuYFIW+f7h6T+shUWK0ya11lcHn/B/CA2xiI+YiKdNZreJrwN0yslpJ/f+MrOzagvftRjt0GNkwveCtwcYUw/zFvqvibUpKeHcRiXs8SaGoHJ5RTm69FbJ7C5tnLwoVT89Af156uvRAXV7yAC4oPcbU/3TGb6hqYosvi1QNyaqG3M9gxS6+AK0C4yWuNbMLDEr+MWiw0SWLVMKQEkCZ4oM+oTCx52otW3+2V9I8Pv3KmmhkvVvE4wBdweOJeRX53Tf5ySkmpIhCfzj6JMmxO+nmTXIhWnJChr4hPVh+ixv1GQK5thIPTCMXmAtXoTIFUx1KWjS6LjOdi2hKQueVI+XZjf0qnY2vTMxRg0ZsLBA2znQTx+DSEqumORb5T/lV73pWZiCNePSAE2msOm7tep+lm4O/VCViCfXjITAY196syhOK0XnhxJvPALchZY8sYRAfuw6hHoDiVr+JUieRoI7eUrhXBp+D6Py9TL/dS/rHe+C2Zhx+xwx2NfGt+xEp8ZAOOCxgZ0UTeSA/abm0Oz7tJIK1n26acQrgbr7rMeBymAX+5L5OWlwI1hGgEBfj6W0rrbSXf3VMfaFXZ5UsXi1VhzQmU3LyWENoDeImXFQj6zMbUSfcVwLsG5Fg8Ee/kO/wJPfG5BO51+/vFqQj6AkaMEcwg5xNrObHYfQ/DMhIn7YDM2zdzbNTdhnobGkz6YRKFPCgFe3EmIEPEpeh9S3eKE9C7MQsrR8jVSiseR/FipJLsN+W7iOwzeXdwxUFlC/0a98bTKvdrbMgNi6ZVXykHY/t2UyEGpxZGTHoZwhX01kiQrwzC4/+v/676ldxPluO9GY7MtrLveCDsiyBz15u43IGHayDEBNT0rqrOKLYmfzwCWoahRLZQrSmepe/FXqgPqRfyWc/Ro+w3sT9dXUkx3B5xxWgSyABowPV48yBUSJuefhKTpqgzkU+LzhNnWHjnxJzzQ2/|IhlRjnyhIoDM85qHX/bY2zaIU5YaRO/iFVTQDd3uFDo=" +}`; diff --git a/libs/common/spec/importers/testData/dashlaneCsv/credentials.csv.ts b/libs/common/spec/importers/testData/dashlaneCsv/credentials.csv.ts new file mode 100644 index 0000000000..78e42cb1ae --- /dev/null +++ b/libs/common/spec/importers/testData/dashlaneCsv/credentials.csv.ts @@ -0,0 +1,2 @@ +export const credentialsData = `username,username2,username3,title,password,note,url,category,otpSecret +jdoe,,,example.com,somePassword,some note for example.com,https://www.example.com,Entertainment,someTOTPSeed`; diff --git a/libs/common/spec/importers/testData/dashlaneCsv/id.csv.ts b/libs/common/spec/importers/testData/dashlaneCsv/id.csv.ts new file mode 100644 index 0000000000..1c939557b4 --- /dev/null +++ b/libs/common/spec/importers/testData/dashlaneCsv/id.csv.ts @@ -0,0 +1,6 @@ +export const identityData = `type,number,name,issue_date,expiration_date,place_of_issue,state +card,123123123,John Doe,2022-1-30,2032-1-30,, +passport,123123123,John Doe,2022-1-30,2032-1-30,somewhere in Germany, +license,1234556,John Doe,2022-8-10,2022-10-10,,DC +social_security,123123123,John Doe,,,, +tax_number,123123123,,,,,`; diff --git a/libs/common/spec/importers/testData/dashlaneCsv/multiplePersonalInfo.csv.ts b/libs/common/spec/importers/testData/dashlaneCsv/multiplePersonalInfo.csv.ts new file mode 100644 index 0000000000..cca5748b45 --- /dev/null +++ b/libs/common/spec/importers/testData/dashlaneCsv/multiplePersonalInfo.csv.ts @@ -0,0 +1,7 @@ +export const multiplePersonalInfoData = `type,title,first_name,middle_name,last_name,login,date_of_birth,place_of_birth,email,email_type,item_name,phone_number,address,country,state,city,zip,address_recipient,address_building,address_apartment,address_floor,address_door_code,job_title,url +name,MR,John,,Doe,jdoe,2022-01-30,world,,,,,,,,,,,,,,,, +email,,,,,,,,jdoe@example.com,personal,Johns email,,,,,,,,,,,,, +number,,,,,,,,,,John's number,+49123123123,,,,,,,,,,,, +address,,,,,,,,,,John's home address,,1 some street,de,DE-0-NW,some city,123123,John,1,1,1,123,, +website,,,,,,,,,,Website,,,,,,,,,,,,,website.com +name,Mrs,Jane,,Doe,jdoe,2022-01-30,earth,,,,,,,,,,,,,,,,`; diff --git a/libs/common/spec/importers/testData/dashlaneCsv/payments.csv.ts b/libs/common/spec/importers/testData/dashlaneCsv/payments.csv.ts new file mode 100644 index 0000000000..336986c1c4 --- /dev/null +++ b/libs/common/spec/importers/testData/dashlaneCsv/payments.csv.ts @@ -0,0 +1,3 @@ +export const paymentsData = `type,account_name,account_holder,cc_number,code,expiration_month,expiration_year,routing_number,account_number,country,issuing_bank +bank,John's savings account,John Doe,,,,,routingNumber,accountNumber,US,US-ALLY +credit_card,John Doe,,41111111111111111,123,01,2023,,,US,`; diff --git a/libs/common/spec/importers/testData/dashlaneCsv/personalInfo.csv.ts b/libs/common/spec/importers/testData/dashlaneCsv/personalInfo.csv.ts new file mode 100644 index 0000000000..ec99f8006a --- /dev/null +++ b/libs/common/spec/importers/testData/dashlaneCsv/personalInfo.csv.ts @@ -0,0 +1,6 @@ +export const personalInfoData = `type,title,first_name,middle_name,last_name,login,date_of_birth,place_of_birth,email,email_type,item_name,phone_number,address,country,state,city,zip,address_recipient,address_building,address_apartment,address_floor,address_door_code,job_title,url +name,MR,John,,Doe,jdoe,2022-01-30,world,,,,,,,,,,,,,,,, +email,,,,,,,,jdoe@example.com,personal,Johns email,,,,,,,,,,,,, +number,,,,,,,,,,John's number,+49123123123,,,,,,,,,,,, +address,,,,,,,,,,John's home address,,1 some street,de,DE-0-NW,some city,123123,John,1,1,1,123,, +website,,,,,,,,,,Website,,,,,,,,,,,,,website.com`; diff --git a/libs/common/spec/importers/testData/dashlaneCsv/securenotes.csv.ts b/libs/common/spec/importers/testData/dashlaneCsv/securenotes.csv.ts new file mode 100644 index 0000000000..22a3b904f9 --- /dev/null +++ b/libs/common/spec/importers/testData/dashlaneCsv/securenotes.csv.ts @@ -0,0 +1,2 @@ +export const secureNoteData = `title,note +01,test`; diff --git a/libs/common/spec/importers/testData/firefoxCsv/firefoxAccountsData.csv.ts b/libs/common/spec/importers/testData/firefoxCsv/firefoxAccountsData.csv.ts new file mode 100644 index 0000000000..2f2c1b55e1 --- /dev/null +++ b/libs/common/spec/importers/testData/firefoxCsv/firefoxAccountsData.csv.ts @@ -0,0 +1,4 @@ +export const data = `"url","username","password","httpRealm","formActionOrigin","guid","timeCreated","timeLastUsed","timePasswordChanged" +"chrome://FirefoxAccounts","bla-bla-foo-bar","{""version"":1,""accountData"":{""kSync"":""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"",""kXCS"":""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"",""kExtSync"":""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"",""kExtKbHash"":""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"",""scopedKeys"":{""https://identity.mozilla.com/apps/oldsync"":{""kid"":""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",""k"":""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"",""kty"":""xxx""},""sync:addon_storage"":{""kid"":""xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"",""k"":""xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"",""kty"":""xxx""}}}}","Firefox Accounts credentials",,"{d61e37fa-2bc4-469a-bd66-41fd3b0005e0}","1612345678900","1612345678900","1612345678900" +"https://example.com","foo","bar",,"","{d61e37fa-2bc4-469a-bd66-41fd3b0005e0}","1612345678900","1612345678900","1612345678900" +`; diff --git a/libs/common/spec/importers/testData/firefoxCsv/simplePasswordData.csv.ts b/libs/common/spec/importers/testData/firefoxCsv/simplePasswordData.csv.ts new file mode 100644 index 0000000000..90e19f199e --- /dev/null +++ b/libs/common/spec/importers/testData/firefoxCsv/simplePasswordData.csv.ts @@ -0,0 +1,2 @@ +export const data = `"url","username","password","httpRealm","formActionOrigin","guid","timeCreated","timeLastUsed","timePasswordChanged" +"https://example.com","foo","bar",,"","{d61e37fa-2bc4-469a-bd66-41fd3b0005e0}","1612345678900","1612345678900","1612345678900"`; diff --git a/libs/common/spec/importers/testData/keeperJson/testData.ts b/libs/common/spec/importers/testData/keeperJson/testData.ts new file mode 100644 index 0000000000..fee8f54c45 --- /dev/null +++ b/libs/common/spec/importers/testData/keeperJson/testData.ts @@ -0,0 +1,90 @@ +import { KeeperJsonExport } from "jslib-common/importers/keeperImporters/types/keeperJsonTypes"; + +export const testData: KeeperJsonExport = { + shared_folders: [ + { + path: "My Customer 1", + manage_users: true, + manage_records: true, + can_edit: true, + can_share: true, + permissions: [ + { + uid: "kVM96KGEoGxhskZoSTd_jw", + manage_users: true, + manage_records: true, + }, + { + name: "user@mycompany.com", + manage_users: true, + manage_records: true, + }, + ], + }, + { + path: "Testing\\My Customer 2", + manage_users: true, + manage_records: true, + can_edit: true, + can_share: true, + permissions: [ + { + uid: "ih1CggiQ-3ENXcn4G0sl-g", + manage_users: true, + manage_records: true, + }, + { + name: "user@mycompany.com", + manage_users: true, + manage_records: true, + }, + ], + }, + ], + records: [ + { + title: "Bank Account 1", + login: "customer1234", + password: "4813fJDHF4239fdk", + login_url: "https://chase.com", + notes: "These are some notes.", + custom_fields: { + "Account Number": "123-456-789", + }, + folders: [ + { + folder: "Optional Private Folder 1", + }, + ], + }, + { + title: "Bank Account 2", + login: "mybankusername", + password: "w4k4k193f$^&@#*%2", + login_url: "https://amex.com", + notes: "Some great information here.", + custom_fields: { + "Security Group": "Public", + "IP Address": "12.45.67.8", + "TFC:Keeper": + "otpauth://totp/Amazon:me@company.com?secret=JBSWY3DPEHPK3PXP&issuer=Amazon&algorithm=SHA1&digits=6&period=30", + }, + folders: [ + { + folder: "Optional Private Folder 1", + }, + { + shared_folder: "My Customer 1", + can_edit: true, + can_share: true, + }, + ], + }, + { + title: "Some Account", + login: "someUserName", + password: "w4k4k1wergf$^&@#*%2", + login_url: "https://example.com", + }, + ], +}; diff --git a/libs/common/spec/importers/testData/mykiCsv/UserAccount.csv.ts b/libs/common/spec/importers/testData/mykiCsv/UserAccount.csv.ts new file mode 100644 index 0000000000..5ccf0971da --- /dev/null +++ b/libs/common/spec/importers/testData/mykiCsv/UserAccount.csv.ts @@ -0,0 +1,3 @@ +/* eslint-disable */ +export const userAccountData = `nickname,url,username,password,additionalInfo,twofaSecret,status,tags +PasswordNickname,www.google.com,user.name@email.com,abc123,This is the additional information text.,someTOTPSeed,active,someTag`; diff --git a/libs/common/spec/importers/testData/mykiCsv/UserCreditCard.csv.ts b/libs/common/spec/importers/testData/mykiCsv/UserCreditCard.csv.ts new file mode 100644 index 0000000000..0b127627ad --- /dev/null +++ b/libs/common/spec/importers/testData/mykiCsv/UserCreditCard.csv.ts @@ -0,0 +1,3 @@ +/* eslint-disable */ +export const userCreditCardData = `nickname,status,tags,cardNumber,cardName,exp_month,exp_year,cvv,additionalInfo +Visa test card,active,someTag,4111111111111111,Joe User,04,24,222,This is the additional information field`; diff --git a/libs/common/spec/importers/testData/mykiCsv/UserIdCard.csv.ts b/libs/common/spec/importers/testData/mykiCsv/UserIdCard.csv.ts new file mode 100644 index 0000000000..8f3fa600e2 --- /dev/null +++ b/libs/common/spec/importers/testData/mykiCsv/UserIdCard.csv.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ +export const userIdCardData = `nickname,status,tags,idType,idNumber,idName,idIssuanceDate,idExpirationDate,idCountry,additionalInfo +Joe User's nickname,active,someTag,Driver's License,123456,Joe M User,02/02/2022,02/02/2024,United States,Additional information +Passport ID card,active,someTag,Passport,1234567,Joe M User,03/07/2022,03/07/2028,United States,Additional information field +Social Security ID card,active,someTag,Social Security,123455678,Joe M User,03/07/2022,03/07/2028,United States,Additional information field text +ID card type ID card,active,someTag,ID Card,1234566,Joe M User,03/07/2022,03/07/2028,United States,Additional Information field text +Tax number ID card,active,someTag,Tax Number,12345678,Joe M User,03/07/2022,03/07/2028,United States,Additinoal information text field +Bank account ID card,active,someTag,Bank Account,12344556677,Joe M User,03/07/2022,03/07/2028,United States,Additional text information here +Insurance card ID card,active,someTag,Insurance Card,123456677,Joe M User,03/07/2022,03/07/2022,United States,Additional information text goes here +Health card Id card,active,someTag,Health Card,1234670,Joe M User,03/07/2022,03/07/2028,United States,More info +Membership ID card,active,someTag,Membership,12345709,Joe M User,03/07/2022,03/07/2028,United States,Add'l info +Database ID card,active,someTag,Database,12345089u,Joe M User,03/07/2022,03/07/2028,United States,Addin't info +Outdoor license ID card,active,someTag,Outdoor License,123890090,Joe M User,03/07/2022,03/07/2028,United States,Additional info +Reward program Id card,active,someTag,Reward Program,12345890b,Joe M User,03/07/2022,03/07/2028,United States,1234890 +Software license ID card,active,someTag,Software License,1234567c,Joe M User,03/07/2022,03/07/2028,United States,"It seems like the fields don't change, which makes it pretty useless that they have so many ID card types." +Tour visa ID card,active,someTag,Tour Visa,123456lkhj,Joe M User,03/07/2022,03/07/2028,United States,Additional Informaion text`; diff --git a/libs/common/spec/importers/testData/mykiCsv/UserIdentity.csv.ts b/libs/common/spec/importers/testData/mykiCsv/UserIdentity.csv.ts new file mode 100644 index 0000000000..13afb16dae --- /dev/null +++ b/libs/common/spec/importers/testData/mykiCsv/UserIdentity.csv.ts @@ -0,0 +1,3 @@ +/* eslint-disable */ +export const userIdentityData = `nickname,status,tags,firstName,middleName,lastName,email,firstAddressLine,secondAddressLine,title,gender,number,city,country,zipCode,additionalInfo +Joe User's nickname,active,someTag,Joe,M,User,joe.user@email.com,1 Example House,Suite 300,Mr,Male,2223334444,Portland,United States,04101,Additional information field`; diff --git a/libs/common/spec/importers/testData/mykiCsv/UserNote.csv.ts b/libs/common/spec/importers/testData/mykiCsv/UserNote.csv.ts new file mode 100644 index 0000000000..8094c92f2a --- /dev/null +++ b/libs/common/spec/importers/testData/mykiCsv/UserNote.csv.ts @@ -0,0 +1,3 @@ +/* eslint-disable */ +export const userNoteData = `nickname,status,content +The title of a secure note,active,"The content of a secure note. Lorem ipsum, etc."`; diff --git a/libs/common/spec/importers/testData/mykiCsv/UserTwofa.csv.ts b/libs/common/spec/importers/testData/mykiCsv/UserTwofa.csv.ts new file mode 100644 index 0000000000..68cfd44f38 --- /dev/null +++ b/libs/common/spec/importers/testData/mykiCsv/UserTwofa.csv.ts @@ -0,0 +1,3 @@ +/* eslint-disable */ +export const userTwoFaData = `nickname,status,tags,authToken,additionalInfo +2FA nickname,active,someTag,someTOTPSeed,"Additional information field content. "`; diff --git a/libs/common/spec/importers/testData/nordpassCsv/nordpass.card.csv.ts b/libs/common/spec/importers/testData/nordpassCsv/nordpass.card.csv.ts new file mode 100644 index 0000000000..8d79d2b1bf --- /dev/null +++ b/libs/common/spec/importers/testData/nordpassCsv/nordpass.card.csv.ts @@ -0,0 +1,2 @@ +export const data = `name,url,username,password,note,cardholdername,cardnumber,cvc,expirydate,zipcode,folder,full_name,phone_number,email,address1,address2,city,country,state +SomeVisa,,,,,SomeHolder,4024007103939509,123,01 / 22,12345,,,,,,,,,`; diff --git a/libs/common/spec/importers/testData/nordpassCsv/nordpass.identity.csv.ts b/libs/common/spec/importers/testData/nordpassCsv/nordpass.identity.csv.ts new file mode 100644 index 0000000000..4dde389c72 --- /dev/null +++ b/libs/common/spec/importers/testData/nordpassCsv/nordpass.identity.csv.ts @@ -0,0 +1,2 @@ +export const data = `name,url,username,password,note,cardholdername,cardnumber,cvc,expirydate,zipcode,folder,full_name,phone_number,email,address1,address2,city,country,state +SomeTitle,,,,SomeNoteToMyIdentity,,,,,123456,,#fullName,123456789,hello@bitwarden.com,Test street 123,additional addressinfo,Cologne,Germany,North-Rhine-Westphalia`; diff --git a/libs/common/spec/importers/testData/nordpassCsv/nordpass.login.csv.ts b/libs/common/spec/importers/testData/nordpassCsv/nordpass.login.csv.ts new file mode 100644 index 0000000000..e2af76b0fb --- /dev/null +++ b/libs/common/spec/importers/testData/nordpassCsv/nordpass.login.csv.ts @@ -0,0 +1,2 @@ +export const data = `name,url,username,password,note,cardholdername,cardnumber,cvc,expirydate,zipcode,folder,full_name,phone_number,email,address1,address2,city,country,state +SomeVaultItemName,https://example.com,hello@bitwarden.com,someStrongPassword,Some note for the VaultItem,,,,,,SomeFolderForVaultItem,,,,,,,,`; diff --git a/libs/common/spec/importers/testData/nordpassCsv/nordpass.secureNote.csv.ts b/libs/common/spec/importers/testData/nordpassCsv/nordpass.secureNote.csv.ts new file mode 100644 index 0000000000..0e4dcb2ef8 --- /dev/null +++ b/libs/common/spec/importers/testData/nordpassCsv/nordpass.secureNote.csv.ts @@ -0,0 +1,3 @@ +export const data = `name,url,username,password,note,cardholdername,cardnumber,cvc,expirydate,zipcode,folder,full_name,phone_number,email,address1,address2,city,country,state +notesFolder,,,,,,,,,,,,,,,,,, +MySuperSecureNoteTitle,,,,MySuperSecureNote,,,,,,notesFolder,,,,,,,,`; diff --git a/libs/common/spec/importers/testData/onePassword1Pux/APICredentials.ts b/libs/common/spec/importers/testData/onePassword1Pux/APICredentials.ts new file mode 100644 index 0000000000..41b7533103 --- /dev/null +++ b/libs/common/spec/importers/testData/onePassword1Pux/APICredentials.ts @@ -0,0 +1,169 @@ +import { ExportData } from "jslib-common/importers/onepasswordImporters/types/onepassword1PuxImporterTypes"; + +export const APICredentialsData: ExportData = { + accounts: [ + { + attrs: { + accountName: "1Password Customer", + name: "1Password Customer", + avatar: "", + email: "username123123123@gmail.com", + uuid: "TRIZ3XV4JJFRXJ3BARILLTUA6E", + domain: "https://my.1password.com/", + }, + vaults: [ + { + attrs: { + uuid: "pqcgbqjxr4tng2hsqt5ffrgwju", + desc: "Just test entries", + avatar: "ke7i5rxnjrh3tj6uesstcosspu.png", + name: "T's Test Vault", + type: "U", + }, + items: [ + { + uuid: "6nqnjdqyk5mwvqbdgbdr47oabe", + favIndex: 0, + createdAt: 1619465969, + updatedAt: 1619466052, + trashed: false, + categoryUuid: "112", + details: { + loginFields: [], + notesPlain: "My API Credential", + sections: [ + { + title: "", + fields: [ + { + title: "username", + id: "username", + value: { + string: "apiuser@nullvalue.test", + }, + indexAtSource: 0, + guarded: true, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "no", + capitalization: "none", + }, + }, + { + title: "credential", + id: "credential", + value: { + concealed: "apiapiapiapiapiapiappy", + }, + indexAtSource: 1, + guarded: true, + multiline: false, + dontGenerate: true, + inputTraits: { + keyboard: "default", + correction: "no", + capitalization: "default", + }, + }, + { + title: "type", + id: "type", + value: { + menu: "jwt", + }, + indexAtSource: 2, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "filename", + id: "filename", + value: { + string: "filename.jwt", + }, + indexAtSource: 3, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "valid from", + id: "validFrom", + value: { + date: 1301918460, + }, + indexAtSource: 4, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "expires", + id: "expires", + value: { + date: 1932811260, + }, + indexAtSource: 5, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "hostname", + id: "hostname", + value: { + string: "not.your.everyday.hostname", + }, + indexAtSource: 6, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "uRL", + correction: "default", + capitalization: "default", + }, + }, + ], + }, + ], + passwordHistory: [], + }, + overview: { + subtitle: "", + title: "API Credential", + url: "", + ps: 0, + pbe: 0.0, + pgrng: false, + }, + }, + ], + }, + ], + }, + ], +}; diff --git a/libs/common/spec/importers/testData/onePassword1Pux/BankAccount.ts b/libs/common/spec/importers/testData/onePassword1Pux/BankAccount.ts new file mode 100644 index 0000000000..1ada271464 --- /dev/null +++ b/libs/common/spec/importers/testData/onePassword1Pux/BankAccount.ts @@ -0,0 +1,224 @@ +import { ExportData } from "jslib-common/importers/onepasswordImporters/types/onepassword1PuxImporterTypes"; + +export const BankAccountData: ExportData = { + accounts: [ + { + attrs: { + accountName: "1Password Customer", + name: "1Password Customer", + avatar: "", + email: "username123123123@gmail.com", + uuid: "TRIZ3XV4JJFRXJ3BARILLTUA6E", + domain: "https://my.1password.com/", + }, + vaults: [ + { + attrs: { + uuid: "pqcgbqjxr4tng2hsqt5ffrgwju", + desc: "Just test entries", + avatar: "ke7i5rxnjrh3tj6uesstcosspu.png", + name: "T's Test Vault", + type: "U", + }, + items: [ + { + uuid: "u2l4sjbencvsowwjuj3dfpt73q", + favIndex: 0, + createdAt: 1619466056, + updatedAt: 1619466187, + trashed: false, + categoryUuid: "101", + details: { + loginFields: [], + notesPlain: "My Bank Account", + sections: [ + { + title: "", + fields: [ + { + title: "bank name", + id: "bankName", + value: { + string: "Super Credit Union", + }, + indexAtSource: 0, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "words", + }, + }, + { + title: "name on account", + id: "owner", + value: { + string: "Cool Guy", + }, + indexAtSource: 1, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "words", + }, + }, + { + title: "type", + id: "accountType", + value: { + menu: "checking", + }, + indexAtSource: 2, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "routing number", + id: "routingNo", + value: { + string: "111000999", + }, + indexAtSource: 3, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numbersAndPunctuation", + correction: "default", + capitalization: "default", + }, + }, + { + title: "account number", + id: "accountNo", + value: { + string: "192837465918273645", + }, + indexAtSource: 4, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numbersAndPunctuation", + correction: "default", + capitalization: "default", + }, + }, + { + title: "SWIFT", + id: "swift", + value: { + string: "123456", + }, + indexAtSource: 5, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numbersAndPunctuation", + correction: "default", + capitalization: "default", + }, + }, + { + title: "IBAN", + id: "iban", + value: { + string: "DE12 123456", + }, + indexAtSource: 6, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numbersAndPunctuation", + correction: "default", + capitalization: "default", + }, + }, + { + title: "PIN", + id: "telephonePin", + value: { + concealed: "5555", + }, + indexAtSource: 7, + guarded: false, + multiline: false, + dontGenerate: true, + inputTraits: { + keyboard: "numberPad", + correction: "default", + capitalization: "default", + }, + }, + ], + }, + { + title: "Branch Information", + name: "branchInfo", + fields: [ + { + title: "phone", + id: "branchPhone", + value: { + phone: "9399399933", + }, + indexAtSource: 0, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "namePhonePad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "address", + id: "branchAddress", + value: { + string: "1 Fifth Avenue", + }, + indexAtSource: 1, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "sentences", + }, + }, + ], + }, + ], + passwordHistory: [], + }, + overview: { + subtitle: "Super Credit Union", + tags: ["Finance"], + title: "Bank Account", + url: "", + ps: 0, + pbe: 0.0, + pgrng: false, + }, + }, + ], + }, + ], + }, + ], +}; diff --git a/libs/common/spec/importers/testData/onePassword1Pux/CreditCard.ts b/libs/common/spec/importers/testData/onePassword1Pux/CreditCard.ts new file mode 100644 index 0000000000..ccdd4aa993 --- /dev/null +++ b/libs/common/spec/importers/testData/onePassword1Pux/CreditCard.ts @@ -0,0 +1,343 @@ +import { ExportData } from "jslib-common/importers/onepasswordImporters/types/onepassword1PuxImporterTypes"; + +export const CreditCardData: ExportData = { + accounts: [ + { + attrs: { + accountName: "1Password Customer", + name: "1Password Customer", + avatar: "", + email: "username123123123@gmail.com", + uuid: "TRIZ3XV4JJFRXJ3BARILLTUA6E", + domain: "https://my.1password.com/", + }, + vaults: [ + { + attrs: { + uuid: "pqcgbqjxr4tng2hsqt5ffrgwju", + desc: "Just test entries", + avatar: "ke7i5rxnjrh3tj6uesstcosspu.png", + name: "T's Test Vault", + type: "U", + }, + items: [ + { + uuid: "vpxi2esuujz7nrbojp34rd5aja", + favIndex: 0, + createdAt: 1619465282, + updatedAt: 1619465447, + trashed: false, + categoryUuid: "002", + details: { + loginFields: [], + notesPlain: "My parents' credit card. ", + sections: [ + { + title: "", + fields: [ + { + title: "cardholder name", + id: "cardholder", + value: { + string: "Fred Engels", + }, + indexAtSource: 0, + guarded: true, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "words", + }, + }, + { + title: "type", + id: "type", + value: { + creditCardType: "discover", + }, + indexAtSource: 1, + guarded: true, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "number", + id: "ccnum", + value: { + creditCardNumber: "6011111111111117", + }, + indexAtSource: 2, + guarded: true, + clipboardFilter: "0123456789", + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numberPad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "verification number", + id: "cvv", + value: { + concealed: "1312", + }, + indexAtSource: 3, + guarded: true, + multiline: false, + dontGenerate: true, + inputTraits: { + keyboard: "numberPad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "expiry date", + id: "expiry", + value: { + monthYear: 209912, + }, + indexAtSource: 4, + guarded: true, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "valid from", + id: "validFrom", + value: { + monthYear: 200101, + }, + indexAtSource: 5, + guarded: true, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "", + id: "txbzvwzpck7ejhfres3733rbpm", + value: { + string: "card", + }, + indexAtSource: 6, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + ], + }, + { + title: "Contact Information", + name: "contactInfo", + fields: [ + { + title: "issuing bank", + id: "bank", + value: { + string: "Some bank", + }, + indexAtSource: 0, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "words", + }, + }, + { + title: "phone (local)", + id: "phoneLocal", + value: { + phone: "123456", + }, + indexAtSource: 1, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "namePhonePad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "phone (toll free)", + id: "phoneTollFree", + value: { + phone: "0800123456", + }, + indexAtSource: 2, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "namePhonePad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "phone (intl)", + id: "phoneIntl", + value: { + phone: "+49123456", + }, + indexAtSource: 3, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "namePhonePad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "website", + id: "website", + value: { + url: "somebank.com", + }, + indexAtSource: 4, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + ], + }, + { + title: "Additional Details", + name: "details", + fields: [ + { + title: "PIN", + id: "pin", + value: { + concealed: "1234", + }, + indexAtSource: 0, + guarded: false, + multiline: false, + dontGenerate: true, + inputTraits: { + keyboard: "numberPad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "credit limit", + id: "creditLimit", + value: { + string: "$1312", + }, + indexAtSource: 1, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numbersAndPunctuation", + correction: "default", + capitalization: "default", + }, + }, + { + title: "cash withdrawal limit", + id: "cashLimit", + value: { + string: "$500", + }, + indexAtSource: 2, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numbersAndPunctuation", + correction: "default", + capitalization: "default", + }, + }, + { + title: "interest rate", + id: "interest", + value: { + string: "1%", + }, + indexAtSource: 3, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numbersAndPunctuation", + correction: "default", + capitalization: "default", + }, + }, + { + title: "issue number", + id: "issuenumber", + value: { + string: "123456", + }, + indexAtSource: 4, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "no", + capitalization: "default", + }, + }, + ], + }, + ], + passwordHistory: [], + }, + overview: { + subtitle: "1234 **** 6789", + tags: ["Finance"], + title: "Parent's Credit Card", + url: "", + ps: 0, + pbe: 0.0, + pgrng: false, + }, + }, + ], + }, + ], + }, + ], +}; diff --git a/libs/common/spec/importers/testData/onePassword1Pux/Database.ts b/libs/common/spec/importers/testData/onePassword1Pux/Database.ts new file mode 100644 index 0000000000..594f53847c --- /dev/null +++ b/libs/common/spec/importers/testData/onePassword1Pux/Database.ts @@ -0,0 +1,201 @@ +import { ExportData } from "jslib-common/importers/onepasswordImporters/types/onepassword1PuxImporterTypes"; + +export const DatabaseData: ExportData = { + accounts: [ + { + attrs: { + accountName: "1Password Customer", + name: "1Password Customer", + avatar: "", + email: "username123123123@gmail.com", + uuid: "TRIZ3XV4JJFRXJ3BARILLTUA6E", + domain: "https://my.1password.com/", + }, + vaults: [ + { + attrs: { + uuid: "pqcgbqjxr4tng2hsqt5ffrgwju", + desc: "Just test entries", + avatar: "ke7i5rxnjrh3tj6uesstcosspu.png", + name: "T's Test Vault", + type: "U", + }, + items: [ + { + uuid: "ospvepl3ex2y6hjwwqwyvtf2sy", + favIndex: 0, + createdAt: 1619466193, + updatedAt: 1619466276, + trashed: false, + categoryUuid: "102", + details: { + loginFields: [], + notesPlain: "My Database", + sections: [ + { + title: "", + fields: [ + { + title: "type", + id: "database_type", + value: { + menu: "postgresql", + }, + indexAtSource: 0, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "server", + id: "hostname", + value: { + string: "my.secret.db.server", + }, + indexAtSource: 1, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "uRL", + correction: "default", + capitalization: "default", + }, + }, + { + title: "port", + id: "port", + value: { + string: "1337", + }, + indexAtSource: 2, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numberPad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "database", + id: "database", + value: { + string: "user_database", + }, + indexAtSource: 3, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "no", + capitalization: "none", + }, + }, + { + title: "username", + id: "username", + value: { + string: "cooldbuser", + }, + indexAtSource: 4, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "no", + capitalization: "none", + }, + }, + { + title: "password", + id: "password", + value: { + concealed: "^+kTjhLaN7wVPAhGU)*J", + }, + indexAtSource: 5, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "SID", + id: "sid", + value: { + string: "ASDIUFU-283234", + }, + indexAtSource: 6, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "alias", + id: "alias", + value: { + string: "cdbu", + }, + indexAtSource: 7, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "connection options", + id: "options", + value: { + string: "ssh", + }, + indexAtSource: 8, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + ], + }, + ], + passwordHistory: [], + }, + overview: { + subtitle: "my.secret.db.server", + title: "Database", + url: "", + ps: 0, + pbe: 0.0, + pgrng: false, + }, + }, + ], + }, + ], + }, + ], +}; diff --git a/libs/common/spec/importers/testData/onePassword1Pux/DriversLicense.ts b/libs/common/spec/importers/testData/onePassword1Pux/DriversLicense.ts new file mode 100644 index 0000000000..468069aeb6 --- /dev/null +++ b/libs/common/spec/importers/testData/onePassword1Pux/DriversLicense.ts @@ -0,0 +1,233 @@ +import { ExportData } from "jslib-common/importers/onepasswordImporters/types/onepassword1PuxImporterTypes"; + +export const DriversLicenseData: ExportData = { + accounts: [ + { + attrs: { + accountName: "1Password Customer", + name: "1Password Customer", + avatar: "", + email: "username123123123@gmail.com", + uuid: "TRIZ3XV4JJFRXJ3BARILLTUA6E", + domain: "https://my.1password.com/", + }, + vaults: [ + { + attrs: { + uuid: "pqcgbqjxr4tng2hsqt5ffrgwju", + desc: "Just test entries", + avatar: "ke7i5rxnjrh3tj6uesstcosspu.png", + name: "T's Test Vault", + type: "U", + }, + items: [ + { + uuid: "nntuge2g7s2wrlokyfhea354ay", + favIndex: 0, + createdAt: 1619466279, + updatedAt: 1619466425, + trashed: false, + categoryUuid: "103", + details: { + loginFields: [], + notesPlain: "My Driver's License", + sections: [ + { + title: "", + fields: [ + { + title: "full name", + id: "fullname", + value: { + string: "Michael Scarn", + }, + indexAtSource: 0, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "words", + }, + }, + { + title: "address", + id: "address", + value: { + string: "2120 Mifflin Rd.", + }, + indexAtSource: 1, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "sentences", + }, + }, + { + title: "date of birth", + id: "birthdate", + value: { + date: 252504060, + }, + indexAtSource: 2, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "sex", + id: "sex", + value: { + gender: "male", + }, + indexAtSource: 3, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "height", + id: "height", + value: { + string: "5'11\"", + }, + indexAtSource: 4, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "number", + id: "number", + value: { + string: "12345678901", + }, + indexAtSource: 5, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "license class", + id: "class", + value: { + string: "C", + }, + indexAtSource: 6, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "conditions / restrictions", + id: "conditions", + value: { + string: "B", + }, + indexAtSource: 7, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "state", + id: "state", + value: { + string: "Pennsylvania", + }, + indexAtSource: 8, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "country", + id: "country", + value: { + string: "United States", + }, + indexAtSource: 9, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "expiry date", + id: "expiry_date", + value: { + monthYear: 203012, + }, + indexAtSource: 10, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + ], + }, + ], + passwordHistory: [], + }, + overview: { + subtitle: "12345678901", + title: "Michael Scarn", + url: "", + ps: 0, + pbe: 0.0, + pgrng: false, + }, + }, + ], + }, + ], + }, + ], +}; diff --git a/libs/common/spec/importers/testData/onePassword1Pux/EmailAccount.ts b/libs/common/spec/importers/testData/onePassword1Pux/EmailAccount.ts new file mode 100644 index 0000000000..1f83a6d89e --- /dev/null +++ b/libs/common/spec/importers/testData/onePassword1Pux/EmailAccount.ts @@ -0,0 +1,341 @@ +import { ExportData } from "jslib-common/importers/onepasswordImporters/types/onepassword1PuxImporterTypes"; + +export const EmailAccountData: ExportData = { + accounts: [ + { + attrs: { + accountName: "1Password Customer", + name: "1Password Customer", + avatar: "", + email: "username123123123@gmail.com", + uuid: "TRIZ3XV4JJFRXJ3BARILLTUA6E", + domain: "https://my.1password.com/", + }, + vaults: [ + { + attrs: { + uuid: "pqcgbqjxr4tng2hsqt5ffrgwju", + desc: "Just test entries", + avatar: "ke7i5rxnjrh3tj6uesstcosspu.png", + name: "T's Test Vault", + type: "U", + }, + items: [ + { + uuid: "p3hohdgwpt4u2ra2fc3tvzomsm", + favIndex: 0, + createdAt: 1619466428, + updatedAt: 1619466585, + trashed: false, + categoryUuid: "111", + details: { + loginFields: [], + notesPlain: "My Email Config", + sections: [ + { + title: "", + fields: [ + { + title: "type", + id: "pop_type", + value: { + menu: "either", + }, + indexAtSource: 0, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "default", + capitalization: "default", + }, + }, + { + title: "username", + id: "pop_username", + value: { + string: "someuser@nullvalue.test", + }, + indexAtSource: 1, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "default", + correction: "no", + capitalization: "none", + }, + }, + { + title: "server", + id: "pop_server", + value: { + string: "mailserver.nullvalue.test", + }, + indexAtSource: 2, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "uRL", + correction: "default", + capitalization: "default", + }, + }, + { + title: "port number", + id: "pop_port", + value: { + string: "587", + }, + indexAtSource: 3, + guarded: false, + multiline: false, + dontGenerate: false, + inputTraits: { + keyboard: "numberPad", + correction: "default", + capitalization: "default", + }, + }, + { + title: "password", + id: "pop_password", + value: { + concealed: "u1jsf + + + + + + + + + + + + This is a sample note. + 3 + + + + 5555123456789000 + John Smith + 01/23 + 555 + 1111 + 555-0153 + 1 + + + john555@gmail.com + early91*Fail* + https://www.facebook.com + 3 + + + john555@gmail.com + plain79{Area{ + https://www.google.com + 3 + thisisanotp + thisshouldbehidden + + + 555111111 + John Smith + 05/05/1980 + 01/01/2018 + 01/01/2028 + 3 + This is a note attached to a card + + + john555@gmail.com + https://twitter.com + 3 + shouldbepassword + + + john555 + Save63\apple\ + 3 + + +`; diff --git a/libs/common/spec/misc/logInStrategies/apiLogIn.strategy.spec.ts b/libs/common/spec/misc/logInStrategies/apiLogIn.strategy.spec.ts new file mode 100644 index 0000000000..2f4fe6c31d --- /dev/null +++ b/libs/common/spec/misc/logInStrategies/apiLogIn.strategy.spec.ts @@ -0,0 +1,114 @@ +import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { ApiLogInStrategy } from "jslib-common/misc/logInStrategies/apiLogin.strategy"; +import { Utils } from "jslib-common/misc/utils"; +import { ApiLogInCredentials } from "jslib-common/models/domain/logInCredentials"; + +import { identityTokenResponseFactory } from "./logIn.strategy.spec"; + +describe("ApiLogInStrategy", () => { + let cryptoService: SubstituteOf; + let apiService: SubstituteOf; + let tokenService: SubstituteOf; + let appIdService: SubstituteOf; + let platformUtilsService: SubstituteOf; + let messagingService: SubstituteOf; + let logService: SubstituteOf; + let environmentService: SubstituteOf; + let keyConnectorService: SubstituteOf; + let stateService: SubstituteOf; + let twoFactorService: SubstituteOf; + + let apiLogInStrategy: ApiLogInStrategy; + let credentials: ApiLogInCredentials; + + const deviceId = Utils.newGuid(); + const keyConnectorUrl = "KEY_CONNECTOR_URL"; + const apiClientId = "API_CLIENT_ID"; + const apiClientSecret = "API_CLIENT_SECRET"; + + beforeEach(async () => { + cryptoService = Substitute.for(); + apiService = Substitute.for(); + tokenService = Substitute.for(); + appIdService = Substitute.for(); + platformUtilsService = Substitute.for(); + messagingService = Substitute.for(); + logService = Substitute.for(); + environmentService = Substitute.for(); + stateService = Substitute.for(); + keyConnectorService = Substitute.for(); + twoFactorService = Substitute.for(); + + appIdService.getAppId().resolves(deviceId); + tokenService.getTwoFactorToken().resolves(null); + + apiLogInStrategy = new ApiLogInStrategy( + cryptoService, + apiService, + tokenService, + appIdService, + platformUtilsService, + messagingService, + logService, + stateService, + twoFactorService, + environmentService, + keyConnectorService + ); + + credentials = new ApiLogInCredentials(apiClientId, apiClientSecret); + }); + + it("sends api key credentials to the server", async () => { + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + await apiLogInStrategy.logIn(credentials); + + apiService.received(1).postIdentityToken( + Arg.is((actual) => { + const apiTokenRequest = actual as any; + return ( + apiTokenRequest.clientId === apiClientId && + apiTokenRequest.clientSecret === apiClientSecret && + apiTokenRequest.device.identifier === deviceId && + apiTokenRequest.twoFactor.provider == null && + apiTokenRequest.twoFactor.token == null && + apiTokenRequest.captchaResponse == null + ); + }) + ); + }); + + it("sets the local environment after a successful login", async () => { + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + + await apiLogInStrategy.logIn(credentials); + + stateService.received(1).setApiKeyClientId(apiClientId); + stateService.received(1).setApiKeyClientSecret(apiClientSecret); + stateService.received(1).addAccount(Arg.any()); + }); + + it("gets and sets the Key Connector key from environmentUrl", async () => { + const tokenResponse = identityTokenResponseFactory(); + tokenResponse.apiUseKeyConnector = true; + + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + environmentService.getKeyConnectorUrl().returns(keyConnectorUrl); + + await apiLogInStrategy.logIn(credentials); + + keyConnectorService.received(1).getAndSetKey(keyConnectorUrl); + }); +}); diff --git a/libs/common/spec/misc/logInStrategies/logIn.strategy.spec.ts b/libs/common/spec/misc/logInStrategies/logIn.strategy.spec.ts new file mode 100644 index 0000000000..5f68881bad --- /dev/null +++ b/libs/common/spec/misc/logInStrategies/logIn.strategy.spec.ts @@ -0,0 +1,288 @@ +import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType"; +import { PasswordLogInStrategy } from "jslib-common/misc/logInStrategies/passwordLogin.strategy"; +import { Utils } from "jslib-common/misc/utils"; +import { Account, AccountProfile, AccountTokens } from "jslib-common/models/domain/account"; +import { AuthResult } from "jslib-common/models/domain/authResult"; +import { EncString } from "jslib-common/models/domain/encString"; +import { PasswordLogInCredentials } from "jslib-common/models/domain/logInCredentials"; +import { PasswordTokenRequest } from "jslib-common/models/request/identityToken/passwordTokenRequest"; +import { TokenRequestTwoFactor } from "jslib-common/models/request/identityToken/tokenRequestTwoFactor"; +import { IdentityCaptchaResponse } from "jslib-common/models/response/identityCaptchaResponse"; +import { IdentityTokenResponse } from "jslib-common/models/response/identityTokenResponse"; +import { IdentityTwoFactorResponse } from "jslib-common/models/response/identityTwoFactorResponse"; + +const email = "hello@world.com"; +const masterPassword = "password"; + +const deviceId = Utils.newGuid(); +const accessToken = "ACCESS_TOKEN"; +const refreshToken = "REFRESH_TOKEN"; +const encKey = "ENC_KEY"; +const privateKey = "PRIVATE_KEY"; +const captchaSiteKey = "CAPTCHA_SITE_KEY"; +const kdf = 0; +const kdfIterations = 10000; +const userId = Utils.newGuid(); +const masterPasswordHash = "MASTER_PASSWORD_HASH"; + +const decodedToken = { + sub: userId, + email: email, + premium: false, +}; + +const twoFactorProviderType = TwoFactorProviderType.Authenticator; +const twoFactorToken = "TWO_FACTOR_TOKEN"; +const twoFactorRemember = true; + +export function identityTokenResponseFactory() { + return new IdentityTokenResponse({ + ForcePasswordReset: false, + Kdf: kdf, + KdfIterations: kdfIterations, + Key: encKey, + PrivateKey: privateKey, + ResetMasterPassword: false, + access_token: accessToken, + expires_in: 3600, + refresh_token: refreshToken, + scope: "api offline_access", + token_type: "Bearer", + }); +} + +describe("LogInStrategy", () => { + let cryptoService: SubstituteOf; + let apiService: SubstituteOf; + let tokenService: SubstituteOf; + let appIdService: SubstituteOf; + let platformUtilsService: SubstituteOf; + let messagingService: SubstituteOf; + let logService: SubstituteOf; + let stateService: SubstituteOf; + let twoFactorService: SubstituteOf; + let authService: SubstituteOf; + + let passwordLogInStrategy: PasswordLogInStrategy; + let credentials: PasswordLogInCredentials; + + beforeEach(async () => { + cryptoService = Substitute.for(); + apiService = Substitute.for(); + tokenService = Substitute.for(); + appIdService = Substitute.for(); + platformUtilsService = Substitute.for(); + messagingService = Substitute.for(); + logService = Substitute.for(); + stateService = Substitute.for(); + twoFactorService = Substitute.for(); + authService = Substitute.for(); + + appIdService.getAppId().resolves(deviceId); + + // The base class is abstract so we test it via PasswordLogInStrategy + passwordLogInStrategy = new PasswordLogInStrategy( + cryptoService, + apiService, + tokenService, + appIdService, + platformUtilsService, + messagingService, + logService, + stateService, + twoFactorService, + authService + ); + credentials = new PasswordLogInCredentials(email, masterPassword); + }); + + describe("base class", () => { + it("sets the local environment after a successful login", async () => { + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + tokenService.decodeToken(accessToken).resolves(decodedToken); + + await passwordLogInStrategy.logIn(credentials); + + stateService.received(1).addAccount( + new Account({ + profile: { + ...new AccountProfile(), + ...{ + userId: userId, + email: email, + hasPremiumPersonally: false, + kdfIterations: kdfIterations, + kdfType: kdf, + }, + }, + tokens: { + ...new AccountTokens(), + ...{ + accessToken: accessToken, + refreshToken: refreshToken, + }, + }, + }) + ); + cryptoService.received(1).setEncKey(encKey); + cryptoService.received(1).setEncPrivateKey(privateKey); + + stateService.received(1).setBiometricLocked(false); + messagingService.received(1).send("loggedIn"); + }); + + it("builds AuthResult", async () => { + const tokenResponse = identityTokenResponseFactory(); + tokenResponse.forcePasswordReset = true; + tokenResponse.resetMasterPassword = true; + + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + + const result = await passwordLogInStrategy.logIn(credentials); + + const expected = new AuthResult(); + expected.forcePasswordReset = true; + expected.resetMasterPassword = true; + expected.twoFactorProviders = null; + expected.captchaSiteKey = ""; + expect(result).toEqual(expected); + }); + + it("rejects login if CAPTCHA is required", async () => { + // Sample CAPTCHA response + const tokenResponse = new IdentityCaptchaResponse({ + error: "invalid_grant", + error_description: "Captcha required.", + HCaptcha_SiteKey: captchaSiteKey, + }); + + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + + const result = await passwordLogInStrategy.logIn(credentials); + + stateService.didNotReceive().addAccount(Arg.any()); + messagingService.didNotReceive().send(Arg.any()); + + const expected = new AuthResult(); + expected.captchaSiteKey = captchaSiteKey; + expect(result).toEqual(expected); + }); + + it("makes a new public and private key for an old account", async () => { + const tokenResponse = identityTokenResponseFactory(); + tokenResponse.privateKey = null; + cryptoService.makeKeyPair(Arg.any()).resolves(["PUBLIC_KEY", new EncString("PRIVATE_KEY")]); + + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + + await passwordLogInStrategy.logIn(credentials); + + apiService.received(1).postAccountKeys(Arg.any()); + }); + }); + + describe("Two-factor authentication", () => { + it("rejects login if 2FA is required", async () => { + // Sample response where TOTP 2FA required + const tokenResponse = new IdentityTwoFactorResponse({ + TwoFactorProviders: ["0"], + TwoFactorProviders2: { 0: null }, + error: "invalid_grant", + error_description: "Two factor required.", + }); + + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + + const result = await passwordLogInStrategy.logIn(credentials); + + stateService.didNotReceive().addAccount(Arg.any()); + messagingService.didNotReceive().send(Arg.any()); + + const expected = new AuthResult(); + expected.twoFactorProviders = new Map(); + expected.twoFactorProviders.set(0, null); + expect(result).toEqual(expected); + }); + + it("sends stored 2FA token to server", async () => { + tokenService.getTwoFactorToken().resolves(twoFactorToken); + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + + await passwordLogInStrategy.logIn(credentials); + + apiService.received(1).postIdentityToken( + Arg.is((actual) => { + const passwordTokenRequest = actual as any; + return ( + passwordTokenRequest.twoFactor.provider === TwoFactorProviderType.Remember && + passwordTokenRequest.twoFactor.token === twoFactorToken && + passwordTokenRequest.twoFactor.remember === false + ); + }) + ); + }); + + it("sends 2FA token provided by user to server (single step)", async () => { + // This occurs if the user enters the 2FA code as an argument in the CLI + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + credentials.twoFactor = new TokenRequestTwoFactor( + twoFactorProviderType, + twoFactorToken, + twoFactorRemember + ); + + await passwordLogInStrategy.logIn(credentials); + + apiService.received(1).postIdentityToken( + Arg.is((actual) => { + const passwordTokenRequest = actual as any; + return ( + passwordTokenRequest.twoFactor.provider === twoFactorProviderType && + passwordTokenRequest.twoFactor.token === twoFactorToken && + passwordTokenRequest.twoFactor.remember === twoFactorRemember + ); + }) + ); + }); + + it("sends 2FA token provided by user to server (two-step)", async () => { + // Simulate a partially completed login + passwordLogInStrategy.tokenRequest = new PasswordTokenRequest( + email, + masterPasswordHash, + null, + null + ); + + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + + await passwordLogInStrategy.logInTwoFactor( + new TokenRequestTwoFactor(twoFactorProviderType, twoFactorToken, twoFactorRemember), + null + ); + + apiService.received(1).postIdentityToken( + Arg.is((actual) => { + const passwordTokenRequest = actual as any; + return ( + passwordTokenRequest.twoFactor.provider === twoFactorProviderType && + passwordTokenRequest.twoFactor.token === twoFactorToken && + passwordTokenRequest.twoFactor.remember === twoFactorRemember + ); + }) + ); + }); + }); +}); diff --git a/libs/common/spec/misc/logInStrategies/passwordLogIn.strategy.spec.ts b/libs/common/spec/misc/logInStrategies/passwordLogIn.strategy.spec.ts new file mode 100644 index 0000000000..65bf536712 --- /dev/null +++ b/libs/common/spec/misc/logInStrategies/passwordLogIn.strategy.spec.ts @@ -0,0 +1,110 @@ +import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { HashPurpose } from "jslib-common/enums/hashPurpose"; +import { PasswordLogInStrategy } from "jslib-common/misc/logInStrategies/passwordLogin.strategy"; +import { Utils } from "jslib-common/misc/utils"; +import { PasswordLogInCredentials } from "jslib-common/models/domain/logInCredentials"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; + +import { identityTokenResponseFactory } from "./logIn.strategy.spec"; + +const email = "hello@world.com"; +const masterPassword = "password"; +const hashedPassword = "HASHED_PASSWORD"; +const localHashedPassword = "LOCAL_HASHED_PASSWORD"; +const preloginKey = new SymmetricCryptoKey( + Utils.fromB64ToArray( + "N2KWjlLpfi5uHjv+YcfUKIpZ1l+W+6HRensmIqD+BFYBf6N/dvFpJfWwYnVBdgFCK2tJTAIMLhqzIQQEUmGFgg==" + ) +); +const deviceId = Utils.newGuid(); + +describe("PasswordLogInStrategy", () => { + let cryptoService: SubstituteOf; + let apiService: SubstituteOf; + let tokenService: SubstituteOf; + let appIdService: SubstituteOf; + let platformUtilsService: SubstituteOf; + let messagingService: SubstituteOf; + let logService: SubstituteOf; + let stateService: SubstituteOf; + let twoFactorService: SubstituteOf; + let authService: SubstituteOf; + + let passwordLogInStrategy: PasswordLogInStrategy; + let credentials: PasswordLogInCredentials; + + beforeEach(async () => { + cryptoService = Substitute.for(); + apiService = Substitute.for(); + tokenService = Substitute.for(); + appIdService = Substitute.for(); + platformUtilsService = Substitute.for(); + messagingService = Substitute.for(); + logService = Substitute.for(); + stateService = Substitute.for(); + twoFactorService = Substitute.for(); + authService = Substitute.for(); + + appIdService.getAppId().resolves(deviceId); + tokenService.getTwoFactorToken().resolves(null); + + authService.makePreloginKey(Arg.any(), Arg.any()).resolves(preloginKey); + + cryptoService.hashPassword(masterPassword, Arg.any()).resolves(hashedPassword); + cryptoService + .hashPassword(masterPassword, Arg.any(), HashPurpose.LocalAuthorization) + .resolves(localHashedPassword); + + passwordLogInStrategy = new PasswordLogInStrategy( + cryptoService, + apiService, + tokenService, + appIdService, + platformUtilsService, + messagingService, + logService, + stateService, + twoFactorService, + authService + ); + credentials = new PasswordLogInCredentials(email, masterPassword); + + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + }); + + it("sends master password credentials to the server", async () => { + await passwordLogInStrategy.logIn(credentials); + + apiService.received(1).postIdentityToken( + Arg.is((actual) => { + const passwordTokenRequest = actual as any; // Need to access private fields + return ( + passwordTokenRequest.email === email && + passwordTokenRequest.masterPasswordHash === hashedPassword && + passwordTokenRequest.device.identifier === deviceId && + passwordTokenRequest.twoFactor.provider == null && + passwordTokenRequest.twoFactor.token == null && + passwordTokenRequest.captchaResponse == null + ); + }) + ); + }); + + it("sets the local environment after a successful login", async () => { + await passwordLogInStrategy.logIn(credentials); + + cryptoService.received(1).setKey(preloginKey); + cryptoService.received(1).setKeyHash(localHashedPassword); + }); +}); diff --git a/libs/common/spec/misc/logInStrategies/ssoLogIn.strategy.spec.ts b/libs/common/spec/misc/logInStrategies/ssoLogIn.strategy.spec.ts new file mode 100644 index 0000000000..826a16a508 --- /dev/null +++ b/libs/common/spec/misc/logInStrategies/ssoLogIn.strategy.spec.ts @@ -0,0 +1,127 @@ +import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { SsoLogInStrategy } from "jslib-common/misc/logInStrategies/ssoLogin.strategy"; +import { Utils } from "jslib-common/misc/utils"; +import { SsoLogInCredentials } from "jslib-common/models/domain/logInCredentials"; + +import { identityTokenResponseFactory } from "./logIn.strategy.spec"; + +describe("SsoLogInStrategy", () => { + let cryptoService: SubstituteOf; + let apiService: SubstituteOf; + let tokenService: SubstituteOf; + let appIdService: SubstituteOf; + let platformUtilsService: SubstituteOf; + let messagingService: SubstituteOf; + let logService: SubstituteOf; + let keyConnectorService: SubstituteOf; + let stateService: SubstituteOf; + let twoFactorService: SubstituteOf; + + let ssoLogInStrategy: SsoLogInStrategy; + let credentials: SsoLogInCredentials; + + const deviceId = Utils.newGuid(); + const encKey = "ENC_KEY"; + const privateKey = "PRIVATE_KEY"; + const keyConnectorUrl = "KEY_CONNECTOR_URL"; + + const ssoCode = "SSO_CODE"; + const ssoCodeVerifier = "SSO_CODE_VERIFIER"; + const ssoRedirectUrl = "SSO_REDIRECT_URL"; + const ssoOrgId = "SSO_ORG_ID"; + + beforeEach(async () => { + cryptoService = Substitute.for(); + apiService = Substitute.for(); + tokenService = Substitute.for(); + appIdService = Substitute.for(); + platformUtilsService = Substitute.for(); + messagingService = Substitute.for(); + logService = Substitute.for(); + stateService = Substitute.for(); + keyConnectorService = Substitute.for(); + twoFactorService = Substitute.for(); + + tokenService.getTwoFactorToken().resolves(null); + appIdService.getAppId().resolves(deviceId); + + ssoLogInStrategy = new SsoLogInStrategy( + cryptoService, + apiService, + tokenService, + appIdService, + platformUtilsService, + messagingService, + logService, + stateService, + twoFactorService, + keyConnectorService + ); + credentials = new SsoLogInCredentials(ssoCode, ssoCodeVerifier, ssoRedirectUrl, ssoOrgId); + }); + + it("sends SSO information to server", async () => { + apiService.postIdentityToken(Arg.any()).resolves(identityTokenResponseFactory()); + + await ssoLogInStrategy.logIn(credentials); + + apiService.received(1).postIdentityToken( + Arg.is((actual) => { + const ssoTokenRequest = actual as any; + return ( + ssoTokenRequest.code === ssoCode && + ssoTokenRequest.codeVerifier === ssoCodeVerifier && + ssoTokenRequest.redirectUri === ssoRedirectUrl && + ssoTokenRequest.device.identifier === deviceId && + ssoTokenRequest.twoFactor.provider == null && + ssoTokenRequest.twoFactor.token == null + ); + }) + ); + }); + + it("does not set keys for new SSO user flow", async () => { + const tokenResponse = identityTokenResponseFactory(); + tokenResponse.key = null; + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + + await ssoLogInStrategy.logIn(credentials); + + cryptoService.didNotReceive().setEncPrivateKey(privateKey); + cryptoService.didNotReceive().setEncKey(encKey); + }); + + it("gets and sets KeyConnector key for enrolled user", async () => { + const tokenResponse = identityTokenResponseFactory(); + tokenResponse.keyConnectorUrl = keyConnectorUrl; + + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + + await ssoLogInStrategy.logIn(credentials); + + keyConnectorService.received(1).getAndSetKey(keyConnectorUrl); + }); + + it("converts new SSO user to Key Connector on first login", async () => { + const tokenResponse = identityTokenResponseFactory(); + tokenResponse.keyConnectorUrl = keyConnectorUrl; + tokenResponse.key = null; + + apiService.postIdentityToken(Arg.any()).resolves(tokenResponse); + + await ssoLogInStrategy.logIn(credentials); + + keyConnectorService.received(1).convertNewSsoUserToKeyConnector(tokenResponse, ssoOrgId); + }); +}); diff --git a/libs/common/spec/misc/sequentialize.spec.ts b/libs/common/spec/misc/sequentialize.spec.ts new file mode 100644 index 0000000000..4165eca2c1 --- /dev/null +++ b/libs/common/spec/misc/sequentialize.spec.ts @@ -0,0 +1,127 @@ +import { sequentialize } from "jslib-common/misc/sequentialize"; + +describe("sequentialize decorator", () => { + it("should call the function once", async () => { + const foo = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.bar(1)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(1); + }); + + it("should call the function once for each instance of the object", async () => { + const foo = new Foo(); + const foo2 = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.bar(1)); + promises.push(foo2.bar(1)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(1); + expect(foo2.calls).toBe(1); + }); + + it("should call the function once with key function", async () => { + const foo = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.baz(1)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(1); + }); + + it("should call the function again when already resolved", async () => { + const foo = new Foo(); + await foo.bar(1); + expect(foo.calls).toBe(1); + await foo.bar(1); + expect(foo.calls).toBe(2); + }); + + it("should call the function again when already resolved with a key function", async () => { + const foo = new Foo(); + await foo.baz(1); + expect(foo.calls).toBe(1); + await foo.baz(1); + expect(foo.calls).toBe(2); + }); + + it("should call the function for each argument", async () => { + const foo = new Foo(); + await Promise.all([foo.bar(1), foo.bar(1), foo.bar(2), foo.bar(2), foo.bar(3), foo.bar(3)]); + expect(foo.calls).toBe(3); + }); + + it("should call the function for each argument with key function", async () => { + const foo = new Foo(); + await Promise.all([foo.baz(1), foo.baz(1), foo.baz(2), foo.baz(2), foo.baz(3), foo.baz(3)]); + expect(foo.calls).toBe(3); + }); + + it("should return correct result for each call", async () => { + const foo = new Foo(); + const allRes: number[] = []; + + await Promise.all([ + foo.bar(1).then((res) => allRes.push(res)), + foo.bar(1).then((res) => allRes.push(res)), + foo.bar(2).then((res) => allRes.push(res)), + foo.bar(2).then((res) => allRes.push(res)), + foo.bar(3).then((res) => allRes.push(res)), + foo.bar(3).then((res) => allRes.push(res)), + ]); + expect(foo.calls).toBe(3); + expect(allRes.length).toBe(6); + allRes.sort(); + expect(allRes).toEqual([2, 2, 4, 4, 6, 6]); + }); + + it("should return correct result for each call with key function", async () => { + const foo = new Foo(); + const allRes: number[] = []; + + await Promise.all([ + foo.baz(1).then((res) => allRes.push(res)), + foo.baz(1).then((res) => allRes.push(res)), + foo.baz(2).then((res) => allRes.push(res)), + foo.baz(2).then((res) => allRes.push(res)), + foo.baz(3).then((res) => allRes.push(res)), + foo.baz(3).then((res) => allRes.push(res)), + ]); + expect(foo.calls).toBe(3); + expect(allRes.length).toBe(6); + allRes.sort(); + expect(allRes).toEqual([3, 3, 6, 6, 9, 9]); + }); +}); + +class Foo { + calls = 0; + + @sequentialize((args) => "bar" + args[0]) + bar(a: number): Promise { + this.calls++; + return new Promise((res) => { + setTimeout(() => { + res(a * 2); + }, Math.random() * 100); + }); + } + + @sequentialize((args) => "baz" + args[0]) + baz(a: number): Promise { + this.calls++; + return new Promise((res) => { + setTimeout(() => { + res(a * 3); + }, Math.random() * 100); + }); + } +} diff --git a/libs/common/spec/misc/throttle.spec.ts b/libs/common/spec/misc/throttle.spec.ts new file mode 100644 index 0000000000..5a8cd27ed3 --- /dev/null +++ b/libs/common/spec/misc/throttle.spec.ts @@ -0,0 +1,110 @@ +import { sequentialize } from "jslib-common/misc/sequentialize"; +import { throttle } from "jslib-common/misc/throttle"; + +describe("throttle decorator", () => { + it("should call the function once at a time", async () => { + const foo = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.bar(1)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(10); + }); + + it("should call the function once at a time for each object", async () => { + const foo = new Foo(); + const foo2 = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.bar(1)); + promises.push(foo2.bar(1)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(10); + expect(foo2.calls).toBe(10); + }); + + it("should call the function limit at a time", async () => { + const foo = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.baz(1)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(10); + }); + + it("should call the function limit at a time for each object", async () => { + const foo = new Foo(); + const foo2 = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.baz(1)); + promises.push(foo2.baz(1)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(10); + expect(foo2.calls).toBe(10); + }); + + it("should work together with sequentialize", async () => { + const foo = new Foo(); + const promises = []; + for (let i = 0; i < 10; i++) { + promises.push(foo.qux(Math.floor(i / 2) * 2)); + } + await Promise.all(promises); + + expect(foo.calls).toBe(5); + }); +}); + +class Foo { + calls = 0; + inflight = 0; + + @throttle(1, () => "bar") + bar(a: number) { + this.calls++; + this.inflight++; + return new Promise((res) => { + setTimeout(() => { + expect(this.inflight).toBe(1); + this.inflight--; + res(a * 2); + }, Math.random() * 10); + }); + } + + @throttle(5, () => "baz") + baz(a: number) { + this.calls++; + this.inflight++; + return new Promise((res) => { + setTimeout(() => { + expect(this.inflight).toBeLessThanOrEqual(5); + this.inflight--; + res(a * 3); + }, Math.random() * 10); + }); + } + + @sequentialize((args) => "qux" + args[0]) + @throttle(1, () => "qux") + qux(a: number) { + this.calls++; + this.inflight++; + return new Promise((res) => { + setTimeout(() => { + expect(this.inflight).toBe(1); + this.inflight--; + res(a * 3); + }, Math.random() * 10); + }); + } +} diff --git a/libs/common/spec/misc/utils.spec.ts b/libs/common/spec/misc/utils.spec.ts new file mode 100644 index 0000000000..eec41e4bb4 --- /dev/null +++ b/libs/common/spec/misc/utils.spec.ts @@ -0,0 +1,73 @@ +import { Utils } from "jslib-common/misc/utils"; + +describe("Utils Service", () => { + describe("getDomain", () => { + it("should fail for invalid urls", () => { + expect(Utils.getDomain(null)).toBeNull(); + expect(Utils.getDomain(undefined)).toBeNull(); + expect(Utils.getDomain(" ")).toBeNull(); + expect(Utils.getDomain('https://bit!:"_&ward.com')).toBeNull(); + expect(Utils.getDomain("bitwarden")).toBeNull(); + }); + + it("should fail for data urls", () => { + expect(Utils.getDomain("data:image/jpeg;base64,AAA")).toBeNull(); + }); + + it("should handle urls without protocol", () => { + expect(Utils.getDomain("bitwarden.com")).toBe("bitwarden.com"); + expect(Utils.getDomain("wrong://bitwarden.com")).toBe("bitwarden.com"); + }); + + it("should handle valid urls", () => { + expect(Utils.getDomain("https://bitwarden")).toBe("bitwarden"); + expect(Utils.getDomain("https://bitwarden.com")).toBe("bitwarden.com"); + expect(Utils.getDomain("http://bitwarden.com")).toBe("bitwarden.com"); + expect(Utils.getDomain("http://vault.bitwarden.com")).toBe("bitwarden.com"); + expect( + Utils.getDomain("https://user:password@bitwarden.com:8080/password/sites?and&query#hash") + ).toBe("bitwarden.com"); + expect(Utils.getDomain("https://bitwarden.unknown")).toBe("bitwarden.unknown"); + }); + + it("should support localhost and IP", () => { + expect(Utils.getDomain("https://localhost")).toBe("localhost"); + expect(Utils.getDomain("https://192.168.1.1")).toBe("192.168.1.1"); + }); + + it("should reject invalid hostnames", () => { + expect(Utils.getDomain("https://mywebsite.com$.mywebsite.com")).toBeNull(); + expect(Utils.getDomain("https://mywebsite.com!.mywebsite.com")).toBeNull(); + }); + }); + + describe("getHostname", () => { + it("should fail for invalid urls", () => { + expect(Utils.getHostname(null)).toBeNull(); + expect(Utils.getHostname(undefined)).toBeNull(); + expect(Utils.getHostname(" ")).toBeNull(); + expect(Utils.getHostname('https://bit!:"_&ward.com')).toBeNull(); + expect(Utils.getHostname("bitwarden")).toBeNull(); + }); + + it("should handle valid urls", () => { + expect(Utils.getHostname("bitwarden.com")).toBe("bitwarden.com"); + expect(Utils.getHostname("https://bitwarden.com")).toBe("bitwarden.com"); + expect(Utils.getHostname("http://bitwarden.com")).toBe("bitwarden.com"); + expect(Utils.getHostname("http://vault.bitwarden.com")).toBe("vault.bitwarden.com"); + }); + + it("should support localhost and IP", () => { + expect(Utils.getHostname("https://localhost")).toBe("localhost"); + expect(Utils.getHostname("https://192.168.1.1")).toBe("192.168.1.1"); + }); + }); + + describe("newGuid", () => { + it("should create a valid guid", () => { + const validGuid = + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; + expect(Utils.newGuid()).toMatch(validGuid); + }); + }); +}); diff --git a/libs/common/spec/services/cipher.service.spec.ts b/libs/common/spec/services/cipher.service.spec.ts new file mode 100644 index 0000000000..79b75787f6 --- /dev/null +++ b/libs/common/spec/services/cipher.service.spec.ts @@ -0,0 +1,69 @@ +import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { FileUploadService } from "jslib-common/abstractions/fileUpload.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { SearchService } from "jslib-common/abstractions/search.service"; +import { SettingsService } from "jslib-common/abstractions/settings.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { Utils } from "jslib-common/misc/utils"; +import { Cipher } from "jslib-common/models/domain/cipher"; +import { EncArrayBuffer } from "jslib-common/models/domain/encArrayBuffer"; +import { EncString } from "jslib-common/models/domain/encString"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { CipherService } from "jslib-common/services/cipher.service"; + +const ENCRYPTED_TEXT = "This data has been encrypted"; +const ENCRYPTED_BYTES = new EncArrayBuffer(Utils.fromUtf8ToArray(ENCRYPTED_TEXT).buffer); + +describe("Cipher Service", () => { + let cryptoService: SubstituteOf; + let stateService: SubstituteOf; + let settingsService: SubstituteOf; + let apiService: SubstituteOf; + let fileUploadService: SubstituteOf; + let i18nService: SubstituteOf; + let searchService: SubstituteOf; + let logService: SubstituteOf; + + let cipherService: CipherService; + + beforeEach(() => { + cryptoService = Substitute.for(); + stateService = Substitute.for(); + settingsService = Substitute.for(); + apiService = Substitute.for(); + fileUploadService = Substitute.for(); + i18nService = Substitute.for(); + searchService = Substitute.for(); + logService = Substitute.for(); + + cryptoService.encryptToBytes(Arg.any(), Arg.any()).resolves(ENCRYPTED_BYTES); + cryptoService.encrypt(Arg.any(), Arg.any()).resolves(new EncString(ENCRYPTED_TEXT)); + + cipherService = new CipherService( + cryptoService, + settingsService, + apiService, + fileUploadService, + i18nService, + () => searchService, + logService, + stateService + ); + }); + + it("attachments upload encrypted file contents", async () => { + const fileName = "filename"; + const fileData = new Uint8Array(10).buffer; + cryptoService.getOrgKey(Arg.any()).resolves(new SymmetricCryptoKey(new Uint8Array(32).buffer)); + + await cipherService.saveAttachmentRawWithServer(new Cipher(), fileName, fileData); + + fileUploadService + .received(1) + .uploadCipherAttachment(Arg.any(), Arg.any(), new EncString(ENCRYPTED_TEXT), ENCRYPTED_BYTES); + }); +}); diff --git a/libs/common/spec/services/consoleLog.service.spec.ts b/libs/common/spec/services/consoleLog.service.spec.ts new file mode 100644 index 0000000000..3f3059f753 --- /dev/null +++ b/libs/common/spec/services/consoleLog.service.spec.ts @@ -0,0 +1,102 @@ +import { ConsoleLogService } from "jslib-common/services/consoleLog.service"; + +const originalConsole = console; +let caughtMessage: any; + +declare let console: any; + +export function interceptConsole(interceptions: any): object { + console = { + log: function () { + // eslint-disable-next-line + interceptions.log = arguments; + }, + warn: function () { + // eslint-disable-next-line + interceptions.warn = arguments; + }, + error: function () { + // eslint-disable-next-line + interceptions.error = arguments; + }, + }; + return interceptions; +} + +export function restoreConsole() { + console = originalConsole; +} + +describe("ConsoleLogService", () => { + let logService: ConsoleLogService; + beforeEach(() => { + caughtMessage = {}; + interceptConsole(caughtMessage); + logService = new ConsoleLogService(true); + }); + + afterAll(() => { + restoreConsole(); + }); + + it("filters messages below the set threshold", () => { + logService = new ConsoleLogService(true, () => true); + logService.debug("debug"); + logService.info("info"); + logService.warning("warning"); + logService.error("error"); + + expect(caughtMessage).toEqual({}); + }); + it("only writes debug messages in dev mode", () => { + logService = new ConsoleLogService(false); + + logService.debug("debug message"); + expect(caughtMessage.log).toBeUndefined(); + }); + + it("writes debug/info messages to console.log", () => { + logService.debug("this is a debug message"); + expect(caughtMessage).toMatchObject({ + log: { "0": "this is a debug message" }, + }); + + logService.info("this is an info message"); + expect(caughtMessage).toMatchObject({ + log: { "0": "this is an info message" }, + }); + }); + it("writes warning messages to console.warn", () => { + logService.warning("this is a warning message"); + expect(caughtMessage).toMatchObject({ + warn: { 0: "this is a warning message" }, + }); + }); + it("writes error messages to console.error", () => { + logService.error("this is an error message"); + expect(caughtMessage).toMatchObject({ + error: { 0: "this is an error message" }, + }); + }); + + it("times with output to info", async () => { + logService.time(); + await new Promise((r) => setTimeout(r, 250)); + const duration = logService.timeEnd(); + expect(duration[0]).toBe(0); + expect(duration[1]).toBeGreaterThan(0); + expect(duration[1]).toBeLessThan(500 * 10e6); + + expect(caughtMessage).toEqual(expect.arrayContaining([])); + expect(caughtMessage.log.length).toBe(1); + expect(caughtMessage.log[0]).toEqual(expect.stringMatching(/^default: \d+\.?\d*ms$/)); + }); + + it("filters time output", async () => { + logService = new ConsoleLogService(true, () => true); + logService.time(); + logService.timeEnd(); + + expect(caughtMessage).toEqual({}); + }); +}); diff --git a/libs/common/spec/services/export.service.spec.ts b/libs/common/spec/services/export.service.spec.ts new file mode 100644 index 0000000000..fcbbff11f7 --- /dev/null +++ b/libs/common/spec/services/export.service.spec.ts @@ -0,0 +1,209 @@ +import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { CipherType } from "jslib-common/enums/cipherType"; +import { KdfType } from "jslib-common/enums/kdfType"; +import { Utils } from "jslib-common/misc/utils"; +import { Cipher } from "jslib-common/models/domain/cipher"; +import { EncString } from "jslib-common/models/domain/encString"; +import { Login } from "jslib-common/models/domain/login"; +import { CipherWithIdExport as CipherExport } from "jslib-common/models/export/cipherWithIdsExport"; +import { CipherView } from "jslib-common/models/view/cipherView"; +import { LoginView } from "jslib-common/models/view/loginView"; +import { ExportService } from "jslib-common/services/export.service"; + +import { BuildTestObject, GetUniqueString } from "../utils"; + +const UserCipherViews = [ + generateCipherView(false), + generateCipherView(false), + generateCipherView(true), +]; + +const UserCipherDomains = [ + generateCipherDomain(false), + generateCipherDomain(false), + generateCipherDomain(true), +]; + +function generateCipherView(deleted: boolean) { + return BuildTestObject( + { + id: GetUniqueString("id"), + notes: GetUniqueString("notes"), + type: CipherType.Login, + login: BuildTestObject( + { + username: GetUniqueString("username"), + password: GetUniqueString("password"), + }, + LoginView + ), + collectionIds: null, + deletedDate: deleted ? new Date() : null, + }, + CipherView + ); +} + +function generateCipherDomain(deleted: boolean) { + return BuildTestObject( + { + id: GetUniqueString("id"), + notes: new EncString(GetUniqueString("notes")), + type: CipherType.Login, + login: BuildTestObject( + { + username: new EncString(GetUniqueString("username")), + password: new EncString(GetUniqueString("password")), + }, + Login + ), + collectionIds: null, + deletedDate: deleted ? new Date() : null, + }, + Cipher + ); +} + +function expectEqualCiphers(ciphers: CipherView[] | Cipher[], jsonResult: string) { + const actual = JSON.stringify(JSON.parse(jsonResult).items); + const items: CipherExport[] = []; + ciphers.forEach((c: CipherView | Cipher) => { + const item = new CipherExport(); + item.build(c); + items.push(item); + }); + + expect(actual).toEqual(JSON.stringify(items)); +} + +describe("ExportService", () => { + let exportService: ExportService; + let apiService: SubstituteOf; + let cryptoFunctionService: SubstituteOf; + let cipherService: SubstituteOf; + let folderService: SubstituteOf; + let cryptoService: SubstituteOf; + + beforeEach(() => { + apiService = Substitute.for(); + cryptoFunctionService = Substitute.for(); + cipherService = Substitute.for(); + folderService = Substitute.for(); + cryptoService = Substitute.for(); + + folderService.getAllDecrypted().resolves([]); + folderService.getAll().resolves([]); + + exportService = new ExportService( + folderService, + cipherService, + apiService, + cryptoService, + cryptoFunctionService + ); + }); + + it("exports unecrypted user ciphers", async () => { + cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1)); + + const actual = await exportService.getExport("json"); + + expectEqualCiphers(UserCipherViews.slice(0, 1), actual); + }); + + it("exports encrypted json user ciphers", async () => { + cipherService.getAll().resolves(UserCipherDomains.slice(0, 1)); + + const actual = await exportService.getExport("encrypted_json"); + + expectEqualCiphers(UserCipherDomains.slice(0, 1), actual); + }); + + it("does not unecrypted export trashed user items", async () => { + cipherService.getAllDecrypted().resolves(UserCipherViews); + + const actual = await exportService.getExport("json"); + + expectEqualCiphers(UserCipherViews.slice(0, 2), actual); + }); + + it("does not encrypted export trashed user items", async () => { + cipherService.getAll().resolves(UserCipherDomains); + + const actual = await exportService.getExport("encrypted_json"); + + expectEqualCiphers(UserCipherDomains.slice(0, 2), actual); + }); + + describe("password protected export", () => { + let exportString: string; + let exportObject: any; + let mac: SubstituteOf; + let data: SubstituteOf; + const password = "password"; + const salt = "salt"; + + describe("export json object", () => { + beforeEach(async () => { + mac = Substitute.for(); + data = Substitute.for(); + + mac.encryptedString.returns("mac"); + data.encryptedString.returns("encData"); + + jest.spyOn(Utils, "fromBufferToB64").mockReturnValue(salt); + cipherService.getAllDecrypted().resolves(UserCipherViews.slice(0, 1)); + + exportString = await exportService.getPasswordProtectedExport(password); + exportObject = JSON.parse(exportString); + }); + + it("specifies it is encrypted", () => { + expect(exportObject.encrypted).toBe(true); + }); + + it("specifies it's password protected", () => { + expect(exportObject.passwordProtected).toBe(true); + }); + + it("specifies salt", () => { + expect(exportObject.salt).toEqual("salt"); + }); + + it("specifies kdfIterations", () => { + expect(exportObject.kdfIterations).toEqual(100000); + }); + + it("has kdfType", () => { + expect(exportObject.kdfType).toEqual(KdfType.PBKDF2_SHA256); + }); + + it("has a mac property", async () => { + cryptoService.encrypt(Arg.any(), Arg.any()).resolves(mac); + exportString = await exportService.getPasswordProtectedExport(password); + exportObject = JSON.parse(exportString); + + expect(exportObject.encKeyValidation_DO_NOT_EDIT).toEqual(mac.encryptedString); + }); + + it("has data property", async () => { + cryptoService.encrypt(Arg.any(), Arg.any()).resolves(data); + exportString = await exportService.getPasswordProtectedExport(password); + exportObject = JSON.parse(exportString); + + expect(exportObject.data).toEqual(data.encryptedString); + }); + + it("encrypts the data property", async () => { + const unencrypted = await exportService.getExport(); + expect(exportObject.data).not.toEqual(unencrypted); + }); + }); + }); +}); diff --git a/libs/common/spec/services/import.service.spec.ts b/libs/common/spec/services/import.service.spec.ts new file mode 100644 index 0000000000..dbf31cb298 --- /dev/null +++ b/libs/common/spec/services/import.service.spec.ts @@ -0,0 +1,72 @@ +import Substitute, { SubstituteOf } from "@fluffy-spoon/substitute"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { CipherService } from "jslib-common/abstractions/cipher.service"; +import { CollectionService } from "jslib-common/abstractions/collection.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { FolderService } from "jslib-common/abstractions/folder.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { BitwardenPasswordProtectedImporter } from "jslib-common/importers/bitwardenPasswordProtectedImporter"; +import { Importer } from "jslib-common/importers/importer"; +import { Utils } from "jslib-common/misc/utils"; +import { ImportService } from "jslib-common/services/import.service"; + +describe("ImportService", () => { + let importService: ImportService; + let cipherService: SubstituteOf; + let folderService: SubstituteOf; + let apiService: SubstituteOf; + let i18nService: SubstituteOf; + let collectionService: SubstituteOf; + let platformUtilsService: SubstituteOf; + let cryptoService: SubstituteOf; + + beforeEach(() => { + cipherService = Substitute.for(); + folderService = Substitute.for(); + apiService = Substitute.for(); + i18nService = Substitute.for(); + collectionService = Substitute.for(); + platformUtilsService = Substitute.for(); + cryptoService = Substitute.for(); + + importService = new ImportService( + cipherService, + folderService, + apiService, + i18nService, + collectionService, + platformUtilsService, + cryptoService + ); + }); + + describe("getImporterInstance", () => { + describe("Get bitPasswordProtected importer", () => { + let importer: Importer; + const organizationId = Utils.newGuid(); + const password = Utils.newGuid(); + + beforeEach(() => { + importer = importService.getImporter( + "bitwardenpasswordprotected", + organizationId, + password + ); + }); + + it("returns an instance of BitwardenPasswordProtectedImporter", () => { + expect(importer).toBeInstanceOf(BitwardenPasswordProtectedImporter); + }); + + it("has the appropriate organization Id", () => { + expect(importer.organizationId).toEqual(organizationId); + }); + + it("has the appropriate password", () => { + expect(Object.entries(importer)).toEqual(expect.arrayContaining([["password", password]])); + }); + }); + }); +}); diff --git a/libs/common/spec/services/stateMigration.service.ts b/libs/common/spec/services/stateMigration.service.ts new file mode 100644 index 0000000000..d325585a7c --- /dev/null +++ b/libs/common/spec/services/stateMigration.service.ts @@ -0,0 +1,84 @@ +import { Arg, Substitute, SubstituteOf } from "@fluffy-spoon/substitute"; + +import { StorageService } from "jslib-common/abstractions/storage.service"; +import { StateVersion } from "jslib-common/enums/stateVersion"; +import { StateFactory } from "jslib-common/factories/stateFactory"; +import { Account } from "jslib-common/models/domain/account"; +import { GlobalState } from "jslib-common/models/domain/globalState"; +import { StateMigrationService } from "jslib-common/services/stateMigration.service"; + +const userId = "USER_ID"; + +describe("State Migration Service", () => { + let storageService: SubstituteOf; + let secureStorageService: SubstituteOf; + let stateFactory: SubstituteOf; + + let stateMigrationService: StateMigrationService; + + beforeEach(() => { + storageService = Substitute.for(); + secureStorageService = Substitute.for(); + stateFactory = Substitute.for(); + + stateMigrationService = new StateMigrationService( + storageService, + secureStorageService, + stateFactory + ); + }); + + describe("StateVersion 3 to 4 migration", async () => { + beforeEach(() => { + const globalVersion3: Partial = { + stateVersion: StateVersion.Three, + }; + + storageService.get("global", Arg.any()).resolves(globalVersion3); + storageService.get("authenticatedAccounts", Arg.any()).resolves([userId]); + }); + + it("clears everBeenUnlocked", async () => { + const accountVersion3: Account = { + profile: { + apiKeyClientId: null, + convertAccountToKeyConnector: null, + email: "EMAIL", + emailVerified: true, + everBeenUnlocked: true, + hasPremiumPersonally: false, + kdfIterations: 100000, + kdfType: 0, + keyHash: "KEY_HASH", + lastSync: "LAST_SYNC", + userId: userId, + usesKeyConnector: false, + forcePasswordReset: false, + }, + }; + + const expectedAccountVersion4: Account = { + profile: { + ...accountVersion3.profile, + }, + }; + delete expectedAccountVersion4.profile.everBeenUnlocked; + + storageService.get(userId, Arg.any()).resolves(accountVersion3); + + await stateMigrationService.migrate(); + + storageService.received(1).save(userId, expectedAccountVersion4, Arg.any()); + }); + + it("updates StateVersion number", async () => { + await stateMigrationService.migrate(); + + storageService.received(1).save( + "global", + Arg.is((globals: GlobalState) => globals.stateVersion === StateVersion.Four), + Arg.any() + ); + }); + }); +}); diff --git a/libs/common/spec/test.ts b/libs/common/spec/test.ts new file mode 100644 index 0000000000..9d9906aa24 --- /dev/null +++ b/libs/common/spec/test.ts @@ -0,0 +1,5 @@ +import { webcrypto } from "crypto"; + +Object.defineProperty(window, "crypto", { + value: webcrypto, +}); diff --git a/libs/common/spec/utils.ts b/libs/common/spec/utils.ts new file mode 100644 index 0000000000..58963d0f83 --- /dev/null +++ b/libs/common/spec/utils.ts @@ -0,0 +1,37 @@ +import Substitute, { Arg } from "@fluffy-spoon/substitute"; + +import { EncString } from "jslib-common/models/domain/encString"; + +function newGuid() { + return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c === "x" ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); +} + +export function GetUniqueString(prefix = "") { + return prefix + "_" + newGuid(); +} + +export function BuildTestObject( + def: Partial> | T, + constructor?: new () => T +): T { + return Object.assign(constructor === null ? {} : new constructor(), def) as T; +} + +export function mockEnc(s: string): EncString { + const mock = Substitute.for(); + mock.decrypt(Arg.any(), Arg.any()).resolves(s); + + return mock; +} + +export function makeStaticByteArray(length: number) { + const arr = new Uint8Array(length); + for (let i = 0; i < length; i++) { + arr[i] = i; + } + return arr; +} diff --git a/libs/common/spec/web/services/webCryptoFunction.service.spec.ts b/libs/common/spec/web/services/webCryptoFunction.service.spec.ts new file mode 100644 index 0000000000..3e437c6a97 --- /dev/null +++ b/libs/common/spec/web/services/webCryptoFunction.service.spec.ts @@ -0,0 +1,558 @@ +import Substitute from "@fluffy-spoon/substitute"; + +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { Utils } from "jslib-common/misc/utils"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { WebCryptoFunctionService } from "jslib-common/services/webCryptoFunction.service"; + +const RsaPublicKey = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl0Vawl/toXzkEvB82FEtqHP" + + "4xlU2ab/v0crqIfXfIoWF/XXdHGIdrZeilnRXPPJT1B9dTsasttEZNnua/0Rek/cjNDHtzT52irfoZYS7X6HNIfOi54Q+egP" + + "RQ1H7iNHVZz3K8Db9GCSKPeC8MbW6gVCzb15esCe1gGzg6wkMuWYDFYPoh/oBqcIqrGah7firqB1nDedzEjw32heP2DAffVN" + + "084iTDjiWrJNUxBJ2pDD5Z9dT3MzQ2s09ew1yMWK2z37rT3YerC7OgEDmo3WYo3xL3qYJznu3EO2nmrYjiRa40wKSjxsTlUc" + + "xDF+F0uMW8oR9EMUHgepdepfAtLsSAQIDAQAB"; +const RsaPrivateKey = + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS8Hz" + + "YUS2oc/jGVTZpv+/Ryuoh9d8ihYX9dd0cYh2tl6KWdFc88lPUH11Oxqy20Rk2e5r/RF6T9yM0Me3NPnaKt+hlhLtfoc0h86L" + + "nhD56A9FDUfuI0dVnPcrwNv0YJIo94LwxtbqBULNvXl6wJ7WAbODrCQy5ZgMVg+iH+gGpwiqsZqHt+KuoHWcN53MSPDfaF4/" + + "YMB99U3TziJMOOJask1TEEnakMPln11PczNDazT17DXIxYrbPfutPdh6sLs6AQOajdZijfEvepgnOe7cQ7aeatiOJFrjTApK" + + "PGxOVRzEMX4XS4xbyhH0QxQeB6l16l8C0uxIBAgMBAAECggEASaWfeVDA3cVzOPFSpvJm20OTE+R6uGOU+7vh36TX/POq92q" + + "Buwbd0h0oMD32FxsXywd2IxtBDUSiFM9699qufTVuM0Q3tZw6lHDTOVG08+tPdr8qSbMtw7PGFxN79fHLBxejjO4IrM9lapj" + + "WpxEF+11x7r+wM+0xRZQ8sNFYG46aPfIaty4BGbL0I2DQ2y8I57iBCAy69eht59NLMm27fRWGJIWCuBIjlpfzET1j2HLXUIh" + + "5bTBNzqaN039WH49HczGE3mQKVEJZc/efk3HaVd0a1Sjzyn0QY+N1jtZN3jTRbuDWA1AknkX1LX/0tUhuS3/7C3ejHxjw4Dk" + + "1ZLo5/QKBgQDIWvqFn0+IKRSu6Ua2hDsufIHHUNLelbfLUMmFthxabcUn4zlvIscJO00Tq/ezopSRRvbGiqnxjv/mYxucvOU" + + "BeZtlus0Q9RTACBtw9TGoNTmQbEunJ2FOSlqbQxkBBAjgGEppRPt30iGj/VjAhCATq2MYOa/X4dVR51BqQAFIEwKBgQDBSIf" + + "TFKC/hDk6FKZlgwvupWYJyU9RkyfstPErZFmzoKhPkQ3YORo2oeAYmVUbS9I2iIYpYpYQJHX8jMuCbCz4ONxTCuSIXYQYUcU" + + "q4PglCKp31xBAE6TN8SvhfME9/MvuDssnQinAHuF0GDAhF646T3LLS1not6Vszv7brwSoGwKBgQC88v/8cGfi80ssQZeMnVv" + + "q1UTXIeQcQnoY5lGHJl3K8mbS3TnXE6c9j417Fdz+rj8KWzBzwWXQB5pSPflWcdZO886Xu/mVGmy9RWgLuVFhXwCwsVEPjNX" + + "5ramRb0/vY0yzenUCninBsIxFSbIfrPtLUYCc4hpxr+sr2Mg/y6jpvQKBgBezMRRs3xkcuXepuI2R+BCXL1/b02IJTUf1F+1" + + "eLLGd7YV0H+J3fgNc7gGWK51hOrF9JBZHBGeOUPlaukmPwiPdtQZpu4QNE3l37VlIpKTF30E6mb+BqR+nht3rUjarnMXgAoE" + + "Z18y6/KIjpSMpqC92Nnk/EBM9EYe6Cf4eA9ApAoGAeqEUg46UTlJySkBKURGpIs3v1kkf5I0X8DnOhwb+HPxNaiEdmO7ckm8" + + "+tPVgppLcG0+tMdLjigFQiDUQk2y3WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEzXKZ" + + "BokBGnjFnTnKcs7nv/O8="; + +const Sha1Mac = "4d4c223f95dc577b665ec4ccbcb680b80a397038"; +const Sha256Mac = "6be3caa84922e12aaaaa2f16c40d44433bb081ef323db584eb616333ab4e874f"; +const Sha512Mac = + "21910e341fa12106ca35758a2285374509326c9fbe0bd64e7b99c898f841dc948c58ce66d3504d8883c" + + "5ea7817a0b7c5d4d9b00364ccd214669131fc17fe4aca"; + +describe("WebCrypto Function Service", () => { + describe("pbkdf2", () => { + const regular256Key = "pj9prw/OHPleXI6bRdmlaD+saJS4awrMiQsQiDjeu2I="; + const utf8256Key = "yqvoFXgMRmHR3QPYr5pyR4uVuoHkltv9aHUP63p8n7I="; + const unicode256Key = "ZdeOata6xoRpB4DLp8zHhXz5kLmkWtX5pd+TdRH8w8w="; + + const regular512Key = + "liTi/Ke8LPU1Qv+Vl7NGEVt/XMbsBVJ2kQxtVG/Z1/JFHFKQW3ZkI81qVlwTiCpb+cFXzs+57" + + "eyhhx5wfKo5Cg=="; + const utf8512Key = + "df0KdvIBeCzD/kyXptwQohaqUa4e7IyFUyhFQjXCANu5T+scq55hCcE4dG4T/MhAk2exw8j7ixRN" + + "zXANiVZpnw=="; + const unicode512Key = + "FE+AnUJaxv8jh+zUDtZz4mjjcYk0/PZDZm+SLJe3XtxtnpdqqpblX6JjuMZt/dYYNMOrb2+mD" + + "L3FiQDTROh1lg=="; + + testPbkdf2("sha256", regular256Key, utf8256Key, unicode256Key); + testPbkdf2("sha512", regular512Key, utf8512Key, unicode512Key); + }); + + describe("hkdf", () => { + const regular256Key = "qBUmEYtwTwwGPuw/z6bs/qYXXYNUlocFlyAuuANI8Pw="; + const utf8256Key = "6DfJwW1R3txgiZKkIFTvVAb7qVlG7lKcmJGJoxR2GBU="; + const unicode256Key = "gejGI82xthA+nKtKmIh82kjw+ttHr+ODsUoGdu5sf0A="; + + const regular512Key = "xe5cIG6ZfwGmb1FvsOedM0XKOm21myZkjL/eDeKIqqM="; + const utf8512Key = "XQMVBnxVEhlvjSFDQc77j5GDE9aorvbS0vKnjhRg0LY="; + const unicode512Key = "148GImrTbrjaGAe/iWEpclINM8Ehhko+9lB14+52lqc="; + + testHkdf("sha256", regular256Key, utf8256Key, unicode256Key); + testHkdf("sha512", regular512Key, utf8512Key, unicode512Key); + }); + + describe("hkdfExpand", () => { + const prk16Byte = "criAmKtfzxanbgea5/kelQ=="; + const prk32Byte = "F5h4KdYQnIVH4rKH0P9CZb1GrR4n16/sJrS0PsQEn0Y="; + const prk64Byte = + "ssBK0mRG17VHdtsgt8yo4v25CRNpauH+0r2fwY/E9rLyaFBAOMbIeTry+" + + "gUJ28p8y+hFh3EI9pcrEWaNvFYonQ=="; + + testHkdfExpand("sha256", prk32Byte, 32, "BnIqJlfnHm0e/2iB/15cbHyR19ARPIcWRp4oNS22CD8="); + testHkdfExpand( + "sha256", + prk32Byte, + 64, + "BnIqJlfnHm0e/2iB/15cbHyR19ARPIcWRp4oNS22CD9BV+" + + "/queOZenPNkDhmlVyL2WZ3OSU5+7ISNF5NhNfvZA==" + ); + testHkdfExpand("sha512", prk64Byte, 32, "uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlk="); + testHkdfExpand( + "sha512", + prk64Byte, + 64, + "uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlkY5Pv0sB+" + + "MqvaopmkC6sD/j89zDwTV9Ib2fpucUydO8w==" + ); + + it("should fail with prk too small", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const f = cryptoFunctionService.hkdfExpand( + Utils.fromB64ToArray(prk16Byte), + "info", + 32, + "sha256" + ); + await expect(f).rejects.toEqual(new Error("prk is too small.")); + }); + + it("should fail with outputByteSize is too large", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const f = cryptoFunctionService.hkdfExpand( + Utils.fromB64ToArray(prk32Byte), + "info", + 8161, + "sha256" + ); + await expect(f).rejects.toEqual(new Error("outputByteSize is too large.")); + }); + }); + + describe("hash", () => { + const regular1Hash = "2a241604fb921fad12bf877282457268e1dccb70"; + const utf81Hash = "85672798dc5831e96d6c48655d3d39365a9c88b6"; + const unicode1Hash = "39c975935054a3efc805a9709b60763a823a6ad4"; + + const regular256Hash = "2b8e96031d352a8655d733d7a930b5ffbea69dc25cf65c7bca7dd946278908b2"; + const utf8256Hash = "25fe8440f5b01ed113b0a0e38e721b126d2f3f77a67518c4a04fcde4e33eeb9d"; + const unicode256Hash = "adc1c0c2afd6e92cefdf703f9b6eb2c38e0d6d1a040c83f8505c561fea58852e"; + + const regular512Hash = + "c15cf11d43bde333647e3f559ec4193bb2edeaa0e8b902772f514cdf3f785a3f49a6e02a4b87b3" + + "b47523271ad45b7e0aebb5cdcc1bc54815d256eb5dcb80da9d"; + const utf8512Hash = + "035c31a877a291af09ed2d3a1a293e69c3e079ea2cecc00211f35e6bce10474ca3ad6e30b59e26118" + + "37463f20969c5bc95282965a051a88f8cdf2e166549fcdd"; + const unicode512Hash = + "2b16a5561af8ad6fe414cc103fc8036492e1fc6d9aabe1b655497054f760fe0e34c5d100ac773d" + + "9f3030438284f22dbfa20cb2e9b019f2c98dfe38ce1ef41bae"; + + const regularMd5 = "5eceffa53a5fd58c44134211e2c5f522"; + const utf8Md5 = "3abc9433c09551b939c80aa0aa3174e1"; + const unicodeMd5 = "85ae134072c8d81257933f7045ba17ca"; + + testHash("sha1", regular1Hash, utf81Hash, unicode1Hash); + testHash("sha256", regular256Hash, utf8256Hash, unicode256Hash); + testHash("sha512", regular512Hash, utf8512Hash, unicode512Hash); + testHash("md5", regularMd5, utf8Md5, unicodeMd5); + }); + + describe("hmac", () => { + testHmac("sha1", Sha1Mac); + testHmac("sha256", Sha256Mac); + testHmac("sha512", Sha512Mac); + }); + + describe("compare", () => { + it("should successfully compare two of the same values", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const equal = await cryptoFunctionService.compare(a.buffer, a.buffer); + expect(equal).toBe(true); + }); + + it("should successfully compare two different values of the same length", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const b = new Uint8Array(2); + b[0] = 3; + b[1] = 4; + const equal = await cryptoFunctionService.compare(a.buffer, b.buffer); + expect(equal).toBe(false); + }); + + it("should successfully compare two different values of different lengths", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const b = new Uint8Array(2); + b[0] = 3; + const equal = await cryptoFunctionService.compare(a.buffer, b.buffer); + expect(equal).toBe(false); + }); + }); + + describe("hmacFast", () => { + testHmacFast("sha1", Sha1Mac); + testHmacFast("sha256", Sha256Mac); + testHmacFast("sha512", Sha512Mac); + }); + + describe("compareFast", () => { + it("should successfully compare two of the same values", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const aByteString = Utils.fromBufferToByteString(a.buffer); + const equal = await cryptoFunctionService.compareFast(aByteString, aByteString); + expect(equal).toBe(true); + }); + + it("should successfully compare two different values of the same length", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const aByteString = Utils.fromBufferToByteString(a.buffer); + const b = new Uint8Array(2); + b[0] = 3; + b[1] = 4; + const bByteString = Utils.fromBufferToByteString(b.buffer); + const equal = await cryptoFunctionService.compareFast(aByteString, bByteString); + expect(equal).toBe(false); + }); + + it("should successfully compare two different values of different lengths", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const aByteString = Utils.fromBufferToByteString(a.buffer); + const b = new Uint8Array(2); + b[0] = 3; + const bByteString = Utils.fromBufferToByteString(b.buffer); + const equal = await cryptoFunctionService.compareFast(aByteString, bByteString); + expect(equal).toBe(false); + }); + }); + + describe("aesEncrypt", () => { + it("should successfully encrypt data", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const iv = makeStaticByteArray(16); + const key = makeStaticByteArray(32); + const data = Utils.fromUtf8ToArray("EncryptMe!"); + const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); + expect(Utils.fromBufferToB64(encValue)).toBe("ByUF8vhyX4ddU9gcooznwA=="); + }); + + it("should successfully encrypt and then decrypt data fast", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const iv = makeStaticByteArray(16); + const key = makeStaticByteArray(32); + const value = "EncryptMe!"; + const data = Utils.fromUtf8ToArray(value); + const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); + const encData = Utils.fromBufferToB64(encValue); + const b64Iv = Utils.fromBufferToB64(iv.buffer); + const symKey = new SymmetricCryptoKey(key.buffer); + const params = cryptoFunctionService.aesDecryptFastParameters(encData, b64Iv, null, symKey); + const decValue = await cryptoFunctionService.aesDecryptFast(params); + expect(decValue).toBe(value); + }); + + it("should successfully encrypt and then decrypt data", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const iv = makeStaticByteArray(16); + const key = makeStaticByteArray(32); + const value = "EncryptMe!"; + const data = Utils.fromUtf8ToArray(value); + const encValue = await cryptoFunctionService.aesEncrypt(data.buffer, iv.buffer, key.buffer); + const decValue = await cryptoFunctionService.aesDecrypt(encValue, iv.buffer, key.buffer); + expect(Utils.fromBufferToUtf8(decValue)).toBe(value); + }); + }); + + describe("aesDecryptFast", () => { + it("should successfully decrypt data", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const iv = Utils.fromBufferToB64(makeStaticByteArray(16).buffer); + const symKey = new SymmetricCryptoKey(makeStaticByteArray(32).buffer); + const data = "ByUF8vhyX4ddU9gcooznwA=="; + const params = cryptoFunctionService.aesDecryptFastParameters(data, iv, null, symKey); + const decValue = await cryptoFunctionService.aesDecryptFast(params); + expect(decValue).toBe("EncryptMe!"); + }); + }); + + describe("aesDecrypt", () => { + it("should successfully decrypt data", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const iv = makeStaticByteArray(16); + const key = makeStaticByteArray(32); + const data = Utils.fromB64ToArray("ByUF8vhyX4ddU9gcooznwA=="); + const decValue = await cryptoFunctionService.aesDecrypt(data.buffer, iv.buffer, key.buffer); + expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!"); + }); + }); + + describe("rsaEncrypt", () => { + it("should successfully encrypt and then decrypt data", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const pubKey = Utils.fromB64ToArray(RsaPublicKey); + const privKey = Utils.fromB64ToArray(RsaPrivateKey); + const value = "EncryptMe!"; + const data = Utils.fromUtf8ToArray(value); + const encValue = await cryptoFunctionService.rsaEncrypt(data.buffer, pubKey.buffer, "sha1"); + const decValue = await cryptoFunctionService.rsaDecrypt(encValue, privKey.buffer, "sha1"); + expect(Utils.fromBufferToUtf8(decValue)).toBe(value); + }); + }); + + describe("rsaDecrypt", () => { + it("should successfully decrypt data", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const privKey = Utils.fromB64ToArray(RsaPrivateKey); + const data = Utils.fromB64ToArray( + "A1/p8BQzN9UrbdYxUY2Va5+kPLyfZXF9JsZrjeEXcaclsnHurdxVAJcnbEqYMP3UXV" + + "4YAS/mpf+Rxe6/X0WS1boQdA0MAHSgx95hIlAraZYpiMLLiJRKeo2u8YivCdTM9V5vuAEJwf9Tof/qFsFci3sApdbATkorCT" + + "zFOIEPF2S1zgperEP23M01mr4dWVdYN18B32YF67xdJHMbFhp5dkQwv9CmscoWq7OE5HIfOb+JAh7BEZb+CmKhM3yWJvoR/D" + + "/5jcercUtK2o+XrzNrL4UQ7yLZcFz6Bfwb/j6ICYvqd/YJwXNE6dwlL57OfwJyCdw2rRYf0/qI00t9u8Iitw==" + ); + const decValue = await cryptoFunctionService.rsaDecrypt(data.buffer, privKey.buffer, "sha1"); + expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!"); + }); + }); + + describe("rsaExtractPublicKey", () => { + it("should successfully extract key", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const privKey = Utils.fromB64ToArray(RsaPrivateKey); + const publicKey = await cryptoFunctionService.rsaExtractPublicKey(privKey.buffer); + expect(Utils.fromBufferToB64(publicKey)).toBe(RsaPublicKey); + }); + }); + + describe("rsaGenerateKeyPair", () => { + testRsaGenerateKeyPair(1024); + testRsaGenerateKeyPair(2048); + + // Generating 4096 bit keys can be slow. Commenting it out to save CI. + // testRsaGenerateKeyPair(4096); + }); + + describe("randomBytes", () => { + it("should make a value of the correct length", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const randomData = await cryptoFunctionService.randomBytes(16); + expect(randomData.byteLength).toBe(16); + }); + + it("should not make the same value twice", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const randomData = await cryptoFunctionService.randomBytes(16); + const randomData2 = await cryptoFunctionService.randomBytes(16); + expect( + randomData.byteLength === randomData2.byteLength && randomData !== randomData2 + ).toBeTruthy(); + }); + }); +}); + +function testPbkdf2( + algorithm: "sha256" | "sha512", + regularKey: string, + utf8Key: string, + unicodeKey: string +) { + const regularEmail = "user@example.com"; + const utf8Email = "üser@example.com"; + + const regularPassword = "password"; + const utf8Password = "pǻssword"; + const unicodePassword = "😀password🙏"; + + it("should create valid " + algorithm + " key from regular input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2(regularPassword, regularEmail, algorithm, 5000); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); + + it("should create valid " + algorithm + " key from utf8 input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2(utf8Password, utf8Email, algorithm, 5000); + expect(Utils.fromBufferToB64(key)).toBe(utf8Key); + }); + + it("should create valid " + algorithm + " key from unicode input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2(unicodePassword, regularEmail, algorithm, 5000); + expect(Utils.fromBufferToB64(key)).toBe(unicodeKey); + }); + + it("should create valid " + algorithm + " key from array buffer input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2( + Utils.fromUtf8ToArray(regularPassword).buffer, + Utils.fromUtf8ToArray(regularEmail).buffer, + algorithm, + 5000 + ); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); +} + +function testHkdf( + algorithm: "sha256" | "sha512", + regularKey: string, + utf8Key: string, + unicodeKey: string +) { + const ikm = Utils.fromB64ToArray("criAmKtfzxanbgea5/kelQ=="); + + const regularSalt = "salt"; + const utf8Salt = "üser_salt"; + const unicodeSalt = "😀salt🙏"; + + const regularInfo = "info"; + const utf8Info = "üser_info"; + const unicodeInfo = "😀info🙏"; + + it("should create valid " + algorithm + " key from regular input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf(ikm, regularSalt, regularInfo, 32, algorithm); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); + + it("should create valid " + algorithm + " key from utf8 input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf(ikm, utf8Salt, utf8Info, 32, algorithm); + expect(Utils.fromBufferToB64(key)).toBe(utf8Key); + }); + + it("should create valid " + algorithm + " key from unicode input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf(ikm, unicodeSalt, unicodeInfo, 32, algorithm); + expect(Utils.fromBufferToB64(key)).toBe(unicodeKey); + }); + + it("should create valid " + algorithm + " key from array buffer input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf( + ikm, + Utils.fromUtf8ToArray(regularSalt).buffer, + Utils.fromUtf8ToArray(regularInfo).buffer, + 32, + algorithm + ); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); +} + +function testHkdfExpand( + algorithm: "sha256" | "sha512", + b64prk: string, + outputByteSize: number, + b64ExpectedOkm: string +) { + const info = "info"; + + it("should create valid " + algorithm + " " + outputByteSize + " byte okm", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const okm = await cryptoFunctionService.hkdfExpand( + Utils.fromB64ToArray(b64prk), + info, + outputByteSize, + algorithm + ); + expect(Utils.fromBufferToB64(okm)).toBe(b64ExpectedOkm); + }); +} + +function testHash( + algorithm: "sha1" | "sha256" | "sha512" | "md5", + regularHash: string, + utf8Hash: string, + unicodeHash: string +) { + const regularValue = "HashMe!!"; + const utf8Value = "HǻshMe!!"; + const unicodeValue = "😀HashMe!!!🙏"; + + it("should create valid " + algorithm + " hash from regular input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const hash = await cryptoFunctionService.hash(regularValue, algorithm); + expect(Utils.fromBufferToHex(hash)).toBe(regularHash); + }); + + it("should create valid " + algorithm + " hash from utf8 input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const hash = await cryptoFunctionService.hash(utf8Value, algorithm); + expect(Utils.fromBufferToHex(hash)).toBe(utf8Hash); + }); + + it("should create valid " + algorithm + " hash from unicode input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const hash = await cryptoFunctionService.hash(unicodeValue, algorithm); + expect(Utils.fromBufferToHex(hash)).toBe(unicodeHash); + }); + + it("should create valid " + algorithm + " hash from array buffer input", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const hash = await cryptoFunctionService.hash( + Utils.fromUtf8ToArray(regularValue).buffer, + algorithm + ); + expect(Utils.fromBufferToHex(hash)).toBe(regularHash); + }); +} + +function testHmac(algorithm: "sha1" | "sha256" | "sha512", mac: string) { + it("should create valid " + algorithm + " hmac", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const computedMac = await cryptoFunctionService.hmac( + Utils.fromUtf8ToArray("SignMe!!").buffer, + Utils.fromUtf8ToArray("secretkey").buffer, + algorithm + ); + expect(Utils.fromBufferToHex(computedMac)).toBe(mac); + }); +} + +function testHmacFast(algorithm: "sha1" | "sha256" | "sha512", mac: string) { + it("should create valid " + algorithm + " hmac", async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const keyByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("secretkey").buffer); + const dataByteString = Utils.fromBufferToByteString(Utils.fromUtf8ToArray("SignMe!!").buffer); + const computedMac = await cryptoFunctionService.hmacFast( + dataByteString, + keyByteString, + algorithm + ); + expect(Utils.fromBufferToHex(Utils.fromByteStringToArray(computedMac).buffer)).toBe(mac); + }); +} + +function testRsaGenerateKeyPair(length: 1024 | 2048 | 4096) { + it( + "should successfully generate a " + length + " bit key pair", + async () => { + const cryptoFunctionService = getWebCryptoFunctionService(); + const keyPair = await cryptoFunctionService.rsaGenerateKeyPair(length); + expect(keyPair[0] == null || keyPair[1] == null).toBe(false); + const publicKey = await cryptoFunctionService.rsaExtractPublicKey(keyPair[1]); + expect(Utils.fromBufferToB64(keyPair[0])).toBe(Utils.fromBufferToB64(publicKey)); + }, + 30000 + ); +} + +function getWebCryptoFunctionService() { + const platformUtilsMock = Substitute.for(); + platformUtilsMock.isEdge().mimicks(() => navigator.userAgent.indexOf(" Edg/") !== -1); + + return new WebCryptoFunctionService(window); +} + +function makeStaticByteArray(length: number) { + const arr = new Uint8Array(length); + for (let i = 0; i < length; i++) { + arr[i] = i; + } + return arr; +} diff --git a/libs/common/src/abstractions/api.service.ts b/libs/common/src/abstractions/api.service.ts new file mode 100644 index 0000000000..21a5373aa7 --- /dev/null +++ b/libs/common/src/abstractions/api.service.ts @@ -0,0 +1,716 @@ +import { OrganizationConnectionType } from "jslib-common/enums/organizationConnectionType"; +import { OrganizationConnectionRequest } from "jslib-common/models/request/organizationConnectionRequest"; +import { BillingHistoryResponse } from "jslib-common/models/response/billingHistoryResponse"; +import { BillingPaymentResponse } from "jslib-common/models/response/billingPaymentResponse"; +import { + OrganizationConnectionConfigApis, + OrganizationConnectionResponse, +} from "jslib-common/models/response/organizationConnectionResponse"; +import { SsoPreValidateResponse } from "jslib-common/models/response/ssoPreValidateResponse"; + +import { PolicyType } from "../enums/policyType"; +import { SetKeyConnectorKeyRequest } from "../models/request/account/setKeyConnectorKeyRequest"; +import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest"; +import { AttachmentRequest } from "../models/request/attachmentRequest"; +import { BitPayInvoiceRequest } from "../models/request/bitPayInvoiceRequest"; +import { CipherBulkDeleteRequest } from "../models/request/cipherBulkDeleteRequest"; +import { CipherBulkMoveRequest } from "../models/request/cipherBulkMoveRequest"; +import { CipherBulkRestoreRequest } from "../models/request/cipherBulkRestoreRequest"; +import { CipherBulkShareRequest } from "../models/request/cipherBulkShareRequest"; +import { CipherCollectionsRequest } from "../models/request/cipherCollectionsRequest"; +import { CipherCreateRequest } from "../models/request/cipherCreateRequest"; +import { CipherRequest } from "../models/request/cipherRequest"; +import { CipherShareRequest } from "../models/request/cipherShareRequest"; +import { CollectionRequest } from "../models/request/collectionRequest"; +import { DeleteRecoverRequest } from "../models/request/deleteRecoverRequest"; +import { EmailRequest } from "../models/request/emailRequest"; +import { EmailTokenRequest } from "../models/request/emailTokenRequest"; +import { EmergencyAccessAcceptRequest } from "../models/request/emergencyAccessAcceptRequest"; +import { EmergencyAccessConfirmRequest } from "../models/request/emergencyAccessConfirmRequest"; +import { EmergencyAccessInviteRequest } from "../models/request/emergencyAccessInviteRequest"; +import { EmergencyAccessPasswordRequest } from "../models/request/emergencyAccessPasswordRequest"; +import { EmergencyAccessUpdateRequest } from "../models/request/emergencyAccessUpdateRequest"; +import { EventRequest } from "../models/request/eventRequest"; +import { FolderRequest } from "../models/request/folderRequest"; +import { GroupRequest } from "../models/request/groupRequest"; +import { IapCheckRequest } from "../models/request/iapCheckRequest"; +import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest"; +import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest"; +import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest"; +import { ImportCiphersRequest } from "../models/request/importCiphersRequest"; +import { ImportDirectoryRequest } from "../models/request/importDirectoryRequest"; +import { ImportOrganizationCiphersRequest } from "../models/request/importOrganizationCiphersRequest"; +import { KdfRequest } from "../models/request/kdfRequest"; +import { KeyConnectorUserKeyRequest } from "../models/request/keyConnectorUserKeyRequest"; +import { KeysRequest } from "../models/request/keysRequest"; +import { OrganizationSponsorshipCreateRequest } from "../models/request/organization/organizationSponsorshipCreateRequest"; +import { OrganizationSponsorshipRedeemRequest } from "../models/request/organization/organizationSponsorshipRedeemRequest"; +import { OrganizationSsoRequest } from "../models/request/organization/organizationSsoRequest"; +import { OrganizationApiKeyRequest } from "../models/request/organizationApiKeyRequest"; +import { OrganizationCreateRequest } from "../models/request/organizationCreateRequest"; +import { OrganizationImportRequest } from "../models/request/organizationImportRequest"; +import { OrganizationKeysRequest } from "../models/request/organizationKeysRequest"; +import { OrganizationSubscriptionUpdateRequest } from "../models/request/organizationSubscriptionUpdateRequest"; +import { OrganizationTaxInfoUpdateRequest } from "../models/request/organizationTaxInfoUpdateRequest"; +import { OrganizationUpdateRequest } from "../models/request/organizationUpdateRequest"; +import { OrganizationUpgradeRequest } from "../models/request/organizationUpgradeRequest"; +import { OrganizationUserAcceptRequest } from "../models/request/organizationUserAcceptRequest"; +import { OrganizationUserBulkConfirmRequest } from "../models/request/organizationUserBulkConfirmRequest"; +import { OrganizationUserBulkRequest } from "../models/request/organizationUserBulkRequest"; +import { OrganizationUserConfirmRequest } from "../models/request/organizationUserConfirmRequest"; +import { OrganizationUserInviteRequest } from "../models/request/organizationUserInviteRequest"; +import { OrganizationUserResetPasswordEnrollmentRequest } from "../models/request/organizationUserResetPasswordEnrollmentRequest"; +import { OrganizationUserResetPasswordRequest } from "../models/request/organizationUserResetPasswordRequest"; +import { OrganizationUserUpdateGroupsRequest } from "../models/request/organizationUserUpdateGroupsRequest"; +import { OrganizationUserUpdateRequest } from "../models/request/organizationUserUpdateRequest"; +import { PasswordHintRequest } from "../models/request/passwordHintRequest"; +import { PasswordRequest } from "../models/request/passwordRequest"; +import { PaymentRequest } from "../models/request/paymentRequest"; +import { PolicyRequest } from "../models/request/policyRequest"; +import { PreloginRequest } from "../models/request/preloginRequest"; +import { ProviderAddOrganizationRequest } from "../models/request/provider/providerAddOrganizationRequest"; +import { ProviderOrganizationCreateRequest } from "../models/request/provider/providerOrganizationCreateRequest"; +import { ProviderSetupRequest } from "../models/request/provider/providerSetupRequest"; +import { ProviderUpdateRequest } from "../models/request/provider/providerUpdateRequest"; +import { ProviderUserAcceptRequest } from "../models/request/provider/providerUserAcceptRequest"; +import { ProviderUserBulkConfirmRequest } from "../models/request/provider/providerUserBulkConfirmRequest"; +import { ProviderUserBulkRequest } from "../models/request/provider/providerUserBulkRequest"; +import { ProviderUserConfirmRequest } from "../models/request/provider/providerUserConfirmRequest"; +import { ProviderUserInviteRequest } from "../models/request/provider/providerUserInviteRequest"; +import { ProviderUserUpdateRequest } from "../models/request/provider/providerUserUpdateRequest"; +import { RegisterRequest } from "../models/request/registerRequest"; +import { SeatRequest } from "../models/request/seatRequest"; +import { SecretVerificationRequest } from "../models/request/secretVerificationRequest"; +import { SelectionReadOnlyRequest } from "../models/request/selectionReadOnlyRequest"; +import { SendAccessRequest } from "../models/request/sendAccessRequest"; +import { SendRequest } from "../models/request/sendRequest"; +import { SetPasswordRequest } from "../models/request/setPasswordRequest"; +import { StorageRequest } from "../models/request/storageRequest"; +import { TaxInfoUpdateRequest } from "../models/request/taxInfoUpdateRequest"; +import { TwoFactorEmailRequest } from "../models/request/twoFactorEmailRequest"; +import { TwoFactorProviderRequest } from "../models/request/twoFactorProviderRequest"; +import { TwoFactorRecoveryRequest } from "../models/request/twoFactorRecoveryRequest"; +import { UpdateDomainsRequest } from "../models/request/updateDomainsRequest"; +import { UpdateKeyRequest } from "../models/request/updateKeyRequest"; +import { UpdateProfileRequest } from "../models/request/updateProfileRequest"; +import { UpdateTempPasswordRequest } from "../models/request/updateTempPasswordRequest"; +import { UpdateTwoFactorAuthenticatorRequest } from "../models/request/updateTwoFactorAuthenticatorRequest"; +import { UpdateTwoFactorDuoRequest } from "../models/request/updateTwoFactorDuoRequest"; +import { UpdateTwoFactorEmailRequest } from "../models/request/updateTwoFactorEmailRequest"; +import { UpdateTwoFactorWebAuthnDeleteRequest } from "../models/request/updateTwoFactorWebAuthnDeleteRequest"; +import { UpdateTwoFactorWebAuthnRequest } from "../models/request/updateTwoFactorWebAuthnRequest"; +import { UpdateTwoFactorYubioOtpRequest } from "../models/request/updateTwoFactorYubioOtpRequest"; +import { VerifyBankRequest } from "../models/request/verifyBankRequest"; +import { VerifyDeleteRecoverRequest } from "../models/request/verifyDeleteRecoverRequest"; +import { VerifyEmailRequest } from "../models/request/verifyEmailRequest"; +import { ApiKeyResponse } from "../models/response/apiKeyResponse"; +import { AttachmentResponse } from "../models/response/attachmentResponse"; +import { AttachmentUploadDataResponse } from "../models/response/attachmentUploadDataResponse"; +import { BillingResponse } from "../models/response/billingResponse"; +import { BreachAccountResponse } from "../models/response/breachAccountResponse"; +import { CipherResponse } from "../models/response/cipherResponse"; +import { + CollectionGroupDetailsResponse, + CollectionResponse, +} from "../models/response/collectionResponse"; +import { DomainsResponse } from "../models/response/domainsResponse"; +import { + EmergencyAccessGranteeDetailsResponse, + EmergencyAccessGrantorDetailsResponse, + EmergencyAccessTakeoverResponse, + EmergencyAccessViewResponse, +} from "../models/response/emergencyAccessResponse"; +import { EventResponse } from "../models/response/eventResponse"; +import { FolderResponse } from "../models/response/folderResponse"; +import { GroupDetailsResponse, GroupResponse } from "../models/response/groupResponse"; +import { IdentityCaptchaResponse } from "../models/response/identityCaptchaResponse"; +import { IdentityTokenResponse } from "../models/response/identityTokenResponse"; +import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse"; +import { KeyConnectorUserKeyResponse } from "../models/response/keyConnectorUserKeyResponse"; +import { ListResponse } from "../models/response/listResponse"; +import { OrganizationSsoResponse } from "../models/response/organization/organizationSsoResponse"; +import { OrganizationApiKeyInformationResponse } from "../models/response/organizationApiKeyInformationResponse"; +import { OrganizationAutoEnrollStatusResponse } from "../models/response/organizationAutoEnrollStatusResponse"; +import { OrganizationKeysResponse } from "../models/response/organizationKeysResponse"; +import { OrganizationResponse } from "../models/response/organizationResponse"; +import { OrganizationSponsorshipSyncStatusResponse } from "../models/response/organizationSponsorshipSyncStatusResponse"; +import { OrganizationSubscriptionResponse } from "../models/response/organizationSubscriptionResponse"; +import { OrganizationUserBulkPublicKeyResponse } from "../models/response/organizationUserBulkPublicKeyResponse"; +import { OrganizationUserBulkResponse } from "../models/response/organizationUserBulkResponse"; +import { + OrganizationUserDetailsResponse, + OrganizationUserResetPasswordDetailsReponse, + OrganizationUserUserDetailsResponse, +} from "../models/response/organizationUserResponse"; +import { PaymentResponse } from "../models/response/paymentResponse"; +import { PlanResponse } from "../models/response/planResponse"; +import { PolicyResponse } from "../models/response/policyResponse"; +import { PreloginResponse } from "../models/response/preloginResponse"; +import { ProfileResponse } from "../models/response/profileResponse"; +import { + ProviderOrganizationOrganizationDetailsResponse, + ProviderOrganizationResponse, +} from "../models/response/provider/providerOrganizationResponse"; +import { ProviderResponse } from "../models/response/provider/providerResponse"; +import { ProviderUserBulkPublicKeyResponse } from "../models/response/provider/providerUserBulkPublicKeyResponse"; +import { ProviderUserBulkResponse } from "../models/response/provider/providerUserBulkResponse"; +import { + ProviderUserResponse, + ProviderUserUserDetailsResponse, +} from "../models/response/provider/providerUserResponse"; +import { SelectionReadOnlyResponse } from "../models/response/selectionReadOnlyResponse"; +import { SendAccessResponse } from "../models/response/sendAccessResponse"; +import { SendFileDownloadDataResponse } from "../models/response/sendFileDownloadDataResponse"; +import { SendFileUploadDataResponse } from "../models/response/sendFileUploadDataResponse"; +import { SendResponse } from "../models/response/sendResponse"; +import { SubscriptionResponse } from "../models/response/subscriptionResponse"; +import { SyncResponse } from "../models/response/syncResponse"; +import { TaxInfoResponse } from "../models/response/taxInfoResponse"; +import { TaxRateResponse } from "../models/response/taxRateResponse"; +import { TwoFactorAuthenticatorResponse } from "../models/response/twoFactorAuthenticatorResponse"; +import { TwoFactorDuoResponse } from "../models/response/twoFactorDuoResponse"; +import { TwoFactorEmailResponse } from "../models/response/twoFactorEmailResponse"; +import { TwoFactorProviderResponse } from "../models/response/twoFactorProviderResponse"; +import { TwoFactorRecoverResponse } from "../models/response/twoFactorRescoverResponse"; +import { + ChallengeResponse, + TwoFactorWebAuthnResponse, +} from "../models/response/twoFactorWebAuthnResponse"; +import { TwoFactorYubiKeyResponse } from "../models/response/twoFactorYubiKeyResponse"; +import { UserKeyResponse } from "../models/response/userKeyResponse"; +import { SendAccessView } from "../models/view/sendAccessView"; + +export abstract class ApiService { + postIdentityToken: ( + request: PasswordTokenRequest | SsoTokenRequest | ApiTokenRequest + ) => Promise; + refreshIdentityToken: () => Promise; + + getProfile: () => Promise; + getUserSubscription: () => Promise; + getTaxInfo: () => Promise; + putProfile: (request: UpdateProfileRequest) => Promise; + putTaxInfo: (request: TaxInfoUpdateRequest) => Promise; + postPrelogin: (request: PreloginRequest) => Promise; + postEmailToken: (request: EmailTokenRequest) => Promise; + postEmail: (request: EmailRequest) => Promise; + postPassword: (request: PasswordRequest) => Promise; + setPassword: (request: SetPasswordRequest) => Promise; + postSetKeyConnectorKey: (request: SetKeyConnectorKeyRequest) => Promise; + postSecurityStamp: (request: SecretVerificationRequest) => Promise; + deleteAccount: (request: SecretVerificationRequest) => Promise; + getAccountRevisionDate: () => Promise; + postPasswordHint: (request: PasswordHintRequest) => Promise; + postRegister: (request: RegisterRequest) => Promise; + postPremium: (data: FormData) => Promise; + postIapCheck: (request: IapCheckRequest) => Promise; + postReinstatePremium: () => Promise; + postCancelPremium: () => Promise; + postAccountStorage: (request: StorageRequest) => Promise; + postAccountPayment: (request: PaymentRequest) => Promise; + postAccountLicense: (data: FormData) => Promise; + postAccountKey: (request: UpdateKeyRequest) => Promise; + postAccountKeys: (request: KeysRequest) => Promise; + postAccountVerifyEmail: () => Promise; + postAccountVerifyEmailToken: (request: VerifyEmailRequest) => Promise; + postAccountVerifyPassword: (request: SecretVerificationRequest) => Promise; + postAccountRecoverDelete: (request: DeleteRecoverRequest) => Promise; + postAccountRecoverDeleteToken: (request: VerifyDeleteRecoverRequest) => Promise; + postAccountKdf: (request: KdfRequest) => Promise; + postUserApiKey: (id: string, request: SecretVerificationRequest) => Promise; + postUserRotateApiKey: (id: string, request: SecretVerificationRequest) => Promise; + putUpdateTempPassword: (request: UpdateTempPasswordRequest) => Promise; + postAccountRequestOTP: () => Promise; + postAccountVerifyOTP: (request: VerifyOTPRequest) => Promise; + postConvertToKeyConnector: () => Promise; + + getUserBillingHistory: () => Promise; + getUserBillingPayment: () => Promise; + + getFolder: (id: string) => Promise; + postFolder: (request: FolderRequest) => Promise; + putFolder: (id: string, request: FolderRequest) => Promise; + deleteFolder: (id: string) => Promise; + + getSend: (id: string) => Promise; + postSendAccess: ( + id: string, + request: SendAccessRequest, + apiUrl?: string + ) => Promise; + getSends: () => Promise>; + postSend: (request: SendRequest) => Promise; + postFileTypeSend: (request: SendRequest) => Promise; + postSendFile: (sendId: string, fileId: string, data: FormData) => Promise; + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + postSendFileLegacy: (data: FormData) => Promise; + putSend: (id: string, request: SendRequest) => Promise; + putSendRemovePassword: (id: string) => Promise; + deleteSend: (id: string) => Promise; + getSendFileDownloadData: ( + send: SendAccessView, + request: SendAccessRequest, + apiUrl?: string + ) => Promise; + renewSendFileUploadUrl: (sendId: string, fileId: string) => Promise; + + getCipher: (id: string) => Promise; + getCipherAdmin: (id: string) => Promise; + getAttachmentData: ( + cipherId: string, + attachmentId: string, + emergencyAccessId?: string + ) => Promise; + getCiphersOrganization: (organizationId: string) => Promise>; + postCipher: (request: CipherRequest) => Promise; + postCipherCreate: (request: CipherCreateRequest) => Promise; + postCipherAdmin: (request: CipherCreateRequest) => Promise; + putCipher: (id: string, request: CipherRequest) => Promise; + putCipherAdmin: (id: string, request: CipherRequest) => Promise; + deleteCipher: (id: string) => Promise; + deleteCipherAdmin: (id: string) => Promise; + deleteManyCiphers: (request: CipherBulkDeleteRequest) => Promise; + deleteManyCiphersAdmin: (request: CipherBulkDeleteRequest) => Promise; + putMoveCiphers: (request: CipherBulkMoveRequest) => Promise; + putShareCipher: (id: string, request: CipherShareRequest) => Promise; + putShareCiphers: (request: CipherBulkShareRequest) => Promise; + putCipherCollections: (id: string, request: CipherCollectionsRequest) => Promise; + putCipherCollectionsAdmin: (id: string, request: CipherCollectionsRequest) => Promise; + postPurgeCiphers: (request: SecretVerificationRequest, organizationId?: string) => Promise; + postImportCiphers: (request: ImportCiphersRequest) => Promise; + postImportOrganizationCiphers: ( + organizationId: string, + request: ImportOrganizationCiphersRequest + ) => Promise; + putDeleteCipher: (id: string) => Promise; + putDeleteCipherAdmin: (id: string) => Promise; + putDeleteManyCiphers: (request: CipherBulkDeleteRequest) => Promise; + putDeleteManyCiphersAdmin: (request: CipherBulkDeleteRequest) => Promise; + putRestoreCipher: (id: string) => Promise; + putRestoreCipherAdmin: (id: string) => Promise; + putRestoreManyCiphers: ( + request: CipherBulkRestoreRequest + ) => Promise>; + + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + postCipherAttachmentLegacy: (id: string, data: FormData) => Promise; + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + postCipherAttachmentAdminLegacy: (id: string, data: FormData) => Promise; + postCipherAttachment: ( + id: string, + request: AttachmentRequest + ) => Promise; + deleteCipherAttachment: (id: string, attachmentId: string) => Promise; + deleteCipherAttachmentAdmin: (id: string, attachmentId: string) => Promise; + postShareCipherAttachment: ( + id: string, + attachmentId: string, + data: FormData, + organizationId: string + ) => Promise; + renewAttachmentUploadUrl: ( + id: string, + attachmentId: string + ) => Promise; + postAttachmentFile: (id: string, attachmentId: string, data: FormData) => Promise; + + getCollectionDetails: ( + organizationId: string, + id: string + ) => Promise; + getUserCollections: () => Promise>; + getCollections: (organizationId: string) => Promise>; + getCollectionUsers: (organizationId: string, id: string) => Promise; + postCollection: ( + organizationId: string, + request: CollectionRequest + ) => Promise; + putCollectionUsers: ( + organizationId: string, + id: string, + request: SelectionReadOnlyRequest[] + ) => Promise; + putCollection: ( + organizationId: string, + id: string, + request: CollectionRequest + ) => Promise; + deleteCollection: (organizationId: string, id: string) => Promise; + deleteCollectionUser: ( + organizationId: string, + id: string, + organizationUserId: string + ) => Promise; + + getGroupDetails: (organizationId: string, id: string) => Promise; + getGroups: (organizationId: string) => Promise>; + getGroupUsers: (organizationId: string, id: string) => Promise; + postGroup: (organizationId: string, request: GroupRequest) => Promise; + putGroup: (organizationId: string, id: string, request: GroupRequest) => Promise; + putGroupUsers: (organizationId: string, id: string, request: string[]) => Promise; + deleteGroup: (organizationId: string, id: string) => Promise; + deleteGroupUser: (organizationId: string, id: string, organizationUserId: string) => Promise; + + getPolicy: (organizationId: string, type: PolicyType) => Promise; + getPolicies: (organizationId: string) => Promise>; + getPoliciesByToken: ( + organizationId: string, + token: string, + email: string, + organizationUserId: string + ) => Promise>; + getPoliciesByInvitedUser: ( + organizationId: string, + userId: string + ) => Promise>; + putPolicy: ( + organizationId: string, + type: PolicyType, + request: PolicyRequest + ) => Promise; + + getOrganizationUser: ( + organizationId: string, + id: string + ) => Promise; + getOrganizationUserGroups: (organizationId: string, id: string) => Promise; + getOrganizationUsers: ( + organizationId: string + ) => Promise>; + getOrganizationUserResetPasswordDetails: ( + organizationId: string, + id: string + ) => Promise; + postOrganizationUserInvite: ( + organizationId: string, + request: OrganizationUserInviteRequest + ) => Promise; + postOrganizationUserReinvite: (organizationId: string, id: string) => Promise; + postManyOrganizationUserReinvite: ( + organizationId: string, + request: OrganizationUserBulkRequest + ) => Promise>; + postOrganizationUserAccept: ( + organizationId: string, + id: string, + request: OrganizationUserAcceptRequest + ) => Promise; + postOrganizationUserConfirm: ( + organizationId: string, + id: string, + request: OrganizationUserConfirmRequest + ) => Promise; + postOrganizationUsersPublicKey: ( + organizationId: string, + request: OrganizationUserBulkRequest + ) => Promise>; + postOrganizationUserBulkConfirm: ( + organizationId: string, + request: OrganizationUserBulkConfirmRequest + ) => Promise>; + + putOrganizationUser: ( + organizationId: string, + id: string, + request: OrganizationUserUpdateRequest + ) => Promise; + putOrganizationUserGroups: ( + organizationId: string, + id: string, + request: OrganizationUserUpdateGroupsRequest + ) => Promise; + putOrganizationUserResetPasswordEnrollment: ( + organizationId: string, + userId: string, + request: OrganizationUserResetPasswordEnrollmentRequest + ) => Promise; + putOrganizationUserResetPassword: ( + organizationId: string, + id: string, + request: OrganizationUserResetPasswordRequest + ) => Promise; + deleteOrganizationUser: (organizationId: string, id: string) => Promise; + deleteManyOrganizationUsers: ( + organizationId: string, + request: OrganizationUserBulkRequest + ) => Promise>; + + getSync: () => Promise; + postImportDirectory: (organizationId: string, request: ImportDirectoryRequest) => Promise; + postPublicImportDirectory: (request: OrganizationImportRequest) => Promise; + + getSettingsDomains: () => Promise; + putSettingsDomains: (request: UpdateDomainsRequest) => Promise; + + getTwoFactorProviders: () => Promise>; + getTwoFactorOrganizationProviders: ( + organizationId: string + ) => Promise>; + getTwoFactorAuthenticator: ( + request: SecretVerificationRequest + ) => Promise; + getTwoFactorEmail: (request: SecretVerificationRequest) => Promise; + getTwoFactorDuo: (request: SecretVerificationRequest) => Promise; + getTwoFactorOrganizationDuo: ( + organizationId: string, + request: SecretVerificationRequest + ) => Promise; + getTwoFactorYubiKey: (request: SecretVerificationRequest) => Promise; + getTwoFactorWebAuthn: (request: SecretVerificationRequest) => Promise; + getTwoFactorWebAuthnChallenge: (request: SecretVerificationRequest) => Promise; + getTwoFactorRecover: (request: SecretVerificationRequest) => Promise; + putTwoFactorAuthenticator: ( + request: UpdateTwoFactorAuthenticatorRequest + ) => Promise; + putTwoFactorEmail: (request: UpdateTwoFactorEmailRequest) => Promise; + putTwoFactorDuo: (request: UpdateTwoFactorDuoRequest) => Promise; + putTwoFactorOrganizationDuo: ( + organizationId: string, + request: UpdateTwoFactorDuoRequest + ) => Promise; + putTwoFactorYubiKey: ( + request: UpdateTwoFactorYubioOtpRequest + ) => Promise; + putTwoFactorWebAuthn: ( + request: UpdateTwoFactorWebAuthnRequest + ) => Promise; + deleteTwoFactorWebAuthn: ( + request: UpdateTwoFactorWebAuthnDeleteRequest + ) => Promise; + putTwoFactorDisable: (request: TwoFactorProviderRequest) => Promise; + putTwoFactorOrganizationDisable: ( + organizationId: string, + request: TwoFactorProviderRequest + ) => Promise; + postTwoFactorRecover: (request: TwoFactorRecoveryRequest) => Promise; + postTwoFactorEmailSetup: (request: TwoFactorEmailRequest) => Promise; + postTwoFactorEmail: (request: TwoFactorEmailRequest) => Promise; + + getEmergencyAccessTrusted: () => Promise>; + getEmergencyAccessGranted: () => Promise>; + getEmergencyAccess: (id: string) => Promise; + getEmergencyGrantorPolicies: (id: string) => Promise>; + putEmergencyAccess: (id: string, request: EmergencyAccessUpdateRequest) => Promise; + deleteEmergencyAccess: (id: string) => Promise; + postEmergencyAccessInvite: (request: EmergencyAccessInviteRequest) => Promise; + postEmergencyAccessReinvite: (id: string) => Promise; + postEmergencyAccessAccept: (id: string, request: EmergencyAccessAcceptRequest) => Promise; + postEmergencyAccessConfirm: (id: string, request: EmergencyAccessConfirmRequest) => Promise; + postEmergencyAccessInitiate: (id: string) => Promise; + postEmergencyAccessApprove: (id: string) => Promise; + postEmergencyAccessReject: (id: string) => Promise; + postEmergencyAccessTakeover: (id: string) => Promise; + postEmergencyAccessPassword: ( + id: string, + request: EmergencyAccessPasswordRequest + ) => Promise; + postEmergencyAccessView: (id: string) => Promise; + + getOrganization: (id: string) => Promise; + getOrganizationBilling: (id: string) => Promise; + getOrganizationSubscription: (id: string) => Promise; + getCloudCommunicationsEnabled: () => Promise; + abstract getOrganizationConnection( + id: string, + type: OrganizationConnectionType, + configType: { new (response: any): TConfig } + ): Promise>; + abstract createOrganizationConnection( + request: OrganizationConnectionRequest, + configType: { new (response: any): TConfig } + ): Promise>; + abstract updateOrganizationConnection( + request: OrganizationConnectionRequest, + configType: { new (response: any): TConfig }, + organizationConnectionId: string + ): Promise>; + deleteOrganizationConnection: (id: string) => Promise; + getOrganizationLicense: (id: string, installationId: string) => Promise; + getOrganizationTaxInfo: (id: string) => Promise; + getOrganizationAutoEnrollStatus: ( + identifier: string + ) => Promise; + getOrganizationSso: (id: string) => Promise; + postOrganization: (request: OrganizationCreateRequest) => Promise; + putOrganization: ( + id: string, + request: OrganizationUpdateRequest + ) => Promise; + putOrganizationTaxInfo: (id: string, request: OrganizationTaxInfoUpdateRequest) => Promise; + postLeaveOrganization: (id: string) => Promise; + postOrganizationLicense: (data: FormData) => Promise; + postOrganizationLicenseUpdate: (id: string, data: FormData) => Promise; + postOrganizationApiKey: ( + id: string, + request: OrganizationApiKeyRequest + ) => Promise; + getOrganizationApiKeyInformation: ( + id: string + ) => Promise>; + postOrganizationRotateApiKey: ( + id: string, + request: OrganizationApiKeyRequest + ) => Promise; + postOrganizationSso: ( + id: string, + request: OrganizationSsoRequest + ) => Promise; + postOrganizationUpgrade: ( + id: string, + request: OrganizationUpgradeRequest + ) => Promise; + postOrganizationUpdateSubscription: ( + id: string, + request: OrganizationSubscriptionUpdateRequest + ) => Promise; + postOrganizationSeat: (id: string, request: SeatRequest) => Promise; + postOrganizationStorage: (id: string, request: StorageRequest) => Promise; + postOrganizationPayment: (id: string, request: PaymentRequest) => Promise; + postOrganizationVerifyBank: (id: string, request: VerifyBankRequest) => Promise; + postOrganizationCancel: (id: string) => Promise; + postOrganizationReinstate: (id: string) => Promise; + deleteOrganization: (id: string, request: SecretVerificationRequest) => Promise; + getPlans: () => Promise>; + getTaxRates: () => Promise>; + getOrganizationKeys: (id: string) => Promise; + postOrganizationKeys: ( + id: string, + request: OrganizationKeysRequest + ) => Promise; + + postProviderSetup: (id: string, request: ProviderSetupRequest) => Promise; + getProvider: (id: string) => Promise; + putProvider: (id: string, request: ProviderUpdateRequest) => Promise; + + getProviderUsers: (providerId: string) => Promise>; + getProviderUser: (providerId: string, id: string) => Promise; + postProviderUserInvite: (providerId: string, request: ProviderUserInviteRequest) => Promise; + postProviderUserReinvite: (providerId: string, id: string) => Promise; + postManyProviderUserReinvite: ( + providerId: string, + request: ProviderUserBulkRequest + ) => Promise>; + postProviderUserAccept: ( + providerId: string, + id: string, + request: ProviderUserAcceptRequest + ) => Promise; + postProviderUserConfirm: ( + providerId: string, + id: string, + request: ProviderUserConfirmRequest + ) => Promise; + postProviderUsersPublicKey: ( + providerId: string, + request: ProviderUserBulkRequest + ) => Promise>; + postProviderUserBulkConfirm: ( + providerId: string, + request: ProviderUserBulkConfirmRequest + ) => Promise>; + putProviderUser: ( + providerId: string, + id: string, + request: ProviderUserUpdateRequest + ) => Promise; + deleteProviderUser: (organizationId: string, id: string) => Promise; + deleteManyProviderUsers: ( + providerId: string, + request: ProviderUserBulkRequest + ) => Promise>; + getProviderClients: ( + providerId: string + ) => Promise>; + postProviderAddOrganization: ( + providerId: string, + request: ProviderAddOrganizationRequest + ) => Promise; + postProviderCreateOrganization: ( + providerId: string, + request: ProviderOrganizationCreateRequest + ) => Promise; + deleteProviderOrganization: (providerId: string, organizationId: string) => Promise; + + getEvents: (start: string, end: string, token: string) => Promise>; + getEventsCipher: ( + id: string, + start: string, + end: string, + token: string + ) => Promise>; + getEventsOrganization: ( + id: string, + start: string, + end: string, + token: string + ) => Promise>; + getEventsOrganizationUser: ( + organizationId: string, + id: string, + start: string, + end: string, + token: string + ) => Promise>; + getEventsProvider: ( + id: string, + start: string, + end: string, + token: string + ) => Promise>; + getEventsProviderUser: ( + providerId: string, + id: string, + start: string, + end: string, + token: string + ) => Promise>; + postEventsCollect: (request: EventRequest[]) => Promise; + + deleteSsoUser: (organizationId: string) => Promise; + getSsoUserIdentifier: () => Promise; + + getUserPublicKey: (id: string) => Promise; + + getHibpBreach: (username: string) => Promise; + + postBitPayInvoice: (request: BitPayInvoiceRequest) => Promise; + postSetupPayment: () => Promise; + + getActiveBearerToken: () => Promise; + fetch: (request: Request) => Promise; + nativeFetch: (request: Request) => Promise; + + preValidateSso: (identifier: string) => Promise; + + postCreateSponsorship: ( + sponsorshipOrgId: string, + request: OrganizationSponsorshipCreateRequest + ) => Promise; + getSponsorshipSyncStatus: ( + sponsoredOrgId: string + ) => Promise; + deleteRevokeSponsorship: (sponsoringOrganizationId: string) => Promise; + deleteRemoveSponsorship: (sponsoringOrgId: string) => Promise; + postPreValidateSponsorshipToken: (sponsorshipToken: string) => Promise; + postRedeemSponsorship: ( + sponsorshipToken: string, + request: OrganizationSponsorshipRedeemRequest + ) => Promise; + postResendSponsorshipOffer: (sponsoringOrgId: string) => Promise; + + getUserKeyFromKeyConnector: (keyConnectorUrl: string) => Promise; + postUserKeyToKeyConnector: ( + keyConnectorUrl: string, + request: KeyConnectorUserKeyRequest + ) => Promise; + getKeyConnectorAlive: (keyConnectorUrl: string) => Promise; +} diff --git a/libs/common/src/abstractions/appId.service.ts b/libs/common/src/abstractions/appId.service.ts new file mode 100644 index 0000000000..99bc6c9eae --- /dev/null +++ b/libs/common/src/abstractions/appId.service.ts @@ -0,0 +1,4 @@ +export abstract class AppIdService { + getAppId: () => Promise; + getAnonymousAppId: () => Promise; +} diff --git a/libs/common/src/abstractions/audit.service.ts b/libs/common/src/abstractions/audit.service.ts new file mode 100644 index 0000000000..6b6b81f69e --- /dev/null +++ b/libs/common/src/abstractions/audit.service.ts @@ -0,0 +1,6 @@ +import { BreachAccountResponse } from "../models/response/breachAccountResponse"; + +export abstract class AuditService { + passwordLeaked: (password: string) => Promise; + breachedAccounts: (username: string) => Promise; +} diff --git a/libs/common/src/abstractions/auth.service.ts b/libs/common/src/abstractions/auth.service.ts new file mode 100644 index 0000000000..4947f21708 --- /dev/null +++ b/libs/common/src/abstractions/auth.service.ts @@ -0,0 +1,27 @@ +import { AuthenticationStatus } from "../enums/authenticationStatus"; +import { AuthResult } from "../models/domain/authResult"; +import { + ApiLogInCredentials, + PasswordLogInCredentials, + SsoLogInCredentials, +} from "../models/domain/logInCredentials"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { TokenRequestTwoFactor } from "../models/request/identityToken/tokenRequestTwoFactor"; + +export abstract class AuthService { + masterPasswordHash: string; + email: string; + logIn: ( + credentials: ApiLogInCredentials | PasswordLogInCredentials | SsoLogInCredentials + ) => Promise; + logInTwoFactor: ( + twoFactor: TokenRequestTwoFactor, + captchaResponse: string + ) => Promise; + logOut: (callback: () => void) => void; + makePreloginKey: (masterPassword: string, email: string) => Promise; + authingWithApiKey: () => boolean; + authingWithSso: () => boolean; + authingWithPassword: () => boolean; + getAuthStatus: (userId?: string) => Promise; +} diff --git a/libs/common/src/abstractions/broadcaster.service.ts b/libs/common/src/abstractions/broadcaster.service.ts new file mode 100644 index 0000000000..1b9d0899ef --- /dev/null +++ b/libs/common/src/abstractions/broadcaster.service.ts @@ -0,0 +1,5 @@ +export abstract class BroadcasterService { + send: (message: any, id?: string) => void; + subscribe: (id: string, messageCallback: (message: any) => any) => void; + unsubscribe: (id: string) => void; +} diff --git a/libs/common/src/abstractions/cipher.service.ts b/libs/common/src/abstractions/cipher.service.ts new file mode 100644 index 0000000000..a87a6f0a1f --- /dev/null +++ b/libs/common/src/abstractions/cipher.service.ts @@ -0,0 +1,79 @@ +import { CipherType } from "../enums/cipherType"; +import { UriMatchType } from "../enums/uriMatchType"; +import { CipherData } from "../models/data/cipherData"; +import { Cipher } from "../models/domain/cipher"; +import { Field } from "../models/domain/field"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { CipherView } from "../models/view/cipherView"; +import { FieldView } from "../models/view/fieldView"; + +export abstract class CipherService { + clearCache: (userId?: string) => Promise; + encrypt: ( + model: CipherView, + key?: SymmetricCryptoKey, + originalCipher?: Cipher + ) => Promise; + encryptFields: (fieldsModel: FieldView[], key: SymmetricCryptoKey) => Promise; + encryptField: (fieldModel: FieldView, key: SymmetricCryptoKey) => Promise; + get: (id: string) => Promise; + getAll: () => Promise; + getAllDecrypted: () => Promise; + getAllDecryptedForGrouping: (groupingId: string, folder?: boolean) => Promise; + getAllDecryptedForUrl: ( + url: string, + includeOtherTypes?: CipherType[], + defaultMatch?: UriMatchType + ) => Promise; + getAllFromApiForOrganization: (organizationId: string) => Promise; + getLastUsedForUrl: (url: string, autofillOnPageLoad: boolean) => Promise; + getLastLaunchedForUrl: (url: string, autofillOnPageLoad: boolean) => Promise; + getNextCipherForUrl: (url: string) => Promise; + updateLastUsedIndexForUrl: (url: string) => void; + updateLastUsedDate: (id: string) => Promise; + updateLastLaunchedDate: (id: string) => Promise; + saveNeverDomain: (domain: string) => Promise; + saveWithServer: (cipher: Cipher) => Promise; + shareWithServer: ( + cipher: CipherView, + organizationId: string, + collectionIds: string[] + ) => Promise; + shareManyWithServer: ( + ciphers: CipherView[], + organizationId: string, + collectionIds: string[] + ) => Promise; + saveAttachmentWithServer: ( + cipher: Cipher, + unencryptedFile: any, + admin?: boolean + ) => Promise; + saveAttachmentRawWithServer: ( + cipher: Cipher, + filename: string, + data: ArrayBuffer, + admin?: boolean + ) => Promise; + saveCollectionsWithServer: (cipher: Cipher) => Promise; + upsert: (cipher: CipherData | CipherData[]) => Promise; + replace: (ciphers: { [id: string]: CipherData }) => Promise; + clear: (userId: string) => Promise; + moveManyWithServer: (ids: string[], folderId: string) => Promise; + delete: (id: string | string[]) => Promise; + deleteWithServer: (id: string) => Promise; + deleteManyWithServer: (ids: string[]) => Promise; + deleteAttachment: (id: string, attachmentId: string) => Promise; + deleteAttachmentWithServer: (id: string, attachmentId: string) => Promise; + sortCiphersByLastUsed: (a: any, b: any) => number; + sortCiphersByLastUsedThenName: (a: any, b: any) => number; + getLocaleSortingFunction: () => (a: CipherView, b: CipherView) => number; + softDelete: (id: string | string[]) => Promise; + softDeleteWithServer: (id: string) => Promise; + softDeleteManyWithServer: (ids: string[]) => Promise; + restore: ( + cipher: { id: string; revisionDate: string } | { id: string; revisionDate: string }[] + ) => Promise; + restoreWithServer: (id: string) => Promise; + restoreManyWithServer: (ids: string[]) => Promise; +} diff --git a/libs/common/src/abstractions/collection.service.ts b/libs/common/src/abstractions/collection.service.ts new file mode 100644 index 0000000000..0673e9066b --- /dev/null +++ b/libs/common/src/abstractions/collection.service.ts @@ -0,0 +1,19 @@ +import { CollectionData } from "../models/data/collectionData"; +import { Collection } from "../models/domain/collection"; +import { TreeNode } from "../models/domain/treeNode"; +import { CollectionView } from "../models/view/collectionView"; + +export abstract class CollectionService { + clearCache: (userId?: string) => Promise; + encrypt: (model: CollectionView) => Promise; + decryptMany: (collections: Collection[]) => Promise; + get: (id: string) => Promise; + getAll: () => Promise; + getAllDecrypted: () => Promise; + getAllNested: (collections?: CollectionView[]) => Promise[]>; + getNested: (id: string) => Promise>; + upsert: (collection: CollectionData | CollectionData[]) => Promise; + replace: (collections: { [id: string]: CollectionData }) => Promise; + clear: (userId: string) => Promise; + delete: (id: string | string[]) => Promise; +} diff --git a/libs/common/src/abstractions/crypto.service.ts b/libs/common/src/abstractions/crypto.service.ts new file mode 100644 index 0000000000..bc61ba7e19 --- /dev/null +++ b/libs/common/src/abstractions/crypto.service.ts @@ -0,0 +1,86 @@ +import { HashPurpose } from "../enums/hashPurpose"; +import { KdfType } from "../enums/kdfType"; +import { KeySuffixOptions } from "../enums/keySuffixOptions"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; +import { EncString } from "../models/domain/encString"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { ProfileOrganizationResponse } from "../models/response/profileOrganizationResponse"; +import { ProfileProviderOrganizationResponse } from "../models/response/profileProviderOrganizationResponse"; +import { ProfileProviderResponse } from "../models/response/profileProviderResponse"; + +export abstract class CryptoService { + setKey: (key: SymmetricCryptoKey) => Promise; + setKeyHash: (keyHash: string) => Promise; + setEncKey: (encKey: string) => Promise; + setEncPrivateKey: (encPrivateKey: string) => Promise; + setOrgKeys: ( + orgs: ProfileOrganizationResponse[], + providerOrgs: ProfileProviderOrganizationResponse[] + ) => Promise; + setProviderKeys: (orgs: ProfileProviderResponse[]) => Promise; + getKey: (keySuffix?: KeySuffixOptions, userId?: string) => Promise; + getKeyFromStorage: (keySuffix: KeySuffixOptions, userId?: string) => Promise; + getKeyHash: () => Promise; + compareAndUpdateKeyHash: (masterPassword: string, key: SymmetricCryptoKey) => Promise; + getEncKey: (key?: SymmetricCryptoKey) => Promise; + getPublicKey: () => Promise; + getPrivateKey: () => Promise; + getFingerprint: (userId: string, publicKey?: ArrayBuffer) => Promise; + getOrgKeys: () => Promise>; + getOrgKey: (orgId: string) => Promise; + getProviderKey: (providerId: string) => Promise; + hasKey: () => Promise; + hasKeyInMemory: (userId?: string) => Promise; + hasKeyStored: (keySuffix?: KeySuffixOptions, userId?: string) => Promise; + hasEncKey: () => Promise; + clearKey: (clearSecretStorage?: boolean, userId?: string) => Promise; + clearKeyHash: () => Promise; + clearEncKey: (memoryOnly?: boolean, userId?: string) => Promise; + clearKeyPair: (memoryOnly?: boolean, userId?: string) => Promise; + clearOrgKeys: (memoryOnly?: boolean, userId?: string) => Promise; + clearProviderKeys: (memoryOnly?: boolean) => Promise; + clearPinProtectedKey: () => Promise; + clearKeys: (userId?: string) => Promise; + toggleKey: () => Promise; + makeKey: ( + password: string, + salt: string, + kdf: KdfType, + kdfIterations: number + ) => Promise; + makeKeyFromPin: ( + pin: string, + salt: string, + kdf: KdfType, + kdfIterations: number, + protectedKeyCs?: EncString + ) => Promise; + makeShareKey: () => Promise<[EncString, SymmetricCryptoKey]>; + makeKeyPair: (key?: SymmetricCryptoKey) => Promise<[string, EncString]>; + makePinKey: ( + pin: string, + salt: string, + kdf: KdfType, + kdfIterations: number + ) => Promise; + makeSendKey: (keyMaterial: ArrayBuffer) => Promise; + hashPassword: ( + password: string, + key: SymmetricCryptoKey, + hashPurpose?: HashPurpose + ) => Promise; + makeEncKey: (key: SymmetricCryptoKey) => Promise<[SymmetricCryptoKey, EncString]>; + remakeEncKey: ( + key: SymmetricCryptoKey, + encKey?: SymmetricCryptoKey + ) => Promise<[SymmetricCryptoKey, EncString]>; + encrypt: (plainValue: string | ArrayBuffer, key?: SymmetricCryptoKey) => Promise; + encryptToBytes: (plainValue: ArrayBuffer, key?: SymmetricCryptoKey) => Promise; + rsaEncrypt: (data: ArrayBuffer, publicKey?: ArrayBuffer) => Promise; + rsaDecrypt: (encValue: string, privateKeyValue?: ArrayBuffer) => Promise; + decryptToBytes: (encString: EncString, key?: SymmetricCryptoKey) => Promise; + decryptToUtf8: (encString: EncString, key?: SymmetricCryptoKey) => Promise; + decryptFromBytes: (encBuf: ArrayBuffer, key: SymmetricCryptoKey) => Promise; + randomNumber: (min: number, max: number) => Promise; + validateKey: (key: SymmetricCryptoKey) => Promise; +} diff --git a/libs/common/src/abstractions/cryptoFunction.service.ts b/libs/common/src/abstractions/cryptoFunction.service.ts new file mode 100644 index 0000000000..21ed33cbe8 --- /dev/null +++ b/libs/common/src/abstractions/cryptoFunction.service.ts @@ -0,0 +1,62 @@ +import { DecryptParameters } from "../models/domain/decryptParameters"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; + +export abstract class CryptoFunctionService { + pbkdf2: ( + password: string | ArrayBuffer, + salt: string | ArrayBuffer, + algorithm: "sha256" | "sha512", + iterations: number + ) => Promise; + hkdf: ( + ikm: ArrayBuffer, + salt: string | ArrayBuffer, + info: string | ArrayBuffer, + outputByteSize: number, + algorithm: "sha256" | "sha512" + ) => Promise; + hkdfExpand: ( + prk: ArrayBuffer, + info: string | ArrayBuffer, + outputByteSize: number, + algorithm: "sha256" | "sha512" + ) => Promise; + hash: ( + value: string | ArrayBuffer, + algorithm: "sha1" | "sha256" | "sha512" | "md5" + ) => Promise; + hmac: ( + value: ArrayBuffer, + key: ArrayBuffer, + algorithm: "sha1" | "sha256" | "sha512" + ) => Promise; + compare: (a: ArrayBuffer, b: ArrayBuffer) => Promise; + hmacFast: ( + value: ArrayBuffer | string, + key: ArrayBuffer | string, + algorithm: "sha1" | "sha256" | "sha512" + ) => Promise; + compareFast: (a: ArrayBuffer | string, b: ArrayBuffer | string) => Promise; + aesEncrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise; + aesDecryptFastParameters: ( + data: string, + iv: string, + mac: string, + key: SymmetricCryptoKey + ) => DecryptParameters; + aesDecryptFast: (parameters: DecryptParameters) => Promise; + aesDecrypt: (data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer) => Promise; + rsaEncrypt: ( + data: ArrayBuffer, + publicKey: ArrayBuffer, + algorithm: "sha1" | "sha256" + ) => Promise; + rsaDecrypt: ( + data: ArrayBuffer, + privateKey: ArrayBuffer, + algorithm: "sha1" | "sha256" + ) => Promise; + rsaExtractPublicKey: (privateKey: ArrayBuffer) => Promise; + rsaGenerateKeyPair: (length: 1024 | 2048 | 4096) => Promise<[ArrayBuffer, ArrayBuffer]>; + randomBytes: (length: number) => Promise; +} diff --git a/libs/common/src/abstractions/environment.service.ts b/libs/common/src/abstractions/environment.service.ts new file mode 100644 index 0000000000..8398b4c634 --- /dev/null +++ b/libs/common/src/abstractions/environment.service.ts @@ -0,0 +1,34 @@ +import { Observable } from "rxjs"; + +export type Urls = { + base?: string; + webVault?: string; + api?: string; + identity?: string; + icons?: string; + notifications?: string; + events?: string; + keyConnector?: string; +}; + +export type PayPalConfig = { + businessId?: string; + buttonAction?: string; +}; + +export abstract class EnvironmentService { + urls: Observable; + + hasBaseUrl: () => boolean; + getNotificationsUrl: () => string; + getWebVaultUrl: () => string; + getSendUrl: () => string; + getIconsUrl: () => string; + getApiUrl: () => string; + getIdentityUrl: () => string; + getEventsUrl: () => string; + getKeyConnectorUrl: () => string; + setUrlsFromStorage: () => Promise; + setUrls: (urls: Urls) => Promise; + getUrls: () => Urls; +} diff --git a/libs/common/src/abstractions/event.service.ts b/libs/common/src/abstractions/event.service.ts new file mode 100644 index 0000000000..2f7660fb51 --- /dev/null +++ b/libs/common/src/abstractions/event.service.ts @@ -0,0 +1,7 @@ +import { EventType } from "../enums/eventType"; + +export abstract class EventService { + collect: (eventType: EventType, cipherId?: string, uploadImmediately?: boolean) => Promise; + uploadEvents: (userId?: string) => Promise; + clearEvents: (userId?: string) => Promise; +} diff --git a/libs/common/src/abstractions/export.service.ts b/libs/common/src/abstractions/export.service.ts new file mode 100644 index 0000000000..b0266530bd --- /dev/null +++ b/libs/common/src/abstractions/export.service.ts @@ -0,0 +1,11 @@ +import { EventView } from "../models/view/eventView"; + +export type ExportFormat = "csv" | "json" | "encrypted_json"; + +export abstract class ExportService { + getExport: (format?: ExportFormat, organizationId?: string) => Promise; + getPasswordProtectedExport: (password: string, organizationId?: string) => Promise; + getOrganizationExport: (organizationId: string, format?: ExportFormat) => Promise; + getEventExport: (events: EventView[]) => Promise; + getFileName: (prefix?: string, extension?: string) => string; +} diff --git a/libs/common/src/abstractions/fileUpload.service.ts b/libs/common/src/abstractions/fileUpload.service.ts new file mode 100644 index 0000000000..fcd3c22c72 --- /dev/null +++ b/libs/common/src/abstractions/fileUpload.service.ts @@ -0,0 +1,18 @@ +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; +import { EncString } from "../models/domain/encString"; +import { AttachmentUploadDataResponse } from "../models/response/attachmentUploadDataResponse"; +import { SendFileUploadDataResponse } from "../models/response/sendFileUploadDataResponse"; + +export abstract class FileUploadService { + uploadSendFile: ( + uploadData: SendFileUploadDataResponse, + fileName: EncString, + encryptedFileData: EncArrayBuffer + ) => Promise; + uploadCipherAttachment: ( + admin: boolean, + uploadData: AttachmentUploadDataResponse, + fileName: EncString, + encryptedFileData: EncArrayBuffer + ) => Promise; +} diff --git a/libs/common/src/abstractions/folder.service.ts b/libs/common/src/abstractions/folder.service.ts new file mode 100644 index 0000000000..f848de9092 --- /dev/null +++ b/libs/common/src/abstractions/folder.service.ts @@ -0,0 +1,21 @@ +import { FolderData } from "../models/data/folderData"; +import { Folder } from "../models/domain/folder"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { TreeNode } from "../models/domain/treeNode"; +import { FolderView } from "../models/view/folderView"; + +export abstract class FolderService { + clearCache: (userId?: string) => Promise; + encrypt: (model: FolderView, key?: SymmetricCryptoKey) => Promise; + get: (id: string) => Promise; + getAll: () => Promise; + getAllDecrypted: () => Promise; + getAllNested: (folders?: FolderView[]) => Promise[]>; + getNested: (id: string) => Promise>; + saveWithServer: (folder: Folder) => Promise; + upsert: (folder: FolderData | FolderData[]) => Promise; + replace: (folders: { [id: string]: FolderData }) => Promise; + clear: (userId: string) => Promise; + delete: (id: string | string[]) => Promise; + deleteWithServer: (id: string) => Promise; +} diff --git a/libs/common/src/abstractions/i18n.service.ts b/libs/common/src/abstractions/i18n.service.ts new file mode 100644 index 0000000000..4706e0d1aa --- /dev/null +++ b/libs/common/src/abstractions/i18n.service.ts @@ -0,0 +1,9 @@ +export abstract class I18nService { + locale: string; + supportedTranslationLocales: string[]; + translationLocale: string; + collator: Intl.Collator; + localeNames: Map; + t: (id: string, p1?: string, p2?: string, p3?: string) => string; + translate: (id: string, p1?: string, p2?: string, p3?: string) => string; +} diff --git a/libs/common/src/abstractions/import.service.ts b/libs/common/src/abstractions/import.service.ts new file mode 100644 index 0000000000..01f099b318 --- /dev/null +++ b/libs/common/src/abstractions/import.service.ts @@ -0,0 +1,19 @@ +import { ImportOption, ImportType } from "../enums/importOptions"; +import { ImportError } from "../importers/importError"; +import { Importer } from "../importers/importer"; + +export abstract class ImportService { + featuredImportOptions: readonly ImportOption[]; + regularImportOptions: readonly ImportOption[]; + getImportOptions: () => ImportOption[]; + import: ( + importer: Importer, + fileContents: string, + organizationId?: string + ) => Promise; + getImporter: ( + format: ImportType | "bitwardenpasswordprotected", + organizationId: string, + password?: string + ) => Importer; +} diff --git a/libs/common/src/abstractions/keyConnector.service.ts b/libs/common/src/abstractions/keyConnector.service.ts new file mode 100644 index 0000000000..b8f3bf7cd8 --- /dev/null +++ b/libs/common/src/abstractions/keyConnector.service.ts @@ -0,0 +1,19 @@ +import { Organization } from "../models/domain/organization"; +import { IdentityTokenResponse } from "../models/response/identityTokenResponse"; + +export abstract class KeyConnectorService { + getAndSetKey: (url?: string) => Promise; + getManagingOrganization: () => Promise; + getUsesKeyConnector: () => Promise; + migrateUser: () => Promise; + userNeedsMigration: () => Promise; + convertNewSsoUserToKeyConnector: ( + tokenResponse: IdentityTokenResponse, + orgId: string + ) => Promise; + setUsesKeyConnector: (enabled: boolean) => Promise; + setConvertAccountRequired: (status: boolean) => Promise; + getConvertAccountRequired: () => Promise; + removeConvertAccountRequired: () => Promise; + clear: () => Promise; +} diff --git a/libs/common/src/abstractions/log.service.ts b/libs/common/src/abstractions/log.service.ts new file mode 100644 index 0000000000..9997e480d6 --- /dev/null +++ b/libs/common/src/abstractions/log.service.ts @@ -0,0 +1,11 @@ +import { LogLevelType } from "../enums/logLevelType"; + +export abstract class LogService { + debug: (message: string) => void; + info: (message: string) => void; + warning: (message: string) => void; + error: (message: string) => void; + write: (level: LogLevelType, message: string) => void; + time: (label: string) => void; + timeEnd: (label: string) => [number, number]; +} diff --git a/libs/common/src/abstractions/messaging.service.ts b/libs/common/src/abstractions/messaging.service.ts new file mode 100644 index 0000000000..7c5f05f919 --- /dev/null +++ b/libs/common/src/abstractions/messaging.service.ts @@ -0,0 +1,3 @@ +export abstract class MessagingService { + send: (subscriber: string, arg?: any) => void; +} diff --git a/libs/common/src/abstractions/notifications.service.ts b/libs/common/src/abstractions/notifications.service.ts new file mode 100644 index 0000000000..921e8e62d5 --- /dev/null +++ b/libs/common/src/abstractions/notifications.service.ts @@ -0,0 +1,6 @@ +export abstract class NotificationsService { + init: () => Promise; + updateConnection: (sync?: boolean) => Promise; + reconnectFromActivity: () => Promise; + disconnectFromInactivity: () => Promise; +} diff --git a/libs/common/src/abstractions/organization.service.ts b/libs/common/src/abstractions/organization.service.ts new file mode 100644 index 0000000000..e0b5fde436 --- /dev/null +++ b/libs/common/src/abstractions/organization.service.ts @@ -0,0 +1,11 @@ +import { OrganizationData } from "../models/data/organizationData"; +import { Organization } from "../models/domain/organization"; + +export abstract class OrganizationService { + get: (id: string) => Promise; + getByIdentifier: (identifier: string) => Promise; + getAll: (userId?: string) => Promise; + save: (orgs: { [id: string]: OrganizationData }) => Promise; + canManageSponsorships: () => Promise; + hasOrganizations: (userId?: string) => Promise; +} diff --git a/libs/common/src/abstractions/passwordGeneration.service.ts b/libs/common/src/abstractions/passwordGeneration.service.ts new file mode 100644 index 0000000000..82bc021fb7 --- /dev/null +++ b/libs/common/src/abstractions/passwordGeneration.service.ts @@ -0,0 +1,20 @@ +import * as zxcvbn from "zxcvbn"; + +import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory"; +import { PasswordGeneratorPolicyOptions } from "../models/domain/passwordGeneratorPolicyOptions"; + +export abstract class PasswordGenerationService { + generatePassword: (options: any) => Promise; + generatePassphrase: (options: any) => Promise; + getOptions: () => Promise<[any, PasswordGeneratorPolicyOptions]>; + enforcePasswordGeneratorPoliciesOnOptions: ( + options: any + ) => Promise<[any, PasswordGeneratorPolicyOptions]>; + getPasswordGeneratorPolicyOptions: () => Promise; + saveOptions: (options: any) => Promise; + getHistory: () => Promise; + addHistory: (password: string) => Promise; + clear: (userId?: string) => Promise; + passwordStrength: (password: string, userInputs?: string[]) => zxcvbn.ZXCVBNResult; + normalizeOptions: (options: any, enforcedPolicyOptions: PasswordGeneratorPolicyOptions) => void; +} diff --git a/libs/common/src/abstractions/passwordReprompt.service.ts b/libs/common/src/abstractions/passwordReprompt.service.ts new file mode 100644 index 0000000000..6253425b34 --- /dev/null +++ b/libs/common/src/abstractions/passwordReprompt.service.ts @@ -0,0 +1,5 @@ +export abstract class PasswordRepromptService { + protectedFields: () => string[]; + showPasswordPrompt: () => Promise; + enabled: () => Promise; +} diff --git a/libs/common/src/abstractions/platformUtils.service.ts b/libs/common/src/abstractions/platformUtils.service.ts new file mode 100644 index 0000000000..4a014868d5 --- /dev/null +++ b/libs/common/src/abstractions/platformUtils.service.ts @@ -0,0 +1,52 @@ +import { ClientType } from "../enums/clientType"; +import { DeviceType } from "../enums/deviceType"; +import { ThemeType } from "../enums/themeType"; + +interface ToastOptions { + timeout?: number; +} + +export abstract class PlatformUtilsService { + getDevice: () => DeviceType; + getDeviceString: () => string; + getClientType: () => ClientType; + isFirefox: () => boolean; + isChrome: () => boolean; + isEdge: () => boolean; + isOpera: () => boolean; + isVivaldi: () => boolean; + isSafari: () => boolean; + isMacAppStore: () => boolean; + isViewOpen: () => Promise; + launchUri: (uri: string, options?: any) => void; + saveFile: (win: Window, blobData: any, blobOptions: any, fileName: string) => void; + getApplicationVersion: () => Promise; + supportsWebAuthn: (win: Window) => boolean; + supportsDuo: () => boolean; + showToast: ( + type: "error" | "success" | "warning" | "info", + title: string, + text: string | string[], + options?: ToastOptions + ) => void; + showDialog: ( + body: string, + title?: string, + confirmText?: string, + cancelText?: string, + type?: string, + bodyIsHtml?: boolean + ) => Promise; + isDev: () => boolean; + isSelfHost: () => boolean; + copyToClipboard: (text: string, options?: any) => void | boolean; + readFromClipboard: (options?: any) => Promise; + supportsBiometric: () => Promise; + authenticateBiometric: () => Promise; + getDefaultSystemTheme: () => Promise; + onDefaultSystemThemeChange: ( + callback: (theme: ThemeType.Light | ThemeType.Dark) => unknown + ) => unknown; + getEffectiveTheme: () => Promise; + supportsSecureStorage: () => boolean; +} diff --git a/libs/common/src/abstractions/policy.service.ts b/libs/common/src/abstractions/policy.service.ts new file mode 100644 index 0000000000..24dcc9965b --- /dev/null +++ b/libs/common/src/abstractions/policy.service.ts @@ -0,0 +1,32 @@ +import { PolicyType } from "../enums/policyType"; +import { PolicyData } from "../models/data/policyData"; +import { MasterPasswordPolicyOptions } from "../models/domain/masterPasswordPolicyOptions"; +import { Policy } from "../models/domain/policy"; +import { ResetPasswordPolicyOptions } from "../models/domain/resetPasswordPolicyOptions"; +import { ListResponse } from "../models/response/listResponse"; +import { PolicyResponse } from "../models/response/policyResponse"; + +export abstract class PolicyService { + clearCache: () => void; + getAll: (type?: PolicyType, userId?: string) => Promise; + getPolicyForOrganization: (policyType: PolicyType, organizationId: string) => Promise; + replace: (policies: { [id: string]: PolicyData }) => Promise; + clear: (userId?: string) => Promise; + getMasterPasswordPoliciesForInvitedUsers: (orgId: string) => Promise; + getMasterPasswordPolicyOptions: (policies?: Policy[]) => Promise; + evaluateMasterPassword: ( + passwordStrength: number, + newPassword: string, + enforcedPolicyOptions?: MasterPasswordPolicyOptions + ) => boolean; + getResetPasswordPolicyOptions: ( + policies: Policy[], + orgId: string + ) => [ResetPasswordPolicyOptions, boolean]; + mapPoliciesFromToken: (policiesResponse: ListResponse) => Policy[]; + policyAppliesToUser: ( + policyType: PolicyType, + policyFilter?: (policy: Policy) => boolean, + userId?: string + ) => Promise; +} diff --git a/libs/common/src/abstractions/provider.service.ts b/libs/common/src/abstractions/provider.service.ts new file mode 100644 index 0000000000..e474636924 --- /dev/null +++ b/libs/common/src/abstractions/provider.service.ts @@ -0,0 +1,8 @@ +import { ProviderData } from "../models/data/providerData"; +import { Provider } from "../models/domain/provider"; + +export abstract class ProviderService { + get: (id: string) => Promise; + getAll: () => Promise; + save: (providers: { [id: string]: ProviderData }) => Promise; +} diff --git a/libs/common/src/abstractions/search.service.ts b/libs/common/src/abstractions/search.service.ts new file mode 100644 index 0000000000..9c2b0eeb8e --- /dev/null +++ b/libs/common/src/abstractions/search.service.ts @@ -0,0 +1,16 @@ +import { CipherView } from "../models/view/cipherView"; +import { SendView } from "../models/view/sendView"; + +export abstract class SearchService { + indexedEntityId?: string = null; + clearIndex: () => void; + isSearchable: (query: string) => boolean; + indexCiphers: (indexedEntityGuid?: string, ciphersToIndex?: CipherView[]) => Promise; + searchCiphers: ( + query: string, + filter?: ((cipher: CipherView) => boolean) | ((cipher: CipherView) => boolean)[], + ciphers?: CipherView[] + ) => Promise; + searchCiphersBasic: (ciphers: CipherView[], query: string, deleted?: boolean) => CipherView[]; + searchSends: (sends: SendView[], query: string) => SendView[]; +} diff --git a/libs/common/src/abstractions/send.service.ts b/libs/common/src/abstractions/send.service.ts new file mode 100644 index 0000000000..3331e41e2a --- /dev/null +++ b/libs/common/src/abstractions/send.service.ts @@ -0,0 +1,25 @@ +import { SendData } from "../models/data/sendData"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; +import { Send } from "../models/domain/send"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { SendView } from "../models/view/sendView"; + +export abstract class SendService { + clearCache: () => Promise; + encrypt: ( + model: SendView, + file: File | ArrayBuffer, + password: string, + key?: SymmetricCryptoKey + ) => Promise<[Send, EncArrayBuffer]>; + get: (id: string) => Promise; + getAll: () => Promise; + getAllDecrypted: () => Promise; + saveWithServer: (sendData: [Send, EncArrayBuffer]) => Promise; + upsert: (send: SendData | SendData[]) => Promise; + replace: (sends: { [id: string]: SendData }) => Promise; + clear: (userId: string) => Promise; + delete: (id: string | string[]) => Promise; + deleteWithServer: (id: string) => Promise; + removePasswordWithServer: (id: string) => Promise; +} diff --git a/libs/common/src/abstractions/settings.service.ts b/libs/common/src/abstractions/settings.service.ts new file mode 100644 index 0000000000..e7886585b4 --- /dev/null +++ b/libs/common/src/abstractions/settings.service.ts @@ -0,0 +1,6 @@ +export abstract class SettingsService { + clearCache: () => Promise; + getEquivalentDomains: () => Promise; + setEquivalentDomains: (equivalentDomains: string[][]) => Promise; + clear: (userId?: string) => Promise; +} diff --git a/libs/common/src/abstractions/state.service.ts b/libs/common/src/abstractions/state.service.ts new file mode 100644 index 0000000000..0cf5060554 --- /dev/null +++ b/libs/common/src/abstractions/state.service.ts @@ -0,0 +1,306 @@ +import { BehaviorSubject } from "rxjs"; + +import { KdfType } from "../enums/kdfType"; +import { ThemeType } from "../enums/themeType"; +import { UriMatchType } from "../enums/uriMatchType"; +import { CipherData } from "../models/data/cipherData"; +import { CollectionData } from "../models/data/collectionData"; +import { EventData } from "../models/data/eventData"; +import { FolderData } from "../models/data/folderData"; +import { OrganizationData } from "../models/data/organizationData"; +import { PolicyData } from "../models/data/policyData"; +import { ProviderData } from "../models/data/providerData"; +import { SendData } from "../models/data/sendData"; +import { Account } from "../models/domain/account"; +import { EncString } from "../models/domain/encString"; +import { EnvironmentUrls } from "../models/domain/environmentUrls"; +import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory"; +import { Policy } from "../models/domain/policy"; +import { StorageOptions } from "../models/domain/storageOptions"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { WindowState } from "../models/domain/windowState"; +import { CipherView } from "../models/view/cipherView"; +import { CollectionView } from "../models/view/collectionView"; +import { FolderView } from "../models/view/folderView"; +import { SendView } from "../models/view/sendView"; + +export abstract class StateService { + accounts: BehaviorSubject<{ [userId: string]: T }>; + activeAccount: BehaviorSubject; + + addAccount: (account: T) => Promise; + setActiveUser: (userId: string) => Promise; + clean: (options?: StorageOptions) => Promise; + init: () => Promise; + + getAccessToken: (options?: StorageOptions) => Promise; + setAccessToken: (value: string, options?: StorageOptions) => Promise; + getAddEditCipherInfo: (options?: StorageOptions) => Promise; + setAddEditCipherInfo: (value: any, options?: StorageOptions) => Promise; + getAlwaysShowDock: (options?: StorageOptions) => Promise; + setAlwaysShowDock: (value: boolean, options?: StorageOptions) => Promise; + getApiKeyClientId: (options?: StorageOptions) => Promise; + setApiKeyClientId: (value: string, options?: StorageOptions) => Promise; + getApiKeyClientSecret: (options?: StorageOptions) => Promise; + setApiKeyClientSecret: (value: string, options?: StorageOptions) => Promise; + getAutoConfirmFingerPrints: (options?: StorageOptions) => Promise; + setAutoConfirmFingerprints: (value: boolean, options?: StorageOptions) => Promise; + getAutoFillOnPageLoadDefault: (options?: StorageOptions) => Promise; + setAutoFillOnPageLoadDefault: (value: boolean, options?: StorageOptions) => Promise; + getBiometricAwaitingAcceptance: (options?: StorageOptions) => Promise; + setBiometricAwaitingAcceptance: (value: boolean, options?: StorageOptions) => Promise; + getBiometricFingerprintValidated: (options?: StorageOptions) => Promise; + setBiometricFingerprintValidated: (value: boolean, options?: StorageOptions) => Promise; + getBiometricLocked: (options?: StorageOptions) => Promise; + setBiometricLocked: (value: boolean, options?: StorageOptions) => Promise; + getBiometricText: (options?: StorageOptions) => Promise; + setBiometricText: (value: string, options?: StorageOptions) => Promise; + getBiometricUnlock: (options?: StorageOptions) => Promise; + setBiometricUnlock: (value: boolean, options?: StorageOptions) => Promise; + getCanAccessPremium: (options?: StorageOptions) => Promise; + setCanAccessPremium: (value: boolean, options?: StorageOptions) => Promise; + getClearClipboard: (options?: StorageOptions) => Promise; + setClearClipboard: (value: number, options?: StorageOptions) => Promise; + getCollapsedGroupings: (options?: StorageOptions) => Promise; + setCollapsedGroupings: (value: string[], options?: StorageOptions) => Promise; + getConvertAccountToKeyConnector: (options?: StorageOptions) => Promise; + setConvertAccountToKeyConnector: (value: boolean, options?: StorageOptions) => Promise; + getCryptoMasterKey: (options?: StorageOptions) => Promise; + setCryptoMasterKey: (value: SymmetricCryptoKey, options?: StorageOptions) => Promise; + getCryptoMasterKeyAuto: (options?: StorageOptions) => Promise; + setCryptoMasterKeyAuto: (value: string, options?: StorageOptions) => Promise; + getCryptoMasterKeyB64: (options?: StorageOptions) => Promise; + setCryptoMasterKeyB64: (value: string, options?: StorageOptions) => Promise; + getCryptoMasterKeyBiometric: (options?: StorageOptions) => Promise; + hasCryptoMasterKeyBiometric: (options?: StorageOptions) => Promise; + setCryptoMasterKeyBiometric: (value: string, options?: StorageOptions) => Promise; + getDecodedToken: (options?: StorageOptions) => Promise; + setDecodedToken: (value: any, options?: StorageOptions) => Promise; + getDecryptedCiphers: (options?: StorageOptions) => Promise; + setDecryptedCiphers: (value: CipherView[], options?: StorageOptions) => Promise; + getDecryptedCollections: (options?: StorageOptions) => Promise; + setDecryptedCollections: (value: CollectionView[], options?: StorageOptions) => Promise; + getDecryptedCryptoSymmetricKey: (options?: StorageOptions) => Promise; + setDecryptedCryptoSymmetricKey: ( + value: SymmetricCryptoKey, + options?: StorageOptions + ) => Promise; + getDecryptedFolders: (options?: StorageOptions) => Promise; + setDecryptedFolders: (value: FolderView[], options?: StorageOptions) => Promise; + getDecryptedOrganizationKeys: ( + options?: StorageOptions + ) => Promise>; + setDecryptedOrganizationKeys: ( + value: Map, + options?: StorageOptions + ) => Promise; + getDecryptedPasswordGenerationHistory: ( + options?: StorageOptions + ) => Promise; + setDecryptedPasswordGenerationHistory: ( + value: GeneratedPasswordHistory[], + options?: StorageOptions + ) => Promise; + getDecryptedPinProtected: (options?: StorageOptions) => Promise; + setDecryptedPinProtected: (value: EncString, options?: StorageOptions) => Promise; + getDecryptedPolicies: (options?: StorageOptions) => Promise; + setDecryptedPolicies: (value: Policy[], options?: StorageOptions) => Promise; + getDecryptedPrivateKey: (options?: StorageOptions) => Promise; + setDecryptedPrivateKey: (value: ArrayBuffer, options?: StorageOptions) => Promise; + getDecryptedProviderKeys: (options?: StorageOptions) => Promise>; + setDecryptedProviderKeys: ( + value: Map, + options?: StorageOptions + ) => Promise; + getDecryptedSends: (options?: StorageOptions) => Promise; + setDecryptedSends: (value: SendView[], options?: StorageOptions) => Promise; + getDefaultUriMatch: (options?: StorageOptions) => Promise; + setDefaultUriMatch: (value: UriMatchType, options?: StorageOptions) => Promise; + getDisableAddLoginNotification: (options?: StorageOptions) => Promise; + setDisableAddLoginNotification: (value: boolean, options?: StorageOptions) => Promise; + getDisableAutoBiometricsPrompt: (options?: StorageOptions) => Promise; + setDisableAutoBiometricsPrompt: (value: boolean, options?: StorageOptions) => Promise; + getDisableAutoTotpCopy: (options?: StorageOptions) => Promise; + setDisableAutoTotpCopy: (value: boolean, options?: StorageOptions) => Promise; + getDisableBadgeCounter: (options?: StorageOptions) => Promise; + setDisableBadgeCounter: (value: boolean, options?: StorageOptions) => Promise; + getDisableChangedPasswordNotification: (options?: StorageOptions) => Promise; + setDisableChangedPasswordNotification: ( + value: boolean, + options?: StorageOptions + ) => Promise; + getDisableContextMenuItem: (options?: StorageOptions) => Promise; + setDisableContextMenuItem: (value: boolean, options?: StorageOptions) => Promise; + getDisableFavicon: (options?: StorageOptions) => Promise; + setDisableFavicon: (value: boolean, options?: StorageOptions) => Promise; + getDisableGa: (options?: StorageOptions) => Promise; + setDisableGa: (value: boolean, options?: StorageOptions) => Promise; + getDontShowCardsCurrentTab: (options?: StorageOptions) => Promise; + setDontShowCardsCurrentTab: (value: boolean, options?: StorageOptions) => Promise; + getDontShowIdentitiesCurrentTab: (options?: StorageOptions) => Promise; + setDontShowIdentitiesCurrentTab: (value: boolean, options?: StorageOptions) => Promise; + getEmail: (options?: StorageOptions) => Promise; + setEmail: (value: string, options?: StorageOptions) => Promise; + getEmailVerified: (options?: StorageOptions) => Promise; + setEmailVerified: (value: boolean, options?: StorageOptions) => Promise; + getEnableAlwaysOnTop: (options?: StorageOptions) => Promise; + setEnableAlwaysOnTop: (value: boolean, options?: StorageOptions) => Promise; + getEnableAutoFillOnPageLoad: (options?: StorageOptions) => Promise; + setEnableAutoFillOnPageLoad: (value: boolean, options?: StorageOptions) => Promise; + getEnableBiometric: (options?: StorageOptions) => Promise; + setEnableBiometric: (value: boolean, options?: StorageOptions) => Promise; + getEnableBrowserIntegration: (options?: StorageOptions) => Promise; + setEnableBrowserIntegration: (value: boolean, options?: StorageOptions) => Promise; + getEnableBrowserIntegrationFingerprint: (options?: StorageOptions) => Promise; + setEnableBrowserIntegrationFingerprint: ( + value: boolean, + options?: StorageOptions + ) => Promise; + getEnableCloseToTray: (options?: StorageOptions) => Promise; + setEnableCloseToTray: (value: boolean, options?: StorageOptions) => Promise; + getEnableFullWidth: (options?: StorageOptions) => Promise; + setEnableFullWidth: (value: boolean, options?: StorageOptions) => Promise; + getEnableGravitars: (options?: StorageOptions) => Promise; + setEnableGravitars: (value: boolean, options?: StorageOptions) => Promise; + getEnableMinimizeToTray: (options?: StorageOptions) => Promise; + setEnableMinimizeToTray: (value: boolean, options?: StorageOptions) => Promise; + getEnableStartToTray: (options?: StorageOptions) => Promise; + setEnableStartToTray: (value: boolean, options?: StorageOptions) => Promise; + getEnableTray: (options?: StorageOptions) => Promise; + setEnableTray: (value: boolean, options?: StorageOptions) => Promise; + getEncryptedCiphers: (options?: StorageOptions) => Promise<{ [id: string]: CipherData }>; + setEncryptedCiphers: ( + value: { [id: string]: CipherData }, + options?: StorageOptions + ) => Promise; + getEncryptedCollections: (options?: StorageOptions) => Promise<{ [id: string]: CollectionData }>; + setEncryptedCollections: ( + value: { [id: string]: CollectionData }, + options?: StorageOptions + ) => Promise; + getEncryptedCryptoSymmetricKey: (options?: StorageOptions) => Promise; + setEncryptedCryptoSymmetricKey: (value: string, options?: StorageOptions) => Promise; + getEncryptedFolders: (options?: StorageOptions) => Promise<{ [id: string]: FolderData }>; + setEncryptedFolders: ( + value: { [id: string]: FolderData }, + options?: StorageOptions + ) => Promise; + getEncryptedOrganizationKeys: (options?: StorageOptions) => Promise; + setEncryptedOrganizationKeys: ( + value: Map, + options?: StorageOptions + ) => Promise; + getEncryptedPasswordGenerationHistory: ( + options?: StorageOptions + ) => Promise; + setEncryptedPasswordGenerationHistory: ( + value: GeneratedPasswordHistory[], + options?: StorageOptions + ) => Promise; + getEncryptedPinProtected: (options?: StorageOptions) => Promise; + setEncryptedPinProtected: (value: string, options?: StorageOptions) => Promise; + getEncryptedPolicies: (options?: StorageOptions) => Promise<{ [id: string]: PolicyData }>; + setEncryptedPolicies: ( + value: { [id: string]: PolicyData }, + options?: StorageOptions + ) => Promise; + getEncryptedPrivateKey: (options?: StorageOptions) => Promise; + setEncryptedPrivateKey: (value: string, options?: StorageOptions) => Promise; + getEncryptedProviderKeys: (options?: StorageOptions) => Promise; + setEncryptedProviderKeys: (value: any, options?: StorageOptions) => Promise; + getEncryptedSends: (options?: StorageOptions) => Promise<{ [id: string]: SendData }>; + setEncryptedSends: (value: { [id: string]: SendData }, options?: StorageOptions) => Promise; + getEntityId: (options?: StorageOptions) => Promise; + setEntityId: (value: string, options?: StorageOptions) => Promise; + getEntityType: (options?: StorageOptions) => Promise; + setEntityType: (value: string, options?: StorageOptions) => Promise; + getEnvironmentUrls: (options?: StorageOptions) => Promise; + setEnvironmentUrls: (value: EnvironmentUrls, options?: StorageOptions) => Promise; + getEquivalentDomains: (options?: StorageOptions) => Promise; + setEquivalentDomains: (value: string, options?: StorageOptions) => Promise; + getEventCollection: (options?: StorageOptions) => Promise; + setEventCollection: (value: EventData[], options?: StorageOptions) => Promise; + getEverBeenUnlocked: (options?: StorageOptions) => Promise; + setEverBeenUnlocked: (value: boolean, options?: StorageOptions) => Promise; + getForcePasswordReset: (options?: StorageOptions) => Promise; + setForcePasswordReset: (value: boolean, options?: StorageOptions) => Promise; + getInstalledVersion: (options?: StorageOptions) => Promise; + setInstalledVersion: (value: string, options?: StorageOptions) => Promise; + getIsAuthenticated: (options?: StorageOptions) => Promise; + getKdfIterations: (options?: StorageOptions) => Promise; + setKdfIterations: (value: number, options?: StorageOptions) => Promise; + getKdfType: (options?: StorageOptions) => Promise; + setKdfType: (value: KdfType, options?: StorageOptions) => Promise; + getKeyHash: (options?: StorageOptions) => Promise; + setKeyHash: (value: string, options?: StorageOptions) => Promise; + getLastActive: (options?: StorageOptions) => Promise; + setLastActive: (value: number, options?: StorageOptions) => Promise; + getLastSync: (options?: StorageOptions) => Promise; + setLastSync: (value: string, options?: StorageOptions) => Promise; + getLegacyEtmKey: (options?: StorageOptions) => Promise; + setLegacyEtmKey: (value: SymmetricCryptoKey, options?: StorageOptions) => Promise; + getLocalData: (options?: StorageOptions) => Promise; + setLocalData: (value: string, options?: StorageOptions) => Promise; + getLocale: (options?: StorageOptions) => Promise; + setLocale: (value: string, options?: StorageOptions) => Promise; + getMainWindowSize: (options?: StorageOptions) => Promise; + setMainWindowSize: (value: number, options?: StorageOptions) => Promise; + getMinimizeOnCopyToClipboard: (options?: StorageOptions) => Promise; + setMinimizeOnCopyToClipboard: (value: boolean, options?: StorageOptions) => Promise; + getNeverDomains: (options?: StorageOptions) => Promise<{ [id: string]: any }>; + setNeverDomains: (value: { [id: string]: any }, options?: StorageOptions) => Promise; + getNoAutoPromptBiometrics: (options?: StorageOptions) => Promise; + setNoAutoPromptBiometrics: (value: boolean, options?: StorageOptions) => Promise; + getNoAutoPromptBiometricsText: (options?: StorageOptions) => Promise; + setNoAutoPromptBiometricsText: (value: string, options?: StorageOptions) => Promise; + getOpenAtLogin: (options?: StorageOptions) => Promise; + setOpenAtLogin: (value: boolean, options?: StorageOptions) => Promise; + getOrganizationInvitation: (options?: StorageOptions) => Promise; + setOrganizationInvitation: (value: any, options?: StorageOptions) => Promise; + getOrganizations: (options?: StorageOptions) => Promise<{ [id: string]: OrganizationData }>; + setOrganizations: ( + value: { [id: string]: OrganizationData }, + options?: StorageOptions + ) => Promise; + getPasswordGenerationOptions: (options?: StorageOptions) => Promise; + setPasswordGenerationOptions: (value: any, options?: StorageOptions) => Promise; + getUsernameGenerationOptions: (options?: StorageOptions) => Promise; + setUsernameGenerationOptions: (value: any, options?: StorageOptions) => Promise; + getGeneratorOptions: (options?: StorageOptions) => Promise; + setGeneratorOptions: (value: any, options?: StorageOptions) => Promise; + getProtectedPin: (options?: StorageOptions) => Promise; + setProtectedPin: (value: string, options?: StorageOptions) => Promise; + getProviders: (options?: StorageOptions) => Promise<{ [id: string]: ProviderData }>; + setProviders: (value: { [id: string]: ProviderData }, options?: StorageOptions) => Promise; + getPublicKey: (options?: StorageOptions) => Promise; + setPublicKey: (value: ArrayBuffer, options?: StorageOptions) => Promise; + getRefreshToken: (options?: StorageOptions) => Promise; + setRefreshToken: (value: string, options?: StorageOptions) => Promise; + getRememberedEmail: (options?: StorageOptions) => Promise; + setRememberedEmail: (value: string, options?: StorageOptions) => Promise; + getSecurityStamp: (options?: StorageOptions) => Promise; + setSecurityStamp: (value: string, options?: StorageOptions) => Promise; + getSettings: (options?: StorageOptions) => Promise; + setSettings: (value: string, options?: StorageOptions) => Promise; + getSsoCodeVerifier: (options?: StorageOptions) => Promise; + setSsoCodeVerifier: (value: string, options?: StorageOptions) => Promise; + getSsoOrgIdentifier: (options?: StorageOptions) => Promise; + setSsoOrganizationIdentifier: (value: string, options?: StorageOptions) => Promise; + getSsoState: (options?: StorageOptions) => Promise; + setSsoState: (value: string, options?: StorageOptions) => Promise; + getTheme: (options?: StorageOptions) => Promise; + setTheme: (value: ThemeType, options?: StorageOptions) => Promise; + getTwoFactorToken: (options?: StorageOptions) => Promise; + setTwoFactorToken: (value: string, options?: StorageOptions) => Promise; + getUserId: (options?: StorageOptions) => Promise; + getUsesKeyConnector: (options?: StorageOptions) => Promise; + setUsesKeyConnector: (vaule: boolean, options?: StorageOptions) => Promise; + getVaultTimeout: (options?: StorageOptions) => Promise; + setVaultTimeout: (value: number, options?: StorageOptions) => Promise; + getVaultTimeoutAction: (options?: StorageOptions) => Promise; + setVaultTimeoutAction: (value: string, options?: StorageOptions) => Promise; + getStateVersion: () => Promise; + setStateVersion: (value: number) => Promise; + getWindow: () => Promise; + setWindow: (value: WindowState) => Promise; +} diff --git a/libs/common/src/abstractions/stateMigration.service.ts b/libs/common/src/abstractions/stateMigration.service.ts new file mode 100644 index 0000000000..f16777a159 --- /dev/null +++ b/libs/common/src/abstractions/stateMigration.service.ts @@ -0,0 +1,4 @@ +export abstract class StateMigrationService { + needsMigration: () => Promise; + migrate: () => Promise; +} diff --git a/libs/common/src/abstractions/storage.service.ts b/libs/common/src/abstractions/storage.service.ts new file mode 100644 index 0000000000..f522d3cf81 --- /dev/null +++ b/libs/common/src/abstractions/storage.service.ts @@ -0,0 +1,8 @@ +import { StorageOptions } from "../models/domain/storageOptions"; + +export abstract class StorageService { + get: (key: string, options?: StorageOptions) => Promise; + has: (key: string, options?: StorageOptions) => Promise; + save: (key: string, obj: any, options?: StorageOptions) => Promise; + remove: (key: string, options?: StorageOptions) => Promise; +} diff --git a/libs/common/src/abstractions/sync.service.ts b/libs/common/src/abstractions/sync.service.ts new file mode 100644 index 0000000000..936d027fd4 --- /dev/null +++ b/libs/common/src/abstractions/sync.service.ts @@ -0,0 +1,19 @@ +import { + SyncCipherNotification, + SyncFolderNotification, + SyncSendNotification, +} from "../models/response/notificationResponse"; + +export abstract class SyncService { + syncInProgress: boolean; + + getLastSync: () => Promise; + setLastSync: (date: Date, userId?: string) => Promise; + fullSync: (forceSync: boolean, allowThrowOnError?: boolean) => Promise; + syncUpsertFolder: (notification: SyncFolderNotification, isEdit: boolean) => Promise; + syncDeleteFolder: (notification: SyncFolderNotification) => Promise; + syncUpsertCipher: (notification: SyncCipherNotification, isEdit: boolean) => Promise; + syncDeleteCipher: (notification: SyncFolderNotification) => Promise; + syncUpsertSend: (notification: SyncSendNotification, isEdit: boolean) => Promise; + syncDeleteSend: (notification: SyncSendNotification) => Promise; +} diff --git a/libs/common/src/abstractions/system.service.ts b/libs/common/src/abstractions/system.service.ts new file mode 100644 index 0000000000..b5c1e5959e --- /dev/null +++ b/libs/common/src/abstractions/system.service.ts @@ -0,0 +1,6 @@ +export abstract class SystemService { + startProcessReload: () => Promise; + cancelProcessReload: () => void; + clearClipboard: (clipboardValue: string, timeoutMs?: number) => Promise; + clearPendingClipboard: () => Promise; +} diff --git a/libs/common/src/abstractions/token.service.ts b/libs/common/src/abstractions/token.service.ts new file mode 100644 index 0000000000..f04704942a --- /dev/null +++ b/libs/common/src/abstractions/token.service.ts @@ -0,0 +1,32 @@ +import { IdentityTokenResponse } from "../models/response/identityTokenResponse"; + +export abstract class TokenService { + setTokens: ( + accessToken: string, + refreshToken: string, + clientIdClientSecret: [string, string] + ) => Promise; + setToken: (token: string) => Promise; + getToken: () => Promise; + setRefreshToken: (refreshToken: string) => Promise; + getRefreshToken: () => Promise; + setClientId: (clientId: string) => Promise; + getClientId: () => Promise; + setClientSecret: (clientSecret: string) => Promise; + getClientSecret: () => Promise; + setTwoFactorToken: (tokenResponse: IdentityTokenResponse) => Promise; + getTwoFactorToken: () => Promise; + clearTwoFactorToken: () => Promise; + clearToken: (userId?: string) => Promise; + decodeToken: (token?: string) => any; + getTokenExpirationDate: () => Promise; + tokenSecondsRemaining: (offsetSeconds?: number) => Promise; + tokenNeedsRefresh: (minutes?: number) => Promise; + getUserId: () => Promise; + getEmail: () => Promise; + getEmailVerified: () => Promise; + getName: () => Promise; + getPremium: () => Promise; + getIssuer: () => Promise; + getIsExternal: () => Promise; +} diff --git a/libs/common/src/abstractions/totp.service.ts b/libs/common/src/abstractions/totp.service.ts new file mode 100644 index 0000000000..bf143e269c --- /dev/null +++ b/libs/common/src/abstractions/totp.service.ts @@ -0,0 +1,5 @@ +export abstract class TotpService { + getCode: (key: string) => Promise; + getTimeInterval: (key: string) => number; + isAutoCopyEnabled: () => Promise; +} diff --git a/libs/common/src/abstractions/twoFactor.service.ts b/libs/common/src/abstractions/twoFactor.service.ts new file mode 100644 index 0000000000..74f091678b --- /dev/null +++ b/libs/common/src/abstractions/twoFactor.service.ts @@ -0,0 +1,23 @@ +import { TwoFactorProviderType } from "../enums/twoFactorProviderType"; +import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse"; + +export interface TwoFactorProviderDetails { + type: TwoFactorProviderType; + name: string; + description: string; + priority: number; + sort: number; + premium: boolean; +} + +export abstract class TwoFactorService { + init: () => void; + getSupportedProviders: (win: Window) => TwoFactorProviderDetails[]; + getDefaultProvider: (webAuthnSupported: boolean) => TwoFactorProviderType; + setSelectedProvider: (type: TwoFactorProviderType) => void; + clearSelectedProvider: () => void; + + setProviders: (response: IdentityTwoFactorResponse) => void; + clearProviders: () => void; + getProviders: () => Map; +} diff --git a/libs/common/src/abstractions/userVerification.service.ts b/libs/common/src/abstractions/userVerification.service.ts new file mode 100644 index 0000000000..ebd7d1f334 --- /dev/null +++ b/libs/common/src/abstractions/userVerification.service.ts @@ -0,0 +1,12 @@ +import { SecretVerificationRequest } from "../models/request/secretVerificationRequest"; +import { Verification } from "../types/verification"; + +export abstract class UserVerificationService { + buildRequest: ( + verification: Verification, + requestClass?: new () => T, + alreadyHashed?: boolean + ) => Promise; + verifyUser: (verification: Verification) => Promise; + requestOTP: () => Promise; +} diff --git a/libs/common/src/abstractions/usernameGeneration.service.ts b/libs/common/src/abstractions/usernameGeneration.service.ts new file mode 100644 index 0000000000..b5bef9fc41 --- /dev/null +++ b/libs/common/src/abstractions/usernameGeneration.service.ts @@ -0,0 +1,9 @@ +export abstract class UsernameGenerationService { + generateUsername: (options: any) => Promise; + generateWord: (options: any) => Promise; + generateSubaddress: (options: any) => Promise; + generateCatchall: (options: any) => Promise; + generateForwarded: (options: any) => Promise; + getOptions: () => Promise; + saveOptions: (options: any) => Promise; +} diff --git a/libs/common/src/abstractions/vaultTimeout.service.ts b/libs/common/src/abstractions/vaultTimeout.service.ts new file mode 100644 index 0000000000..317fbca86d --- /dev/null +++ b/libs/common/src/abstractions/vaultTimeout.service.ts @@ -0,0 +1,10 @@ +export abstract class VaultTimeoutService { + checkVaultTimeout: () => Promise; + lock: (allowSoftLock?: boolean, userId?: string) => Promise; + logOut: (userId?: string) => Promise; + setVaultTimeoutOptions: (vaultTimeout: number, vaultTimeoutAction: string) => Promise; + getVaultTimeout: () => Promise; + isPinLockSet: () => Promise<[boolean, boolean]>; + isBiometricLockSet: () => Promise; + clear: (userId?: string) => Promise; +} diff --git a/libs/common/src/enums/authenticationStatus.ts b/libs/common/src/enums/authenticationStatus.ts new file mode 100644 index 0000000000..17b4f1f21e --- /dev/null +++ b/libs/common/src/enums/authenticationStatus.ts @@ -0,0 +1,5 @@ +export enum AuthenticationStatus { + LoggedOut = 0, + Locked = 1, + Unlocked = 2, +} diff --git a/libs/common/src/enums/authenticationType.ts b/libs/common/src/enums/authenticationType.ts new file mode 100644 index 0000000000..ed7375c808 --- /dev/null +++ b/libs/common/src/enums/authenticationType.ts @@ -0,0 +1,5 @@ +export enum AuthenticationType { + Password = 0, + Sso = 1, + Api = 2, +} diff --git a/libs/common/src/enums/cipherRepromptType.ts b/libs/common/src/enums/cipherRepromptType.ts new file mode 100644 index 0000000000..1d0a523ced --- /dev/null +++ b/libs/common/src/enums/cipherRepromptType.ts @@ -0,0 +1,4 @@ +export enum CipherRepromptType { + None = 0, + Password = 1, +} diff --git a/libs/common/src/enums/cipherType.ts b/libs/common/src/enums/cipherType.ts new file mode 100644 index 0000000000..cce7874d66 --- /dev/null +++ b/libs/common/src/enums/cipherType.ts @@ -0,0 +1,6 @@ +export enum CipherType { + Login = 1, + SecureNote = 2, + Card = 3, + Identity = 4, +} diff --git a/libs/common/src/enums/clientType.ts b/libs/common/src/enums/clientType.ts new file mode 100644 index 0000000000..246769ebf2 --- /dev/null +++ b/libs/common/src/enums/clientType.ts @@ -0,0 +1,8 @@ +export enum ClientType { + Web = "web", + Browser = "browser", + Desktop = "desktop", + Mobile = "mobile", + Cli = "cli", + DirectoryConnector = "connector", +} diff --git a/libs/common/src/enums/deviceType.ts b/libs/common/src/enums/deviceType.ts new file mode 100644 index 0000000000..707f83d84a --- /dev/null +++ b/libs/common/src/enums/deviceType.ts @@ -0,0 +1,23 @@ +export enum DeviceType { + Android = 0, + iOS = 1, + ChromeExtension = 2, + FirefoxExtension = 3, + OperaExtension = 4, + EdgeExtension = 5, + WindowsDesktop = 6, + MacOsDesktop = 7, + LinuxDesktop = 8, + ChromeBrowser = 9, + FirefoxBrowser = 10, + OperaBrowser = 11, + EdgeBrowser = 12, + IEBrowser = 13, + UnknownBrowser = 14, + AndroidAmazon = 15, + UWP = 16, + SafariBrowser = 17, + VivaldiBrowser = 18, + VivaldiExtension = 19, + SafariExtension = 20, +} diff --git a/libs/common/src/enums/emergencyAccessStatusType.ts b/libs/common/src/enums/emergencyAccessStatusType.ts new file mode 100644 index 0000000000..94400f34e6 --- /dev/null +++ b/libs/common/src/enums/emergencyAccessStatusType.ts @@ -0,0 +1,7 @@ +export enum EmergencyAccessStatusType { + Invited = 0, + Accepted = 1, + Confirmed = 2, + RecoveryInitiated = 3, + RecoveryApproved = 4, +} diff --git a/libs/common/src/enums/emergencyAccessType.ts b/libs/common/src/enums/emergencyAccessType.ts new file mode 100644 index 0000000000..61a366c433 --- /dev/null +++ b/libs/common/src/enums/emergencyAccessType.ts @@ -0,0 +1,4 @@ +export enum EmergencyAccessType { + View = 0, + Takeover = 1, +} diff --git a/libs/common/src/enums/encryptionType.ts b/libs/common/src/enums/encryptionType.ts new file mode 100644 index 0000000000..1c12dba21c --- /dev/null +++ b/libs/common/src/enums/encryptionType.ts @@ -0,0 +1,9 @@ +export enum EncryptionType { + AesCbc256_B64 = 0, + AesCbc128_HmacSha256_B64 = 1, + AesCbc256_HmacSha256_B64 = 2, + Rsa2048_OaepSha256_B64 = 3, + Rsa2048_OaepSha1_B64 = 4, + Rsa2048_OaepSha256_HmacSha256_B64 = 5, + Rsa2048_OaepSha1_HmacSha256_B64 = 6, +} diff --git a/libs/common/src/enums/eventType.ts b/libs/common/src/enums/eventType.ts new file mode 100644 index 0000000000..d6268aea55 --- /dev/null +++ b/libs/common/src/enums/eventType.ts @@ -0,0 +1,73 @@ +export enum EventType { + User_LoggedIn = 1000, + User_ChangedPassword = 1001, + User_Updated2fa = 1002, + User_Disabled2fa = 1003, + User_Recovered2fa = 1004, + User_FailedLogIn = 1005, + User_FailedLogIn2fa = 1006, + User_ClientExportedVault = 1007, + User_UpdatedTempPassword = 1008, + User_MigratedKeyToKeyConnector = 1009, + + Cipher_Created = 1100, + Cipher_Updated = 1101, + Cipher_Deleted = 1102, + Cipher_AttachmentCreated = 1103, + Cipher_AttachmentDeleted = 1104, + Cipher_Shared = 1105, + Cipher_UpdatedCollections = 1106, + Cipher_ClientViewed = 1107, + Cipher_ClientToggledPasswordVisible = 1108, + Cipher_ClientToggledHiddenFieldVisible = 1109, + Cipher_ClientToggledCardCodeVisible = 1110, + Cipher_ClientCopiedPassword = 1111, + Cipher_ClientCopiedHiddenField = 1112, + Cipher_ClientCopiedCardCode = 1113, + Cipher_ClientAutofilled = 1114, + Cipher_SoftDeleted = 1115, + Cipher_Restored = 1116, + Cipher_ClientToggledCardNumberVisible = 1117, + + Collection_Created = 1300, + Collection_Updated = 1301, + Collection_Deleted = 1302, + + Group_Created = 1400, + Group_Updated = 1401, + Group_Deleted = 1402, + + OrganizationUser_Invited = 1500, + OrganizationUser_Confirmed = 1501, + OrganizationUser_Updated = 1502, + OrganizationUser_Removed = 1503, + OrganizationUser_UpdatedGroups = 1504, + OrganizationUser_UnlinkedSso = 1505, + OrganizationUser_ResetPassword_Enroll = 1506, + OrganizationUser_ResetPassword_Withdraw = 1507, + OrganizationUser_AdminResetPassword = 1508, + OrganizationUser_ResetSsoLink = 1509, + OrganizationUser_FirstSsoLogin = 1510, + + Organization_Updated = 1600, + Organization_PurgedVault = 1601, + // Organization_ClientExportedVault = 1602, + Organization_VaultAccessed = 1603, + Organization_EnabledSso = 1604, + Organization_DisabledSso = 1605, + Organization_EnabledKeyConnector = 1606, + Organization_DisabledKeyConnector = 1607, + Organization_SponsorshipsSynced = 1608, + + Policy_Updated = 1700, + + ProviderUser_Invited = 1800, + ProviderUser_Confirmed = 1801, + ProviderUser_Updated = 1802, + ProviderUser_Removed = 1803, + + ProviderOrganization_Created = 1900, + ProviderOrganization_Added = 1901, + ProviderOrganization_Removed = 1902, + ProviderOrganization_VaultAccessed = 1903, +} diff --git a/libs/common/src/enums/fieldType.ts b/libs/common/src/enums/fieldType.ts new file mode 100644 index 0000000000..d6deb30e69 --- /dev/null +++ b/libs/common/src/enums/fieldType.ts @@ -0,0 +1,6 @@ +export enum FieldType { + Text = 0, + Hidden = 1, + Boolean = 2, + Linked = 3, +} diff --git a/libs/common/src/enums/fileUploadType.ts b/libs/common/src/enums/fileUploadType.ts new file mode 100644 index 0000000000..4cf654fd0f --- /dev/null +++ b/libs/common/src/enums/fileUploadType.ts @@ -0,0 +1,4 @@ +export enum FileUploadType { + Direct = 0, + Azure = 1, +} diff --git a/libs/common/src/enums/hashPurpose.ts b/libs/common/src/enums/hashPurpose.ts new file mode 100644 index 0000000000..887931b9ed --- /dev/null +++ b/libs/common/src/enums/hashPurpose.ts @@ -0,0 +1,4 @@ +export enum HashPurpose { + ServerAuthorization = 1, + LocalAuthorization = 2, +} diff --git a/libs/common/src/enums/htmlStorageLocation.ts b/libs/common/src/enums/htmlStorageLocation.ts new file mode 100644 index 0000000000..19c84fe88c --- /dev/null +++ b/libs/common/src/enums/htmlStorageLocation.ts @@ -0,0 +1,5 @@ +export enum HtmlStorageLocation { + Local = "local", + Memory = "memory", + Session = "session", +} diff --git a/libs/common/src/enums/importOptions.ts b/libs/common/src/enums/importOptions.ts new file mode 100644 index 0000000000..6535b13363 --- /dev/null +++ b/libs/common/src/enums/importOptions.ts @@ -0,0 +1,74 @@ +export interface ImportOption { + id: string; + name: string; +} + +export const featuredImportOptions = [ + { id: "bitwardenjson", name: "Bitwarden (json)" }, + { id: "bitwardencsv", name: "Bitwarden (csv)" }, + { id: "chromecsv", name: "Chrome (csv)" }, + { id: "dashlanecsv", name: "Dashlane (csv)" }, + { id: "firefoxcsv", name: "Firefox (csv)" }, + { id: "keepass2xml", name: "KeePass 2 (xml)" }, + { id: "lastpasscsv", name: "LastPass (csv)" }, + { id: "safaricsv", name: "Safari and macOS (csv)" }, + { id: "1password1pux", name: "1Password (1pux)" }, +] as const; + +export const regularImportOptions = [ + { id: "keepassxcsv", name: "KeePassX (csv)" }, + { id: "1password1pif", name: "1Password (1pif)" }, + { id: "1passwordwincsv", name: "1Password 6 and 7 Windows (csv)" }, + { id: "1passwordmaccsv", name: "1Password 6 and 7 Mac (csv)" }, + { id: "dashlanejson", name: "Dashlane (json)" }, + { id: "roboformcsv", name: "RoboForm (csv)" }, + { id: "keepercsv", name: "Keeper (csv)" }, + // Temporarily remove this option for the Feb release + // { id: "keeperjson", name: "Keeper (json)" }, + { id: "enpasscsv", name: "Enpass (csv)" }, + { id: "enpassjson", name: "Enpass (json)" }, + { id: "safeincloudxml", name: "SafeInCloud (xml)" }, + { id: "pwsafexml", name: "Password Safe (xml)" }, + { id: "stickypasswordxml", name: "Sticky Password (xml)" }, + { id: "msecurecsv", name: "mSecure (csv)" }, + { id: "truekeycsv", name: "True Key (csv)" }, + { id: "passwordbossjson", name: "Password Boss (json)" }, + { id: "zohovaultcsv", name: "Zoho Vault (csv)" }, + { id: "splashidcsv", name: "SplashID (csv)" }, + { id: "passworddragonxml", name: "Password Dragon (xml)" }, + { id: "padlockcsv", name: "Padlock (csv)" }, + { id: "passboltcsv", name: "Passbolt (csv)" }, + { id: "clipperzhtml", name: "Clipperz (html)" }, + { id: "aviracsv", name: "Avira (csv)" }, + { id: "saferpasscsv", name: "SaferPass (csv)" }, + { id: "upmcsv", name: "Universal Password Manager (csv)" }, + { id: "ascendocsv", name: "Ascendo DataVault (csv)" }, + { id: "meldiumcsv", name: "Meldium (csv)" }, + { id: "passkeepcsv", name: "PassKeep (csv)" }, + { id: "operacsv", name: "Opera (csv)" }, + { id: "vivaldicsv", name: "Vivaldi (csv)" }, + { id: "gnomejson", name: "GNOME Passwords and Keys/Seahorse (json)" }, + { id: "blurcsv", name: "Blur (csv)" }, + { id: "passwordagentcsv", name: "Password Agent (csv)" }, + { id: "passpackcsv", name: "Passpack (csv)" }, + { id: "passmanjson", name: "Passman (json)" }, + { id: "avastcsv", name: "Avast Passwords (csv)" }, + { id: "avastjson", name: "Avast Passwords (json)" }, + { id: "fsecurefsk", name: "F-Secure KEY (fsk)" }, + { id: "kasperskytxt", name: "Kaspersky Password Manager (txt)" }, + { id: "remembearcsv", name: "RememBear (csv)" }, + { id: "passwordwallettxt", name: "PasswordWallet (txt)" }, + { id: "mykicsv", name: "Myki (csv)" }, + { id: "securesafecsv", name: "SecureSafe (csv)" }, + { id: "logmeoncecsv", name: "LogMeOnce (csv)" }, + { id: "blackberrycsv", name: "BlackBerry Password Keeper (csv)" }, + { id: "buttercupcsv", name: "Buttercup (csv)" }, + { id: "codebookcsv", name: "Codebook (csv)" }, + { id: "encryptrcsv", name: "Encryptr (csv)" }, + { id: "yoticsv", name: "Yoti (csv)" }, + { id: "nordpasscsv", name: "Nordpass (csv)" }, +] as const; + +export type ImportType = + | typeof featuredImportOptions[number]["id"] + | typeof regularImportOptions[number]["id"]; diff --git a/libs/common/src/enums/kdfType.ts b/libs/common/src/enums/kdfType.ts new file mode 100644 index 0000000000..cc7fa7e0dc --- /dev/null +++ b/libs/common/src/enums/kdfType.ts @@ -0,0 +1,7 @@ +export enum KdfType { + PBKDF2_SHA256 = 0, +} + +export const DEFAULT_KDF_TYPE = KdfType.PBKDF2_SHA256; +export const DEFAULT_KDF_ITERATIONS = 100000; +export const SEND_KDF_ITERATIONS = 100000; diff --git a/libs/common/src/enums/keySuffixOptions.ts b/libs/common/src/enums/keySuffixOptions.ts new file mode 100644 index 0000000000..2ae98d8e9f --- /dev/null +++ b/libs/common/src/enums/keySuffixOptions.ts @@ -0,0 +1,4 @@ +export enum KeySuffixOptions { + Auto = "auto", + Biometric = "biometric", +} diff --git a/libs/common/src/enums/linkedIdType.ts b/libs/common/src/enums/linkedIdType.ts new file mode 100644 index 0000000000..c38ebc1c6e --- /dev/null +++ b/libs/common/src/enums/linkedIdType.ts @@ -0,0 +1,40 @@ +export type LinkedIdType = LoginLinkedId | CardLinkedId | IdentityLinkedId; + +// LoginView +export enum LoginLinkedId { + Username = 100, + Password = 101, +} + +// CardView +export enum CardLinkedId { + CardholderName = 300, + ExpMonth = 301, + ExpYear = 302, + Code = 303, + Brand = 304, + Number = 305, +} + +// IdentityView +export enum IdentityLinkedId { + Title = 400, + MiddleName = 401, + Address1 = 402, + Address2 = 403, + Address3 = 404, + City = 405, + State = 406, + PostalCode = 407, + Country = 408, + Company = 409, + Email = 410, + Phone = 411, + Ssn = 412, + Username = 413, + PassportNumber = 414, + LicenseNumber = 415, + FirstName = 416, + LastName = 417, + FullName = 418, +} diff --git a/libs/common/src/enums/logLevelType.ts b/libs/common/src/enums/logLevelType.ts new file mode 100644 index 0000000000..709871dd5e --- /dev/null +++ b/libs/common/src/enums/logLevelType.ts @@ -0,0 +1,6 @@ +export enum LogLevelType { + Debug, + Info, + Warning, + Error, +} diff --git a/libs/common/src/enums/notificationType.ts b/libs/common/src/enums/notificationType.ts new file mode 100644 index 0000000000..77ebde01fc --- /dev/null +++ b/libs/common/src/enums/notificationType.ts @@ -0,0 +1,20 @@ +export enum NotificationType { + SyncCipherUpdate = 0, + SyncCipherCreate = 1, + SyncLoginDelete = 2, + SyncFolderDelete = 3, + SyncCiphers = 4, + + SyncVault = 5, + SyncOrgKeys = 6, + SyncFolderCreate = 7, + SyncFolderUpdate = 8, + SyncCipherDelete = 9, + SyncSettings = 10, + + LogOut = 11, + + SyncSendCreate = 12, + SyncSendUpdate = 13, + SyncSendDelete = 14, +} diff --git a/libs/common/src/enums/organizationApiKeyType.ts b/libs/common/src/enums/organizationApiKeyType.ts new file mode 100644 index 0000000000..27479a8de0 --- /dev/null +++ b/libs/common/src/enums/organizationApiKeyType.ts @@ -0,0 +1,4 @@ +export enum OrganizationApiKeyType { + Default = 0, + BillingSync = 1, +} diff --git a/libs/common/src/enums/organizationConnectionType.ts b/libs/common/src/enums/organizationConnectionType.ts new file mode 100644 index 0000000000..1291874370 --- /dev/null +++ b/libs/common/src/enums/organizationConnectionType.ts @@ -0,0 +1,3 @@ +export enum OrganizationConnectionType { + CloudBillingSync = 1, +} diff --git a/libs/common/src/enums/organizationUserStatusType.ts b/libs/common/src/enums/organizationUserStatusType.ts new file mode 100644 index 0000000000..3342218053 --- /dev/null +++ b/libs/common/src/enums/organizationUserStatusType.ts @@ -0,0 +1,5 @@ +export enum OrganizationUserStatusType { + Invited = 0, + Accepted = 1, + Confirmed = 2, +} diff --git a/libs/common/src/enums/organizationUserType.ts b/libs/common/src/enums/organizationUserType.ts new file mode 100644 index 0000000000..950fbaaeb9 --- /dev/null +++ b/libs/common/src/enums/organizationUserType.ts @@ -0,0 +1,7 @@ +export enum OrganizationUserType { + Owner = 0, + Admin = 1, + User = 2, + Manager = 3, + Custom = 4, +} diff --git a/libs/common/src/enums/paymentMethodType.ts b/libs/common/src/enums/paymentMethodType.ts new file mode 100644 index 0000000000..701bd886ac --- /dev/null +++ b/libs/common/src/enums/paymentMethodType.ts @@ -0,0 +1,11 @@ +export enum PaymentMethodType { + Card = 0, + BankAccount = 1, + PayPal = 2, + BitPay = 3, + Credit = 4, + WireTransfer = 5, + AppleInApp = 6, + GoogleInApp = 7, + Check = 8, +} diff --git a/libs/common/src/enums/permissions.ts b/libs/common/src/enums/permissions.ts new file mode 100644 index 0000000000..bb0021506a --- /dev/null +++ b/libs/common/src/enums/permissions.ts @@ -0,0 +1,28 @@ +export enum Permissions { + AccessEventLogs, + AccessImportExport, + AccessReports, + /** + * @deprecated Sep 29 2021: This permission has been split out to `createNewCollections`, `editAnyCollection`, and + * `deleteAnyCollection`. It exists here for backwards compatibility with Server versions <= 1.43.0 + */ + ManageAllCollections, + /** + * @deprecated Sep 29 2021: This permission has been split out to `editAssignedCollections` and + * `deleteAssignedCollections`. It exists here for backwards compatibility with Server versions <= 1.43.0 + */ + ManageAssignedCollections, + ManageGroups, + ManageOrganization, + ManagePolicies, + ManageProvider, + ManageUsers, + ManageUsersPassword, + CreateNewCollections, + EditAnyCollection, + DeleteAnyCollection, + EditAssignedCollections, + DeleteAssignedCollections, + ManageSso, + ManageBilling, +} diff --git a/libs/common/src/enums/planSponsorshipType.ts b/libs/common/src/enums/planSponsorshipType.ts new file mode 100644 index 0000000000..3b4c00467c --- /dev/null +++ b/libs/common/src/enums/planSponsorshipType.ts @@ -0,0 +1,3 @@ +export enum PlanSponsorshipType { + FamiliesForEnterprise = 0, +} diff --git a/libs/common/src/enums/planType.ts b/libs/common/src/enums/planType.ts new file mode 100644 index 0000000000..f4c89d2cbd --- /dev/null +++ b/libs/common/src/enums/planType.ts @@ -0,0 +1,14 @@ +export enum PlanType { + Free = 0, + FamiliesAnnually2019 = 1, + TeamsMonthly2019 = 2, + TeamsAnnually2019 = 3, + EnterpriseMonthly2019 = 4, + EnterpriseAnnually2019 = 5, + Custom = 6, + FamiliesAnnually = 7, + TeamsMonthly = 8, + TeamsAnnually = 9, + EnterpriseMonthly = 10, + EnterpriseAnnually = 11, +} diff --git a/libs/common/src/enums/policyType.ts b/libs/common/src/enums/policyType.ts new file mode 100644 index 0000000000..02dce41ebb --- /dev/null +++ b/libs/common/src/enums/policyType.ts @@ -0,0 +1,13 @@ +export enum PolicyType { + TwoFactorAuthentication = 0, // Requires users to have 2fa enabled + MasterPassword = 1, // Sets minimum requirements for master password complexity + PasswordGenerator = 2, // Sets minimum requirements/default type for generated passwords/passphrases + SingleOrg = 3, // Allows users to only be apart of one organization + RequireSso = 4, // Requires users to authenticate with SSO + PersonalOwnership = 5, // Disables personal vault ownership for adding/cloning items + DisableSend = 6, // Disables the ability to create and edit Bitwarden Sends + SendOptions = 7, // Sets restrictions or defaults for Bitwarden Sends + ResetPassword = 8, // Allows orgs to use reset password : also can enable auto-enrollment during invite flow + MaximumVaultTimeout = 9, // Sets the maximum allowed vault timeout + DisablePersonalVaultExport = 10, // Disable personal vault export +} diff --git a/libs/common/src/enums/productType.ts b/libs/common/src/enums/productType.ts new file mode 100644 index 0000000000..50b836d1f7 --- /dev/null +++ b/libs/common/src/enums/productType.ts @@ -0,0 +1,6 @@ +export enum ProductType { + Free = 0, + Families = 1, + Teams = 2, + Enterprise = 3, +} diff --git a/libs/common/src/enums/providerUserStatusType.ts b/libs/common/src/enums/providerUserStatusType.ts new file mode 100644 index 0000000000..3b84555117 --- /dev/null +++ b/libs/common/src/enums/providerUserStatusType.ts @@ -0,0 +1,5 @@ +export enum ProviderUserStatusType { + Invited = 0, + Accepted = 1, + Confirmed = 2, +} diff --git a/libs/common/src/enums/providerUserType.ts b/libs/common/src/enums/providerUserType.ts new file mode 100644 index 0000000000..00490adcfc --- /dev/null +++ b/libs/common/src/enums/providerUserType.ts @@ -0,0 +1,4 @@ +export enum ProviderUserType { + ProviderAdmin = 0, + ServiceUser = 1, +} diff --git a/libs/common/src/enums/secureNoteType.ts b/libs/common/src/enums/secureNoteType.ts new file mode 100644 index 0000000000..8015236d14 --- /dev/null +++ b/libs/common/src/enums/secureNoteType.ts @@ -0,0 +1,3 @@ +export enum SecureNoteType { + Generic = 0, +} diff --git a/libs/common/src/enums/sendType.ts b/libs/common/src/enums/sendType.ts new file mode 100644 index 0000000000..487930c90c --- /dev/null +++ b/libs/common/src/enums/sendType.ts @@ -0,0 +1,4 @@ +export enum SendType { + Text = 0, + File = 1, +} diff --git a/libs/common/src/enums/ssoEnums.ts b/libs/common/src/enums/ssoEnums.ts new file mode 100644 index 0000000000..d9be7274bb --- /dev/null +++ b/libs/common/src/enums/ssoEnums.ts @@ -0,0 +1,33 @@ +export enum SsoType { + None = 0, + OpenIdConnect = 1, + Saml2 = 2, +} + +export enum OpenIdConnectRedirectBehavior { + RedirectGet = 0, + FormPost = 1, +} + +export enum Saml2BindingType { + HttpRedirect = 1, + HttpPost = 2, +} + +export enum Saml2NameIdFormat { + NotConfigured = 0, + Unspecified = 1, + EmailAddress = 2, + X509SubjectName = 3, + WindowsDomainQualifiedName = 4, + KerberosPrincipalName = 5, + EntityIdentifier = 6, + Persistent = 7, + Transient = 8, +} + +export enum Saml2SigningBehavior { + IfIdpWantAuthnRequestsSigned = 0, + Always = 1, + Never = 3, +} diff --git a/libs/common/src/enums/stateVersion.ts b/libs/common/src/enums/stateVersion.ts new file mode 100644 index 0000000000..5aeb02e540 --- /dev/null +++ b/libs/common/src/enums/stateVersion.ts @@ -0,0 +1,7 @@ +export enum StateVersion { + One = 1, // Original flat key/value pair store + Two = 2, // Move to a typed State object + Three = 3, // Fix migration of users' premium status + Four = 4, // Fix 'Never Lock' option by removing stale data + Latest = Four, +} diff --git a/libs/common/src/enums/storageLocation.ts b/libs/common/src/enums/storageLocation.ts new file mode 100644 index 0000000000..46d50d1d38 --- /dev/null +++ b/libs/common/src/enums/storageLocation.ts @@ -0,0 +1,5 @@ +export enum StorageLocation { + Both = "both", + Disk = "disk", + Memory = "memory", +} diff --git a/libs/common/src/enums/themeType.ts b/libs/common/src/enums/themeType.ts new file mode 100644 index 0000000000..8afca77098 --- /dev/null +++ b/libs/common/src/enums/themeType.ts @@ -0,0 +1,7 @@ +export enum ThemeType { + System = "system", + Light = "light", + Dark = "dark", + Nord = "nord", + SolarizedDark = "solarizedDark", +} diff --git a/libs/common/src/enums/transactionType.ts b/libs/common/src/enums/transactionType.ts new file mode 100644 index 0000000000..34731a2ec3 --- /dev/null +++ b/libs/common/src/enums/transactionType.ts @@ -0,0 +1,7 @@ +export enum TransactionType { + Charge = 0, + Credit = 1, + PromotionalCredit = 2, + ReferralCredit = 3, + Refund = 4, +} diff --git a/libs/common/src/enums/twoFactorProviderType.ts b/libs/common/src/enums/twoFactorProviderType.ts new file mode 100644 index 0000000000..a170803201 --- /dev/null +++ b/libs/common/src/enums/twoFactorProviderType.ts @@ -0,0 +1,10 @@ +export enum TwoFactorProviderType { + Authenticator = 0, + Email = 1, + Duo = 2, + Yubikey = 3, + U2f = 4, + Remember = 5, + OrganizationDuo = 6, + WebAuthn = 7, +} diff --git a/libs/common/src/enums/uriMatchType.ts b/libs/common/src/enums/uriMatchType.ts new file mode 100644 index 0000000000..4a4193ba46 --- /dev/null +++ b/libs/common/src/enums/uriMatchType.ts @@ -0,0 +1,8 @@ +export enum UriMatchType { + Domain = 0, + Host = 1, + StartsWith = 2, + Exact = 3, + RegularExpression = 4, + Never = 5, +} diff --git a/libs/common/src/enums/verificationType.ts b/libs/common/src/enums/verificationType.ts new file mode 100644 index 0000000000..76a51ab7b5 --- /dev/null +++ b/libs/common/src/enums/verificationType.ts @@ -0,0 +1,4 @@ +export enum VerificationType { + MasterPassword = 0, + OTP = 1, +} diff --git a/libs/common/src/factories/accountFactory.ts b/libs/common/src/factories/accountFactory.ts new file mode 100644 index 0000000000..1fe5aee369 --- /dev/null +++ b/libs/common/src/factories/accountFactory.ts @@ -0,0 +1,13 @@ +import { Account } from "../models/domain/account"; + +export class AccountFactory { + private accountConstructor: new (init: Partial) => T; + + constructor(accountConstructor: new (init: Partial) => T) { + this.accountConstructor = accountConstructor; + } + + create(args: Partial) { + return new this.accountConstructor(args); + } +} diff --git a/libs/common/src/factories/globalStateFactory.ts b/libs/common/src/factories/globalStateFactory.ts new file mode 100644 index 0000000000..a2c25c4661 --- /dev/null +++ b/libs/common/src/factories/globalStateFactory.ts @@ -0,0 +1,13 @@ +import { GlobalState } from "../models/domain/globalState"; + +export class GlobalStateFactory { + private globalStateConstructor: new (init: Partial) => T; + + constructor(globalStateConstructor: new (init: Partial) => T) { + this.globalStateConstructor = globalStateConstructor; + } + + create(args?: Partial) { + return new this.globalStateConstructor(args); + } +} diff --git a/libs/common/src/factories/stateFactory.ts b/libs/common/src/factories/stateFactory.ts new file mode 100644 index 0000000000..203ae6722f --- /dev/null +++ b/libs/common/src/factories/stateFactory.ts @@ -0,0 +1,29 @@ +import { Account } from "../models/domain/account"; +import { GlobalState } from "../models/domain/globalState"; + +import { AccountFactory } from "./accountFactory"; +import { GlobalStateFactory } from "./globalStateFactory"; + +export class StateFactory< + TGlobal extends GlobalState = GlobalState, + TAccount extends Account = Account +> { + private globalStateFactory: GlobalStateFactory; + private accountFactory: AccountFactory; + + constructor( + globalStateConstructor: new (init: Partial) => TGlobal, + accountConstructor: new (init: Partial) => TAccount + ) { + this.globalStateFactory = new GlobalStateFactory(globalStateConstructor); + this.accountFactory = new AccountFactory(accountConstructor); + } + + createGlobal(args: Partial): TGlobal { + return this.globalStateFactory.create(args); + } + + createAccount(args: Partial): TAccount { + return this.accountFactory.create(args); + } +} diff --git a/libs/common/src/globals.d.ts b/libs/common/src/globals.d.ts new file mode 100644 index 0000000000..4859a0869e --- /dev/null +++ b/libs/common/src/globals.d.ts @@ -0,0 +1,2 @@ +declare function escape(s: string): string; +declare function unescape(s: string): string; diff --git a/libs/common/src/importers/ascendoCsvImporter.ts b/libs/common/src/importers/ascendoCsvImporter.ts new file mode 100644 index 0000000000..75191a1cbc --- /dev/null +++ b/libs/common/src/importers/ascendoCsvImporter.ts @@ -0,0 +1,59 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class AscendoCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.length < 2) { + return; + } + + const cipher = this.initLoginCipher(); + cipher.notes = this.getValueOrDefault(value[value.length - 1]); + cipher.name = this.getValueOrDefault(value[0], "--"); + + if (value.length > 2 && value.length % 2 === 0) { + for (let i = 0; i < value.length - 2; i += 2) { + const val: string = value[i + 2]; + const field: string = value[i + 1]; + if (this.isNullOrWhitespace(val) || this.isNullOrWhitespace(field)) { + continue; + } + + const fieldLower = field.toLowerCase(); + if (cipher.login.password == null && this.passwordFieldNames.indexOf(fieldLower) > -1) { + cipher.login.password = this.getValueOrDefault(val); + } else if ( + cipher.login.username == null && + this.usernameFieldNames.indexOf(fieldLower) > -1 + ) { + cipher.login.username = this.getValueOrDefault(val); + } else if ( + (cipher.login.uris == null || cipher.login.uris.length === 0) && + this.uriFieldNames.indexOf(fieldLower) > -1 + ) { + cipher.login.uris = this.makeUriArray(val); + } else { + this.processKvp(cipher, field, val); + } + } + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/avastCsvImporter.ts b/libs/common/src/importers/avastCsvImporter.ts new file mode 100644 index 0000000000..9bf1063954 --- /dev/null +++ b/libs/common/src/importers/avastCsvImporter.ts @@ -0,0 +1,28 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class AvastCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.name); + cipher.login.uris = this.makeUriArray(value.web); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.username = this.getValueOrDefault(value.login); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/avastJsonImporter.ts b/libs/common/src/importers/avastJsonImporter.ts new file mode 100644 index 0000000000..0d424a7186 --- /dev/null +++ b/libs/common/src/importers/avastJsonImporter.ts @@ -0,0 +1,68 @@ +import { CipherType } from "../enums/cipherType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class AvastJsonImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = JSON.parse(data); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + if (results.logins != null) { + results.logins.forEach((value: any) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.custName); + cipher.notes = this.getValueOrDefault(value.note); + cipher.login.uris = this.makeUriArray(value.url); + cipher.login.password = this.getValueOrDefault(value.pwd); + cipher.login.username = this.getValueOrDefault(value.loginName); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + } + + if (results.notes != null) { + results.notes.forEach((value: any) => { + const cipher = this.initLoginCipher(); + cipher.type = CipherType.SecureNote; + cipher.secureNote.type = SecureNoteType.Generic; + cipher.name = this.getValueOrDefault(value.label); + cipher.notes = this.getValueOrDefault(value.text); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + } + + if (results.cards != null) { + results.cards.forEach((value: any) => { + const cipher = this.initLoginCipher(); + cipher.type = CipherType.Card; + cipher.name = this.getValueOrDefault(value.custName); + cipher.notes = this.getValueOrDefault(value.note); + cipher.card.cardholderName = this.getValueOrDefault(value.holderName); + cipher.card.number = this.getValueOrDefault(value.cardNumber); + cipher.card.code = this.getValueOrDefault(value.cvv); + cipher.card.brand = this.getCardBrand(cipher.card.number); + if (value.expirationDate != null) { + if (value.expirationDate.month != null) { + cipher.card.expMonth = value.expirationDate.month + ""; + } + if (value.expirationDate.year != null) { + cipher.card.expYear = value.expirationDate.year + ""; + } + } + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/aviraCsvImporter.ts b/libs/common/src/importers/aviraCsvImporter.ts new file mode 100644 index 0000000000..f4c578b018 --- /dev/null +++ b/libs/common/src/importers/aviraCsvImporter.ts @@ -0,0 +1,41 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class AviraCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault( + value.name, + this.getValueOrDefault(this.nameFromUrl(value.website), "--") + ); + cipher.login.uris = this.makeUriArray(value.website); + cipher.login.password = this.getValueOrDefault(value.password); + + if ( + this.isNullOrWhitespace(value.username) && + !this.isNullOrWhitespace(value.secondary_username) + ) { + cipher.login.username = value.secondary_username; + } else { + cipher.login.username = this.getValueOrDefault(value.username); + cipher.notes = this.getValueOrDefault(value.secondary_username); + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/baseImporter.ts b/libs/common/src/importers/baseImporter.ts new file mode 100644 index 0000000000..122b34724d --- /dev/null +++ b/libs/common/src/importers/baseImporter.ts @@ -0,0 +1,466 @@ +import * as papa from "papaparse"; + +import { LogService } from "../abstractions/log.service"; +import { CipherType } from "../enums/cipherType"; +import { FieldType } from "../enums/fieldType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { Utils } from "../misc/utils"; +import { ImportResult } from "../models/domain/importResult"; +import { CipherView } from "../models/view/cipherView"; +import { CollectionView } from "../models/view/collectionView"; +import { FieldView } from "../models/view/fieldView"; +import { FolderView } from "../models/view/folderView"; +import { LoginUriView } from "../models/view/loginUriView"; +import { LoginView } from "../models/view/loginView"; +import { SecureNoteView } from "../models/view/secureNoteView"; +import { ConsoleLogService } from "../services/consoleLog.service"; + +export abstract class BaseImporter { + organizationId: string = null; + + protected logService: LogService = new ConsoleLogService(false); + + protected newLineRegex = /(?:\r\n|\r|\n)/; + + protected passwordFieldNames = [ + "password", + "pass word", + "passphrase", + "pass phrase", + "pass", + "code", + "code word", + "codeword", + "secret", + "secret word", + "personpwd", + "key", + "keyword", + "key word", + "keyphrase", + "key phrase", + "form_pw", + "wppassword", + "pin", + "pwd", + "pw", + "pword", + "passwd", + "p", + "serial", + "serial#", + "license key", + "reg #", + + // Non-English names + "passwort", + ]; + + protected usernameFieldNames = [ + "user", + "name", + "user name", + "username", + "login name", + "email", + "e-mail", + "id", + "userid", + "user id", + "login", + "form_loginname", + "wpname", + "mail", + "loginid", + "login id", + "log", + "personlogin", + "first name", + "last name", + "card#", + "account #", + "member", + "member #", + + // Non-English names + "nom", + "benutzername", + ]; + + protected notesFieldNames = [ + "note", + "notes", + "comment", + "comments", + "memo", + "description", + "free form", + "freeform", + "free text", + "freetext", + "free", + + // Non-English names + "kommentar", + ]; + + protected uriFieldNames: string[] = [ + "url", + "hyper link", + "hyperlink", + "link", + "host", + "hostname", + "host name", + "server", + "address", + "hyper ref", + "href", + "web", + "website", + "web site", + "site", + "web-site", + "uri", + + // Non-English names + "ort", + "adresse", + ]; + + protected parseCsvOptions = { + encoding: "UTF-8", + skipEmptyLines: false, + }; + + protected get organization() { + return this.organizationId != null; + } + + protected parseXml(data: string): Document { + const parser = new DOMParser(); + const doc = parser.parseFromString(data, "application/xml"); + return doc != null && doc.querySelector("parsererror") == null ? doc : null; + } + + protected parseCsv(data: string, header: boolean, options: any = {}): any[] { + const parseOptions: papa.ParseConfig = Object.assign( + { header: header }, + this.parseCsvOptions, + options + ); + data = this.splitNewLine(data).join("\n").trim(); + const result = papa.parse(data, parseOptions); + if (result.errors != null && result.errors.length > 0) { + result.errors.forEach((e) => { + if (e.row != null) { + this.logService.warning("Error parsing row " + e.row + ": " + e.message); + } + }); + } + return result.data && result.data.length > 0 ? result.data : null; + } + + protected parseSingleRowCsv(rowData: string) { + if (this.isNullOrWhitespace(rowData)) { + return null; + } + const parsedRow = this.parseCsv(rowData, false); + if (parsedRow != null && parsedRow.length > 0 && parsedRow[0].length > 0) { + return parsedRow[0]; + } + return null; + } + + protected makeUriArray(uri: string | string[]): LoginUriView[] { + if (uri == null) { + return null; + } + + if (typeof uri === "string") { + const loginUri = new LoginUriView(); + loginUri.uri = this.fixUri(uri); + if (this.isNullOrWhitespace(loginUri.uri)) { + return null; + } + loginUri.match = null; + return [loginUri]; + } + + if (uri.length > 0) { + const returnArr: LoginUriView[] = []; + uri.forEach((u) => { + const loginUri = new LoginUriView(); + loginUri.uri = this.fixUri(u); + if (this.isNullOrWhitespace(loginUri.uri)) { + return; + } + loginUri.match = null; + returnArr.push(loginUri); + }); + return returnArr.length === 0 ? null : returnArr; + } + + return null; + } + + protected fixUri(uri: string) { + if (uri == null) { + return null; + } + uri = uri.trim(); + if (uri.indexOf("://") === -1 && uri.indexOf(".") >= 0) { + uri = "http://" + uri; + } + if (uri.length > 1000) { + return uri.substring(0, 1000); + } + return uri; + } + + protected nameFromUrl(url: string) { + const hostname = Utils.getHostname(url); + if (this.isNullOrWhitespace(hostname)) { + return null; + } + return hostname.startsWith("www.") ? hostname.replace("www.", "") : hostname; + } + + protected isNullOrWhitespace(str: string): boolean { + return Utils.isNullOrWhitespace(str); + } + + protected getValueOrDefault(str: string, defaultValue: string = null): string { + if (this.isNullOrWhitespace(str)) { + return defaultValue; + } + return str; + } + + protected splitNewLine(str: string): string[] { + return str.split(this.newLineRegex); + } + + // ref https://stackoverflow.com/a/5911300 + protected getCardBrand(cardNum: string) { + if (this.isNullOrWhitespace(cardNum)) { + return null; + } + + // Visa + let re = new RegExp("^4"); + if (cardNum.match(re) != null) { + return "Visa"; + } + + // Mastercard + // Updated for Mastercard 2017 BINs expansion + if ( + /^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$/.test( + cardNum + ) + ) { + return "Mastercard"; + } + + // AMEX + re = new RegExp("^3[47]"); + if (cardNum.match(re) != null) { + return "Amex"; + } + + // Discover + re = new RegExp( + "^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)" + ); + if (cardNum.match(re) != null) { + return "Discover"; + } + + // Diners + re = new RegExp("^36"); + if (cardNum.match(re) != null) { + return "Diners Club"; + } + + // Diners - Carte Blanche + re = new RegExp("^30[0-5]"); + if (cardNum.match(re) != null) { + return "Diners Club"; + } + + // JCB + re = new RegExp("^35(2[89]|[3-8][0-9])"); + if (cardNum.match(re) != null) { + return "JCB"; + } + + // Visa Electron + re = new RegExp("^(4026|417500|4508|4844|491(3|7))"); + if (cardNum.match(re) != null) { + return "Visa"; + } + + return null; + } + + protected setCardExpiration(cipher: CipherView, expiration: string): boolean { + if (!this.isNullOrWhitespace(expiration)) { + expiration = expiration.replace(/\s/g, ""); + const parts = expiration.split("/"); + if (parts.length === 2) { + let month: string = null; + let year: string = null; + if (parts[0].length === 1 || parts[0].length === 2) { + month = parts[0]; + if (month.length === 2 && month[0] === "0") { + month = month.substr(1, 1); + } + } + if (parts[1].length === 2 || parts[1].length === 4) { + year = month.length === 2 ? "20" + parts[1] : parts[1]; + } + if (month != null && year != null) { + cipher.card.expMonth = month; + cipher.card.expYear = year; + return true; + } + } + } + return false; + } + + protected moveFoldersToCollections(result: ImportResult) { + result.folderRelationships.forEach((r) => result.collectionRelationships.push(r)); + result.collections = result.folders.map((f) => { + const collection = new CollectionView(); + collection.name = f.name; + return collection; + }); + result.folderRelationships = []; + result.folders = []; + } + + protected querySelectorDirectChild(parentEl: Element, query: string) { + const els = this.querySelectorAllDirectChild(parentEl, query); + return els.length === 0 ? null : els[0]; + } + + protected querySelectorAllDirectChild(parentEl: Element, query: string) { + return Array.from(parentEl.querySelectorAll(query)).filter((el) => el.parentNode === parentEl); + } + + protected initLoginCipher() { + const cipher = new CipherView(); + cipher.favorite = false; + cipher.notes = ""; + cipher.fields = []; + cipher.login = new LoginView(); + cipher.type = CipherType.Login; + return cipher; + } + + protected cleanupCipher(cipher: CipherView) { + if (cipher == null) { + return; + } + if (cipher.type !== CipherType.Login) { + cipher.login = null; + } + if (this.isNullOrWhitespace(cipher.name)) { + cipher.name = "--"; + } + if (this.isNullOrWhitespace(cipher.notes)) { + cipher.notes = null; + } else { + cipher.notes = cipher.notes.trim(); + } + if (cipher.fields != null && cipher.fields.length === 0) { + cipher.fields = null; + } + } + + protected processKvp( + cipher: CipherView, + key: string, + value: string, + type: FieldType = FieldType.Text + ) { + if (this.isNullOrWhitespace(value)) { + return; + } + if (this.isNullOrWhitespace(key)) { + key = ""; + } + if (value.length > 200 || value.trim().search(this.newLineRegex) > -1) { + if (cipher.notes == null) { + cipher.notes = ""; + } + cipher.notes += key + ": " + this.splitNewLine(value).join("\n") + "\n"; + } else { + if (cipher.fields == null) { + cipher.fields = []; + } + const field = new FieldView(); + field.type = type; + field.name = key; + field.value = value; + cipher.fields.push(field); + } + } + + protected processFolder(result: ImportResult, folderName: string) { + let folderIndex = result.folders.length; + const hasFolder = !this.isNullOrWhitespace(folderName); + let addFolder = hasFolder; + + if (hasFolder) { + for (let i = 0; i < result.folders.length; i++) { + if (result.folders[i].name === folderName) { + addFolder = false; + folderIndex = i; + break; + } + } + } + + if (addFolder) { + const f = new FolderView(); + f.name = folderName; + result.folders.push(f); + } + if (hasFolder) { + result.folderRelationships.push([result.ciphers.length, folderIndex]); + } + } + + protected convertToNoteIfNeeded(cipher: CipherView) { + if ( + cipher.type === CipherType.Login && + this.isNullOrWhitespace(cipher.login.username) && + this.isNullOrWhitespace(cipher.login.password) && + (cipher.login.uris == null || cipher.login.uris.length === 0) + ) { + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + } + } + + protected processFullName(cipher: CipherView, fullName: string) { + if (this.isNullOrWhitespace(fullName)) { + return; + } + + const nameParts = fullName.split(" "); + if (nameParts.length > 0) { + cipher.identity.firstName = this.getValueOrDefault(nameParts[0]); + } + if (nameParts.length === 2) { + cipher.identity.lastName = this.getValueOrDefault(nameParts[1]); + } else if (nameParts.length >= 3) { + cipher.identity.middleName = this.getValueOrDefault(nameParts[1]); + cipher.identity.lastName = nameParts.slice(2, nameParts.length).join(" "); + } + } +} diff --git a/libs/common/src/importers/bitwardenCsvImporter.ts b/libs/common/src/importers/bitwardenCsvImporter.ts new file mode 100644 index 0000000000..cc5419c303 --- /dev/null +++ b/libs/common/src/importers/bitwardenCsvImporter.ts @@ -0,0 +1,120 @@ +import { CipherRepromptType } from "../enums/cipherRepromptType"; +import { CipherType } from "../enums/cipherType"; +import { FieldType } from "../enums/fieldType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { CipherView } from "../models/view/cipherView"; +import { CollectionView } from "../models/view/collectionView"; +import { FieldView } from "../models/view/fieldView"; +import { LoginView } from "../models/view/loginView"; +import { SecureNoteView } from "../models/view/secureNoteView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class BitwardenCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (this.organization && !this.isNullOrWhitespace(value.collections)) { + const collections = (value.collections as string).split(","); + collections.forEach((col) => { + let addCollection = true; + let collectionIndex = result.collections.length; + + for (let i = 0; i < result.collections.length; i++) { + if (result.collections[i].name === col) { + addCollection = false; + collectionIndex = i; + break; + } + } + + if (addCollection) { + const collection = new CollectionView(); + collection.name = col; + result.collections.push(collection); + } + + result.collectionRelationships.push([result.ciphers.length, collectionIndex]); + }); + } else if (!this.organization) { + this.processFolder(result, value.folder); + } + + const cipher = new CipherView(); + cipher.favorite = + !this.organization && this.getValueOrDefault(value.favorite, "0") !== "0" ? true : false; + cipher.type = CipherType.Login; + cipher.notes = this.getValueOrDefault(value.notes); + cipher.name = this.getValueOrDefault(value.name, "--"); + try { + cipher.reprompt = parseInt( + this.getValueOrDefault(value.reprompt, CipherRepromptType.None.toString()), + 10 + ); + } catch (e) { + // eslint-disable-next-line + console.error("Unable to parse reprompt value", e); + cipher.reprompt = CipherRepromptType.None; + } + + if (!this.isNullOrWhitespace(value.fields)) { + const fields = this.splitNewLine(value.fields); + for (let i = 0; i < fields.length; i++) { + if (this.isNullOrWhitespace(fields[i])) { + continue; + } + + const delimPosition = fields[i].lastIndexOf(": "); + if (delimPosition === -1) { + continue; + } + + if (cipher.fields == null) { + cipher.fields = []; + } + + const field = new FieldView(); + field.name = fields[i].substr(0, delimPosition); + field.value = null; + field.type = FieldType.Text; + if (fields[i].length > delimPosition + 2) { + field.value = fields[i].substr(delimPosition + 2); + } + cipher.fields.push(field); + } + } + + const valueType = value.type != null ? value.type.toLowerCase() : null; + switch (valueType) { + case "note": + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + break; + default: { + cipher.type = CipherType.Login; + cipher.login = new LoginView(); + cipher.login.totp = this.getValueOrDefault(value.login_totp || value.totp); + cipher.login.username = this.getValueOrDefault(value.login_username || value.username); + cipher.login.password = this.getValueOrDefault(value.login_password || value.password); + const uris = this.parseSingleRowCsv(value.login_uri || value.uri); + cipher.login.uris = this.makeUriArray(uris); + break; + } + } + + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/bitwardenJsonImporter.ts b/libs/common/src/importers/bitwardenJsonImporter.ts new file mode 100644 index 0000000000..ed707a45d8 --- /dev/null +++ b/libs/common/src/importers/bitwardenJsonImporter.ts @@ -0,0 +1,179 @@ +import { CryptoService } from "../abstractions/crypto.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { EncString } from "../models/domain/encString"; +import { ImportResult } from "../models/domain/importResult"; +import { CipherWithIdExport } from "../models/export/cipherWithIdsExport"; +import { CollectionWithIdExport } from "../models/export/collectionWithIdExport"; +import { FolderWithIdExport } from "../models/export/folderWithIdExport"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class BitwardenJsonImporter extends BaseImporter implements Importer { + private results: any; + private result: ImportResult; + + constructor(protected cryptoService: CryptoService, protected i18nService: I18nService) { + super(); + } + + async parse(data: string): Promise { + this.result = new ImportResult(); + this.results = JSON.parse(data); + if (this.results == null || this.results.items == null) { + if (this.results?.passwordProtected) { + this.result.success = false; + this.result.missingPassword = true; + this.result.errorMessage = this.i18nService.t("importPasswordRequired"); + return this.result; + } + + this.result.success = false; + return this.result; + } + + if (this.results.encrypted) { + await this.parseEncrypted(); + } else { + this.parseDecrypted(); + } + + return this.result; + } + + private async parseEncrypted() { + if (this.results.encKeyValidation_DO_NOT_EDIT != null) { + const orgKey = await this.cryptoService.getOrgKey(this.organizationId); + const encKeyValidation = new EncString(this.results.encKeyValidation_DO_NOT_EDIT); + const encKeyValidationDecrypt = await this.cryptoService.decryptToUtf8( + encKeyValidation, + orgKey + ); + if (encKeyValidationDecrypt === null) { + this.result.success = false; + this.result.errorMessage = this.i18nService.t("importEncKeyError"); + return; + } + } + + const groupingsMap = new Map(); + + if (this.organization && this.results.collections != null) { + for (const c of this.results.collections as CollectionWithIdExport[]) { + const collection = CollectionWithIdExport.toDomain(c); + if (collection != null) { + collection.id = null; + collection.organizationId = this.organizationId; + const view = await collection.decrypt(); + groupingsMap.set(c.id, this.result.collections.length); + this.result.collections.push(view); + } + } + } else if (!this.organization && this.results.folders != null) { + for (const f of this.results.folders as FolderWithIdExport[]) { + const folder = FolderWithIdExport.toDomain(f); + if (folder != null) { + folder.id = null; + const view = await folder.decrypt(); + groupingsMap.set(f.id, this.result.folders.length); + this.result.folders.push(view); + } + } + } + + for (const c of this.results.items as CipherWithIdExport[]) { + const cipher = CipherWithIdExport.toDomain(c); + // reset ids incase they were set for some reason + cipher.id = null; + cipher.folderId = null; + cipher.organizationId = this.organizationId; + cipher.collectionIds = null; + + // make sure password history is limited + if (cipher.passwordHistory != null && cipher.passwordHistory.length > 5) { + cipher.passwordHistory = cipher.passwordHistory.slice(0, 5); + } + + if (!this.organization && c.folderId != null && groupingsMap.has(c.folderId)) { + this.result.folderRelationships.push([ + this.result.ciphers.length, + groupingsMap.get(c.folderId), + ]); + } else if (this.organization && c.collectionIds != null) { + c.collectionIds.forEach((cId) => { + if (groupingsMap.has(cId)) { + this.result.collectionRelationships.push([ + this.result.ciphers.length, + groupingsMap.get(cId), + ]); + } + }); + } + + const view = await cipher.decrypt(); + this.cleanupCipher(view); + this.result.ciphers.push(view); + } + + this.result.success = true; + } + + private parseDecrypted() { + const groupingsMap = new Map(); + if (this.organization && this.results.collections != null) { + this.results.collections.forEach((c: CollectionWithIdExport) => { + const collection = CollectionWithIdExport.toView(c); + if (collection != null) { + collection.id = null; + collection.organizationId = null; + groupingsMap.set(c.id, this.result.collections.length); + this.result.collections.push(collection); + } + }); + } else if (!this.organization && this.results.folders != null) { + this.results.folders.forEach((f: FolderWithIdExport) => { + const folder = FolderWithIdExport.toView(f); + if (folder != null) { + folder.id = null; + groupingsMap.set(f.id, this.result.folders.length); + this.result.folders.push(folder); + } + }); + } + + this.results.items.forEach((c: CipherWithIdExport) => { + const cipher = CipherWithIdExport.toView(c); + // reset ids incase they were set for some reason + cipher.id = null; + cipher.folderId = null; + cipher.organizationId = null; + cipher.collectionIds = null; + + // make sure password history is limited + if (cipher.passwordHistory != null && cipher.passwordHistory.length > 5) { + cipher.passwordHistory = cipher.passwordHistory.slice(0, 5); + } + + if (!this.organization && c.folderId != null && groupingsMap.has(c.folderId)) { + this.result.folderRelationships.push([ + this.result.ciphers.length, + groupingsMap.get(c.folderId), + ]); + } else if (this.organization && c.collectionIds != null) { + c.collectionIds.forEach((cId) => { + if (groupingsMap.has(cId)) { + this.result.collectionRelationships.push([ + this.result.ciphers.length, + groupingsMap.get(cId), + ]); + } + }); + } + + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + + this.result.success = true; + } +} diff --git a/libs/common/src/importers/bitwardenPasswordProtectedImporter.ts b/libs/common/src/importers/bitwardenPasswordProtectedImporter.ts new file mode 100644 index 0000000000..54da71b5e5 --- /dev/null +++ b/libs/common/src/importers/bitwardenPasswordProtectedImporter.ts @@ -0,0 +1,81 @@ +import { CryptoService } from "../abstractions/crypto.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { KdfType } from "../enums/kdfType"; +import { EncString } from "../models/domain/encString"; +import { ImportResult } from "../models/domain/importResult"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; + +import { BitwardenJsonImporter } from "./bitwardenJsonImporter"; +import { Importer } from "./importer"; + +interface BitwardenPasswordProtectedFileFormat { + encrypted: boolean; + passwordProtected: boolean; + salt: string; + kdfIterations: number; + kdfType: number; + encKeyValidation_DO_NOT_EDIT: string; + data: string; +} + +export class BitwardenPasswordProtectedImporter extends BitwardenJsonImporter implements Importer { + private key: SymmetricCryptoKey; + + constructor(cryptoService: CryptoService, i18nService: I18nService, private password: string) { + super(cryptoService, i18nService); + } + + async parse(data: string): Promise { + const result = new ImportResult(); + const parsedData = JSON.parse(data); + if (this.cannotParseFile(parsedData)) { + result.success = false; + return result; + } + + if (!(await this.checkPassword(parsedData))) { + result.success = false; + result.errorMessage = this.i18nService.t("importEncKeyError"); + return result; + } + + const encData = new EncString(parsedData.data); + const clearTextData = await this.cryptoService.decryptToUtf8(encData, this.key); + return await super.parse(clearTextData); + } + + private async checkPassword(jdoc: BitwardenPasswordProtectedFileFormat): Promise { + this.key = await this.cryptoService.makePinKey( + this.password, + jdoc.salt, + KdfType.PBKDF2_SHA256, + jdoc.kdfIterations + ); + + const encKeyValidation = new EncString(jdoc.encKeyValidation_DO_NOT_EDIT); + + const encKeyValidationDecrypt = await this.cryptoService.decryptToUtf8( + encKeyValidation, + this.key + ); + if (encKeyValidationDecrypt === null) { + return false; + } + return true; + } + + private cannotParseFile(jdoc: BitwardenPasswordProtectedFileFormat): boolean { + return ( + !jdoc || + !jdoc.encrypted || + !jdoc.passwordProtected || + !jdoc.salt || + !jdoc.kdfIterations || + typeof jdoc.kdfIterations !== "number" || + jdoc.kdfType == null || + KdfType[jdoc.kdfType] == null || + !jdoc.encKeyValidation_DO_NOT_EDIT || + !jdoc.data + ); + } +} diff --git a/libs/common/src/importers/blackBerryCsvImporter.ts b/libs/common/src/importers/blackBerryCsvImporter.ts new file mode 100644 index 0000000000..ea3d08ebcf --- /dev/null +++ b/libs/common/src/importers/blackBerryCsvImporter.ts @@ -0,0 +1,36 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class BlackBerryCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.grouping === "list") { + return; + } + const cipher = this.initLoginCipher(); + cipher.favorite = value.fav === "1"; + cipher.name = this.getValueOrDefault(value.name); + cipher.notes = this.getValueOrDefault(value.extra); + if (value.grouping !== "note") { + cipher.login.uris = this.makeUriArray(value.url); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.username = this.getValueOrDefault(value.username); + } + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/blurCsvImporter.ts b/libs/common/src/importers/blurCsvImporter.ts new file mode 100644 index 0000000000..ca9ecd1cd8 --- /dev/null +++ b/libs/common/src/importers/blurCsvImporter.ts @@ -0,0 +1,41 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class BlurCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.label === "null") { + value.label = null; + } + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault( + value.label, + this.getValueOrDefault(this.nameFromUrl(value.domain), "--") + ); + cipher.login.uris = this.makeUriArray(value.domain); + cipher.login.password = this.getValueOrDefault(value.password); + + if (this.isNullOrWhitespace(value.email) && !this.isNullOrWhitespace(value.username)) { + cipher.login.username = value.username; + } else { + cipher.login.username = this.getValueOrDefault(value.email); + cipher.notes = this.getValueOrDefault(value.username); + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/buttercupCsvImporter.ts b/libs/common/src/importers/buttercupCsvImporter.ts new file mode 100644 index 0000000000..aa3dda2d43 --- /dev/null +++ b/libs/common/src/importers/buttercupCsvImporter.ts @@ -0,0 +1,50 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +const OfficialProps = ["!group_id", "!group_name", "title", "username", "password", "URL", "id"]; + +export class ButtercupCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + this.processFolder(result, this.getValueOrDefault(value["!group_name"])); + + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.title, "--"); + cipher.login.username = this.getValueOrDefault(value.username); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.uris = this.makeUriArray(value.URL); + + let processingCustomFields = false; + for (const prop in value) { + // eslint-disable-next-line + if (value.hasOwnProperty(prop)) { + if (!processingCustomFields && OfficialProps.indexOf(prop) === -1) { + processingCustomFields = true; + } + if (processingCustomFields) { + this.processKvp(cipher, prop, value[prop]); + } + } + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/chromeCsvImporter.ts b/libs/common/src/importers/chromeCsvImporter.ts new file mode 100644 index 0000000000..35c72ac342 --- /dev/null +++ b/libs/common/src/importers/chromeCsvImporter.ts @@ -0,0 +1,28 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class ChromeCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.name, "--"); + cipher.login.username = this.getValueOrDefault(value.username); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.uris = this.makeUriArray(value.url); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/clipperzHtmlImporter.ts b/libs/common/src/importers/clipperzHtmlImporter.ts new file mode 100644 index 0000000000..c4f0402c5b --- /dev/null +++ b/libs/common/src/importers/clipperzHtmlImporter.ts @@ -0,0 +1,88 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class ClipperzHtmlImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const doc = this.parseXml(data); + if (doc == null) { + result.success = false; + return Promise.resolve(result); + } + + const textarea = doc.querySelector("textarea"); + if (textarea == null || this.isNullOrWhitespace(textarea.textContent)) { + result.errorMessage = "Missing textarea."; + result.success = false; + return Promise.resolve(result); + } + + const entries = JSON.parse(textarea.textContent); + entries.forEach((entry: any) => { + const cipher = this.initLoginCipher(); + if (!this.isNullOrWhitespace(entry.label)) { + cipher.name = entry.label.split(" ")[0]; + } + if (entry.data != null && !this.isNullOrWhitespace(entry.data.notes)) { + cipher.notes = entry.data.notes.split("\\n").join("\n"); + } + + if (entry.currentVersion != null && entry.currentVersion.fields != null) { + for (const property in entry.currentVersion.fields) { + // eslint-disable-next-line + if (!entry.currentVersion.fields.hasOwnProperty(property)) { + continue; + } + + const field = entry.currentVersion.fields[property]; + const actionType = field.actionType != null ? field.actionType.toLowerCase() : null; + switch (actionType) { + case "password": + cipher.login.password = this.getValueOrDefault(field.value); + break; + case "email": + case "username": + case "user": + case "name": + cipher.login.username = this.getValueOrDefault(field.value); + break; + case "url": + cipher.login.uris = this.makeUriArray(field.value); + break; + default: { + const labelLower = field.label != null ? field.label.toLowerCase() : null; + if ( + cipher.login.password == null && + this.passwordFieldNames.indexOf(labelLower) > -1 + ) { + cipher.login.password = this.getValueOrDefault(field.value); + } else if ( + cipher.login.username == null && + this.usernameFieldNames.indexOf(labelLower) > -1 + ) { + cipher.login.username = this.getValueOrDefault(field.value); + } else if ( + (cipher.login.uris == null || cipher.login.uris.length === 0) && + this.uriFieldNames.indexOf(labelLower) > -1 + ) { + cipher.login.uris = this.makeUriArray(field.value); + } else { + this.processKvp(cipher, field.label, field.value); + } + break; + } + } + } + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/codebookCsvImporter.ts b/libs/common/src/importers/codebookCsvImporter.ts new file mode 100644 index 0000000000..f842f21c09 --- /dev/null +++ b/libs/common/src/importers/codebookCsvImporter.ts @@ -0,0 +1,47 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class CodebookCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + this.processFolder(result, this.getValueOrDefault(value.Category)); + + const cipher = this.initLoginCipher(); + cipher.favorite = this.getValueOrDefault(value.Favorite) === "True"; + cipher.name = this.getValueOrDefault(value.Entry, "--"); + cipher.notes = this.getValueOrDefault(value.Note); + cipher.login.username = this.getValueOrDefault(value.Username, value.Email); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.totp = this.getValueOrDefault(value.TOTP); + cipher.login.uris = this.makeUriArray(value.Website); + + if (!this.isNullOrWhitespace(value.Username)) { + this.processKvp(cipher, "Email", value.Email); + } + this.processKvp(cipher, "Phone", value.Phone); + this.processKvp(cipher, "PIN", value.PIN); + this.processKvp(cipher, "Account", value.Account); + this.processKvp(cipher, "Date", value.Date); + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/dashlaneImporters/dashlaneCsvImporter.ts b/libs/common/src/importers/dashlaneImporters/dashlaneCsvImporter.ts new file mode 100644 index 0000000000..2bb6ce14fe --- /dev/null +++ b/libs/common/src/importers/dashlaneImporters/dashlaneCsvImporter.ts @@ -0,0 +1,271 @@ +import { CipherType } from "../../enums/cipherType"; +import { SecureNoteType } from "../../enums/secureNoteType"; +import { ImportResult } from "../../models/domain/importResult"; +import { CardView } from "../../models/view/cardView"; +import { CipherView } from "../../models/view/cipherView"; +import { IdentityView } from "../../models/view/identityView"; +import { LoginView } from "../../models/view/loginView"; +import { BaseImporter } from "../baseImporter"; +import { Importer } from "../importer"; + +import { + CredentialsRecord, + IdRecord, + PaymentsRecord, + PersonalInformationRecord, + SecureNoteRecord, +} from "./types/dashlaneCsvTypes"; + +const _mappedCredentialsColums = new Set([ + "title", + "note", + "username", + "password", + "url", + "otpSecret", + "category", +]); + +const _mappedPersonalInfoAsIdentiyColumns = new Set([ + "type", + "title", + "first_name", + "middle_name", + "last_name", + "login", + "email", + "phone_number", + "address", + "country", + "state", + "city", + "zip", + // Skip item_name as we already have set a combined name + "item_name", +]); + +const _mappedSecureNoteColumns = new Set(["title", "note"]); + +export class DashlaneCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + if (results[0].type != null && results[0].title != null) { + const personalRecords = results as PersonalInformationRecord[]; + + // If personalRecords has only one "name" then create an Identity-Cipher + if (personalRecords.filter((x) => x.type === "name").length === 1) { + const cipher = this.initLoginCipher(); + cipher.type = CipherType.Identity; + cipher.identity = new IdentityView(); + results.forEach((row) => { + this.parsePersonalInformationRecordAsIdentity(cipher, row); + }); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + result.success = true; + return Promise.resolve(result); + } + } + + results.forEach((row) => { + const cipher = this.initLoginCipher(); + + const rowKeys = Object.keys(row); + if (rowKeys[0] === "username") { + this.processFolder(result, row.category); + this.parseCredentialsRecord(cipher, row); + } + + if (rowKeys[0] === "type" && rowKeys[1] === "account_name") { + this.parsePaymentRecord(cipher, row); + } + + if (rowKeys[0] === "type" && rowKeys[1] === "number") { + this.parseIdRecord(cipher, row); + } + + if ((rowKeys[0] === "type") != null && rowKeys[1] === "title") { + this.parsePersonalInformationRecord(cipher, row); + } + + if (rowKeys[0] === "title" && rowKeys[1] === "note") { + this.parseSecureNoteRecords(cipher, row); + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + parseCredentialsRecord(cipher: CipherView, row: CredentialsRecord) { + cipher.type = CipherType.Login; + cipher.login = new LoginView(); + + cipher.name = row.title; + cipher.notes = row.note; + cipher.login.username = row.username; + cipher.login.password = row.password; + cipher.login.totp = row.otpSecret; + cipher.login.uris = this.makeUriArray(row.url); + + this.importUnmappedFields(cipher, row, _mappedCredentialsColums); + } + + parsePaymentRecord(cipher: CipherView, row: PaymentsRecord) { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + + cipher.name = row.account_name; + let mappedValues: string[] = []; + switch (row.type) { + case "credit_card": + cipher.card.cardholderName = row.account_name; + cipher.card.number = row.cc_number; + cipher.card.brand = this.getCardBrand(cipher.card.number); + cipher.card.code = row.code; + cipher.card.expMonth = row.expiration_month; + cipher.card.expYear = row.expiration_year.substring(2, 4); + + // If you add more mapped fields please extend this + mappedValues = [ + "account_name", + "account_holder", + "cc_number", + "code", + "expiration_month", + "expiration_year", + ]; + break; + case "bank": + cipher.card.cardholderName = row.account_holder; + cipher.card.number = row.account_number; + + // If you add more mapped fields please extend this + mappedValues = ["account_name", "account_holder", "account_number"]; + break; + default: + break; + } + + this.importUnmappedFields(cipher, row, new Set(mappedValues)); + } + + parseIdRecord(cipher: CipherView, row: IdRecord) { + cipher.type = CipherType.Identity; + cipher.identity = new IdentityView(); + + const mappedValues: string[] = ["name", "number"]; + switch (row.type) { + case "card": + cipher.name = `${row.name} ${row.type}`; + this.processFullName(cipher, row.name); + cipher.identity.licenseNumber = row.number; + break; + case "passport": + cipher.name = `${row.name} ${row.type}`; + this.processFullName(cipher, row.name); + cipher.identity.passportNumber = row.number; + break; + case "license": + cipher.name = `${row.name} ${row.type}`; + this.processFullName(cipher, row.name); + cipher.identity.licenseNumber = row.number; + cipher.identity.state = row.state; + + mappedValues.push("state"); + break; + case "social_security": + cipher.name = `${row.name} ${row.type}`; + this.processFullName(cipher, row.name); + cipher.identity.ssn = row.number; + break; + case "tax_number": + cipher.name = row.type; + cipher.identity.licenseNumber = row.number; + break; + + default: + break; + } + + // If you add more mapped fields please extend this + this.importUnmappedFields(cipher, row, new Set(mappedValues)); + } + + parsePersonalInformationRecord(cipher: CipherView, row: PersonalInformationRecord) { + cipher.type = CipherType.SecureNote; + cipher.secureNote.type = SecureNoteType.Generic; + if (row.type === "name") { + cipher.name = `${row.title} ${row.first_name} ${row.middle_name} ${row.last_name}` + .replace(" ", " ") + .trim(); + } else { + cipher.name = row.item_name; + } + + const dataRow = row as any; + Object.keys(row).forEach((key) => { + this.processKvp(cipher, key, dataRow[key]); + }); + } + + parsePersonalInformationRecordAsIdentity(cipher: CipherView, row: PersonalInformationRecord) { + switch (row.type) { + case "name": + this.processFullName(cipher, `${row.first_name} ${row.middle_name} ${row.last_name}`); + cipher.identity.title = row.title; + cipher.name = cipher.identity.fullName; + + cipher.identity.username = row.login; + break; + case "email": + cipher.identity.email = row.email; + break; + case "number": + cipher.identity.phone = row.phone_number; + break; + case "address": + cipher.identity.address1 = row.address; + cipher.identity.city = row.city; + cipher.identity.postalCode = row.zip; + cipher.identity.state = row.state; + cipher.identity.country = row.country; + break; + default: + break; + } + + this.importUnmappedFields(cipher, row, _mappedPersonalInfoAsIdentiyColumns); + } + + parseSecureNoteRecords(cipher: CipherView, row: SecureNoteRecord) { + cipher.type = CipherType.SecureNote; + cipher.secureNote.type = SecureNoteType.Generic; + cipher.name = row.title; + cipher.notes = row.note; + + this.importUnmappedFields(cipher, row, _mappedSecureNoteColumns); + } + + importUnmappedFields(cipher: CipherView, row: any, mappedValues: Set) { + const unmappedFields = Object.keys(row).filter((x) => !mappedValues.has(x)); + unmappedFields.forEach((key) => { + const item = row as any; + this.processKvp(cipher, key, item[key]); + }); + } +} diff --git a/libs/common/src/importers/dashlaneImporters/dashlaneJsonImporter.ts b/libs/common/src/importers/dashlaneImporters/dashlaneJsonImporter.ts new file mode 100644 index 0000000000..cb7db59dad --- /dev/null +++ b/libs/common/src/importers/dashlaneImporters/dashlaneJsonImporter.ts @@ -0,0 +1,171 @@ +import { CipherType } from "../../enums/cipherType"; +import { SecureNoteType } from "../../enums/secureNoteType"; +import { ImportResult } from "../../models/domain/importResult"; +import { CardView } from "../../models/view/cardView"; +import { CipherView } from "../../models/view/cipherView"; +import { IdentityView } from "../../models/view/identityView"; +import { SecureNoteView } from "../../models/view/secureNoteView"; +import { BaseImporter } from "../baseImporter"; +import { Importer } from "../importer"; + +const HandledResults = new Set([ + "ADDRESS", + "AUTHENTIFIANT", + "BANKSTATEMENT", + "IDCARD", + "IDENTITY", + "PAYMENTMEANS_CREDITCARD", + "PAYMENTMEAN_PAYPAL", + "EMAIL", +]); + +export class DashlaneJsonImporter extends BaseImporter implements Importer { + private result: ImportResult; + + parse(data: string): Promise { + this.result = new ImportResult(); + const results = JSON.parse(data); + if (results == null || results.length === 0) { + this.result.success = false; + return Promise.resolve(this.result); + } + + if (results.ADDRESS != null) { + this.processAddress(results.ADDRESS); + } + if (results.AUTHENTIFIANT != null) { + this.processAuth(results.AUTHENTIFIANT); + } + if (results.BANKSTATEMENT != null) { + this.processNote(results.BANKSTATEMENT, "BankAccountName"); + } + if (results.IDCARD != null) { + this.processNote(results.IDCARD, "Fullname"); + } + if (results.PAYMENTMEANS_CREDITCARD != null) { + this.processCard(results.PAYMENTMEANS_CREDITCARD); + } + if (results.IDENTITY != null) { + this.processIdentity(results.IDENTITY); + } + + for (const key in results) { + // eslint-disable-next-line + if (results.hasOwnProperty(key) && !HandledResults.has(key)) { + this.processNote(results[key], null, "Generic Note"); + } + } + + this.result.success = true; + return Promise.resolve(this.result); + } + + private processAuth(results: any[]) { + results.forEach((credential: any) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(credential.title); + + cipher.login.username = this.getValueOrDefault( + credential.login, + this.getValueOrDefault(credential.secondaryLogin) + ); + if (this.isNullOrWhitespace(cipher.login.username)) { + cipher.login.username = this.getValueOrDefault(credential.email); + } else if (!this.isNullOrWhitespace(credential.email)) { + cipher.notes = "Email: " + credential.email + "\n"; + } + + cipher.login.password = this.getValueOrDefault(credential.password); + cipher.login.uris = this.makeUriArray(credential.domain); + cipher.notes += this.getValueOrDefault(credential.note, ""); + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + } + + private processIdentity(results: any[]) { + results.forEach((obj: any) => { + const cipher = new CipherView(); + cipher.identity = new IdentityView(); + cipher.type = CipherType.Identity; + cipher.name = this.getValueOrDefault(obj.fullName, ""); + const nameParts = cipher.name.split(" "); + if (nameParts.length > 0) { + cipher.identity.firstName = this.getValueOrDefault(nameParts[0]); + } + if (nameParts.length === 2) { + cipher.identity.lastName = this.getValueOrDefault(nameParts[1]); + } else if (nameParts.length === 3) { + cipher.identity.middleName = this.getValueOrDefault(nameParts[1]); + cipher.identity.lastName = this.getValueOrDefault(nameParts[2]); + } + cipher.identity.username = this.getValueOrDefault(obj.pseudo); + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + } + + private processAddress(results: any[]) { + results.forEach((obj: any) => { + const cipher = new CipherView(); + cipher.identity = new IdentityView(); + cipher.type = CipherType.Identity; + cipher.name = this.getValueOrDefault(obj.addressName); + cipher.identity.address1 = this.getValueOrDefault(obj.addressFull); + cipher.identity.city = this.getValueOrDefault(obj.city); + cipher.identity.state = this.getValueOrDefault(obj.state); + cipher.identity.postalCode = this.getValueOrDefault(obj.zipcode); + cipher.identity.country = this.getValueOrDefault(obj.country); + if (cipher.identity.country != null) { + cipher.identity.country = cipher.identity.country.toUpperCase(); + } + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + } + + private processCard(results: any[]) { + results.forEach((obj: any) => { + const cipher = new CipherView(); + cipher.card = new CardView(); + cipher.type = CipherType.Card; + cipher.name = this.getValueOrDefault(obj.bank); + cipher.card.number = this.getValueOrDefault(obj.cardNumber); + cipher.card.brand = this.getCardBrand(cipher.card.number); + cipher.card.cardholderName = this.getValueOrDefault(obj.owner); + if (!this.isNullOrWhitespace(cipher.card.brand)) { + if (this.isNullOrWhitespace(cipher.name)) { + cipher.name = cipher.card.brand; + } else { + cipher.name += " - " + cipher.card.brand; + } + } + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + } + + private processNote(results: any[], nameProperty: string, name: string = null) { + results.forEach((obj: any) => { + const cipher = new CipherView(); + cipher.secureNote = new SecureNoteView(); + cipher.type = CipherType.SecureNote; + cipher.secureNote.type = SecureNoteType.Generic; + if (name != null) { + cipher.name = name; + } else { + cipher.name = this.getValueOrDefault(obj[nameProperty]); + } + for (const key in obj) { + // eslint-disable-next-line + if (obj.hasOwnProperty(key) && key !== nameProperty) { + this.processKvp(cipher, key, obj[key].toString()); + } + } + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + } +} diff --git a/libs/common/src/importers/dashlaneImporters/types/dashlaneCsvTypes.ts b/libs/common/src/importers/dashlaneImporters/types/dashlaneCsvTypes.ts new file mode 100644 index 0000000000..cb321c56da --- /dev/null +++ b/libs/common/src/importers/dashlaneImporters/types/dashlaneCsvTypes.ts @@ -0,0 +1,68 @@ +// tslint:disable +export class CredentialsRecord { + username: string; + username2: string; + username3: string; + title: string; + password: string; + note: string; + url: string; + category: string; + otpSecret: string; +} + +export class PaymentsRecord { + type: string; + account_name: string; + account_holder: string; + cc_number: string; + code: string; + expiration_month: string; + expiration_year: string; + routing_number: string; + account_number: string; + country: string; + issuing_bank: string; +} + +export class IdRecord { + type: string; + number: string; + name: string; + issue_date: string; + expiration_date: string; + place_of_issue: string; + state: string; +} + +export class PersonalInformationRecord { + type: string; + title: string; + first_name: string; + middle_name: string; + last_name: string; + login: string; + date_of_birth: string; + place_of_birth: string; + email: string; + email_type: string; + item_name: string; + phone_number: string; + address: string; + country: string; + state: string; + city: string; + zip: string; + address_recipient: string; + address_building: string; + address_apartment: string; + address_floor: string; + address_door_code: string; + job_title: string; + url: string; +} + +export class SecureNoteRecord { + title: string; + note: string; +} diff --git a/libs/common/src/importers/encryptrCsvImporter.ts b/libs/common/src/importers/encryptrCsvImporter.ts new file mode 100644 index 0000000000..8c3e9e08ac --- /dev/null +++ b/libs/common/src/importers/encryptrCsvImporter.ts @@ -0,0 +1,60 @@ +import { CipherType } from "../enums/cipherType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class EncryptrCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.Label, "--"); + cipher.notes = this.getValueOrDefault(value.Notes); + const text = this.getValueOrDefault(value.Text); + if (!this.isNullOrWhitespace(text)) { + if (this.isNullOrWhitespace(cipher.notes)) { + cipher.notes = text; + } else { + cipher.notes += "\n\n" + text; + } + } + + const type = value["Entry Type"]; + if (type === "Password") { + cipher.login.username = this.getValueOrDefault(value.Username); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.uris = this.makeUriArray(value["Site URL"]); + } else if (type === "Credit Card") { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + cipher.card.cardholderName = this.getValueOrDefault(value["Name on card"]); + cipher.card.number = this.getValueOrDefault(value["Card Number"]); + cipher.card.brand = this.getCardBrand(cipher.card.number); + cipher.card.code = this.getValueOrDefault(value.CVV); + const expiry = this.getValueOrDefault(value.Expiry); + if (!this.isNullOrWhitespace(expiry)) { + const expParts = expiry.split("/"); + if (expParts.length > 1) { + cipher.card.expMonth = parseInt(expParts[0], null).toString(); + cipher.card.expYear = (2000 + parseInt(expParts[1], null)).toString(); + } + } + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/enpassCsvImporter.ts b/libs/common/src/importers/enpassCsvImporter.ts new file mode 100644 index 0000000000..b5eb0b6027 --- /dev/null +++ b/libs/common/src/importers/enpassCsvImporter.ts @@ -0,0 +1,133 @@ +import { CipherType } from "../enums/cipherType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; +import { SecureNoteView } from "../models/view/secureNoteView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class EnpassCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + let firstRow = true; + results.forEach((value) => { + if (value.length < 2 || (firstRow && (value[0] === "Title" || value[0] === "title"))) { + firstRow = false; + return; + } + + const cipher = this.initLoginCipher(); + cipher.notes = this.getValueOrDefault(value[value.length - 1]); + cipher.name = this.getValueOrDefault(value[0], "--"); + + if ( + value.length === 2 || + (!this.containsField(value, "username") && + !this.containsField(value, "password") && + !this.containsField(value, "email") && + !this.containsField(value, "url")) + ) { + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + } + + if ( + this.containsField(value, "cardholder") && + this.containsField(value, "number") && + this.containsField(value, "expiry date") + ) { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + } + + if (value.length > 2 && value.length % 2 === 0) { + for (let i = 0; i < value.length - 2; i += 2) { + const fieldValue: string = value[i + 2]; + if (this.isNullOrWhitespace(fieldValue)) { + continue; + } + + const fieldName: string = value[i + 1]; + const fieldNameLower = fieldName.toLowerCase(); + + if (cipher.type === CipherType.Login) { + if ( + fieldNameLower === "url" && + (cipher.login.uris == null || cipher.login.uris.length === 0) + ) { + cipher.login.uris = this.makeUriArray(fieldValue); + continue; + } else if ( + (fieldNameLower === "username" || fieldNameLower === "email") && + this.isNullOrWhitespace(cipher.login.username) + ) { + cipher.login.username = fieldValue; + continue; + } else if ( + fieldNameLower === "password" && + this.isNullOrWhitespace(cipher.login.password) + ) { + cipher.login.password = fieldValue; + continue; + } else if (fieldNameLower === "totp" && this.isNullOrWhitespace(cipher.login.totp)) { + cipher.login.totp = fieldValue; + continue; + } + } else if (cipher.type === CipherType.Card) { + if ( + fieldNameLower === "cardholder" && + this.isNullOrWhitespace(cipher.card.cardholderName) + ) { + cipher.card.cardholderName = fieldValue; + continue; + } else if (fieldNameLower === "number" && this.isNullOrWhitespace(cipher.card.number)) { + cipher.card.number = fieldValue; + cipher.card.brand = this.getCardBrand(fieldValue); + continue; + } else if (fieldNameLower === "cvc" && this.isNullOrWhitespace(cipher.card.code)) { + cipher.card.code = fieldValue; + continue; + } else if ( + fieldNameLower === "expiry date" && + this.isNullOrWhitespace(cipher.card.expMonth) && + this.isNullOrWhitespace(cipher.card.expYear) + ) { + if (this.setCardExpiration(cipher, fieldValue)) { + continue; + } + } else if (fieldNameLower === "type") { + // Skip since brand was determined from number above + continue; + } + } + + this.processKvp(cipher, fieldName, fieldValue); + } + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } + + private containsField(fields: any[], name: string) { + if (fields == null || name == null) { + return false; + } + return ( + fields.filter((f) => !this.isNullOrWhitespace(f) && f.toLowerCase() === name.toLowerCase()) + .length > 0 + ); + } +} diff --git a/libs/common/src/importers/enpassJsonImporter.ts b/libs/common/src/importers/enpassJsonImporter.ts new file mode 100644 index 0000000000..033c5995b0 --- /dev/null +++ b/libs/common/src/importers/enpassJsonImporter.ts @@ -0,0 +1,191 @@ +import { CipherType } from "../enums/cipherType"; +import { FieldType } from "../enums/fieldType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; +import { CipherView } from "../models/view/cipherView"; +import { FolderView } from "../models/view/folderView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class EnpassJsonImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = JSON.parse(data); + if (results == null || results.items == null || results.items.length === 0) { + result.success = false; + return Promise.resolve(result); + } + + const foldersMap = new Map(); + const foldersIndexMap = new Map(); + const folderTree = this.buildFolderTree(results.folders); + this.flattenFolderTree(null, folderTree, foldersMap); + foldersMap.forEach((val, key) => { + foldersIndexMap.set(key, result.folders.length); + const f = new FolderView(); + f.name = val; + result.folders.push(f); + }); + + results.items.forEach((item: any) => { + if (item.folders != null && item.folders.length > 0 && foldersIndexMap.has(item.folders[0])) { + result.folderRelationships.push([ + result.ciphers.length, + foldersIndexMap.get(item.folders[0]), + ]); + } + + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(item.title); + cipher.favorite = item.favorite > 0; + + if (item.template_type != null && item.fields != null && item.fields.length > 0) { + if ( + item.template_type.indexOf("login.") === 0 || + item.template_type.indexOf("password.") === 0 + ) { + this.processLogin(cipher, item.fields); + } else if (item.template_type.indexOf("creditcard.") === 0) { + this.processCard(cipher, item.fields); + } else if ( + item.template_type.indexOf("identity.") < 0 && + item.fields.some((f: any) => f.type === "password" && !this.isNullOrWhitespace(f.value)) + ) { + this.processLogin(cipher, item.fields); + } else { + this.processNote(cipher, item.fields); + } + } + + cipher.notes += "\n" + this.getValueOrDefault(item.note, ""); + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } + + private processLogin(cipher: CipherView, fields: any[]) { + const urls: string[] = []; + fields.forEach((field: any) => { + if (this.isNullOrWhitespace(field.value) || field.type === "section") { + return; + } + + if ( + (field.type === "username" || field.type === "email") && + this.isNullOrWhitespace(cipher.login.username) + ) { + cipher.login.username = field.value; + } else if (field.type === "password" && this.isNullOrWhitespace(cipher.login.password)) { + cipher.login.password = field.value; + } else if (field.type === "totp" && this.isNullOrWhitespace(cipher.login.totp)) { + cipher.login.totp = field.value; + } else if (field.type === "url") { + urls.push(field.value); + } else { + this.processKvp( + cipher, + field.label, + field.value, + field.sensitive === 1 ? FieldType.Hidden : FieldType.Text + ); + } + }); + cipher.login.uris = this.makeUriArray(urls); + } + + private processCard(cipher: CipherView, fields: any[]) { + cipher.card = new CardView(); + cipher.type = CipherType.Card; + fields.forEach((field: any) => { + if ( + this.isNullOrWhitespace(field.value) || + field.type === "section" || + field.type === "ccType" + ) { + return; + } + + if (field.type === "ccName" && this.isNullOrWhitespace(cipher.card.cardholderName)) { + cipher.card.cardholderName = field.value; + } else if (field.type === "ccNumber" && this.isNullOrWhitespace(cipher.card.number)) { + cipher.card.number = field.value; + cipher.card.brand = this.getCardBrand(cipher.card.number); + } else if (field.type === "ccCvc" && this.isNullOrWhitespace(cipher.card.code)) { + cipher.card.code = field.value; + } else if (field.type === "ccExpiry" && this.isNullOrWhitespace(cipher.card.expYear)) { + if (!this.setCardExpiration(cipher, field.value)) { + this.processKvp( + cipher, + field.label, + field.value, + field.sensitive === 1 ? FieldType.Hidden : FieldType.Text + ); + } + } else { + this.processKvp( + cipher, + field.label, + field.value, + field.sensitive === 1 ? FieldType.Hidden : FieldType.Text + ); + } + }); + } + + private processNote(cipher: CipherView, fields: any[]) { + fields.forEach((field: any) => { + if (this.isNullOrWhitespace(field.value) || field.type === "section") { + return; + } + this.processKvp( + cipher, + field.label, + field.value, + field.sensitive === 1 ? FieldType.Hidden : FieldType.Text + ); + }); + } + + private buildFolderTree(folders: any[]): any[] { + if (folders == null) { + return []; + } + const folderTree: any[] = []; + const map = new Map([]); + folders.forEach((obj: any) => { + map.set(obj.uuid, obj); + obj.children = []; + }); + folders.forEach((obj: any) => { + if (obj.parent_uuid != null && obj.parent_uuid !== "" && map.has(obj.parent_uuid)) { + map.get(obj.parent_uuid).children.push(obj); + } else { + folderTree.push(obj); + } + }); + return folderTree; + } + + private flattenFolderTree(titlePrefix: string, tree: any[], map: Map) { + if (tree == null) { + return; + } + tree.forEach((f: any) => { + if (f.title != null && f.title.trim() !== "") { + let title = f.title.trim(); + if (titlePrefix != null && titlePrefix.trim() !== "") { + title = titlePrefix + "/" + title; + } + map.set(f.uuid, title); + if (f.children != null && f.children.length !== 0) { + this.flattenFolderTree(title, f.children, map); + } + } + }); + } +} diff --git a/libs/common/src/importers/firefoxCsvImporter.ts b/libs/common/src/importers/firefoxCsvImporter.ts new file mode 100644 index 0000000000..1b71aac960 --- /dev/null +++ b/libs/common/src/importers/firefoxCsvImporter.ts @@ -0,0 +1,33 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class FirefoxCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results + .filter((value) => { + return value.url !== "chrome://FirefoxAccounts"; + }) + .forEach((value) => { + const cipher = this.initLoginCipher(); + const url = this.getValueOrDefault(value.url, this.getValueOrDefault(value.hostname)); + cipher.name = this.getValueOrDefault(this.nameFromUrl(url), "--"); + cipher.login.username = this.getValueOrDefault(value.username); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.uris = this.makeUriArray(url); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/fsecureFskImporter.ts b/libs/common/src/importers/fsecureFskImporter.ts new file mode 100644 index 0000000000..c81a0820f2 --- /dev/null +++ b/libs/common/src/importers/fsecureFskImporter.ts @@ -0,0 +1,59 @@ +import { CipherType } from "../enums/cipherType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class FSecureFskImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = JSON.parse(data); + if (results == null || results.data == null) { + result.success = false; + return Promise.resolve(result); + } + + for (const key in results.data) { + // eslint-disable-next-line + if (!results.data.hasOwnProperty(key)) { + continue; + } + + const value = results.data[key]; + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.service); + cipher.notes = this.getValueOrDefault(value.notes); + + if (value.style === "website" || value.style === "globe") { + cipher.login.username = this.getValueOrDefault(value.username); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.uris = this.makeUriArray(value.url); + } else if (value.style === "creditcard") { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + cipher.card.cardholderName = this.getValueOrDefault(value.username); + cipher.card.number = this.getValueOrDefault(value.creditNumber); + cipher.card.brand = this.getCardBrand(cipher.card.number); + cipher.card.code = this.getValueOrDefault(value.creditCvv); + if (!this.isNullOrWhitespace(value.creditExpiry)) { + if (!this.setCardExpiration(cipher, value.creditExpiry)) { + this.processKvp(cipher, "Expiration", value.creditExpiry); + } + } + if (!this.isNullOrWhitespace(value.password)) { + this.processKvp(cipher, "PIN", value.password); + } + } else { + continue; + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/gnomeJsonImporter.ts b/libs/common/src/importers/gnomeJsonImporter.ts new file mode 100644 index 0000000000..1dfac67545 --- /dev/null +++ b/libs/common/src/importers/gnomeJsonImporter.ts @@ -0,0 +1,71 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class GnomeJsonImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = JSON.parse(data); + if (results == null || Object.keys(results).length === 0) { + result.success = false; + return Promise.resolve(result); + } + + for (const keyRing in results) { + if ( + !results.hasOwnProperty(keyRing) || // eslint-disable-line + this.isNullOrWhitespace(keyRing) || + results[keyRing].length === 0 + ) { + continue; + } + + results[keyRing].forEach((value: any) => { + if ( + this.isNullOrWhitespace(value.display_name) || + value.display_name.indexOf("http") !== 0 + ) { + return; + } + + this.processFolder(result, keyRing); + const cipher = this.initLoginCipher(); + cipher.name = value.display_name.replace("http://", "").replace("https://", ""); + if (cipher.name.length > 30) { + cipher.name = cipher.name.substring(0, 30); + } + cipher.login.password = this.getValueOrDefault(value.secret); + cipher.login.uris = this.makeUriArray(value.display_name); + + if (value.attributes != null) { + cipher.login.username = + value.attributes != null + ? this.getValueOrDefault(value.attributes.username_value) + : null; + for (const attr in value.attributes) { + if ( + !value.attributes.hasOwnProperty(attr) || // eslint-disable-line + attr === "username_value" || + attr === "xdg:schema" + ) { + continue; + } + this.processKvp(cipher, attr, value.attributes[attr]); + } + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + } + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/importError.ts b/libs/common/src/importers/importError.ts new file mode 100644 index 0000000000..6a74d66e9f --- /dev/null +++ b/libs/common/src/importers/importError.ts @@ -0,0 +1,5 @@ +export class ImportError extends Error { + constructor(message?: string, public passwordRequired: boolean = false) { + super(message); + } +} diff --git a/libs/common/src/importers/importer.ts b/libs/common/src/importers/importer.ts new file mode 100644 index 0000000000..a62cc6c139 --- /dev/null +++ b/libs/common/src/importers/importer.ts @@ -0,0 +1,6 @@ +import { ImportResult } from "../models/domain/importResult"; + +export interface Importer { + organizationId: string; + parse(data: string): Promise; +} diff --git a/libs/common/src/importers/kasperskyTxtImporter.ts b/libs/common/src/importers/kasperskyTxtImporter.ts new file mode 100644 index 0000000000..b049f2bb1d --- /dev/null +++ b/libs/common/src/importers/kasperskyTxtImporter.ts @@ -0,0 +1,124 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +const NotesHeader = "Notes\n\n"; +const ApplicationsHeader = "Applications\n\n"; +const WebsitesHeader = "Websites\n\n"; +const Delimiter = "\n---\n"; + +export class KasperskyTxtImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + + let notesData: string; + let applicationsData: string; + let websitesData: string; + let workingData = this.splitNewLine(data).join("\n"); + + if (workingData.indexOf(NotesHeader) !== -1) { + const parts = workingData.split(NotesHeader); + if (parts.length > 1) { + workingData = parts[0]; + notesData = parts[1]; + } + } + if (workingData.indexOf(ApplicationsHeader) !== -1) { + const parts = workingData.split(ApplicationsHeader); + if (parts.length > 1) { + workingData = parts[0]; + applicationsData = parts[1]; + } + } + if (workingData.indexOf(WebsitesHeader) === 0) { + const parts = workingData.split(WebsitesHeader); + if (parts.length > 1) { + workingData = parts[0]; + websitesData = parts[1]; + } + } + + const notes = this.parseDataCategory(notesData); + const applications = this.parseDataCategory(applicationsData); + const websites = this.parseDataCategory(websitesData); + + notes.forEach((n) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(n.get("Name")); + cipher.notes = this.getValueOrDefault(n.get("Text")); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + websites.concat(applications).forEach((w) => { + const cipher = this.initLoginCipher(); + const nameKey = w.has("Website name") ? "Website name" : "Application"; + cipher.name = this.getValueOrDefault(w.get(nameKey), ""); + if (!this.isNullOrWhitespace(w.get("Login name"))) { + if (!this.isNullOrWhitespace(cipher.name)) { + cipher.name += ": "; + } + cipher.name += w.get("Login name"); + } + cipher.notes = this.getValueOrDefault(w.get("Comment")); + if (w.has("Website URL")) { + cipher.login.uris = this.makeUriArray(w.get("Website URL")); + } + cipher.login.username = this.getValueOrDefault(w.get("Login")); + cipher.login.password = this.getValueOrDefault(w.get("Password")); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } + + private parseDataCategory(data: string): Map[] { + if (this.isNullOrWhitespace(data) || data.indexOf(Delimiter) === -1) { + return []; + } + const items: Map[] = []; + data.split(Delimiter).forEach((p) => { + if (p.indexOf("\n") === -1) { + return; + } + const item = new Map(); + let itemComment: string; + let itemCommentKey: string; + p.split("\n").forEach((l) => { + if (itemComment != null) { + itemComment += "\n" + l; + return; + } + const colonIndex = l.indexOf(":"); + let key: string; + let val: string; + if (colonIndex === -1) { + return; + } else { + key = l.substring(0, colonIndex); + if (l.length > colonIndex + 1) { + val = l.substring(colonIndex + 2); + } + } + if (key != null) { + item.set(key, val); + } + if (key === "Comment" || key === "Text") { + itemComment = val; + itemCommentKey = key; + } + }); + if (itemComment != null && itemCommentKey != null) { + item.set(itemCommentKey, itemComment); + } + if (item.size === 0) { + return; + } + items.push(item); + }); + return items; + } +} diff --git a/libs/common/src/importers/keepass2XmlImporter.ts b/libs/common/src/importers/keepass2XmlImporter.ts new file mode 100644 index 0000000000..2ed5d0f96f --- /dev/null +++ b/libs/common/src/importers/keepass2XmlImporter.ts @@ -0,0 +1,101 @@ +import { FieldType } from "../enums/fieldType"; +import { ImportResult } from "../models/domain/importResult"; +import { FolderView } from "../models/view/folderView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class KeePass2XmlImporter extends BaseImporter implements Importer { + result = new ImportResult(); + + parse(data: string): Promise { + const doc = this.parseXml(data); + if (doc == null) { + this.result.success = false; + return Promise.resolve(this.result); + } + + const rootGroup = doc.querySelector("KeePassFile > Root > Group"); + if (rootGroup == null) { + this.result.errorMessage = "Missing `KeePassFile > Root > Group` node."; + this.result.success = false; + return Promise.resolve(this.result); + } + + this.traverse(rootGroup, true, ""); + + if (this.organization) { + this.moveFoldersToCollections(this.result); + } + + this.result.success = true; + return Promise.resolve(this.result); + } + + traverse(node: Element, isRootNode: boolean, groupPrefixName: string) { + const folderIndex = this.result.folders.length; + let groupName = groupPrefixName; + + if (!isRootNode) { + if (groupName !== "") { + groupName += "/"; + } + const nameEl = this.querySelectorDirectChild(node, "Name"); + groupName += nameEl == null ? "-" : nameEl.textContent; + const folder = new FolderView(); + folder.name = groupName; + this.result.folders.push(folder); + } + + this.querySelectorAllDirectChild(node, "Entry").forEach((entry) => { + const cipherIndex = this.result.ciphers.length; + + const cipher = this.initLoginCipher(); + this.querySelectorAllDirectChild(entry, "String").forEach((entryString) => { + const valueEl = this.querySelectorDirectChild(entryString, "Value"); + const value = valueEl != null ? valueEl.textContent : null; + if (this.isNullOrWhitespace(value)) { + return; + } + const keyEl = this.querySelectorDirectChild(entryString, "Key"); + const key = keyEl != null ? keyEl.textContent : null; + + if (key === "URL") { + cipher.login.uris = this.makeUriArray(value); + } else if (key === "UserName") { + cipher.login.username = value; + } else if (key === "Password") { + cipher.login.password = value; + } else if (key === "otp") { + cipher.login.totp = value.replace("key=", ""); + } else if (key === "Title") { + cipher.name = value; + } else if (key === "Notes") { + cipher.notes += value + "\n"; + } else { + let type = FieldType.Text; + const attrs = valueEl.attributes as any; + if ( + attrs.length > 0 && + attrs.ProtectInMemory != null && + attrs.ProtectInMemory.value === "True" + ) { + type = FieldType.Hidden; + } + this.processKvp(cipher, key, value, type); + } + }); + + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + + if (!isRootNode) { + this.result.folderRelationships.push([cipherIndex, folderIndex]); + } + }); + + this.querySelectorAllDirectChild(node, "Group").forEach((group) => { + this.traverse(group, false, groupName); + }); + } +} diff --git a/libs/common/src/importers/keepassxCsvImporter.ts b/libs/common/src/importers/keepassxCsvImporter.ts new file mode 100644 index 0000000000..58640d5aed --- /dev/null +++ b/libs/common/src/importers/keepassxCsvImporter.ts @@ -0,0 +1,44 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class KeePassXCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (this.isNullOrWhitespace(value.Title)) { + return; + } + + value.Group = + !this.isNullOrWhitespace(value.Group) && value.Group.startsWith("Root/") + ? value.Group.replace("Root/", "") + : value.Group; + const groupName = !this.isNullOrWhitespace(value.Group) ? value.Group : null; + this.processFolder(result, groupName); + + const cipher = this.initLoginCipher(); + cipher.notes = this.getValueOrDefault(value.Notes); + cipher.name = this.getValueOrDefault(value.Title, "--"); + cipher.login.username = this.getValueOrDefault(value.Username); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.uris = this.makeUriArray(value.URL); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/keeperImporters/keeperCsvImporter.ts b/libs/common/src/importers/keeperImporters/keeperCsvImporter.ts new file mode 100644 index 0000000000..e9c65d7153 --- /dev/null +++ b/libs/common/src/importers/keeperImporters/keeperCsvImporter.ts @@ -0,0 +1,45 @@ +import { ImportResult } from "../../models/domain/importResult"; +import { BaseImporter } from "../baseImporter"; +import { Importer } from "../importer"; + +export class KeeperCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.length < 6) { + return; + } + + this.processFolder(result, value[0]); + const cipher = this.initLoginCipher(); + cipher.notes = this.getValueOrDefault(value[5]) + "\n"; + cipher.name = this.getValueOrDefault(value[1], "--"); + cipher.login.username = this.getValueOrDefault(value[2]); + cipher.login.password = this.getValueOrDefault(value[3]); + cipher.login.uris = this.makeUriArray(value[4]); + + if (value.length > 7) { + // we have some custom fields. + for (let i = 7; i < value.length; i = i + 2) { + this.processKvp(cipher, value[i], value[i + 1]); + } + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/keeperImporters/keeperJsonImporter.ts b/libs/common/src/importers/keeperImporters/keeperJsonImporter.ts new file mode 100644 index 0000000000..7ee80b08e0 --- /dev/null +++ b/libs/common/src/importers/keeperImporters/keeperJsonImporter.ts @@ -0,0 +1,69 @@ +import { ImportResult } from "../../models/domain/importResult"; +import { BaseImporter } from "../baseImporter"; +import { Importer } from "../importer"; + +import { KeeperJsonExport, RecordsEntity } from "./types/keeperJsonTypes"; + +export class KeeperJsonImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const keeperExport: KeeperJsonExport = JSON.parse(data); + if (keeperExport == null || keeperExport.records == null || keeperExport.records.length === 0) { + result.success = false; + return Promise.resolve(result); + } + + keeperExport.records.forEach((record) => { + this.parseFolders(result, record); + + const cipher = this.initLoginCipher(); + cipher.name = record.title; + cipher.login.username = record.login; + cipher.login.password = record.password; + + cipher.login.uris = this.makeUriArray(record.login_url); + cipher.notes = record.notes; + + if (record.custom_fields != null) { + let customfieldKeys = Object.keys(record.custom_fields); + if (record.custom_fields["TFC:Keeper"] != null) { + customfieldKeys = customfieldKeys.filter((item) => item !== "TFC:Keeper"); + cipher.login.totp = record.custom_fields["TFC:Keeper"]; + } + + customfieldKeys.forEach((key) => { + this.processKvp(cipher, key, record.custom_fields[key]); + }); + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + private parseFolders(result: ImportResult, record: RecordsEntity) { + if (record.folders == null || record.folders.length === 0) { + return; + } + + record.folders.forEach((item) => { + if (item.folder != null) { + this.processFolder(result, item.folder); + return; + } + + if (item.shared_folder != null) { + this.processFolder(result, item.shared_folder); + return; + } + }); + } +} diff --git a/libs/common/src/importers/keeperImporters/types/keeperJsonTypes.ts b/libs/common/src/importers/keeperImporters/types/keeperJsonTypes.ts new file mode 100644 index 0000000000..1f6d2ea4c2 --- /dev/null +++ b/libs/common/src/importers/keeperImporters/types/keeperJsonTypes.ts @@ -0,0 +1,41 @@ +export interface KeeperJsonExport { + shared_folders?: SharedFoldersEntity[] | null; + records?: RecordsEntity[] | null; +} + +export interface SharedFoldersEntity { + path: string; + manage_users: boolean; + manage_records: boolean; + can_edit: boolean; + can_share: boolean; + permissions?: PermissionsEntity[] | null; +} + +export interface PermissionsEntity { + uid?: string | null; + manage_users: boolean; + manage_records: boolean; + name?: string | null; +} + +export interface RecordsEntity { + title: string; + login: string; + password: string; + login_url: string; + notes?: string; + custom_fields?: CustomFields; + folders?: FoldersEntity[] | null; +} + +export type CustomFields = { + [key: string]: string | null; +}; + +export interface FoldersEntity { + folder?: string | null; + shared_folder?: string | null; + can_edit?: boolean | null; + can_share?: boolean | null; +} diff --git a/libs/common/src/importers/lastpassCsvImporter.ts b/libs/common/src/importers/lastpassCsvImporter.ts new file mode 100644 index 0000000000..5c0160280f --- /dev/null +++ b/libs/common/src/importers/lastpassCsvImporter.ts @@ -0,0 +1,285 @@ +import { CipherType } from "../enums/cipherType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; +import { CipherView } from "../models/view/cipherView"; +import { FolderView } from "../models/view/folderView"; +import { IdentityView } from "../models/view/identityView"; +import { LoginView } from "../models/view/loginView"; +import { SecureNoteView } from "../models/view/secureNoteView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class LastPassCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipherIndex = result.ciphers.length; + let folderIndex = result.folders.length; + let grouping = value.grouping; + if (grouping != null) { + // eslint-disable-next-line + grouping = grouping.replace(/\\/g, "/").replace(/[\x00-\x1F\x7F-\x9F]/g, ""); + } + const hasFolder = this.getValueOrDefault(grouping, "(none)") !== "(none)"; + let addFolder = hasFolder; + + if (hasFolder) { + for (let i = 0; i < result.folders.length; i++) { + if (result.folders[i].name === grouping) { + addFolder = false; + folderIndex = i; + break; + } + } + } + + const cipher = this.buildBaseCipher(value); + if (cipher.type === CipherType.Login) { + cipher.notes = this.getValueOrDefault(value.extra); + cipher.login = new LoginView(); + cipher.login.uris = this.makeUriArray(value.url); + cipher.login.username = this.getValueOrDefault(value.username); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.totp = this.getValueOrDefault(value.totp); + } else if (cipher.type === CipherType.SecureNote) { + this.parseSecureNote(value, cipher); + } else if (cipher.type === CipherType.Card) { + cipher.card = this.parseCard(value); + cipher.notes = this.getValueOrDefault(value.notes); + } else if (cipher.type === CipherType.Identity) { + cipher.identity = this.parseIdentity(value); + cipher.notes = this.getValueOrDefault(value.notes); + if (!this.isNullOrWhitespace(value.ccnum)) { + // there is a card on this identity too + const cardCipher = this.buildBaseCipher(value); + cardCipher.identity = null; + cardCipher.type = CipherType.Card; + cardCipher.card = this.parseCard(value); + result.ciphers.push(cardCipher); + } + } + + result.ciphers.push(cipher); + + if (addFolder) { + const f = new FolderView(); + f.name = grouping; + result.folders.push(f); + } + if (hasFolder) { + result.folderRelationships.push([cipherIndex, folderIndex]); + } + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + private buildBaseCipher(value: any) { + const cipher = new CipherView(); + // eslint-disable-next-line + if (value.hasOwnProperty("profilename") && value.hasOwnProperty("profilelanguage")) { + // form fill + cipher.favorite = false; + cipher.name = this.getValueOrDefault(value.profilename, "--"); + cipher.type = CipherType.Card; + + if ( + !this.isNullOrWhitespace(value.title) || + !this.isNullOrWhitespace(value.firstname) || + !this.isNullOrWhitespace(value.lastname) || + !this.isNullOrWhitespace(value.address1) || + !this.isNullOrWhitespace(value.phone) || + !this.isNullOrWhitespace(value.username) || + !this.isNullOrWhitespace(value.email) + ) { + cipher.type = CipherType.Identity; + } + } else { + // site or secure note + cipher.favorite = !this.organization && this.getValueOrDefault(value.fav, "0") === "1"; + cipher.name = this.getValueOrDefault(value.name, "--"); + cipher.type = value.url === "http://sn" ? CipherType.SecureNote : CipherType.Login; + } + return cipher; + } + + private parseCard(value: any): CardView { + const card = new CardView(); + card.cardholderName = this.getValueOrDefault(value.ccname); + card.number = this.getValueOrDefault(value.ccnum); + card.code = this.getValueOrDefault(value.cccsc); + card.brand = this.getCardBrand(value.ccnum); + + if (!this.isNullOrWhitespace(value.ccexp) && value.ccexp.indexOf("-") > -1) { + const ccexpParts = (value.ccexp as string).split("-"); + if (ccexpParts.length > 1) { + card.expYear = ccexpParts[0]; + card.expMonth = ccexpParts[1]; + if (card.expMonth.length === 2 && card.expMonth[0] === "0") { + card.expMonth = card.expMonth[1]; + } + } + } + + return card; + } + + private parseIdentity(value: any): IdentityView { + const identity = new IdentityView(); + identity.title = this.getValueOrDefault(value.title); + identity.firstName = this.getValueOrDefault(value.firstname); + identity.middleName = this.getValueOrDefault(value.middlename); + identity.lastName = this.getValueOrDefault(value.lastname); + identity.username = this.getValueOrDefault(value.username); + identity.company = this.getValueOrDefault(value.company); + identity.ssn = this.getValueOrDefault(value.ssn); + identity.address1 = this.getValueOrDefault(value.address1); + identity.address2 = this.getValueOrDefault(value.address2); + identity.address3 = this.getValueOrDefault(value.address3); + identity.city = this.getValueOrDefault(value.city); + identity.state = this.getValueOrDefault(value.state); + identity.postalCode = this.getValueOrDefault(value.zip); + identity.country = this.getValueOrDefault(value.country); + identity.email = this.getValueOrDefault(value.email); + identity.phone = this.getValueOrDefault(value.phone); + + if (!this.isNullOrWhitespace(identity.title)) { + identity.title = identity.title.charAt(0).toUpperCase() + identity.title.slice(1); + } + + return identity; + } + + private parseSecureNote(value: any, cipher: CipherView) { + const extraParts = this.splitNewLine(value.extra); + let processedNote = false; + + if (extraParts.length) { + const typeParts = extraParts[0].split(":"); + if ( + typeParts.length > 1 && + typeParts[0] === "NoteType" && + (typeParts[1] === "Credit Card" || typeParts[1] === "Address") + ) { + if (typeParts[1] === "Credit Card") { + const mappedData = this.parseSecureNoteMapping(cipher, extraParts, { + Number: "number", + "Name on Card": "cardholderName", + "Security Code": "code", + // LP provides date in a format like 'June,2020' + // Store in expMonth, then parse and modify + "Expiration Date": "expMonth", + }); + + if (this.isNullOrWhitespace(mappedData.expMonth) || mappedData.expMonth === ",") { + // No expiration data + mappedData.expMonth = undefined; + } else { + const [monthString, year] = mappedData.expMonth.split(","); + // Parse month name into number + if (!this.isNullOrWhitespace(monthString)) { + const month = new Date(Date.parse(monthString.trim() + " 1, 2012")).getMonth() + 1; + if (isNaN(month)) { + mappedData.expMonth = undefined; + } else { + mappedData.expMonth = month.toString(); + } + } else { + mappedData.expMonth = undefined; + } + if (!this.isNullOrWhitespace(year)) { + mappedData.expYear = year; + } + } + + cipher.type = CipherType.Card; + cipher.card = mappedData; + } else if (typeParts[1] === "Address") { + const mappedData = this.parseSecureNoteMapping(cipher, extraParts, { + Title: "title", + "First Name": "firstName", + "Last Name": "lastName", + "Middle Name": "middleName", + Company: "company", + "Address 1": "address1", + "Address 2": "address2", + "Address 3": "address3", + "City / Town": "city", + State: "state", + "Zip / Postal Code": "postalCode", + Country: "country", + "Email Address": "email", + Username: "username", + }); + cipher.type = CipherType.Identity; + cipher.identity = mappedData; + } + processedNote = true; + } + } + + if (!processedNote) { + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + cipher.notes = this.getValueOrDefault(value.extra); + } + } + + private parseSecureNoteMapping(cipher: CipherView, extraParts: string[], map: any): T { + const dataObj: any = {}; + + let processingNotes = false; + extraParts.forEach((extraPart) => { + let key: string = null; + let val: string = null; + if (!processingNotes) { + if (this.isNullOrWhitespace(extraPart)) { + return; + } + const colonIndex = extraPart.indexOf(":"); + if (colonIndex === -1) { + key = extraPart; + } else { + key = extraPart.substring(0, colonIndex); + if (extraPart.length > colonIndex) { + val = extraPart.substring(colonIndex + 1); + } + } + if (this.isNullOrWhitespace(key) || this.isNullOrWhitespace(val) || key === "NoteType") { + return; + } + } + + if (processingNotes) { + cipher.notes += "\n" + extraPart; + } else if (key === "Notes") { + if (!this.isNullOrWhitespace(cipher.notes)) { + cipher.notes += "\n" + val; + } else { + cipher.notes = val; + } + processingNotes = true; + // eslint-disable-next-line + } else if (map.hasOwnProperty(key)) { + dataObj[map[key]] = val; + } else { + this.processKvp(cipher, key, val); + } + }); + + return dataObj; + } +} diff --git a/libs/common/src/importers/logMeOnceCsvImporter.ts b/libs/common/src/importers/logMeOnceCsvImporter.ts new file mode 100644 index 0000000000..698ebc8020 --- /dev/null +++ b/libs/common/src/importers/logMeOnceCsvImporter.ts @@ -0,0 +1,31 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class LogMeOnceCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.length < 4) { + return; + } + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value[0], "--"); + cipher.login.username = this.getValueOrDefault(value[2]); + cipher.login.password = this.getValueOrDefault(value[3]); + cipher.login.uris = this.makeUriArray(value[1]); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/meldiumCsvImporter.ts b/libs/common/src/importers/meldiumCsvImporter.ts new file mode 100644 index 0000000000..79835a90b3 --- /dev/null +++ b/libs/common/src/importers/meldiumCsvImporter.ts @@ -0,0 +1,29 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class MeldiumCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.DisplayName, "--"); + cipher.notes = this.getValueOrDefault(value.Notes); + cipher.login.username = this.getValueOrDefault(value.UserName); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.uris = this.makeUriArray(value.Url); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/msecureCsvImporter.ts b/libs/common/src/importers/msecureCsvImporter.ts new file mode 100644 index 0000000000..583d13d7d9 --- /dev/null +++ b/libs/common/src/importers/msecureCsvImporter.ts @@ -0,0 +1,61 @@ +import { CipherType } from "../enums/cipherType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { SecureNoteView } from "../models/view/secureNoteView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class MSecureCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.length < 3) { + return; + } + + const folderName = + this.getValueOrDefault(value[0], "Unassigned") !== "Unassigned" ? value[0] : null; + this.processFolder(result, folderName); + + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value[2], "--"); + + if (value[1] === "Web Logins" || value[1] === "Login") { + cipher.login.uris = this.makeUriArray(value[4]); + cipher.login.username = this.getValueOrDefault(value[5]); + cipher.login.password = this.getValueOrDefault(value[6]); + cipher.notes = !this.isNullOrWhitespace(value[3]) ? value[3].split("\\n").join("\n") : null; + } else if (value.length > 3) { + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + for (let i = 3; i < value.length; i++) { + if (!this.isNullOrWhitespace(value[i])) { + cipher.notes += value[i] + "\n"; + } + } + } + + if (!this.isNullOrWhitespace(value[1]) && cipher.type !== CipherType.Login) { + cipher.name = value[1] + ": " + cipher.name; + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/mykiCsvImporter.ts b/libs/common/src/importers/mykiCsvImporter.ts new file mode 100644 index 0000000000..d9a05e1ebb --- /dev/null +++ b/libs/common/src/importers/mykiCsvImporter.ts @@ -0,0 +1,157 @@ +import { CipherType } from "../enums/cipherType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; +import { CipherView } from "../models/view/cipherView"; +import { IdentityView } from "../models/view/identityView"; +import { SecureNoteView } from "../models/view/secureNoteView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +const mappedBaseColumns = ["nickname", "additionalInfo"]; +const _mappedUserAccountColumns = new Set( + mappedBaseColumns.concat(["url", "username", "password", "twofaSecret"]) +); +const _mappedCreditCardColumns = new Set( + mappedBaseColumns.concat(["cardNumber", "cardName", "exp_month", "exp_year", "cvv"]) +); + +const _mappedIdentityColumns = new Set( + mappedBaseColumns.concat([ + "title", + "firstName", + "middleName", + "lastName", + "email", + "firstAddressLine", + "secondAddressLine", + "city", + "country", + "zipCode", + ]) +); + +const _mappedIdCardColumns = new Set(mappedBaseColumns.concat(["idName", "idNumber", "idCountry"])); + +const _mappedTwoFaColumns = new Set(mappedBaseColumns.concat(["authToken"])); + +const _mappedUserNoteColumns = new Set(mappedBaseColumns.concat(["content"])); + +export class MykiCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.nickname, "--"); + cipher.notes = this.getValueOrDefault(value.additionalInfo); + + if (value.url !== undefined) { + // Accounts + cipher.login.uris = this.makeUriArray(value.url); + cipher.login.username = this.getValueOrDefault(value.username); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.totp = this.getValueOrDefault(value.twofaSecret); + + this.importUnmappedFields(cipher, value, _mappedUserAccountColumns); + } else if (value.authToken !== undefined) { + // TwoFA + cipher.login.totp = this.getValueOrDefault(value.authToken); + + this.importUnmappedFields(cipher, value, _mappedTwoFaColumns); + } else if (value.cardNumber !== undefined) { + // Cards + cipher.card = new CardView(); + cipher.type = CipherType.Card; + cipher.card.cardholderName = this.getValueOrDefault(value.cardName); + cipher.card.number = this.getValueOrDefault(value.cardNumber); + cipher.card.brand = this.getCardBrand(cipher.card.number); + cipher.card.expMonth = this.getValueOrDefault(value.exp_month); + cipher.card.expYear = this.getValueOrDefault(value.exp_year); + cipher.card.code = this.getValueOrDefault(value.cvv); + + this.importUnmappedFields(cipher, value, _mappedCreditCardColumns); + } else if (value.firstName !== undefined) { + // Identities + cipher.identity = new IdentityView(); + cipher.type = CipherType.Identity; + cipher.identity.title = this.getValueOrDefault(value.title); + cipher.identity.firstName = this.getValueOrDefault(value.firstName); + cipher.identity.middleName = this.getValueOrDefault(value.middleName); + cipher.identity.lastName = this.getValueOrDefault(value.lastName); + cipher.identity.phone = this.getValueOrDefault(value.number); + cipher.identity.email = this.getValueOrDefault(value.email); + cipher.identity.address1 = this.getValueOrDefault(value.firstAddressLine); + cipher.identity.address2 = this.getValueOrDefault(value.secondAddressLine); + cipher.identity.city = this.getValueOrDefault(value.city); + cipher.identity.country = this.getValueOrDefault(value.country); + cipher.identity.postalCode = this.getValueOrDefault(value.zipCode); + + this.importUnmappedFields(cipher, value, _mappedIdentityColumns); + } else if (value.idType !== undefined) { + // IdCards + + cipher.identity = new IdentityView(); + cipher.type = CipherType.Identity; + this.processFullName(cipher, value.idName); + cipher.identity.country = this.getValueOrDefault(value.idCountry); + + switch (value.idType) { + // case "Driver's License": + // case "ID Card": + // case "Outdoor License": + // case "Software License": + // case "Tax Number": + // case "Bank Account": + // case "Insurance Card": + // case "Health Card": + // case "Membership": + // case "Database": + // case "Reward Program": + // case "Tour Visa": + case "Passport": + cipher.identity.passportNumber = value.idNumber; + break; + case "Social Security": + cipher.identity.ssn = value.idNumber; + break; + default: + cipher.identity.licenseNumber = value.idNumber; + break; + } + + this.importUnmappedFields(cipher, value, _mappedIdCardColumns); + } else if (value.content !== undefined) { + // Notes + cipher.secureNote = new SecureNoteView(); + cipher.type = CipherType.SecureNote; + cipher.secureNote.type = SecureNoteType.Generic; + cipher.notes = this.getValueOrDefault(value.content); + + this.importUnmappedFields(cipher, value, _mappedUserNoteColumns); + } else { + return; + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } + + importUnmappedFields(cipher: CipherView, row: any, mappedValues: Set) { + const unmappedFields = Object.keys(row).filter((x) => !mappedValues.has(x)); + unmappedFields.forEach((key) => { + const item = row as any; + this.processKvp(cipher, key, item[key]); + }); + } +} diff --git a/libs/common/src/importers/nordpassCsvImporter.ts b/libs/common/src/importers/nordpassCsvImporter.ts new file mode 100644 index 0000000000..225e7ec2ae --- /dev/null +++ b/libs/common/src/importers/nordpassCsvImporter.ts @@ -0,0 +1,127 @@ +import { CipherType } from "../enums/cipherType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { CipherView } from "../models/view/cipherView"; +import { LoginView } from "../models/view/loginView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +type nodePassCsvParsed = { + name: string; + url: string; + username: string; + password: string; + note: string; + cardholdername: string; + cardnumber: string; + cvc: string; + expirydate: string; + zipcode: string; + folder: string; + full_name: string; + phone_number: string; + email: string; + address1: string; + address2: string; + city: string; + country: string; + state: string; +}; + +export class NordPassCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results: nodePassCsvParsed[] = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((record) => { + const recordType = this.evaluateType(record); + if (recordType === undefined) { + return; + } + + if (!this.organization) { + this.processFolder(result, record.folder); + } + + const cipher = new CipherView(); + cipher.name = this.getValueOrDefault(record.name, "--"); + cipher.notes = this.getValueOrDefault(record.note); + + switch (recordType) { + case CipherType.Login: + cipher.type = CipherType.Login; + cipher.login = new LoginView(); + cipher.login.username = this.getValueOrDefault(record.username); + cipher.login.password = this.getValueOrDefault(record.password); + cipher.login.uris = this.makeUriArray(record.url); + break; + case CipherType.Card: + cipher.type = CipherType.Card; + cipher.card.cardholderName = this.getValueOrDefault(record.cardholdername); + cipher.card.number = this.getValueOrDefault(record.cardnumber); + cipher.card.code = this.getValueOrDefault(record.cvc); + cipher.card.brand = this.getCardBrand(cipher.card.number); + this.setCardExpiration(cipher, record.expirydate); + break; + + case CipherType.Identity: + cipher.type = CipherType.Identity; + + this.processFullName(cipher, this.getValueOrDefault(record.full_name)); + cipher.identity.address1 = this.getValueOrDefault(record.address1); + cipher.identity.address2 = this.getValueOrDefault(record.address2); + cipher.identity.city = this.getValueOrDefault(record.city); + cipher.identity.state = this.getValueOrDefault(record.state); + cipher.identity.postalCode = this.getValueOrDefault(record.zipcode); + cipher.identity.country = this.getValueOrDefault(record.country); + if (cipher.identity.country != null) { + cipher.identity.country = cipher.identity.country.toUpperCase(); + } + cipher.identity.email = this.getValueOrDefault(record.email); + cipher.identity.phone = this.getValueOrDefault(record.phone_number); + break; + case CipherType.SecureNote: + cipher.type = CipherType.SecureNote; + cipher.secureNote.type = SecureNoteType.Generic; + break; + default: + break; + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + private evaluateType(record: nodePassCsvParsed): CipherType { + if (!this.isNullOrWhitespace(record.username)) { + return CipherType.Login; + } + + if (!this.isNullOrWhitespace(record.cardnumber)) { + return CipherType.Card; + } + + if (!this.isNullOrWhitespace(record.full_name)) { + return CipherType.Identity; + } + + if (!this.isNullOrWhitespace(record.note)) { + return CipherType.SecureNote; + } + + return undefined; + } +} diff --git a/libs/common/src/importers/onepasswordImporters/cipherImportContext.ts b/libs/common/src/importers/onepasswordImporters/cipherImportContext.ts new file mode 100644 index 0000000000..560f5c013b --- /dev/null +++ b/libs/common/src/importers/onepasswordImporters/cipherImportContext.ts @@ -0,0 +1,8 @@ +import { CipherView } from "../../models/view/cipherView"; + +export class CipherImportContext { + lowerProperty: string; + constructor(public importRecord: any, public property: string, public cipher: CipherView) { + this.lowerProperty = property.toLowerCase(); + } +} diff --git a/libs/common/src/importers/onepasswordImporters/onepassword1PifImporter.ts b/libs/common/src/importers/onepasswordImporters/onepassword1PifImporter.ts new file mode 100644 index 0000000000..f261140e27 --- /dev/null +++ b/libs/common/src/importers/onepasswordImporters/onepassword1PifImporter.ts @@ -0,0 +1,276 @@ +import { CipherType } from "../../enums/cipherType"; +import { FieldType } from "../../enums/fieldType"; +import { SecureNoteType } from "../../enums/secureNoteType"; +import { ImportResult } from "../../models/domain/importResult"; +import { CardView } from "../../models/view/cardView"; +import { CipherView } from "../../models/view/cipherView"; +import { IdentityView } from "../../models/view/identityView"; +import { PasswordHistoryView } from "../../models/view/passwordHistoryView"; +import { SecureNoteView } from "../../models/view/secureNoteView"; +import { BaseImporter } from "../baseImporter"; +import { Importer } from "../importer"; + +export class OnePassword1PifImporter extends BaseImporter implements Importer { + result = new ImportResult(); + + parse(data: string): Promise { + data.split(this.newLineRegex).forEach((line) => { + if (this.isNullOrWhitespace(line) || line[0] !== "{") { + return; + } + const item = JSON.parse(line); + if (item.trashed === true) { + return; + } + const cipher = this.initLoginCipher(); + + if (this.isNullOrWhitespace(item.hmac)) { + this.processStandardItem(item, cipher); + } else { + this.processWinOpVaultItem(item, cipher); + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + + this.result.success = true; + return Promise.resolve(this.result); + } + + private processWinOpVaultItem(item: any, cipher: CipherView) { + if (item.overview != null) { + cipher.name = this.getValueOrDefault(item.overview.title); + if (item.overview.URLs != null) { + const urls: string[] = []; + item.overview.URLs.forEach((url: any) => { + if (!this.isNullOrWhitespace(url.u)) { + urls.push(url.u); + } + }); + cipher.login.uris = this.makeUriArray(urls); + } + } + + if (item.details != null) { + if (item.details.passwordHistory != null) { + this.parsePasswordHistory(item.details.passwordHistory, cipher); + } + if ( + !this.isNullOrWhitespace(item.details.ccnum) || + !this.isNullOrWhitespace(item.details.cvv) + ) { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + } else if ( + !this.isNullOrWhitespace(item.details.firstname) || + !this.isNullOrWhitespace(item.details.address1) + ) { + cipher.type = CipherType.Identity; + cipher.identity = new IdentityView(); + } + if (cipher.type === CipherType.Login && !this.isNullOrWhitespace(item.details.password)) { + cipher.login.password = item.details.password; + } + if (!this.isNullOrWhitespace(item.details.notesPlain)) { + cipher.notes = item.details.notesPlain.split(this.newLineRegex).join("\n") + "\n"; + } + if (item.details.fields != null) { + this.parseFields(item.details.fields, cipher, "designation", "value", "name"); + } + if (item.details.sections != null) { + item.details.sections.forEach((section: any) => { + if (section.fields != null) { + this.parseFields(section.fields, cipher, "n", "v", "t"); + } + }); + } + } + } + + private processStandardItem(item: any, cipher: CipherView) { + cipher.favorite = item.openContents && item.openContents.faveIndex ? true : false; + cipher.name = this.getValueOrDefault(item.title); + + if (item.typeName === "securenotes.SecureNote") { + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + } else if (item.typeName === "wallet.financial.CreditCard") { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + } else if (item.typeName === "identities.Identity") { + cipher.type = CipherType.Identity; + cipher.identity = new IdentityView(); + } else { + cipher.login.uris = this.makeUriArray(item.location); + } + + if (item.secureContents != null) { + if (item.secureContents.passwordHistory != null) { + this.parsePasswordHistory(item.secureContents.passwordHistory, cipher); + } + if (!this.isNullOrWhitespace(item.secureContents.notesPlain)) { + cipher.notes = item.secureContents.notesPlain.split(this.newLineRegex).join("\n") + "\n"; + } + if (cipher.type === CipherType.Login) { + if (!this.isNullOrWhitespace(item.secureContents.password)) { + cipher.login.password = item.secureContents.password; + } + if (item.secureContents.URLs != null) { + const urls: string[] = []; + item.secureContents.URLs.forEach((u: any) => { + if (!this.isNullOrWhitespace(u.url)) { + urls.push(u.url); + } + }); + if (urls.length > 0) { + cipher.login.uris = this.makeUriArray(urls); + } + } + } + if (item.secureContents.fields != null) { + this.parseFields(item.secureContents.fields, cipher, "designation", "value", "name"); + } + if (item.secureContents.sections != null) { + item.secureContents.sections.forEach((section: any) => { + if (section.fields != null) { + this.parseFields(section.fields, cipher, "n", "v", "t"); + } + }); + } + } + } + + private parsePasswordHistory(items: any[], cipher: CipherView) { + const maxSize = items.length > 5 ? 5 : items.length; + cipher.passwordHistory = items + .filter((h: any) => !this.isNullOrWhitespace(h.value) && h.time != null) + .sort((a, b) => b.time - a.time) + .slice(0, maxSize) + .map((h: any) => { + const ph = new PasswordHistoryView(); + ph.password = h.value; + ph.lastUsedDate = new Date(("" + h.time).length >= 13 ? h.time : h.time * 1000); + return ph; + }); + } + + private parseFields( + fields: any[], + cipher: CipherView, + designationKey: string, + valueKey: string, + nameKey: string + ) { + fields.forEach((field: any) => { + if (field[valueKey] == null || field[valueKey].toString().trim() === "") { + return; + } + + // TODO: when date FieldType exists, store this as a date field type instead of formatted Text if k is 'date' + const fieldValue = + field.k === "date" + ? new Date(field[valueKey] * 1000).toUTCString() + : field[valueKey].toString(); + const fieldDesignation = + field[designationKey] != null ? field[designationKey].toString() : null; + + if (cipher.type === CipherType.Login) { + if (this.isNullOrWhitespace(cipher.login.username) && fieldDesignation === "username") { + cipher.login.username = fieldValue; + return; + } else if ( + this.isNullOrWhitespace(cipher.login.password) && + fieldDesignation === "password" + ) { + cipher.login.password = fieldValue; + return; + } else if ( + this.isNullOrWhitespace(cipher.login.totp) && + fieldDesignation != null && + fieldDesignation.startsWith("TOTP_") + ) { + cipher.login.totp = fieldValue; + return; + } + } else if (cipher.type === CipherType.Card) { + if (this.isNullOrWhitespace(cipher.card.number) && fieldDesignation === "ccnum") { + cipher.card.number = fieldValue; + cipher.card.brand = this.getCardBrand(fieldValue); + return; + } else if (this.isNullOrWhitespace(cipher.card.code) && fieldDesignation === "cvv") { + cipher.card.code = fieldValue; + return; + } else if ( + this.isNullOrWhitespace(cipher.card.cardholderName) && + fieldDesignation === "cardholder" + ) { + cipher.card.cardholderName = fieldValue; + return; + } else if ( + this.isNullOrWhitespace(cipher.card.expiration) && + fieldDesignation === "expiry" && + fieldValue.length === 6 + ) { + cipher.card.expMonth = (fieldValue as string).substr(4, 2); + if (cipher.card.expMonth[0] === "0") { + cipher.card.expMonth = cipher.card.expMonth.substr(1, 1); + } + cipher.card.expYear = (fieldValue as string).substr(0, 4); + return; + } else if (fieldDesignation === "type") { + // Skip since brand was determined from number above + return; + } + } else if (cipher.type === CipherType.Identity) { + const identity = cipher.identity; + if (this.isNullOrWhitespace(identity.firstName) && fieldDesignation === "firstname") { + identity.firstName = fieldValue; + return; + } else if (this.isNullOrWhitespace(identity.lastName) && fieldDesignation === "lastname") { + identity.lastName = fieldValue; + return; + } else if (this.isNullOrWhitespace(identity.middleName) && fieldDesignation === "initial") { + identity.middleName = fieldValue; + return; + } else if (this.isNullOrWhitespace(identity.phone) && fieldDesignation === "defphone") { + identity.phone = fieldValue; + return; + } else if (this.isNullOrWhitespace(identity.company) && fieldDesignation === "company") { + identity.company = fieldValue; + return; + } else if (this.isNullOrWhitespace(identity.email) && fieldDesignation === "email") { + identity.email = fieldValue; + return; + } else if (this.isNullOrWhitespace(identity.username) && fieldDesignation === "username") { + identity.username = fieldValue; + return; + } else if (fieldDesignation === "address") { + // fieldValue is an object casted into a string, so access the plain value instead + const { street, city, country, zip } = field[valueKey]; + identity.address1 = this.getValueOrDefault(street); + identity.city = this.getValueOrDefault(city); + if (!this.isNullOrWhitespace(country)) { + identity.country = country.toUpperCase(); + } + identity.postalCode = this.getValueOrDefault(zip); + return; + } + } + + const fieldName = this.isNullOrWhitespace(field[nameKey]) ? "no_name" : field[nameKey]; + if ( + fieldName === "password" && + cipher.passwordHistory != null && + cipher.passwordHistory.some((h) => h.password === fieldValue) + ) { + return; + } + + const fieldType = field.k === "concealed" ? FieldType.Hidden : FieldType.Text; + this.processKvp(cipher, fieldName, fieldValue, fieldType); + }); + } +} diff --git a/libs/common/src/importers/onepasswordImporters/onepassword1PuxImporter.ts b/libs/common/src/importers/onepasswordImporters/onepassword1PuxImporter.ts new file mode 100644 index 0000000000..67f4bb2590 --- /dev/null +++ b/libs/common/src/importers/onepasswordImporters/onepassword1PuxImporter.ts @@ -0,0 +1,637 @@ +import { CipherRepromptType } from "../../enums/cipherRepromptType"; +import { CipherType } from "../../enums/cipherType"; +import { FieldType } from "../../enums/fieldType"; +import { SecureNoteType } from "../../enums/secureNoteType"; +import { ImportResult } from "../../models/domain/importResult"; +import { CardView } from "../../models/view/cardView"; +import { CipherView } from "../../models/view/cipherView"; +import { IdentityView } from "../../models/view/identityView"; +import { LoginView } from "../../models/view/loginView"; +import { PasswordHistoryView } from "../../models/view/passwordHistoryView"; +import { SecureNoteView } from "../../models/view/secureNoteView"; +import { BaseImporter } from "../baseImporter"; +import { Importer } from "../importer"; + +import { + CategoryEnum, + Details, + ExportData, + FieldsEntity, + Item, + LoginFieldTypeEnum, + Overview, + PasswordHistoryEntity, + SectionsEntity, + UrlsEntity, + Value, + VaultsEntity, +} from "./types/onepassword1PuxImporterTypes"; + +export class OnePassword1PuxImporter extends BaseImporter implements Importer { + result = new ImportResult(); + + parse(data: string): Promise { + const exportData: ExportData = JSON.parse(data); + + const account = exportData.accounts[0]; + // TODO Add handling of multiple vaults + // const personalVaults = account.vaults[0].filter((v) => v.attrs.type === VaultAttributeTypeEnum.Personal); + account.vaults.forEach((vault: VaultsEntity) => { + vault.items.forEach((item: Item) => { + if (item.trashed === true) { + return; + } + + const cipher = this.initLoginCipher(); + + const category = item.categoryUuid as CategoryEnum; + switch (category) { + case CategoryEnum.Login: + case CategoryEnum.Database: + case CategoryEnum.Password: + case CategoryEnum.WirelessRouter: + case CategoryEnum.Server: + case CategoryEnum.API_Credential: + cipher.type = CipherType.Login; + cipher.login = new LoginView(); + break; + case CategoryEnum.CreditCard: + case CategoryEnum.BankAccount: + cipher.type = CipherType.Card; + cipher.card = new CardView(); + break; + case CategoryEnum.SecureNote: + case CategoryEnum.SoftwareLicense: + case CategoryEnum.EmailAccount: + case CategoryEnum.MedicalRecord: + // case CategoryEnum.Document: + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + break; + case CategoryEnum.Identity: + case CategoryEnum.DriversLicense: + case CategoryEnum.OutdoorLicense: + case CategoryEnum.Membership: + case CategoryEnum.Passport: + case CategoryEnum.RewardsProgram: + case CategoryEnum.SocialSecurityNumber: + cipher.type = CipherType.Identity; + cipher.identity = new IdentityView(); + break; + default: + break; + } + + cipher.favorite = item.favIndex === 1 ? true : false; + + this.processOverview(item.overview, cipher); + + this.processLoginFields(item, cipher); + + this.processDetails(category, item.details, cipher); + + this.parsePasswordHistory(item.details.passwordHistory, cipher); + + this.processSections(category, item.details.sections, cipher); + + if (!this.isNullOrWhitespace(item.details.notesPlain)) { + cipher.notes = item.details.notesPlain.split(this.newLineRegex).join("\n") + "\n"; + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + this.result.ciphers.push(cipher); + }); + }); + + if (this.organization) { + this.moveFoldersToCollections(this.result); + } + + this.result.success = true; + return Promise.resolve(this.result); + } + + private processOverview(overview: Overview, cipher: CipherView) { + if (overview == null) { + return; + } + + cipher.name = this.getValueOrDefault(overview.title); + + if (overview.urls != null) { + const urls: string[] = []; + overview.urls.forEach((url: UrlsEntity) => { + if (!this.isNullOrWhitespace(url.url)) { + urls.push(url.url); + } + }); + cipher.login.uris = this.makeUriArray(urls); + } + + if (overview.tags != null && overview.tags.length > 0) { + const folderName = this.capitalize(overview.tags[0]); + this.processFolder(this.result, folderName); + } + } + + private capitalize(inputString: string): string { + return inputString.trim().replace(/\w\S*/g, (w) => w.replace(/^\w/, (c) => c.toUpperCase())); + } + + private processLoginFields(item: Item, cipher: CipherView) { + if (item.details == null) { + return; + } + + if (item.details.loginFields == null || item.details.loginFields.length === 0) { + return; + } + + item.details.loginFields.forEach((loginField) => { + if (loginField.designation === "username" && loginField.value !== "") { + cipher.type = CipherType.Login; + cipher.login.username = loginField.value; + return; + } + + if (loginField.designation === "password" && loginField.value !== "") { + cipher.type = CipherType.Login; + cipher.login.password = loginField.value; + return; + } + + let fieldValue = loginField.value; + let fieldType: FieldType = FieldType.Text; + switch (loginField.fieldType) { + case LoginFieldTypeEnum.Password: + fieldType = FieldType.Hidden; + break; + case LoginFieldTypeEnum.CheckBox: + fieldValue = loginField.value !== "" ? "true" : "false"; + fieldType = FieldType.Boolean; + break; + default: + break; + } + this.processKvp(cipher, loginField.name, fieldValue, fieldType); + }); + } + + private processDetails(category: CategoryEnum, details: Details, cipher: CipherView) { + if (category !== CategoryEnum.Password) { + return; + } + + if (details == null) { + return; + } + cipher.login.password = details.password; + } + + private processSections(category: CategoryEnum, sections: SectionsEntity[], cipher: CipherView) { + if (sections == null || sections.length === 0) { + return; + } + + sections.forEach((section: SectionsEntity) => { + if (section.fields == null) { + return; + } + + this.parseSectionFields(category, section.fields, cipher); + }); + } + + private parseSectionFields(category: CategoryEnum, fields: FieldsEntity[], cipher: CipherView) { + fields.forEach((field: FieldsEntity) => { + const valueKey = Object.keys(field.value)[0]; + const anyField = field as any; + + if ( + anyField.value == null || + anyField.value[valueKey] == null || + anyField.value[valueKey] === "" + ) { + return; + } + + const fieldName = this.getFieldName(field.id, field.title); + const fieldValue = this.extractValue(field.value, valueKey); + + if (cipher.type === CipherType.Login) { + if (this.fillLogin(field, fieldValue, cipher)) { + return; + } + + switch (category) { + case CategoryEnum.Login: + case CategoryEnum.Database: + case CategoryEnum.EmailAccount: + case CategoryEnum.WirelessRouter: + break; + + case CategoryEnum.Server: + if (this.isNullOrWhitespace(cipher.login.uri) && field.id === "url") { + cipher.login.uris = this.makeUriArray(fieldValue); + return; + } + break; + + case CategoryEnum.API_Credential: + if (this.fillApiCredentials(field, fieldValue, cipher)) { + return; + } + break; + default: + break; + } + } else if (cipher.type === CipherType.Card) { + if (this.fillCreditCard(field, fieldValue, cipher)) { + return; + } + + if (category === CategoryEnum.BankAccount) { + if (this.fillBankAccount(field, fieldValue, cipher)) { + return; + } + } + } else if (cipher.type === CipherType.Identity) { + if (this.fillIdentity(field, fieldValue, cipher, valueKey)) { + return; + } + if (valueKey === "address") { + // fieldValue is an object casted into a string, so access the plain value instead + const { street, city, country, zip, state } = field.value.address; + cipher.identity.address1 = this.getValueOrDefault(street); + cipher.identity.city = this.getValueOrDefault(city); + if (!this.isNullOrWhitespace(country)) { + cipher.identity.country = country.toUpperCase(); + } + cipher.identity.postalCode = this.getValueOrDefault(zip); + cipher.identity.state = this.getValueOrDefault(state); + return; + } + + switch (category) { + case CategoryEnum.Identity: + break; + case CategoryEnum.DriversLicense: + if (this.fillDriversLicense(field, fieldValue, cipher)) { + return; + } + break; + case CategoryEnum.OutdoorLicense: + if (this.fillOutdoorLicense(field, fieldValue, cipher)) { + return; + } + break; + case CategoryEnum.Membership: + if (this.fillMembership(field, fieldValue, cipher)) { + return; + } + break; + case CategoryEnum.Passport: + if (this.fillPassport(field, fieldValue, cipher)) { + return; + } + break; + case CategoryEnum.RewardsProgram: + if (this.fillRewardsProgram(field, fieldValue, cipher)) { + return; + } + break; + case CategoryEnum.SocialSecurityNumber: + if (this.fillSSN(field, fieldValue, cipher)) { + return; + } + break; + default: + break; + } + } + + if (valueKey === "email") { + // fieldValue is an object casted into a string, so access the plain value instead + const { email_address, provider } = field.value.email; + this.processKvp(cipher, fieldName, email_address, FieldType.Text); + this.processKvp(cipher, "provider", provider, FieldType.Text); + return; + } + + // Do not include a password field if it's already in the history + if ( + field.title === "password" && + cipher.passwordHistory != null && + cipher.passwordHistory.some((h) => h.password === fieldValue) + ) { + return; + } + + // TODO ?? If one of the fields is marked as guarded, then activate Password-Reprompt for the entire item + if (field.guarded && cipher.reprompt === CipherRepromptType.None) { + cipher.reprompt = CipherRepromptType.Password; + } + + const fieldType = valueKey === "concealed" ? FieldType.Hidden : FieldType.Text; + this.processKvp(cipher, fieldName, fieldValue, fieldType); + }); + } + + private getFieldName(id: string, title: string): string { + if (this.isNullOrWhitespace(title)) { + return id; + } + + // Naive approach of checking if the fields id is usable + if (id.length > 25 && RegExp(/[0-9]{2}[A-Z]{2}/, "i").test(id)) { + return title; + } + return id; + } + + private extractValue(value: Value, valueKey: string): string { + if (valueKey === "date") { + return new Date(value.date * 1000).toUTCString(); + } + + if (valueKey === "monthYear") { + return value.monthYear.toString(); + } + + return (value as any)[valueKey]; + } + + private fillLogin(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + const fieldName = this.getFieldName(field.id, field.title); + + if (this.isNullOrWhitespace(cipher.login.username) && fieldName === "username") { + cipher.login.username = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.login.password) && fieldName === "password") { + cipher.login.password = fieldValue; + return true; + } + + if ( + this.isNullOrWhitespace(cipher.login.totp) && + field.id != null && + field.id.startsWith("TOTP_") + ) { + cipher.login.totp = fieldValue; + return true; + } + + return false; + } + + private fillApiCredentials(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + const fieldName = this.getFieldName(field.id, field.title); + + if (this.isNullOrWhitespace(cipher.login.password) && fieldName === "credential") { + cipher.login.password = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.login.uri) && fieldName === "hostname") { + cipher.login.uris = this.makeUriArray(fieldValue); + return true; + } + + return false; + } + + private fillCreditCard(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.card.number) && field.id === "ccnum") { + cipher.card.number = fieldValue; + cipher.card.brand = this.getCardBrand(fieldValue); + return true; + } + + if (this.isNullOrWhitespace(cipher.card.code) && field.id === "cvv") { + cipher.card.code = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.card.cardholderName) && field.id === "cardholder") { + cipher.card.cardholderName = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.card.expiration) && field.id === "expiry") { + const monthYear: string = fieldValue.toString().trim(); + cipher.card.expMonth = monthYear.substring(4, 6); + if (cipher.card.expMonth[0] === "0") { + cipher.card.expMonth = cipher.card.expMonth.substring(1, 2); + } + cipher.card.expYear = monthYear.substring(0, 4); + return true; + } + + if (field.id === "type") { + // Skip since brand was determined from number above + return true; + } + + return false; + } + + private fillBankAccount(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.card.cardholderName) && field.id === "owner") { + cipher.card.cardholderName = fieldValue; + return true; + } + + return false; + } + + private fillIdentity( + field: FieldsEntity, + fieldValue: string, + cipher: CipherView, + valueKey: string + ): boolean { + if (this.isNullOrWhitespace(cipher.identity.firstName) && field.id === "firstname") { + cipher.identity.firstName = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.lastName) && field.id === "lastname") { + cipher.identity.lastName = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.middleName) && field.id === "initial") { + cipher.identity.middleName = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.phone) && field.id === "defphone") { + cipher.identity.phone = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.company) && field.id === "company") { + cipher.identity.company = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.email)) { + if (valueKey === "email") { + const { email_address, provider } = field.value.email; + cipher.identity.email = this.getValueOrDefault(email_address); + this.processKvp(cipher, "provider", provider, FieldType.Text); + return true; + } + + if (field.id === "email") { + cipher.identity.email = fieldValue; + return true; + } + } + + if (this.isNullOrWhitespace(cipher.identity.username) && field.id === "username") { + cipher.identity.username = fieldValue; + return true; + } + return false; + } + + private fillDriversLicense(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.identity.firstName) && field.id === "fullname") { + this.processFullName(cipher, fieldValue); + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.address1) && field.id === "address") { + cipher.identity.address1 = fieldValue; + return true; + } + + // TODO ISO code + if (this.isNullOrWhitespace(cipher.identity.country) && field.id === "country") { + cipher.identity.country = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.state) && field.id === "state") { + cipher.identity.state = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.licenseNumber) && field.id === "number") { + cipher.identity.licenseNumber = fieldValue; + return true; + } + + return false; + } + + private fillOutdoorLicense(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.identity.firstName) && field.id === "name") { + this.processFullName(cipher, fieldValue); + return true; + } + + // TODO ISO code + if (this.isNullOrWhitespace(cipher.identity.country) && field.id === "country") { + cipher.identity.country = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.state) && field.id === "state") { + cipher.identity.state = fieldValue; + return true; + } + + return false; + } + + private fillMembership(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.identity.firstName) && field.id === "member_name") { + this.processFullName(cipher, fieldValue); + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.company) && field.id === "org_name") { + cipher.identity.company = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.phone) && field.id === "phone") { + cipher.identity.phone = fieldValue; + return true; + } + + return false; + } + + private fillPassport(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.identity.firstName) && field.id === "fullname") { + this.processFullName(cipher, fieldValue); + return true; + } + + // TODO Iso + if (this.isNullOrWhitespace(cipher.identity.country) && field.id === "issuing_country") { + cipher.identity.country = fieldValue; + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.passportNumber) && field.id === "number") { + cipher.identity.passportNumber = fieldValue; + return true; + } + + return false; + } + + private fillRewardsProgram(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.identity.firstName) && field.id === "member_name") { + this.processFullName(cipher, fieldValue); + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.company) && field.id === "company_name") { + cipher.identity.company = fieldValue; + return true; + } + + return false; + } + + private fillSSN(field: FieldsEntity, fieldValue: string, cipher: CipherView): boolean { + if (this.isNullOrWhitespace(cipher.identity.firstName) && field.id === "name") { + this.processFullName(cipher, fieldValue); + return true; + } + + if (this.isNullOrWhitespace(cipher.identity.ssn) && field.id === "number") { + cipher.identity.ssn = fieldValue; + return true; + } + + return false; + } + + private parsePasswordHistory(historyItems: PasswordHistoryEntity[], cipher: CipherView) { + if (historyItems == null || historyItems.length === 0) { + return; + } + + const maxSize = historyItems.length > 5 ? 5 : historyItems.length; + cipher.passwordHistory = historyItems + .filter((h: any) => !this.isNullOrWhitespace(h.value) && h.time != null) + .sort((a, b) => b.time - a.time) + .slice(0, maxSize) + .map((h: any) => { + const ph = new PasswordHistoryView(); + ph.password = h.value; + ph.lastUsedDate = new Date(("" + h.time).length >= 13 ? h.time : h.time * 1000); + return ph; + }); + } +} diff --git a/libs/common/src/importers/onepasswordImporters/onepasswordCsvImporter.ts b/libs/common/src/importers/onepasswordImporters/onepasswordCsvImporter.ts new file mode 100644 index 0000000000..d28bdcccc5 --- /dev/null +++ b/libs/common/src/importers/onepasswordImporters/onepasswordCsvImporter.ts @@ -0,0 +1,383 @@ +import { CipherType } from "../../enums/cipherType"; +import { FieldType } from "../../enums/fieldType"; +import { ImportResult } from "../../models/domain/importResult"; +import { CipherView } from "../../models/view/cipherView"; +import { BaseImporter } from "../baseImporter"; +import { Importer } from "../importer"; + +import { CipherImportContext } from "./cipherImportContext"; + +export const IgnoredProperties = [ + "ainfo", + "autosubmit", + "notesplain", + "ps", + "scope", + "tags", + "title", + "uuid", + "notes", +]; + +export abstract class OnePasswordCsvImporter extends BaseImporter implements Importer { + protected loginPropertyParsers = [ + this.setLoginUsername, + this.setLoginPassword, + this.setLoginUris, + ]; + protected creditCardPropertyParsers = [ + this.setCreditCardNumber, + this.setCreditCardVerification, + this.setCreditCardCardholderName, + this.setCreditCardExpiry, + ]; + protected identityPropertyParsers = [ + this.setIdentityFirstName, + this.setIdentityInitial, + this.setIdentityLastName, + this.setIdentityUserName, + this.setIdentityEmail, + this.setIdentityPhone, + this.setIdentityCompany, + ]; + + abstract setCipherType(value: any, cipher: CipherView): void; + + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true, { + quoteChar: '"', + escapeChar: "\\", + }); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (this.isNullOrWhitespace(this.getProp(value, "title"))) { + return; + } + + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(this.getProp(value, "title"), "--"); + + this.setNotes(value, cipher); + + this.setCipherType(value, cipher); + + let altUsername: string = null; + for (const property in value) { + // eslint-disable-next-line + if (!value.hasOwnProperty(property) || this.isNullOrWhitespace(value[property])) { + continue; + } + + const context = new CipherImportContext(value, property, cipher); + if (cipher.type === CipherType.Login && this.setKnownLoginValue(context)) { + continue; + } else if (cipher.type === CipherType.Card && this.setKnownCreditCardValue(context)) { + continue; + } else if (cipher.type === CipherType.Identity && this.setKnownIdentityValue(context)) { + continue; + } + + altUsername = this.setUnknownValue(context, altUsername); + } + + if ( + cipher.type === CipherType.Login && + !this.isNullOrWhitespace(altUsername) && + this.isNullOrWhitespace(cipher.login.username) && + altUsername.indexOf("://") === -1 + ) { + cipher.login.username = altUsername; + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } + + protected getProp(obj: any, name: string): any { + const lowerObj = Object.entries(obj).reduce((agg: any, entry: [string, any]) => { + agg[entry[0].toLowerCase()] = entry[1]; + return agg; + }, {}); + return lowerObj[name.toLowerCase()]; + } + + protected getPropByRegexp(obj: any, regexp: RegExp): any { + const matchingKeys = Object.keys(obj).reduce((agg: string[], key: string) => { + if (key.match(regexp)) { + agg.push(key); + } + return agg; + }, []); + if (matchingKeys.length === 0) { + return null; + } else { + return obj[matchingKeys[0]]; + } + } + + protected getPropIncluding(obj: any, name: string): any { + const includesMap = Object.keys(obj).reduce((agg: string[], entry: string) => { + if (entry.toLowerCase().includes(name.toLowerCase())) { + agg.push(entry); + } + return agg; + }, []); + if (includesMap.length === 0) { + return null; + } else { + return obj[includesMap[0]]; + } + } + + protected setNotes(importRecord: any, cipher: CipherView) { + cipher.notes = + this.getValueOrDefault(this.getProp(importRecord, "notesPlain"), "") + + "\n" + + this.getValueOrDefault(this.getProp(importRecord, "notes"), "") + + "\n"; + cipher.notes.trim(); + } + + protected setKnownLoginValue(context: CipherImportContext): boolean { + return this.loginPropertyParsers.reduce((agg: boolean, func) => { + if (!agg) { + agg = func.bind(this)(context); + } + return agg; + }, false); + } + + protected setKnownCreditCardValue(context: CipherImportContext): boolean { + return this.creditCardPropertyParsers.reduce((agg: boolean, func) => { + if (!agg) { + agg = func.bind(this)(context); + } + return agg; + }, false); + } + + protected setKnownIdentityValue(context: CipherImportContext): boolean { + return this.identityPropertyParsers.reduce((agg: boolean, func) => { + if (!agg) { + agg = func.bind(this)(context); + } + return agg; + }, false); + } + + protected setUnknownValue(context: CipherImportContext, altUsername: string): string { + if ( + IgnoredProperties.indexOf(context.lowerProperty) === -1 && + !context.lowerProperty.startsWith("section:") && + !context.lowerProperty.startsWith("section ") + ) { + if (altUsername == null && context.lowerProperty === "email") { + return context.importRecord[context.property]; + } else if ( + context.lowerProperty === "created date" || + context.lowerProperty === "modified date" + ) { + const readableDate = new Date( + parseInt(context.importRecord[context.property], 10) * 1000 + ).toUTCString(); + this.processKvp(context.cipher, "1Password " + context.property, readableDate); + return null; + } + if ( + context.lowerProperty.includes("password") || + context.lowerProperty.includes("key") || + context.lowerProperty.includes("secret") + ) { + this.processKvp( + context.cipher, + context.property, + context.importRecord[context.property], + FieldType.Hidden + ); + } else { + this.processKvp(context.cipher, context.property, context.importRecord[context.property]); + } + } + return null; + } + + protected setIdentityFirstName(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.identity.firstName) && + context.lowerProperty.includes("first name") + ) { + context.cipher.identity.firstName = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setIdentityInitial(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.identity.middleName) && + context.lowerProperty.includes("initial") + ) { + context.cipher.identity.middleName = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setIdentityLastName(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.identity.lastName) && + context.lowerProperty.includes("last name") + ) { + context.cipher.identity.lastName = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setIdentityUserName(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.identity.username) && + context.lowerProperty.includes("username") + ) { + context.cipher.identity.username = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setIdentityCompany(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.identity.company) && + context.lowerProperty.includes("company") + ) { + context.cipher.identity.company = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setIdentityPhone(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.identity.phone) && + context.lowerProperty.includes("default phone") + ) { + context.cipher.identity.phone = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setIdentityEmail(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.identity.email) && + context.lowerProperty.includes("email") + ) { + context.cipher.identity.email = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setCreditCardNumber(context: CipherImportContext): boolean { + if ( + this.isNullOrWhitespace(context.cipher.card.number) && + context.lowerProperty.includes("number") + ) { + context.cipher.card.number = context.importRecord[context.property]; + context.cipher.card.brand = this.getCardBrand(context.cipher.card.number); + return true; + } + return false; + } + + protected setCreditCardVerification(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.card.code) && + context.lowerProperty.includes("verification number") + ) { + context.cipher.card.code = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setCreditCardCardholderName(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.card.cardholderName) && + context.lowerProperty.includes("cardholder name") + ) { + context.cipher.card.cardholderName = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setCreditCardExpiry(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.card.expiration) && + context.lowerProperty.includes("expiry date") && + context.importRecord[context.property].length === 7 + ) { + context.cipher.card.expMonth = (context.importRecord[context.property] as string).substr( + 0, + 2 + ); + if (context.cipher.card.expMonth[0] === "0") { + context.cipher.card.expMonth = context.cipher.card.expMonth.substr(1, 1); + } + context.cipher.card.expYear = (context.importRecord[context.property] as string).substr(3, 4); + return true; + } + return false; + } + + protected setLoginPassword(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.login.password) && + context.lowerProperty === "password" + ) { + context.cipher.login.password = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setLoginUsername(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.login.username) && + context.lowerProperty === "username" + ) { + context.cipher.login.username = context.importRecord[context.property]; + return true; + } + return false; + } + + protected setLoginUris(context: CipherImportContext) { + if ( + (context.cipher.login.uris == null || context.cipher.login.uris.length === 0) && + context.lowerProperty === "urls" + ) { + const urls = context.importRecord[context.property].split(this.newLineRegex); + context.cipher.login.uris = this.makeUriArray(urls); + return true; + } else if (context.lowerProperty === "url") { + if (context.cipher.login.uris == null) { + context.cipher.login.uris = []; + } + context.cipher.login.uris.concat(this.makeUriArray(context.importRecord[context.property])); + return true; + } + return false; + } +} diff --git a/libs/common/src/importers/onepasswordImporters/onepasswordMacCsvImporter.ts b/libs/common/src/importers/onepasswordImporters/onepasswordMacCsvImporter.ts new file mode 100644 index 0000000000..2135c80a34 --- /dev/null +++ b/libs/common/src/importers/onepasswordImporters/onepasswordMacCsvImporter.ts @@ -0,0 +1,31 @@ +import { CipherType } from "../../enums/cipherType"; +import { CardView } from "../../models/view/cardView"; +import { CipherView } from "../../models/view/cipherView"; +import { IdentityView } from "../../models/view/identityView"; +import { Importer } from "../importer"; + +import { IgnoredProperties, OnePasswordCsvImporter } from "./onepasswordCsvImporter"; + +export class OnePasswordMacCsvImporter extends OnePasswordCsvImporter implements Importer { + setCipherType(value: any, cipher: CipherView) { + const onePassType = this.getValueOrDefault(this.getProp(value, "type"), "Login"); + switch (onePassType) { + case "Credit Card": + cipher.type = CipherType.Card; + cipher.card = new CardView(); + IgnoredProperties.push("type"); + break; + case "Identity": + cipher.type = CipherType.Identity; + cipher.identity = new IdentityView(); + IgnoredProperties.push("type"); + break; + case "Login": + case "Secure Note": + IgnoredProperties.push("type"); + break; + default: + break; + } + } +} diff --git a/libs/common/src/importers/onepasswordImporters/onepasswordWinCsvImporter.ts b/libs/common/src/importers/onepasswordImporters/onepasswordWinCsvImporter.ts new file mode 100644 index 0000000000..3b3d6454f0 --- /dev/null +++ b/libs/common/src/importers/onepasswordImporters/onepasswordWinCsvImporter.ts @@ -0,0 +1,63 @@ +import { CipherType } from "../../enums/cipherType"; +import { CardView } from "../../models/view/cardView"; +import { CipherView } from "../../models/view/cipherView"; +import { IdentityView } from "../../models/view/identityView"; +import { LoginView } from "../../models/view/loginView"; +import { Importer } from "../importer"; + +import { CipherImportContext } from "./cipherImportContext"; +import { OnePasswordCsvImporter } from "./onepasswordCsvImporter"; + +export class OnePasswordWinCsvImporter extends OnePasswordCsvImporter implements Importer { + constructor() { + super(); + this.identityPropertyParsers.push(this.setIdentityAddress); + } + + setCipherType(value: any, cipher: CipherView) { + cipher.type = CipherType.Login; + cipher.login = new LoginView(); + + if ( + !this.isNullOrWhitespace(this.getPropByRegexp(value, /\d+: number/i)) && + !this.isNullOrWhitespace(this.getPropByRegexp(value, /\d+: expiry date/i)) + ) { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + } + + if ( + !this.isNullOrWhitespace(this.getPropByRegexp(value, /name \d+: first name/i)) || + !this.isNullOrWhitespace(this.getPropByRegexp(value, /name \d+: initial/i)) || + !this.isNullOrWhitespace(this.getPropByRegexp(value, /name \d+: last name/i)) || + !this.isNullOrWhitespace(this.getPropByRegexp(value, /internet \d+: email/i)) + ) { + cipher.type = CipherType.Identity; + cipher.identity = new IdentityView(); + } + } + + setIdentityAddress(context: CipherImportContext) { + if (context.lowerProperty.match(/address \d+: address/i)) { + this.processKvp(context.cipher, "address", context.importRecord[context.property]); + return true; + } + return false; + } + + setCreditCardExpiry(context: CipherImportContext) { + if ( + this.isNullOrWhitespace(context.cipher.card.expiration) && + context.lowerProperty.includes("expiry date") + ) { + const expSplit = (context.importRecord[context.property] as string).split("/"); + context.cipher.card.expMonth = expSplit[0]; + if (context.cipher.card.expMonth[0] === "0" && context.cipher.card.expMonth.length === 2) { + context.cipher.card.expMonth = context.cipher.card.expMonth.substr(1, 1); + } + context.cipher.card.expYear = expSplit[2].length > 4 ? expSplit[2].substr(0, 4) : expSplit[2]; + return true; + } + return false; + } +} diff --git a/libs/common/src/importers/onepasswordImporters/types/onepassword1PuxImporterTypes.ts b/libs/common/src/importers/onepasswordImporters/types/onepassword1PuxImporterTypes.ts new file mode 100644 index 0000000000..46ee06197b --- /dev/null +++ b/libs/common/src/importers/onepasswordImporters/types/onepassword1PuxImporterTypes.ts @@ -0,0 +1,160 @@ +export interface ExportData { + accounts?: AccountsEntity[] | null; +} +export interface AccountsEntity { + attrs: AccountAttributes; + vaults?: VaultsEntity[] | null; +} +export interface AccountAttributes { + accountName: string; + name: string; + avatar: string; + email: string; + uuid: string; + domain: string; +} +export interface VaultsEntity { + attrs: VaultAttributes; + items?: Item[] | null; +} +export interface VaultAttributes { + uuid: string; + desc: string; + avatar: string; + name: string; + type: string; +} + +export enum CategoryEnum { + Login = "001", + CreditCard = "002", + SecureNote = "003", + Identity = "004", + Password = "005", + Document = "006", + SoftwareLicense = "100", + BankAccount = "101", + Database = "102", + DriversLicense = "103", + OutdoorLicense = "104", + Membership = "105", + Passport = "106", + RewardsProgram = "107", + SocialSecurityNumber = "108", + WirelessRouter = "109", + Server = "110", + EmailAccount = "111", + API_Credential = "112", + MedicalRecord = "113", +} + +export interface Item { + uuid: string; + favIndex: number; + createdAt: number; + updatedAt: number; + trashed?: boolean; + categoryUuid: string; + details: Details; + overview: Overview; +} +export interface Details { + loginFields?: (LoginFieldsEntity | null)[] | null; + notesPlain?: string | null; + sections?: (SectionsEntity | null)[] | null; + passwordHistory?: (PasswordHistoryEntity | null)[] | null; + documentAttributes?: DocumentAttributes | null; + password?: string | null; +} + +export enum LoginFieldTypeEnum { + TextOrHtml = "T", + EmailAddress = "E", + URL = "U", + Number = "N", + Password = "P", + TextArea = "A", + PhoneNumber = "T", + CheckBox = "C", +} +export interface LoginFieldsEntity { + value: string; + id: string; + name: string; + fieldType: LoginFieldTypeEnum | string; + designation?: string | null; +} +export interface SectionsEntity { + title: string; + name?: string | null; + fields?: FieldsEntity[] | null; +} +export interface FieldsEntity { + title: string; + id: string; + value: Value; + indexAtSource: number; + guarded: boolean; + multiline: boolean; + dontGenerate: boolean; + placeholder?: string; + inputTraits: InputTraits; + clipboardFilter?: string | null; +} +export interface Value { + totp?: string | null; + date?: number | null; + string?: string | null; + concealed?: string | null; + email?: Email | null; + phone?: string | null; + menu?: string | null; + gender?: string | null; + monthYear?: number | null; + url?: string | null; + address?: Address | null; + creditCardType?: string | null; + creditCardNumber?: string | null; + reference?: string | null; +} + +export interface Email { + email_address: string; + provider: string; +} + +export interface Address { + street: string; + city: string; + country: string; + zip: string; + state: string; +} +export interface InputTraits { + keyboard: string; + correction: string; + capitalization: string; +} +export interface PasswordHistoryEntity { + value: string; + time: number; +} +export interface DocumentAttributes { + fileName: string; + documentId: string; + decryptedSize: number; +} +export interface Overview { + subtitle: string; + title: string; + url: string; + urls?: UrlsEntity[] | null; + ps?: number | null; + pbe?: number | null; + pgrng?: boolean | null; + tags?: string[] | null; +} +export interface UrlsEntity { + label: string; + url: string; +} diff --git a/libs/common/src/importers/padlockCsvImporter.ts b/libs/common/src/importers/padlockCsvImporter.ts new file mode 100644 index 0000000000..821391cff3 --- /dev/null +++ b/libs/common/src/importers/padlockCsvImporter.ts @@ -0,0 +1,85 @@ +import { ImportResult } from "../models/domain/importResult"; +import { CollectionView } from "../models/view/collectionView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PadlockCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + let headers: string[] = null; + results.forEach((value) => { + if (headers == null) { + headers = value.map((v: string) => v); + return; + } + + if (value.length < 2 || value.length !== headers.length) { + return; + } + + if (!this.isNullOrWhitespace(value[1])) { + if (this.organization) { + const tags = (value[1] as string).split(","); + tags.forEach((tag) => { + tag = tag.trim(); + let addCollection = true; + let collectionIndex = result.collections.length; + + for (let i = 0; i < result.collections.length; i++) { + if (result.collections[i].name === tag) { + addCollection = false; + collectionIndex = i; + break; + } + } + + if (addCollection) { + const collection = new CollectionView(); + collection.name = tag; + result.collections.push(collection); + } + + result.collectionRelationships.push([result.ciphers.length, collectionIndex]); + }); + } else { + const tags = (value[1] as string).split(","); + const tag = tags.length > 0 ? tags[0].trim() : null; + this.processFolder(result, tag); + } + } + + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value[0], "--"); + + for (let i = 2; i < value.length; i++) { + const header = headers[i].trim().toLowerCase(); + if (this.isNullOrWhitespace(value[i]) || this.isNullOrWhitespace(header)) { + continue; + } + + if (this.usernameFieldNames.indexOf(header) > -1) { + cipher.login.username = value[i]; + } else if (this.passwordFieldNames.indexOf(header) > -1) { + cipher.login.password = value[i]; + } else if (this.uriFieldNames.indexOf(header) > -1) { + cipher.login.uris = this.makeUriArray(value[i]); + } else { + this.processKvp(cipher, headers[i], value[i]); + } + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/passkeepCsvImporter.ts b/libs/common/src/importers/passkeepCsvImporter.ts new file mode 100644 index 0000000000..c93b3a42ee --- /dev/null +++ b/libs/common/src/importers/passkeepCsvImporter.ts @@ -0,0 +1,39 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PassKeepCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + this.processFolder(result, this.getValue("category", value)); + const cipher = this.initLoginCipher(); + cipher.notes = this.getValue("description", value); + cipher.name = this.getValueOrDefault(this.getValue("title", value), "--"); + cipher.login.username = this.getValue("username", value); + cipher.login.password = this.getValue("password", value); + cipher.login.uris = this.makeUriArray(this.getValue("site", value)); + this.processKvp(cipher, "Password 2", this.getValue("password2", value)); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + private getValue(key: string, value: any) { + return this.getValueOrDefault(value[key], this.getValueOrDefault(value[" " + key])); + } +} diff --git a/libs/common/src/importers/passmanJsonImporter.ts b/libs/common/src/importers/passmanJsonImporter.ts new file mode 100644 index 0000000000..f8bc7106bd --- /dev/null +++ b/libs/common/src/importers/passmanJsonImporter.ts @@ -0,0 +1,61 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PassmanJsonImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = JSON.parse(data); + if (results == null || results.length === 0) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((credential: any) => { + if (credential.tags != null && credential.tags.length > 0) { + const folderName = credential.tags[0].text; + this.processFolder(result, folderName); + } + + const cipher = this.initLoginCipher(); + cipher.name = credential.label; + + cipher.login.username = this.getValueOrDefault(credential.username); + if (this.isNullOrWhitespace(cipher.login.username)) { + cipher.login.username = this.getValueOrDefault(credential.email); + } else if (!this.isNullOrWhitespace(credential.email)) { + cipher.notes = "Email: " + credential.email + "\n"; + } + + cipher.login.password = this.getValueOrDefault(credential.password); + cipher.login.uris = this.makeUriArray(credential.url); + cipher.notes += this.getValueOrDefault(credential.description, ""); + if (credential.otp != null) { + cipher.login.totp = this.getValueOrDefault(credential.otp.secret); + } + + if (credential.custom_fields != null) { + credential.custom_fields.forEach((customField: any) => { + switch (customField.field_type) { + case "text": + case "password": + this.processKvp(cipher, customField.label, customField.value); + break; + } + }); + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/passpackCsvImporter.ts b/libs/common/src/importers/passpackCsvImporter.ts new file mode 100644 index 0000000000..8efaa3c3e7 --- /dev/null +++ b/libs/common/src/importers/passpackCsvImporter.ts @@ -0,0 +1,103 @@ +import { ImportResult } from "../models/domain/importResult"; +import { CollectionView } from "../models/view/collectionView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PasspackCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const tagsJson = !this.isNullOrWhitespace(value.Tags) ? JSON.parse(value.Tags) : null; + const tags: string[] = + tagsJson != null && tagsJson.tags != null && tagsJson.tags.length > 0 + ? tagsJson.tags + .map((tagJson: string) => { + try { + const t = JSON.parse(tagJson); + return this.getValueOrDefault(t.tag); + } catch { + // Ignore error + } + return null; + }) + .filter((t: string) => !this.isNullOrWhitespace(t)) + : null; + + if (this.organization && tags != null && tags.length > 0) { + tags.forEach((tag) => { + let addCollection = true; + let collectionIndex = result.collections.length; + + for (let i = 0; i < result.collections.length; i++) { + if (result.collections[i].name === tag) { + addCollection = false; + collectionIndex = i; + break; + } + } + + if (addCollection) { + const collection = new CollectionView(); + collection.name = tag; + result.collections.push(collection); + } + + result.collectionRelationships.push([result.ciphers.length, collectionIndex]); + }); + } else if (!this.organization && tags != null && tags.length > 0) { + this.processFolder(result, tags[0]); + } + + const cipher = this.initLoginCipher(); + cipher.notes = this.getValueOrDefault(value.Notes, ""); + cipher.notes += "\n\n" + this.getValueOrDefault(value["Shared Notes"], "") + "\n"; + cipher.name = this.getValueOrDefault(value["Entry Name"], "--"); + cipher.login.username = this.getValueOrDefault(value["User ID"]); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.uris = this.makeUriArray(value.URL); + + if (value.__parsed_extra != null && value.__parsed_extra.length > 0) { + value.__parsed_extra.forEach((extra: string) => { + if (!this.isNullOrWhitespace(extra)) { + cipher.notes += "\n" + extra; + } + }); + } + + const fieldsJson = !this.isNullOrWhitespace(value["Extra Fields"]) + ? JSON.parse(value["Extra Fields"]) + : null; + const fields = + fieldsJson != null && fieldsJson.extraFields != null && fieldsJson.extraFields.length > 0 + ? fieldsJson.extraFields.map((fieldJson: string) => { + try { + return JSON.parse(fieldJson); + } catch { + // Ignore error + } + return null; + }) + : null; + if (fields != null) { + fields.forEach((f: any) => { + if (f != null) { + this.processKvp(cipher, f.name, f.data); + } + }); + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/passwordAgentCsvImporter.ts b/libs/common/src/importers/passwordAgentCsvImporter.ts new file mode 100644 index 0000000000..cc37f5dd30 --- /dev/null +++ b/libs/common/src/importers/passwordAgentCsvImporter.ts @@ -0,0 +1,52 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PasswordAgentCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + let newVersion = true; + results.forEach((value) => { + if (value.length !== 5 && value.length < 9) { + return; + } + const altFormat = value.length === 10 && value[0] === "0"; + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value[altFormat ? 1 : 0], "--"); + cipher.login.username = this.getValueOrDefault(value[altFormat ? 2 : 1]); + cipher.login.password = this.getValueOrDefault(value[altFormat ? 3 : 2]); + if (value.length === 5) { + newVersion = false; + cipher.notes = this.getValueOrDefault(value[4]); + cipher.login.uris = this.makeUriArray(value[3]); + } else { + const folder = this.getValueOrDefault(value[altFormat ? 9 : 8], "(None)"); + let folderName = folder !== "(None)" ? folder.split("\\").join("/") : null; + if (folderName != null) { + folderName = folder.split(" > ").join("/"); + folderName = folder.split(">").join("/"); + } + this.processFolder(result, folderName); + cipher.notes = this.getValueOrDefault(value[altFormat ? 5 : 3]); + cipher.login.uris = this.makeUriArray(value[4]); + } + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (newVersion && this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/passwordBossJsonImporter.ts b/libs/common/src/importers/passwordBossJsonImporter.ts new file mode 100644 index 0000000000..d60a84fb06 --- /dev/null +++ b/libs/common/src/importers/passwordBossJsonImporter.ts @@ -0,0 +1,130 @@ +import { CipherType } from "../enums/cipherType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; +import { FolderView } from "../models/view/folderView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PasswordBossJsonImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = JSON.parse(data); + if (results == null || results.items == null) { + result.success = false; + return Promise.resolve(result); + } + + const foldersMap = new Map(); + results.folders.forEach((value: any) => { + foldersMap.set(value.id, value.name); + }); + const foldersIndexMap = new Map(); + foldersMap.forEach((val, key) => { + foldersIndexMap.set(key, result.folders.length); + const f = new FolderView(); + f.name = val; + result.folders.push(f); + }); + + results.items.forEach((value: any) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.name, "--"); + cipher.login.uris = this.makeUriArray(value.login_url); + + if (value.folder != null && foldersIndexMap.has(value.folder)) { + result.folderRelationships.push([result.ciphers.length, foldersIndexMap.get(value.folder)]); + } + + if (value.identifiers == null) { + return; + } + + if (!this.isNullOrWhitespace(value.identifiers.notes)) { + cipher.notes = value.identifiers.notes.split("\\r\\n").join("\n").split("\\n").join("\n"); + } + + if (value.type === "CreditCard") { + cipher.card = new CardView(); + cipher.type = CipherType.Card; + } + + for (const property in value.identifiers) { + // eslint-disable-next-line + if (!value.identifiers.hasOwnProperty(property)) { + continue; + } + const valObj = value.identifiers[property]; + const val = valObj != null ? valObj.toString() : null; + if ( + this.isNullOrWhitespace(val) || + property === "notes" || + property === "ignoreItemInSecurityScore" + ) { + continue; + } + + if (property === "custom_fields") { + valObj.forEach((cf: any) => { + this.processKvp(cipher, cf.name, cf.value); + }); + continue; + } + + if (cipher.type === CipherType.Card) { + if (property === "cardNumber") { + cipher.card.number = val; + cipher.card.brand = this.getCardBrand(val); + continue; + } else if (property === "nameOnCard") { + cipher.card.cardholderName = val; + continue; + } else if (property === "security_code") { + cipher.card.code = val; + continue; + } else if (property === "expires") { + try { + const expDate = new Date(val); + cipher.card.expYear = expDate.getFullYear().toString(); + cipher.card.expMonth = (expDate.getMonth() + 1).toString(); + } catch { + // Ignore error + } + continue; + } else if (property === "cardType") { + continue; + } + } else { + if ( + (property === "username" || property === "email") && + this.isNullOrWhitespace(cipher.login.username) + ) { + cipher.login.username = val; + continue; + } else if (property === "password") { + cipher.login.password = val; + continue; + } else if (property === "totp") { + cipher.login.totp = val; + continue; + } else if ( + (cipher.login.uris == null || cipher.login.uris.length === 0) && + this.uriFieldNames.indexOf(property) > -1 + ) { + cipher.login.uris = this.makeUriArray(val); + continue; + } + } + + this.processKvp(cipher, property, val); + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/passwordDragonXmlImporter.ts b/libs/common/src/importers/passwordDragonXmlImporter.ts new file mode 100644 index 0000000000..433950ad5f --- /dev/null +++ b/libs/common/src/importers/passwordDragonXmlImporter.ts @@ -0,0 +1,63 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PasswordDragonXmlImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const doc = this.parseXml(data); + if (doc == null) { + result.success = false; + return Promise.resolve(result); + } + + const records = doc.querySelectorAll("PasswordManager > record"); + Array.from(records).forEach((record) => { + const category = this.querySelectorDirectChild(record, "Category"); + const categoryText = + category != null && + !this.isNullOrWhitespace(category.textContent) && + category.textContent !== "Unfiled" + ? category.textContent + : null; + this.processFolder(result, categoryText); + + const accountName = this.querySelectorDirectChild(record, "Account-Name"); + const userId = this.querySelectorDirectChild(record, "User-Id"); + const password = this.querySelectorDirectChild(record, "Password"); + const url = this.querySelectorDirectChild(record, "URL"); + const notes = this.querySelectorDirectChild(record, "Notes"); + const cipher = this.initLoginCipher(); + cipher.name = + accountName != null ? this.getValueOrDefault(accountName.textContent, "--") : "--"; + cipher.notes = notes != null ? this.getValueOrDefault(notes.textContent) : ""; + cipher.login.username = userId != null ? this.getValueOrDefault(userId.textContent) : null; + cipher.login.password = + password != null ? this.getValueOrDefault(password.textContent) : null; + cipher.login.uris = url != null ? this.makeUriArray(url.textContent) : null; + + const attributes: string[] = []; + for (let i = 1; i <= 10; i++) { + attributes.push("Attribute-" + i); + } + + this.querySelectorAllDirectChild(record, attributes.join(",")).forEach((attr) => { + if (this.isNullOrWhitespace(attr.textContent) || attr.textContent === "null") { + return; + } + this.processKvp(cipher, attr.tagName, attr.textContent); + }); + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/passwordSafeXmlImporter.ts b/libs/common/src/importers/passwordSafeXmlImporter.ts new file mode 100644 index 0000000000..b7aa935879 --- /dev/null +++ b/libs/common/src/importers/passwordSafeXmlImporter.ts @@ -0,0 +1,69 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PasswordSafeXmlImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const doc = this.parseXml(data); + if (doc == null) { + result.success = false; + return Promise.resolve(result); + } + + const passwordSafe = doc.querySelector("passwordsafe"); + if (passwordSafe == null) { + result.errorMessage = "Missing `passwordsafe` node."; + result.success = false; + return Promise.resolve(result); + } + + const notesDelimiter = passwordSafe.getAttribute("delimiter"); + const entries = doc.querySelectorAll("passwordsafe > entry"); + Array.from(entries).forEach((entry) => { + const group = this.querySelectorDirectChild(entry, "group"); + const groupText = + group != null && !this.isNullOrWhitespace(group.textContent) + ? group.textContent.split(".").join("/") + : null; + this.processFolder(result, groupText); + + const title = this.querySelectorDirectChild(entry, "title"); + const username = this.querySelectorDirectChild(entry, "username"); + const email = this.querySelectorDirectChild(entry, "email"); + const password = this.querySelectorDirectChild(entry, "password"); + const url = this.querySelectorDirectChild(entry, "url"); + const notes = this.querySelectorDirectChild(entry, "notes"); + const cipher = this.initLoginCipher(); + cipher.name = title != null ? this.getValueOrDefault(title.textContent, "--") : "--"; + cipher.notes = + notes != null + ? this.getValueOrDefault(notes.textContent, "").split(notesDelimiter).join("\n") + : null; + cipher.login.username = + username != null ? this.getValueOrDefault(username.textContent) : null; + cipher.login.password = + password != null ? this.getValueOrDefault(password.textContent) : null; + cipher.login.uris = url != null ? this.makeUriArray(url.textContent) : null; + + if (this.isNullOrWhitespace(cipher.login.username) && email != null) { + cipher.login.username = this.getValueOrDefault(email.textContent); + } else if (email != null && !this.isNullOrWhitespace(email.textContent)) { + cipher.notes = this.isNullOrWhitespace(cipher.notes) + ? "Email: " + email.textContent + : cipher.notes + "\n" + "Email: " + email.textContent; + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/passwordWalletTxtImporter.ts b/libs/common/src/importers/passwordWalletTxtImporter.ts new file mode 100644 index 0000000000..b5940372a2 --- /dev/null +++ b/libs/common/src/importers/passwordWalletTxtImporter.ts @@ -0,0 +1,47 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class PasswordWalletTxtImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.length < 1) { + return; + } + if (value.length > 5) { + this.processFolder(result, value[5]); + } + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value[0], "--"); + if (value.length > 4) { + cipher.notes = this.getValueOrDefault(value[4], "").split("¬").join("\n"); + } + if (value.length > 2) { + cipher.login.username = this.getValueOrDefault(value[2]); + } + if (value.length > 3) { + cipher.login.password = this.getValueOrDefault(value[3]); + } + if (value.length > 1) { + cipher.login.uris = this.makeUriArray(value[1]); + } + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/rememBearCsvImporter.ts b/libs/common/src/importers/rememBearCsvImporter.ts new file mode 100644 index 0000000000..3f7dc464f3 --- /dev/null +++ b/libs/common/src/importers/rememBearCsvImporter.ts @@ -0,0 +1,75 @@ +import { CipherType } from "../enums/cipherType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class RememBearCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.trash === "true") { + return; + } + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.name); + cipher.notes = this.getValueOrDefault(value.notes); + if (value.type === "LoginItem") { + cipher.login.uris = this.makeUriArray(value.website); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.username = this.getValueOrDefault(value.username); + } else if (value.type === "CreditCardItem") { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + cipher.card.cardholderName = this.getValueOrDefault(value.cardholder); + cipher.card.number = this.getValueOrDefault(value.number); + cipher.card.brand = this.getCardBrand(cipher.card.number); + cipher.card.code = this.getValueOrDefault(value.verification); + + try { + const expMonth = this.getValueOrDefault(value.expiryMonth); + if (expMonth != null) { + const expMonthNumber = parseInt(expMonth, null); + if (expMonthNumber != null && expMonthNumber >= 1 && expMonthNumber <= 12) { + cipher.card.expMonth = expMonthNumber.toString(); + } + } + } catch { + // Ignore error + } + try { + const expYear = this.getValueOrDefault(value.expiryYear); + if (expYear != null) { + const expYearNumber = parseInt(expYear, null); + if (expYearNumber != null) { + cipher.card.expYear = expYearNumber.toString(); + } + } + } catch { + // Ignore error + } + + const pin = this.getValueOrDefault(value.pin); + if (pin != null) { + this.processKvp(cipher, "PIN", pin); + } + const zip = this.getValueOrDefault(value.zipCode); + if (zip != null) { + this.processKvp(cipher, "Zip Code", zip); + } + } + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/roboformCsvImporter.ts b/libs/common/src/importers/roboformCsvImporter.ts new file mode 100644 index 0000000000..c5279e2b1c --- /dev/null +++ b/libs/common/src/importers/roboformCsvImporter.ts @@ -0,0 +1,69 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class RoboFormCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + let i = 1; + results.forEach((value) => { + const folder = + !this.isNullOrWhitespace(value.Folder) && value.Folder.startsWith("/") + ? value.Folder.replace("/", "") + : value.Folder; + const folderName = !this.isNullOrWhitespace(folder) ? folder : null; + this.processFolder(result, folderName); + + const cipher = this.initLoginCipher(); + cipher.notes = this.getValueOrDefault(value.Note); + cipher.name = this.getValueOrDefault(value.Name, "--"); + cipher.login.username = this.getValueOrDefault(value.Login); + cipher.login.password = this.getValueOrDefault(value.Pwd); + cipher.login.uris = this.makeUriArray(value.Url); + + if (!this.isNullOrWhitespace(value.Rf_fields)) { + let fields: string[] = [value.Rf_fields]; + if (value.__parsed_extra != null && value.__parsed_extra.length > 0) { + fields = fields.concat(value.__parsed_extra); + } + fields.forEach((field: string) => { + const parts = field.split(":"); + if (parts.length < 3) { + return; + } + const key = parts[0] === "-no-name-" ? null : parts[0]; + const val = parts.length === 4 && parts[2] === "rck" ? parts[1] : parts[2]; + this.processKvp(cipher, key, val); + }); + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + + if ( + i === results.length && + cipher.name === "--" && + this.isNullOrWhitespace(cipher.login.password) + ) { + return; + } + + result.ciphers.push(cipher); + i++; + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/safariCsvImporter.ts b/libs/common/src/importers/safariCsvImporter.ts new file mode 100644 index 0000000000..786b282783 --- /dev/null +++ b/libs/common/src/importers/safariCsvImporter.ts @@ -0,0 +1,30 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class SafariCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.Title, "--"); + cipher.login.username = this.getValueOrDefault(value.Username); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.uris = this.makeUriArray(value.Url ?? value.URL); + cipher.login.totp = this.getValueOrDefault(value.OTPAuth); + cipher.notes = this.getValueOrDefault(value.Notes); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/safeInCloudXmlImporter.ts b/libs/common/src/importers/safeInCloudXmlImporter.ts new file mode 100644 index 0000000000..3e5a819938 --- /dev/null +++ b/libs/common/src/importers/safeInCloudXmlImporter.ts @@ -0,0 +1,132 @@ +import { CipherType } from "../enums/cipherType"; +import { FieldType } from "../enums/fieldType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { CipherView } from "../models/view/cipherView"; +import { FieldView } from "../models/view/fieldView"; +import { FolderView } from "../models/view/folderView"; +import { SecureNoteView } from "../models/view/secureNoteView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class SafeInCloudXmlImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const doc = this.parseXml(data); + if (doc == null) { + result.success = false; + return Promise.resolve(result); + } + + const db = doc.querySelector("database"); + if (db == null) { + result.errorMessage = "Missing `database` node."; + result.success = false; + return Promise.resolve(result); + } + + const foldersMap = new Map(); + + Array.from(doc.querySelectorAll("database > label")).forEach((labelEl) => { + const name = labelEl.getAttribute("name"); + const id = labelEl.getAttribute("id"); + if (!this.isNullOrWhitespace(name) && !this.isNullOrWhitespace(id)) { + foldersMap.set(id, result.folders.length); + const folder = new FolderView(); + folder.name = name; + result.folders.push(folder); + } + }); + + Array.from(doc.querySelectorAll("database > card")).forEach((cardEl) => { + if (cardEl.getAttribute("template") === "true" || cardEl.getAttribute("deleted") === "true") { + return; + } + + const labelIdEl = this.querySelectorDirectChild(cardEl, "label_id"); + if (labelIdEl != null) { + const labelId = labelIdEl.textContent; + if (!this.isNullOrWhitespace(labelId) && foldersMap.has(labelId)) { + result.folderRelationships.push([result.ciphers.length, foldersMap.get(labelId)]); + } + } + + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(cardEl.getAttribute("title"), "--"); + + if (cardEl.getAttribute("star") === "true") { + cipher.favorite = true; + } + + const cardType = cardEl.getAttribute("type"); + if (cardType === "note") { + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + } else { + Array.from(this.querySelectorAllDirectChild(cardEl, "field")).forEach((fieldEl) => { + const text = fieldEl.textContent; + if (this.isNullOrWhitespace(text)) { + return; + } + const name = fieldEl.getAttribute("name"); + const fieldType = this.getValueOrDefault(fieldEl.getAttribute("type"), "").toLowerCase(); + if (fieldType === "login") { + cipher.login.username = text; + } else if (fieldType === "password" || fieldType === "secret") { + // safeInCloud allows for more than one password. we just insert them here and find the one used as password later + this.processKvp(cipher, name, text, FieldType.Hidden); + } else if (fieldType === "one_time_password") { + cipher.login.totp = text; + } else if (fieldType === "notes") { + cipher.notes += text + "\n"; + } else if (fieldType === "weblogin" || fieldType === "website") { + cipher.login.uris = this.makeUriArray(text); + } else { + this.processKvp(cipher, name, text); + } + }); + } + + Array.from(this.querySelectorAllDirectChild(cardEl, "notes")).forEach((notesEl) => { + cipher.notes += notesEl.textContent + "\n"; + }); + + this.setPassword(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + // Choose a password from all passwords. Take one that has password in its name, or the first one if there is no such entry + // if its name is password, we can safely remove it form the fields. otherwise, it would maybe be best to keep it as a hidden field + setPassword(cipher: CipherView) { + const candidates = cipher.fields.filter((field) => field.type === FieldType.Hidden); + if (!candidates.length) { + return; + } + + let choice: FieldView; + for (const field of candidates) { + if (this.passwordFieldNames.includes(field.name.toLowerCase())) { + choice = field; + cipher.fields = cipher.fields.filter((f) => f !== choice); + break; + } + } + + if (!choice) { + choice = candidates[0]; + } + + cipher.login.password = choice.value; + } +} diff --git a/libs/common/src/importers/saferpassCsvImport.ts b/libs/common/src/importers/saferpassCsvImport.ts new file mode 100644 index 0000000000..6d962ba1b5 --- /dev/null +++ b/libs/common/src/importers/saferpassCsvImport.ts @@ -0,0 +1,29 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class SaferPassCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(this.nameFromUrl(value.url), "--"); + cipher.notes = this.getValueOrDefault(value.notes); + cipher.login.username = this.getValueOrDefault(value.username); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.uris = this.makeUriArray(value.url); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/secureSafeCsvImporter.ts b/libs/common/src/importers/secureSafeCsvImporter.ts new file mode 100644 index 0000000000..8d0ac1fee6 --- /dev/null +++ b/libs/common/src/importers/secureSafeCsvImporter.ts @@ -0,0 +1,29 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class SecureSafeCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.Title); + cipher.notes = this.getValueOrDefault(value.Comment); + cipher.login.uris = this.makeUriArray(value.Url); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.username = this.getValueOrDefault(value.Username); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/splashIdCsvImporter.ts b/libs/common/src/importers/splashIdCsvImporter.ts new file mode 100644 index 0000000000..df1118d178 --- /dev/null +++ b/libs/common/src/importers/splashIdCsvImporter.ts @@ -0,0 +1,57 @@ +import { ImportResult } from "../models/domain/importResult"; +import { CipherView } from "../models/view/cipherView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class SplashIdCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.length < 3) { + return; + } + + this.processFolder(result, this.getValueOrDefault(value[value.length - 1])); + const cipher = this.initLoginCipher(); + cipher.notes = this.getValueOrDefault(value[value.length - 2], ""); + cipher.name = this.getValueOrDefault(value[1], "--"); + + if (value[0] === "Web Logins" || value[0] === "Servers" || value[0] === "Email Accounts") { + cipher.login.username = this.getValueOrDefault(value[2]); + cipher.login.password = this.getValueOrDefault(value[3]); + cipher.login.uris = this.makeUriArray(value[4]); + this.parseFieldsToNotes(cipher, 5, value); + } else { + this.parseFieldsToNotes(cipher, 2, value); + } + + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + private parseFieldsToNotes(cipher: CipherView, startIndex: number, value: any) { + // last 3 rows do not get parsed + for (let i = startIndex; i < value.length - 3; i++) { + if (this.isNullOrWhitespace(value[i])) { + continue; + } + cipher.notes += value[i] + "\n"; + } + } +} diff --git a/libs/common/src/importers/stickyPasswordXmlImporter.ts b/libs/common/src/importers/stickyPasswordXmlImporter.ts new file mode 100644 index 0000000000..caaa33702f --- /dev/null +++ b/libs/common/src/importers/stickyPasswordXmlImporter.ts @@ -0,0 +1,83 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class StickyPasswordXmlImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const doc = this.parseXml(data); + if (doc == null) { + result.success = false; + return Promise.resolve(result); + } + + const loginNodes = doc.querySelectorAll("root > Database > Logins > Login"); + Array.from(loginNodes).forEach((loginNode) => { + const accountId = loginNode.getAttribute("ID"); + if (this.isNullOrWhitespace(accountId)) { + return; + } + + const usernameText = loginNode.getAttribute("Name"); + const passwordText = loginNode.getAttribute("Password"); + let titleText: string = null; + let linkText: string = null; + let notesText: string = null; + let groupId: string = null; + let groupText: string = null; + + const accountLogin = doc.querySelector( + "root > Database > Accounts > Account > " + + 'LoginLinks > Login[SourceLoginID="' + + accountId + + '"]' + ); + if (accountLogin != null) { + const account = accountLogin.parentElement.parentElement; + if (account != null) { + titleText = account.getAttribute("Name"); + linkText = account.getAttribute("Link"); + groupId = account.getAttribute("ParentID"); + notesText = account.getAttribute("Comments"); + if (!this.isNullOrWhitespace(notesText)) { + notesText = notesText.split("/n").join("\n"); + } + } + } + + if (!this.isNullOrWhitespace(groupId)) { + groupText = this.buildGroupText(doc, groupId, ""); + this.processFolder(result, groupText); + } + + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(titleText, "--"); + cipher.notes = this.getValueOrDefault(notesText); + cipher.login.username = this.getValueOrDefault(usernameText); + cipher.login.password = this.getValueOrDefault(passwordText); + cipher.login.uris = this.makeUriArray(linkText); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + buildGroupText(doc: Document, groupId: string, groupText: string): string { + const group = doc.querySelector('root > Database > Groups > Group[ID="' + groupId + '"]'); + if (group == null) { + return groupText; + } + if (!this.isNullOrWhitespace(groupText)) { + groupText = "/" + groupText; + } + groupText = group.getAttribute("Name") + groupText; + return this.buildGroupText(doc, group.getAttribute("ParentID"), groupText); + } +} diff --git a/libs/common/src/importers/truekeyCsvImporter.ts b/libs/common/src/importers/truekeyCsvImporter.ts new file mode 100644 index 0000000000..d28af7af07 --- /dev/null +++ b/libs/common/src/importers/truekeyCsvImporter.ts @@ -0,0 +1,87 @@ +import { CipherType } from "../enums/cipherType"; +import { SecureNoteType } from "../enums/secureNoteType"; +import { ImportResult } from "../models/domain/importResult"; +import { CardView } from "../models/view/cardView"; +import { SecureNoteView } from "../models/view/secureNoteView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +const PropertiesToIgnore = [ + "kind", + "autologin", + "favorite", + "hexcolor", + "protectedwithpassword", + "subdomainonly", + "type", + "tk_export_version", + "note", + "title", + "document_content", +]; + +export class TrueKeyCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.favorite = this.getValueOrDefault(value.favorite, "").toLowerCase() === "true"; + cipher.name = this.getValueOrDefault(value.name, "--"); + cipher.notes = this.getValueOrDefault(value.memo, ""); + cipher.login.username = this.getValueOrDefault(value.login); + cipher.login.password = this.getValueOrDefault(value.password); + cipher.login.uris = this.makeUriArray(value.url); + + if (value.kind !== "login") { + cipher.name = this.getValueOrDefault(value.title, "--"); + cipher.notes = this.getValueOrDefault(value.note, ""); + } + + if (value.kind === "cc") { + cipher.type = CipherType.Card; + cipher.card = new CardView(); + cipher.card.cardholderName = this.getValueOrDefault(value.cardholder); + cipher.card.number = this.getValueOrDefault(value.number); + cipher.card.brand = this.getCardBrand(cipher.card.number); + if (!this.isNullOrWhitespace(value.expiryDate)) { + try { + const expDate = new Date(value.expiryDate); + cipher.card.expYear = expDate.getFullYear().toString(); + cipher.card.expMonth = (expDate.getMonth() + 1).toString(); + } catch { + // Ignore error + } + } + } else if (value.kind !== "login") { + cipher.type = CipherType.SecureNote; + cipher.secureNote = new SecureNoteView(); + cipher.secureNote.type = SecureNoteType.Generic; + if (!this.isNullOrWhitespace(cipher.notes)) { + cipher.notes = this.getValueOrDefault(value.document_content, ""); + } + for (const property in value) { + if ( + value.hasOwnProperty(property) && // eslint-disable-line + PropertiesToIgnore.indexOf(property.toLowerCase()) < 0 && + !this.isNullOrWhitespace(value[property]) + ) { + this.processKvp(cipher, property, value[property]); + } + } + } + + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/upmCsvImporter.ts b/libs/common/src/importers/upmCsvImporter.ts new file mode 100644 index 0000000000..ea092ffcb7 --- /dev/null +++ b/libs/common/src/importers/upmCsvImporter.ts @@ -0,0 +1,32 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class UpmCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, false); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if (value.length !== 5) { + return; + } + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value[0], "--"); + cipher.notes = this.getValueOrDefault(value[4]); + cipher.login.username = this.getValueOrDefault(value[1]); + cipher.login.password = this.getValueOrDefault(value[2]); + cipher.login.uris = this.makeUriArray(value[3]); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/yotiCsvImporter.ts b/libs/common/src/importers/yotiCsvImporter.ts new file mode 100644 index 0000000000..526f7d6928 --- /dev/null +++ b/libs/common/src/importers/yotiCsvImporter.ts @@ -0,0 +1,28 @@ +import { ImportResult } from "../models/domain/importResult"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class YotiCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + const cipher = this.initLoginCipher(); + cipher.name = this.getValueOrDefault(value.Name, "--"); + cipher.login.username = this.getValueOrDefault(value["User name"]); + cipher.login.password = this.getValueOrDefault(value.Password); + cipher.login.uris = this.makeUriArray(value.URL); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + result.success = true; + return Promise.resolve(result); + } +} diff --git a/libs/common/src/importers/zohoVaultCsvImporter.ts b/libs/common/src/importers/zohoVaultCsvImporter.ts new file mode 100644 index 0000000000..18008e8072 --- /dev/null +++ b/libs/common/src/importers/zohoVaultCsvImporter.ts @@ -0,0 +1,81 @@ +import { ImportResult } from "../models/domain/importResult"; +import { CipherView } from "../models/view/cipherView"; + +import { BaseImporter } from "./baseImporter"; +import { Importer } from "./importer"; + +export class ZohoVaultCsvImporter extends BaseImporter implements Importer { + parse(data: string): Promise { + const result = new ImportResult(); + const results = this.parseCsv(data, true); + if (results == null) { + result.success = false; + return Promise.resolve(result); + } + + results.forEach((value) => { + if ( + this.isNullOrWhitespace(value["Password Name"]) && + this.isNullOrWhitespace(value["Secret Name"]) + ) { + return; + } + this.processFolder(result, this.getValueOrDefault(value.ChamberName)); + const cipher = this.initLoginCipher(); + cipher.favorite = this.getValueOrDefault(value.Favorite, "0") === "1"; + cipher.notes = this.getValueOrDefault(value.Notes); + cipher.name = this.getValueOrDefault( + value["Password Name"], + this.getValueOrDefault(value["Secret Name"], "--") + ); + cipher.login.uris = this.makeUriArray( + this.getValueOrDefault(value["Password URL"], this.getValueOrDefault(value["Secret URL"])) + ); + this.parseData(cipher, value.SecretData); + this.parseData(cipher, value.CustomData); + this.convertToNoteIfNeeded(cipher); + this.cleanupCipher(cipher); + result.ciphers.push(cipher); + }); + + if (this.organization) { + this.moveFoldersToCollections(result); + } + + result.success = true; + return Promise.resolve(result); + } + + private parseData(cipher: CipherView, data: string) { + if (this.isNullOrWhitespace(data)) { + return; + } + const dataLines = this.splitNewLine(data); + dataLines.forEach((line) => { + const delimPosition = line.indexOf(":"); + if (delimPosition < 0) { + return; + } + const field = line.substring(0, delimPosition); + const value = line.length > delimPosition ? line.substring(delimPosition + 1) : null; + if ( + this.isNullOrWhitespace(field) || + this.isNullOrWhitespace(value) || + field === "SecretType" + ) { + return; + } + const fieldLower = field.toLowerCase(); + if (cipher.login.username == null && this.usernameFieldNames.indexOf(fieldLower) > -1) { + cipher.login.username = value; + } else if ( + cipher.login.password == null && + this.passwordFieldNames.indexOf(fieldLower) > -1 + ) { + cipher.login.password = value; + } else { + this.processKvp(cipher, field, value); + } + }); + } +} diff --git a/libs/common/src/misc/captcha_iframe.ts b/libs/common/src/misc/captcha_iframe.ts new file mode 100644 index 0000000000..ca422fc021 --- /dev/null +++ b/libs/common/src/misc/captcha_iframe.ts @@ -0,0 +1,38 @@ +import { I18nService } from "../abstractions/i18n.service"; + +import { IFrameComponent } from "./iframe_component"; + +export class CaptchaIFrame extends IFrameComponent { + constructor( + win: Window, + webVaultUrl: string, + private i18nService: I18nService, + successCallback: (message: string) => any, + errorCallback: (message: string) => any, + infoCallback: (message: string) => any + ) { + super( + win, + webVaultUrl, + "captcha-connector.html", + "hcaptcha_iframe", + successCallback, + errorCallback, + (message: string) => { + const parsedMessage = JSON.parse(message); + if (typeof parsedMessage !== "string") { + this.iframe.height = parsedMessage.height.toString(); + this.iframe.width = parsedMessage.width.toString(); + } else { + infoCallback(parsedMessage); + } + } + ); + } + + init(siteKey: string): void { + super.initComponent( + this.createParams({ siteKey: siteKey, locale: this.i18nService.translationLocale }, 1) + ); + } +} diff --git a/libs/common/src/misc/iframe_component.ts b/libs/common/src/misc/iframe_component.ts new file mode 100644 index 0000000000..2cd702ad36 --- /dev/null +++ b/libs/common/src/misc/iframe_component.ts @@ -0,0 +1,94 @@ +export abstract class IFrameComponent { + iframe: HTMLIFrameElement; + private connectorLink: HTMLAnchorElement; + private parseFunction = this.parseMessage.bind(this); + + constructor( + private win: Window, + protected webVaultUrl: string, + private path: string, + private iframeId: string, + public successCallback?: (message: string) => any, + public errorCallback?: (message: string) => any, + public infoCallback?: (message: string) => any + ) { + this.connectorLink = win.document.createElement("a"); + } + + stop() { + this.sendMessage("stop"); + } + + start() { + this.sendMessage("start"); + } + + sendMessage(message: any) { + if (!this.iframe || !this.iframe.src || !this.iframe.contentWindow) { + return; + } + + this.iframe.contentWindow.postMessage(message, this.iframe.src); + } + + base64Encode(str: string): string { + return btoa( + encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => { + return String.fromCharCode(("0x" + p1) as any); + }) + ); + } + + cleanup() { + this.win.removeEventListener("message", this.parseFunction, false); + } + + protected createParams(data: any, version: number) { + return new URLSearchParams({ + data: this.base64Encode(JSON.stringify(data)), + parent: encodeURIComponent(this.win.document.location.href), + v: version.toString(), + }); + } + + protected initComponent(params: URLSearchParams): void { + this.connectorLink.href = `${this.webVaultUrl}/${this.path}?${params}`; + this.iframe = this.win.document.getElementById(this.iframeId) as HTMLIFrameElement; + this.iframe.src = this.connectorLink.href; + + this.win.addEventListener("message", this.parseFunction, false); + } + + private parseMessage(event: MessageEvent) { + if (!this.validMessage(event)) { + return; + } + + const parts: string[] = event.data.split("|"); + if (parts[0] === "success" && this.successCallback) { + this.successCallback(parts[1]); + } else if (parts[0] === "error" && this.errorCallback) { + this.errorCallback(parts[1]); + } else if (parts[0] === "info" && this.infoCallback) { + this.infoCallback(parts[1]); + } + } + + private validMessage(event: MessageEvent) { + if ( + event.origin == null || + event.origin === "" || + event.origin !== (this.connectorLink as any).origin || + event.data == null || + typeof event.data !== "string" + ) { + return false; + } + + return ( + event.data.indexOf("success|") === 0 || + event.data.indexOf("error|") === 0 || + event.data.indexOf("info|") === 0 + ); + } +} diff --git a/libs/common/src/misc/linkedFieldOption.decorator.ts b/libs/common/src/misc/linkedFieldOption.decorator.ts new file mode 100644 index 0000000000..4383631875 --- /dev/null +++ b/libs/common/src/misc/linkedFieldOption.decorator.ts @@ -0,0 +1,27 @@ +import { LinkedIdType } from "../enums/linkedIdType"; +import { ItemView } from "../models/view/itemView"; + +export class LinkedMetadata { + constructor(readonly propertyKey: string, private readonly _i18nKey?: string) {} + + get i18nKey() { + return this._i18nKey ?? this.propertyKey; + } +} + +/** + * A decorator used to set metadata used by Linked custom fields. Apply it to a class property or getter to make it + * available as a Linked custom field option. + * @param id - A unique value that is saved in the Field model. It is used to look up the decorated class property. + * @param i18nKey - The i18n key used to describe the decorated class property in the UI. If it is null, then the name + * of the class property will be used as the i18n key. + */ +export function linkedFieldOption(id: LinkedIdType, i18nKey?: string) { + return (prototype: ItemView, propertyKey: string) => { + if (prototype.linkedFieldOptions == null) { + prototype.linkedFieldOptions = new Map(); + } + + prototype.linkedFieldOptions.set(id, new LinkedMetadata(propertyKey, i18nKey)); + }; +} diff --git a/libs/common/src/misc/logInStrategies/apiLogin.strategy.ts b/libs/common/src/misc/logInStrategies/apiLogin.strategy.ts new file mode 100644 index 0000000000..89ebc37910 --- /dev/null +++ b/libs/common/src/misc/logInStrategies/apiLogin.strategy.ts @@ -0,0 +1,70 @@ +import { ApiService } from "../../abstractions/api.service"; +import { AppIdService } from "../../abstractions/appId.service"; +import { CryptoService } from "../../abstractions/crypto.service"; +import { EnvironmentService } from "../../abstractions/environment.service"; +import { KeyConnectorService } from "../../abstractions/keyConnector.service"; +import { LogService } from "../../abstractions/log.service"; +import { MessagingService } from "../../abstractions/messaging.service"; +import { PlatformUtilsService } from "../../abstractions/platformUtils.service"; +import { StateService } from "../../abstractions/state.service"; +import { TokenService } from "../../abstractions/token.service"; +import { TwoFactorService } from "../../abstractions/twoFactor.service"; +import { ApiLogInCredentials } from "../../models/domain/logInCredentials"; +import { ApiTokenRequest } from "../../models/request/identityToken/apiTokenRequest"; +import { IdentityTokenResponse } from "../../models/response/identityTokenResponse"; + +import { LogInStrategy } from "./logIn.strategy"; + +export class ApiLogInStrategy extends LogInStrategy { + tokenRequest: ApiTokenRequest; + + constructor( + cryptoService: CryptoService, + apiService: ApiService, + tokenService: TokenService, + appIdService: AppIdService, + platformUtilsService: PlatformUtilsService, + messagingService: MessagingService, + logService: LogService, + stateService: StateService, + twoFactorService: TwoFactorService, + private environmentService: EnvironmentService, + private keyConnectorService: KeyConnectorService + ) { + super( + cryptoService, + apiService, + tokenService, + appIdService, + platformUtilsService, + messagingService, + logService, + stateService, + twoFactorService + ); + } + + async onSuccessfulLogin(tokenResponse: IdentityTokenResponse) { + if (tokenResponse.apiUseKeyConnector) { + const keyConnectorUrl = this.environmentService.getKeyConnectorUrl(); + await this.keyConnectorService.getAndSetKey(keyConnectorUrl); + } + } + + async logIn(credentials: ApiLogInCredentials) { + this.tokenRequest = new ApiTokenRequest( + credentials.clientId, + credentials.clientSecret, + await this.buildTwoFactor(), + await this.buildDeviceRequest() + ); + + return this.startLogIn(); + } + + protected async saveAccountInformation(tokenResponse: IdentityTokenResponse) { + await super.saveAccountInformation(tokenResponse); + await this.stateService.setApiKeyClientId(this.tokenRequest.clientId); + await this.stateService.setApiKeyClientSecret(this.tokenRequest.clientSecret); + } +} diff --git a/libs/common/src/misc/logInStrategies/logIn.strategy.ts b/libs/common/src/misc/logInStrategies/logIn.strategy.ts new file mode 100644 index 0000000000..a58a7bc898 --- /dev/null +++ b/libs/common/src/misc/logInStrategies/logIn.strategy.ts @@ -0,0 +1,170 @@ +import { ApiService } from "../../abstractions/api.service"; +import { AppIdService } from "../../abstractions/appId.service"; +import { CryptoService } from "../../abstractions/crypto.service"; +import { LogService } from "../../abstractions/log.service"; +import { MessagingService } from "../../abstractions/messaging.service"; +import { PlatformUtilsService } from "../../abstractions/platformUtils.service"; +import { StateService } from "../../abstractions/state.service"; +import { TokenService } from "../../abstractions/token.service"; +import { TwoFactorService } from "../../abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "../../enums/twoFactorProviderType"; +import { Account, AccountProfile, AccountTokens } from "../../models/domain/account"; +import { AuthResult } from "../../models/domain/authResult"; +import { + ApiLogInCredentials, + PasswordLogInCredentials, + SsoLogInCredentials, +} from "../../models/domain/logInCredentials"; +import { DeviceRequest } from "../../models/request/deviceRequest"; +import { ApiTokenRequest } from "../../models/request/identityToken/apiTokenRequest"; +import { PasswordTokenRequest } from "../../models/request/identityToken/passwordTokenRequest"; +import { SsoTokenRequest } from "../../models/request/identityToken/ssoTokenRequest"; +import { TokenRequestTwoFactor } from "../../models/request/identityToken/tokenRequestTwoFactor"; +import { KeysRequest } from "../../models/request/keysRequest"; +import { IdentityCaptchaResponse } from "../../models/response/identityCaptchaResponse"; +import { IdentityTokenResponse } from "../../models/response/identityTokenResponse"; +import { IdentityTwoFactorResponse } from "../../models/response/identityTwoFactorResponse"; + +export abstract class LogInStrategy { + protected abstract tokenRequest: ApiTokenRequest | PasswordTokenRequest | SsoTokenRequest; + protected captchaBypassToken: string = null; + + constructor( + protected cryptoService: CryptoService, + protected apiService: ApiService, + protected tokenService: TokenService, + protected appIdService: AppIdService, + protected platformUtilsService: PlatformUtilsService, + protected messagingService: MessagingService, + protected logService: LogService, + protected stateService: StateService, + protected twoFactorService: TwoFactorService + ) {} + + abstract logIn( + credentials: ApiLogInCredentials | PasswordLogInCredentials | SsoLogInCredentials + ): Promise; + + async logInTwoFactor( + twoFactor: TokenRequestTwoFactor, + captchaResponse: string = null + ): Promise { + this.tokenRequest.setTwoFactor(twoFactor); + return this.startLogIn(); + } + + protected async startLogIn(): Promise { + this.twoFactorService.clearSelectedProvider(); + + const response = await this.apiService.postIdentityToken(this.tokenRequest); + + if (response instanceof IdentityTwoFactorResponse) { + return this.processTwoFactorResponse(response); + } else if (response instanceof IdentityCaptchaResponse) { + return this.processCaptchaResponse(response); + } else if (response instanceof IdentityTokenResponse) { + return this.processTokenResponse(response); + } + + throw new Error("Invalid response object."); + } + + protected onSuccessfulLogin(response: IdentityTokenResponse): Promise { + // Implemented in subclass if required + return null; + } + + protected async buildDeviceRequest() { + const appId = await this.appIdService.getAppId(); + return new DeviceRequest(appId, this.platformUtilsService); + } + + protected async buildTwoFactor(userProvidedTwoFactor?: TokenRequestTwoFactor) { + if (userProvidedTwoFactor != null) { + return userProvidedTwoFactor; + } + + const storedTwoFactorToken = await this.tokenService.getTwoFactorToken(); + if (storedTwoFactorToken != null) { + return new TokenRequestTwoFactor(TwoFactorProviderType.Remember, storedTwoFactorToken, false); + } + + return new TokenRequestTwoFactor(); + } + + protected async saveAccountInformation(tokenResponse: IdentityTokenResponse) { + const accountInformation = await this.tokenService.decodeToken(tokenResponse.accessToken); + await this.stateService.addAccount( + new Account({ + profile: { + ...new AccountProfile(), + ...{ + userId: accountInformation.sub, + email: accountInformation.email, + hasPremiumPersonally: accountInformation.premium, + kdfIterations: tokenResponse.kdfIterations, + kdfType: tokenResponse.kdf, + }, + }, + tokens: { + ...new AccountTokens(), + ...{ + accessToken: tokenResponse.accessToken, + refreshToken: tokenResponse.refreshToken, + }, + }, + }) + ); + } + + protected async processTokenResponse(response: IdentityTokenResponse): Promise { + const result = new AuthResult(); + result.resetMasterPassword = response.resetMasterPassword; + result.forcePasswordReset = response.forcePasswordReset; + + await this.saveAccountInformation(response); + + if (response.twoFactorToken != null) { + await this.tokenService.setTwoFactorToken(response); + } + + const newSsoUser = response.key == null; + if (!newSsoUser) { + await this.cryptoService.setEncKey(response.key); + await this.cryptoService.setEncPrivateKey( + response.privateKey ?? (await this.createKeyPairForOldAccount()) + ); + } + + await this.onSuccessfulLogin(response); + + await this.stateService.setBiometricLocked(false); + this.messagingService.send("loggedIn"); + + return result; + } + + private async processTwoFactorResponse(response: IdentityTwoFactorResponse): Promise { + const result = new AuthResult(); + result.twoFactorProviders = response.twoFactorProviders2; + this.twoFactorService.setProviders(response); + this.captchaBypassToken = response.captchaToken ?? null; + return result; + } + + private async processCaptchaResponse(response: IdentityCaptchaResponse): Promise { + const result = new AuthResult(); + result.captchaSiteKey = response.siteKey; + return result; + } + + private async createKeyPairForOldAccount() { + try { + const [publicKey, privateKey] = await this.cryptoService.makeKeyPair(); + await this.apiService.postAccountKeys(new KeysRequest(publicKey, privateKey.encryptedString)); + return privateKey.encryptedString; + } catch (e) { + this.logService.error(e); + } + } +} diff --git a/libs/common/src/misc/logInStrategies/passwordLogin.strategy.ts b/libs/common/src/misc/logInStrategies/passwordLogin.strategy.ts new file mode 100644 index 0000000000..81947e562d --- /dev/null +++ b/libs/common/src/misc/logInStrategies/passwordLogin.strategy.ts @@ -0,0 +1,95 @@ +import { ApiService } from "../../abstractions/api.service"; +import { AppIdService } from "../../abstractions/appId.service"; +import { AuthService } from "../../abstractions/auth.service"; +import { CryptoService } from "../../abstractions/crypto.service"; +import { LogService } from "../../abstractions/log.service"; +import { MessagingService } from "../../abstractions/messaging.service"; +import { PlatformUtilsService } from "../../abstractions/platformUtils.service"; +import { StateService } from "../../abstractions/state.service"; +import { TokenService } from "../../abstractions/token.service"; +import { TwoFactorService } from "../../abstractions/twoFactor.service"; +import { HashPurpose } from "../../enums/hashPurpose"; +import { AuthResult } from "../../models/domain/authResult"; +import { PasswordLogInCredentials } from "../../models/domain/logInCredentials"; +import { SymmetricCryptoKey } from "../../models/domain/symmetricCryptoKey"; +import { PasswordTokenRequest } from "../../models/request/identityToken/passwordTokenRequest"; +import { TokenRequestTwoFactor } from "../../models/request/identityToken/tokenRequestTwoFactor"; + +import { LogInStrategy } from "./logIn.strategy"; + +export class PasswordLogInStrategy extends LogInStrategy { + get email() { + return this.tokenRequest.email; + } + + get masterPasswordHash() { + return this.tokenRequest.masterPasswordHash; + } + + tokenRequest: PasswordTokenRequest; + + private localHashedPassword: string; + private key: SymmetricCryptoKey; + + constructor( + cryptoService: CryptoService, + apiService: ApiService, + tokenService: TokenService, + appIdService: AppIdService, + platformUtilsService: PlatformUtilsService, + messagingService: MessagingService, + logService: LogService, + stateService: StateService, + twoFactorService: TwoFactorService, + private authService: AuthService + ) { + super( + cryptoService, + apiService, + tokenService, + appIdService, + platformUtilsService, + messagingService, + logService, + stateService, + twoFactorService + ); + } + + async onSuccessfulLogin() { + await this.cryptoService.setKey(this.key); + await this.cryptoService.setKeyHash(this.localHashedPassword); + } + + async logInTwoFactor( + twoFactor: TokenRequestTwoFactor, + captchaResponse: string + ): Promise { + this.tokenRequest.captchaResponse = captchaResponse ?? this.captchaBypassToken; + return super.logInTwoFactor(twoFactor); + } + + async logIn(credentials: PasswordLogInCredentials) { + const { email, masterPassword, captchaToken, twoFactor } = credentials; + + this.key = await this.authService.makePreloginKey(masterPassword, email); + + // Hash the password early (before authentication) so we don't persist it in memory in plaintext + this.localHashedPassword = await this.cryptoService.hashPassword( + masterPassword, + this.key, + HashPurpose.LocalAuthorization + ); + const hashedPassword = await this.cryptoService.hashPassword(masterPassword, this.key); + + this.tokenRequest = new PasswordTokenRequest( + email, + hashedPassword, + captchaToken, + await this.buildTwoFactor(twoFactor), + await this.buildDeviceRequest() + ); + + return this.startLogIn(); + } +} diff --git a/libs/common/src/misc/logInStrategies/ssoLogin.strategy.ts b/libs/common/src/misc/logInStrategies/ssoLogin.strategy.ts new file mode 100644 index 0000000000..e56bd7a3d1 --- /dev/null +++ b/libs/common/src/misc/logInStrategies/ssoLogin.strategy.ts @@ -0,0 +1,70 @@ +import { ApiService } from "../../abstractions/api.service"; +import { AppIdService } from "../../abstractions/appId.service"; +import { CryptoService } from "../../abstractions/crypto.service"; +import { KeyConnectorService } from "../../abstractions/keyConnector.service"; +import { LogService } from "../../abstractions/log.service"; +import { MessagingService } from "../../abstractions/messaging.service"; +import { PlatformUtilsService } from "../../abstractions/platformUtils.service"; +import { StateService } from "../../abstractions/state.service"; +import { TokenService } from "../../abstractions/token.service"; +import { TwoFactorService } from "../../abstractions/twoFactor.service"; +import { SsoLogInCredentials } from "../../models/domain/logInCredentials"; +import { SsoTokenRequest } from "../../models/request/identityToken/ssoTokenRequest"; +import { IdentityTokenResponse } from "../../models/response/identityTokenResponse"; + +import { LogInStrategy } from "./logIn.strategy"; + +export class SsoLogInStrategy extends LogInStrategy { + tokenRequest: SsoTokenRequest; + orgId: string; + + constructor( + cryptoService: CryptoService, + apiService: ApiService, + tokenService: TokenService, + appIdService: AppIdService, + platformUtilsService: PlatformUtilsService, + messagingService: MessagingService, + logService: LogService, + stateService: StateService, + twoFactorService: TwoFactorService, + private keyConnectorService: KeyConnectorService + ) { + super( + cryptoService, + apiService, + tokenService, + appIdService, + platformUtilsService, + messagingService, + logService, + stateService, + twoFactorService + ); + } + + async onSuccessfulLogin(tokenResponse: IdentityTokenResponse) { + const newSsoUser = tokenResponse.key == null; + + if (tokenResponse.keyConnectorUrl != null) { + if (!newSsoUser) { + await this.keyConnectorService.getAndSetKey(tokenResponse.keyConnectorUrl); + } else { + await this.keyConnectorService.convertNewSsoUserToKeyConnector(tokenResponse, this.orgId); + } + } + } + + async logIn(credentials: SsoLogInCredentials) { + this.orgId = credentials.orgId; + this.tokenRequest = new SsoTokenRequest( + credentials.code, + credentials.codeVerifier, + credentials.redirectUrl, + await this.buildTwoFactor(credentials.twoFactor), + await this.buildDeviceRequest() + ); + + return this.startLogIn(); + } +} diff --git a/libs/common/src/misc/nodeUtils.ts b/libs/common/src/misc/nodeUtils.ts new file mode 100644 index 0000000000..5b5ba27bed --- /dev/null +++ b/libs/common/src/misc/nodeUtils.ts @@ -0,0 +1,34 @@ +import * as fs from "fs"; +import * as path from "path"; +import * as readline from "readline"; + +export class NodeUtils { + static mkdirpSync(targetDir: string, mode = "700", relative = false, relativeDir: string = null) { + const initialDir = path.isAbsolute(targetDir) ? path.sep : ""; + const baseDir = relative ? (relativeDir != null ? relativeDir : __dirname) : "."; + targetDir.split(path.sep).reduce((parentDir, childDir) => { + const dir = path.resolve(baseDir, parentDir, childDir); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, mode); + } + return dir; + }, initialDir); + } + static readFirstLine(fileName: string) { + return new Promise((resolve, reject) => { + const readStream = fs.createReadStream(fileName, { encoding: "utf8" }); + const readInterface = readline.createInterface(readStream); + readInterface + .on("line", (line) => { + readStream.close(); + resolve(line); + }) + .on("error", (err) => reject(err)); + }); + } + + // https://stackoverflow.com/a/31394257 + static bufferToArrayBuffer(buf: Buffer): ArrayBuffer { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + } +} diff --git a/libs/common/src/misc/sequentialize.ts b/libs/common/src/misc/sequentialize.ts new file mode 100644 index 0000000000..c242114764 --- /dev/null +++ b/libs/common/src/misc/sequentialize.ts @@ -0,0 +1,57 @@ +/** + * Use as a Decorator on async functions, it will prevent multiple 'active' calls as the same time + * + * If a promise was returned from a previous call to this function, that hasn't yet resolved it will + * be returned, instead of calling the original function again + * + * Results are not cached, once the promise has returned, the next call will result in a fresh call + * + * Read more at https://github.com/bitwarden/jslib/pull/7 + */ +export function sequentialize(cacheKey: (args: any[]) => string) { + return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => { + const originalMethod: () => Promise = descriptor.value; + const caches = new Map>>(); + + const getCache = (obj: any) => { + let cache = caches.get(obj); + if (cache != null) { + return cache; + } + cache = new Map>(); + caches.set(obj, cache); + return cache; + }; + + return { + value: function (...args: any[]) { + const cache = getCache(this); + const argsCacheKey = cacheKey(args); + let response = cache.get(argsCacheKey); + if (response != null) { + return response; + } + + const onFinally = () => { + cache.delete(argsCacheKey); + if (cache.size === 0) { + caches.delete(this); + } + }; + response = originalMethod + .apply(this, args) + .then((val: any) => { + onFinally(); + return val; + }) + .catch((err: any) => { + onFinally(); + throw err; + }); + + cache.set(argsCacheKey, response); + return response; + }, + }; + }; +} diff --git a/libs/common/src/misc/serviceUtils.ts b/libs/common/src/misc/serviceUtils.ts new file mode 100644 index 0000000000..b6c0509237 --- /dev/null +++ b/libs/common/src/misc/serviceUtils.ts @@ -0,0 +1,72 @@ +import { ITreeNodeObject, TreeNode } from "../models/domain/treeNode"; + +export class ServiceUtils { + static nestedTraverse( + nodeTree: TreeNode[], + partIndex: number, + parts: string[], + obj: ITreeNodeObject, + parent: ITreeNodeObject, + delimiter: string + ) { + if (parts.length <= partIndex) { + return; + } + + const end = partIndex === parts.length - 1; + const partName = parts[partIndex]; + + for (let i = 0; i < nodeTree.length; i++) { + if (nodeTree[i].node.name !== parts[partIndex]) { + continue; + } + if (end && nodeTree[i].node.id !== obj.id) { + // Another node with the same name. + nodeTree.push(new TreeNode(obj, partName, parent)); + return; + } + ServiceUtils.nestedTraverse( + nodeTree[i].children, + partIndex + 1, + parts, + obj, + nodeTree[i].node, + delimiter + ); + return; + } + + if (nodeTree.filter((n) => n.node.name === partName).length === 0) { + if (end) { + nodeTree.push(new TreeNode(obj, partName, parent)); + return; + } + const newPartName = parts[partIndex] + delimiter + parts[partIndex + 1]; + ServiceUtils.nestedTraverse( + nodeTree, + 0, + [newPartName, ...parts.slice(partIndex + 2)], + obj, + parent, + delimiter + ); + } + } + + static getTreeNodeObject( + nodeTree: TreeNode[], + id: string + ): TreeNode { + for (let i = 0; i < nodeTree.length; i++) { + if (nodeTree[i].node.id === id) { + return nodeTree[i]; + } else if (nodeTree[i].children != null) { + const node = ServiceUtils.getTreeNodeObject(nodeTree[i].children, id); + if (node !== null) { + return node; + } + } + } + return null; + } +} diff --git a/libs/common/src/misc/throttle.ts b/libs/common/src/misc/throttle.ts new file mode 100644 index 0000000000..852ee9998f --- /dev/null +++ b/libs/common/src/misc/throttle.ts @@ -0,0 +1,69 @@ +/** + * Use as a Decorator on async functions, it will limit how many times the function can be + * in-flight at a time. + * + * Calls beyond the limit will be queued, and run when one of the active calls finishes + */ +export function throttle(limit: number, throttleKey: (args: any[]) => string) { + return ( + target: any, + propertyKey: string | symbol, + descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise> + ) => { + const originalMethod: () => Promise = descriptor.value; + const allThrottles = new Map void)[]>>(); + + const getThrottles = (obj: any) => { + let throttles = allThrottles.get(obj); + if (throttles != null) { + return throttles; + } + throttles = new Map void)[]>(); + allThrottles.set(obj, throttles); + return throttles; + }; + + return { + value: function (...args: any[]) { + const throttles = getThrottles(this); + const argsThrottleKey = throttleKey(args); + let queue = throttles.get(argsThrottleKey); + if (queue == null) { + queue = []; + throttles.set(argsThrottleKey, queue); + } + + return new Promise((resolve, reject) => { + const exec = () => { + const onFinally = () => { + queue.splice(queue.indexOf(exec), 1); + if (queue.length >= limit) { + queue[limit - 1](); + } else if (queue.length === 0) { + throttles.delete(argsThrottleKey); + if (throttles.size === 0) { + allThrottles.delete(this); + } + } + }; + originalMethod + .apply(this, args) + .then((val: any) => { + onFinally(); + return val; + }) + .catch((err: any) => { + onFinally(); + throw err; + }) + .then(resolve, reject); + }; + queue.push(exec); + if (queue.length <= limit) { + exec(); + } + }); + }, + }; + }; +} diff --git a/libs/common/src/misc/tldjs.noop.ts b/libs/common/src/misc/tldjs.noop.ts new file mode 100644 index 0000000000..b6273a617c --- /dev/null +++ b/libs/common/src/misc/tldjs.noop.ts @@ -0,0 +1,7 @@ +export function getDomain(host: string): string | null { + return null; +} + +export function isValid(host: string): boolean { + return true; +} diff --git a/libs/common/src/misc/utils.ts b/libs/common/src/misc/utils.ts new file mode 100644 index 0000000000..1d96e08287 --- /dev/null +++ b/libs/common/src/misc/utils.ts @@ -0,0 +1,406 @@ +/* eslint-disable no-useless-escape */ +import * as tldjs from "tldjs"; + +import { I18nService } from "../abstractions/i18n.service"; + +const nodeURL = typeof window === "undefined" ? require("url") : null; + +export class Utils { + static inited = false; + static isNode = false; + static isBrowser = true; + static isMobileBrowser = false; + static isAppleMobileBrowser = false; + static global: any = null; + static tldEndingRegex = + /.*\.(com|net|org|edu|uk|gov|ca|de|jp|fr|au|ru|ch|io|es|us|co|xyz|info|ly|mil)$/; + // Transpiled version of /\p{Emoji_Presentation}/gu using https://mothereff.in/regexpu. Used for compatability in older browsers. + static regexpEmojiPresentation = + /(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])/g; + + static init() { + if (Utils.inited) { + return; + } + + Utils.inited = true; + Utils.isNode = + typeof process !== "undefined" && + (process as any).release != null && + (process as any).release.name === "node"; + Utils.isBrowser = typeof window !== "undefined"; + Utils.isMobileBrowser = Utils.isBrowser && this.isMobile(window); + Utils.isAppleMobileBrowser = Utils.isBrowser && this.isAppleMobile(window); + Utils.global = Utils.isNode && !Utils.isBrowser ? global : window; + } + + static fromB64ToArray(str: string): Uint8Array { + if (Utils.isNode) { + return new Uint8Array(Buffer.from(str, "base64")); + } else { + const binaryString = window.atob(str); + const bytes = new Uint8Array(binaryString.length); + for (let i = 0; i < binaryString.length; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + return bytes; + } + } + + static fromUrlB64ToArray(str: string): Uint8Array { + return Utils.fromB64ToArray(Utils.fromUrlB64ToB64(str)); + } + + static fromHexToArray(str: string): Uint8Array { + if (Utils.isNode) { + return new Uint8Array(Buffer.from(str, "hex")); + } else { + const bytes = new Uint8Array(str.length / 2); + for (let i = 0; i < str.length; i += 2) { + bytes[i / 2] = parseInt(str.substr(i, 2), 16); + } + return bytes; + } + } + + static fromUtf8ToArray(str: string): Uint8Array { + if (Utils.isNode) { + return new Uint8Array(Buffer.from(str, "utf8")); + } else { + const strUtf8 = unescape(encodeURIComponent(str)); + const arr = new Uint8Array(strUtf8.length); + for (let i = 0; i < strUtf8.length; i++) { + arr[i] = strUtf8.charCodeAt(i); + } + return arr; + } + } + + static fromByteStringToArray(str: string): Uint8Array { + const arr = new Uint8Array(str.length); + for (let i = 0; i < str.length; i++) { + arr[i] = str.charCodeAt(i); + } + return arr; + } + + static fromBufferToB64(buffer: ArrayBuffer): string { + if (Utils.isNode) { + return Buffer.from(buffer).toString("base64"); + } else { + let binary = ""; + const bytes = new Uint8Array(buffer); + for (let i = 0; i < bytes.byteLength; i++) { + binary += String.fromCharCode(bytes[i]); + } + return window.btoa(binary); + } + } + + static fromBufferToUrlB64(buffer: ArrayBuffer): string { + return Utils.fromB64toUrlB64(Utils.fromBufferToB64(buffer)); + } + + static fromB64toUrlB64(b64Str: string) { + return b64Str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, ""); + } + + static fromBufferToUtf8(buffer: ArrayBuffer): string { + if (Utils.isNode) { + return Buffer.from(buffer).toString("utf8"); + } else { + const bytes = new Uint8Array(buffer); + const encodedString = String.fromCharCode.apply(null, bytes); + return decodeURIComponent(escape(encodedString)); + } + } + + static fromBufferToByteString(buffer: ArrayBuffer): string { + return String.fromCharCode.apply(null, new Uint8Array(buffer)); + } + + // ref: https://stackoverflow.com/a/40031979/1090359 + static fromBufferToHex(buffer: ArrayBuffer): string { + if (Utils.isNode) { + return Buffer.from(buffer).toString("hex"); + } else { + const bytes = new Uint8Array(buffer); + return Array.prototype.map + .call(bytes, (x: number) => ("00" + x.toString(16)).slice(-2)) + .join(""); + } + } + + static fromUrlB64ToB64(urlB64Str: string): string { + let output = urlB64Str.replace(/-/g, "+").replace(/_/g, "/"); + switch (output.length % 4) { + case 0: + break; + case 2: + output += "=="; + break; + case 3: + output += "="; + break; + default: + throw new Error("Illegal base64url string!"); + } + + return output; + } + + static fromUrlB64ToUtf8(urlB64Str: string): string { + return Utils.fromB64ToUtf8(Utils.fromUrlB64ToB64(urlB64Str)); + } + + static fromUtf8ToB64(utfStr: string): string { + if (Utils.isNode) { + return Buffer.from(utfStr, "utf8").toString("base64"); + } else { + return decodeURIComponent(escape(window.btoa(utfStr))); + } + } + + static fromUtf8ToUrlB64(utfStr: string): string { + return Utils.fromBufferToUrlB64(Utils.fromUtf8ToArray(utfStr)); + } + + static fromB64ToUtf8(b64Str: string): string { + if (Utils.isNode) { + return Buffer.from(b64Str, "base64").toString("utf8"); + } else { + return decodeURIComponent(escape(window.atob(b64Str))); + } + } + + // ref: http://stackoverflow.com/a/2117523/1090359 + static newGuid(): string { + return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c === "x" ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + } + + static isGuid(id: string) { + return RegExp( + /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, + "i" + ).test(id); + } + + static getHostname(uriString: string): string { + const url = Utils.getUrl(uriString); + try { + return url != null && url.hostname !== "" ? url.hostname : null; + } catch { + return null; + } + } + + static getHost(uriString: string): string { + const url = Utils.getUrl(uriString); + try { + return url != null && url.host !== "" ? url.host : null; + } catch { + return null; + } + } + + static getDomain(uriString: string): string { + if (uriString == null) { + return null; + } + + uriString = uriString.trim(); + if (uriString === "") { + return null; + } + + if (uriString.startsWith("data:")) { + return null; + } + + let httpUrl = uriString.startsWith("http://") || uriString.startsWith("https://"); + if ( + !httpUrl && + uriString.indexOf("://") < 0 && + Utils.tldEndingRegex.test(uriString) && + uriString.indexOf("@") < 0 + ) { + uriString = "http://" + uriString; + httpUrl = true; + } + + if (httpUrl) { + try { + const url = Utils.getUrlObject(uriString); + const validHostname = tldjs?.isValid != null ? tldjs.isValid(url.hostname) : true; + if (!validHostname) { + return null; + } + + if (url.hostname === "localhost" || Utils.validIpAddress(url.hostname)) { + return url.hostname; + } + + const urlDomain = + tldjs != null && tldjs.getDomain != null ? tldjs.getDomain(url.hostname) : null; + return urlDomain != null ? urlDomain : url.hostname; + } catch (e) { + // Invalid domain, try another approach below. + } + } + + try { + const domain = tldjs != null && tldjs.getDomain != null ? tldjs.getDomain(uriString) : null; + + if (domain != null) { + return domain; + } + } catch { + return null; + } + + return null; + } + + static getQueryParams(uriString: string): Map { + const url = Utils.getUrl(uriString); + if (url == null || url.search == null || url.search === "") { + return null; + } + const map = new Map(); + const pairs = (url.search[0] === "?" ? url.search.substr(1) : url.search).split("&"); + pairs.forEach((pair) => { + const parts = pair.split("="); + if (parts.length < 1) { + return; + } + map.set( + decodeURIComponent(parts[0]).toLowerCase(), + parts[1] == null ? "" : decodeURIComponent(parts[1]) + ); + }); + return map; + } + + static getSortFunction(i18nService: I18nService, prop: string) { + return (a: any, b: any) => { + if (a[prop] == null && b[prop] != null) { + return -1; + } + if (a[prop] != null && b[prop] == null) { + return 1; + } + if (a[prop] == null && b[prop] == null) { + return 0; + } + + return i18nService.collator + ? i18nService.collator.compare(a[prop], b[prop]) + : a[prop].localeCompare(b[prop]); + }; + } + + static isNullOrWhitespace(str: string): boolean { + return str == null || typeof str !== "string" || str.trim() === ""; + } + + static isNullOrEmpty(str: string): boolean { + return str == null || typeof str !== "string" || str == ""; + } + + static nameOf(name: string & keyof T) { + return name; + } + + static assign(target: T, source: Partial): T { + return Object.assign(target, source); + } + + static iterateEnum(obj: O) { + return (Object.keys(obj).filter((k) => Number.isNaN(+k)) as K[]).map((k) => obj[k]); + } + + static getUrl(uriString: string): URL { + if (uriString == null) { + return null; + } + + uriString = uriString.trim(); + if (uriString === "") { + return null; + } + + let url = Utils.getUrlObject(uriString); + if (url == null) { + const hasHttpProtocol = + uriString.indexOf("http://") === 0 || uriString.indexOf("https://") === 0; + if (!hasHttpProtocol && uriString.indexOf(".") > -1) { + url = Utils.getUrlObject("http://" + uriString); + } + } + return url; + } + + static camelToPascalCase(s: string) { + return s.charAt(0).toUpperCase() + s.slice(1); + } + + private static validIpAddress(ipString: string): boolean { + const ipRegex = + /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; + return ipRegex.test(ipString); + } + + private static isMobile(win: Window) { + let mobile = false; + ((a) => { + if ( + /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test( + a + ) || + /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test( + a.substr(0, 4) + ) + ) { + mobile = true; + } + })(win.navigator.userAgent || win.navigator.vendor || (win as any).opera); + return mobile || win.navigator.userAgent.match(/iPad/i) != null; + } + + private static isAppleMobile(win: Window) { + return ( + win.navigator.userAgent.match(/iPhone/i) != null || + win.navigator.userAgent.match(/iPad/i) != null + ); + } + + private static getUrlObject(uriString: string): URL { + try { + if (nodeURL != null) { + return new nodeURL.URL(uriString); + } else if (typeof URL === "function") { + return new URL(uriString); + } else if (window != null) { + const hasProtocol = uriString.indexOf("://") > -1; + if (!hasProtocol && uriString.indexOf(".") > -1) { + uriString = "http://" + uriString; + } else if (!hasProtocol) { + return null; + } + const anchor = window.document.createElement("a"); + anchor.href = uriString; + return anchor as any; + } + } catch (e) { + // Ignore error + } + + return null; + } +} + +Utils.init(); diff --git a/libs/common/src/misc/webauthn_iframe.ts b/libs/common/src/misc/webauthn_iframe.ts new file mode 100644 index 0000000000..969dde0460 --- /dev/null +++ b/libs/common/src/misc/webauthn_iframe.ts @@ -0,0 +1,106 @@ +import { I18nService } from "../abstractions/i18n.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; + +export class WebAuthnIFrame { + private iframe: HTMLIFrameElement = null; + private connectorLink: HTMLAnchorElement; + private parseFunction = this.parseMessage.bind(this); + + constructor( + private win: Window, + private webVaultUrl: string, + private webAuthnNewTab: boolean, + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService, + private successCallback: Function, // eslint-disable-line + private errorCallback: Function, // eslint-disable-line + private infoCallback: Function // eslint-disable-line + ) { + this.connectorLink = win.document.createElement("a"); + } + + init(data: any): void { + const params = new URLSearchParams({ + data: this.base64Encode(JSON.stringify(data)), + parent: encodeURIComponent(this.win.document.location.href), + btnText: encodeURIComponent(this.i18nService.t("webAuthnAuthenticate")), + v: "1", + }); + + if (this.webAuthnNewTab) { + // Firefox fallback which opens the webauthn page in a new tab + params.append("locale", this.i18nService.translationLocale); + this.platformUtilsService.launchUri( + `${this.webVaultUrl}/webauthn-fallback-connector.html?${params}` + ); + } else { + this.connectorLink.href = `${this.webVaultUrl}/webauthn-connector.html?${params}`; + this.iframe = this.win.document.getElementById("webauthn_iframe") as HTMLIFrameElement; + this.iframe.allow = "publickey-credentials-get " + new URL(this.webVaultUrl).origin; + this.iframe.src = this.connectorLink.href; + + this.win.addEventListener("message", this.parseFunction, false); + } + } + + stop() { + this.sendMessage("stop"); + } + + start() { + this.sendMessage("start"); + } + + sendMessage(message: any) { + if (!this.iframe || !this.iframe.src || !this.iframe.contentWindow) { + return; + } + + this.iframe.contentWindow.postMessage(message, this.iframe.src); + } + + base64Encode(str: string): string { + return btoa( + encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => { + return String.fromCharCode(("0x" + p1) as any); + }) + ); + } + + cleanup() { + this.win.removeEventListener("message", this.parseFunction, false); + } + + private parseMessage(event: MessageEvent) { + if (!this.validMessage(event)) { + return; + } + + const parts: string[] = event.data.split("|"); + if (parts[0] === "success" && this.successCallback) { + this.successCallback(parts[1]); + } else if (parts[0] === "error" && this.errorCallback) { + this.errorCallback(parts[1]); + } else if (parts[0] === "info" && this.infoCallback) { + this.infoCallback(parts[1]); + } + } + + private validMessage(event: MessageEvent) { + if ( + event.origin == null || + event.origin === "" || + event.origin !== (this.connectorLink as any).origin || + event.data == null || + typeof event.data !== "string" + ) { + return false; + } + + return ( + event.data.indexOf("success|") === 0 || + event.data.indexOf("error|") === 0 || + event.data.indexOf("info|") === 0 + ); + } +} diff --git a/libs/common/src/misc/wordlist.ts b/libs/common/src/misc/wordlist.ts new file mode 100644 index 0000000000..cdd30110ec --- /dev/null +++ b/libs/common/src/misc/wordlist.ts @@ -0,0 +1,7779 @@ +// EFF's Long Wordlist from https://www.eff.org/dice +export const EEFLongWordList = [ + "abacus", + "abdomen", + "abdominal", + "abide", + "abiding", + "ability", + "ablaze", + "able", + "abnormal", + "abrasion", + "abrasive", + "abreast", + "abridge", + "abroad", + "abruptly", + "absence", + "absentee", + "absently", + "absinthe", + "absolute", + "absolve", + "abstain", + "abstract", + "absurd", + "accent", + "acclaim", + "acclimate", + "accompany", + "account", + "accuracy", + "accurate", + "accustom", + "acetone", + "achiness", + "aching", + "acid", + "acorn", + "acquaint", + "acquire", + "acre", + "acrobat", + "acronym", + "acting", + "action", + "activate", + "activator", + "active", + "activism", + "activist", + "activity", + "actress", + "acts", + "acutely", + "acuteness", + "aeration", + "aerobics", + "aerosol", + "aerospace", + "afar", + "affair", + "affected", + "affecting", + "affection", + "affidavit", + "affiliate", + "affirm", + "affix", + "afflicted", + "affluent", + "afford", + "affront", + "aflame", + "afloat", + "aflutter", + "afoot", + "afraid", + "afterglow", + "afterlife", + "aftermath", + "aftermost", + "afternoon", + "aged", + "ageless", + "agency", + "agenda", + "agent", + "aggregate", + "aghast", + "agile", + "agility", + "aging", + "agnostic", + "agonize", + "agonizing", + "agony", + "agreeable", + "agreeably", + "agreed", + "agreeing", + "agreement", + "aground", + "ahead", + "ahoy", + "aide", + "aids", + "aim", + "ajar", + "alabaster", + "alarm", + "albatross", + "album", + "alfalfa", + "algebra", + "algorithm", + "alias", + "alibi", + "alienable", + "alienate", + "aliens", + "alike", + "alive", + "alkaline", + "alkalize", + "almanac", + "almighty", + "almost", + "aloe", + "aloft", + "aloha", + "alone", + "alongside", + "aloof", + "alphabet", + "alright", + "although", + "altitude", + "alto", + "aluminum", + "alumni", + "always", + "amaretto", + "amaze", + "amazingly", + "amber", + "ambiance", + "ambiguity", + "ambiguous", + "ambition", + "ambitious", + "ambulance", + "ambush", + "amendable", + "amendment", + "amends", + "amenity", + "amiable", + "amicably", + "amid", + "amigo", + "amino", + "amiss", + "ammonia", + "ammonium", + "amnesty", + "amniotic", + "among", + "amount", + "amperage", + "ample", + "amplifier", + "amplify", + "amply", + "amuck", + "amulet", + "amusable", + "amused", + "amusement", + "amuser", + "amusing", + "anaconda", + "anaerobic", + "anagram", + "anatomist", + "anatomy", + "anchor", + "anchovy", + "ancient", + "android", + "anemia", + "anemic", + "aneurism", + "anew", + "angelfish", + "angelic", + "anger", + "angled", + "angler", + "angles", + "angling", + "angrily", + "angriness", + "anguished", + "angular", + "animal", + "animate", + "animating", + "animation", + "animator", + "anime", + "animosity", + "ankle", + "annex", + "annotate", + "announcer", + "annoying", + "annually", + "annuity", + "anointer", + "another", + "answering", + "antacid", + "antarctic", + "anteater", + "antelope", + "antennae", + "anthem", + "anthill", + "anthology", + "antibody", + "antics", + "antidote", + "antihero", + "antiquely", + "antiques", + "antiquity", + "antirust", + "antitoxic", + "antitrust", + "antiviral", + "antivirus", + "antler", + "antonym", + "antsy", + "anvil", + "anybody", + "anyhow", + "anymore", + "anyone", + "anyplace", + "anything", + "anytime", + "anyway", + "anywhere", + "aorta", + "apache", + "apostle", + "appealing", + "appear", + "appease", + "appeasing", + "appendage", + "appendix", + "appetite", + "appetizer", + "applaud", + "applause", + "apple", + "appliance", + "applicant", + "applied", + "apply", + "appointee", + "appraisal", + "appraiser", + "apprehend", + "approach", + "approval", + "approve", + "apricot", + "april", + "apron", + "aptitude", + "aptly", + "aqua", + "aqueduct", + "arbitrary", + "arbitrate", + "ardently", + "area", + "arena", + "arguable", + "arguably", + "argue", + "arise", + "armadillo", + "armband", + "armchair", + "armed", + "armful", + "armhole", + "arming", + "armless", + "armoire", + "armored", + "armory", + "armrest", + "army", + "aroma", + "arose", + "around", + "arousal", + "arrange", + "array", + "arrest", + "arrival", + "arrive", + "arrogance", + "arrogant", + "arson", + "art", + "ascend", + "ascension", + "ascent", + "ascertain", + "ashamed", + "ashen", + "ashes", + "ashy", + "aside", + "askew", + "asleep", + "asparagus", + "aspect", + "aspirate", + "aspire", + "aspirin", + "astonish", + "astound", + "astride", + "astrology", + "astronaut", + "astronomy", + "astute", + "atlantic", + "atlas", + "atom", + "atonable", + "atop", + "atrium", + "atrocious", + "atrophy", + "attach", + "attain", + "attempt", + "attendant", + "attendee", + "attention", + "attentive", + "attest", + "attic", + "attire", + "attitude", + "attractor", + "attribute", + "atypical", + "auction", + "audacious", + "audacity", + "audible", + "audibly", + "audience", + "audio", + "audition", + "augmented", + "august", + "authentic", + "author", + "autism", + "autistic", + "autograph", + "automaker", + "automated", + "automatic", + "autopilot", + "available", + "avalanche", + "avatar", + "avenge", + "avenging", + "avenue", + "average", + "aversion", + "avert", + "aviation", + "aviator", + "avid", + "avoid", + "await", + "awaken", + "award", + "aware", + "awhile", + "awkward", + "awning", + "awoke", + "awry", + "axis", + "babble", + "babbling", + "babied", + "baboon", + "backache", + "backboard", + "backboned", + "backdrop", + "backed", + "backer", + "backfield", + "backfire", + "backhand", + "backing", + "backlands", + "backlash", + "backless", + "backlight", + "backlit", + "backlog", + "backpack", + "backpedal", + "backrest", + "backroom", + "backshift", + "backside", + "backslid", + "backspace", + "backspin", + "backstab", + "backstage", + "backtalk", + "backtrack", + "backup", + "backward", + "backwash", + "backwater", + "backyard", + "bacon", + "bacteria", + "bacterium", + "badass", + "badge", + "badland", + "badly", + "badness", + "baffle", + "baffling", + "bagel", + "bagful", + "baggage", + "bagged", + "baggie", + "bagginess", + "bagging", + "baggy", + "bagpipe", + "baguette", + "baked", + "bakery", + "bakeshop", + "baking", + "balance", + "balancing", + "balcony", + "balmy", + "balsamic", + "bamboo", + "banana", + "banish", + "banister", + "banjo", + "bankable", + "bankbook", + "banked", + "banker", + "banking", + "banknote", + "bankroll", + "banner", + "bannister", + "banshee", + "banter", + "barbecue", + "barbed", + "barbell", + "barber", + "barcode", + "barge", + "bargraph", + "barista", + "baritone", + "barley", + "barmaid", + "barman", + "barn", + "barometer", + "barrack", + "barracuda", + "barrel", + "barrette", + "barricade", + "barrier", + "barstool", + "bartender", + "barterer", + "bash", + "basically", + "basics", + "basil", + "basin", + "basis", + "basket", + "batboy", + "batch", + "bath", + "baton", + "bats", + "battalion", + "battered", + "battering", + "battery", + "batting", + "battle", + "bauble", + "bazooka", + "blabber", + "bladder", + "blade", + "blah", + "blame", + "blaming", + "blanching", + "blandness", + "blank", + "blaspheme", + "blasphemy", + "blast", + "blatancy", + "blatantly", + "blazer", + "blazing", + "bleach", + "bleak", + "bleep", + "blemish", + "blend", + "bless", + "blighted", + "blimp", + "bling", + "blinked", + "blinker", + "blinking", + "blinks", + "blip", + "blissful", + "blitz", + "blizzard", + "bloated", + "bloating", + "blob", + "blog", + "bloomers", + "blooming", + "blooper", + "blot", + "blouse", + "blubber", + "bluff", + "bluish", + "blunderer", + "blunt", + "blurb", + "blurred", + "blurry", + "blurt", + "blush", + "blustery", + "boaster", + "boastful", + "boasting", + "boat", + "bobbed", + "bobbing", + "bobble", + "bobcat", + "bobsled", + "bobtail", + "bodacious", + "body", + "bogged", + "boggle", + "bogus", + "boil", + "bok", + "bolster", + "bolt", + "bonanza", + "bonded", + "bonding", + "bondless", + "boned", + "bonehead", + "boneless", + "bonelike", + "boney", + "bonfire", + "bonnet", + "bonsai", + "bonus", + "bony", + "boogeyman", + "boogieman", + "book", + "boondocks", + "booted", + "booth", + "bootie", + "booting", + "bootlace", + "bootleg", + "boots", + "boozy", + "borax", + "boring", + "borough", + "borrower", + "borrowing", + "boss", + "botanical", + "botanist", + "botany", + "botch", + "both", + "bottle", + "bottling", + "bottom", + "bounce", + "bouncing", + "bouncy", + "bounding", + "boundless", + "bountiful", + "bovine", + "boxcar", + "boxer", + "boxing", + "boxlike", + "boxy", + "breach", + "breath", + "breeches", + "breeching", + "breeder", + "breeding", + "breeze", + "breezy", + "brethren", + "brewery", + "brewing", + "briar", + "bribe", + "brick", + "bride", + "bridged", + "brigade", + "bright", + "brilliant", + "brim", + "bring", + "brink", + "brisket", + "briskly", + "briskness", + "bristle", + "brittle", + "broadband", + "broadcast", + "broaden", + "broadly", + "broadness", + "broadside", + "broadways", + "broiler", + "broiling", + "broken", + "broker", + "bronchial", + "bronco", + "bronze", + "bronzing", + "brook", + "broom", + "brought", + "browbeat", + "brownnose", + "browse", + "browsing", + "bruising", + "brunch", + "brunette", + "brunt", + "brush", + "brussels", + "brute", + "brutishly", + "bubble", + "bubbling", + "bubbly", + "buccaneer", + "bucked", + "bucket", + "buckle", + "buckshot", + "buckskin", + "bucktooth", + "buckwheat", + "buddhism", + "buddhist", + "budding", + "buddy", + "budget", + "buffalo", + "buffed", + "buffer", + "buffing", + "buffoon", + "buggy", + "bulb", + "bulge", + "bulginess", + "bulgur", + "bulk", + "bulldog", + "bulldozer", + "bullfight", + "bullfrog", + "bullhorn", + "bullion", + "bullish", + "bullpen", + "bullring", + "bullseye", + "bullwhip", + "bully", + "bunch", + "bundle", + "bungee", + "bunion", + "bunkbed", + "bunkhouse", + "bunkmate", + "bunny", + "bunt", + "busboy", + "bush", + "busily", + "busload", + "bust", + "busybody", + "buzz", + "cabana", + "cabbage", + "cabbie", + "cabdriver", + "cable", + "caboose", + "cache", + "cackle", + "cacti", + "cactus", + "caddie", + "caddy", + "cadet", + "cadillac", + "cadmium", + "cage", + "cahoots", + "cake", + "calamari", + "calamity", + "calcium", + "calculate", + "calculus", + "caliber", + "calibrate", + "calm", + "caloric", + "calorie", + "calzone", + "camcorder", + "cameo", + "camera", + "camisole", + "camper", + "campfire", + "camping", + "campsite", + "campus", + "canal", + "canary", + "cancel", + "candied", + "candle", + "candy", + "cane", + "canine", + "canister", + "cannabis", + "canned", + "canning", + "cannon", + "cannot", + "canola", + "canon", + "canopener", + "canopy", + "canteen", + "canyon", + "capable", + "capably", + "capacity", + "cape", + "capillary", + "capital", + "capitol", + "capped", + "capricorn", + "capsize", + "capsule", + "caption", + "captivate", + "captive", + "captivity", + "capture", + "caramel", + "carat", + "caravan", + "carbon", + "cardboard", + "carded", + "cardiac", + "cardigan", + "cardinal", + "cardstock", + "carefully", + "caregiver", + "careless", + "caress", + "caretaker", + "cargo", + "caring", + "carless", + "carload", + "carmaker", + "carnage", + "carnation", + "carnival", + "carnivore", + "carol", + "carpenter", + "carpentry", + "carpool", + "carport", + "carried", + "carrot", + "carrousel", + "carry", + "cartel", + "cartload", + "carton", + "cartoon", + "cartridge", + "cartwheel", + "carve", + "carving", + "carwash", + "cascade", + "case", + "cash", + "casing", + "casino", + "casket", + "cassette", + "casually", + "casualty", + "catacomb", + "catalog", + "catalyst", + "catalyze", + "catapult", + "cataract", + "catatonic", + "catcall", + "catchable", + "catcher", + "catching", + "catchy", + "caterer", + "catering", + "catfight", + "catfish", + "cathedral", + "cathouse", + "catlike", + "catnap", + "catnip", + "catsup", + "cattail", + "cattishly", + "cattle", + "catty", + "catwalk", + "caucasian", + "caucus", + "causal", + "causation", + "cause", + "causing", + "cauterize", + "caution", + "cautious", + "cavalier", + "cavalry", + "caviar", + "cavity", + "cedar", + "celery", + "celestial", + "celibacy", + "celibate", + "celtic", + "cement", + "census", + "ceramics", + "ceremony", + "certainly", + "certainty", + "certified", + "certify", + "cesarean", + "cesspool", + "chafe", + "chaffing", + "chain", + "chair", + "chalice", + "challenge", + "chamber", + "chamomile", + "champion", + "chance", + "change", + "channel", + "chant", + "chaos", + "chaperone", + "chaplain", + "chapped", + "chaps", + "chapter", + "character", + "charbroil", + "charcoal", + "charger", + "charging", + "chariot", + "charity", + "charm", + "charred", + "charter", + "charting", + "chase", + "chasing", + "chaste", + "chastise", + "chastity", + "chatroom", + "chatter", + "chatting", + "chatty", + "cheating", + "cheddar", + "cheek", + "cheer", + "cheese", + "cheesy", + "chef", + "chemicals", + "chemist", + "chemo", + "cherisher", + "cherub", + "chess", + "chest", + "chevron", + "chevy", + "chewable", + "chewer", + "chewing", + "chewy", + "chief", + "chihuahua", + "childcare", + "childhood", + "childish", + "childless", + "childlike", + "chili", + "chill", + "chimp", + "chip", + "chirping", + "chirpy", + "chitchat", + "chivalry", + "chive", + "chloride", + "chlorine", + "choice", + "chokehold", + "choking", + "chomp", + "chooser", + "choosing", + "choosy", + "chop", + "chosen", + "chowder", + "chowtime", + "chrome", + "chubby", + "chuck", + "chug", + "chummy", + "chump", + "chunk", + "churn", + "chute", + "cider", + "cilantro", + "cinch", + "cinema", + "cinnamon", + "circle", + "circling", + "circular", + "circulate", + "circus", + "citable", + "citadel", + "citation", + "citizen", + "citric", + "citrus", + "city", + "civic", + "civil", + "clad", + "claim", + "clambake", + "clammy", + "clamor", + "clamp", + "clamshell", + "clang", + "clanking", + "clapped", + "clapper", + "clapping", + "clarify", + "clarinet", + "clarity", + "clash", + "clasp", + "class", + "clatter", + "clause", + "clavicle", + "claw", + "clay", + "clean", + "clear", + "cleat", + "cleaver", + "cleft", + "clench", + "clergyman", + "clerical", + "clerk", + "clever", + "clicker", + "client", + "climate", + "climatic", + "cling", + "clinic", + "clinking", + "clip", + "clique", + "cloak", + "clobber", + "clock", + "clone", + "cloning", + "closable", + "closure", + "clothes", + "clothing", + "cloud", + "clover", + "clubbed", + "clubbing", + "clubhouse", + "clump", + "clumsily", + "clumsy", + "clunky", + "clustered", + "clutch", + "clutter", + "coach", + "coagulant", + "coastal", + "coaster", + "coasting", + "coastland", + "coastline", + "coat", + "coauthor", + "cobalt", + "cobbler", + "cobweb", + "cocoa", + "coconut", + "cod", + "coeditor", + "coerce", + "coexist", + "coffee", + "cofounder", + "cognition", + "cognitive", + "cogwheel", + "coherence", + "coherent", + "cohesive", + "coil", + "coke", + "cola", + "cold", + "coleslaw", + "coliseum", + "collage", + "collapse", + "collar", + "collected", + "collector", + "collide", + "collie", + "collision", + "colonial", + "colonist", + "colonize", + "colony", + "colossal", + "colt", + "coma", + "come", + "comfort", + "comfy", + "comic", + "coming", + "comma", + "commence", + "commend", + "comment", + "commerce", + "commode", + "commodity", + "commodore", + "common", + "commotion", + "commute", + "commuting", + "compacted", + "compacter", + "compactly", + "compactor", + "companion", + "company", + "compare", + "compel", + "compile", + "comply", + "component", + "composed", + "composer", + "composite", + "compost", + "composure", + "compound", + "compress", + "comprised", + "computer", + "computing", + "comrade", + "concave", + "conceal", + "conceded", + "concept", + "concerned", + "concert", + "conch", + "concierge", + "concise", + "conclude", + "concrete", + "concur", + "condense", + "condiment", + "condition", + "condone", + "conducive", + "conductor", + "conduit", + "cone", + "confess", + "confetti", + "confidant", + "confident", + "confider", + "confiding", + "configure", + "confined", + "confining", + "confirm", + "conflict", + "conform", + "confound", + "confront", + "confused", + "confusing", + "confusion", + "congenial", + "congested", + "congrats", + "congress", + "conical", + "conjoined", + "conjure", + "conjuror", + "connected", + "connector", + "consensus", + "consent", + "console", + "consoling", + "consonant", + "constable", + "constant", + "constrain", + "constrict", + "construct", + "consult", + "consumer", + "consuming", + "contact", + "container", + "contempt", + "contend", + "contented", + "contently", + "contents", + "contest", + "context", + "contort", + "contour", + "contrite", + "control", + "contusion", + "convene", + "convent", + "copartner", + "cope", + "copied", + "copier", + "copilot", + "coping", + "copious", + "copper", + "copy", + "coral", + "cork", + "cornball", + "cornbread", + "corncob", + "cornea", + "corned", + "corner", + "cornfield", + "cornflake", + "cornhusk", + "cornmeal", + "cornstalk", + "corny", + "coronary", + "coroner", + "corporal", + "corporate", + "corral", + "correct", + "corridor", + "corrode", + "corroding", + "corrosive", + "corsage", + "corset", + "cortex", + "cosigner", + "cosmetics", + "cosmic", + "cosmos", + "cosponsor", + "cost", + "cottage", + "cotton", + "couch", + "cough", + "could", + "countable", + "countdown", + "counting", + "countless", + "country", + "county", + "courier", + "covenant", + "cover", + "coveted", + "coveting", + "coyness", + "cozily", + "coziness", + "cozy", + "crabbing", + "crabgrass", + "crablike", + "crabmeat", + "cradle", + "cradling", + "crafter", + "craftily", + "craftsman", + "craftwork", + "crafty", + "cramp", + "cranberry", + "crane", + "cranial", + "cranium", + "crank", + "crate", + "crave", + "craving", + "crawfish", + "crawlers", + "crawling", + "crayfish", + "crayon", + "crazed", + "crazily", + "craziness", + "crazy", + "creamed", + "creamer", + "creamlike", + "crease", + "creasing", + "creatable", + "create", + "creation", + "creative", + "creature", + "credible", + "credibly", + "credit", + "creed", + "creme", + "creole", + "crepe", + "crept", + "crescent", + "crested", + "cresting", + "crestless", + "crevice", + "crewless", + "crewman", + "crewmate", + "crib", + "cricket", + "cried", + "crier", + "crimp", + "crimson", + "cringe", + "cringing", + "crinkle", + "crinkly", + "crisped", + "crisping", + "crisply", + "crispness", + "crispy", + "criteria", + "critter", + "croak", + "crock", + "crook", + "croon", + "crop", + "cross", + "crouch", + "crouton", + "crowbar", + "crowd", + "crown", + "crucial", + "crudely", + "crudeness", + "cruelly", + "cruelness", + "cruelty", + "crumb", + "crummiest", + "crummy", + "crumpet", + "crumpled", + "cruncher", + "crunching", + "crunchy", + "crusader", + "crushable", + "crushed", + "crusher", + "crushing", + "crust", + "crux", + "crying", + "cryptic", + "crystal", + "cubbyhole", + "cube", + "cubical", + "cubicle", + "cucumber", + "cuddle", + "cuddly", + "cufflink", + "culinary", + "culminate", + "culpable", + "culprit", + "cultivate", + "cultural", + "culture", + "cupbearer", + "cupcake", + "cupid", + "cupped", + "cupping", + "curable", + "curator", + "curdle", + "cure", + "curfew", + "curing", + "curled", + "curler", + "curliness", + "curling", + "curly", + "curry", + "curse", + "cursive", + "cursor", + "curtain", + "curtly", + "curtsy", + "curvature", + "curve", + "curvy", + "cushy", + "cusp", + "cussed", + "custard", + "custodian", + "custody", + "customary", + "customer", + "customize", + "customs", + "cut", + "cycle", + "cyclic", + "cycling", + "cyclist", + "cylinder", + "cymbal", + "cytoplasm", + "cytoplast", + "dab", + "dad", + "daffodil", + "dagger", + "daily", + "daintily", + "dainty", + "dairy", + "daisy", + "dallying", + "dance", + "dancing", + "dandelion", + "dander", + "dandruff", + "dandy", + "danger", + "dangle", + "dangling", + "daredevil", + "dares", + "daringly", + "darkened", + "darkening", + "darkish", + "darkness", + "darkroom", + "darling", + "darn", + "dart", + "darwinism", + "dash", + "dastardly", + "data", + "datebook", + "dating", + "daughter", + "daunting", + "dawdler", + "dawn", + "daybed", + "daybreak", + "daycare", + "daydream", + "daylight", + "daylong", + "dayroom", + "daytime", + "dazzler", + "dazzling", + "deacon", + "deafening", + "deafness", + "dealer", + "dealing", + "dealmaker", + "dealt", + "dean", + "debatable", + "debate", + "debating", + "debit", + "debrief", + "debtless", + "debtor", + "debug", + "debunk", + "decade", + "decaf", + "decal", + "decathlon", + "decay", + "deceased", + "deceit", + "deceiver", + "deceiving", + "december", + "decency", + "decent", + "deception", + "deceptive", + "decibel", + "decidable", + "decimal", + "decimeter", + "decipher", + "deck", + "declared", + "decline", + "decode", + "decompose", + "decorated", + "decorator", + "decoy", + "decrease", + "decree", + "dedicate", + "dedicator", + "deduce", + "deduct", + "deed", + "deem", + "deepen", + "deeply", + "deepness", + "deface", + "defacing", + "defame", + "default", + "defeat", + "defection", + "defective", + "defendant", + "defender", + "defense", + "defensive", + "deferral", + "deferred", + "defiance", + "defiant", + "defile", + "defiling", + "define", + "definite", + "deflate", + "deflation", + "deflator", + "deflected", + "deflector", + "defog", + "deforest", + "defraud", + "defrost", + "deftly", + "defuse", + "defy", + "degraded", + "degrading", + "degrease", + "degree", + "dehydrate", + "deity", + "dejected", + "delay", + "delegate", + "delegator", + "delete", + "deletion", + "delicacy", + "delicate", + "delicious", + "delighted", + "delirious", + "delirium", + "deliverer", + "delivery", + "delouse", + "delta", + "deluge", + "delusion", + "deluxe", + "demanding", + "demeaning", + "demeanor", + "demise", + "democracy", + "democrat", + "demote", + "demotion", + "demystify", + "denatured", + "deniable", + "denial", + "denim", + "denote", + "dense", + "density", + "dental", + "dentist", + "denture", + "deny", + "deodorant", + "deodorize", + "departed", + "departure", + "depict", + "deplete", + "depletion", + "deplored", + "deploy", + "deport", + "depose", + "depraved", + "depravity", + "deprecate", + "depress", + "deprive", + "depth", + "deputize", + "deputy", + "derail", + "deranged", + "derby", + "derived", + "desecrate", + "deserve", + "deserving", + "designate", + "designed", + "designer", + "designing", + "deskbound", + "desktop", + "deskwork", + "desolate", + "despair", + "despise", + "despite", + "destiny", + "destitute", + "destruct", + "detached", + "detail", + "detection", + "detective", + "detector", + "detention", + "detergent", + "detest", + "detonate", + "detonator", + "detoxify", + "detract", + "deuce", + "devalue", + "deviancy", + "deviant", + "deviate", + "deviation", + "deviator", + "device", + "devious", + "devotedly", + "devotee", + "devotion", + "devourer", + "devouring", + "devoutly", + "dexterity", + "dexterous", + "diabetes", + "diabetic", + "diabolic", + "diagnoses", + "diagnosis", + "diagram", + "dial", + "diameter", + "diaper", + "diaphragm", + "diary", + "dice", + "dicing", + "dictate", + "dictation", + "dictator", + "difficult", + "diffused", + "diffuser", + "diffusion", + "diffusive", + "dig", + "dilation", + "diligence", + "diligent", + "dill", + "dilute", + "dime", + "diminish", + "dimly", + "dimmed", + "dimmer", + "dimness", + "dimple", + "diner", + "dingbat", + "dinghy", + "dinginess", + "dingo", + "dingy", + "dining", + "dinner", + "diocese", + "dioxide", + "diploma", + "dipped", + "dipper", + "dipping", + "directed", + "direction", + "directive", + "directly", + "directory", + "direness", + "dirtiness", + "disabled", + "disagree", + "disallow", + "disarm", + "disarray", + "disaster", + "disband", + "disbelief", + "disburse", + "discard", + "discern", + "discharge", + "disclose", + "discolor", + "discount", + "discourse", + "discover", + "discuss", + "disdain", + "disengage", + "disfigure", + "disgrace", + "dish", + "disinfect", + "disjoin", + "disk", + "dislike", + "disliking", + "dislocate", + "dislodge", + "disloyal", + "dismantle", + "dismay", + "dismiss", + "dismount", + "disobey", + "disorder", + "disown", + "disparate", + "disparity", + "dispatch", + "dispense", + "dispersal", + "dispersed", + "disperser", + "displace", + "display", + "displease", + "disposal", + "dispose", + "disprove", + "dispute", + "disregard", + "disrupt", + "dissuade", + "distance", + "distant", + "distaste", + "distill", + "distinct", + "distort", + "distract", + "distress", + "district", + "distrust", + "ditch", + "ditto", + "ditzy", + "dividable", + "divided", + "dividend", + "dividers", + "dividing", + "divinely", + "diving", + "divinity", + "divisible", + "divisibly", + "division", + "divisive", + "divorcee", + "dizziness", + "dizzy", + "doable", + "docile", + "dock", + "doctrine", + "document", + "dodge", + "dodgy", + "doily", + "doing", + "dole", + "dollar", + "dollhouse", + "dollop", + "dolly", + "dolphin", + "domain", + "domelike", + "domestic", + "dominion", + "dominoes", + "donated", + "donation", + "donator", + "donor", + "donut", + "doodle", + "doorbell", + "doorframe", + "doorknob", + "doorman", + "doormat", + "doornail", + "doorpost", + "doorstep", + "doorstop", + "doorway", + "doozy", + "dork", + "dormitory", + "dorsal", + "dosage", + "dose", + "dotted", + "doubling", + "douche", + "dove", + "down", + "dowry", + "doze", + "drab", + "dragging", + "dragonfly", + "dragonish", + "dragster", + "drainable", + "drainage", + "drained", + "drainer", + "drainpipe", + "dramatic", + "dramatize", + "drank", + "drapery", + "drastic", + "draw", + "dreaded", + "dreadful", + "dreadlock", + "dreamboat", + "dreamily", + "dreamland", + "dreamless", + "dreamlike", + "dreamt", + "dreamy", + "drearily", + "dreary", + "drench", + "dress", + "drew", + "dribble", + "dried", + "drier", + "drift", + "driller", + "drilling", + "drinkable", + "drinking", + "dripping", + "drippy", + "drivable", + "driven", + "driver", + "driveway", + "driving", + "drizzle", + "drizzly", + "drone", + "drool", + "droop", + "drop-down", + "dropbox", + "dropkick", + "droplet", + "dropout", + "dropper", + "drove", + "drown", + "drowsily", + "drudge", + "drum", + "dry", + "dubbed", + "dubiously", + "duchess", + "duckbill", + "ducking", + "duckling", + "ducktail", + "ducky", + "duct", + "dude", + "duffel", + "dugout", + "duh", + "duke", + "duller", + "dullness", + "duly", + "dumping", + "dumpling", + "dumpster", + "duo", + "dupe", + "duplex", + "duplicate", + "duplicity", + "durable", + "durably", + "duration", + "duress", + "during", + "dusk", + "dust", + "dutiful", + "duty", + "duvet", + "dwarf", + "dweeb", + "dwelled", + "dweller", + "dwelling", + "dwindle", + "dwindling", + "dynamic", + "dynamite", + "dynasty", + "dyslexia", + "dyslexic", + "each", + "eagle", + "earache", + "eardrum", + "earflap", + "earful", + "earlobe", + "early", + "earmark", + "earmuff", + "earphone", + "earpiece", + "earplugs", + "earring", + "earshot", + "earthen", + "earthlike", + "earthling", + "earthly", + "earthworm", + "earthy", + "earwig", + "easeful", + "easel", + "easiest", + "easily", + "easiness", + "easing", + "eastbound", + "eastcoast", + "easter", + "eastward", + "eatable", + "eaten", + "eatery", + "eating", + "eats", + "ebay", + "ebony", + "ebook", + "ecard", + "eccentric", + "echo", + "eclair", + "eclipse", + "ecologist", + "ecology", + "economic", + "economist", + "economy", + "ecosphere", + "ecosystem", + "edge", + "edginess", + "edging", + "edgy", + "edition", + "editor", + "educated", + "education", + "educator", + "eel", + "effective", + "effects", + "efficient", + "effort", + "eggbeater", + "egging", + "eggnog", + "eggplant", + "eggshell", + "egomaniac", + "egotism", + "egotistic", + "either", + "eject", + "elaborate", + "elastic", + "elated", + "elbow", + "eldercare", + "elderly", + "eldest", + "electable", + "election", + "elective", + "elephant", + "elevate", + "elevating", + "elevation", + "elevator", + "eleven", + "elf", + "eligible", + "eligibly", + "eliminate", + "elite", + "elitism", + "elixir", + "elk", + "ellipse", + "elliptic", + "elm", + "elongated", + "elope", + "eloquence", + "eloquent", + "elsewhere", + "elude", + "elusive", + "elves", + "email", + "embargo", + "embark", + "embassy", + "embattled", + "embellish", + "ember", + "embezzle", + "emblaze", + "emblem", + "embody", + "embolism", + "emboss", + "embroider", + "emcee", + "emerald", + "emergency", + "emission", + "emit", + "emote", + "emoticon", + "emotion", + "empathic", + "empathy", + "emperor", + "emphases", + "emphasis", + "emphasize", + "emphatic", + "empirical", + "employed", + "employee", + "employer", + "emporium", + "empower", + "emptier", + "emptiness", + "empty", + "emu", + "enable", + "enactment", + "enamel", + "enchanted", + "enchilada", + "encircle", + "enclose", + "enclosure", + "encode", + "encore", + "encounter", + "encourage", + "encroach", + "encrust", + "encrypt", + "endanger", + "endeared", + "endearing", + "ended", + "ending", + "endless", + "endnote", + "endocrine", + "endorphin", + "endorse", + "endowment", + "endpoint", + "endurable", + "endurance", + "enduring", + "energetic", + "energize", + "energy", + "enforced", + "enforcer", + "engaged", + "engaging", + "engine", + "engorge", + "engraved", + "engraver", + "engraving", + "engross", + "engulf", + "enhance", + "enigmatic", + "enjoyable", + "enjoyably", + "enjoyer", + "enjoying", + "enjoyment", + "enlarged", + "enlarging", + "enlighten", + "enlisted", + "enquirer", + "enrage", + "enrich", + "enroll", + "enslave", + "ensnare", + "ensure", + "entail", + "entangled", + "entering", + "entertain", + "enticing", + "entire", + "entitle", + "entity", + "entomb", + "entourage", + "entrap", + "entree", + "entrench", + "entrust", + "entryway", + "entwine", + "enunciate", + "envelope", + "enviable", + "enviably", + "envious", + "envision", + "envoy", + "envy", + "enzyme", + "epic", + "epidemic", + "epidermal", + "epidermis", + "epidural", + "epilepsy", + "epileptic", + "epilogue", + "epiphany", + "episode", + "equal", + "equate", + "equation", + "equator", + "equinox", + "equipment", + "equity", + "equivocal", + "eradicate", + "erasable", + "erased", + "eraser", + "erasure", + "ergonomic", + "errand", + "errant", + "erratic", + "error", + "erupt", + "escalate", + "escalator", + "escapable", + "escapade", + "escapist", + "escargot", + "eskimo", + "esophagus", + "espionage", + "espresso", + "esquire", + "essay", + "essence", + "essential", + "establish", + "estate", + "esteemed", + "estimate", + "estimator", + "estranged", + "estrogen", + "etching", + "eternal", + "eternity", + "ethanol", + "ether", + "ethically", + "ethics", + "euphemism", + "evacuate", + "evacuee", + "evade", + "evaluate", + "evaluator", + "evaporate", + "evasion", + "evasive", + "even", + "everglade", + "evergreen", + "everybody", + "everyday", + "everyone", + "evict", + "evidence", + "evident", + "evil", + "evoke", + "evolution", + "evolve", + "exact", + "exalted", + "example", + "excavate", + "excavator", + "exceeding", + "exception", + "excess", + "exchange", + "excitable", + "exciting", + "exclaim", + "exclude", + "excluding", + "exclusion", + "exclusive", + "excretion", + "excretory", + "excursion", + "excusable", + "excusably", + "excuse", + "exemplary", + "exemplify", + "exemption", + "exerciser", + "exert", + "exes", + "exfoliate", + "exhale", + "exhaust", + "exhume", + "exile", + "existing", + "exit", + "exodus", + "exonerate", + "exorcism", + "exorcist", + "expand", + "expanse", + "expansion", + "expansive", + "expectant", + "expedited", + "expediter", + "expel", + "expend", + "expenses", + "expensive", + "expert", + "expire", + "expiring", + "explain", + "expletive", + "explicit", + "explode", + "exploit", + "explore", + "exploring", + "exponent", + "exporter", + "exposable", + "expose", + "exposure", + "express", + "expulsion", + "exquisite", + "extended", + "extending", + "extent", + "extenuate", + "exterior", + "external", + "extinct", + "extortion", + "extradite", + "extras", + "extrovert", + "extrude", + "extruding", + "exuberant", + "fable", + "fabric", + "fabulous", + "facebook", + "facecloth", + "facedown", + "faceless", + "facelift", + "faceplate", + "faceted", + "facial", + "facility", + "facing", + "facsimile", + "faction", + "factoid", + "factor", + "factsheet", + "factual", + "faculty", + "fade", + "fading", + "failing", + "falcon", + "fall", + "false", + "falsify", + "fame", + "familiar", + "family", + "famine", + "famished", + "fanatic", + "fancied", + "fanciness", + "fancy", + "fanfare", + "fang", + "fanning", + "fantasize", + "fantastic", + "fantasy", + "fascism", + "fastball", + "faster", + "fasting", + "fastness", + "faucet", + "favorable", + "favorably", + "favored", + "favoring", + "favorite", + "fax", + "feast", + "federal", + "fedora", + "feeble", + "feed", + "feel", + "feisty", + "feline", + "felt-tip", + "feminine", + "feminism", + "feminist", + "feminize", + "femur", + "fence", + "fencing", + "fender", + "ferment", + "fernlike", + "ferocious", + "ferocity", + "ferret", + "ferris", + "ferry", + "fervor", + "fester", + "festival", + "festive", + "festivity", + "fetal", + "fetch", + "fever", + "fiber", + "fiction", + "fiddle", + "fiddling", + "fidelity", + "fidgeting", + "fidgety", + "fifteen", + "fifth", + "fiftieth", + "fifty", + "figment", + "figure", + "figurine", + "filing", + "filled", + "filler", + "filling", + "film", + "filter", + "filth", + "filtrate", + "finale", + "finalist", + "finalize", + "finally", + "finance", + "financial", + "finch", + "fineness", + "finer", + "finicky", + "finished", + "finisher", + "finishing", + "finite", + "finless", + "finlike", + "fiscally", + "fit", + "five", + "flaccid", + "flagman", + "flagpole", + "flagship", + "flagstick", + "flagstone", + "flail", + "flakily", + "flaky", + "flame", + "flammable", + "flanked", + "flanking", + "flannels", + "flap", + "flaring", + "flashback", + "flashbulb", + "flashcard", + "flashily", + "flashing", + "flashy", + "flask", + "flatbed", + "flatfoot", + "flatly", + "flatness", + "flatten", + "flattered", + "flatterer", + "flattery", + "flattop", + "flatware", + "flatworm", + "flavored", + "flavorful", + "flavoring", + "flaxseed", + "fled", + "fleshed", + "fleshy", + "flick", + "flier", + "flight", + "flinch", + "fling", + "flint", + "flip", + "flirt", + "float", + "flock", + "flogging", + "flop", + "floral", + "florist", + "floss", + "flounder", + "flyable", + "flyaway", + "flyer", + "flying", + "flyover", + "flypaper", + "foam", + "foe", + "fog", + "foil", + "folic", + "folk", + "follicle", + "follow", + "fondling", + "fondly", + "fondness", + "fondue", + "font", + "food", + "fool", + "footage", + "football", + "footbath", + "footboard", + "footer", + "footgear", + "foothill", + "foothold", + "footing", + "footless", + "footman", + "footnote", + "footpad", + "footpath", + "footprint", + "footrest", + "footsie", + "footsore", + "footwear", + "footwork", + "fossil", + "foster", + "founder", + "founding", + "fountain", + "fox", + "foyer", + "fraction", + "fracture", + "fragile", + "fragility", + "fragment", + "fragrance", + "fragrant", + "frail", + "frame", + "framing", + "frantic", + "fraternal", + "frayed", + "fraying", + "frays", + "freckled", + "freckles", + "freebase", + "freebee", + "freebie", + "freedom", + "freefall", + "freehand", + "freeing", + "freeload", + "freely", + "freemason", + "freeness", + "freestyle", + "freeware", + "freeway", + "freewill", + "freezable", + "freezing", + "freight", + "french", + "frenzied", + "frenzy", + "frequency", + "frequent", + "fresh", + "fretful", + "fretted", + "friction", + "friday", + "fridge", + "fried", + "friend", + "frighten", + "frightful", + "frigidity", + "frigidly", + "frill", + "fringe", + "frisbee", + "frisk", + "fritter", + "frivolous", + "frolic", + "from", + "front", + "frostbite", + "frosted", + "frostily", + "frosting", + "frostlike", + "frosty", + "froth", + "frown", + "frozen", + "fructose", + "frugality", + "frugally", + "fruit", + "frustrate", + "frying", + "gab", + "gaffe", + "gag", + "gainfully", + "gaining", + "gains", + "gala", + "gallantly", + "galleria", + "gallery", + "galley", + "gallon", + "gallows", + "gallstone", + "galore", + "galvanize", + "gambling", + "game", + "gaming", + "gamma", + "gander", + "gangly", + "gangrene", + "gangway", + "gap", + "garage", + "garbage", + "garden", + "gargle", + "garland", + "garlic", + "garment", + "garnet", + "garnish", + "garter", + "gas", + "gatherer", + "gathering", + "gating", + "gauging", + "gauntlet", + "gauze", + "gave", + "gawk", + "gazing", + "gear", + "gecko", + "geek", + "geiger", + "gem", + "gender", + "generic", + "generous", + "genetics", + "genre", + "gentile", + "gentleman", + "gently", + "gents", + "geography", + "geologic", + "geologist", + "geology", + "geometric", + "geometry", + "geranium", + "gerbil", + "geriatric", + "germicide", + "germinate", + "germless", + "germproof", + "gestate", + "gestation", + "gesture", + "getaway", + "getting", + "getup", + "giant", + "gibberish", + "giblet", + "giddily", + "giddiness", + "giddy", + "gift", + "gigabyte", + "gigahertz", + "gigantic", + "giggle", + "giggling", + "giggly", + "gigolo", + "gilled", + "gills", + "gimmick", + "girdle", + "giveaway", + "given", + "giver", + "giving", + "gizmo", + "gizzard", + "glacial", + "glacier", + "glade", + "gladiator", + "gladly", + "glamorous", + "glamour", + "glance", + "glancing", + "glandular", + "glare", + "glaring", + "glass", + "glaucoma", + "glazing", + "gleaming", + "gleeful", + "glider", + "gliding", + "glimmer", + "glimpse", + "glisten", + "glitch", + "glitter", + "glitzy", + "gloater", + "gloating", + "gloomily", + "gloomy", + "glorified", + "glorifier", + "glorify", + "glorious", + "glory", + "gloss", + "glove", + "glowing", + "glowworm", + "glucose", + "glue", + "gluten", + "glutinous", + "glutton", + "gnarly", + "gnat", + "goal", + "goatskin", + "goes", + "goggles", + "going", + "goldfish", + "goldmine", + "goldsmith", + "golf", + "goliath", + "gonad", + "gondola", + "gone", + "gong", + "good", + "gooey", + "goofball", + "goofiness", + "goofy", + "google", + "goon", + "gopher", + "gore", + "gorged", + "gorgeous", + "gory", + "gosling", + "gossip", + "gothic", + "gotten", + "gout", + "gown", + "grab", + "graceful", + "graceless", + "gracious", + "gradation", + "graded", + "grader", + "gradient", + "grading", + "gradually", + "graduate", + "graffiti", + "grafted", + "grafting", + "grain", + "granddad", + "grandkid", + "grandly", + "grandma", + "grandpa", + "grandson", + "granite", + "granny", + "granola", + "grant", + "granular", + "grape", + "graph", + "grapple", + "grappling", + "grasp", + "grass", + "gratified", + "gratify", + "grating", + "gratitude", + "gratuity", + "gravel", + "graveness", + "graves", + "graveyard", + "gravitate", + "gravity", + "gravy", + "gray", + "grazing", + "greasily", + "greedily", + "greedless", + "greedy", + "green", + "greeter", + "greeting", + "grew", + "greyhound", + "grid", + "grief", + "grievance", + "grieving", + "grievous", + "grill", + "grimace", + "grimacing", + "grime", + "griminess", + "grimy", + "grinch", + "grinning", + "grip", + "gristle", + "grit", + "groggily", + "groggy", + "groin", + "groom", + "groove", + "grooving", + "groovy", + "grope", + "ground", + "grouped", + "grout", + "grove", + "grower", + "growing", + "growl", + "grub", + "grudge", + "grudging", + "grueling", + "gruffly", + "grumble", + "grumbling", + "grumbly", + "grumpily", + "grunge", + "grunt", + "guacamole", + "guidable", + "guidance", + "guide", + "guiding", + "guileless", + "guise", + "gulf", + "gullible", + "gully", + "gulp", + "gumball", + "gumdrop", + "gumminess", + "gumming", + "gummy", + "gurgle", + "gurgling", + "guru", + "gush", + "gusto", + "gusty", + "gutless", + "guts", + "gutter", + "guy", + "guzzler", + "gyration", + "habitable", + "habitant", + "habitat", + "habitual", + "hacked", + "hacker", + "hacking", + "hacksaw", + "had", + "haggler", + "haiku", + "half", + "halogen", + "halt", + "halved", + "halves", + "hamburger", + "hamlet", + "hammock", + "hamper", + "hamster", + "hamstring", + "handbag", + "handball", + "handbook", + "handbrake", + "handcart", + "handclap", + "handclasp", + "handcraft", + "handcuff", + "handed", + "handful", + "handgrip", + "handgun", + "handheld", + "handiness", + "handiwork", + "handlebar", + "handled", + "handler", + "handling", + "handmade", + "handoff", + "handpick", + "handprint", + "handrail", + "handsaw", + "handset", + "handsfree", + "handshake", + "handstand", + "handwash", + "handwork", + "handwoven", + "handwrite", + "handyman", + "hangnail", + "hangout", + "hangover", + "hangup", + "hankering", + "hankie", + "hanky", + "haphazard", + "happening", + "happier", + "happiest", + "happily", + "happiness", + "happy", + "harbor", + "hardcopy", + "hardcore", + "hardcover", + "harddisk", + "hardened", + "hardener", + "hardening", + "hardhat", + "hardhead", + "hardiness", + "hardly", + "hardness", + "hardship", + "hardware", + "hardwired", + "hardwood", + "hardy", + "harmful", + "harmless", + "harmonica", + "harmonics", + "harmonize", + "harmony", + "harness", + "harpist", + "harsh", + "harvest", + "hash", + "hassle", + "haste", + "hastily", + "hastiness", + "hasty", + "hatbox", + "hatchback", + "hatchery", + "hatchet", + "hatching", + "hatchling", + "hate", + "hatless", + "hatred", + "haunt", + "haven", + "hazard", + "hazelnut", + "hazily", + "haziness", + "hazing", + "hazy", + "headache", + "headband", + "headboard", + "headcount", + "headdress", + "headed", + "header", + "headfirst", + "headgear", + "heading", + "headlamp", + "headless", + "headlock", + "headphone", + "headpiece", + "headrest", + "headroom", + "headscarf", + "headset", + "headsman", + "headstand", + "headstone", + "headway", + "headwear", + "heap", + "heat", + "heave", + "heavily", + "heaviness", + "heaving", + "hedge", + "hedging", + "heftiness", + "hefty", + "helium", + "helmet", + "helper", + "helpful", + "helping", + "helpless", + "helpline", + "hemlock", + "hemstitch", + "hence", + "henchman", + "henna", + "herald", + "herbal", + "herbicide", + "herbs", + "heritage", + "hermit", + "heroics", + "heroism", + "herring", + "herself", + "hertz", + "hesitancy", + "hesitant", + "hesitate", + "hexagon", + "hexagram", + "hubcap", + "huddle", + "huddling", + "huff", + "hug", + "hula", + "hulk", + "hull", + "human", + "humble", + "humbling", + "humbly", + "humid", + "humiliate", + "humility", + "humming", + "hummus", + "humongous", + "humorist", + "humorless", + "humorous", + "humpback", + "humped", + "humvee", + "hunchback", + "hundredth", + "hunger", + "hungrily", + "hungry", + "hunk", + "hunter", + "hunting", + "huntress", + "huntsman", + "hurdle", + "hurled", + "hurler", + "hurling", + "hurray", + "hurricane", + "hurried", + "hurry", + "hurt", + "husband", + "hush", + "husked", + "huskiness", + "hut", + "hybrid", + "hydrant", + "hydrated", + "hydration", + "hydrogen", + "hydroxide", + "hyperlink", + "hypertext", + "hyphen", + "hypnoses", + "hypnosis", + "hypnotic", + "hypnotism", + "hypnotist", + "hypnotize", + "hypocrisy", + "hypocrite", + "ibuprofen", + "ice", + "iciness", + "icing", + "icky", + "icon", + "icy", + "idealism", + "idealist", + "idealize", + "ideally", + "idealness", + "identical", + "identify", + "identity", + "ideology", + "idiocy", + "idiom", + "idly", + "igloo", + "ignition", + "ignore", + "iguana", + "illicitly", + "illusion", + "illusive", + "image", + "imaginary", + "imagines", + "imaging", + "imbecile", + "imitate", + "imitation", + "immature", + "immerse", + "immersion", + "imminent", + "immobile", + "immodest", + "immorally", + "immortal", + "immovable", + "immovably", + "immunity", + "immunize", + "impaired", + "impale", + "impart", + "impatient", + "impeach", + "impeding", + "impending", + "imperfect", + "imperial", + "impish", + "implant", + "implement", + "implicate", + "implicit", + "implode", + "implosion", + "implosive", + "imply", + "impolite", + "important", + "importer", + "impose", + "imposing", + "impotence", + "impotency", + "impotent", + "impound", + "imprecise", + "imprint", + "imprison", + "impromptu", + "improper", + "improve", + "improving", + "improvise", + "imprudent", + "impulse", + "impulsive", + "impure", + "impurity", + "iodine", + "iodize", + "ion", + "ipad", + "iphone", + "ipod", + "irate", + "irk", + "iron", + "irregular", + "irrigate", + "irritable", + "irritably", + "irritant", + "irritate", + "islamic", + "islamist", + "isolated", + "isolating", + "isolation", + "isotope", + "issue", + "issuing", + "italicize", + "italics", + "item", + "itinerary", + "itunes", + "ivory", + "ivy", + "jab", + "jackal", + "jacket", + "jackknife", + "jackpot", + "jailbird", + "jailbreak", + "jailer", + "jailhouse", + "jalapeno", + "jam", + "janitor", + "january", + "jargon", + "jarring", + "jasmine", + "jaundice", + "jaunt", + "java", + "jawed", + "jawless", + "jawline", + "jaws", + "jaybird", + "jaywalker", + "jazz", + "jeep", + "jeeringly", + "jellied", + "jelly", + "jersey", + "jester", + "jet", + "jiffy", + "jigsaw", + "jimmy", + "jingle", + "jingling", + "jinx", + "jitters", + "jittery", + "job", + "jockey", + "jockstrap", + "jogger", + "jogging", + "john", + "joining", + "jokester", + "jokingly", + "jolliness", + "jolly", + "jolt", + "jot", + "jovial", + "joyfully", + "joylessly", + "joyous", + "joyride", + "joystick", + "jubilance", + "jubilant", + "judge", + "judgingly", + "judicial", + "judiciary", + "judo", + "juggle", + "juggling", + "jugular", + "juice", + "juiciness", + "juicy", + "jujitsu", + "jukebox", + "july", + "jumble", + "jumbo", + "jump", + "junction", + "juncture", + "june", + "junior", + "juniper", + "junkie", + "junkman", + "junkyard", + "jurist", + "juror", + "jury", + "justice", + "justifier", + "justify", + "justly", + "justness", + "juvenile", + "kabob", + "kangaroo", + "karaoke", + "karate", + "karma", + "kebab", + "keenly", + "keenness", + "keep", + "keg", + "kelp", + "kennel", + "kept", + "kerchief", + "kerosene", + "kettle", + "kick", + "kiln", + "kilobyte", + "kilogram", + "kilometer", + "kilowatt", + "kilt", + "kimono", + "kindle", + "kindling", + "kindly", + "kindness", + "kindred", + "kinetic", + "kinfolk", + "king", + "kinship", + "kinsman", + "kinswoman", + "kissable", + "kisser", + "kissing", + "kitchen", + "kite", + "kitten", + "kitty", + "kiwi", + "kleenex", + "knapsack", + "knee", + "knelt", + "knickers", + "knoll", + "koala", + "kooky", + "kosher", + "krypton", + "kudos", + "kung", + "labored", + "laborer", + "laboring", + "laborious", + "labrador", + "ladder", + "ladies", + "ladle", + "ladybug", + "ladylike", + "lagged", + "lagging", + "lagoon", + "lair", + "lake", + "lance", + "landed", + "landfall", + "landfill", + "landing", + "landlady", + "landless", + "landline", + "landlord", + "landmark", + "landmass", + "landmine", + "landowner", + "landscape", + "landside", + "landslide", + "language", + "lankiness", + "lanky", + "lantern", + "lapdog", + "lapel", + "lapped", + "lapping", + "laptop", + "lard", + "large", + "lark", + "lash", + "lasso", + "last", + "latch", + "late", + "lather", + "latitude", + "latrine", + "latter", + "latticed", + "launch", + "launder", + "laundry", + "laurel", + "lavender", + "lavish", + "laxative", + "lazily", + "laziness", + "lazy", + "lecturer", + "left", + "legacy", + "legal", + "legend", + "legged", + "leggings", + "legible", + "legibly", + "legislate", + "lego", + "legroom", + "legume", + "legwarmer", + "legwork", + "lemon", + "lend", + "length", + "lens", + "lent", + "leotard", + "lesser", + "letdown", + "lethargic", + "lethargy", + "letter", + "lettuce", + "level", + "leverage", + "levers", + "levitate", + "levitator", + "liability", + "liable", + "liberty", + "librarian", + "library", + "licking", + "licorice", + "lid", + "life", + "lifter", + "lifting", + "liftoff", + "ligament", + "likely", + "likeness", + "likewise", + "liking", + "lilac", + "lilly", + "lily", + "limb", + "limeade", + "limelight", + "limes", + "limit", + "limping", + "limpness", + "line", + "lingo", + "linguini", + "linguist", + "lining", + "linked", + "linoleum", + "linseed", + "lint", + "lion", + "lip", + "liquefy", + "liqueur", + "liquid", + "lisp", + "list", + "litigate", + "litigator", + "litmus", + "litter", + "little", + "livable", + "lived", + "lively", + "liver", + "livestock", + "lividly", + "living", + "lizard", + "lubricant", + "lubricate", + "lucid", + "luckily", + "luckiness", + "luckless", + "lucrative", + "ludicrous", + "lugged", + "lukewarm", + "lullaby", + "lumber", + "luminance", + "luminous", + "lumpiness", + "lumping", + "lumpish", + "lunacy", + "lunar", + "lunchbox", + "luncheon", + "lunchroom", + "lunchtime", + "lung", + "lurch", + "lure", + "luridness", + "lurk", + "lushly", + "lushness", + "luster", + "lustfully", + "lustily", + "lustiness", + "lustrous", + "lusty", + "luxurious", + "luxury", + "lying", + "lyrically", + "lyricism", + "lyricist", + "lyrics", + "macarena", + "macaroni", + "macaw", + "mace", + "machine", + "machinist", + "magazine", + "magenta", + "maggot", + "magical", + "magician", + "magma", + "magnesium", + "magnetic", + "magnetism", + "magnetize", + "magnifier", + "magnify", + "magnitude", + "magnolia", + "mahogany", + "maimed", + "majestic", + "majesty", + "majorette", + "majority", + "makeover", + "maker", + "makeshift", + "making", + "malformed", + "malt", + "mama", + "mammal", + "mammary", + "mammogram", + "manager", + "managing", + "manatee", + "mandarin", + "mandate", + "mandatory", + "mandolin", + "manger", + "mangle", + "mango", + "mangy", + "manhandle", + "manhole", + "manhood", + "manhunt", + "manicotti", + "manicure", + "manifesto", + "manila", + "mankind", + "manlike", + "manliness", + "manly", + "manmade", + "manned", + "mannish", + "manor", + "manpower", + "mantis", + "mantra", + "manual", + "many", + "map", + "marathon", + "marauding", + "marbled", + "marbles", + "marbling", + "march", + "mardi", + "margarine", + "margarita", + "margin", + "marigold", + "marina", + "marine", + "marital", + "maritime", + "marlin", + "marmalade", + "maroon", + "married", + "marrow", + "marry", + "marshland", + "marshy", + "marsupial", + "marvelous", + "marxism", + "mascot", + "masculine", + "mashed", + "mashing", + "massager", + "masses", + "massive", + "mastiff", + "matador", + "matchbook", + "matchbox", + "matcher", + "matching", + "matchless", + "material", + "maternal", + "maternity", + "math", + "mating", + "matriarch", + "matrimony", + "matrix", + "matron", + "matted", + "matter", + "maturely", + "maturing", + "maturity", + "mauve", + "maverick", + "maximize", + "maximum", + "maybe", + "mayday", + "mayflower", + "moaner", + "moaning", + "mobile", + "mobility", + "mobilize", + "mobster", + "mocha", + "mocker", + "mockup", + "modified", + "modify", + "modular", + "modulator", + "module", + "moisten", + "moistness", + "moisture", + "molar", + "molasses", + "mold", + "molecular", + "molecule", + "molehill", + "mollusk", + "mom", + "monastery", + "monday", + "monetary", + "monetize", + "moneybags", + "moneyless", + "moneywise", + "mongoose", + "mongrel", + "monitor", + "monkhood", + "monogamy", + "monogram", + "monologue", + "monopoly", + "monorail", + "monotone", + "monotype", + "monoxide", + "monsieur", + "monsoon", + "monstrous", + "monthly", + "monument", + "moocher", + "moodiness", + "moody", + "mooing", + "moonbeam", + "mooned", + "moonlight", + "moonlike", + "moonlit", + "moonrise", + "moonscape", + "moonshine", + "moonstone", + "moonwalk", + "mop", + "morale", + "morality", + "morally", + "morbidity", + "morbidly", + "morphine", + "morphing", + "morse", + "mortality", + "mortally", + "mortician", + "mortified", + "mortify", + "mortuary", + "mosaic", + "mossy", + "most", + "mothball", + "mothproof", + "motion", + "motivate", + "motivator", + "motive", + "motocross", + "motor", + "motto", + "mountable", + "mountain", + "mounted", + "mounting", + "mourner", + "mournful", + "mouse", + "mousiness", + "moustache", + "mousy", + "mouth", + "movable", + "move", + "movie", + "moving", + "mower", + "mowing", + "much", + "muck", + "mud", + "mug", + "mulberry", + "mulch", + "mule", + "mulled", + "mullets", + "multiple", + "multiply", + "multitask", + "multitude", + "mumble", + "mumbling", + "mumbo", + "mummified", + "mummify", + "mummy", + "mumps", + "munchkin", + "mundane", + "municipal", + "muppet", + "mural", + "murkiness", + "murky", + "murmuring", + "muscular", + "museum", + "mushily", + "mushiness", + "mushroom", + "mushy", + "music", + "musket", + "muskiness", + "musky", + "mustang", + "mustard", + "muster", + "mustiness", + "musty", + "mutable", + "mutate", + "mutation", + "mute", + "mutilated", + "mutilator", + "mutiny", + "mutt", + "mutual", + "muzzle", + "myself", + "myspace", + "mystified", + "mystify", + "myth", + "nacho", + "nag", + "nail", + "name", + "naming", + "nanny", + "nanometer", + "nape", + "napkin", + "napped", + "napping", + "nappy", + "narrow", + "nastily", + "nastiness", + "national", + "native", + "nativity", + "natural", + "nature", + "naturist", + "nautical", + "navigate", + "navigator", + "navy", + "nearby", + "nearest", + "nearly", + "nearness", + "neatly", + "neatness", + "nebula", + "nebulizer", + "nectar", + "negate", + "negation", + "negative", + "neglector", + "negligee", + "negligent", + "negotiate", + "nemeses", + "nemesis", + "neon", + "nephew", + "nerd", + "nervous", + "nervy", + "nest", + "net", + "neurology", + "neuron", + "neurosis", + "neurotic", + "neuter", + "neutron", + "never", + "next", + "nibble", + "nickname", + "nicotine", + "niece", + "nifty", + "nimble", + "nimbly", + "nineteen", + "ninetieth", + "ninja", + "nintendo", + "ninth", + "nuclear", + "nuclei", + "nucleus", + "nugget", + "nullify", + "number", + "numbing", + "numbly", + "numbness", + "numeral", + "numerate", + "numerator", + "numeric", + "numerous", + "nuptials", + "nursery", + "nursing", + "nurture", + "nutcase", + "nutlike", + "nutmeg", + "nutrient", + "nutshell", + "nuttiness", + "nutty", + "nuzzle", + "nylon", + "oaf", + "oak", + "oasis", + "oat", + "obedience", + "obedient", + "obituary", + "object", + "obligate", + "obliged", + "oblivion", + "oblivious", + "oblong", + "obnoxious", + "oboe", + "obscure", + "obscurity", + "observant", + "observer", + "observing", + "obsessed", + "obsession", + "obsessive", + "obsolete", + "obstacle", + "obstinate", + "obstruct", + "obtain", + "obtrusive", + "obtuse", + "obvious", + "occultist", + "occupancy", + "occupant", + "occupier", + "occupy", + "ocean", + "ocelot", + "octagon", + "octane", + "october", + "octopus", + "ogle", + "oil", + "oink", + "ointment", + "okay", + "old", + "olive", + "olympics", + "omega", + "omen", + "ominous", + "omission", + "omit", + "omnivore", + "onboard", + "oncoming", + "ongoing", + "onion", + "online", + "onlooker", + "only", + "onscreen", + "onset", + "onshore", + "onslaught", + "onstage", + "onto", + "onward", + "onyx", + "oops", + "ooze", + "oozy", + "opacity", + "opal", + "open", + "operable", + "operate", + "operating", + "operation", + "operative", + "operator", + "opium", + "opossum", + "opponent", + "oppose", + "opposing", + "opposite", + "oppressed", + "oppressor", + "opt", + "opulently", + "osmosis", + "other", + "otter", + "ouch", + "ought", + "ounce", + "outage", + "outback", + "outbid", + "outboard", + "outbound", + "outbreak", + "outburst", + "outcast", + "outclass", + "outcome", + "outdated", + "outdoors", + "outer", + "outfield", + "outfit", + "outflank", + "outgoing", + "outgrow", + "outhouse", + "outing", + "outlast", + "outlet", + "outline", + "outlook", + "outlying", + "outmatch", + "outmost", + "outnumber", + "outplayed", + "outpost", + "outpour", + "output", + "outrage", + "outrank", + "outreach", + "outright", + "outscore", + "outsell", + "outshine", + "outshoot", + "outsider", + "outskirts", + "outsmart", + "outsource", + "outspoken", + "outtakes", + "outthink", + "outward", + "outweigh", + "outwit", + "oval", + "ovary", + "oven", + "overact", + "overall", + "overarch", + "overbid", + "overbill", + "overbite", + "overblown", + "overboard", + "overbook", + "overbuilt", + "overcast", + "overcoat", + "overcome", + "overcook", + "overcrowd", + "overdraft", + "overdrawn", + "overdress", + "overdrive", + "overdue", + "overeager", + "overeater", + "overexert", + "overfed", + "overfeed", + "overfill", + "overflow", + "overfull", + "overgrown", + "overhand", + "overhang", + "overhaul", + "overhead", + "overhear", + "overheat", + "overhung", + "overjoyed", + "overkill", + "overlabor", + "overlaid", + "overlap", + "overlay", + "overload", + "overlook", + "overlord", + "overlying", + "overnight", + "overpass", + "overpay", + "overplant", + "overplay", + "overpower", + "overprice", + "overrate", + "overreach", + "overreact", + "override", + "overripe", + "overrule", + "overrun", + "overshoot", + "overshot", + "oversight", + "oversized", + "oversleep", + "oversold", + "overspend", + "overstate", + "overstay", + "overstep", + "overstock", + "overstuff", + "oversweet", + "overtake", + "overthrow", + "overtime", + "overtly", + "overtone", + "overture", + "overturn", + "overuse", + "overvalue", + "overview", + "overwrite", + "owl", + "oxford", + "oxidant", + "oxidation", + "oxidize", + "oxidizing", + "oxygen", + "oxymoron", + "oyster", + "ozone", + "paced", + "pacemaker", + "pacific", + "pacifier", + "pacifism", + "pacifist", + "pacify", + "padded", + "padding", + "paddle", + "paddling", + "padlock", + "pagan", + "pager", + "paging", + "pajamas", + "palace", + "palatable", + "palm", + "palpable", + "palpitate", + "paltry", + "pampered", + "pamperer", + "pampers", + "pamphlet", + "panama", + "pancake", + "pancreas", + "panda", + "pandemic", + "pang", + "panhandle", + "panic", + "panning", + "panorama", + "panoramic", + "panther", + "pantomime", + "pantry", + "pants", + "pantyhose", + "paparazzi", + "papaya", + "paper", + "paprika", + "papyrus", + "parabola", + "parachute", + "parade", + "paradox", + "paragraph", + "parakeet", + "paralegal", + "paralyses", + "paralysis", + "paralyze", + "paramedic", + "parameter", + "paramount", + "parasail", + "parasite", + "parasitic", + "parcel", + "parched", + "parchment", + "pardon", + "parish", + "parka", + "parking", + "parkway", + "parlor", + "parmesan", + "parole", + "parrot", + "parsley", + "parsnip", + "partake", + "parted", + "parting", + "partition", + "partly", + "partner", + "partridge", + "party", + "passable", + "passably", + "passage", + "passcode", + "passenger", + "passerby", + "passing", + "passion", + "passive", + "passivism", + "passover", + "passport", + "password", + "pasta", + "pasted", + "pastel", + "pastime", + "pastor", + "pastrami", + "pasture", + "pasty", + "patchwork", + "patchy", + "paternal", + "paternity", + "path", + "patience", + "patient", + "patio", + "patriarch", + "patriot", + "patrol", + "patronage", + "patronize", + "pauper", + "pavement", + "paver", + "pavestone", + "pavilion", + "paving", + "pawing", + "payable", + "payback", + "paycheck", + "payday", + "payee", + "payer", + "paying", + "payment", + "payphone", + "payroll", + "pebble", + "pebbly", + "pecan", + "pectin", + "peculiar", + "peddling", + "pediatric", + "pedicure", + "pedigree", + "pedometer", + "pegboard", + "pelican", + "pellet", + "pelt", + "pelvis", + "penalize", + "penalty", + "pencil", + "pendant", + "pending", + "penholder", + "penknife", + "pennant", + "penniless", + "penny", + "penpal", + "pension", + "pentagon", + "pentagram", + "pep", + "perceive", + "percent", + "perch", + "percolate", + "perennial", + "perfected", + "perfectly", + "perfume", + "periscope", + "perish", + "perjurer", + "perjury", + "perkiness", + "perky", + "perm", + "peroxide", + "perpetual", + "perplexed", + "persecute", + "persevere", + "persuaded", + "persuader", + "pesky", + "peso", + "pessimism", + "pessimist", + "pester", + "pesticide", + "petal", + "petite", + "petition", + "petri", + "petroleum", + "petted", + "petticoat", + "pettiness", + "petty", + "petunia", + "phantom", + "phobia", + "phoenix", + "phonebook", + "phoney", + "phonics", + "phoniness", + "phony", + "phosphate", + "photo", + "phrase", + "phrasing", + "placard", + "placate", + "placidly", + "plank", + "planner", + "plant", + "plasma", + "plaster", + "plastic", + "plated", + "platform", + "plating", + "platinum", + "platonic", + "platter", + "platypus", + "plausible", + "plausibly", + "playable", + "playback", + "player", + "playful", + "playgroup", + "playhouse", + "playing", + "playlist", + "playmaker", + "playmate", + "playoff", + "playpen", + "playroom", + "playset", + "plaything", + "playtime", + "plaza", + "pleading", + "pleat", + "pledge", + "plentiful", + "plenty", + "plethora", + "plexiglas", + "pliable", + "plod", + "plop", + "plot", + "plow", + "ploy", + "pluck", + "plug", + "plunder", + "plunging", + "plural", + "plus", + "plutonium", + "plywood", + "poach", + "pod", + "poem", + "poet", + "pogo", + "pointed", + "pointer", + "pointing", + "pointless", + "pointy", + "poise", + "poison", + "poker", + "poking", + "polar", + "police", + "policy", + "polio", + "polish", + "politely", + "polka", + "polo", + "polyester", + "polygon", + "polygraph", + "polymer", + "poncho", + "pond", + "pony", + "popcorn", + "pope", + "poplar", + "popper", + "poppy", + "popsicle", + "populace", + "popular", + "populate", + "porcupine", + "pork", + "porous", + "porridge", + "portable", + "portal", + "portfolio", + "porthole", + "portion", + "portly", + "portside", + "poser", + "posh", + "posing", + "possible", + "possibly", + "possum", + "postage", + "postal", + "postbox", + "postcard", + "posted", + "poster", + "posting", + "postnasal", + "posture", + "postwar", + "pouch", + "pounce", + "pouncing", + "pound", + "pouring", + "pout", + "powdered", + "powdering", + "powdery", + "power", + "powwow", + "pox", + "praising", + "prance", + "prancing", + "pranker", + "prankish", + "prankster", + "prayer", + "praying", + "preacher", + "preaching", + "preachy", + "preamble", + "precinct", + "precise", + "precision", + "precook", + "precut", + "predator", + "predefine", + "predict", + "preface", + "prefix", + "preflight", + "preformed", + "pregame", + "pregnancy", + "pregnant", + "preheated", + "prelaunch", + "prelaw", + "prelude", + "premiere", + "premises", + "premium", + "prenatal", + "preoccupy", + "preorder", + "prepaid", + "prepay", + "preplan", + "preppy", + "preschool", + "prescribe", + "preseason", + "preset", + "preshow", + "president", + "presoak", + "press", + "presume", + "presuming", + "preteen", + "pretended", + "pretender", + "pretense", + "pretext", + "pretty", + "pretzel", + "prevail", + "prevalent", + "prevent", + "preview", + "previous", + "prewar", + "prewashed", + "prideful", + "pried", + "primal", + "primarily", + "primary", + "primate", + "primer", + "primp", + "princess", + "print", + "prior", + "prism", + "prison", + "prissy", + "pristine", + "privacy", + "private", + "privatize", + "prize", + "proactive", + "probable", + "probably", + "probation", + "probe", + "probing", + "probiotic", + "problem", + "procedure", + "process", + "proclaim", + "procreate", + "procurer", + "prodigal", + "prodigy", + "produce", + "product", + "profane", + "profanity", + "professed", + "professor", + "profile", + "profound", + "profusely", + "progeny", + "prognosis", + "program", + "progress", + "projector", + "prologue", + "prolonged", + "promenade", + "prominent", + "promoter", + "promotion", + "prompter", + "promptly", + "prone", + "prong", + "pronounce", + "pronto", + "proofing", + "proofread", + "proofs", + "propeller", + "properly", + "property", + "proponent", + "proposal", + "propose", + "props", + "prorate", + "protector", + "protegee", + "proton", + "prototype", + "protozoan", + "protract", + "protrude", + "proud", + "provable", + "proved", + "proven", + "provided", + "provider", + "providing", + "province", + "proving", + "provoke", + "provoking", + "provolone", + "prowess", + "prowler", + "prowling", + "proximity", + "proxy", + "prozac", + "prude", + "prudishly", + "prune", + "pruning", + "pry", + "psychic", + "public", + "publisher", + "pucker", + "pueblo", + "pug", + "pull", + "pulmonary", + "pulp", + "pulsate", + "pulse", + "pulverize", + "puma", + "pumice", + "pummel", + "punch", + "punctual", + "punctuate", + "punctured", + "pungent", + "punisher", + "punk", + "pupil", + "puppet", + "puppy", + "purchase", + "pureblood", + "purebred", + "purely", + "pureness", + "purgatory", + "purge", + "purging", + "purifier", + "purify", + "purist", + "puritan", + "purity", + "purple", + "purplish", + "purposely", + "purr", + "purse", + "pursuable", + "pursuant", + "pursuit", + "purveyor", + "pushcart", + "pushchair", + "pusher", + "pushiness", + "pushing", + "pushover", + "pushpin", + "pushup", + "pushy", + "putdown", + "putt", + "puzzle", + "puzzling", + "pyramid", + "pyromania", + "python", + "quack", + "quadrant", + "quail", + "quaintly", + "quake", + "quaking", + "qualified", + "qualifier", + "qualify", + "quality", + "qualm", + "quantum", + "quarrel", + "quarry", + "quartered", + "quarterly", + "quarters", + "quartet", + "quench", + "query", + "quicken", + "quickly", + "quickness", + "quicksand", + "quickstep", + "quiet", + "quill", + "quilt", + "quintet", + "quintuple", + "quirk", + "quit", + "quiver", + "quizzical", + "quotable", + "quotation", + "quote", + "rabid", + "race", + "racing", + "racism", + "rack", + "racoon", + "radar", + "radial", + "radiance", + "radiantly", + "radiated", + "radiation", + "radiator", + "radio", + "radish", + "raffle", + "raft", + "rage", + "ragged", + "raging", + "ragweed", + "raider", + "railcar", + "railing", + "railroad", + "railway", + "raisin", + "rake", + "raking", + "rally", + "ramble", + "rambling", + "ramp", + "ramrod", + "ranch", + "rancidity", + "random", + "ranged", + "ranger", + "ranging", + "ranked", + "ranking", + "ransack", + "ranting", + "rants", + "rare", + "rarity", + "rascal", + "rash", + "rasping", + "ravage", + "raven", + "ravine", + "raving", + "ravioli", + "ravishing", + "reabsorb", + "reach", + "reacquire", + "reaction", + "reactive", + "reactor", + "reaffirm", + "ream", + "reanalyze", + "reappear", + "reapply", + "reappoint", + "reapprove", + "rearrange", + "rearview", + "reason", + "reassign", + "reassure", + "reattach", + "reawake", + "rebalance", + "rebate", + "rebel", + "rebirth", + "reboot", + "reborn", + "rebound", + "rebuff", + "rebuild", + "rebuilt", + "reburial", + "rebuttal", + "recall", + "recant", + "recapture", + "recast", + "recede", + "recent", + "recess", + "recharger", + "recipient", + "recital", + "recite", + "reckless", + "reclaim", + "recliner", + "reclining", + "recluse", + "reclusive", + "recognize", + "recoil", + "recollect", + "recolor", + "reconcile", + "reconfirm", + "reconvene", + "recopy", + "record", + "recount", + "recoup", + "recovery", + "recreate", + "rectal", + "rectangle", + "rectified", + "rectify", + "recycled", + "recycler", + "recycling", + "reemerge", + "reenact", + "reenter", + "reentry", + "reexamine", + "referable", + "referee", + "reference", + "refill", + "refinance", + "refined", + "refinery", + "refining", + "refinish", + "reflected", + "reflector", + "reflex", + "reflux", + "refocus", + "refold", + "reforest", + "reformat", + "reformed", + "reformer", + "reformist", + "refract", + "refrain", + "refreeze", + "refresh", + "refried", + "refueling", + "refund", + "refurbish", + "refurnish", + "refusal", + "refuse", + "refusing", + "refutable", + "refute", + "regain", + "regalia", + "regally", + "reggae", + "regime", + "region", + "register", + "registrar", + "registry", + "regress", + "regretful", + "regroup", + "regular", + "regulate", + "regulator", + "rehab", + "reheat", + "rehire", + "rehydrate", + "reimburse", + "reissue", + "reiterate", + "rejoice", + "rejoicing", + "rejoin", + "rekindle", + "relapse", + "relapsing", + "relatable", + "related", + "relation", + "relative", + "relax", + "relay", + "relearn", + "release", + "relenting", + "reliable", + "reliably", + "reliance", + "reliant", + "relic", + "relieve", + "relieving", + "relight", + "relish", + "relive", + "reload", + "relocate", + "relock", + "reluctant", + "rely", + "remake", + "remark", + "remarry", + "rematch", + "remedial", + "remedy", + "remember", + "reminder", + "remindful", + "remission", + "remix", + "remnant", + "remodeler", + "remold", + "remorse", + "remote", + "removable", + "removal", + "removed", + "remover", + "removing", + "rename", + "renderer", + "rendering", + "rendition", + "renegade", + "renewable", + "renewably", + "renewal", + "renewed", + "renounce", + "renovate", + "renovator", + "rentable", + "rental", + "rented", + "renter", + "reoccupy", + "reoccur", + "reopen", + "reorder", + "repackage", + "repacking", + "repaint", + "repair", + "repave", + "repaying", + "repayment", + "repeal", + "repeated", + "repeater", + "repent", + "rephrase", + "replace", + "replay", + "replica", + "reply", + "reporter", + "repose", + "repossess", + "repost", + "repressed", + "reprimand", + "reprint", + "reprise", + "reproach", + "reprocess", + "reproduce", + "reprogram", + "reps", + "reptile", + "reptilian", + "repugnant", + "repulsion", + "repulsive", + "repurpose", + "reputable", + "reputably", + "request", + "require", + "requisite", + "reroute", + "rerun", + "resale", + "resample", + "rescuer", + "reseal", + "research", + "reselect", + "reseller", + "resemble", + "resend", + "resent", + "reset", + "reshape", + "reshoot", + "reshuffle", + "residence", + "residency", + "resident", + "residual", + "residue", + "resigned", + "resilient", + "resistant", + "resisting", + "resize", + "resolute", + "resolved", + "resonant", + "resonate", + "resort", + "resource", + "respect", + "resubmit", + "result", + "resume", + "resupply", + "resurface", + "resurrect", + "retail", + "retainer", + "retaining", + "retake", + "retaliate", + "retention", + "rethink", + "retinal", + "retired", + "retiree", + "retiring", + "retold", + "retool", + "retorted", + "retouch", + "retrace", + "retract", + "retrain", + "retread", + "retreat", + "retrial", + "retrieval", + "retriever", + "retry", + "return", + "retying", + "retype", + "reunion", + "reunite", + "reusable", + "reuse", + "reveal", + "reveler", + "revenge", + "revenue", + "reverb", + "revered", + "reverence", + "reverend", + "reversal", + "reverse", + "reversing", + "reversion", + "revert", + "revisable", + "revise", + "revision", + "revisit", + "revivable", + "revival", + "reviver", + "reviving", + "revocable", + "revoke", + "revolt", + "revolver", + "revolving", + "reward", + "rewash", + "rewind", + "rewire", + "reword", + "rework", + "rewrap", + "rewrite", + "rhyme", + "ribbon", + "ribcage", + "rice", + "riches", + "richly", + "richness", + "rickety", + "ricotta", + "riddance", + "ridden", + "ride", + "riding", + "rifling", + "rift", + "rigging", + "rigid", + "rigor", + "rimless", + "rimmed", + "rind", + "rink", + "rinse", + "rinsing", + "riot", + "ripcord", + "ripeness", + "ripening", + "ripping", + "ripple", + "rippling", + "riptide", + "rise", + "rising", + "risk", + "risotto", + "ritalin", + "ritzy", + "rival", + "riverbank", + "riverbed", + "riverboat", + "riverside", + "riveter", + "riveting", + "roamer", + "roaming", + "roast", + "robbing", + "robe", + "robin", + "robotics", + "robust", + "rockband", + "rocker", + "rocket", + "rockfish", + "rockiness", + "rocking", + "rocklike", + "rockslide", + "rockstar", + "rocky", + "rogue", + "roman", + "romp", + "rope", + "roping", + "roster", + "rosy", + "rotten", + "rotting", + "rotunda", + "roulette", + "rounding", + "roundish", + "roundness", + "roundup", + "roundworm", + "routine", + "routing", + "rover", + "roving", + "royal", + "rubbed", + "rubber", + "rubbing", + "rubble", + "rubdown", + "ruby", + "ruckus", + "rudder", + "rug", + "ruined", + "rule", + "rumble", + "rumbling", + "rummage", + "rumor", + "runaround", + "rundown", + "runner", + "running", + "runny", + "runt", + "runway", + "rupture", + "rural", + "ruse", + "rush", + "rust", + "rut", + "sabbath", + "sabotage", + "sacrament", + "sacred", + "sacrifice", + "sadden", + "saddlebag", + "saddled", + "saddling", + "sadly", + "sadness", + "safari", + "safeguard", + "safehouse", + "safely", + "safeness", + "saffron", + "saga", + "sage", + "sagging", + "saggy", + "said", + "saint", + "sake", + "salad", + "salami", + "salaried", + "salary", + "saline", + "salon", + "saloon", + "salsa", + "salt", + "salutary", + "salute", + "salvage", + "salvaging", + "salvation", + "same", + "sample", + "sampling", + "sanction", + "sanctity", + "sanctuary", + "sandal", + "sandbag", + "sandbank", + "sandbar", + "sandblast", + "sandbox", + "sanded", + "sandfish", + "sanding", + "sandlot", + "sandpaper", + "sandpit", + "sandstone", + "sandstorm", + "sandworm", + "sandy", + "sanitary", + "sanitizer", + "sank", + "santa", + "sapling", + "sappiness", + "sappy", + "sarcasm", + "sarcastic", + "sardine", + "sash", + "sasquatch", + "sassy", + "satchel", + "satiable", + "satin", + "satirical", + "satisfied", + "satisfy", + "saturate", + "saturday", + "sauciness", + "saucy", + "sauna", + "savage", + "savanna", + "saved", + "savings", + "savior", + "savor", + "saxophone", + "say", + "scabbed", + "scabby", + "scalded", + "scalding", + "scale", + "scaling", + "scallion", + "scallop", + "scalping", + "scam", + "scandal", + "scanner", + "scanning", + "scant", + "scapegoat", + "scarce", + "scarcity", + "scarecrow", + "scared", + "scarf", + "scarily", + "scariness", + "scarring", + "scary", + "scavenger", + "scenic", + "schedule", + "schematic", + "scheme", + "scheming", + "schilling", + "schnapps", + "scholar", + "science", + "scientist", + "scion", + "scoff", + "scolding", + "scone", + "scoop", + "scooter", + "scope", + "scorch", + "scorebook", + "scorecard", + "scored", + "scoreless", + "scorer", + "scoring", + "scorn", + "scorpion", + "scotch", + "scoundrel", + "scoured", + "scouring", + "scouting", + "scouts", + "scowling", + "scrabble", + "scraggly", + "scrambled", + "scrambler", + "scrap", + "scratch", + "scrawny", + "screen", + "scribble", + "scribe", + "scribing", + "scrimmage", + "script", + "scroll", + "scrooge", + "scrounger", + "scrubbed", + "scrubber", + "scruffy", + "scrunch", + "scrutiny", + "scuba", + "scuff", + "sculptor", + "sculpture", + "scurvy", + "scuttle", + "secluded", + "secluding", + "seclusion", + "second", + "secrecy", + "secret", + "sectional", + "sector", + "secular", + "securely", + "security", + "sedan", + "sedate", + "sedation", + "sedative", + "sediment", + "seduce", + "seducing", + "segment", + "seismic", + "seizing", + "seldom", + "selected", + "selection", + "selective", + "selector", + "self", + "seltzer", + "semantic", + "semester", + "semicolon", + "semifinal", + "seminar", + "semisoft", + "semisweet", + "senate", + "senator", + "send", + "senior", + "senorita", + "sensation", + "sensitive", + "sensitize", + "sensually", + "sensuous", + "sepia", + "september", + "septic", + "septum", + "sequel", + "sequence", + "sequester", + "series", + "sermon", + "serotonin", + "serpent", + "serrated", + "serve", + "service", + "serving", + "sesame", + "sessions", + "setback", + "setting", + "settle", + "settling", + "setup", + "sevenfold", + "seventeen", + "seventh", + "seventy", + "severity", + "shabby", + "shack", + "shaded", + "shadily", + "shadiness", + "shading", + "shadow", + "shady", + "shaft", + "shakable", + "shakily", + "shakiness", + "shaking", + "shaky", + "shale", + "shallot", + "shallow", + "shame", + "shampoo", + "shamrock", + "shank", + "shanty", + "shape", + "shaping", + "share", + "sharpener", + "sharper", + "sharpie", + "sharply", + "sharpness", + "shawl", + "sheath", + "shed", + "sheep", + "sheet", + "shelf", + "shell", + "shelter", + "shelve", + "shelving", + "sherry", + "shield", + "shifter", + "shifting", + "shiftless", + "shifty", + "shimmer", + "shimmy", + "shindig", + "shine", + "shingle", + "shininess", + "shining", + "shiny", + "ship", + "shirt", + "shivering", + "shock", + "shone", + "shoplift", + "shopper", + "shopping", + "shoptalk", + "shore", + "shortage", + "shortcake", + "shortcut", + "shorten", + "shorter", + "shorthand", + "shortlist", + "shortly", + "shortness", + "shorts", + "shortwave", + "shorty", + "shout", + "shove", + "showbiz", + "showcase", + "showdown", + "shower", + "showgirl", + "showing", + "showman", + "shown", + "showoff", + "showpiece", + "showplace", + "showroom", + "showy", + "shrank", + "shrapnel", + "shredder", + "shredding", + "shrewdly", + "shriek", + "shrill", + "shrimp", + "shrine", + "shrink", + "shrivel", + "shrouded", + "shrubbery", + "shrubs", + "shrug", + "shrunk", + "shucking", + "shudder", + "shuffle", + "shuffling", + "shun", + "shush", + "shut", + "shy", + "siamese", + "siberian", + "sibling", + "siding", + "sierra", + "siesta", + "sift", + "sighing", + "silenced", + "silencer", + "silent", + "silica", + "silicon", + "silk", + "silliness", + "silly", + "silo", + "silt", + "silver", + "similarly", + "simile", + "simmering", + "simple", + "simplify", + "simply", + "sincere", + "sincerity", + "singer", + "singing", + "single", + "singular", + "sinister", + "sinless", + "sinner", + "sinuous", + "sip", + "siren", + "sister", + "sitcom", + "sitter", + "sitting", + "situated", + "situation", + "sixfold", + "sixteen", + "sixth", + "sixties", + "sixtieth", + "sixtyfold", + "sizable", + "sizably", + "size", + "sizing", + "sizzle", + "sizzling", + "skater", + "skating", + "skedaddle", + "skeletal", + "skeleton", + "skeptic", + "sketch", + "skewed", + "skewer", + "skid", + "skied", + "skier", + "skies", + "skiing", + "skilled", + "skillet", + "skillful", + "skimmed", + "skimmer", + "skimming", + "skimpily", + "skincare", + "skinhead", + "skinless", + "skinning", + "skinny", + "skintight", + "skipper", + "skipping", + "skirmish", + "skirt", + "skittle", + "skydiver", + "skylight", + "skyline", + "skype", + "skyrocket", + "skyward", + "slab", + "slacked", + "slacker", + "slacking", + "slackness", + "slacks", + "slain", + "slam", + "slander", + "slang", + "slapping", + "slapstick", + "slashed", + "slashing", + "slate", + "slather", + "slaw", + "sled", + "sleek", + "sleep", + "sleet", + "sleeve", + "slept", + "sliceable", + "sliced", + "slicer", + "slicing", + "slick", + "slider", + "slideshow", + "sliding", + "slighted", + "slighting", + "slightly", + "slimness", + "slimy", + "slinging", + "slingshot", + "slinky", + "slip", + "slit", + "sliver", + "slobbery", + "slogan", + "sloped", + "sloping", + "sloppily", + "sloppy", + "slot", + "slouching", + "slouchy", + "sludge", + "slug", + "slum", + "slurp", + "slush", + "sly", + "small", + "smartly", + "smartness", + "smasher", + "smashing", + "smashup", + "smell", + "smelting", + "smile", + "smilingly", + "smirk", + "smite", + "smith", + "smitten", + "smock", + "smog", + "smoked", + "smokeless", + "smokiness", + "smoking", + "smoky", + "smolder", + "smooth", + "smother", + "smudge", + "smudgy", + "smuggler", + "smuggling", + "smugly", + "smugness", + "snack", + "snagged", + "snaking", + "snap", + "snare", + "snarl", + "snazzy", + "sneak", + "sneer", + "sneeze", + "sneezing", + "snide", + "sniff", + "snippet", + "snipping", + "snitch", + "snooper", + "snooze", + "snore", + "snoring", + "snorkel", + "snort", + "snout", + "snowbird", + "snowboard", + "snowbound", + "snowcap", + "snowdrift", + "snowdrop", + "snowfall", + "snowfield", + "snowflake", + "snowiness", + "snowless", + "snowman", + "snowplow", + "snowshoe", + "snowstorm", + "snowsuit", + "snowy", + "snub", + "snuff", + "snuggle", + "snugly", + "snugness", + "speak", + "spearfish", + "spearhead", + "spearman", + "spearmint", + "species", + "specimen", + "specked", + "speckled", + "specks", + "spectacle", + "spectator", + "spectrum", + "speculate", + "speech", + "speed", + "spellbind", + "speller", + "spelling", + "spendable", + "spender", + "spending", + "spent", + "spew", + "sphere", + "spherical", + "sphinx", + "spider", + "spied", + "spiffy", + "spill", + "spilt", + "spinach", + "spinal", + "spindle", + "spinner", + "spinning", + "spinout", + "spinster", + "spiny", + "spiral", + "spirited", + "spiritism", + "spirits", + "spiritual", + "splashed", + "splashing", + "splashy", + "splatter", + "spleen", + "splendid", + "splendor", + "splice", + "splicing", + "splinter", + "splotchy", + "splurge", + "spoilage", + "spoiled", + "spoiler", + "spoiling", + "spoils", + "spoken", + "spokesman", + "sponge", + "spongy", + "sponsor", + "spoof", + "spookily", + "spooky", + "spool", + "spoon", + "spore", + "sporting", + "sports", + "sporty", + "spotless", + "spotlight", + "spotted", + "spotter", + "spotting", + "spotty", + "spousal", + "spouse", + "spout", + "sprain", + "sprang", + "sprawl", + "spray", + "spree", + "sprig", + "spring", + "sprinkled", + "sprinkler", + "sprint", + "sprite", + "sprout", + "spruce", + "sprung", + "spry", + "spud", + "spur", + "sputter", + "spyglass", + "squabble", + "squad", + "squall", + "squander", + "squash", + "squatted", + "squatter", + "squatting", + "squeak", + "squealer", + "squealing", + "squeamish", + "squeegee", + "squeeze", + "squeezing", + "squid", + "squiggle", + "squiggly", + "squint", + "squire", + "squirt", + "squishier", + "squishy", + "stability", + "stabilize", + "stable", + "stack", + "stadium", + "staff", + "stage", + "staging", + "stagnant", + "stagnate", + "stainable", + "stained", + "staining", + "stainless", + "stalemate", + "staleness", + "stalling", + "stallion", + "stamina", + "stammer", + "stamp", + "stand", + "stank", + "staple", + "stapling", + "starboard", + "starch", + "stardom", + "stardust", + "starfish", + "stargazer", + "staring", + "stark", + "starless", + "starlet", + "starlight", + "starlit", + "starring", + "starry", + "starship", + "starter", + "starting", + "startle", + "startling", + "startup", + "starved", + "starving", + "stash", + "state", + "static", + "statistic", + "statue", + "stature", + "status", + "statute", + "statutory", + "staunch", + "stays", + "steadfast", + "steadier", + "steadily", + "steadying", + "steam", + "steed", + "steep", + "steerable", + "steering", + "steersman", + "stegosaur", + "stellar", + "stem", + "stench", + "stencil", + "step", + "stereo", + "sterile", + "sterility", + "sterilize", + "sterling", + "sternness", + "sternum", + "stew", + "stick", + "stiffen", + "stiffly", + "stiffness", + "stifle", + "stifling", + "stillness", + "stilt", + "stimulant", + "stimulate", + "stimuli", + "stimulus", + "stinger", + "stingily", + "stinging", + "stingray", + "stingy", + "stinking", + "stinky", + "stipend", + "stipulate", + "stir", + "stitch", + "stock", + "stoic", + "stoke", + "stole", + "stomp", + "stonewall", + "stoneware", + "stonework", + "stoning", + "stony", + "stood", + "stooge", + "stool", + "stoop", + "stoplight", + "stoppable", + "stoppage", + "stopped", + "stopper", + "stopping", + "stopwatch", + "storable", + "storage", + "storeroom", + "storewide", + "storm", + "stout", + "stove", + "stowaway", + "stowing", + "straddle", + "straggler", + "strained", + "strainer", + "straining", + "strangely", + "stranger", + "strangle", + "strategic", + "strategy", + "stratus", + "straw", + "stray", + "streak", + "stream", + "street", + "strength", + "strenuous", + "strep", + "stress", + "stretch", + "strewn", + "stricken", + "strict", + "stride", + "strife", + "strike", + "striking", + "strive", + "striving", + "strobe", + "strode", + "stroller", + "strongbox", + "strongly", + "strongman", + "struck", + "structure", + "strudel", + "struggle", + "strum", + "strung", + "strut", + "stubbed", + "stubble", + "stubbly", + "stubborn", + "stucco", + "stuck", + "student", + "studied", + "studio", + "study", + "stuffed", + "stuffing", + "stuffy", + "stumble", + "stumbling", + "stump", + "stung", + "stunned", + "stunner", + "stunning", + "stunt", + "stupor", + "sturdily", + "sturdy", + "styling", + "stylishly", + "stylist", + "stylized", + "stylus", + "suave", + "subarctic", + "subatomic", + "subdivide", + "subdued", + "subduing", + "subfloor", + "subgroup", + "subheader", + "subject", + "sublease", + "sublet", + "sublevel", + "sublime", + "submarine", + "submerge", + "submersed", + "submitter", + "subpanel", + "subpar", + "subplot", + "subprime", + "subscribe", + "subscript", + "subsector", + "subside", + "subsiding", + "subsidize", + "subsidy", + "subsoil", + "subsonic", + "substance", + "subsystem", + "subtext", + "subtitle", + "subtly", + "subtotal", + "subtract", + "subtype", + "suburb", + "subway", + "subwoofer", + "subzero", + "succulent", + "such", + "suction", + "sudden", + "sudoku", + "suds", + "sufferer", + "suffering", + "suffice", + "suffix", + "suffocate", + "suffrage", + "sugar", + "suggest", + "suing", + "suitable", + "suitably", + "suitcase", + "suitor", + "sulfate", + "sulfide", + "sulfite", + "sulfur", + "sulk", + "sullen", + "sulphate", + "sulphuric", + "sultry", + "superbowl", + "superglue", + "superhero", + "superior", + "superjet", + "superman", + "supermom", + "supernova", + "supervise", + "supper", + "supplier", + "supply", + "support", + "supremacy", + "supreme", + "surcharge", + "surely", + "sureness", + "surface", + "surfacing", + "surfboard", + "surfer", + "surgery", + "surgical", + "surging", + "surname", + "surpass", + "surplus", + "surprise", + "surreal", + "surrender", + "surrogate", + "surround", + "survey", + "survival", + "survive", + "surviving", + "survivor", + "sushi", + "suspect", + "suspend", + "suspense", + "sustained", + "sustainer", + "swab", + "swaddling", + "swagger", + "swampland", + "swan", + "swapping", + "swarm", + "sway", + "swear", + "sweat", + "sweep", + "swell", + "swept", + "swerve", + "swifter", + "swiftly", + "swiftness", + "swimmable", + "swimmer", + "swimming", + "swimsuit", + "swimwear", + "swinger", + "swinging", + "swipe", + "swirl", + "switch", + "swivel", + "swizzle", + "swooned", + "swoop", + "swoosh", + "swore", + "sworn", + "swung", + "sycamore", + "sympathy", + "symphonic", + "symphony", + "symptom", + "synapse", + "syndrome", + "synergy", + "synopses", + "synopsis", + "synthesis", + "synthetic", + "syrup", + "system", + "t-shirt", + "tabasco", + "tabby", + "tableful", + "tables", + "tablet", + "tableware", + "tabloid", + "tackiness", + "tacking", + "tackle", + "tackling", + "tacky", + "taco", + "tactful", + "tactical", + "tactics", + "tactile", + "tactless", + "tadpole", + "taekwondo", + "tag", + "tainted", + "take", + "taking", + "talcum", + "talisman", + "tall", + "talon", + "tamale", + "tameness", + "tamer", + "tamper", + "tank", + "tanned", + "tannery", + "tanning", + "tantrum", + "tapeless", + "tapered", + "tapering", + "tapestry", + "tapioca", + "tapping", + "taps", + "tarantula", + "target", + "tarmac", + "tarnish", + "tarot", + "tartar", + "tartly", + "tartness", + "task", + "tassel", + "taste", + "tastiness", + "tasting", + "tasty", + "tattered", + "tattle", + "tattling", + "tattoo", + "taunt", + "tavern", + "thank", + "that", + "thaw", + "theater", + "theatrics", + "thee", + "theft", + "theme", + "theology", + "theorize", + "thermal", + "thermos", + "thesaurus", + "these", + "thesis", + "thespian", + "thicken", + "thicket", + "thickness", + "thieving", + "thievish", + "thigh", + "thimble", + "thing", + "think", + "thinly", + "thinner", + "thinness", + "thinning", + "thirstily", + "thirsting", + "thirsty", + "thirteen", + "thirty", + "thong", + "thorn", + "those", + "thousand", + "thrash", + "thread", + "threaten", + "threefold", + "thrift", + "thrill", + "thrive", + "thriving", + "throat", + "throbbing", + "throng", + "throttle", + "throwaway", + "throwback", + "thrower", + "throwing", + "thud", + "thumb", + "thumping", + "thursday", + "thus", + "thwarting", + "thyself", + "tiara", + "tibia", + "tidal", + "tidbit", + "tidiness", + "tidings", + "tidy", + "tiger", + "tighten", + "tightly", + "tightness", + "tightrope", + "tightwad", + "tigress", + "tile", + "tiling", + "till", + "tilt", + "timid", + "timing", + "timothy", + "tinderbox", + "tinfoil", + "tingle", + "tingling", + "tingly", + "tinker", + "tinkling", + "tinsel", + "tinsmith", + "tint", + "tinwork", + "tiny", + "tipoff", + "tipped", + "tipper", + "tipping", + "tiptoeing", + "tiptop", + "tiring", + "tissue", + "trace", + "tracing", + "track", + "traction", + "tractor", + "trade", + "trading", + "tradition", + "traffic", + "tragedy", + "trailing", + "trailside", + "train", + "traitor", + "trance", + "tranquil", + "transfer", + "transform", + "translate", + "transpire", + "transport", + "transpose", + "trapdoor", + "trapeze", + "trapezoid", + "trapped", + "trapper", + "trapping", + "traps", + "trash", + "travel", + "traverse", + "travesty", + "tray", + "treachery", + "treading", + "treadmill", + "treason", + "treat", + "treble", + "tree", + "trekker", + "tremble", + "trembling", + "tremor", + "trench", + "trend", + "trespass", + "triage", + "trial", + "triangle", + "tribesman", + "tribunal", + "tribune", + "tributary", + "tribute", + "triceps", + "trickery", + "trickily", + "tricking", + "trickle", + "trickster", + "tricky", + "tricolor", + "tricycle", + "trident", + "tried", + "trifle", + "trifocals", + "trillion", + "trilogy", + "trimester", + "trimmer", + "trimming", + "trimness", + "trinity", + "trio", + "tripod", + "tripping", + "triumph", + "trivial", + "trodden", + "trolling", + "trombone", + "trophy", + "tropical", + "tropics", + "trouble", + "troubling", + "trough", + "trousers", + "trout", + "trowel", + "truce", + "truck", + "truffle", + "trump", + "trunks", + "trustable", + "trustee", + "trustful", + "trusting", + "trustless", + "truth", + "try", + "tubby", + "tubeless", + "tubular", + "tucking", + "tuesday", + "tug", + "tuition", + "tulip", + "tumble", + "tumbling", + "tummy", + "turban", + "turbine", + "turbofan", + "turbojet", + "turbulent", + "turf", + "turkey", + "turmoil", + "turret", + "turtle", + "tusk", + "tutor", + "tutu", + "tux", + "tweak", + "tweed", + "tweet", + "tweezers", + "twelve", + "twentieth", + "twenty", + "twerp", + "twice", + "twiddle", + "twiddling", + "twig", + "twilight", + "twine", + "twins", + "twirl", + "twistable", + "twisted", + "twister", + "twisting", + "twisty", + "twitch", + "twitter", + "tycoon", + "tying", + "tyke", + "udder", + "ultimate", + "ultimatum", + "ultra", + "umbilical", + "umbrella", + "umpire", + "unabashed", + "unable", + "unadorned", + "unadvised", + "unafraid", + "unaired", + "unaligned", + "unaltered", + "unarmored", + "unashamed", + "unaudited", + "unawake", + "unaware", + "unbaked", + "unbalance", + "unbeaten", + "unbend", + "unbent", + "unbiased", + "unbitten", + "unblended", + "unblessed", + "unblock", + "unbolted", + "unbounded", + "unboxed", + "unbraided", + "unbridle", + "unbroken", + "unbuckled", + "unbundle", + "unburned", + "unbutton", + "uncanny", + "uncapped", + "uncaring", + "uncertain", + "unchain", + "unchanged", + "uncharted", + "uncheck", + "uncivil", + "unclad", + "unclaimed", + "unclamped", + "unclasp", + "uncle", + "unclip", + "uncloak", + "unclog", + "unclothed", + "uncoated", + "uncoiled", + "uncolored", + "uncombed", + "uncommon", + "uncooked", + "uncork", + "uncorrupt", + "uncounted", + "uncouple", + "uncouth", + "uncover", + "uncross", + "uncrown", + "uncrushed", + "uncured", + "uncurious", + "uncurled", + "uncut", + "undamaged", + "undated", + "undaunted", + "undead", + "undecided", + "undefined", + "underage", + "underarm", + "undercoat", + "undercook", + "undercut", + "underdog", + "underdone", + "underfed", + "underfeed", + "underfoot", + "undergo", + "undergrad", + "underhand", + "underline", + "underling", + "undermine", + "undermost", + "underpaid", + "underpass", + "underpay", + "underrate", + "undertake", + "undertone", + "undertook", + "undertow", + "underuse", + "underwear", + "underwent", + "underwire", + "undesired", + "undiluted", + "undivided", + "undocked", + "undoing", + "undone", + "undrafted", + "undress", + "undrilled", + "undusted", + "undying", + "unearned", + "unearth", + "unease", + "uneasily", + "uneasy", + "uneatable", + "uneaten", + "unedited", + "unelected", + "unending", + "unengaged", + "unenvied", + "unequal", + "unethical", + "uneven", + "unexpired", + "unexposed", + "unfailing", + "unfair", + "unfasten", + "unfazed", + "unfeeling", + "unfiled", + "unfilled", + "unfitted", + "unfitting", + "unfixable", + "unfixed", + "unflawed", + "unfocused", + "unfold", + "unfounded", + "unframed", + "unfreeze", + "unfrosted", + "unfrozen", + "unfunded", + "unglazed", + "ungloved", + "unglue", + "ungodly", + "ungraded", + "ungreased", + "unguarded", + "unguided", + "unhappily", + "unhappy", + "unharmed", + "unhealthy", + "unheard", + "unhearing", + "unheated", + "unhelpful", + "unhidden", + "unhinge", + "unhitched", + "unholy", + "unhook", + "unicorn", + "unicycle", + "unified", + "unifier", + "uniformed", + "uniformly", + "unify", + "unimpeded", + "uninjured", + "uninstall", + "uninsured", + "uninvited", + "union", + "uniquely", + "unisexual", + "unison", + "unissued", + "unit", + "universal", + "universe", + "unjustly", + "unkempt", + "unkind", + "unknotted", + "unknowing", + "unknown", + "unlaced", + "unlatch", + "unlawful", + "unleaded", + "unlearned", + "unleash", + "unless", + "unleveled", + "unlighted", + "unlikable", + "unlimited", + "unlined", + "unlinked", + "unlisted", + "unlit", + "unlivable", + "unloaded", + "unloader", + "unlocked", + "unlocking", + "unlovable", + "unloved", + "unlovely", + "unloving", + "unluckily", + "unlucky", + "unmade", + "unmanaged", + "unmanned", + "unmapped", + "unmarked", + "unmasked", + "unmasking", + "unmatched", + "unmindful", + "unmixable", + "unmixed", + "unmolded", + "unmoral", + "unmovable", + "unmoved", + "unmoving", + "unnamable", + "unnamed", + "unnatural", + "unneeded", + "unnerve", + "unnerving", + "unnoticed", + "unopened", + "unopposed", + "unpack", + "unpadded", + "unpaid", + "unpainted", + "unpaired", + "unpaved", + "unpeeled", + "unpicked", + "unpiloted", + "unpinned", + "unplanned", + "unplanted", + "unpleased", + "unpledged", + "unplowed", + "unplug", + "unpopular", + "unproven", + "unquote", + "unranked", + "unrated", + "unraveled", + "unreached", + "unread", + "unreal", + "unreeling", + "unrefined", + "unrelated", + "unrented", + "unrest", + "unretired", + "unrevised", + "unrigged", + "unripe", + "unrivaled", + "unroasted", + "unrobed", + "unroll", + "unruffled", + "unruly", + "unrushed", + "unsaddle", + "unsafe", + "unsaid", + "unsalted", + "unsaved", + "unsavory", + "unscathed", + "unscented", + "unscrew", + "unsealed", + "unseated", + "unsecured", + "unseeing", + "unseemly", + "unseen", + "unselect", + "unselfish", + "unsent", + "unsettled", + "unshackle", + "unshaken", + "unshaved", + "unshaven", + "unsheathe", + "unshipped", + "unsightly", + "unsigned", + "unskilled", + "unsliced", + "unsmooth", + "unsnap", + "unsocial", + "unsoiled", + "unsold", + "unsolved", + "unsorted", + "unspoiled", + "unspoken", + "unstable", + "unstaffed", + "unstamped", + "unsteady", + "unsterile", + "unstirred", + "unstitch", + "unstopped", + "unstuck", + "unstuffed", + "unstylish", + "unsubtle", + "unsubtly", + "unsuited", + "unsure", + "unsworn", + "untagged", + "untainted", + "untaken", + "untamed", + "untangled", + "untapped", + "untaxed", + "unthawed", + "unthread", + "untidy", + "untie", + "until", + "untimed", + "untimely", + "untitled", + "untoasted", + "untold", + "untouched", + "untracked", + "untrained", + "untreated", + "untried", + "untrimmed", + "untrue", + "untruth", + "unturned", + "untwist", + "untying", + "unusable", + "unused", + "unusual", + "unvalued", + "unvaried", + "unvarying", + "unveiled", + "unveiling", + "unvented", + "unviable", + "unvisited", + "unvocal", + "unwanted", + "unwarlike", + "unwary", + "unwashed", + "unwatched", + "unweave", + "unwed", + "unwelcome", + "unwell", + "unwieldy", + "unwilling", + "unwind", + "unwired", + "unwitting", + "unwomanly", + "unworldly", + "unworn", + "unworried", + "unworthy", + "unwound", + "unwoven", + "unwrapped", + "unwritten", + "unzip", + "upbeat", + "upchuck", + "upcoming", + "upcountry", + "update", + "upfront", + "upgrade", + "upheaval", + "upheld", + "uphill", + "uphold", + "uplifted", + "uplifting", + "upload", + "upon", + "upper", + "upright", + "uprising", + "upriver", + "uproar", + "uproot", + "upscale", + "upside", + "upstage", + "upstairs", + "upstart", + "upstate", + "upstream", + "upstroke", + "upswing", + "uptake", + "uptight", + "uptown", + "upturned", + "upward", + "upwind", + "uranium", + "urban", + "urchin", + "urethane", + "urgency", + "urgent", + "urging", + "urologist", + "urology", + "usable", + "usage", + "useable", + "used", + "uselessly", + "user", + "usher", + "usual", + "utensil", + "utility", + "utilize", + "utmost", + "utopia", + "utter", + "vacancy", + "vacant", + "vacate", + "vacation", + "vagabond", + "vagrancy", + "vagrantly", + "vaguely", + "vagueness", + "valiant", + "valid", + "valium", + "valley", + "valuables", + "value", + "vanilla", + "vanish", + "vanity", + "vanquish", + "vantage", + "vaporizer", + "variable", + "variably", + "varied", + "variety", + "various", + "varmint", + "varnish", + "varsity", + "varying", + "vascular", + "vaseline", + "vastly", + "vastness", + "veal", + "vegan", + "veggie", + "vehicular", + "velcro", + "velocity", + "velvet", + "vendetta", + "vending", + "vendor", + "veneering", + "vengeful", + "venomous", + "ventricle", + "venture", + "venue", + "venus", + "verbalize", + "verbally", + "verbose", + "verdict", + "verify", + "verse", + "version", + "versus", + "vertebrae", + "vertical", + "vertigo", + "very", + "vessel", + "vest", + "veteran", + "veto", + "vexingly", + "viability", + "viable", + "vibes", + "vice", + "vicinity", + "victory", + "video", + "viewable", + "viewer", + "viewing", + "viewless", + "viewpoint", + "vigorous", + "village", + "villain", + "vindicate", + "vineyard", + "vintage", + "violate", + "violation", + "violator", + "violet", + "violin", + "viper", + "viral", + "virtual", + "virtuous", + "virus", + "visa", + "viscosity", + "viscous", + "viselike", + "visible", + "visibly", + "vision", + "visiting", + "visitor", + "visor", + "vista", + "vitality", + "vitalize", + "vitally", + "vitamins", + "vivacious", + "vividly", + "vividness", + "vixen", + "vocalist", + "vocalize", + "vocally", + "vocation", + "voice", + "voicing", + "void", + "volatile", + "volley", + "voltage", + "volumes", + "voter", + "voting", + "voucher", + "vowed", + "vowel", + "voyage", + "wackiness", + "wad", + "wafer", + "waffle", + "waged", + "wager", + "wages", + "waggle", + "wagon", + "wake", + "waking", + "walk", + "walmart", + "walnut", + "walrus", + "waltz", + "wand", + "wannabe", + "wanted", + "wanting", + "wasabi", + "washable", + "washbasin", + "washboard", + "washbowl", + "washcloth", + "washday", + "washed", + "washer", + "washhouse", + "washing", + "washout", + "washroom", + "washstand", + "washtub", + "wasp", + "wasting", + "watch", + "water", + "waviness", + "waving", + "wavy", + "whacking", + "whacky", + "wham", + "wharf", + "wheat", + "whenever", + "whiff", + "whimsical", + "whinny", + "whiny", + "whisking", + "whoever", + "whole", + "whomever", + "whoopee", + "whooping", + "whoops", + "why", + "wick", + "widely", + "widen", + "widget", + "widow", + "width", + "wieldable", + "wielder", + "wife", + "wifi", + "wikipedia", + "wildcard", + "wildcat", + "wilder", + "wildfire", + "wildfowl", + "wildland", + "wildlife", + "wildly", + "wildness", + "willed", + "willfully", + "willing", + "willow", + "willpower", + "wilt", + "wimp", + "wince", + "wincing", + "wind", + "wing", + "winking", + "winner", + "winnings", + "winter", + "wipe", + "wired", + "wireless", + "wiring", + "wiry", + "wisdom", + "wise", + "wish", + "wisplike", + "wispy", + "wistful", + "wizard", + "wobble", + "wobbling", + "wobbly", + "wok", + "wolf", + "wolverine", + "womanhood", + "womankind", + "womanless", + "womanlike", + "womanly", + "womb", + "woof", + "wooing", + "wool", + "woozy", + "word", + "work", + "worried", + "worrier", + "worrisome", + "worry", + "worsening", + "worshiper", + "worst", + "wound", + "woven", + "wow", + "wrangle", + "wrath", + "wreath", + "wreckage", + "wrecker", + "wrecking", + "wrench", + "wriggle", + "wriggly", + "wrinkle", + "wrinkly", + "wrist", + "writing", + "written", + "wrongdoer", + "wronged", + "wrongful", + "wrongly", + "wrongness", + "wrought", + "xbox", + "xerox", + "yahoo", + "yam", + "yanking", + "yapping", + "yard", + "yarn", + "yeah", + "yearbook", + "yearling", + "yearly", + "yearning", + "yeast", + "yelling", + "yelp", + "yen", + "yesterday", + "yiddish", + "yield", + "yin", + "yippee", + "yo-yo", + "yodel", + "yoga", + "yogurt", + "yonder", + "yoyo", + "yummy", + "zap", + "zealous", + "zebra", + "zen", + "zeppelin", + "zero", + "zestfully", + "zesty", + "zigzagged", + "zipfile", + "zipping", + "zippy", + "zips", + "zit", + "zodiac", + "zombie", + "zone", + "zoning", + "zookeeper", + "zoologist", + "zoology", + "zoom", +]; diff --git a/libs/common/src/models/api/billingSyncConfigApi.ts b/libs/common/src/models/api/billingSyncConfigApi.ts new file mode 100644 index 0000000000..78af5bd342 --- /dev/null +++ b/libs/common/src/models/api/billingSyncConfigApi.ts @@ -0,0 +1,13 @@ +import { BaseResponse } from "../response/baseResponse"; + +export class BillingSyncConfigApi extends BaseResponse { + billingSyncKey: string; + + constructor(data: any) { + super(data); + if (data == null) { + return; + } + this.billingSyncKey = this.getResponseProperty("BillingSyncKey"); + } +} diff --git a/libs/common/src/models/api/cardApi.ts b/libs/common/src/models/api/cardApi.ts new file mode 100644 index 0000000000..8d972624d4 --- /dev/null +++ b/libs/common/src/models/api/cardApi.ts @@ -0,0 +1,23 @@ +import { BaseResponse } from "../response/baseResponse"; + +export class CardApi extends BaseResponse { + cardholderName: string; + brand: string; + number: string; + expMonth: string; + expYear: string; + code: string; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.cardholderName = this.getResponseProperty("CardholderName"); + this.brand = this.getResponseProperty("Brand"); + this.number = this.getResponseProperty("Number"); + this.expMonth = this.getResponseProperty("ExpMonth"); + this.expYear = this.getResponseProperty("ExpYear"); + this.code = this.getResponseProperty("Code"); + } +} diff --git a/libs/common/src/models/api/fieldApi.ts b/libs/common/src/models/api/fieldApi.ts new file mode 100644 index 0000000000..cabdb7cca1 --- /dev/null +++ b/libs/common/src/models/api/fieldApi.ts @@ -0,0 +1,21 @@ +import { FieldType } from "../../enums/fieldType"; +import { LinkedIdType } from "../../enums/linkedIdType"; +import { BaseResponse } from "../response/baseResponse"; + +export class FieldApi extends BaseResponse { + name: string; + value: string; + type: FieldType; + linkedId: LinkedIdType; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.type = this.getResponseProperty("Type"); + this.name = this.getResponseProperty("Name"); + this.value = this.getResponseProperty("Value"); + this.linkedId = this.getResponseProperty("linkedId"); + } +} diff --git a/libs/common/src/models/api/identityApi.ts b/libs/common/src/models/api/identityApi.ts new file mode 100644 index 0000000000..9312438f76 --- /dev/null +++ b/libs/common/src/models/api/identityApi.ts @@ -0,0 +1,47 @@ +import { BaseResponse } from "../response/baseResponse"; + +export class IdentityApi extends BaseResponse { + title: string; + firstName: string; + middleName: string; + lastName: string; + address1: string; + address2: string; + address3: string; + city: string; + state: string; + postalCode: string; + country: string; + company: string; + email: string; + phone: string; + ssn: string; + username: string; + passportNumber: string; + licenseNumber: string; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.title = this.getResponseProperty("Title"); + this.firstName = this.getResponseProperty("FirstName"); + this.middleName = this.getResponseProperty("MiddleName"); + this.lastName = this.getResponseProperty("LastName"); + this.address1 = this.getResponseProperty("Address1"); + this.address2 = this.getResponseProperty("Address2"); + this.address3 = this.getResponseProperty("Address3"); + this.city = this.getResponseProperty("City"); + this.state = this.getResponseProperty("State"); + this.postalCode = this.getResponseProperty("PostalCode"); + this.country = this.getResponseProperty("Country"); + this.company = this.getResponseProperty("Company"); + this.email = this.getResponseProperty("Email"); + this.phone = this.getResponseProperty("Phone"); + this.ssn = this.getResponseProperty("SSN"); + this.username = this.getResponseProperty("Username"); + this.passportNumber = this.getResponseProperty("PassportNumber"); + this.licenseNumber = this.getResponseProperty("LicenseNumber"); + } +} diff --git a/libs/common/src/models/api/loginApi.ts b/libs/common/src/models/api/loginApi.ts new file mode 100644 index 0000000000..ddbe37ec9b --- /dev/null +++ b/libs/common/src/models/api/loginApi.ts @@ -0,0 +1,29 @@ +import { BaseResponse } from "../response/baseResponse"; + +import { LoginUriApi } from "./loginUriApi"; + +export class LoginApi extends BaseResponse { + uris: LoginUriApi[]; + username: string; + password: string; + passwordRevisionDate: string; + totp: string; + autofillOnPageLoad: boolean; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.username = this.getResponseProperty("Username"); + this.password = this.getResponseProperty("Password"); + this.passwordRevisionDate = this.getResponseProperty("PasswordRevisionDate"); + this.totp = this.getResponseProperty("Totp"); + this.autofillOnPageLoad = this.getResponseProperty("AutofillOnPageLoad"); + + const uris = this.getResponseProperty("Uris"); + if (uris != null) { + this.uris = uris.map((u: any) => new LoginUriApi(u)); + } + } +} diff --git a/libs/common/src/models/api/loginUriApi.ts b/libs/common/src/models/api/loginUriApi.ts new file mode 100644 index 0000000000..50ffb0dabb --- /dev/null +++ b/libs/common/src/models/api/loginUriApi.ts @@ -0,0 +1,17 @@ +import { UriMatchType } from "../../enums/uriMatchType"; +import { BaseResponse } from "../response/baseResponse"; + +export class LoginUriApi extends BaseResponse { + uri: string; + match: UriMatchType = null; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.uri = this.getResponseProperty("Uri"); + const match = this.getResponseProperty("Match"); + this.match = match != null ? match : null; + } +} diff --git a/libs/common/src/models/api/permissionsApi.ts b/libs/common/src/models/api/permissionsApi.ts new file mode 100644 index 0000000000..bac79bd3cf --- /dev/null +++ b/libs/common/src/models/api/permissionsApi.ts @@ -0,0 +1,55 @@ +import { BaseResponse } from "../response/baseResponse"; + +export class PermissionsApi extends BaseResponse { + accessEventLogs: boolean; + accessImportExport: boolean; + accessReports: boolean; + /** + * @deprecated Sep 29 2021: This permission has been split out to `createNewCollections`, `editAnyCollection`, and + * `deleteAnyCollection`. It exists here for backwards compatibility with Server versions <= 1.43.0 + */ + manageAllCollections: boolean; + createNewCollections: boolean; + editAnyCollection: boolean; + deleteAnyCollection: boolean; + /** + * @deprecated Sep 29 2021: This permission has been split out to `editAssignedCollections` and + * `deleteAssignedCollections`. It exists here for backwards compatibility with Server versions <= 1.43.0 + */ + manageAssignedCollections: boolean; + editAssignedCollections: boolean; + deleteAssignedCollections: boolean; + manageCiphers: boolean; + manageGroups: boolean; + manageSso: boolean; + managePolicies: boolean; + manageUsers: boolean; + manageResetPassword: boolean; + + constructor(data: any = null) { + super(data); + if (data == null) { + return this; + } + this.accessEventLogs = this.getResponseProperty("AccessEventLogs"); + this.accessImportExport = this.getResponseProperty("AccessImportExport"); + this.accessReports = this.getResponseProperty("AccessReports"); + + // For backwards compatibility with Server <= 1.43.0 + this.manageAllCollections = this.getResponseProperty("ManageAllCollections"); + this.manageAssignedCollections = this.getResponseProperty("ManageAssignedCollections"); + + this.createNewCollections = this.getResponseProperty("CreateNewCollections"); + this.editAnyCollection = this.getResponseProperty("EditAnyCollection"); + this.deleteAnyCollection = this.getResponseProperty("DeleteAnyCollection"); + this.editAssignedCollections = this.getResponseProperty("EditAssignedCollections"); + this.deleteAssignedCollections = this.getResponseProperty("DeleteAssignedCollections"); + + this.manageCiphers = this.getResponseProperty("ManageCiphers"); + this.manageGroups = this.getResponseProperty("ManageGroups"); + this.manageSso = this.getResponseProperty("ManageSso"); + this.managePolicies = this.getResponseProperty("ManagePolicies"); + this.manageUsers = this.getResponseProperty("ManageUsers"); + this.manageResetPassword = this.getResponseProperty("ManageResetPassword"); + } +} diff --git a/libs/common/src/models/api/secureNoteApi.ts b/libs/common/src/models/api/secureNoteApi.ts new file mode 100644 index 0000000000..80f18c6108 --- /dev/null +++ b/libs/common/src/models/api/secureNoteApi.ts @@ -0,0 +1,14 @@ +import { SecureNoteType } from "../../enums/secureNoteType"; +import { BaseResponse } from "../response/baseResponse"; + +export class SecureNoteApi extends BaseResponse { + type: SecureNoteType; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.type = this.getResponseProperty("Type"); + } +} diff --git a/libs/common/src/models/api/sendFileApi.ts b/libs/common/src/models/api/sendFileApi.ts new file mode 100644 index 0000000000..99fa0ff5d1 --- /dev/null +++ b/libs/common/src/models/api/sendFileApi.ts @@ -0,0 +1,19 @@ +import { BaseResponse } from "../response/baseResponse"; + +export class SendFileApi extends BaseResponse { + id: string; + fileName: string; + size: string; + sizeName: string; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.id = this.getResponseProperty("Id"); + this.fileName = this.getResponseProperty("FileName"); + this.size = this.getResponseProperty("Size"); + this.sizeName = this.getResponseProperty("SizeName"); + } +} diff --git a/libs/common/src/models/api/sendTextApi.ts b/libs/common/src/models/api/sendTextApi.ts new file mode 100644 index 0000000000..56d2145069 --- /dev/null +++ b/libs/common/src/models/api/sendTextApi.ts @@ -0,0 +1,15 @@ +import { BaseResponse } from "../response/baseResponse"; + +export class SendTextApi extends BaseResponse { + text: string; + hidden: boolean; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + this.text = this.getResponseProperty("Text"); + this.hidden = this.getResponseProperty("Hidden") || false; + } +} diff --git a/libs/common/src/models/api/ssoConfigApi.ts b/libs/common/src/models/api/ssoConfigApi.ts new file mode 100644 index 0000000000..0767f3d672 --- /dev/null +++ b/libs/common/src/models/api/ssoConfigApi.ts @@ -0,0 +1,136 @@ +import { + OpenIdConnectRedirectBehavior, + Saml2BindingType, + Saml2NameIdFormat, + Saml2SigningBehavior, + SsoType, +} from "../../enums/ssoEnums"; +import { BaseResponse } from "../response/baseResponse"; +import { SsoConfigView } from "../view/ssoConfigView"; + +export class SsoConfigApi extends BaseResponse { + static fromView(view: SsoConfigView, api = new SsoConfigApi()) { + api.configType = view.configType; + + api.keyConnectorEnabled = view.keyConnectorEnabled; + api.keyConnectorUrl = view.keyConnectorUrl; + + if (api.configType === SsoType.OpenIdConnect) { + api.authority = view.openId.authority; + api.clientId = view.openId.clientId; + api.clientSecret = view.openId.clientSecret; + api.metadataAddress = view.openId.metadataAddress; + api.redirectBehavior = view.openId.redirectBehavior; + api.getClaimsFromUserInfoEndpoint = view.openId.getClaimsFromUserInfoEndpoint; + api.additionalScopes = view.openId.additionalScopes; + api.additionalUserIdClaimTypes = view.openId.additionalUserIdClaimTypes; + api.additionalEmailClaimTypes = view.openId.additionalEmailClaimTypes; + api.additionalNameClaimTypes = view.openId.additionalNameClaimTypes; + api.acrValues = view.openId.acrValues; + api.expectedReturnAcrValue = view.openId.expectedReturnAcrValue; + } else if (api.configType === SsoType.Saml2) { + api.spNameIdFormat = view.saml.spNameIdFormat; + api.spOutboundSigningAlgorithm = view.saml.spOutboundSigningAlgorithm; + api.spSigningBehavior = view.saml.spSigningBehavior; + api.spMinIncomingSigningAlgorithm = view.saml.spMinIncomingSigningAlgorithm; + api.spWantAssertionsSigned = view.saml.spWantAssertionsSigned; + api.spValidateCertificates = view.saml.spValidateCertificates; + + api.idpEntityId = view.saml.idpEntityId; + api.idpBindingType = view.saml.idpBindingType; + api.idpSingleSignOnServiceUrl = view.saml.idpSingleSignOnServiceUrl; + api.idpSingleLogoutServiceUrl = view.saml.idpSingleLogoutServiceUrl; + api.idpX509PublicCert = view.saml.idpX509PublicCert; + api.idpOutboundSigningAlgorithm = view.saml.idpOutboundSigningAlgorithm; + api.idpAllowUnsolicitedAuthnResponse = view.saml.idpAllowUnsolicitedAuthnResponse; + api.idpWantAuthnRequestsSigned = view.saml.idpWantAuthnRequestsSigned; + + // Value is inverted in the api model (disable instead of allow) + api.idpDisableOutboundLogoutRequests = !view.saml.idpAllowOutboundLogoutRequests; + } + + return api; + } + configType: SsoType; + + keyConnectorEnabled: boolean; + keyConnectorUrl: string; + + // OpenId + authority: string; + clientId: string; + clientSecret: string; + metadataAddress: string; + redirectBehavior: OpenIdConnectRedirectBehavior; + getClaimsFromUserInfoEndpoint: boolean; + additionalScopes: string; + additionalUserIdClaimTypes: string; + additionalEmailClaimTypes: string; + additionalNameClaimTypes: string; + acrValues: string; + expectedReturnAcrValue: string; + + // SAML + spNameIdFormat: Saml2NameIdFormat; + spOutboundSigningAlgorithm: string; + spSigningBehavior: Saml2SigningBehavior; + spMinIncomingSigningAlgorithm: boolean; + spWantAssertionsSigned: boolean; + spValidateCertificates: boolean; + + idpEntityId: string; + idpBindingType: Saml2BindingType; + idpSingleSignOnServiceUrl: string; + idpSingleLogoutServiceUrl: string; + idpX509PublicCert: string; + idpOutboundSigningAlgorithm: string; + idpAllowUnsolicitedAuthnResponse: boolean; + idpDisableOutboundLogoutRequests: boolean; + idpWantAuthnRequestsSigned: boolean; + + constructor(data: any = null) { + super(data); + if (data == null) { + return; + } + + this.configType = this.getResponseProperty("ConfigType"); + + this.keyConnectorEnabled = this.getResponseProperty("KeyConnectorEnabled"); + this.keyConnectorUrl = this.getResponseProperty("KeyConnectorUrl"); + + this.authority = this.getResponseProperty("Authority"); + this.clientId = this.getResponseProperty("ClientId"); + this.clientSecret = this.getResponseProperty("ClientSecret"); + this.metadataAddress = this.getResponseProperty("MetadataAddress"); + this.redirectBehavior = this.getResponseProperty("RedirectBehavior"); + this.getClaimsFromUserInfoEndpoint = this.getResponseProperty("GetClaimsFromUserInfoEndpoint"); + this.additionalScopes = this.getResponseProperty("AdditionalScopes"); + this.additionalUserIdClaimTypes = this.getResponseProperty("AdditionalUserIdClaimTypes"); + this.additionalEmailClaimTypes = this.getResponseProperty("AdditionalEmailClaimTypes"); + this.additionalNameClaimTypes = this.getResponseProperty("AdditionalNameClaimTypes"); + this.acrValues = this.getResponseProperty("AcrValues"); + this.expectedReturnAcrValue = this.getResponseProperty("ExpectedReturnAcrValue"); + + this.spNameIdFormat = this.getResponseProperty("SpNameIdFormat"); + this.spOutboundSigningAlgorithm = this.getResponseProperty("SpOutboundSigningAlgorithm"); + this.spSigningBehavior = this.getResponseProperty("SpSigningBehavior"); + this.spMinIncomingSigningAlgorithm = this.getResponseProperty("SpMinIncomingSigningAlgorithm"); + this.spWantAssertionsSigned = this.getResponseProperty("SpWantAssertionsSigned"); + this.spValidateCertificates = this.getResponseProperty("SpValidateCertificates"); + + this.idpEntityId = this.getResponseProperty("IdpEntityId"); + this.idpBindingType = this.getResponseProperty("IdpBindingType"); + this.idpSingleSignOnServiceUrl = this.getResponseProperty("IdpSingleSignOnServiceUrl"); + this.idpSingleLogoutServiceUrl = this.getResponseProperty("IdpSingleLogoutServiceUrl"); + this.idpX509PublicCert = this.getResponseProperty("IdpX509PublicCert"); + this.idpOutboundSigningAlgorithm = this.getResponseProperty("IdpOutboundSigningAlgorithm"); + this.idpAllowUnsolicitedAuthnResponse = this.getResponseProperty( + "IdpAllowUnsolicitedAuthnResponse" + ); + this.idpDisableOutboundLogoutRequests = this.getResponseProperty( + "IdpDisableOutboundLogoutRequests" + ); + this.idpWantAuthnRequestsSigned = this.getResponseProperty("IdpWantAuthnRequestsSigned"); + } +} diff --git a/libs/common/src/models/data/attachmentData.ts b/libs/common/src/models/data/attachmentData.ts new file mode 100644 index 0000000000..50af03acda --- /dev/null +++ b/libs/common/src/models/data/attachmentData.ts @@ -0,0 +1,22 @@ +import { AttachmentResponse } from "../response/attachmentResponse"; + +export class AttachmentData { + id: string; + url: string; + fileName: string; + key: string; + size: string; + sizeName: string; + + constructor(response?: AttachmentResponse) { + if (response == null) { + return; + } + this.id = response.id; + this.url = response.url; + this.fileName = response.fileName; + this.key = response.key; + this.size = response.size; + this.sizeName = response.sizeName; + } +} diff --git a/libs/common/src/models/data/cardData.ts b/libs/common/src/models/data/cardData.ts new file mode 100644 index 0000000000..9d90e4b2c9 --- /dev/null +++ b/libs/common/src/models/data/cardData.ts @@ -0,0 +1,23 @@ +import { CardApi } from "../api/cardApi"; + +export class CardData { + cardholderName: string; + brand: string; + number: string; + expMonth: string; + expYear: string; + code: string; + + constructor(data?: CardApi) { + if (data == null) { + return; + } + + this.cardholderName = data.cardholderName; + this.brand = data.brand; + this.number = data.number; + this.expMonth = data.expMonth; + this.expYear = data.expYear; + this.code = data.code; + } +} diff --git a/libs/common/src/models/data/cipherData.ts b/libs/common/src/models/data/cipherData.ts new file mode 100644 index 0000000000..aa82a5fd0b --- /dev/null +++ b/libs/common/src/models/data/cipherData.ts @@ -0,0 +1,83 @@ +import { CipherRepromptType } from "../../enums/cipherRepromptType"; +import { CipherType } from "../../enums/cipherType"; +import { CipherResponse } from "../response/cipherResponse"; + +import { AttachmentData } from "./attachmentData"; +import { CardData } from "./cardData"; +import { FieldData } from "./fieldData"; +import { IdentityData } from "./identityData"; +import { LoginData } from "./loginData"; +import { PasswordHistoryData } from "./passwordHistoryData"; +import { SecureNoteData } from "./secureNoteData"; + +export class CipherData { + id: string; + organizationId: string; + folderId: string; + edit: boolean; + viewPassword: boolean; + organizationUseTotp: boolean; + favorite: boolean; + revisionDate: string; + type: CipherType; + name: string; + notes: string; + login?: LoginData; + secureNote?: SecureNoteData; + card?: CardData; + identity?: IdentityData; + fields?: FieldData[]; + attachments?: AttachmentData[]; + passwordHistory?: PasswordHistoryData[]; + collectionIds?: string[]; + deletedDate: string; + reprompt: CipherRepromptType; + + constructor(response?: CipherResponse, collectionIds?: string[]) { + if (response == null) { + return; + } + + this.id = response.id; + this.organizationId = response.organizationId; + this.folderId = response.folderId; + this.edit = response.edit; + this.viewPassword = response.viewPassword; + this.organizationUseTotp = response.organizationUseTotp; + this.favorite = response.favorite; + this.revisionDate = response.revisionDate; + this.type = response.type; + this.name = response.name; + this.notes = response.notes; + this.collectionIds = collectionIds != null ? collectionIds : response.collectionIds; + this.deletedDate = response.deletedDate; + this.reprompt = response.reprompt; + + switch (this.type) { + case CipherType.Login: + this.login = new LoginData(response.login); + break; + case CipherType.SecureNote: + this.secureNote = new SecureNoteData(response.secureNote); + break; + case CipherType.Card: + this.card = new CardData(response.card); + break; + case CipherType.Identity: + this.identity = new IdentityData(response.identity); + break; + default: + break; + } + + if (response.fields != null) { + this.fields = response.fields.map((f) => new FieldData(f)); + } + if (response.attachments != null) { + this.attachments = response.attachments.map((a) => new AttachmentData(a)); + } + if (response.passwordHistory != null) { + this.passwordHistory = response.passwordHistory.map((ph) => new PasswordHistoryData(ph)); + } + } +} diff --git a/libs/common/src/models/data/collectionData.ts b/libs/common/src/models/data/collectionData.ts new file mode 100644 index 0000000000..9e2607edc6 --- /dev/null +++ b/libs/common/src/models/data/collectionData.ts @@ -0,0 +1,17 @@ +import { CollectionDetailsResponse } from "../response/collectionResponse"; + +export class CollectionData { + id: string; + organizationId: string; + name: string; + externalId: string; + readOnly: boolean; + + constructor(response: CollectionDetailsResponse) { + this.id = response.id; + this.organizationId = response.organizationId; + this.name = response.name; + this.externalId = response.externalId; + this.readOnly = response.readOnly; + } +} diff --git a/libs/common/src/models/data/eventData.ts b/libs/common/src/models/data/eventData.ts new file mode 100644 index 0000000000..c0e38ddc38 --- /dev/null +++ b/libs/common/src/models/data/eventData.ts @@ -0,0 +1,7 @@ +import { EventType } from "../../enums/eventType"; + +export class EventData { + type: EventType; + cipherId: string; + date: string; +} diff --git a/libs/common/src/models/data/fieldData.ts b/libs/common/src/models/data/fieldData.ts new file mode 100644 index 0000000000..6bec9def08 --- /dev/null +++ b/libs/common/src/models/data/fieldData.ts @@ -0,0 +1,20 @@ +import { FieldType } from "../../enums/fieldType"; +import { LinkedIdType } from "../../enums/linkedIdType"; +import { FieldApi } from "../api/fieldApi"; + +export class FieldData { + type: FieldType; + name: string; + value: string; + linkedId: LinkedIdType; + + constructor(response?: FieldApi) { + if (response == null) { + return; + } + this.type = response.type; + this.name = response.name; + this.value = response.value; + this.linkedId = response.linkedId; + } +} diff --git a/libs/common/src/models/data/folderData.ts b/libs/common/src/models/data/folderData.ts new file mode 100644 index 0000000000..76f1e5d724 --- /dev/null +++ b/libs/common/src/models/data/folderData.ts @@ -0,0 +1,13 @@ +import { FolderResponse } from "../response/folderResponse"; + +export class FolderData { + id: string; + name: string; + revisionDate: string; + + constructor(response: FolderResponse) { + this.name = response.name; + this.id = response.id; + this.revisionDate = response.revisionDate; + } +} diff --git a/libs/common/src/models/data/identityData.ts b/libs/common/src/models/data/identityData.ts new file mode 100644 index 0000000000..02aa7eb66c --- /dev/null +++ b/libs/common/src/models/data/identityData.ts @@ -0,0 +1,47 @@ +import { IdentityApi } from "../api/identityApi"; + +export class IdentityData { + title: string; + firstName: string; + middleName: string; + lastName: string; + address1: string; + address2: string; + address3: string; + city: string; + state: string; + postalCode: string; + country: string; + company: string; + email: string; + phone: string; + ssn: string; + username: string; + passportNumber: string; + licenseNumber: string; + + constructor(data?: IdentityApi) { + if (data == null) { + return; + } + + this.title = data.title; + this.firstName = data.firstName; + this.middleName = data.middleName; + this.lastName = data.lastName; + this.address1 = data.address1; + this.address2 = data.address2; + this.address3 = data.address3; + this.city = data.city; + this.state = data.state; + this.postalCode = data.postalCode; + this.country = data.country; + this.company = data.company; + this.email = data.email; + this.phone = data.phone; + this.ssn = data.ssn; + this.username = data.username; + this.passportNumber = data.passportNumber; + this.licenseNumber = data.licenseNumber; + } +} diff --git a/libs/common/src/models/data/loginData.ts b/libs/common/src/models/data/loginData.ts new file mode 100644 index 0000000000..e51180c8b0 --- /dev/null +++ b/libs/common/src/models/data/loginData.ts @@ -0,0 +1,28 @@ +import { LoginApi } from "../api/loginApi"; + +import { LoginUriData } from "./loginUriData"; + +export class LoginData { + uris: LoginUriData[]; + username: string; + password: string; + passwordRevisionDate: string; + totp: string; + autofillOnPageLoad: boolean; + + constructor(data?: LoginApi) { + if (data == null) { + return; + } + + this.username = data.username; + this.password = data.password; + this.passwordRevisionDate = data.passwordRevisionDate; + this.totp = data.totp; + this.autofillOnPageLoad = data.autofillOnPageLoad; + + if (data.uris) { + this.uris = data.uris.map((u) => new LoginUriData(u)); + } + } +} diff --git a/libs/common/src/models/data/loginUriData.ts b/libs/common/src/models/data/loginUriData.ts new file mode 100644 index 0000000000..874db4e818 --- /dev/null +++ b/libs/common/src/models/data/loginUriData.ts @@ -0,0 +1,15 @@ +import { UriMatchType } from "../../enums/uriMatchType"; +import { LoginUriApi } from "../api/loginUriApi"; + +export class LoginUriData { + uri: string; + match: UriMatchType = null; + + constructor(data?: LoginUriApi) { + if (data == null) { + return; + } + this.uri = data.uri; + this.match = data.match; + } +} diff --git a/libs/common/src/models/data/organizationData.ts b/libs/common/src/models/data/organizationData.ts new file mode 100644 index 0000000000..d093821fc3 --- /dev/null +++ b/libs/common/src/models/data/organizationData.ts @@ -0,0 +1,84 @@ +import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType"; +import { OrganizationUserType } from "../../enums/organizationUserType"; +import { ProductType } from "../../enums/productType"; +import { PermissionsApi } from "../api/permissionsApi"; +import { ProfileOrganizationResponse } from "../response/profileOrganizationResponse"; + +export class OrganizationData { + id: string; + name: string; + status: OrganizationUserStatusType; + type: OrganizationUserType; + enabled: boolean; + usePolicies: boolean; + useGroups: boolean; + useDirectory: boolean; + useEvents: boolean; + useTotp: boolean; + use2fa: boolean; + useApi: boolean; + useSso: boolean; + useKeyConnector: boolean; + useResetPassword: boolean; + selfHost: boolean; + usersGetPremium: boolean; + seats: number; + maxCollections: number; + maxStorageGb?: number; + ssoBound: boolean; + identifier: string; + permissions: PermissionsApi; + resetPasswordEnrolled: boolean; + userId: string; + hasPublicAndPrivateKeys: boolean; + providerId: string; + providerName: string; + isProviderUser: boolean; + familySponsorshipFriendlyName: string; + familySponsorshipAvailable: boolean; + planProductType: ProductType; + keyConnectorEnabled: boolean; + keyConnectorUrl: string; + familySponsorshipLastSyncDate?: Date; + familySponsorshipValidUntil?: Date; + familySponsorshipToDelete?: boolean; + + constructor(response: ProfileOrganizationResponse) { + this.id = response.id; + this.name = response.name; + this.status = response.status; + this.type = response.type; + this.enabled = response.enabled; + this.usePolicies = response.usePolicies; + this.useGroups = response.useGroups; + this.useDirectory = response.useDirectory; + this.useEvents = response.useEvents; + this.useTotp = response.useTotp; + this.use2fa = response.use2fa; + this.useApi = response.useApi; + this.useSso = response.useSso; + this.useKeyConnector = response.useKeyConnector; + this.useResetPassword = response.useResetPassword; + this.selfHost = response.selfHost; + this.usersGetPremium = response.usersGetPremium; + this.seats = response.seats; + this.maxCollections = response.maxCollections; + this.maxStorageGb = response.maxStorageGb; + this.ssoBound = response.ssoBound; + this.identifier = response.identifier; + this.permissions = response.permissions; + this.resetPasswordEnrolled = response.resetPasswordEnrolled; + this.userId = response.userId; + this.hasPublicAndPrivateKeys = response.hasPublicAndPrivateKeys; + this.providerId = response.providerId; + this.providerName = response.providerName; + this.familySponsorshipFriendlyName = response.familySponsorshipFriendlyName; + this.familySponsorshipAvailable = response.familySponsorshipAvailable; + this.planProductType = response.planProductType; + this.keyConnectorEnabled = response.keyConnectorEnabled; + this.keyConnectorUrl = response.keyConnectorUrl; + this.familySponsorshipLastSyncDate = response.familySponsorshipLastSyncDate; + this.familySponsorshipValidUntil = response.familySponsorshipValidUntil; + this.familySponsorshipToDelete = response.familySponsorshipToDelete; + } +} diff --git a/libs/common/src/models/data/passwordHistoryData.ts b/libs/common/src/models/data/passwordHistoryData.ts new file mode 100644 index 0000000000..72436f3d13 --- /dev/null +++ b/libs/common/src/models/data/passwordHistoryData.ts @@ -0,0 +1,15 @@ +import { PasswordHistoryResponse } from "../response/passwordHistoryResponse"; + +export class PasswordHistoryData { + password: string; + lastUsedDate: string; + + constructor(response?: PasswordHistoryResponse) { + if (response == null) { + return; + } + + this.password = response.password; + this.lastUsedDate = response.lastUsedDate; + } +} diff --git a/libs/common/src/models/data/policyData.ts b/libs/common/src/models/data/policyData.ts new file mode 100644 index 0000000000..c93b404028 --- /dev/null +++ b/libs/common/src/models/data/policyData.ts @@ -0,0 +1,18 @@ +import { PolicyType } from "../../enums/policyType"; +import { PolicyResponse } from "../response/policyResponse"; + +export class PolicyData { + id: string; + organizationId: string; + type: PolicyType; + data: any; + enabled: boolean; + + constructor(response: PolicyResponse) { + this.id = response.id; + this.organizationId = response.organizationId; + this.type = response.type; + this.data = response.data; + this.enabled = response.enabled; + } +} diff --git a/libs/common/src/models/data/providerData.ts b/libs/common/src/models/data/providerData.ts new file mode 100644 index 0000000000..5d141ed1a2 --- /dev/null +++ b/libs/common/src/models/data/providerData.ts @@ -0,0 +1,23 @@ +import { ProviderUserStatusType } from "../../enums/providerUserStatusType"; +import { ProviderUserType } from "../../enums/providerUserType"; +import { ProfileProviderResponse } from "../response/profileProviderResponse"; + +export class ProviderData { + id: string; + name: string; + status: ProviderUserStatusType; + type: ProviderUserType; + enabled: boolean; + userId: string; + useEvents: boolean; + + constructor(response: ProfileProviderResponse) { + this.id = response.id; + this.name = response.name; + this.status = response.status; + this.type = response.type; + this.enabled = response.enabled; + this.userId = response.userId; + this.useEvents = response.useEvents; + } +} diff --git a/libs/common/src/models/data/secureNoteData.ts b/libs/common/src/models/data/secureNoteData.ts new file mode 100644 index 0000000000..f536b2de5d --- /dev/null +++ b/libs/common/src/models/data/secureNoteData.ts @@ -0,0 +1,14 @@ +import { SecureNoteType } from "../../enums/secureNoteType"; +import { SecureNoteApi } from "../api/secureNoteApi"; + +export class SecureNoteData { + type: SecureNoteType; + + constructor(data?: SecureNoteApi) { + if (data == null) { + return; + } + + this.type = data.type; + } +} diff --git a/libs/common/src/models/data/sendData.ts b/libs/common/src/models/data/sendData.ts new file mode 100644 index 0000000000..4c3bb8b2ff --- /dev/null +++ b/libs/common/src/models/data/sendData.ts @@ -0,0 +1,56 @@ +import { SendType } from "../../enums/sendType"; +import { SendResponse } from "../response/sendResponse"; + +import { SendFileData } from "./sendFileData"; +import { SendTextData } from "./sendTextData"; + +export class SendData { + id: string; + accessId: string; + type: SendType; + name: string; + notes: string; + file: SendFileData; + text: SendTextData; + key: string; + maxAccessCount?: number; + accessCount: number; + revisionDate: string; + expirationDate: string; + deletionDate: string; + password: string; + disabled: boolean; + hideEmail: boolean; + + constructor(response?: SendResponse) { + if (response == null) { + return; + } + + this.id = response.id; + this.accessId = response.accessId; + this.type = response.type; + this.name = response.name; + this.notes = response.notes; + this.key = response.key; + this.maxAccessCount = response.maxAccessCount; + this.accessCount = response.accessCount; + this.revisionDate = response.revisionDate; + this.expirationDate = response.expirationDate; + this.deletionDate = response.deletionDate; + this.password = response.password; + this.disabled = response.disable; + this.hideEmail = response.hideEmail; + + switch (this.type) { + case SendType.Text: + this.text = new SendTextData(response.text); + break; + case SendType.File: + this.file = new SendFileData(response.file); + break; + default: + break; + } + } +} diff --git a/libs/common/src/models/data/sendFileData.ts b/libs/common/src/models/data/sendFileData.ts new file mode 100644 index 0000000000..aaf868c19d --- /dev/null +++ b/libs/common/src/models/data/sendFileData.ts @@ -0,0 +1,19 @@ +import { SendFileApi } from "../api/sendFileApi"; + +export class SendFileData { + id: string; + fileName: string; + size: string; + sizeName: string; + + constructor(data?: SendFileApi) { + if (data == null) { + return; + } + + this.id = data.id; + this.fileName = data.fileName; + this.size = data.size; + this.sizeName = data.sizeName; + } +} diff --git a/libs/common/src/models/data/sendTextData.ts b/libs/common/src/models/data/sendTextData.ts new file mode 100644 index 0000000000..fedf2ed616 --- /dev/null +++ b/libs/common/src/models/data/sendTextData.ts @@ -0,0 +1,15 @@ +import { SendTextApi } from "../api/sendTextApi"; + +export class SendTextData { + text: string; + hidden: boolean; + + constructor(data?: SendTextApi) { + if (data == null) { + return; + } + + this.text = data.text; + this.hidden = data.hidden; + } +} diff --git a/libs/common/src/models/domain/account.ts b/libs/common/src/models/domain/account.ts new file mode 100644 index 0000000000..e03f9be347 --- /dev/null +++ b/libs/common/src/models/domain/account.ts @@ -0,0 +1,175 @@ +import { AuthenticationStatus } from "../../enums/authenticationStatus"; +import { KdfType } from "../../enums/kdfType"; +import { UriMatchType } from "../../enums/uriMatchType"; +import { CipherData } from "../data/cipherData"; +import { CollectionData } from "../data/collectionData"; +import { EventData } from "../data/eventData"; +import { FolderData } from "../data/folderData"; +import { OrganizationData } from "../data/organizationData"; +import { PolicyData } from "../data/policyData"; +import { ProviderData } from "../data/providerData"; +import { SendData } from "../data/sendData"; +import { CipherView } from "../view/cipherView"; +import { CollectionView } from "../view/collectionView"; +import { FolderView } from "../view/folderView"; +import { SendView } from "../view/sendView"; + +import { EncString } from "./encString"; +import { EnvironmentUrls } from "./environmentUrls"; +import { GeneratedPasswordHistory } from "./generatedPasswordHistory"; +import { Policy } from "./policy"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class EncryptionPair { + encrypted?: TEncrypted; + decrypted?: TDecrypted; +} + +export class DataEncryptionPair { + encrypted?: { [id: string]: TEncrypted }; + decrypted?: TDecrypted[]; +} + +export class AccountData { + ciphers?: DataEncryptionPair = new DataEncryptionPair< + CipherData, + CipherView + >(); + folders?: DataEncryptionPair = new DataEncryptionPair< + FolderData, + FolderView + >(); + localData?: any; + sends?: DataEncryptionPair = new DataEncryptionPair(); + collections?: DataEncryptionPair = new DataEncryptionPair< + CollectionData, + CollectionView + >(); + policies?: DataEncryptionPair = new DataEncryptionPair(); + passwordGenerationHistory?: EncryptionPair< + GeneratedPasswordHistory[], + GeneratedPasswordHistory[] + > = new EncryptionPair(); + addEditCipherInfo?: any; + eventCollection?: EventData[]; + organizations?: { [id: string]: OrganizationData }; + providers?: { [id: string]: ProviderData }; +} + +export class AccountKeys { + cryptoMasterKey?: SymmetricCryptoKey; + cryptoMasterKeyAuto?: string; + cryptoMasterKeyB64?: string; + cryptoMasterKeyBiometric?: string; + cryptoSymmetricKey?: EncryptionPair = new EncryptionPair< + string, + SymmetricCryptoKey + >(); + organizationKeys?: EncryptionPair> = new EncryptionPair< + any, + Map + >(); + providerKeys?: EncryptionPair> = new EncryptionPair< + any, + Map + >(); + privateKey?: EncryptionPair = new EncryptionPair(); + legacyEtmKey?: SymmetricCryptoKey; + publicKey?: ArrayBuffer; + apiKeyClientSecret?: string; +} + +export class AccountProfile { + apiKeyClientId?: string; + authenticationStatus?: AuthenticationStatus; + convertAccountToKeyConnector?: boolean; + email?: string; + emailVerified?: boolean; + entityId?: string; + entityType?: string; + everBeenUnlocked?: boolean; + forcePasswordReset?: boolean; + hasPremiumPersonally?: boolean; + lastSync?: string; + userId?: string; + usesKeyConnector?: boolean; + keyHash?: string; + kdfIterations?: number; + kdfType?: KdfType; +} + +export class AccountSettings { + autoConfirmFingerPrints?: boolean; + autoFillOnPageLoadDefault?: boolean; + biometricLocked?: boolean; + biometricUnlock?: boolean; + clearClipboard?: number; + collapsedGroupings?: string[]; + defaultUriMatch?: UriMatchType; + disableAddLoginNotification?: boolean; + disableAutoBiometricsPrompt?: boolean; + disableAutoTotpCopy?: boolean; + disableBadgeCounter?: boolean; + disableChangedPasswordNotification?: boolean; + disableContextMenuItem?: boolean; + disableGa?: boolean; + dontShowCardsCurrentTab?: boolean; + dontShowIdentitiesCurrentTab?: boolean; + enableAlwaysOnTop?: boolean; + enableAutoFillOnPageLoad?: boolean; + enableBiometric?: boolean; + enableFullWidth?: boolean; + enableGravitars?: boolean; + environmentUrls: EnvironmentUrls = new EnvironmentUrls(); + equivalentDomains?: any; + minimizeOnCopyToClipboard?: boolean; + neverDomains?: { [id: string]: any }; + passwordGenerationOptions?: any; + usernameGenerationOptions?: any; + generatorOptions?: any; + pinProtected?: EncryptionPair = new EncryptionPair(); + protectedPin?: string; + settings?: any; // TODO: Merge whatever is going on here into the AccountSettings model properly + vaultTimeout?: number; + vaultTimeoutAction?: string = "lock"; +} + +export class AccountTokens { + accessToken?: string; + decodedToken?: any; + refreshToken?: string; + securityStamp?: string; +} + +export class Account { + data?: AccountData = new AccountData(); + keys?: AccountKeys = new AccountKeys(); + profile?: AccountProfile = new AccountProfile(); + settings?: AccountSettings = new AccountSettings(); + tokens?: AccountTokens = new AccountTokens(); + + constructor(init: Partial) { + Object.assign(this, { + data: { + ...new AccountData(), + ...init?.data, + }, + keys: { + ...new AccountKeys(), + ...init?.keys, + }, + profile: { + ...new AccountProfile(), + ...init?.profile, + }, + settings: { + ...new AccountSettings(), + ...init?.settings, + }, + tokens: { + ...new AccountTokens(), + ...init?.tokens, + }, + }); + } +} diff --git a/libs/common/src/models/domain/attachment.ts b/libs/common/src/models/domain/attachment.ts new file mode 100644 index 0000000000..cbfffdcf68 --- /dev/null +++ b/libs/common/src/models/domain/attachment.ts @@ -0,0 +1,87 @@ +import { CryptoService } from "../../abstractions/crypto.service"; +import { Utils } from "../../misc/utils"; +import { AttachmentData } from "../data/attachmentData"; +import { AttachmentView } from "../view/attachmentView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class Attachment extends Domain { + id: string; + url: string; + size: string; + sizeName: string; // Readable size, ex: "4.2 KB" or "1.43 GB" + key: EncString; + fileName: EncString; + + constructor(obj?: AttachmentData) { + super(); + if (obj == null) { + return; + } + + this.size = obj.size; + this.buildDomainModel( + this, + obj, + { + id: null, + url: null, + sizeName: null, + fileName: null, + key: null, + }, + ["id", "url", "sizeName"] + ); + } + + async decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + const view = await this.decryptObj( + new AttachmentView(this), + { + fileName: null, + }, + orgId, + encKey + ); + + if (this.key != null) { + let cryptoService: CryptoService; + const containerService = (Utils.global as any).bitwardenContainerService; + if (containerService) { + cryptoService = containerService.getCryptoService(); + } else { + throw new Error("global bitwardenContainerService not initialized."); + } + + try { + const orgKey = await cryptoService.getOrgKey(orgId); + const decValue = await cryptoService.decryptToBytes(this.key, orgKey ?? encKey); + view.key = new SymmetricCryptoKey(decValue); + } catch (e) { + // TODO: error? + } + } + + return view; + } + + toAttachmentData(): AttachmentData { + const a = new AttachmentData(); + a.size = this.size; + this.buildDataModel( + this, + a, + { + id: null, + url: null, + sizeName: null, + fileName: null, + key: null, + }, + ["id", "url", "sizeName"] + ); + return a; + } +} diff --git a/libs/common/src/models/domain/authResult.ts b/libs/common/src/models/domain/authResult.ts new file mode 100644 index 0000000000..0781f87214 --- /dev/null +++ b/libs/common/src/models/domain/authResult.ts @@ -0,0 +1,17 @@ +import { TwoFactorProviderType } from "../../enums/twoFactorProviderType"; +import { Utils } from "../../misc/utils"; + +export class AuthResult { + captchaSiteKey = ""; + resetMasterPassword = false; + forcePasswordReset = false; + twoFactorProviders: Map = null; + + get requiresCaptcha() { + return !Utils.isNullOrWhitespace(this.captchaSiteKey); + } + + get requiresTwoFactor() { + return this.twoFactorProviders != null; + } +} diff --git a/libs/common/src/models/domain/card.ts b/libs/common/src/models/domain/card.ts new file mode 100644 index 0000000000..59f73f9028 --- /dev/null +++ b/libs/common/src/models/domain/card.ts @@ -0,0 +1,65 @@ +import { CardData } from "../data/cardData"; +import { CardView } from "../view/cardView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class Card extends Domain { + cardholderName: EncString; + brand: EncString; + number: EncString; + expMonth: EncString; + expYear: EncString; + code: EncString; + + constructor(obj?: CardData) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel( + this, + obj, + { + cardholderName: null, + brand: null, + number: null, + expMonth: null, + expYear: null, + code: null, + }, + [] + ); + } + + decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + return this.decryptObj( + new CardView(), + { + cardholderName: null, + brand: null, + number: null, + expMonth: null, + expYear: null, + code: null, + }, + orgId, + encKey + ); + } + + toCardData(): CardData { + const c = new CardData(); + this.buildDataModel(this, c, { + cardholderName: null, + brand: null, + number: null, + expMonth: null, + expYear: null, + code: null, + }); + return c; + } +} diff --git a/libs/common/src/models/domain/cipher.ts b/libs/common/src/models/domain/cipher.ts new file mode 100644 index 0000000000..b25be35520 --- /dev/null +++ b/libs/common/src/models/domain/cipher.ts @@ -0,0 +1,236 @@ +import { CipherRepromptType } from "../../enums/cipherRepromptType"; +import { CipherType } from "../../enums/cipherType"; +import { CipherData } from "../data/cipherData"; +import { CipherView } from "../view/cipherView"; + +import { Attachment } from "./attachment"; +import { Card } from "./card"; +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { Field } from "./field"; +import { Identity } from "./identity"; +import { Login } from "./login"; +import { Password } from "./password"; +import { SecureNote } from "./secureNote"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class Cipher extends Domain { + id: string; + organizationId: string; + folderId: string; + name: EncString; + notes: EncString; + type: CipherType; + favorite: boolean; + organizationUseTotp: boolean; + edit: boolean; + viewPassword: boolean; + revisionDate: Date; + localData: any; + login: Login; + identity: Identity; + card: Card; + secureNote: SecureNote; + attachments: Attachment[]; + fields: Field[]; + passwordHistory: Password[]; + collectionIds: string[]; + deletedDate: Date; + reprompt: CipherRepromptType; + + constructor(obj?: CipherData, localData: any = null) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel( + this, + obj, + { + id: null, + organizationId: null, + folderId: null, + name: null, + notes: null, + }, + ["id", "organizationId", "folderId"] + ); + + this.type = obj.type; + this.favorite = obj.favorite; + this.organizationUseTotp = obj.organizationUseTotp; + this.edit = obj.edit; + if (obj.viewPassword != null) { + this.viewPassword = obj.viewPassword; + } else { + this.viewPassword = true; // Default for already synced Ciphers without viewPassword + } + this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null; + this.collectionIds = obj.collectionIds; + this.localData = localData; + this.deletedDate = obj.deletedDate != null ? new Date(obj.deletedDate) : null; + this.reprompt = obj.reprompt; + + switch (this.type) { + case CipherType.Login: + this.login = new Login(obj.login); + break; + case CipherType.SecureNote: + this.secureNote = new SecureNote(obj.secureNote); + break; + case CipherType.Card: + this.card = new Card(obj.card); + break; + case CipherType.Identity: + this.identity = new Identity(obj.identity); + break; + default: + break; + } + + if (obj.attachments != null) { + this.attachments = obj.attachments.map((a) => new Attachment(a)); + } else { + this.attachments = null; + } + + if (obj.fields != null) { + this.fields = obj.fields.map((f) => new Field(f)); + } else { + this.fields = null; + } + + if (obj.passwordHistory != null) { + this.passwordHistory = obj.passwordHistory.map((ph) => new Password(ph)); + } else { + this.passwordHistory = null; + } + } + + async decrypt(encKey?: SymmetricCryptoKey): Promise { + const model = new CipherView(this); + + await this.decryptObj( + model, + { + name: null, + notes: null, + }, + this.organizationId, + encKey + ); + + switch (this.type) { + case CipherType.Login: + model.login = await this.login.decrypt(this.organizationId, encKey); + break; + case CipherType.SecureNote: + model.secureNote = await this.secureNote.decrypt(this.organizationId, encKey); + break; + case CipherType.Card: + model.card = await this.card.decrypt(this.organizationId, encKey); + break; + case CipherType.Identity: + model.identity = await this.identity.decrypt(this.organizationId, encKey); + break; + default: + break; + } + + const orgId = this.organizationId; + + if (this.attachments != null && this.attachments.length > 0) { + const attachments: any[] = []; + await this.attachments.reduce((promise, attachment) => { + return promise + .then(() => { + return attachment.decrypt(orgId, encKey); + }) + .then((decAttachment) => { + attachments.push(decAttachment); + }); + }, Promise.resolve()); + model.attachments = attachments; + } + + if (this.fields != null && this.fields.length > 0) { + const fields: any[] = []; + await this.fields.reduce((promise, field) => { + return promise + .then(() => { + return field.decrypt(orgId, encKey); + }) + .then((decField) => { + fields.push(decField); + }); + }, Promise.resolve()); + model.fields = fields; + } + + if (this.passwordHistory != null && this.passwordHistory.length > 0) { + const passwordHistory: any[] = []; + await this.passwordHistory.reduce((promise, ph) => { + return promise + .then(() => { + return ph.decrypt(orgId, encKey); + }) + .then((decPh) => { + passwordHistory.push(decPh); + }); + }, Promise.resolve()); + model.passwordHistory = passwordHistory; + } + + return model; + } + + toCipherData(): CipherData { + const c = new CipherData(); + c.id = this.id; + c.organizationId = this.organizationId; + c.folderId = this.folderId; + c.edit = this.edit; + c.viewPassword = this.viewPassword; + c.organizationUseTotp = this.organizationUseTotp; + c.favorite = this.favorite; + c.revisionDate = this.revisionDate != null ? this.revisionDate.toISOString() : null; + c.type = this.type; + c.collectionIds = this.collectionIds; + c.deletedDate = this.deletedDate != null ? this.deletedDate.toISOString() : null; + c.reprompt = this.reprompt; + + this.buildDataModel(this, c, { + name: null, + notes: null, + }); + + switch (c.type) { + case CipherType.Login: + c.login = this.login.toLoginData(); + break; + case CipherType.SecureNote: + c.secureNote = this.secureNote.toSecureNoteData(); + break; + case CipherType.Card: + c.card = this.card.toCardData(); + break; + case CipherType.Identity: + c.identity = this.identity.toIdentityData(); + break; + default: + break; + } + + if (this.fields != null) { + c.fields = this.fields.map((f) => f.toFieldData()); + } + if (this.attachments != null) { + c.attachments = this.attachments.map((a) => a.toAttachmentData()); + } + if (this.passwordHistory != null) { + c.passwordHistory = this.passwordHistory.map((ph) => ph.toPasswordHistoryData()); + } + return c; + } +} diff --git a/libs/common/src/models/domain/collection.ts b/libs/common/src/models/domain/collection.ts new file mode 100644 index 0000000000..6f737cd477 --- /dev/null +++ b/libs/common/src/models/domain/collection.ts @@ -0,0 +1,45 @@ +import { CollectionData } from "../data/collectionData"; +import { CollectionView } from "../view/collectionView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; + +export class Collection extends Domain { + id: string; + organizationId: string; + name: EncString; + externalId: string; + readOnly: boolean; + hidePasswords: boolean; + + constructor(obj?: CollectionData) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel( + this, + obj, + { + id: null, + organizationId: null, + name: null, + externalId: null, + readOnly: null, + hidePasswords: null, + }, + ["id", "organizationId", "externalId", "readOnly", "hidePasswords"] + ); + } + + decrypt(): Promise { + return this.decryptObj( + new CollectionView(this), + { + name: null, + }, + this.organizationId + ); + } +} diff --git a/libs/common/src/models/domain/decryptParameters.ts b/libs/common/src/models/domain/decryptParameters.ts new file mode 100644 index 0000000000..09a4c1d8f4 --- /dev/null +++ b/libs/common/src/models/domain/decryptParameters.ts @@ -0,0 +1,8 @@ +export class DecryptParameters { + encKey: T; + data: T; + iv: T; + macKey: T; + mac: T; + macData: T; +} diff --git a/libs/common/src/models/domain/domainBase.ts b/libs/common/src/models/domain/domainBase.ts new file mode 100644 index 0000000000..0c9e5ad688 --- /dev/null +++ b/libs/common/src/models/domain/domainBase.ts @@ -0,0 +1,82 @@ +import { View } from "../view/view"; + +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export default class Domain { + protected buildDomainModel( + domain: D, + dataObj: any, + map: any, + notEncList: any[] = [] + ) { + for (const prop in map) { + // eslint-disable-next-line + if (!map.hasOwnProperty(prop)) { + continue; + } + + const objProp = dataObj[map[prop] || prop]; + if (notEncList.indexOf(prop) > -1) { + (domain as any)[prop] = objProp ? objProp : null; + } else { + (domain as any)[prop] = objProp ? new EncString(objProp) : null; + } + } + } + protected buildDataModel( + domain: D, + dataObj: any, + map: any, + notEncStringList: any[] = [] + ) { + for (const prop in map) { + // eslint-disable-next-line + if (!map.hasOwnProperty(prop)) { + continue; + } + + const objProp = (domain as any)[map[prop] || prop]; + if (notEncStringList.indexOf(prop) > -1) { + (dataObj as any)[prop] = objProp != null ? objProp : null; + } else { + (dataObj as any)[prop] = objProp != null ? (objProp as EncString).encryptedString : null; + } + } + } + + protected async decryptObj( + viewModel: T, + map: any, + orgId: string, + key: SymmetricCryptoKey = null + ): Promise { + const promises = []; + const self: any = this; + + for (const prop in map) { + // eslint-disable-next-line + if (!map.hasOwnProperty(prop)) { + continue; + } + + (function (theProp) { + const p = Promise.resolve() + .then(() => { + const mapProp = map[theProp] || theProp; + if (self[mapProp]) { + return self[mapProp].decrypt(orgId, key); + } + return null; + }) + .then((val: any) => { + (viewModel as any)[theProp] = val; + }); + promises.push(p); + })(prop); + } + + await Promise.all(promises); + return viewModel; + } +} diff --git a/libs/common/src/models/domain/encArrayBuffer.ts b/libs/common/src/models/domain/encArrayBuffer.ts new file mode 100644 index 0000000000..97f47c39ae --- /dev/null +++ b/libs/common/src/models/domain/encArrayBuffer.ts @@ -0,0 +1,3 @@ +export class EncArrayBuffer { + constructor(public buffer: ArrayBuffer) {} +} diff --git a/libs/common/src/models/domain/encString.ts b/libs/common/src/models/domain/encString.ts new file mode 100644 index 0000000000..74ae83707b --- /dev/null +++ b/libs/common/src/models/domain/encString.ts @@ -0,0 +1,122 @@ +import { CryptoService } from "../../abstractions/crypto.service"; +import { EncryptionType } from "../../enums/encryptionType"; +import { Utils } from "../../misc/utils"; + +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class EncString { + encryptedString?: string; + encryptionType?: EncryptionType; + decryptedValue?: string; + data?: string; + iv?: string; + mac?: string; + + constructor( + encryptedStringOrType: string | EncryptionType, + data?: string, + iv?: string, + mac?: string + ) { + if (data != null) { + // data and header + const encType = encryptedStringOrType as EncryptionType; + + if (iv != null) { + this.encryptedString = encType + "." + iv + "|" + data; + } else { + this.encryptedString = encType + "." + data; + } + + // mac + if (mac != null) { + this.encryptedString += "|" + mac; + } + + this.encryptionType = encType; + this.data = data; + this.iv = iv; + this.mac = mac; + + return; + } + + this.encryptedString = encryptedStringOrType as string; + if (!this.encryptedString) { + return; + } + + const headerPieces = this.encryptedString.split("."); + let encPieces: string[] = null; + + if (headerPieces.length === 2) { + try { + this.encryptionType = parseInt(headerPieces[0], null); + encPieces = headerPieces[1].split("|"); + } catch (e) { + return; + } + } else { + encPieces = this.encryptedString.split("|"); + this.encryptionType = + encPieces.length === 3 + ? EncryptionType.AesCbc128_HmacSha256_B64 + : EncryptionType.AesCbc256_B64; + } + + switch (this.encryptionType) { + case EncryptionType.AesCbc128_HmacSha256_B64: + case EncryptionType.AesCbc256_HmacSha256_B64: + if (encPieces.length !== 3) { + return; + } + + this.iv = encPieces[0]; + this.data = encPieces[1]; + this.mac = encPieces[2]; + break; + case EncryptionType.AesCbc256_B64: + if (encPieces.length !== 2) { + return; + } + + this.iv = encPieces[0]; + this.data = encPieces[1]; + break; + case EncryptionType.Rsa2048_OaepSha256_B64: + case EncryptionType.Rsa2048_OaepSha1_B64: + if (encPieces.length !== 1) { + return; + } + + this.data = encPieces[0]; + break; + default: + return; + } + } + + async decrypt(orgId: string, key: SymmetricCryptoKey = null): Promise { + if (this.decryptedValue != null) { + return this.decryptedValue; + } + + let cryptoService: CryptoService; + const containerService = (Utils.global as any).bitwardenContainerService; + if (containerService) { + cryptoService = containerService.getCryptoService(); + } else { + throw new Error("global bitwardenContainerService not initialized."); + } + + try { + if (key == null) { + key = await cryptoService.getOrgKey(orgId); + } + this.decryptedValue = await cryptoService.decryptToUtf8(this, key); + } catch (e) { + this.decryptedValue = "[error: cannot decrypt]"; + } + return this.decryptedValue; + } +} diff --git a/libs/common/src/models/domain/encryptedObject.ts b/libs/common/src/models/domain/encryptedObject.ts new file mode 100644 index 0000000000..5ce93dbe92 --- /dev/null +++ b/libs/common/src/models/domain/encryptedObject.ts @@ -0,0 +1,8 @@ +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class EncryptedObject { + iv: ArrayBuffer; + data: ArrayBuffer; + mac: ArrayBuffer; + key: SymmetricCryptoKey; +} diff --git a/libs/common/src/models/domain/environmentUrls.ts b/libs/common/src/models/domain/environmentUrls.ts new file mode 100644 index 0000000000..d4fd173c83 --- /dev/null +++ b/libs/common/src/models/domain/environmentUrls.ts @@ -0,0 +1,10 @@ +export class EnvironmentUrls { + base: string = null; + api: string = null; + identity: string = null; + icons: string = null; + notifications: string = null; + events: string = null; + webVault: string = null; + keyConnector: string = null; +} diff --git a/libs/common/src/models/domain/field.ts b/libs/common/src/models/domain/field.ts new file mode 100644 index 0000000000..71dc615afd --- /dev/null +++ b/libs/common/src/models/domain/field.ts @@ -0,0 +1,62 @@ +import { FieldType } from "../../enums/fieldType"; +import { LinkedIdType } from "../../enums/linkedIdType"; +import { FieldData } from "../data/fieldData"; +import { FieldView } from "../view/fieldView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class Field extends Domain { + name: EncString; + value: EncString; + type: FieldType; + linkedId: LinkedIdType; + + constructor(obj?: FieldData) { + super(); + if (obj == null) { + return; + } + + this.type = obj.type; + this.linkedId = obj.linkedId; + this.buildDomainModel( + this, + obj, + { + name: null, + value: null, + }, + [] + ); + } + + decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + return this.decryptObj( + new FieldView(this), + { + name: null, + value: null, + }, + orgId, + encKey + ); + } + + toFieldData(): FieldData { + const f = new FieldData(); + this.buildDataModel( + this, + f, + { + name: null, + value: null, + type: null, + linkedId: null, + }, + ["type", "linkedId"] + ); + return f; + } +} diff --git a/libs/common/src/models/domain/folder.ts b/libs/common/src/models/domain/folder.ts new file mode 100644 index 0000000000..8596e94d76 --- /dev/null +++ b/libs/common/src/models/domain/folder.ts @@ -0,0 +1,40 @@ +import { FolderData } from "../data/folderData"; +import { FolderView } from "../view/folderView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; + +export class Folder extends Domain { + id: string; + name: EncString; + revisionDate: Date; + + constructor(obj?: FolderData) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel( + this, + obj, + { + id: null, + name: null, + }, + ["id"] + ); + + this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null; + } + + decrypt(): Promise { + return this.decryptObj( + new FolderView(this), + { + name: null, + }, + null + ); + } +} diff --git a/libs/common/src/models/domain/generatedPasswordHistory.ts b/libs/common/src/models/domain/generatedPasswordHistory.ts new file mode 100644 index 0000000000..b4cc9b22fa --- /dev/null +++ b/libs/common/src/models/domain/generatedPasswordHistory.ts @@ -0,0 +1,9 @@ +export class GeneratedPasswordHistory { + password: string; + date: number; + + constructor(password: string, date: number) { + this.password = password; + this.date = date; + } +} diff --git a/libs/common/src/models/domain/globalState.ts b/libs/common/src/models/domain/globalState.ts new file mode 100644 index 0000000000..422293fced --- /dev/null +++ b/libs/common/src/models/domain/globalState.ts @@ -0,0 +1,40 @@ +import { StateVersion } from "../../enums/stateVersion"; +import { ThemeType } from "../../enums/themeType"; + +import { EnvironmentUrls } from "./environmentUrls"; +import { WindowState } from "./windowState"; + +export class GlobalState { + enableAlwaysOnTop?: boolean; + installedVersion?: string; + locale?: string; + organizationInvitation?: any; + ssoCodeVerifier?: string; + ssoOrganizationIdentifier?: string; + ssoState?: string; + rememberedEmail?: string; + theme?: ThemeType = ThemeType.System; + window?: WindowState = new WindowState(); + twoFactorToken?: string; + disableFavicon?: boolean; + biometricAwaitingAcceptance?: boolean; + biometricFingerprintValidated?: boolean; + vaultTimeout?: number; + vaultTimeoutAction?: string; + loginRedirect?: any; + mainWindowSize?: number; + enableBiometrics?: boolean; + biometricText?: string; + noAutoPromptBiometrics?: boolean; + noAutoPromptBiometricsText?: string; + stateVersion: StateVersion = StateVersion.One; + environmentUrls: EnvironmentUrls = new EnvironmentUrls(); + enableTray?: boolean; + enableMinimizeToTray?: boolean; + enableCloseToTray?: boolean; + enableStartToTray?: boolean; + openAtLogin?: boolean; + alwaysShowDock?: boolean; + enableBrowserIntegration?: boolean; + enableBrowserIntegrationFingerprint?: boolean; +} diff --git a/libs/common/src/models/domain/identity.ts b/libs/common/src/models/domain/identity.ts new file mode 100644 index 0000000000..4af228499b --- /dev/null +++ b/libs/common/src/models/domain/identity.ts @@ -0,0 +1,113 @@ +import { IdentityData } from "../data/identityData"; +import { IdentityView } from "../view/identityView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class Identity extends Domain { + title: EncString; + firstName: EncString; + middleName: EncString; + lastName: EncString; + address1: EncString; + address2: EncString; + address3: EncString; + city: EncString; + state: EncString; + postalCode: EncString; + country: EncString; + company: EncString; + email: EncString; + phone: EncString; + ssn: EncString; + username: EncString; + passportNumber: EncString; + licenseNumber: EncString; + + constructor(obj?: IdentityData) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel( + this, + obj, + { + title: null, + firstName: null, + middleName: null, + lastName: null, + address1: null, + address2: null, + address3: null, + city: null, + state: null, + postalCode: null, + country: null, + company: null, + email: null, + phone: null, + ssn: null, + username: null, + passportNumber: null, + licenseNumber: null, + }, + [] + ); + } + + decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + return this.decryptObj( + new IdentityView(), + { + title: null, + firstName: null, + middleName: null, + lastName: null, + address1: null, + address2: null, + address3: null, + city: null, + state: null, + postalCode: null, + country: null, + company: null, + email: null, + phone: null, + ssn: null, + username: null, + passportNumber: null, + licenseNumber: null, + }, + orgId, + encKey + ); + } + + toIdentityData(): IdentityData { + const i = new IdentityData(); + this.buildDataModel(this, i, { + title: null, + firstName: null, + middleName: null, + lastName: null, + address1: null, + address2: null, + address3: null, + city: null, + state: null, + postalCode: null, + country: null, + company: null, + email: null, + phone: null, + ssn: null, + username: null, + passportNumber: null, + licenseNumber: null, + }); + return i; + } +} diff --git a/libs/common/src/models/domain/importResult.ts b/libs/common/src/models/domain/importResult.ts new file mode 100644 index 0000000000..695dbf9d4a --- /dev/null +++ b/libs/common/src/models/domain/importResult.ts @@ -0,0 +1,14 @@ +import { CipherView } from "../view/cipherView"; +import { CollectionView } from "../view/collectionView"; +import { FolderView } from "../view/folderView"; + +export class ImportResult { + success = false; + missingPassword = false; + errorMessage: string; + ciphers: CipherView[] = []; + folders: FolderView[] = []; + folderRelationships: [number, number][] = []; + collections: CollectionView[] = []; + collectionRelationships: [number, number][] = []; +} diff --git a/libs/common/src/models/domain/logInCredentials.ts b/libs/common/src/models/domain/logInCredentials.ts new file mode 100644 index 0000000000..c1e23610e4 --- /dev/null +++ b/libs/common/src/models/domain/logInCredentials.ts @@ -0,0 +1,31 @@ +import { AuthenticationType } from "../../enums/authenticationType"; +import { TokenRequestTwoFactor } from "../request/identityToken/tokenRequestTwoFactor"; + +export class PasswordLogInCredentials { + readonly type = AuthenticationType.Password; + + constructor( + public email: string, + public masterPassword: string, + public captchaToken?: string, + public twoFactor?: TokenRequestTwoFactor + ) {} +} + +export class SsoLogInCredentials { + readonly type = AuthenticationType.Sso; + + constructor( + public code: string, + public codeVerifier: string, + public redirectUrl: string, + public orgId: string, + public twoFactor?: TokenRequestTwoFactor + ) {} +} + +export class ApiLogInCredentials { + readonly type = AuthenticationType.Api; + + constructor(public clientId: string, public clientSecret: string) {} +} diff --git a/libs/common/src/models/domain/login.ts b/libs/common/src/models/domain/login.ts new file mode 100644 index 0000000000..76ba402000 --- /dev/null +++ b/libs/common/src/models/domain/login.ts @@ -0,0 +1,88 @@ +import { LoginData } from "../data/loginData"; +import { LoginView } from "../view/loginView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { LoginUri } from "./loginUri"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class Login extends Domain { + uris: LoginUri[]; + username: EncString; + password: EncString; + passwordRevisionDate?: Date; + totp: EncString; + autofillOnPageLoad: boolean; + + constructor(obj?: LoginData) { + super(); + if (obj == null) { + return; + } + + this.passwordRevisionDate = + obj.passwordRevisionDate != null ? new Date(obj.passwordRevisionDate) : null; + this.autofillOnPageLoad = obj.autofillOnPageLoad; + this.buildDomainModel( + this, + obj, + { + username: null, + password: null, + totp: null, + }, + [] + ); + + if (obj.uris) { + this.uris = []; + obj.uris.forEach((u) => { + this.uris.push(new LoginUri(u)); + }); + } + } + + async decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + const view = await this.decryptObj( + new LoginView(this), + { + username: null, + password: null, + totp: null, + }, + orgId, + encKey + ); + + if (this.uris != null) { + view.uris = []; + for (let i = 0; i < this.uris.length; i++) { + const uri = await this.uris[i].decrypt(orgId, encKey); + view.uris.push(uri); + } + } + + return view; + } + + toLoginData(): LoginData { + const l = new LoginData(); + l.passwordRevisionDate = + this.passwordRevisionDate != null ? this.passwordRevisionDate.toISOString() : null; + l.autofillOnPageLoad = this.autofillOnPageLoad; + this.buildDataModel(this, l, { + username: null, + password: null, + totp: null, + }); + + if (this.uris != null && this.uris.length > 0) { + l.uris = []; + this.uris.forEach((u) => { + l.uris.push(u.toLoginUriData()); + }); + } + + return l; + } +} diff --git a/libs/common/src/models/domain/loginUri.ts b/libs/common/src/models/domain/loginUri.ts new file mode 100644 index 0000000000..9bd78c655f --- /dev/null +++ b/libs/common/src/models/domain/loginUri.ts @@ -0,0 +1,54 @@ +import { UriMatchType } from "../../enums/uriMatchType"; +import { LoginUriData } from "../data/loginUriData"; +import { LoginUriView } from "../view/loginUriView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class LoginUri extends Domain { + uri: EncString; + match: UriMatchType; + + constructor(obj?: LoginUriData) { + super(); + if (obj == null) { + return; + } + + this.match = obj.match; + this.buildDomainModel( + this, + obj, + { + uri: null, + }, + [] + ); + } + + decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + return this.decryptObj( + new LoginUriView(this), + { + uri: null, + }, + orgId, + encKey + ); + } + + toLoginUriData(): LoginUriData { + const u = new LoginUriData(); + this.buildDataModel( + this, + u, + { + uri: null, + match: null, + }, + ["match"] + ); + return u; + } +} diff --git a/libs/common/src/models/domain/masterPasswordPolicyOptions.ts b/libs/common/src/models/domain/masterPasswordPolicyOptions.ts new file mode 100644 index 0000000000..2207d00c7e --- /dev/null +++ b/libs/common/src/models/domain/masterPasswordPolicyOptions.ts @@ -0,0 +1,10 @@ +import Domain from "./domainBase"; + +export class MasterPasswordPolicyOptions extends Domain { + minComplexity = 0; + minLength = 0; + requireUpper = false; + requireLower = false; + requireNumbers = false; + requireSpecial = false; +} diff --git a/libs/common/src/models/domain/organization.ts b/libs/common/src/models/domain/organization.ts new file mode 100644 index 0000000000..ba1c8e1a17 --- /dev/null +++ b/libs/common/src/models/domain/organization.ts @@ -0,0 +1,222 @@ +import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType"; +import { OrganizationUserType } from "../../enums/organizationUserType"; +import { Permissions } from "../../enums/permissions"; +import { ProductType } from "../../enums/productType"; +import { PermissionsApi } from "../api/permissionsApi"; +import { OrganizationData } from "../data/organizationData"; + +export class Organization { + id: string; + name: string; + status: OrganizationUserStatusType; + type: OrganizationUserType; + enabled: boolean; + usePolicies: boolean; + useGroups: boolean; + useDirectory: boolean; + useEvents: boolean; + useTotp: boolean; + use2fa: boolean; + useApi: boolean; + useSso: boolean; + useKeyConnector: boolean; + useResetPassword: boolean; + selfHost: boolean; + usersGetPremium: boolean; + seats: number; + maxCollections: number; + maxStorageGb?: number; + ssoBound: boolean; + identifier: string; + permissions: PermissionsApi; + resetPasswordEnrolled: boolean; + userId: string; + hasPublicAndPrivateKeys: boolean; + providerId: string; + providerName: string; + isProviderUser: boolean; + familySponsorshipFriendlyName: string; + familySponsorshipAvailable: boolean; + planProductType: ProductType; + keyConnectorEnabled: boolean; + keyConnectorUrl: string; + familySponsorshipLastSyncDate?: Date; + familySponsorshipValidUntil?: Date; + familySponsorshipToDelete?: boolean; + + constructor(obj?: OrganizationData) { + if (obj == null) { + return; + } + + this.id = obj.id; + this.name = obj.name; + this.status = obj.status; + this.type = obj.type; + this.enabled = obj.enabled; + this.usePolicies = obj.usePolicies; + this.useGroups = obj.useGroups; + this.useDirectory = obj.useDirectory; + this.useEvents = obj.useEvents; + this.useTotp = obj.useTotp; + this.use2fa = obj.use2fa; + this.useApi = obj.useApi; + this.useSso = obj.useSso; + this.useKeyConnector = obj.useKeyConnector; + this.useResetPassword = obj.useResetPassword; + this.selfHost = obj.selfHost; + this.usersGetPremium = obj.usersGetPremium; + this.seats = obj.seats; + this.maxCollections = obj.maxCollections; + this.maxStorageGb = obj.maxStorageGb; + this.ssoBound = obj.ssoBound; + this.identifier = obj.identifier; + this.permissions = obj.permissions; + this.resetPasswordEnrolled = obj.resetPasswordEnrolled; + this.userId = obj.userId; + this.hasPublicAndPrivateKeys = obj.hasPublicAndPrivateKeys; + this.providerId = obj.providerId; + this.providerName = obj.providerName; + this.isProviderUser = obj.isProviderUser; + this.familySponsorshipFriendlyName = obj.familySponsorshipFriendlyName; + this.familySponsorshipAvailable = obj.familySponsorshipAvailable; + this.planProductType = obj.planProductType; + this.keyConnectorEnabled = obj.keyConnectorEnabled; + this.keyConnectorUrl = obj.keyConnectorUrl; + this.familySponsorshipLastSyncDate = obj.familySponsorshipLastSyncDate; + this.familySponsorshipValidUntil = obj.familySponsorshipValidUntil; + this.familySponsorshipToDelete = obj.familySponsorshipToDelete; + } + + get canAccess() { + if (this.type === OrganizationUserType.Owner) { + return true; + } + return this.enabled && this.status === OrganizationUserStatusType.Confirmed; + } + + get isManager() { + return ( + this.type === OrganizationUserType.Manager || + this.type === OrganizationUserType.Owner || + this.type === OrganizationUserType.Admin + ); + } + + get isAdmin() { + return this.type === OrganizationUserType.Owner || this.type === OrganizationUserType.Admin; + } + + get isOwner() { + return this.type === OrganizationUserType.Owner || this.isProviderUser; + } + + get canAccessEventLogs() { + return this.isAdmin || this.permissions.accessEventLogs; + } + + get canAccessImportExport() { + return this.isAdmin || this.permissions.accessImportExport; + } + + get canAccessReports() { + return this.isAdmin || this.permissions.accessReports; + } + + get canCreateNewCollections() { + return ( + this.isManager || + (this.permissions.createNewCollections ?? this.permissions.manageAllCollections) + ); + } + + get canEditAnyCollection() { + return ( + this.isAdmin || (this.permissions.editAnyCollection ?? this.permissions.manageAllCollections) + ); + } + + get canDeleteAnyCollection() { + return ( + this.isAdmin || + (this.permissions.deleteAnyCollection ?? this.permissions.manageAllCollections) + ); + } + + get canViewAllCollections() { + return this.canCreateNewCollections || this.canEditAnyCollection || this.canDeleteAnyCollection; + } + + get canEditAssignedCollections() { + return ( + this.isManager || + (this.permissions.editAssignedCollections ?? this.permissions.manageAssignedCollections) + ); + } + + get canDeleteAssignedCollections() { + return ( + this.isManager || + (this.permissions.deleteAssignedCollections ?? this.permissions.manageAssignedCollections) + ); + } + + get canViewAssignedCollections() { + return this.canDeleteAssignedCollections || this.canEditAssignedCollections; + } + + get canManageGroups() { + return this.isAdmin || this.permissions.manageGroups; + } + + get canManageSso() { + return this.isAdmin || this.permissions.manageSso; + } + + get canManagePolicies() { + return this.isAdmin || this.permissions.managePolicies; + } + + get canManageUsers() { + return this.isAdmin || this.permissions.manageUsers; + } + + get canManageUsersPassword() { + return this.isAdmin || this.permissions.manageResetPassword; + } + + get isExemptFromPolicies() { + return this.canManagePolicies; + } + + hasAnyPermission(permissions: Permissions[]) { + const specifiedPermissions = + (permissions.includes(Permissions.AccessEventLogs) && this.canAccessEventLogs) || + (permissions.includes(Permissions.AccessImportExport) && this.canAccessImportExport) || + (permissions.includes(Permissions.AccessReports) && this.canAccessReports) || + (permissions.includes(Permissions.CreateNewCollections) && this.canCreateNewCollections) || + (permissions.includes(Permissions.EditAnyCollection) && this.canEditAnyCollection) || + (permissions.includes(Permissions.DeleteAnyCollection) && this.canDeleteAnyCollection) || + (permissions.includes(Permissions.EditAssignedCollections) && + this.canEditAssignedCollections) || + (permissions.includes(Permissions.DeleteAssignedCollections) && + this.canDeleteAssignedCollections) || + (permissions.includes(Permissions.ManageGroups) && this.canManageGroups) || + (permissions.includes(Permissions.ManageOrganization) && this.isOwner) || + (permissions.includes(Permissions.ManagePolicies) && this.canManagePolicies) || + (permissions.includes(Permissions.ManageUsers) && this.canManageUsers) || + (permissions.includes(Permissions.ManageUsersPassword) && this.canManageUsersPassword) || + (permissions.includes(Permissions.ManageSso) && this.canManageSso) || + (permissions.includes(Permissions.ManageBilling) && this.canManageBilling); + + return specifiedPermissions && (this.enabled || this.isOwner); + } + + get canManageBilling() { + return this.isOwner && (this.isProviderUser || !this.hasProvider); + } + + get hasProvider() { + return this.providerId != null || this.providerName != null; + } +} diff --git a/libs/common/src/models/domain/password.ts b/libs/common/src/models/domain/password.ts new file mode 100644 index 0000000000..ae47b18db8 --- /dev/null +++ b/libs/common/src/models/domain/password.ts @@ -0,0 +1,43 @@ +import { PasswordHistoryData } from "../data/passwordHistoryData"; +import { PasswordHistoryView } from "../view/passwordHistoryView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class Password extends Domain { + password: EncString; + lastUsedDate: Date; + + constructor(obj?: PasswordHistoryData) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel(this, obj, { + password: null, + }); + this.lastUsedDate = new Date(obj.lastUsedDate); + } + + decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + return this.decryptObj( + new PasswordHistoryView(this), + { + password: null, + }, + orgId, + encKey + ); + } + + toPasswordHistoryData(): PasswordHistoryData { + const ph = new PasswordHistoryData(); + ph.lastUsedDate = this.lastUsedDate.toISOString(); + this.buildDataModel(this, ph, { + password: null, + }); + return ph; + } +} diff --git a/libs/common/src/models/domain/passwordGeneratorPolicyOptions.ts b/libs/common/src/models/domain/passwordGeneratorPolicyOptions.ts new file mode 100644 index 0000000000..19072a9f7c --- /dev/null +++ b/libs/common/src/models/domain/passwordGeneratorPolicyOptions.ts @@ -0,0 +1,31 @@ +import Domain from "./domainBase"; + +export class PasswordGeneratorPolicyOptions extends Domain { + defaultType = ""; + minLength = 0; + useUppercase = false; + useLowercase = false; + useNumbers = false; + numberCount = 0; + useSpecial = false; + specialCount = 0; + minNumberWords = 0; + capitalize = false; + includeNumber = false; + + inEffect() { + return ( + this.defaultType !== "" || + this.minLength > 0 || + this.numberCount > 0 || + this.specialCount > 0 || + this.useUppercase || + this.useLowercase || + this.useNumbers || + this.useSpecial || + this.minNumberWords > 0 || + this.capitalize || + this.includeNumber + ); + } +} diff --git a/libs/common/src/models/domain/policy.ts b/libs/common/src/models/domain/policy.ts new file mode 100644 index 0000000000..c4a113cc33 --- /dev/null +++ b/libs/common/src/models/domain/policy.ts @@ -0,0 +1,25 @@ +import { PolicyType } from "../../enums/policyType"; +import { PolicyData } from "../data/policyData"; + +import Domain from "./domainBase"; + +export class Policy extends Domain { + id: string; + organizationId: string; + type: PolicyType; + data: any; + enabled: boolean; + + constructor(obj?: PolicyData) { + super(); + if (obj == null) { + return; + } + + this.id = obj.id; + this.organizationId = obj.organizationId; + this.type = obj.type; + this.data = obj.data; + this.enabled = obj.enabled; + } +} diff --git a/libs/common/src/models/domain/provider.ts b/libs/common/src/models/domain/provider.ts new file mode 100644 index 0000000000..6e14340ba5 --- /dev/null +++ b/libs/common/src/models/domain/provider.ts @@ -0,0 +1,50 @@ +import { ProviderUserStatusType } from "../../enums/providerUserStatusType"; +import { ProviderUserType } from "../../enums/providerUserType"; +import { ProviderData } from "../data/providerData"; + +export class Provider { + id: string; + name: string; + status: ProviderUserStatusType; + type: ProviderUserType; + enabled: boolean; + userId: string; + useEvents: boolean; + + constructor(obj?: ProviderData) { + if (obj == null) { + return; + } + + this.id = obj.id; + this.name = obj.name; + this.status = obj.status; + this.type = obj.type; + this.enabled = obj.enabled; + this.userId = obj.userId; + this.useEvents = obj.useEvents; + } + + get canAccess() { + if (this.isProviderAdmin) { + return true; + } + return this.enabled && this.status === ProviderUserStatusType.Confirmed; + } + + get canCreateOrganizations() { + return this.enabled && this.isProviderAdmin; + } + + get canManageUsers() { + return this.isProviderAdmin; + } + + get canAccessEventLogs() { + return this.isProviderAdmin; + } + + get isProviderAdmin() { + return this.type === ProviderUserType.ProviderAdmin; + } +} diff --git a/libs/common/src/models/domain/resetPasswordPolicyOptions.ts b/libs/common/src/models/domain/resetPasswordPolicyOptions.ts new file mode 100644 index 0000000000..2ee11a5c27 --- /dev/null +++ b/libs/common/src/models/domain/resetPasswordPolicyOptions.ts @@ -0,0 +1,5 @@ +import Domain from "./domainBase"; + +export class ResetPasswordPolicyOptions extends Domain { + autoEnrollEnabled = false; +} diff --git a/libs/common/src/models/domain/secureNote.ts b/libs/common/src/models/domain/secureNote.ts new file mode 100644 index 0000000000..8bde3164e7 --- /dev/null +++ b/libs/common/src/models/domain/secureNote.ts @@ -0,0 +1,29 @@ +import { SecureNoteType } from "../../enums/secureNoteType"; +import { SecureNoteData } from "../data/secureNoteData"; +import { SecureNoteView } from "../view/secureNoteView"; + +import Domain from "./domainBase"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class SecureNote extends Domain { + type: SecureNoteType; + + constructor(obj?: SecureNoteData) { + super(); + if (obj == null) { + return; + } + + this.type = obj.type; + } + + decrypt(orgId: string, encKey?: SymmetricCryptoKey): Promise { + return Promise.resolve(new SecureNoteView(this)); + } + + toSecureNoteData(): SecureNoteData { + const n = new SecureNoteData(); + n.type = this.type; + return n; + } +} diff --git a/libs/common/src/models/domain/send.ts b/libs/common/src/models/domain/send.ts new file mode 100644 index 0000000000..a398ac2dbf --- /dev/null +++ b/libs/common/src/models/domain/send.ts @@ -0,0 +1,112 @@ +import { CryptoService } from "../../abstractions/crypto.service"; +import { SendType } from "../../enums/sendType"; +import { Utils } from "../../misc/utils"; +import { SendData } from "../data/sendData"; +import { SendView } from "../view/sendView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SendFile } from "./sendFile"; +import { SendText } from "./sendText"; + +export class Send extends Domain { + id: string; + accessId: string; + type: SendType; + name: EncString; + notes: EncString; + file: SendFile; + text: SendText; + key: EncString; + maxAccessCount?: number; + accessCount: number; + revisionDate: Date; + expirationDate: Date; + deletionDate: Date; + password: string; + disabled: boolean; + hideEmail: boolean; + + constructor(obj?: SendData) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel( + this, + obj, + { + id: null, + accessId: null, + name: null, + notes: null, + key: null, + }, + ["id", "accessId"] + ); + + this.type = obj.type; + this.maxAccessCount = obj.maxAccessCount; + this.accessCount = obj.accessCount; + this.password = obj.password; + this.disabled = obj.disabled; + this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null; + this.deletionDate = obj.deletionDate != null ? new Date(obj.deletionDate) : null; + this.expirationDate = obj.expirationDate != null ? new Date(obj.expirationDate) : null; + this.hideEmail = obj.hideEmail; + + switch (this.type) { + case SendType.Text: + this.text = new SendText(obj.text); + break; + case SendType.File: + this.file = new SendFile(obj.file); + break; + default: + break; + } + } + + async decrypt(): Promise { + const model = new SendView(this); + + let cryptoService: CryptoService; + const containerService = (Utils.global as any).bitwardenContainerService; + if (containerService) { + cryptoService = containerService.getCryptoService(); + } else { + throw new Error("global bitwardenContainerService not initialized."); + } + + try { + model.key = await cryptoService.decryptToBytes(this.key, null); + model.cryptoKey = await cryptoService.makeSendKey(model.key); + } catch (e) { + // TODO: error? + } + + await this.decryptObj( + model, + { + name: null, + notes: null, + }, + null, + model.cryptoKey + ); + + switch (this.type) { + case SendType.File: + model.file = await this.file.decrypt(model.cryptoKey); + break; + case SendType.Text: + model.text = await this.text.decrypt(model.cryptoKey); + break; + default: + break; + } + + return model; + } +} diff --git a/libs/common/src/models/domain/sendAccess.ts b/libs/common/src/models/domain/sendAccess.ts new file mode 100644 index 0000000000..dab68cc646 --- /dev/null +++ b/libs/common/src/models/domain/sendAccess.ts @@ -0,0 +1,77 @@ +import { SendType } from "../../enums/sendType"; +import { SendAccessResponse } from "../response/sendAccessResponse"; +import { SendAccessView } from "../view/sendAccessView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SendFile } from "./sendFile"; +import { SendText } from "./sendText"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class SendAccess extends Domain { + id: string; + type: SendType; + name: EncString; + file: SendFile; + text: SendText; + expirationDate: Date; + creatorIdentifier: string; + + constructor(obj?: SendAccessResponse) { + super(); + if (obj == null) { + return; + } + + this.buildDomainModel( + this, + obj, + { + id: null, + name: null, + expirationDate: null, + creatorIdentifier: null, + }, + ["id", "expirationDate", "creatorIdentifier"] + ); + + this.type = obj.type; + + switch (this.type) { + case SendType.Text: + this.text = new SendText(obj.text); + break; + case SendType.File: + this.file = new SendFile(obj.file); + break; + default: + break; + } + } + + async decrypt(key: SymmetricCryptoKey): Promise { + const model = new SendAccessView(this); + + await this.decryptObj( + model, + { + name: null, + }, + null, + key + ); + + switch (this.type) { + case SendType.File: + model.file = await this.file.decrypt(key); + break; + case SendType.Text: + model.text = await this.text.decrypt(key); + break; + default: + break; + } + + return model; + } +} diff --git a/libs/common/src/models/domain/sendFile.ts b/libs/common/src/models/domain/sendFile.ts new file mode 100644 index 0000000000..177994078f --- /dev/null +++ b/libs/common/src/models/domain/sendFile.ts @@ -0,0 +1,44 @@ +import { SendFileData } from "../data/sendFileData"; +import { SendFileView } from "../view/sendFileView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class SendFile extends Domain { + id: string; + size: string; + sizeName: string; + fileName: EncString; + + constructor(obj?: SendFileData) { + super(); + if (obj == null) { + return; + } + + this.size = obj.size; + this.buildDomainModel( + this, + obj, + { + id: null, + sizeName: null, + fileName: null, + }, + ["id", "sizeName"] + ); + } + + async decrypt(key: SymmetricCryptoKey): Promise { + const view = await this.decryptObj( + new SendFileView(this), + { + fileName: null, + }, + null, + key + ); + return view; + } +} diff --git a/libs/common/src/models/domain/sendText.ts b/libs/common/src/models/domain/sendText.ts new file mode 100644 index 0000000000..523e5ee58a --- /dev/null +++ b/libs/common/src/models/domain/sendText.ts @@ -0,0 +1,39 @@ +import { SendTextData } from "../data/sendTextData"; +import { SendTextView } from "../view/sendTextView"; + +import Domain from "./domainBase"; +import { EncString } from "./encString"; +import { SymmetricCryptoKey } from "./symmetricCryptoKey"; + +export class SendText extends Domain { + text: EncString; + hidden: boolean; + + constructor(obj?: SendTextData) { + super(); + if (obj == null) { + return; + } + + this.hidden = obj.hidden; + this.buildDomainModel( + this, + obj, + { + text: null, + }, + [] + ); + } + + decrypt(key: SymmetricCryptoKey): Promise { + return this.decryptObj( + new SendTextView(this), + { + text: null, + }, + null, + key + ); + } +} diff --git a/libs/common/src/models/domain/sortedCiphersCache.ts b/libs/common/src/models/domain/sortedCiphersCache.ts new file mode 100644 index 0000000000..8c32744e23 --- /dev/null +++ b/libs/common/src/models/domain/sortedCiphersCache.ts @@ -0,0 +1,87 @@ +import { CipherView } from "../view/cipherView"; + +const CacheTTL = 3000; + +export class SortedCiphersCache { + private readonly sortedCiphersByUrl: Map = new Map(); + private readonly timeouts: Map = new Map(); + + constructor(private readonly comparator: (a: CipherView, b: CipherView) => number) {} + + isCached(url: string) { + return this.sortedCiphersByUrl.has(url); + } + + addCiphers(url: string, ciphers: CipherView[]) { + ciphers.sort(this.comparator); + this.sortedCiphersByUrl.set(url, new Ciphers(ciphers)); + this.resetTimer(url); + } + + getLastUsed(url: string) { + this.resetTimer(url); + return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getLastUsed() : null; + } + + getLastLaunched(url: string) { + return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getLastLaunched() : null; + } + + getNext(url: string) { + this.resetTimer(url); + return this.isCached(url) ? this.sortedCiphersByUrl.get(url).getNext() : null; + } + + updateLastUsedIndex(url: string) { + if (this.isCached(url)) { + this.sortedCiphersByUrl.get(url).updateLastUsedIndex(); + } + } + + clear() { + this.sortedCiphersByUrl.clear(); + this.timeouts.clear(); + } + + private resetTimer(url: string) { + clearTimeout(this.timeouts.get(url)); + this.timeouts.set( + url, + setTimeout(() => { + this.sortedCiphersByUrl.delete(url); + this.timeouts.delete(url); + }, CacheTTL) + ); + } +} + +class Ciphers { + lastUsedIndex = -1; + + constructor(private readonly ciphers: CipherView[]) {} + + getLastUsed() { + this.lastUsedIndex = Math.max(this.lastUsedIndex, 0); + return this.ciphers[this.lastUsedIndex]; + } + + getLastLaunched() { + const usedCiphers = this.ciphers.filter((cipher) => cipher.localData?.lastLaunched); + const sortedCiphers = usedCiphers.sort( + (x, y) => y.localData.lastLaunched.valueOf() - x.localData.lastLaunched.valueOf() + ); + return sortedCiphers[0]; + } + + getNextIndex() { + return (this.lastUsedIndex + 1) % this.ciphers.length; + } + + getNext() { + return this.ciphers[this.getNextIndex()]; + } + + updateLastUsedIndex() { + this.lastUsedIndex = this.getNextIndex(); + } +} diff --git a/libs/common/src/models/domain/state.ts b/libs/common/src/models/domain/state.ts new file mode 100644 index 0000000000..f5a2c046b5 --- /dev/null +++ b/libs/common/src/models/domain/state.ts @@ -0,0 +1,17 @@ +import { Account } from "./account"; +import { GlobalState } from "./globalState"; + +export class State< + TGlobalState extends GlobalState = GlobalState, + TAccount extends Account = Account +> { + accounts: { [userId: string]: TAccount } = {}; + globals: TGlobalState; + activeUserId: string; + authenticatedAccounts: string[] = []; + accountActivity: { [userId: string]: number } = {}; + + constructor(globals: TGlobalState) { + this.globals = globals; + } +} diff --git a/libs/common/src/models/domain/storageOptions.ts b/libs/common/src/models/domain/storageOptions.ts new file mode 100644 index 0000000000..2db7e0ccf5 --- /dev/null +++ b/libs/common/src/models/domain/storageOptions.ts @@ -0,0 +1,10 @@ +import { HtmlStorageLocation } from "../../enums/htmlStorageLocation"; +import { StorageLocation } from "../../enums/storageLocation"; + +export type StorageOptions = { + storageLocation?: StorageLocation; + useSecureStorage?: boolean; + userId?: string; + htmlStorageLocation?: HtmlStorageLocation; + keySuffix?: string; +}; diff --git a/libs/common/src/models/domain/symmetricCryptoKey.ts b/libs/common/src/models/domain/symmetricCryptoKey.ts new file mode 100644 index 0000000000..a58dc6fde4 --- /dev/null +++ b/libs/common/src/models/domain/symmetricCryptoKey.ts @@ -0,0 +1,57 @@ +import { EncryptionType } from "../../enums/encryptionType"; +import { Utils } from "../../misc/utils"; + +export class SymmetricCryptoKey { + key: ArrayBuffer; + encKey?: ArrayBuffer; + macKey?: ArrayBuffer; + encType: EncryptionType; + + keyB64: string; + encKeyB64: string; + macKeyB64: string; + + meta: any; + + constructor(key: ArrayBuffer, encType?: EncryptionType) { + if (key == null) { + throw new Error("Must provide key"); + } + + if (encType == null) { + if (key.byteLength === 32) { + encType = EncryptionType.AesCbc256_B64; + } else if (key.byteLength === 64) { + encType = EncryptionType.AesCbc256_HmacSha256_B64; + } else { + throw new Error("Unable to determine encType."); + } + } + + this.key = key; + this.encType = encType; + + if (encType === EncryptionType.AesCbc256_B64 && key.byteLength === 32) { + this.encKey = key; + this.macKey = null; + } else if (encType === EncryptionType.AesCbc128_HmacSha256_B64 && key.byteLength === 32) { + this.encKey = key.slice(0, 16); + this.macKey = key.slice(16, 32); + } else if (encType === EncryptionType.AesCbc256_HmacSha256_B64 && key.byteLength === 64) { + this.encKey = key.slice(0, 32); + this.macKey = key.slice(32, 64); + } else { + throw new Error("Unsupported encType/key length."); + } + + if (this.key != null) { + this.keyB64 = Utils.fromBufferToB64(this.key); + } + if (this.encKey != null) { + this.encKeyB64 = Utils.fromBufferToB64(this.encKey); + } + if (this.macKey != null) { + this.macKeyB64 = Utils.fromBufferToB64(this.macKey); + } + } +} diff --git a/libs/common/src/models/domain/treeNode.ts b/libs/common/src/models/domain/treeNode.ts new file mode 100644 index 0000000000..6af973a595 --- /dev/null +++ b/libs/common/src/models/domain/treeNode.ts @@ -0,0 +1,16 @@ +export class TreeNode { + parent: T; + node: T; + children: TreeNode[] = []; + + constructor(node: T, name: string, parent: T) { + this.parent = parent; + this.node = node; + this.node.name = name; + } +} + +export interface ITreeNodeObject { + id: string; + name: string; +} diff --git a/libs/common/src/models/domain/windowState.ts b/libs/common/src/models/domain/windowState.ts new file mode 100644 index 0000000000..cb260d8b08 --- /dev/null +++ b/libs/common/src/models/domain/windowState.ts @@ -0,0 +1,10 @@ +export class WindowState { + width?: number; + height?: number; + isMaximized?: boolean; + // TODO: displayBounds is an Electron.Rectangle. + // We need to establish some kind of client-specific global state, similiar to the way we already extend a base Account. + displayBounds: any; + x?: number; + y?: number; +} diff --git a/libs/common/src/models/export/cardExport.ts b/libs/common/src/models/export/cardExport.ts new file mode 100644 index 0000000000..b0525e4e9c --- /dev/null +++ b/libs/common/src/models/export/cardExport.ts @@ -0,0 +1,65 @@ +import { Card as CardDomain } from "../domain/card"; +import { EncString } from "../domain/encString"; +import { CardView } from "../view/cardView"; + +export class CardExport { + static template(): CardExport { + const req = new CardExport(); + req.cardholderName = "John Doe"; + req.brand = "visa"; + req.number = "4242424242424242"; + req.expMonth = "04"; + req.expYear = "2023"; + req.code = "123"; + return req; + } + + static toView(req: CardExport, view = new CardView()) { + view.cardholderName = req.cardholderName; + view.brand = req.brand; + view.number = req.number; + view.expMonth = req.expMonth; + view.expYear = req.expYear; + view.code = req.code; + return view; + } + + static toDomain(req: CardExport, domain = new CardDomain()) { + domain.cardholderName = req.cardholderName != null ? new EncString(req.cardholderName) : null; + domain.brand = req.brand != null ? new EncString(req.brand) : null; + domain.number = req.number != null ? new EncString(req.number) : null; + domain.expMonth = req.expMonth != null ? new EncString(req.expMonth) : null; + domain.expYear = req.expYear != null ? new EncString(req.expYear) : null; + domain.code = req.code != null ? new EncString(req.code) : null; + return domain; + } + + cardholderName: string; + brand: string; + number: string; + expMonth: string; + expYear: string; + code: string; + + constructor(o?: CardView | CardDomain) { + if (o == null) { + return; + } + + if (o instanceof CardView) { + this.cardholderName = o.cardholderName; + this.brand = o.brand; + this.number = o.number; + this.expMonth = o.expMonth; + this.expYear = o.expYear; + this.code = o.code; + } else { + this.cardholderName = o.cardholderName?.encryptedString; + this.brand = o.brand?.encryptedString; + this.number = o.number?.encryptedString; + this.expMonth = o.expMonth?.encryptedString; + this.expYear = o.expYear?.encryptedString; + this.code = o.code?.encryptedString; + } + } +} diff --git a/libs/common/src/models/export/cipherExport.ts b/libs/common/src/models/export/cipherExport.ts new file mode 100644 index 0000000000..33f66ffd79 --- /dev/null +++ b/libs/common/src/models/export/cipherExport.ts @@ -0,0 +1,156 @@ +import { CipherRepromptType } from "../../enums/cipherRepromptType"; +import { CipherType } from "../../enums/cipherType"; +import { Cipher as CipherDomain } from "../domain/cipher"; +import { EncString } from "../domain/encString"; +import { CipherView } from "../view/cipherView"; + +import { CardExport } from "./cardExport"; +import { FieldExport } from "./fieldExport"; +import { IdentityExport } from "./identityExport"; +import { LoginExport } from "./loginExport"; +import { SecureNoteExport } from "./secureNoteExport"; + +export class CipherExport { + static template(): CipherExport { + const req = new CipherExport(); + req.organizationId = null; + req.collectionIds = null; + req.folderId = null; + req.type = CipherType.Login; + req.name = "Item name"; + req.notes = "Some notes about this item."; + req.favorite = false; + req.fields = []; + req.login = null; + req.secureNote = null; + req.card = null; + req.identity = null; + req.reprompt = CipherRepromptType.None; + return req; + } + + static toView(req: CipherExport, view = new CipherView()) { + view.type = req.type; + view.folderId = req.folderId; + if (view.organizationId == null) { + view.organizationId = req.organizationId; + } + if (view.collectionIds || req.collectionIds) { + const set = new Set((view.collectionIds ?? []).concat(req.collectionIds ?? [])); + view.collectionIds = Array.from(set.values()); + } + view.name = req.name; + view.notes = req.notes; + view.favorite = req.favorite; + view.reprompt = req.reprompt ?? CipherRepromptType.None; + + if (req.fields != null) { + view.fields = req.fields.map((f) => FieldExport.toView(f)); + } + + switch (req.type) { + case CipherType.Login: + view.login = LoginExport.toView(req.login); + break; + case CipherType.SecureNote: + view.secureNote = SecureNoteExport.toView(req.secureNote); + break; + case CipherType.Card: + view.card = CardExport.toView(req.card); + break; + case CipherType.Identity: + view.identity = IdentityExport.toView(req.identity); + break; + } + + return view; + } + + static toDomain(req: CipherExport, domain = new CipherDomain()) { + domain.type = req.type; + domain.folderId = req.folderId; + if (domain.organizationId == null) { + domain.organizationId = req.organizationId; + } + domain.name = req.name != null ? new EncString(req.name) : null; + domain.notes = req.notes != null ? new EncString(req.notes) : null; + domain.favorite = req.favorite; + domain.reprompt = req.reprompt ?? CipherRepromptType.None; + + if (req.fields != null) { + domain.fields = req.fields.map((f) => FieldExport.toDomain(f)); + } + + switch (req.type) { + case CipherType.Login: + domain.login = LoginExport.toDomain(req.login); + break; + case CipherType.SecureNote: + domain.secureNote = SecureNoteExport.toDomain(req.secureNote); + break; + case CipherType.Card: + domain.card = CardExport.toDomain(req.card); + break; + case CipherType.Identity: + domain.identity = IdentityExport.toDomain(req.identity); + break; + } + + return domain; + } + + type: CipherType; + folderId: string; + organizationId: string; + collectionIds: string[]; + name: string; + notes: string; + favorite: boolean; + fields: FieldExport[]; + login: LoginExport; + secureNote: SecureNoteExport; + card: CardExport; + identity: IdentityExport; + reprompt: CipherRepromptType; + + // Use build method instead of ctor so that we can control order of JSON stringify for pretty print + build(o: CipherView | CipherDomain) { + this.organizationId = o.organizationId; + this.folderId = o.folderId; + this.type = o.type; + this.reprompt = o.reprompt; + + if (o instanceof CipherView) { + this.name = o.name; + this.notes = o.notes; + } else { + this.name = o.name?.encryptedString; + this.notes = o.notes?.encryptedString; + } + + this.favorite = o.favorite; + + if (o.fields != null) { + if (o instanceof CipherView) { + this.fields = o.fields.map((f) => new FieldExport(f)); + } else { + this.fields = o.fields.map((f) => new FieldExport(f)); + } + } + + switch (o.type) { + case CipherType.Login: + this.login = new LoginExport(o.login); + break; + case CipherType.SecureNote: + this.secureNote = new SecureNoteExport(o.secureNote); + break; + case CipherType.Card: + this.card = new CardExport(o.card); + break; + case CipherType.Identity: + this.identity = new IdentityExport(o.identity); + break; + } + } +} diff --git a/libs/common/src/models/export/cipherWithIdsExport.ts b/libs/common/src/models/export/cipherWithIdsExport.ts new file mode 100644 index 0000000000..c9d789640b --- /dev/null +++ b/libs/common/src/models/export/cipherWithIdsExport.ts @@ -0,0 +1,16 @@ +import { Cipher as CipherDomain } from "../domain/cipher"; +import { CipherView } from "../view/cipherView"; + +import { CipherExport } from "./cipherExport"; + +export class CipherWithIdExport extends CipherExport { + id: string; + collectionIds: string[]; + + // Use build method instead of ctor so that we can control order of JSON stringify for pretty print + build(o: CipherView | CipherDomain) { + this.id = o.id; + super.build(o); + this.collectionIds = o.collectionIds; + } +} diff --git a/libs/common/src/models/export/collectionExport.ts b/libs/common/src/models/export/collectionExport.ts new file mode 100644 index 0000000000..fe0777af1f --- /dev/null +++ b/libs/common/src/models/export/collectionExport.ts @@ -0,0 +1,46 @@ +import { Collection as CollectionDomain } from "../domain/collection"; +import { EncString } from "../domain/encString"; +import { CollectionView } from "../view/collectionView"; + +export class CollectionExport { + static template(): CollectionExport { + const req = new CollectionExport(); + req.organizationId = "00000000-0000-0000-0000-000000000000"; + req.name = "Collection name"; + req.externalId = null; + return req; + } + + static toView(req: CollectionExport, view = new CollectionView()) { + view.name = req.name; + view.externalId = req.externalId; + if (view.organizationId == null) { + view.organizationId = req.organizationId; + } + return view; + } + + static toDomain(req: CollectionExport, domain = new CollectionDomain()) { + domain.name = req.name != null ? new EncString(req.name) : null; + domain.externalId = req.externalId; + if (domain.organizationId == null) { + domain.organizationId = req.organizationId; + } + return domain; + } + + organizationId: string; + name: string; + externalId: string; + + // Use build method instead of ctor so that we can control order of JSON stringify for pretty print + build(o: CollectionView | CollectionDomain) { + this.organizationId = o.organizationId; + if (o instanceof CollectionView) { + this.name = o.name; + } else { + this.name = o.name?.encryptedString; + } + this.externalId = o.externalId; + } +} diff --git a/libs/common/src/models/export/collectionWithIdExport.ts b/libs/common/src/models/export/collectionWithIdExport.ts new file mode 100644 index 0000000000..7c668f8a9c --- /dev/null +++ b/libs/common/src/models/export/collectionWithIdExport.ts @@ -0,0 +1,14 @@ +import { Collection as CollectionDomain } from "../domain/collection"; +import { CollectionView } from "../view/collectionView"; + +import { CollectionExport } from "./collectionExport"; + +export class CollectionWithIdExport extends CollectionExport { + id: string; + + // Use build method instead of ctor so that we can control order of JSON stringify for pretty print + build(o: CollectionView | CollectionDomain) { + this.id = o.id; + super.build(o); + } +} diff --git a/libs/common/src/models/export/eventExport.ts b/libs/common/src/models/export/eventExport.ts new file mode 100644 index 0000000000..670c1b166a --- /dev/null +++ b/libs/common/src/models/export/eventExport.ts @@ -0,0 +1,28 @@ +import { EventType } from "../../enums/eventType"; +import { EventView } from "../view/eventView"; + +export class EventExport { + message: string; + appIcon: string; + appName: string; + userId: string; + userName: string; + userEmail: string; + date: string; + ip: string; + type: string; + installationId: string; + + constructor(event: EventView) { + this.message = event.humanReadableMessage; + this.appIcon = event.appIcon; + this.appName = event.appName; + this.userId = event.userId; + this.userName = event.userName; + this.userEmail = event.userEmail; + this.date = event.date; + this.ip = event.ip; + this.type = EventType[event.type]; + this.installationId = event.installationId; + } +} diff --git a/libs/common/src/models/export/fieldExport.ts b/libs/common/src/models/export/fieldExport.ts new file mode 100644 index 0000000000..13cc2d9fa3 --- /dev/null +++ b/libs/common/src/models/export/fieldExport.ts @@ -0,0 +1,52 @@ +import { FieldType } from "../../enums/fieldType"; +import { LinkedIdType } from "../../enums/linkedIdType"; +import { EncString } from "../domain/encString"; +import { Field as FieldDomain } from "../domain/field"; +import { FieldView } from "../view/fieldView"; + +export class FieldExport { + static template(): FieldExport { + const req = new FieldExport(); + req.name = "Field name"; + req.value = "Some value"; + req.type = FieldType.Text; + return req; + } + + static toView(req: FieldExport, view = new FieldView()) { + view.type = req.type; + view.value = req.value; + view.name = req.name; + view.linkedId = req.linkedId; + return view; + } + + static toDomain(req: FieldExport, domain = new FieldDomain()) { + domain.type = req.type; + domain.value = req.value != null ? new EncString(req.value) : null; + domain.name = req.name != null ? new EncString(req.name) : null; + domain.linkedId = req.linkedId; + return domain; + } + + name: string; + value: string; + type: FieldType; + linkedId: LinkedIdType; + + constructor(o?: FieldView | FieldDomain) { + if (o == null) { + return; + } + + if (o instanceof FieldView) { + this.name = o.name; + this.value = o.value; + } else { + this.name = o.name?.encryptedString; + this.value = o.value?.encryptedString; + } + this.type = o.type; + this.linkedId = o.linkedId; + } +} diff --git a/libs/common/src/models/export/folderExport.ts b/libs/common/src/models/export/folderExport.ts new file mode 100644 index 0000000000..8f3483c357 --- /dev/null +++ b/libs/common/src/models/export/folderExport.ts @@ -0,0 +1,32 @@ +import { EncString } from "../domain/encString"; +import { Folder as FolderDomain } from "../domain/folder"; +import { FolderView } from "../view/folderView"; + +export class FolderExport { + static template(): FolderExport { + const req = new FolderExport(); + req.name = "Folder name"; + return req; + } + + static toView(req: FolderExport, view = new FolderView()) { + view.name = req.name; + return view; + } + + static toDomain(req: FolderExport, domain = new FolderDomain()) { + domain.name = req.name != null ? new EncString(req.name) : null; + return domain; + } + + name: string; + + // Use build method instead of ctor so that we can control order of JSON stringify for pretty print + build(o: FolderView | FolderDomain) { + if (o instanceof FolderView) { + this.name = o.name; + } else { + this.name = o.name?.encryptedString; + } + } +} diff --git a/libs/common/src/models/export/folderWithIdExport.ts b/libs/common/src/models/export/folderWithIdExport.ts new file mode 100644 index 0000000000..77c96811c4 --- /dev/null +++ b/libs/common/src/models/export/folderWithIdExport.ts @@ -0,0 +1,14 @@ +import { Folder as FolderDomain } from "../domain/folder"; +import { FolderView } from "../view/folderView"; + +import { FolderExport } from "./folderExport"; + +export class FolderWithIdExport extends FolderExport { + id: string; + + // Use build method instead of ctor so that we can control order of JSON stringify for pretty print + build(o: FolderView | FolderDomain) { + this.id = o.id; + super.build(o); + } +} diff --git a/libs/common/src/models/export/identityExport.ts b/libs/common/src/models/export/identityExport.ts new file mode 100644 index 0000000000..c8f06e9e95 --- /dev/null +++ b/libs/common/src/models/export/identityExport.ts @@ -0,0 +1,137 @@ +import { EncString } from "../domain/encString"; +import { Identity as IdentityDomain } from "../domain/identity"; +import { IdentityView } from "../view/identityView"; + +export class IdentityExport { + static template(): IdentityExport { + const req = new IdentityExport(); + req.title = "Mr"; + req.firstName = "John"; + req.middleName = "William"; + req.lastName = "Doe"; + req.address1 = "123 Any St"; + req.address2 = "Apt #123"; + req.address3 = null; + req.city = "New York"; + req.state = "NY"; + req.postalCode = "10001"; + req.country = "US"; + req.company = "Acme Inc."; + req.email = "john@company.com"; + req.phone = "5555551234"; + req.ssn = "000-123-4567"; + req.username = "jdoe"; + req.passportNumber = "US-123456789"; + req.licenseNumber = "D123-12-123-12333"; + return req; + } + + static toView(req: IdentityExport, view = new IdentityView()) { + view.title = req.title; + view.firstName = req.firstName; + view.middleName = req.middleName; + view.lastName = req.lastName; + view.address1 = req.address1; + view.address2 = req.address2; + view.address3 = req.address3; + view.city = req.city; + view.state = req.state; + view.postalCode = req.postalCode; + view.country = req.country; + view.company = req.company; + view.email = req.email; + view.phone = req.phone; + view.ssn = req.ssn; + view.username = req.username; + view.passportNumber = req.passportNumber; + view.licenseNumber = req.licenseNumber; + return view; + } + + static toDomain(req: IdentityExport, domain = new IdentityDomain()) { + domain.title = req.title != null ? new EncString(req.title) : null; + domain.firstName = req.firstName != null ? new EncString(req.firstName) : null; + domain.middleName = req.middleName != null ? new EncString(req.middleName) : null; + domain.lastName = req.lastName != null ? new EncString(req.lastName) : null; + domain.address1 = req.address1 != null ? new EncString(req.address1) : null; + domain.address2 = req.address2 != null ? new EncString(req.address2) : null; + domain.address3 = req.address3 != null ? new EncString(req.address3) : null; + domain.city = req.city != null ? new EncString(req.city) : null; + domain.state = req.state != null ? new EncString(req.state) : null; + domain.postalCode = req.postalCode != null ? new EncString(req.postalCode) : null; + domain.country = req.country != null ? new EncString(req.country) : null; + domain.company = req.company != null ? new EncString(req.company) : null; + domain.email = req.email != null ? new EncString(req.email) : null; + domain.phone = req.phone != null ? new EncString(req.phone) : null; + domain.ssn = req.ssn != null ? new EncString(req.ssn) : null; + domain.username = req.username != null ? new EncString(req.username) : null; + domain.passportNumber = req.passportNumber != null ? new EncString(req.passportNumber) : null; + domain.licenseNumber = req.licenseNumber != null ? new EncString(req.licenseNumber) : null; + return domain; + } + + title: string; + firstName: string; + middleName: string; + lastName: string; + address1: string; + address2: string; + address3: string; + city: string; + state: string; + postalCode: string; + country: string; + company: string; + email: string; + phone: string; + ssn: string; + username: string; + passportNumber: string; + licenseNumber: string; + + constructor(o?: IdentityView | IdentityDomain) { + if (o == null) { + return; + } + + if (o instanceof IdentityView) { + this.title = o.title; + this.firstName = o.firstName; + this.middleName = o.middleName; + this.lastName = o.lastName; + this.address1 = o.address1; + this.address2 = o.address2; + this.address3 = o.address3; + this.city = o.city; + this.state = o.state; + this.postalCode = o.postalCode; + this.country = o.country; + this.company = o.company; + this.email = o.email; + this.phone = o.phone; + this.ssn = o.ssn; + this.username = o.username; + this.passportNumber = o.passportNumber; + this.licenseNumber = o.licenseNumber; + } else { + this.title = o.title?.encryptedString; + this.firstName = o.firstName?.encryptedString; + this.middleName = o.middleName?.encryptedString; + this.lastName = o.lastName?.encryptedString; + this.address1 = o.address1?.encryptedString; + this.address2 = o.address2?.encryptedString; + this.address3 = o.address3?.encryptedString; + this.city = o.city?.encryptedString; + this.state = o.state?.encryptedString; + this.postalCode = o.postalCode?.encryptedString; + this.country = o.country?.encryptedString; + this.company = o.company?.encryptedString; + this.email = o.email?.encryptedString; + this.phone = o.phone?.encryptedString; + this.ssn = o.ssn?.encryptedString; + this.username = o.username?.encryptedString; + this.passportNumber = o.passportNumber?.encryptedString; + this.licenseNumber = o.licenseNumber?.encryptedString; + } + } +} diff --git a/libs/common/src/models/export/loginExport.ts b/libs/common/src/models/export/loginExport.ts new file mode 100644 index 0000000000..1be631daa9 --- /dev/null +++ b/libs/common/src/models/export/loginExport.ts @@ -0,0 +1,65 @@ +import { EncString } from "../domain/encString"; +import { Login as LoginDomain } from "../domain/login"; +import { LoginView } from "../view/loginView"; + +import { LoginUriExport } from "./loginUriExport"; + +export class LoginExport { + static template(): LoginExport { + const req = new LoginExport(); + req.uris = []; + req.username = "jdoe"; + req.password = "myp@ssword123"; + req.totp = "JBSWY3DPEHPK3PXP"; + return req; + } + + static toView(req: LoginExport, view = new LoginView()) { + if (req.uris != null) { + view.uris = req.uris.map((u) => LoginUriExport.toView(u)); + } + view.username = req.username; + view.password = req.password; + view.totp = req.totp; + return view; + } + + static toDomain(req: LoginExport, domain = new LoginDomain()) { + if (req.uris != null) { + domain.uris = req.uris.map((u) => LoginUriExport.toDomain(u)); + } + domain.username = req.username != null ? new EncString(req.username) : null; + domain.password = req.password != null ? new EncString(req.password) : null; + domain.totp = req.totp != null ? new EncString(req.totp) : null; + return domain; + } + + uris: LoginUriExport[]; + username: string; + password: string; + totp: string; + + constructor(o?: LoginView | LoginDomain) { + if (o == null) { + return; + } + + if (o.uris != null) { + if (o instanceof LoginView) { + this.uris = o.uris.map((u) => new LoginUriExport(u)); + } else { + this.uris = o.uris.map((u) => new LoginUriExport(u)); + } + } + + if (o instanceof LoginView) { + this.username = o.username; + this.password = o.password; + this.totp = o.totp; + } else { + this.username = o.username?.encryptedString; + this.password = o.password?.encryptedString; + this.totp = o.totp?.encryptedString; + } + } +} diff --git a/libs/common/src/models/export/loginUriExport.ts b/libs/common/src/models/export/loginUriExport.ts new file mode 100644 index 0000000000..b27d8ba84f --- /dev/null +++ b/libs/common/src/models/export/loginUriExport.ts @@ -0,0 +1,41 @@ +import { UriMatchType } from "../../enums/uriMatchType"; +import { EncString } from "../domain/encString"; +import { LoginUri as LoginUriDomain } from "../domain/loginUri"; +import { LoginUriView } from "../view/loginUriView"; + +export class LoginUriExport { + static template(): LoginUriExport { + const req = new LoginUriExport(); + req.uri = "https://google.com"; + req.match = null; + return req; + } + + static toView(req: LoginUriExport, view = new LoginUriView()) { + view.uri = req.uri; + view.match = req.match; + return view; + } + + static toDomain(req: LoginUriExport, domain = new LoginUriDomain()) { + domain.uri = req.uri != null ? new EncString(req.uri) : null; + domain.match = req.match; + return domain; + } + + uri: string; + match: UriMatchType = null; + + constructor(o?: LoginUriView | LoginUriDomain) { + if (o == null) { + return; + } + + if (o instanceof LoginUriView) { + this.uri = o.uri; + } else { + this.uri = o.uri?.encryptedString; + } + this.match = o.match; + } +} diff --git a/libs/common/src/models/export/secureNoteExport.ts b/libs/common/src/models/export/secureNoteExport.ts new file mode 100644 index 0000000000..de85bacd3b --- /dev/null +++ b/libs/common/src/models/export/secureNoteExport.ts @@ -0,0 +1,31 @@ +import { SecureNoteType } from "../../enums/secureNoteType"; +import { SecureNote as SecureNoteDomain } from "../domain/secureNote"; +import { SecureNoteView } from "../view/secureNoteView"; + +export class SecureNoteExport { + static template(): SecureNoteExport { + const req = new SecureNoteExport(); + req.type = SecureNoteType.Generic; + return req; + } + + static toView(req: SecureNoteExport, view = new SecureNoteView()) { + view.type = req.type; + return view; + } + + static toDomain(req: SecureNoteExport, view = new SecureNoteDomain()) { + view.type = req.type; + return view; + } + + type: SecureNoteType; + + constructor(o?: SecureNoteView | SecureNoteDomain) { + if (o == null) { + return; + } + + this.type = o.type; + } +} diff --git a/libs/common/src/models/request/account/setKeyConnectorKeyRequest.ts b/libs/common/src/models/request/account/setKeyConnectorKeyRequest.ts new file mode 100644 index 0000000000..a84cc7efd8 --- /dev/null +++ b/libs/common/src/models/request/account/setKeyConnectorKeyRequest.ts @@ -0,0 +1,24 @@ +import { KdfType } from "../../../enums/kdfType"; +import { KeysRequest } from "../keysRequest"; + +export class SetKeyConnectorKeyRequest { + key: string; + keys: KeysRequest; + kdf: KdfType; + kdfIterations: number; + orgIdentifier: string; + + constructor( + key: string, + kdf: KdfType, + kdfIterations: number, + orgIdentifier: string, + keys: KeysRequest + ) { + this.key = key; + this.kdf = kdf; + this.kdfIterations = kdfIterations; + this.orgIdentifier = orgIdentifier; + this.keys = keys; + } +} diff --git a/libs/common/src/models/request/account/verifyOTPRequest.ts b/libs/common/src/models/request/account/verifyOTPRequest.ts new file mode 100644 index 0000000000..2eb8816e26 --- /dev/null +++ b/libs/common/src/models/request/account/verifyOTPRequest.ts @@ -0,0 +1,7 @@ +export class VerifyOTPRequest { + OTP: string; + + constructor(OTP: string) { + this.OTP = OTP; + } +} diff --git a/libs/common/src/models/request/attachmentRequest.ts b/libs/common/src/models/request/attachmentRequest.ts new file mode 100644 index 0000000000..ea1ea82112 --- /dev/null +++ b/libs/common/src/models/request/attachmentRequest.ts @@ -0,0 +1,6 @@ +export class AttachmentRequest { + fileName: string; + key: string; + fileSize: number; + adminRequest: boolean; +} diff --git a/libs/common/src/models/request/billingSyncConfigRequest.ts b/libs/common/src/models/request/billingSyncConfigRequest.ts new file mode 100644 index 0000000000..16ad1606be --- /dev/null +++ b/libs/common/src/models/request/billingSyncConfigRequest.ts @@ -0,0 +1,3 @@ +export class BillingSyncConfigRequest { + constructor(private billingSyncKey: string) {} +} diff --git a/libs/common/src/models/request/bitPayInvoiceRequest.ts b/libs/common/src/models/request/bitPayInvoiceRequest.ts new file mode 100644 index 0000000000..9042611b24 --- /dev/null +++ b/libs/common/src/models/request/bitPayInvoiceRequest.ts @@ -0,0 +1,9 @@ +export class BitPayInvoiceRequest { + userId: string; + organizationId: string; + credit: boolean; + amount: number; + returnUrl: string; + name: string; + email: string; +} diff --git a/libs/common/src/models/request/captchaProtectedRequest.ts b/libs/common/src/models/request/captchaProtectedRequest.ts new file mode 100644 index 0000000000..54721e0147 --- /dev/null +++ b/libs/common/src/models/request/captchaProtectedRequest.ts @@ -0,0 +1,3 @@ +export abstract class CaptchaProtectedRequest { + captchaResponse: string = null; +} diff --git a/libs/common/src/models/request/cipherBulkDeleteRequest.ts b/libs/common/src/models/request/cipherBulkDeleteRequest.ts new file mode 100644 index 0000000000..227f1a6699 --- /dev/null +++ b/libs/common/src/models/request/cipherBulkDeleteRequest.ts @@ -0,0 +1,9 @@ +export class CipherBulkDeleteRequest { + ids: string[]; + organizationId: string; + + constructor(ids: string[], organizationId?: string) { + this.ids = ids == null ? [] : ids; + this.organizationId = organizationId; + } +} diff --git a/libs/common/src/models/request/cipherBulkMoveRequest.ts b/libs/common/src/models/request/cipherBulkMoveRequest.ts new file mode 100644 index 0000000000..06a737de76 --- /dev/null +++ b/libs/common/src/models/request/cipherBulkMoveRequest.ts @@ -0,0 +1,9 @@ +export class CipherBulkMoveRequest { + ids: string[]; + folderId: string; + + constructor(ids: string[], folderId: string) { + this.ids = ids == null ? [] : ids; + this.folderId = folderId; + } +} diff --git a/libs/common/src/models/request/cipherBulkRestoreRequest.ts b/libs/common/src/models/request/cipherBulkRestoreRequest.ts new file mode 100644 index 0000000000..70e5a4e82a --- /dev/null +++ b/libs/common/src/models/request/cipherBulkRestoreRequest.ts @@ -0,0 +1,7 @@ +export class CipherBulkRestoreRequest { + ids: string[]; + + constructor(ids: string[]) { + this.ids = ids == null ? [] : ids; + } +} diff --git a/libs/common/src/models/request/cipherBulkShareRequest.ts b/libs/common/src/models/request/cipherBulkShareRequest.ts new file mode 100644 index 0000000000..6e77ad56de --- /dev/null +++ b/libs/common/src/models/request/cipherBulkShareRequest.ts @@ -0,0 +1,18 @@ +import { Cipher } from "../domain/cipher"; + +import { CipherWithIdRequest } from "./cipherWithIdRequest"; + +export class CipherBulkShareRequest { + ciphers: CipherWithIdRequest[]; + collectionIds: string[]; + + constructor(ciphers: Cipher[], collectionIds: string[]) { + if (ciphers != null) { + this.ciphers = []; + ciphers.forEach((c) => { + this.ciphers.push(new CipherWithIdRequest(c)); + }); + } + this.collectionIds = collectionIds; + } +} diff --git a/libs/common/src/models/request/cipherCollectionsRequest.ts b/libs/common/src/models/request/cipherCollectionsRequest.ts new file mode 100644 index 0000000000..8d5553896b --- /dev/null +++ b/libs/common/src/models/request/cipherCollectionsRequest.ts @@ -0,0 +1,7 @@ +export class CipherCollectionsRequest { + collectionIds: string[]; + + constructor(collectionIds: string[]) { + this.collectionIds = collectionIds == null ? [] : collectionIds; + } +} diff --git a/libs/common/src/models/request/cipherCreateRequest.ts b/libs/common/src/models/request/cipherCreateRequest.ts new file mode 100644 index 0000000000..d7ff5128d4 --- /dev/null +++ b/libs/common/src/models/request/cipherCreateRequest.ts @@ -0,0 +1,13 @@ +import { Cipher } from "../domain/cipher"; + +import { CipherRequest } from "./cipherRequest"; + +export class CipherCreateRequest { + cipher: CipherRequest; + collectionIds: string[]; + + constructor(cipher: Cipher) { + this.cipher = new CipherRequest(cipher); + this.collectionIds = cipher.collectionIds; + } +} diff --git a/libs/common/src/models/request/cipherRequest.ts b/libs/common/src/models/request/cipherRequest.ts new file mode 100644 index 0000000000..4ed5885082 --- /dev/null +++ b/libs/common/src/models/request/cipherRequest.ts @@ -0,0 +1,164 @@ +import { CipherRepromptType } from "../../enums/cipherRepromptType"; +import { CipherType } from "../../enums/cipherType"; +import { CardApi } from "../api/cardApi"; +import { FieldApi } from "../api/fieldApi"; +import { IdentityApi } from "../api/identityApi"; +import { LoginApi } from "../api/loginApi"; +import { LoginUriApi } from "../api/loginUriApi"; +import { SecureNoteApi } from "../api/secureNoteApi"; +import { Cipher } from "../domain/cipher"; + +import { AttachmentRequest } from "./attachmentRequest"; +import { PasswordHistoryRequest } from "./passwordHistoryRequest"; + +export class CipherRequest { + type: CipherType; + folderId: string; + organizationId: string; + name: string; + notes: string; + favorite: boolean; + login: LoginApi; + secureNote: SecureNoteApi; + card: CardApi; + identity: IdentityApi; + fields: FieldApi[]; + passwordHistory: PasswordHistoryRequest[]; + // Deprecated, remove at some point and rename attachments2 to attachments + attachments: { [id: string]: string }; + attachments2: { [id: string]: AttachmentRequest }; + lastKnownRevisionDate: Date; + reprompt: CipherRepromptType; + + constructor(cipher: Cipher) { + this.type = cipher.type; + this.folderId = cipher.folderId; + this.organizationId = cipher.organizationId; + this.name = cipher.name ? cipher.name.encryptedString : null; + this.notes = cipher.notes ? cipher.notes.encryptedString : null; + this.favorite = cipher.favorite; + this.lastKnownRevisionDate = cipher.revisionDate; + this.reprompt = cipher.reprompt; + + switch (this.type) { + case CipherType.Login: + this.login = new LoginApi(); + this.login.uris = null; + this.login.username = cipher.login.username ? cipher.login.username.encryptedString : null; + this.login.password = cipher.login.password ? cipher.login.password.encryptedString : null; + this.login.passwordRevisionDate = + cipher.login.passwordRevisionDate != null + ? cipher.login.passwordRevisionDate.toISOString() + : null; + this.login.totp = cipher.login.totp ? cipher.login.totp.encryptedString : null; + this.login.autofillOnPageLoad = cipher.login.autofillOnPageLoad; + + if (cipher.login.uris != null) { + this.login.uris = cipher.login.uris.map((u) => { + const uri = new LoginUriApi(); + uri.uri = u.uri != null ? u.uri.encryptedString : null; + uri.match = u.match != null ? u.match : null; + return uri; + }); + } + break; + case CipherType.SecureNote: + this.secureNote = new SecureNoteApi(); + this.secureNote.type = cipher.secureNote.type; + break; + case CipherType.Card: + this.card = new CardApi(); + this.card.cardholderName = + cipher.card.cardholderName != null ? cipher.card.cardholderName.encryptedString : null; + this.card.brand = cipher.card.brand != null ? cipher.card.brand.encryptedString : null; + this.card.number = cipher.card.number != null ? cipher.card.number.encryptedString : null; + this.card.expMonth = + cipher.card.expMonth != null ? cipher.card.expMonth.encryptedString : null; + this.card.expYear = + cipher.card.expYear != null ? cipher.card.expYear.encryptedString : null; + this.card.code = cipher.card.code != null ? cipher.card.code.encryptedString : null; + break; + case CipherType.Identity: + this.identity = new IdentityApi(); + this.identity.title = + cipher.identity.title != null ? cipher.identity.title.encryptedString : null; + this.identity.firstName = + cipher.identity.firstName != null ? cipher.identity.firstName.encryptedString : null; + this.identity.middleName = + cipher.identity.middleName != null ? cipher.identity.middleName.encryptedString : null; + this.identity.lastName = + cipher.identity.lastName != null ? cipher.identity.lastName.encryptedString : null; + this.identity.address1 = + cipher.identity.address1 != null ? cipher.identity.address1.encryptedString : null; + this.identity.address2 = + cipher.identity.address2 != null ? cipher.identity.address2.encryptedString : null; + this.identity.address3 = + cipher.identity.address3 != null ? cipher.identity.address3.encryptedString : null; + this.identity.city = + cipher.identity.city != null ? cipher.identity.city.encryptedString : null; + this.identity.state = + cipher.identity.state != null ? cipher.identity.state.encryptedString : null; + this.identity.postalCode = + cipher.identity.postalCode != null ? cipher.identity.postalCode.encryptedString : null; + this.identity.country = + cipher.identity.country != null ? cipher.identity.country.encryptedString : null; + this.identity.company = + cipher.identity.company != null ? cipher.identity.company.encryptedString : null; + this.identity.email = + cipher.identity.email != null ? cipher.identity.email.encryptedString : null; + this.identity.phone = + cipher.identity.phone != null ? cipher.identity.phone.encryptedString : null; + this.identity.ssn = + cipher.identity.ssn != null ? cipher.identity.ssn.encryptedString : null; + this.identity.username = + cipher.identity.username != null ? cipher.identity.username.encryptedString : null; + this.identity.passportNumber = + cipher.identity.passportNumber != null + ? cipher.identity.passportNumber.encryptedString + : null; + this.identity.licenseNumber = + cipher.identity.licenseNumber != null + ? cipher.identity.licenseNumber.encryptedString + : null; + break; + default: + break; + } + + if (cipher.fields != null) { + this.fields = cipher.fields.map((f) => { + const field = new FieldApi(); + field.type = f.type; + field.name = f.name ? f.name.encryptedString : null; + field.value = f.value ? f.value.encryptedString : null; + field.linkedId = f.linkedId; + return field; + }); + } + + if (cipher.passwordHistory != null) { + this.passwordHistory = []; + cipher.passwordHistory.forEach((ph) => { + this.passwordHistory.push({ + lastUsedDate: ph.lastUsedDate, + password: ph.password ? ph.password.encryptedString : null, + }); + }); + } + + if (cipher.attachments != null) { + this.attachments = {}; + this.attachments2 = {}; + cipher.attachments.forEach((attachment) => { + const fileName = attachment.fileName ? attachment.fileName.encryptedString : null; + this.attachments[attachment.id] = fileName; + const attachmentRequest = new AttachmentRequest(); + attachmentRequest.fileName = fileName; + if (attachment.key != null) { + attachmentRequest.key = attachment.key.encryptedString; + } + this.attachments2[attachment.id] = attachmentRequest; + }); + } + } +} diff --git a/libs/common/src/models/request/cipherShareRequest.ts b/libs/common/src/models/request/cipherShareRequest.ts new file mode 100644 index 0000000000..4cf6dfde1e --- /dev/null +++ b/libs/common/src/models/request/cipherShareRequest.ts @@ -0,0 +1,13 @@ +import { Cipher } from "../domain/cipher"; + +import { CipherRequest } from "./cipherRequest"; + +export class CipherShareRequest { + cipher: CipherRequest; + collectionIds: string[]; + + constructor(cipher: Cipher) { + this.cipher = new CipherRequest(cipher); + this.collectionIds = cipher.collectionIds; + } +} diff --git a/libs/common/src/models/request/cipherWithIdRequest.ts b/libs/common/src/models/request/cipherWithIdRequest.ts new file mode 100644 index 0000000000..0f22322f8c --- /dev/null +++ b/libs/common/src/models/request/cipherWithIdRequest.ts @@ -0,0 +1,12 @@ +import { Cipher } from "../domain/cipher"; + +import { CipherRequest } from "./cipherRequest"; + +export class CipherWithIdRequest extends CipherRequest { + id: string; + + constructor(cipher: Cipher) { + super(cipher); + this.id = cipher.id; + } +} diff --git a/libs/common/src/models/request/collectionRequest.ts b/libs/common/src/models/request/collectionRequest.ts new file mode 100644 index 0000000000..c2176095f9 --- /dev/null +++ b/libs/common/src/models/request/collectionRequest.ts @@ -0,0 +1,17 @@ +import { Collection } from "../domain/collection"; + +import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest"; + +export class CollectionRequest { + name: string; + externalId: string; + groups: SelectionReadOnlyRequest[] = []; + + constructor(collection?: Collection) { + if (collection == null) { + return; + } + this.name = collection.name ? collection.name.encryptedString : null; + this.externalId = collection.externalId; + } +} diff --git a/libs/common/src/models/request/deleteRecoverRequest.ts b/libs/common/src/models/request/deleteRecoverRequest.ts new file mode 100644 index 0000000000..02a019b8f6 --- /dev/null +++ b/libs/common/src/models/request/deleteRecoverRequest.ts @@ -0,0 +1,3 @@ +export class DeleteRecoverRequest { + email: string; +} diff --git a/libs/common/src/models/request/deviceRequest.ts b/libs/common/src/models/request/deviceRequest.ts new file mode 100644 index 0000000000..66c17b57dc --- /dev/null +++ b/libs/common/src/models/request/deviceRequest.ts @@ -0,0 +1,16 @@ +import { PlatformUtilsService } from "../../abstractions/platformUtils.service"; +import { DeviceType } from "../../enums/deviceType"; + +export class DeviceRequest { + type: DeviceType; + name: string; + identifier: string; + pushToken?: string; + + constructor(appId: string, platformUtilsService: PlatformUtilsService) { + this.type = platformUtilsService.getDevice(); + this.name = platformUtilsService.getDeviceString(); + this.identifier = appId; + this.pushToken = null; + } +} diff --git a/libs/common/src/models/request/deviceTokenRequest.ts b/libs/common/src/models/request/deviceTokenRequest.ts new file mode 100644 index 0000000000..99ca69a2f5 --- /dev/null +++ b/libs/common/src/models/request/deviceTokenRequest.ts @@ -0,0 +1,7 @@ +export class DeviceTokenRequest { + pushToken: string; + + constructor() { + this.pushToken = null; + } +} diff --git a/libs/common/src/models/request/emailRequest.ts b/libs/common/src/models/request/emailRequest.ts new file mode 100644 index 0000000000..0b55961596 --- /dev/null +++ b/libs/common/src/models/request/emailRequest.ts @@ -0,0 +1,7 @@ +import { EmailTokenRequest } from "./emailTokenRequest"; + +export class EmailRequest extends EmailTokenRequest { + newMasterPasswordHash: string; + token: string; + key: string; +} diff --git a/libs/common/src/models/request/emailTokenRequest.ts b/libs/common/src/models/request/emailTokenRequest.ts new file mode 100644 index 0000000000..7e0515ca19 --- /dev/null +++ b/libs/common/src/models/request/emailTokenRequest.ts @@ -0,0 +1,6 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class EmailTokenRequest extends SecretVerificationRequest { + newEmail: string; + masterPasswordHash: string; +} diff --git a/libs/common/src/models/request/emergencyAccessAcceptRequest.ts b/libs/common/src/models/request/emergencyAccessAcceptRequest.ts new file mode 100644 index 0000000000..1cb1025335 --- /dev/null +++ b/libs/common/src/models/request/emergencyAccessAcceptRequest.ts @@ -0,0 +1,3 @@ +export class EmergencyAccessAcceptRequest { + token: string; +} diff --git a/libs/common/src/models/request/emergencyAccessConfirmRequest.ts b/libs/common/src/models/request/emergencyAccessConfirmRequest.ts new file mode 100644 index 0000000000..ee54a4fe34 --- /dev/null +++ b/libs/common/src/models/request/emergencyAccessConfirmRequest.ts @@ -0,0 +1,3 @@ +export class EmergencyAccessConfirmRequest { + key: string; +} diff --git a/libs/common/src/models/request/emergencyAccessInviteRequest.ts b/libs/common/src/models/request/emergencyAccessInviteRequest.ts new file mode 100644 index 0000000000..d75ed4195c --- /dev/null +++ b/libs/common/src/models/request/emergencyAccessInviteRequest.ts @@ -0,0 +1,7 @@ +import { EmergencyAccessType } from "../../enums/emergencyAccessType"; + +export class EmergencyAccessInviteRequest { + email: string; + type: EmergencyAccessType; + waitTimeDays: number; +} diff --git a/libs/common/src/models/request/emergencyAccessPasswordRequest.ts b/libs/common/src/models/request/emergencyAccessPasswordRequest.ts new file mode 100644 index 0000000000..3fb459e1ab --- /dev/null +++ b/libs/common/src/models/request/emergencyAccessPasswordRequest.ts @@ -0,0 +1,4 @@ +export class EmergencyAccessPasswordRequest { + newMasterPasswordHash: string; + key: string; +} diff --git a/libs/common/src/models/request/emergencyAccessUpdateRequest.ts b/libs/common/src/models/request/emergencyAccessUpdateRequest.ts new file mode 100644 index 0000000000..d7c55c94a1 --- /dev/null +++ b/libs/common/src/models/request/emergencyAccessUpdateRequest.ts @@ -0,0 +1,7 @@ +import { EmergencyAccessType } from "../../enums/emergencyAccessType"; + +export class EmergencyAccessUpdateRequest { + type: EmergencyAccessType; + waitTimeDays: number; + keyEncrypted?: string; +} diff --git a/libs/common/src/models/request/eventRequest.ts b/libs/common/src/models/request/eventRequest.ts new file mode 100644 index 0000000000..a6228fd673 --- /dev/null +++ b/libs/common/src/models/request/eventRequest.ts @@ -0,0 +1,7 @@ +import { EventType } from "../../enums/eventType"; + +export class EventRequest { + type: EventType; + cipherId: string; + date: string; +} diff --git a/libs/common/src/models/request/folderRequest.ts b/libs/common/src/models/request/folderRequest.ts new file mode 100644 index 0000000000..a37f66ddfa --- /dev/null +++ b/libs/common/src/models/request/folderRequest.ts @@ -0,0 +1,9 @@ +import { Folder } from "../domain/folder"; + +export class FolderRequest { + name: string; + + constructor(folder: Folder) { + this.name = folder.name ? folder.name.encryptedString : null; + } +} diff --git a/libs/common/src/models/request/folderWithIdRequest.ts b/libs/common/src/models/request/folderWithIdRequest.ts new file mode 100644 index 0000000000..a36c2b7064 --- /dev/null +++ b/libs/common/src/models/request/folderWithIdRequest.ts @@ -0,0 +1,12 @@ +import { Folder } from "../domain/folder"; + +import { FolderRequest } from "./folderRequest"; + +export class FolderWithIdRequest extends FolderRequest { + id: string; + + constructor(folder: Folder) { + super(folder); + this.id = folder.id; + } +} diff --git a/libs/common/src/models/request/groupRequest.ts b/libs/common/src/models/request/groupRequest.ts new file mode 100644 index 0000000000..c4c349c8e8 --- /dev/null +++ b/libs/common/src/models/request/groupRequest.ts @@ -0,0 +1,8 @@ +import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest"; + +export class GroupRequest { + name: string; + accessAll: boolean; + externalId: string; + collections: SelectionReadOnlyRequest[] = []; +} diff --git a/libs/common/src/models/request/iapCheckRequest.ts b/libs/common/src/models/request/iapCheckRequest.ts new file mode 100644 index 0000000000..b8796e8c90 --- /dev/null +++ b/libs/common/src/models/request/iapCheckRequest.ts @@ -0,0 +1,5 @@ +import { PaymentMethodType } from "../../enums/paymentMethodType"; + +export class IapCheckRequest { + paymentMethodType: PaymentMethodType; +} diff --git a/libs/common/src/models/request/identityToken/apiTokenRequest.ts b/libs/common/src/models/request/identityToken/apiTokenRequest.ts new file mode 100644 index 0000000000..247ba1746e --- /dev/null +++ b/libs/common/src/models/request/identityToken/apiTokenRequest.ts @@ -0,0 +1,25 @@ +import { DeviceRequest } from "../deviceRequest"; + +import { TokenRequest } from "./tokenRequest"; +import { TokenRequestTwoFactor } from "./tokenRequestTwoFactor"; + +export class ApiTokenRequest extends TokenRequest { + constructor( + public clientId: string, + public clientSecret: string, + protected twoFactor: TokenRequestTwoFactor, + device?: DeviceRequest + ) { + super(twoFactor, device); + } + + toIdentityToken() { + const obj = super.toIdentityToken(this.clientId); + + obj.scope = this.clientId.startsWith("organization") ? "api.organization" : "api"; + obj.grant_type = "client_credentials"; + obj.client_secret = this.clientSecret; + + return obj; + } +} diff --git a/libs/common/src/models/request/identityToken/passwordTokenRequest.ts b/libs/common/src/models/request/identityToken/passwordTokenRequest.ts new file mode 100644 index 0000000000..eda100374d --- /dev/null +++ b/libs/common/src/models/request/identityToken/passwordTokenRequest.ts @@ -0,0 +1,37 @@ +import { ClientType } from "../../../enums/clientType"; +import { Utils } from "../../../misc/utils"; +import { CaptchaProtectedRequest } from "../captchaProtectedRequest"; +import { DeviceRequest } from "../deviceRequest"; + +import { TokenRequest } from "./tokenRequest"; +import { TokenRequestTwoFactor } from "./tokenRequestTwoFactor"; + +export class PasswordTokenRequest extends TokenRequest implements CaptchaProtectedRequest { + constructor( + public email: string, + public masterPasswordHash: string, + public captchaResponse: string, + protected twoFactor: TokenRequestTwoFactor, + device?: DeviceRequest + ) { + super(twoFactor, device); + } + + toIdentityToken(clientId: ClientType) { + const obj = super.toIdentityToken(clientId); + + obj.grant_type = "password"; + obj.username = this.email; + obj.password = this.masterPasswordHash; + + if (this.captchaResponse != null) { + obj.captchaResponse = this.captchaResponse; + } + + return obj; + } + + alterIdentityTokenHeaders(headers: Headers) { + headers.set("Auth-Email", Utils.fromUtf8ToUrlB64(this.email)); + } +} diff --git a/libs/common/src/models/request/identityToken/ssoTokenRequest.ts b/libs/common/src/models/request/identityToken/ssoTokenRequest.ts new file mode 100644 index 0000000000..c7697c2f13 --- /dev/null +++ b/libs/common/src/models/request/identityToken/ssoTokenRequest.ts @@ -0,0 +1,27 @@ +import { DeviceRequest } from "../deviceRequest"; + +import { TokenRequest } from "./tokenRequest"; +import { TokenRequestTwoFactor } from "./tokenRequestTwoFactor"; + +export class SsoTokenRequest extends TokenRequest { + constructor( + public code: string, + public codeVerifier: string, + public redirectUri: string, + protected twoFactor: TokenRequestTwoFactor, + device?: DeviceRequest + ) { + super(twoFactor, device); + } + + toIdentityToken(clientId: string) { + const obj = super.toIdentityToken(clientId); + + obj.grant_type = "authorization_code"; + obj.code = this.code; + obj.code_verifier = this.codeVerifier; + obj.redirect_uri = this.redirectUri; + + return obj; + } +} diff --git a/libs/common/src/models/request/identityToken/tokenRequest.ts b/libs/common/src/models/request/identityToken/tokenRequest.ts new file mode 100644 index 0000000000..82a4a394c5 --- /dev/null +++ b/libs/common/src/models/request/identityToken/tokenRequest.ts @@ -0,0 +1,43 @@ +import { DeviceRequest } from "../deviceRequest"; + +import { TokenRequestTwoFactor } from "./tokenRequestTwoFactor"; + +export abstract class TokenRequest { + protected device?: DeviceRequest; + + constructor(protected twoFactor: TokenRequestTwoFactor, device?: DeviceRequest) { + this.device = device != null ? device : null; + } + + // eslint-disable-next-line + alterIdentityTokenHeaders(headers: Headers) { + // Implemented in subclass if required + } + + setTwoFactor(twoFactor: TokenRequestTwoFactor) { + this.twoFactor = twoFactor; + } + + protected toIdentityToken(clientId: string) { + const obj: any = { + scope: "api offline_access", + client_id: clientId, + }; + + if (this.device) { + obj.deviceType = this.device.type; + obj.deviceIdentifier = this.device.identifier; + obj.deviceName = this.device.name; + // no push tokens for browser apps yet + // obj.devicePushToken = this.device.pushToken; + } + + if (this.twoFactor.token && this.twoFactor.provider != null) { + obj.twoFactorToken = this.twoFactor.token; + obj.twoFactorProvider = this.twoFactor.provider; + obj.twoFactorRemember = this.twoFactor.remember ? "1" : "0"; + } + + return obj; + } +} diff --git a/libs/common/src/models/request/identityToken/tokenRequestTwoFactor.ts b/libs/common/src/models/request/identityToken/tokenRequestTwoFactor.ts new file mode 100644 index 0000000000..567e8c66e6 --- /dev/null +++ b/libs/common/src/models/request/identityToken/tokenRequestTwoFactor.ts @@ -0,0 +1,9 @@ +import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType"; + +export class TokenRequestTwoFactor { + constructor( + public provider: TwoFactorProviderType = null, + public token: string = null, + public remember: boolean = false + ) {} +} diff --git a/libs/common/src/models/request/importCiphersRequest.ts b/libs/common/src/models/request/importCiphersRequest.ts new file mode 100644 index 0000000000..ebaa03a33d --- /dev/null +++ b/libs/common/src/models/request/importCiphersRequest.ts @@ -0,0 +1,9 @@ +import { CipherRequest } from "./cipherRequest"; +import { FolderRequest } from "./folderRequest"; +import { KvpRequest } from "./kvpRequest"; + +export class ImportCiphersRequest { + ciphers: CipherRequest[] = []; + folders: FolderRequest[] = []; + folderRelationships: KvpRequest[] = []; +} diff --git a/libs/common/src/models/request/importDirectoryRequest.ts b/libs/common/src/models/request/importDirectoryRequest.ts new file mode 100644 index 0000000000..a13ce4564f --- /dev/null +++ b/libs/common/src/models/request/importDirectoryRequest.ts @@ -0,0 +1,9 @@ +import { ImportDirectoryRequestGroup } from "./importDirectoryRequestGroup"; +import { ImportDirectoryRequestUser } from "./importDirectoryRequestUser"; + +export class ImportDirectoryRequest { + groups: ImportDirectoryRequestGroup[] = []; + users: ImportDirectoryRequestUser[] = []; + overwriteExisting = false; + largeImport = false; +} diff --git a/libs/common/src/models/request/importDirectoryRequestGroup.ts b/libs/common/src/models/request/importDirectoryRequestGroup.ts new file mode 100644 index 0000000000..4b7b3567c7 --- /dev/null +++ b/libs/common/src/models/request/importDirectoryRequestGroup.ts @@ -0,0 +1,5 @@ +export class ImportDirectoryRequestGroup { + name: string; + externalId: string; + users: string[]; +} diff --git a/libs/common/src/models/request/importDirectoryRequestUser.ts b/libs/common/src/models/request/importDirectoryRequestUser.ts new file mode 100644 index 0000000000..9dbf6a3433 --- /dev/null +++ b/libs/common/src/models/request/importDirectoryRequestUser.ts @@ -0,0 +1,5 @@ +export class ImportDirectoryRequestUser { + externalId: string; + email: string; + deleted: boolean; +} diff --git a/libs/common/src/models/request/importOrganizationCiphersRequest.ts b/libs/common/src/models/request/importOrganizationCiphersRequest.ts new file mode 100644 index 0000000000..f2936afbc6 --- /dev/null +++ b/libs/common/src/models/request/importOrganizationCiphersRequest.ts @@ -0,0 +1,9 @@ +import { CipherRequest } from "./cipherRequest"; +import { CollectionRequest } from "./collectionRequest"; +import { KvpRequest } from "./kvpRequest"; + +export class ImportOrganizationCiphersRequest { + ciphers: CipherRequest[] = []; + collections: CollectionRequest[] = []; + collectionRelationships: KvpRequest[] = []; +} diff --git a/libs/common/src/models/request/kdfRequest.ts b/libs/common/src/models/request/kdfRequest.ts new file mode 100644 index 0000000000..47c1ce0776 --- /dev/null +++ b/libs/common/src/models/request/kdfRequest.ts @@ -0,0 +1,8 @@ +import { KdfType } from "../../enums/kdfType"; + +import { PasswordRequest } from "./passwordRequest"; + +export class KdfRequest extends PasswordRequest { + kdf: KdfType; + kdfIterations: number; +} diff --git a/libs/common/src/models/request/keyConnectorUserKeyRequest.ts b/libs/common/src/models/request/keyConnectorUserKeyRequest.ts new file mode 100644 index 0000000000..3df2db82cb --- /dev/null +++ b/libs/common/src/models/request/keyConnectorUserKeyRequest.ts @@ -0,0 +1,7 @@ +export class KeyConnectorUserKeyRequest { + key: string; + + constructor(key: string) { + this.key = key; + } +} diff --git a/libs/common/src/models/request/keysRequest.ts b/libs/common/src/models/request/keysRequest.ts new file mode 100644 index 0000000000..da4144e9b4 --- /dev/null +++ b/libs/common/src/models/request/keysRequest.ts @@ -0,0 +1,9 @@ +export class KeysRequest { + publicKey: string; + encryptedPrivateKey: string; + + constructor(publicKey: string, encryptedPrivateKey: string) { + this.publicKey = publicKey; + this.encryptedPrivateKey = encryptedPrivateKey; + } +} diff --git a/libs/common/src/models/request/kvpRequest.ts b/libs/common/src/models/request/kvpRequest.ts new file mode 100644 index 0000000000..ca37a85d62 --- /dev/null +++ b/libs/common/src/models/request/kvpRequest.ts @@ -0,0 +1,9 @@ +export class KvpRequest { + key: TK; + value: TV; + + constructor(key: TK, value: TV) { + this.key = key; + this.value = value; + } +} diff --git a/libs/common/src/models/request/organization/organizationSponsorshipCreateRequest.ts b/libs/common/src/models/request/organization/organizationSponsorshipCreateRequest.ts new file mode 100644 index 0000000000..7cc854b67b --- /dev/null +++ b/libs/common/src/models/request/organization/organizationSponsorshipCreateRequest.ts @@ -0,0 +1,7 @@ +import { PlanSponsorshipType } from "../../../enums/planSponsorshipType"; + +export class OrganizationSponsorshipCreateRequest { + sponsoredEmail: string; + planSponsorshipType: PlanSponsorshipType; + friendlyName: string; +} diff --git a/libs/common/src/models/request/organization/organizationSponsorshipRedeemRequest.ts b/libs/common/src/models/request/organization/organizationSponsorshipRedeemRequest.ts new file mode 100644 index 0000000000..4c73836e56 --- /dev/null +++ b/libs/common/src/models/request/organization/organizationSponsorshipRedeemRequest.ts @@ -0,0 +1,6 @@ +import { PlanSponsorshipType } from "../../../enums/planSponsorshipType"; + +export class OrganizationSponsorshipRedeemRequest { + planSponsorshipType: PlanSponsorshipType; + sponsoredOrganizationId: string; +} diff --git a/libs/common/src/models/request/organization/organizationSsoRequest.ts b/libs/common/src/models/request/organization/organizationSsoRequest.ts new file mode 100644 index 0000000000..e7fdb61ca1 --- /dev/null +++ b/libs/common/src/models/request/organization/organizationSsoRequest.ts @@ -0,0 +1,6 @@ +import { SsoConfigApi } from "../../api/ssoConfigApi"; + +export class OrganizationSsoRequest { + enabled = false; + data: SsoConfigApi; +} diff --git a/libs/common/src/models/request/organizationApiKeyRequest.ts b/libs/common/src/models/request/organizationApiKeyRequest.ts new file mode 100644 index 0000000000..613a3bfb39 --- /dev/null +++ b/libs/common/src/models/request/organizationApiKeyRequest.ts @@ -0,0 +1,7 @@ +import { OrganizationApiKeyType } from "../../enums/organizationApiKeyType"; + +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class OrganizationApiKeyRequest extends SecretVerificationRequest { + type: OrganizationApiKeyType = OrganizationApiKeyType.Default; +} diff --git a/libs/common/src/models/request/organizationConnectionRequest.ts b/libs/common/src/models/request/organizationConnectionRequest.ts new file mode 100644 index 0000000000..89cd25fe65 --- /dev/null +++ b/libs/common/src/models/request/organizationConnectionRequest.ts @@ -0,0 +1,15 @@ +import { OrganizationConnectionType } from "jslib-common/enums/organizationConnectionType"; + +import { BillingSyncConfigRequest } from "./billingSyncConfigRequest"; + +/**API request config types for OrganizationConnectionRequest */ +export type OrganizationConnectionRequestConfigs = BillingSyncConfigRequest; + +export class OrganizationConnectionRequest { + constructor( + public organizationId: string, + public type: OrganizationConnectionType, + public enabled: boolean, + public config: OrganizationConnectionRequestConfigs + ) {} +} diff --git a/libs/common/src/models/request/organizationCreateRequest.ts b/libs/common/src/models/request/organizationCreateRequest.ts new file mode 100644 index 0000000000..db713d90c1 --- /dev/null +++ b/libs/common/src/models/request/organizationCreateRequest.ts @@ -0,0 +1,27 @@ +import { PaymentMethodType } from "../../enums/paymentMethodType"; +import { PlanType } from "../../enums/planType"; + +import { OrganizationKeysRequest } from "./organizationKeysRequest"; + +export class OrganizationCreateRequest { + name: string; + businessName: string; + billingEmail: string; + planType: PlanType; + key: string; + keys: OrganizationKeysRequest; + paymentMethodType: PaymentMethodType; + paymentToken: string; + additionalSeats: number; + maxAutoscaleSeats: number; + additionalStorageGb: number; + premiumAccessAddon: boolean; + collectionName: string; + taxIdNumber: string; + billingAddressLine1: string; + billingAddressLine2: string; + billingAddressCity: string; + billingAddressState: string; + billingAddressPostalCode: string; + billingAddressCountry: string; +} diff --git a/libs/common/src/models/request/organizationImportGroupRequest.ts b/libs/common/src/models/request/organizationImportGroupRequest.ts new file mode 100644 index 0000000000..086ce65345 --- /dev/null +++ b/libs/common/src/models/request/organizationImportGroupRequest.ts @@ -0,0 +1,18 @@ +import { ImportDirectoryRequestGroup } from "./importDirectoryRequestGroup"; + +export class OrganizationImportGroupRequest { + name: string; + externalId: string; + memberExternalIds: string[]; + + constructor(model: Required | ImportDirectoryRequestGroup) { + this.name = model.name; + this.externalId = model.externalId; + + if (model instanceof ImportDirectoryRequestGroup) { + this.memberExternalIds = model.users; + } else { + this.memberExternalIds = model.memberExternalIds; + } + } +} diff --git a/libs/common/src/models/request/organizationImportMemberRequest.ts b/libs/common/src/models/request/organizationImportMemberRequest.ts new file mode 100644 index 0000000000..8161365cbd --- /dev/null +++ b/libs/common/src/models/request/organizationImportMemberRequest.ts @@ -0,0 +1,13 @@ +import { ImportDirectoryRequestUser } from "./importDirectoryRequestUser"; + +export class OrganizationImportMemberRequest { + email: string; + externalId: string; + deleted: boolean; + + constructor(model: Required | ImportDirectoryRequestUser) { + this.email = model.email; + this.externalId = model.externalId; + this.deleted = model.deleted; + } +} diff --git a/libs/common/src/models/request/organizationImportRequest.ts b/libs/common/src/models/request/organizationImportRequest.ts new file mode 100644 index 0000000000..af7db2be70 --- /dev/null +++ b/libs/common/src/models/request/organizationImportRequest.ts @@ -0,0 +1,31 @@ +import { ImportDirectoryRequest } from "./importDirectoryRequest"; +import { OrganizationImportGroupRequest } from "./organizationImportGroupRequest"; +import { OrganizationImportMemberRequest } from "./organizationImportMemberRequest"; + +export class OrganizationImportRequest { + groups: OrganizationImportGroupRequest[] = []; + members: OrganizationImportMemberRequest[] = []; + overwriteExisting = false; + largeImport = false; + + constructor( + model: + | { + groups: Required[]; + users: Required[]; + overwriteExisting: boolean; + largeImport: boolean; + } + | ImportDirectoryRequest + ) { + if (model instanceof ImportDirectoryRequest) { + this.groups = model.groups.map((g) => new OrganizationImportGroupRequest(g)); + this.members = model.users.map((u) => new OrganizationImportMemberRequest(u)); + } else { + this.groups = model.groups.map((g) => new OrganizationImportGroupRequest(g)); + this.members = model.users.map((u) => new OrganizationImportMemberRequest(u)); + } + this.overwriteExisting = model.overwriteExisting; + this.largeImport = model.largeImport; + } +} diff --git a/libs/common/src/models/request/organizationKeysRequest.ts b/libs/common/src/models/request/organizationKeysRequest.ts new file mode 100644 index 0000000000..c63e05ab11 --- /dev/null +++ b/libs/common/src/models/request/organizationKeysRequest.ts @@ -0,0 +1,7 @@ +import { KeysRequest } from "./keysRequest"; + +export class OrganizationKeysRequest extends KeysRequest { + constructor(publicKey: string, encryptedPrivateKey: string) { + super(publicKey, encryptedPrivateKey); + } +} diff --git a/libs/common/src/models/request/organizationSubscriptionUpdateRequest.ts b/libs/common/src/models/request/organizationSubscriptionUpdateRequest.ts new file mode 100644 index 0000000000..9db3d4be80 --- /dev/null +++ b/libs/common/src/models/request/organizationSubscriptionUpdateRequest.ts @@ -0,0 +1,3 @@ +export class OrganizationSubscriptionUpdateRequest { + constructor(public seatAdjustment: number, public maxAutoscaleSeats?: number) {} +} diff --git a/libs/common/src/models/request/organizationTaxInfoUpdateRequest.ts b/libs/common/src/models/request/organizationTaxInfoUpdateRequest.ts new file mode 100644 index 0000000000..283151f4b5 --- /dev/null +++ b/libs/common/src/models/request/organizationTaxInfoUpdateRequest.ts @@ -0,0 +1,9 @@ +import { TaxInfoUpdateRequest } from "./taxInfoUpdateRequest"; + +export class OrganizationTaxInfoUpdateRequest extends TaxInfoUpdateRequest { + taxId: string; + line1: string; + line2: string; + city: string; + state: string; +} diff --git a/libs/common/src/models/request/organizationUpdateRequest.ts b/libs/common/src/models/request/organizationUpdateRequest.ts new file mode 100644 index 0000000000..faddf6410a --- /dev/null +++ b/libs/common/src/models/request/organizationUpdateRequest.ts @@ -0,0 +1,9 @@ +import { OrganizationKeysRequest } from "./organizationKeysRequest"; + +export class OrganizationUpdateRequest { + name: string; + identifier: string; + businessName: string; + billingEmail: string; + keys: OrganizationKeysRequest; +} diff --git a/libs/common/src/models/request/organizationUpgradeRequest.ts b/libs/common/src/models/request/organizationUpgradeRequest.ts new file mode 100644 index 0000000000..b62976fa2f --- /dev/null +++ b/libs/common/src/models/request/organizationUpgradeRequest.ts @@ -0,0 +1,14 @@ +import { PlanType } from "../../enums/planType"; + +import { OrganizationKeysRequest } from "./organizationKeysRequest"; + +export class OrganizationUpgradeRequest { + businessName: string; + planType: PlanType; + additionalSeats: number; + additionalStorageGb: number; + premiumAccessAddon: boolean; + billingAddressCountry: string; + billingAddressPostalCode: string; + keys: OrganizationKeysRequest; +} diff --git a/libs/common/src/models/request/organizationUserAcceptRequest.ts b/libs/common/src/models/request/organizationUserAcceptRequest.ts new file mode 100644 index 0000000000..c4b2a4d31e --- /dev/null +++ b/libs/common/src/models/request/organizationUserAcceptRequest.ts @@ -0,0 +1,3 @@ +export class OrganizationUserAcceptRequest { + token: string; +} diff --git a/libs/common/src/models/request/organizationUserBulkConfirmRequest.ts b/libs/common/src/models/request/organizationUserBulkConfirmRequest.ts new file mode 100644 index 0000000000..35e0560283 --- /dev/null +++ b/libs/common/src/models/request/organizationUserBulkConfirmRequest.ts @@ -0,0 +1,12 @@ +type OrganizationUserBulkRequestEntry = { + id: string; + key: string; +}; + +export class OrganizationUserBulkConfirmRequest { + keys: OrganizationUserBulkRequestEntry[]; + + constructor(keys: OrganizationUserBulkRequestEntry[]) { + this.keys = keys; + } +} diff --git a/libs/common/src/models/request/organizationUserBulkRequest.ts b/libs/common/src/models/request/organizationUserBulkRequest.ts new file mode 100644 index 0000000000..c73800eb72 --- /dev/null +++ b/libs/common/src/models/request/organizationUserBulkRequest.ts @@ -0,0 +1,7 @@ +export class OrganizationUserBulkRequest { + ids: string[]; + + constructor(ids: string[]) { + this.ids = ids == null ? [] : ids; + } +} diff --git a/libs/common/src/models/request/organizationUserConfirmRequest.ts b/libs/common/src/models/request/organizationUserConfirmRequest.ts new file mode 100644 index 0000000000..abd487495f --- /dev/null +++ b/libs/common/src/models/request/organizationUserConfirmRequest.ts @@ -0,0 +1,3 @@ +export class OrganizationUserConfirmRequest { + key: string; +} diff --git a/libs/common/src/models/request/organizationUserInviteRequest.ts b/libs/common/src/models/request/organizationUserInviteRequest.ts new file mode 100644 index 0000000000..7d03700437 --- /dev/null +++ b/libs/common/src/models/request/organizationUserInviteRequest.ts @@ -0,0 +1,12 @@ +import { OrganizationUserType } from "../../enums/organizationUserType"; +import { PermissionsApi } from "../api/permissionsApi"; + +import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest"; + +export class OrganizationUserInviteRequest { + emails: string[] = []; + type: OrganizationUserType; + accessAll: boolean; + collections: SelectionReadOnlyRequest[] = []; + permissions: PermissionsApi; +} diff --git a/libs/common/src/models/request/organizationUserResetPasswordEnrollmentRequest.ts b/libs/common/src/models/request/organizationUserResetPasswordEnrollmentRequest.ts new file mode 100644 index 0000000000..f7129d156a --- /dev/null +++ b/libs/common/src/models/request/organizationUserResetPasswordEnrollmentRequest.ts @@ -0,0 +1,5 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class OrganizationUserResetPasswordEnrollmentRequest extends SecretVerificationRequest { + resetPasswordKey: string; +} diff --git a/libs/common/src/models/request/organizationUserResetPasswordRequest.ts b/libs/common/src/models/request/organizationUserResetPasswordRequest.ts new file mode 100644 index 0000000000..b0c4e483b9 --- /dev/null +++ b/libs/common/src/models/request/organizationUserResetPasswordRequest.ts @@ -0,0 +1,4 @@ +export class OrganizationUserResetPasswordRequest { + newMasterPasswordHash: string; + key: string; +} diff --git a/libs/common/src/models/request/organizationUserUpdateGroupsRequest.ts b/libs/common/src/models/request/organizationUserUpdateGroupsRequest.ts new file mode 100644 index 0000000000..cd30d940de --- /dev/null +++ b/libs/common/src/models/request/organizationUserUpdateGroupsRequest.ts @@ -0,0 +1,3 @@ +export class OrganizationUserUpdateGroupsRequest { + groupIds: string[] = []; +} diff --git a/libs/common/src/models/request/organizationUserUpdateRequest.ts b/libs/common/src/models/request/organizationUserUpdateRequest.ts new file mode 100644 index 0000000000..ec9ae3bc64 --- /dev/null +++ b/libs/common/src/models/request/organizationUserUpdateRequest.ts @@ -0,0 +1,11 @@ +import { OrganizationUserType } from "../../enums/organizationUserType"; +import { PermissionsApi } from "../api/permissionsApi"; + +import { SelectionReadOnlyRequest } from "./selectionReadOnlyRequest"; + +export class OrganizationUserUpdateRequest { + type: OrganizationUserType; + accessAll: boolean; + collections: SelectionReadOnlyRequest[] = []; + permissions: PermissionsApi; +} diff --git a/libs/common/src/models/request/passwordHintRequest.ts b/libs/common/src/models/request/passwordHintRequest.ts new file mode 100644 index 0000000000..7182e05ee9 --- /dev/null +++ b/libs/common/src/models/request/passwordHintRequest.ts @@ -0,0 +1,7 @@ +export class PasswordHintRequest { + email: string; + + constructor(email: string) { + this.email = email; + } +} diff --git a/libs/common/src/models/request/passwordHistoryRequest.ts b/libs/common/src/models/request/passwordHistoryRequest.ts new file mode 100644 index 0000000000..6cca2b86d2 --- /dev/null +++ b/libs/common/src/models/request/passwordHistoryRequest.ts @@ -0,0 +1,4 @@ +export class PasswordHistoryRequest { + password: string; + lastUsedDate: Date; +} diff --git a/libs/common/src/models/request/passwordRequest.ts b/libs/common/src/models/request/passwordRequest.ts new file mode 100644 index 0000000000..9f7df7df37 --- /dev/null +++ b/libs/common/src/models/request/passwordRequest.ts @@ -0,0 +1,6 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class PasswordRequest extends SecretVerificationRequest { + newMasterPasswordHash: string; + key: string; +} diff --git a/libs/common/src/models/request/paymentRequest.ts b/libs/common/src/models/request/paymentRequest.ts new file mode 100644 index 0000000000..8e7f70a1bf --- /dev/null +++ b/libs/common/src/models/request/paymentRequest.ts @@ -0,0 +1,7 @@ +import { PaymentMethodType } from "../../enums/paymentMethodType"; +import { OrganizationTaxInfoUpdateRequest } from "../request/organizationTaxInfoUpdateRequest"; + +export class PaymentRequest extends OrganizationTaxInfoUpdateRequest { + paymentMethodType: PaymentMethodType; + paymentToken: string; +} diff --git a/libs/common/src/models/request/policyRequest.ts b/libs/common/src/models/request/policyRequest.ts new file mode 100644 index 0000000000..98b05912b4 --- /dev/null +++ b/libs/common/src/models/request/policyRequest.ts @@ -0,0 +1,7 @@ +import { PolicyType } from "../../enums/policyType"; + +export class PolicyRequest { + type: PolicyType; + enabled: boolean; + data: any; +} diff --git a/libs/common/src/models/request/preloginRequest.ts b/libs/common/src/models/request/preloginRequest.ts new file mode 100644 index 0000000000..689204b79e --- /dev/null +++ b/libs/common/src/models/request/preloginRequest.ts @@ -0,0 +1,7 @@ +export class PreloginRequest { + email: string; + + constructor(email: string) { + this.email = email; + } +} diff --git a/libs/common/src/models/request/provider/providerAddOrganizationRequest.ts b/libs/common/src/models/request/provider/providerAddOrganizationRequest.ts new file mode 100644 index 0000000000..380eea1d60 --- /dev/null +++ b/libs/common/src/models/request/provider/providerAddOrganizationRequest.ts @@ -0,0 +1,4 @@ +export class ProviderAddOrganizationRequest { + organizationId: string; + key: string; +} diff --git a/libs/common/src/models/request/provider/providerOrganizationCreateRequest.ts b/libs/common/src/models/request/provider/providerOrganizationCreateRequest.ts new file mode 100644 index 0000000000..8d02f53068 --- /dev/null +++ b/libs/common/src/models/request/provider/providerOrganizationCreateRequest.ts @@ -0,0 +1,8 @@ +import { OrganizationCreateRequest } from "../organizationCreateRequest"; + +export class ProviderOrganizationCreateRequest { + constructor( + public clientOwnerEmail: string, + public organizationCreateRequest: OrganizationCreateRequest + ) {} +} diff --git a/libs/common/src/models/request/provider/providerSetupRequest.ts b/libs/common/src/models/request/provider/providerSetupRequest.ts new file mode 100644 index 0000000000..61eb943f1d --- /dev/null +++ b/libs/common/src/models/request/provider/providerSetupRequest.ts @@ -0,0 +1,7 @@ +export class ProviderSetupRequest { + name: string; + businessName: string; + billingEmail: string; + token: string; + key: string; +} diff --git a/libs/common/src/models/request/provider/providerUpdateRequest.ts b/libs/common/src/models/request/provider/providerUpdateRequest.ts new file mode 100644 index 0000000000..dafa7418a3 --- /dev/null +++ b/libs/common/src/models/request/provider/providerUpdateRequest.ts @@ -0,0 +1,5 @@ +export class ProviderUpdateRequest { + name: string; + businessName: string; + billingEmail: string; +} diff --git a/libs/common/src/models/request/provider/providerUserAcceptRequest.ts b/libs/common/src/models/request/provider/providerUserAcceptRequest.ts new file mode 100644 index 0000000000..0435e1df08 --- /dev/null +++ b/libs/common/src/models/request/provider/providerUserAcceptRequest.ts @@ -0,0 +1,3 @@ +export class ProviderUserAcceptRequest { + token: string; +} diff --git a/libs/common/src/models/request/provider/providerUserBulkConfirmRequest.ts b/libs/common/src/models/request/provider/providerUserBulkConfirmRequest.ts new file mode 100644 index 0000000000..76628b09da --- /dev/null +++ b/libs/common/src/models/request/provider/providerUserBulkConfirmRequest.ts @@ -0,0 +1,12 @@ +type ProviderUserBulkRequestEntry = { + id: string; + key: string; +}; + +export class ProviderUserBulkConfirmRequest { + keys: ProviderUserBulkRequestEntry[]; + + constructor(keys: ProviderUserBulkRequestEntry[]) { + this.keys = keys; + } +} diff --git a/libs/common/src/models/request/provider/providerUserBulkRequest.ts b/libs/common/src/models/request/provider/providerUserBulkRequest.ts new file mode 100644 index 0000000000..f45ed1bbc5 --- /dev/null +++ b/libs/common/src/models/request/provider/providerUserBulkRequest.ts @@ -0,0 +1,7 @@ +export class ProviderUserBulkRequest { + ids: string[]; + + constructor(ids: string[]) { + this.ids = ids == null ? [] : ids; + } +} diff --git a/libs/common/src/models/request/provider/providerUserConfirmRequest.ts b/libs/common/src/models/request/provider/providerUserConfirmRequest.ts new file mode 100644 index 0000000000..1b7d4a0615 --- /dev/null +++ b/libs/common/src/models/request/provider/providerUserConfirmRequest.ts @@ -0,0 +1,3 @@ +export class ProviderUserConfirmRequest { + key: string; +} diff --git a/libs/common/src/models/request/provider/providerUserInviteRequest.ts b/libs/common/src/models/request/provider/providerUserInviteRequest.ts new file mode 100644 index 0000000000..65d8ba67f6 --- /dev/null +++ b/libs/common/src/models/request/provider/providerUserInviteRequest.ts @@ -0,0 +1,6 @@ +import { ProviderUserType } from "../../../enums/providerUserType"; + +export class ProviderUserInviteRequest { + emails: string[] = []; + type: ProviderUserType; +} diff --git a/libs/common/src/models/request/provider/providerUserUpdateRequest.ts b/libs/common/src/models/request/provider/providerUserUpdateRequest.ts new file mode 100644 index 0000000000..25efdd89ce --- /dev/null +++ b/libs/common/src/models/request/provider/providerUserUpdateRequest.ts @@ -0,0 +1,5 @@ +import { ProviderUserType } from "../../../enums/providerUserType"; + +export class ProviderUserUpdateRequest { + type: ProviderUserType; +} diff --git a/libs/common/src/models/request/referenceEventRequest.ts b/libs/common/src/models/request/referenceEventRequest.ts new file mode 100644 index 0000000000..7a0b535a12 --- /dev/null +++ b/libs/common/src/models/request/referenceEventRequest.ts @@ -0,0 +1,5 @@ +export class ReferenceEventRequest { + id: string; + layout: string; + flow: string; +} diff --git a/libs/common/src/models/request/registerRequest.ts b/libs/common/src/models/request/registerRequest.ts new file mode 100644 index 0000000000..8650c5c509 --- /dev/null +++ b/libs/common/src/models/request/registerRequest.ts @@ -0,0 +1,26 @@ +import { KdfType } from "../../enums/kdfType"; + +import { CaptchaProtectedRequest } from "./captchaProtectedRequest"; +import { KeysRequest } from "./keysRequest"; +import { ReferenceEventRequest } from "./referenceEventRequest"; + +export class RegisterRequest implements CaptchaProtectedRequest { + masterPasswordHint: string; + keys: KeysRequest; + token: string; + organizationUserId: string; + + constructor( + public email: string, + public name: string, + public masterPasswordHash: string, + masterPasswordHint: string, + public key: string, + public kdf: KdfType, + public kdfIterations: number, + public referenceData: ReferenceEventRequest, + public captchaResponse: string + ) { + this.masterPasswordHint = masterPasswordHint ? masterPasswordHint : null; + } +} diff --git a/libs/common/src/models/request/seatRequest.ts b/libs/common/src/models/request/seatRequest.ts new file mode 100644 index 0000000000..d60e41fade --- /dev/null +++ b/libs/common/src/models/request/seatRequest.ts @@ -0,0 +1,3 @@ +export class SeatRequest { + seatAdjustment: number; +} diff --git a/libs/common/src/models/request/secretVerificationRequest.ts b/libs/common/src/models/request/secretVerificationRequest.ts new file mode 100644 index 0000000000..c0170a3e52 --- /dev/null +++ b/libs/common/src/models/request/secretVerificationRequest.ts @@ -0,0 +1,4 @@ +export class SecretVerificationRequest { + masterPasswordHash: string; + otp: string; +} diff --git a/libs/common/src/models/request/selectionReadOnlyRequest.ts b/libs/common/src/models/request/selectionReadOnlyRequest.ts new file mode 100644 index 0000000000..7b007324c4 --- /dev/null +++ b/libs/common/src/models/request/selectionReadOnlyRequest.ts @@ -0,0 +1,11 @@ +export class SelectionReadOnlyRequest { + id: string; + readOnly: boolean; + hidePasswords: boolean; + + constructor(id: string, readOnly: boolean, hidePasswords: boolean) { + this.id = id; + this.readOnly = readOnly; + this.hidePasswords = hidePasswords; + } +} diff --git a/libs/common/src/models/request/sendAccessRequest.ts b/libs/common/src/models/request/sendAccessRequest.ts new file mode 100644 index 0000000000..7607b03c62 --- /dev/null +++ b/libs/common/src/models/request/sendAccessRequest.ts @@ -0,0 +1,3 @@ +export class SendAccessRequest { + password: string; +} diff --git a/libs/common/src/models/request/sendRequest.ts b/libs/common/src/models/request/sendRequest.ts new file mode 100644 index 0000000000..1c77204c07 --- /dev/null +++ b/libs/common/src/models/request/sendRequest.ts @@ -0,0 +1,48 @@ +import { SendType } from "../../enums/sendType"; +import { SendFileApi } from "../api/sendFileApi"; +import { SendTextApi } from "../api/sendTextApi"; +import { Send } from "../domain/send"; + +export class SendRequest { + type: SendType; + fileLength?: number; + name: string; + notes: string; + key: string; + maxAccessCount?: number; + expirationDate: string; + deletionDate: string; + text: SendTextApi; + file: SendFileApi; + password: string; + disabled: boolean; + hideEmail: boolean; + + constructor(send: Send, fileLength?: number) { + this.type = send.type; + this.fileLength = fileLength; + this.name = send.name ? send.name.encryptedString : null; + this.notes = send.notes ? send.notes.encryptedString : null; + this.maxAccessCount = send.maxAccessCount; + this.expirationDate = send.expirationDate != null ? send.expirationDate.toISOString() : null; + this.deletionDate = send.deletionDate != null ? send.deletionDate.toISOString() : null; + this.key = send.key != null ? send.key.encryptedString : null; + this.password = send.password; + this.disabled = send.disabled; + this.hideEmail = send.hideEmail; + + switch (this.type) { + case SendType.Text: + this.text = new SendTextApi(); + this.text.text = send.text.text != null ? send.text.text.encryptedString : null; + this.text.hidden = send.text.hidden; + break; + case SendType.File: + this.file = new SendFileApi(); + this.file.fileName = send.file.fileName != null ? send.file.fileName.encryptedString : null; + break; + default: + break; + } + } +} diff --git a/libs/common/src/models/request/sendWithIdRequest.ts b/libs/common/src/models/request/sendWithIdRequest.ts new file mode 100644 index 0000000000..8591a57ecb --- /dev/null +++ b/libs/common/src/models/request/sendWithIdRequest.ts @@ -0,0 +1,12 @@ +import { Send } from "../domain/send"; + +import { SendRequest } from "./sendRequest"; + +export class SendWithIdRequest extends SendRequest { + id: string; + + constructor(send: Send) { + super(send); + this.id = send.id; + } +} diff --git a/libs/common/src/models/request/setPasswordRequest.ts b/libs/common/src/models/request/setPasswordRequest.ts new file mode 100644 index 0000000000..919a132f58 --- /dev/null +++ b/libs/common/src/models/request/setPasswordRequest.ts @@ -0,0 +1,31 @@ +import { KdfType } from "../../enums/kdfType"; + +import { KeysRequest } from "./keysRequest"; + +export class SetPasswordRequest { + masterPasswordHash: string; + key: string; + masterPasswordHint: string; + keys: KeysRequest; + kdf: KdfType; + kdfIterations: number; + orgIdentifier: string; + + constructor( + masterPasswordHash: string, + key: string, + masterPasswordHint: string, + kdf: KdfType, + kdfIterations: number, + orgIdentifier: string, + keys: KeysRequest + ) { + this.masterPasswordHash = masterPasswordHash; + this.key = key; + this.masterPasswordHint = masterPasswordHint; + this.kdf = kdf; + this.kdfIterations = kdfIterations; + this.orgIdentifier = orgIdentifier; + this.keys = keys; + } +} diff --git a/libs/common/src/models/request/storageRequest.ts b/libs/common/src/models/request/storageRequest.ts new file mode 100644 index 0000000000..4b3b614d09 --- /dev/null +++ b/libs/common/src/models/request/storageRequest.ts @@ -0,0 +1,3 @@ +export class StorageRequest { + storageGbAdjustment: number; +} diff --git a/libs/common/src/models/request/taxInfoUpdateRequest.ts b/libs/common/src/models/request/taxInfoUpdateRequest.ts new file mode 100644 index 0000000000..6881a8a432 --- /dev/null +++ b/libs/common/src/models/request/taxInfoUpdateRequest.ts @@ -0,0 +1,4 @@ +export class TaxInfoUpdateRequest { + country: string; + postalCode: string; +} diff --git a/libs/common/src/models/request/twoFactorEmailRequest.ts b/libs/common/src/models/request/twoFactorEmailRequest.ts new file mode 100644 index 0000000000..e4fa59c259 --- /dev/null +++ b/libs/common/src/models/request/twoFactorEmailRequest.ts @@ -0,0 +1,6 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class TwoFactorEmailRequest extends SecretVerificationRequest { + email: string; + deviceIdentifier: string; +} diff --git a/libs/common/src/models/request/twoFactorProviderRequest.ts b/libs/common/src/models/request/twoFactorProviderRequest.ts new file mode 100644 index 0000000000..9d606bc95e --- /dev/null +++ b/libs/common/src/models/request/twoFactorProviderRequest.ts @@ -0,0 +1,7 @@ +import { TwoFactorProviderType } from "../../enums/twoFactorProviderType"; + +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class TwoFactorProviderRequest extends SecretVerificationRequest { + type: TwoFactorProviderType; +} diff --git a/libs/common/src/models/request/twoFactorRecoveryRequest.ts b/libs/common/src/models/request/twoFactorRecoveryRequest.ts new file mode 100644 index 0000000000..39135a37f7 --- /dev/null +++ b/libs/common/src/models/request/twoFactorRecoveryRequest.ts @@ -0,0 +1,6 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class TwoFactorRecoveryRequest extends SecretVerificationRequest { + recoveryCode: string; + email: string; +} diff --git a/libs/common/src/models/request/updateDomainsRequest.ts b/libs/common/src/models/request/updateDomainsRequest.ts new file mode 100644 index 0000000000..528d36829e --- /dev/null +++ b/libs/common/src/models/request/updateDomainsRequest.ts @@ -0,0 +1,4 @@ +export class UpdateDomainsRequest { + equivalentDomains: string[][]; + excludedGlobalEquivalentDomains: number[]; +} diff --git a/libs/common/src/models/request/updateKeyRequest.ts b/libs/common/src/models/request/updateKeyRequest.ts new file mode 100644 index 0000000000..a9fceffdb0 --- /dev/null +++ b/libs/common/src/models/request/updateKeyRequest.ts @@ -0,0 +1,12 @@ +import { CipherWithIdRequest } from "./cipherWithIdRequest"; +import { FolderWithIdRequest } from "./folderWithIdRequest"; +import { SendWithIdRequest } from "./sendWithIdRequest"; + +export class UpdateKeyRequest { + ciphers: CipherWithIdRequest[] = []; + folders: FolderWithIdRequest[] = []; + sends: SendWithIdRequest[] = []; + masterPasswordHash: string; + privateKey: string; + key: string; +} diff --git a/libs/common/src/models/request/updateProfileRequest.ts b/libs/common/src/models/request/updateProfileRequest.ts new file mode 100644 index 0000000000..14ed554dc9 --- /dev/null +++ b/libs/common/src/models/request/updateProfileRequest.ts @@ -0,0 +1,10 @@ +export class UpdateProfileRequest { + name: string; + masterPasswordHint: string; + culture = "en-US"; // deprecated + + constructor(name: string, masterPasswordHint: string) { + this.name = name; + this.masterPasswordHint = masterPasswordHint ? masterPasswordHint : null; + } +} diff --git a/libs/common/src/models/request/updateTempPasswordRequest.ts b/libs/common/src/models/request/updateTempPasswordRequest.ts new file mode 100644 index 0000000000..1bd97697c5 --- /dev/null +++ b/libs/common/src/models/request/updateTempPasswordRequest.ts @@ -0,0 +1,5 @@ +import { OrganizationUserResetPasswordRequest } from "./organizationUserResetPasswordRequest"; + +export class UpdateTempPasswordRequest extends OrganizationUserResetPasswordRequest { + masterPasswordHint: string; +} diff --git a/libs/common/src/models/request/updateTwoFactorAuthenticatorRequest.ts b/libs/common/src/models/request/updateTwoFactorAuthenticatorRequest.ts new file mode 100644 index 0000000000..9b7182873b --- /dev/null +++ b/libs/common/src/models/request/updateTwoFactorAuthenticatorRequest.ts @@ -0,0 +1,6 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class UpdateTwoFactorAuthenticatorRequest extends SecretVerificationRequest { + token: string; + key: string; +} diff --git a/libs/common/src/models/request/updateTwoFactorDuoRequest.ts b/libs/common/src/models/request/updateTwoFactorDuoRequest.ts new file mode 100644 index 0000000000..cd82215d97 --- /dev/null +++ b/libs/common/src/models/request/updateTwoFactorDuoRequest.ts @@ -0,0 +1,7 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class UpdateTwoFactorDuoRequest extends SecretVerificationRequest { + integrationKey: string; + secretKey: string; + host: string; +} diff --git a/libs/common/src/models/request/updateTwoFactorEmailRequest.ts b/libs/common/src/models/request/updateTwoFactorEmailRequest.ts new file mode 100644 index 0000000000..be7da1fdc6 --- /dev/null +++ b/libs/common/src/models/request/updateTwoFactorEmailRequest.ts @@ -0,0 +1,6 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class UpdateTwoFactorEmailRequest extends SecretVerificationRequest { + token: string; + email: string; +} diff --git a/libs/common/src/models/request/updateTwoFactorWebAuthnDeleteRequest.ts b/libs/common/src/models/request/updateTwoFactorWebAuthnDeleteRequest.ts new file mode 100644 index 0000000000..1decda7256 --- /dev/null +++ b/libs/common/src/models/request/updateTwoFactorWebAuthnDeleteRequest.ts @@ -0,0 +1,5 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class UpdateTwoFactorWebAuthnDeleteRequest extends SecretVerificationRequest { + id: number; +} diff --git a/libs/common/src/models/request/updateTwoFactorWebAuthnRequest.ts b/libs/common/src/models/request/updateTwoFactorWebAuthnRequest.ts new file mode 100644 index 0000000000..2e788b52d9 --- /dev/null +++ b/libs/common/src/models/request/updateTwoFactorWebAuthnRequest.ts @@ -0,0 +1,7 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class UpdateTwoFactorWebAuthnRequest extends SecretVerificationRequest { + deviceResponse: PublicKeyCredential; + name: string; + id: number; +} diff --git a/libs/common/src/models/request/updateTwoFactorYubioOtpRequest.ts b/libs/common/src/models/request/updateTwoFactorYubioOtpRequest.ts new file mode 100644 index 0000000000..cb495b1e6a --- /dev/null +++ b/libs/common/src/models/request/updateTwoFactorYubioOtpRequest.ts @@ -0,0 +1,10 @@ +import { SecretVerificationRequest } from "./secretVerificationRequest"; + +export class UpdateTwoFactorYubioOtpRequest extends SecretVerificationRequest { + key1: string; + key2: string; + key3: string; + key4: string; + key5: string; + nfc: boolean; +} diff --git a/libs/common/src/models/request/verifyBankRequest.ts b/libs/common/src/models/request/verifyBankRequest.ts new file mode 100644 index 0000000000..823eaf4616 --- /dev/null +++ b/libs/common/src/models/request/verifyBankRequest.ts @@ -0,0 +1,4 @@ +export class VerifyBankRequest { + amount1: number; + amount2: number; +} diff --git a/libs/common/src/models/request/verifyDeleteRecoverRequest.ts b/libs/common/src/models/request/verifyDeleteRecoverRequest.ts new file mode 100644 index 0000000000..2374d32db8 --- /dev/null +++ b/libs/common/src/models/request/verifyDeleteRecoverRequest.ts @@ -0,0 +1,9 @@ +export class VerifyDeleteRecoverRequest { + userId: string; + token: string; + + constructor(userId: string, token: string) { + this.userId = userId; + this.token = token; + } +} diff --git a/libs/common/src/models/request/verifyEmailRequest.ts b/libs/common/src/models/request/verifyEmailRequest.ts new file mode 100644 index 0000000000..ecee0190f0 --- /dev/null +++ b/libs/common/src/models/request/verifyEmailRequest.ts @@ -0,0 +1,9 @@ +export class VerifyEmailRequest { + userId: string; + token: string; + + constructor(userId: string, token: string) { + this.userId = userId; + this.token = token; + } +} diff --git a/libs/common/src/models/response/apiKeyResponse.ts b/libs/common/src/models/response/apiKeyResponse.ts new file mode 100644 index 0000000000..950850eec1 --- /dev/null +++ b/libs/common/src/models/response/apiKeyResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class ApiKeyResponse extends BaseResponse { + apiKey: string; + revisionDate: Date; + + constructor(response: any) { + super(response); + this.apiKey = this.getResponseProperty("ApiKey"); + this.revisionDate = new Date(this.getResponseProperty("RevisionDate")); + } +} diff --git a/libs/common/src/models/response/attachmentResponse.ts b/libs/common/src/models/response/attachmentResponse.ts new file mode 100644 index 0000000000..a9ebfaf329 --- /dev/null +++ b/libs/common/src/models/response/attachmentResponse.ts @@ -0,0 +1,20 @@ +import { BaseResponse } from "./baseResponse"; + +export class AttachmentResponse extends BaseResponse { + id: string; + url: string; + fileName: string; + key: string; + size: string; + sizeName: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.url = this.getResponseProperty("Url"); + this.fileName = this.getResponseProperty("FileName"); + this.key = this.getResponseProperty("Key"); + this.size = this.getResponseProperty("Size"); + this.sizeName = this.getResponseProperty("SizeName"); + } +} diff --git a/libs/common/src/models/response/attachmentUploadDataResponse.ts b/libs/common/src/models/response/attachmentUploadDataResponse.ts new file mode 100644 index 0000000000..4520c30997 --- /dev/null +++ b/libs/common/src/models/response/attachmentUploadDataResponse.ts @@ -0,0 +1,23 @@ +import { FileUploadType } from "../../enums/fileUploadType"; + +import { BaseResponse } from "./baseResponse"; +import { CipherResponse } from "./cipherResponse"; + +export class AttachmentUploadDataResponse extends BaseResponse { + attachmentId: string; + fileUploadType: FileUploadType; + cipherResponse: CipherResponse; + cipherMiniResponse: CipherResponse; + url: string = null; + constructor(response: any) { + super(response); + this.attachmentId = this.getResponseProperty("AttachmentId"); + this.fileUploadType = this.getResponseProperty("FileUploadType"); + const cipherResponse = this.getResponseProperty("CipherResponse"); + const cipherMiniResponse = this.getResponseProperty("CipherMiniResponse"); + this.cipherResponse = cipherResponse == null ? null : new CipherResponse(cipherResponse); + this.cipherMiniResponse = + cipherMiniResponse == null ? null : new CipherResponse(cipherMiniResponse); + this.url = this.getResponseProperty("Url"); + } +} diff --git a/libs/common/src/models/response/baseResponse.ts b/libs/common/src/models/response/baseResponse.ts new file mode 100644 index 0000000000..8c599fba59 --- /dev/null +++ b/libs/common/src/models/response/baseResponse.ts @@ -0,0 +1,43 @@ +export abstract class BaseResponse { + private response: any; + + constructor(response: any) { + this.response = response; + } + + protected getResponseProperty( + propertyName: string, + response: any = null, + exactName = false + ): any { + if (propertyName == null || propertyName === "") { + throw new Error("propertyName must not be null/empty."); + } + if (response == null && this.response != null) { + response = this.response; + } + if (response == null) { + return null; + } + if (!exactName && response[propertyName] === undefined) { + let otherCasePropertyName: string = null; + if (propertyName.charAt(0) === propertyName.charAt(0).toUpperCase()) { + otherCasePropertyName = propertyName.charAt(0).toLowerCase(); + } else { + otherCasePropertyName = propertyName.charAt(0).toUpperCase(); + } + if (propertyName.length > 1) { + otherCasePropertyName += propertyName.slice(1); + } + + propertyName = otherCasePropertyName; + if (response[propertyName] === undefined) { + propertyName = propertyName.toLowerCase(); + } + if (response[propertyName] === undefined) { + propertyName = propertyName.toUpperCase(); + } + } + return response[propertyName]; + } +} diff --git a/libs/common/src/models/response/billingHistoryResponse.ts b/libs/common/src/models/response/billingHistoryResponse.ts new file mode 100644 index 0000000000..c7dead81f5 --- /dev/null +++ b/libs/common/src/models/response/billingHistoryResponse.ts @@ -0,0 +1,23 @@ +import { BaseResponse } from "./baseResponse"; +import { BillingInvoiceResponse, BillingTransactionResponse } from "./billingResponse"; + +export class BillingHistoryResponse extends BaseResponse { + invoices: BillingInvoiceResponse[] = []; + transactions: BillingTransactionResponse[] = []; + + constructor(response: any) { + super(response); + const transactions = this.getResponseProperty("Transactions"); + const invoices = this.getResponseProperty("Invoices"); + if (transactions != null) { + this.transactions = transactions.map((t: any) => new BillingTransactionResponse(t)); + } + if (invoices != null) { + this.invoices = invoices.map((i: any) => new BillingInvoiceResponse(i)); + } + } + + get hasNoHistory() { + return this.invoices.length == 0 && this.transactions.length == 0; + } +} diff --git a/libs/common/src/models/response/billingPaymentResponse.ts b/libs/common/src/models/response/billingPaymentResponse.ts new file mode 100644 index 0000000000..869e5a0d3f --- /dev/null +++ b/libs/common/src/models/response/billingPaymentResponse.ts @@ -0,0 +1,14 @@ +import { BaseResponse } from "./baseResponse"; +import { BillingSourceResponse } from "./billingResponse"; + +export class BillingPaymentResponse extends BaseResponse { + balance: number; + paymentSource: BillingSourceResponse; + + constructor(response: any) { + super(response); + this.balance = this.getResponseProperty("Balance"); + const paymentSource = this.getResponseProperty("PaymentSource"); + this.paymentSource = paymentSource == null ? null : new BillingSourceResponse(paymentSource); + } +} diff --git a/libs/common/src/models/response/billingResponse.ts b/libs/common/src/models/response/billingResponse.ts new file mode 100644 index 0000000000..8d09cf9311 --- /dev/null +++ b/libs/common/src/models/response/billingResponse.ts @@ -0,0 +1,83 @@ +import { PaymentMethodType } from "../../enums/paymentMethodType"; +import { TransactionType } from "../../enums/transactionType"; + +import { BaseResponse } from "./baseResponse"; + +export class BillingResponse extends BaseResponse { + balance: number; + paymentSource: BillingSourceResponse; + invoices: BillingInvoiceResponse[] = []; + transactions: BillingTransactionResponse[] = []; + + constructor(response: any) { + super(response); + this.balance = this.getResponseProperty("Balance"); + const paymentSource = this.getResponseProperty("PaymentSource"); + const transactions = this.getResponseProperty("Transactions"); + const invoices = this.getResponseProperty("Invoices"); + this.paymentSource = paymentSource == null ? null : new BillingSourceResponse(paymentSource); + if (transactions != null) { + this.transactions = transactions.map((t: any) => new BillingTransactionResponse(t)); + } + if (invoices != null) { + this.invoices = invoices.map((i: any) => new BillingInvoiceResponse(i)); + } + } +} + +export class BillingSourceResponse extends BaseResponse { + type: PaymentMethodType; + cardBrand: string; + description: string; + needsVerification: boolean; + + constructor(response: any) { + super(response); + this.type = this.getResponseProperty("Type"); + this.cardBrand = this.getResponseProperty("CardBrand"); + this.description = this.getResponseProperty("Description"); + this.needsVerification = this.getResponseProperty("NeedsVerification"); + } +} + +export class BillingInvoiceResponse extends BaseResponse { + url: string; + pdfUrl: string; + number: string; + paid: boolean; + date: string; + amount: number; + + constructor(response: any) { + super(response); + this.url = this.getResponseProperty("Url"); + this.pdfUrl = this.getResponseProperty("PdfUrl"); + this.number = this.getResponseProperty("Number"); + this.paid = this.getResponseProperty("Paid"); + this.date = this.getResponseProperty("Date"); + this.amount = this.getResponseProperty("Amount"); + } +} + +export class BillingTransactionResponse extends BaseResponse { + createdDate: string; + amount: number; + refunded: boolean; + partiallyRefunded: boolean; + refundedAmount: number; + type: TransactionType; + paymentMethodType: PaymentMethodType; + details: string; + + constructor(response: any) { + super(response); + this.createdDate = this.getResponseProperty("CreatedDate"); + this.amount = this.getResponseProperty("Amount"); + this.refunded = this.getResponseProperty("Refunded"); + this.partiallyRefunded = this.getResponseProperty("PartiallyRefunded"); + this.refundedAmount = this.getResponseProperty("RefundedAmount"); + this.type = this.getResponseProperty("Type"); + this.paymentMethodType = this.getResponseProperty("PaymentMethodType"); + this.details = this.getResponseProperty("Details"); + } +} diff --git a/libs/common/src/models/response/breachAccountResponse.ts b/libs/common/src/models/response/breachAccountResponse.ts new file mode 100644 index 0000000000..00d39acc0e --- /dev/null +++ b/libs/common/src/models/response/breachAccountResponse.ts @@ -0,0 +1,32 @@ +import { BaseResponse } from "./baseResponse"; + +export class BreachAccountResponse extends BaseResponse { + addedDate: string; + breachDate: string; + dataClasses: string[]; + description: string; + domain: string; + isActive: boolean; + isVerified: boolean; + logoPath: string; + modifiedDate: string; + name: string; + pwnCount: number; + title: string; + + constructor(response: any) { + super(response); + this.addedDate = this.getResponseProperty("AddedDate"); + this.breachDate = this.getResponseProperty("BreachDate"); + this.dataClasses = this.getResponseProperty("DataClasses"); + this.description = this.getResponseProperty("Description"); + this.domain = this.getResponseProperty("Domain"); + this.isActive = this.getResponseProperty("IsActive"); + this.isVerified = this.getResponseProperty("IsVerified"); + this.logoPath = this.getResponseProperty("LogoPath"); + this.modifiedDate = this.getResponseProperty("ModifiedDate"); + this.name = this.getResponseProperty("Name"); + this.pwnCount = this.getResponseProperty("PwnCount"); + this.title = this.getResponseProperty("Title"); + } +} diff --git a/libs/common/src/models/response/cipherResponse.ts b/libs/common/src/models/response/cipherResponse.ts new file mode 100644 index 0000000000..5b461438e9 --- /dev/null +++ b/libs/common/src/models/response/cipherResponse.ts @@ -0,0 +1,92 @@ +import { CipherRepromptType } from "../../enums/cipherRepromptType"; +import { CardApi } from "../api/cardApi"; +import { FieldApi } from "../api/fieldApi"; +import { IdentityApi } from "../api/identityApi"; +import { LoginApi } from "../api/loginApi"; +import { SecureNoteApi } from "../api/secureNoteApi"; + +import { AttachmentResponse } from "./attachmentResponse"; +import { BaseResponse } from "./baseResponse"; +import { PasswordHistoryResponse } from "./passwordHistoryResponse"; + +export class CipherResponse extends BaseResponse { + id: string; + organizationId: string; + folderId: string; + type: number; + name: string; + notes: string; + fields: FieldApi[]; + login: LoginApi; + card: CardApi; + identity: IdentityApi; + secureNote: SecureNoteApi; + favorite: boolean; + edit: boolean; + viewPassword: boolean; + organizationUseTotp: boolean; + revisionDate: string; + attachments: AttachmentResponse[]; + passwordHistory: PasswordHistoryResponse[]; + collectionIds: string[]; + deletedDate: string; + reprompt: CipherRepromptType; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.folderId = this.getResponseProperty("FolderId") || null; + this.type = this.getResponseProperty("Type"); + this.name = this.getResponseProperty("Name"); + this.notes = this.getResponseProperty("Notes"); + this.favorite = this.getResponseProperty("Favorite") || false; + this.edit = !!this.getResponseProperty("Edit"); + if (this.getResponseProperty("ViewPassword") == null) { + this.viewPassword = true; + } else { + this.viewPassword = this.getResponseProperty("ViewPassword"); + } + this.organizationUseTotp = this.getResponseProperty("OrganizationUseTotp"); + this.revisionDate = this.getResponseProperty("RevisionDate"); + this.collectionIds = this.getResponseProperty("CollectionIds"); + this.deletedDate = this.getResponseProperty("DeletedDate"); + + const login = this.getResponseProperty("Login"); + if (login != null) { + this.login = new LoginApi(login); + } + + const card = this.getResponseProperty("Card"); + if (card != null) { + this.card = new CardApi(card); + } + + const identity = this.getResponseProperty("Identity"); + if (identity != null) { + this.identity = new IdentityApi(identity); + } + + const secureNote = this.getResponseProperty("SecureNote"); + if (secureNote != null) { + this.secureNote = new SecureNoteApi(secureNote); + } + + const fields = this.getResponseProperty("Fields"); + if (fields != null) { + this.fields = fields.map((f: any) => new FieldApi(f)); + } + + const attachments = this.getResponseProperty("Attachments"); + if (attachments != null) { + this.attachments = attachments.map((a: any) => new AttachmentResponse(a)); + } + + const passwordHistory = this.getResponseProperty("PasswordHistory"); + if (passwordHistory != null) { + this.passwordHistory = passwordHistory.map((h: any) => new PasswordHistoryResponse(h)); + } + + this.reprompt = this.getResponseProperty("Reprompt") || CipherRepromptType.None; + } +} diff --git a/libs/common/src/models/response/collectionResponse.ts b/libs/common/src/models/response/collectionResponse.ts new file mode 100644 index 0000000000..2f677f7d85 --- /dev/null +++ b/libs/common/src/models/response/collectionResponse.ts @@ -0,0 +1,38 @@ +import { BaseResponse } from "./baseResponse"; +import { SelectionReadOnlyResponse } from "./selectionReadOnlyResponse"; + +export class CollectionResponse extends BaseResponse { + id: string; + organizationId: string; + name: string; + externalId: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.name = this.getResponseProperty("Name"); + this.externalId = this.getResponseProperty("ExternalId"); + } +} + +export class CollectionDetailsResponse extends CollectionResponse { + readOnly: boolean; + + constructor(response: any) { + super(response); + this.readOnly = this.getResponseProperty("ReadOnly") || false; + } +} + +export class CollectionGroupDetailsResponse extends CollectionResponse { + groups: SelectionReadOnlyResponse[] = []; + + constructor(response: any) { + super(response); + const groups = this.getResponseProperty("Groups"); + if (groups != null) { + this.groups = groups.map((g: any) => new SelectionReadOnlyResponse(g)); + } + } +} diff --git a/libs/common/src/models/response/deviceResponse.ts b/libs/common/src/models/response/deviceResponse.ts new file mode 100644 index 0000000000..aac9ac6c6b --- /dev/null +++ b/libs/common/src/models/response/deviceResponse.ts @@ -0,0 +1,20 @@ +import { DeviceType } from "../../enums/deviceType"; + +import { BaseResponse } from "./baseResponse"; + +export class DeviceResponse extends BaseResponse { + id: string; + name: number; + identifier: string; + type: DeviceType; + creationDate: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.name = this.getResponseProperty("Name"); + this.identifier = this.getResponseProperty("Identifier"); + this.type = this.getResponseProperty("Type"); + this.creationDate = this.getResponseProperty("CreationDate"); + } +} diff --git a/libs/common/src/models/response/domainsResponse.ts b/libs/common/src/models/response/domainsResponse.ts new file mode 100644 index 0000000000..3014c2f21b --- /dev/null +++ b/libs/common/src/models/response/domainsResponse.ts @@ -0,0 +1,20 @@ +import { BaseResponse } from "./baseResponse"; +import { GlobalDomainResponse } from "./globalDomainResponse"; + +export class DomainsResponse extends BaseResponse { + equivalentDomains: string[][]; + globalEquivalentDomains: GlobalDomainResponse[] = []; + + constructor(response: any) { + super(response); + this.equivalentDomains = this.getResponseProperty("EquivalentDomains"); + const globalEquivalentDomains = this.getResponseProperty("GlobalEquivalentDomains"); + if (globalEquivalentDomains != null) { + this.globalEquivalentDomains = globalEquivalentDomains.map( + (d: any) => new GlobalDomainResponse(d) + ); + } else { + this.globalEquivalentDomains = []; + } + } +} diff --git a/libs/common/src/models/response/emergencyAccessResponse.ts b/libs/common/src/models/response/emergencyAccessResponse.ts new file mode 100644 index 0000000000..9ac5380dc2 --- /dev/null +++ b/libs/common/src/models/response/emergencyAccessResponse.ts @@ -0,0 +1,82 @@ +import { EmergencyAccessStatusType } from "../../enums/emergencyAccessStatusType"; +import { EmergencyAccessType } from "../../enums/emergencyAccessType"; +import { KdfType } from "../../enums/kdfType"; + +import { BaseResponse } from "./baseResponse"; +import { CipherResponse } from "./cipherResponse"; + +export class EmergencyAccessGranteeDetailsResponse extends BaseResponse { + id: string; + granteeId: string; + name: string; + email: string; + type: EmergencyAccessType; + status: EmergencyAccessStatusType; + waitTimeDays: number; + creationDate: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.granteeId = this.getResponseProperty("GranteeId"); + this.name = this.getResponseProperty("Name"); + this.email = this.getResponseProperty("Email"); + this.type = this.getResponseProperty("Type"); + this.status = this.getResponseProperty("Status"); + this.waitTimeDays = this.getResponseProperty("WaitTimeDays"); + this.creationDate = this.getResponseProperty("CreationDate"); + } +} + +export class EmergencyAccessGrantorDetailsResponse extends BaseResponse { + id: string; + grantorId: string; + name: string; + email: string; + type: EmergencyAccessType; + status: EmergencyAccessStatusType; + waitTimeDays: number; + creationDate: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.grantorId = this.getResponseProperty("GrantorId"); + this.name = this.getResponseProperty("Name"); + this.email = this.getResponseProperty("Email"); + this.type = this.getResponseProperty("Type"); + this.status = this.getResponseProperty("Status"); + this.waitTimeDays = this.getResponseProperty("WaitTimeDays"); + this.creationDate = this.getResponseProperty("CreationDate"); + } +} + +export class EmergencyAccessTakeoverResponse extends BaseResponse { + keyEncrypted: string; + kdf: KdfType; + kdfIterations: number; + + constructor(response: any) { + super(response); + + this.keyEncrypted = this.getResponseProperty("KeyEncrypted"); + this.kdf = this.getResponseProperty("Kdf"); + this.kdfIterations = this.getResponseProperty("KdfIterations"); + } +} + +export class EmergencyAccessViewResponse extends BaseResponse { + keyEncrypted: string; + ciphers: CipherResponse[] = []; + + constructor(response: any) { + super(response); + + this.keyEncrypted = this.getResponseProperty("KeyEncrypted"); + + const ciphers = this.getResponseProperty("Ciphers"); + if (ciphers != null) { + this.ciphers = ciphers.map((c: any) => new CipherResponse(c)); + } + } +} diff --git a/libs/common/src/models/response/errorResponse.ts b/libs/common/src/models/response/errorResponse.ts new file mode 100644 index 0000000000..3a0d22e695 --- /dev/null +++ b/libs/common/src/models/response/errorResponse.ts @@ -0,0 +1,74 @@ +import { Utils } from "../../misc/utils"; + +import { BaseResponse } from "./baseResponse"; + +export class ErrorResponse extends BaseResponse { + message: string; + validationErrors: { [key: string]: string[] }; + statusCode: number; + captchaRequired: boolean; + captchaSiteKey: string; + + constructor(response: any, status: number, identityResponse?: boolean) { + super(response); + let errorModel = null; + if (response != null) { + const responseErrorModel = this.getResponseProperty("ErrorModel"); + if (responseErrorModel && identityResponse) { + errorModel = responseErrorModel; + } else { + errorModel = response; + } + } + + if (errorModel) { + this.message = this.getResponseProperty("Message", errorModel); + this.validationErrors = this.getResponseProperty("ValidationErrors", errorModel); + this.captchaSiteKey = this.validationErrors?.HCaptcha_SiteKey?.[0]; + this.captchaRequired = !Utils.isNullOrWhitespace(this.captchaSiteKey); + } else { + if (status === 429) { + this.message = "Rate limit exceeded. Try again later."; + } + } + this.statusCode = status; + } + + getSingleMessage(): string { + if (this.validationErrors == null) { + return this.message; + } + for (const key in this.validationErrors) { + // eslint-disable-next-line + if (!this.validationErrors.hasOwnProperty(key)) { + continue; + } + if (this.validationErrors[key].length) { + return this.validationErrors[key][0]; + } + } + return this.message; + } + + getAllMessages(): string[] { + const messages: string[] = []; + if (this.validationErrors == null) { + return messages; + } + for (const key in this.validationErrors) { + // eslint-disable-next-line + if (!this.validationErrors.hasOwnProperty(key)) { + continue; + } + this.validationErrors[key].forEach((item: string) => { + let prefix = ""; + if (key.indexOf("[") > -1 && key.indexOf("]") > -1) { + const lastSep = key.lastIndexOf("."); + prefix = key.substr(0, lastSep > -1 ? lastSep : key.length) + ": "; + } + messages.push(prefix + item); + }); + } + return messages; + } +} diff --git a/libs/common/src/models/response/eventResponse.ts b/libs/common/src/models/response/eventResponse.ts new file mode 100644 index 0000000000..47e3d14093 --- /dev/null +++ b/libs/common/src/models/response/eventResponse.ts @@ -0,0 +1,43 @@ +import { DeviceType } from "../../enums/deviceType"; +import { EventType } from "../../enums/eventType"; + +import { BaseResponse } from "./baseResponse"; + +export class EventResponse extends BaseResponse { + type: EventType; + userId: string; + organizationId: string; + providerId: string; + cipherId: string; + collectionId: string; + groupId: string; + policyId: string; + organizationUserId: string; + providerUserId: string; + providerOrganizationId: string; + actingUserId: string; + date: string; + deviceType: DeviceType; + ipAddress: string; + installationId: string; + + constructor(response: any) { + super(response); + this.type = this.getResponseProperty("Type"); + this.userId = this.getResponseProperty("UserId"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.providerId = this.getResponseProperty("ProviderId"); + this.cipherId = this.getResponseProperty("CipherId"); + this.collectionId = this.getResponseProperty("CollectionId"); + this.groupId = this.getResponseProperty("GroupId"); + this.policyId = this.getResponseProperty("PolicyId"); + this.organizationUserId = this.getResponseProperty("OrganizationUserId"); + this.providerUserId = this.getResponseProperty("ProviderUserId"); + this.providerOrganizationId = this.getResponseProperty("ProviderOrganizationId"); + this.actingUserId = this.getResponseProperty("ActingUserId"); + this.date = this.getResponseProperty("Date"); + this.deviceType = this.getResponseProperty("DeviceType"); + this.ipAddress = this.getResponseProperty("IpAddress"); + this.installationId = this.getResponseProperty("InstallationId"); + } +} diff --git a/libs/common/src/models/response/folderResponse.ts b/libs/common/src/models/response/folderResponse.ts new file mode 100644 index 0000000000..70d4897f87 --- /dev/null +++ b/libs/common/src/models/response/folderResponse.ts @@ -0,0 +1,14 @@ +import { BaseResponse } from "./baseResponse"; + +export class FolderResponse extends BaseResponse { + id: string; + name: string; + revisionDate: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.name = this.getResponseProperty("Name"); + this.revisionDate = this.getResponseProperty("RevisionDate"); + } +} diff --git a/libs/common/src/models/response/globalDomainResponse.ts b/libs/common/src/models/response/globalDomainResponse.ts new file mode 100644 index 0000000000..e3197e769f --- /dev/null +++ b/libs/common/src/models/response/globalDomainResponse.ts @@ -0,0 +1,14 @@ +import { BaseResponse } from "./baseResponse"; + +export class GlobalDomainResponse extends BaseResponse { + type: number; + domains: string[]; + excluded: boolean; + + constructor(response: any) { + super(response); + this.type = this.getResponseProperty("Type"); + this.domains = this.getResponseProperty("Domains"); + this.excluded = this.getResponseProperty("Excluded"); + } +} diff --git a/libs/common/src/models/response/groupResponse.ts b/libs/common/src/models/response/groupResponse.ts new file mode 100644 index 0000000000..ab4b58b7b5 --- /dev/null +++ b/libs/common/src/models/response/groupResponse.ts @@ -0,0 +1,31 @@ +import { BaseResponse } from "./baseResponse"; +import { SelectionReadOnlyResponse } from "./selectionReadOnlyResponse"; + +export class GroupResponse extends BaseResponse { + id: string; + organizationId: string; + name: string; + accessAll: boolean; + externalId: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.name = this.getResponseProperty("Name"); + this.accessAll = this.getResponseProperty("AccessAll"); + this.externalId = this.getResponseProperty("ExternalId"); + } +} + +export class GroupDetailsResponse extends GroupResponse { + collections: SelectionReadOnlyResponse[] = []; + + constructor(response: any) { + super(response); + const collections = this.getResponseProperty("Collections"); + if (collections != null) { + this.collections = collections.map((c: any) => new SelectionReadOnlyResponse(c)); + } + } +} diff --git a/libs/common/src/models/response/identityCaptchaResponse.ts b/libs/common/src/models/response/identityCaptchaResponse.ts new file mode 100644 index 0000000000..2537057e1b --- /dev/null +++ b/libs/common/src/models/response/identityCaptchaResponse.ts @@ -0,0 +1,10 @@ +import { BaseResponse } from "./baseResponse"; + +export class IdentityCaptchaResponse extends BaseResponse { + siteKey: string; + + constructor(response: any) { + super(response); + this.siteKey = this.getResponseProperty("HCaptcha_SiteKey"); + } +} diff --git a/libs/common/src/models/response/identityTokenResponse.ts b/libs/common/src/models/response/identityTokenResponse.ts new file mode 100644 index 0000000000..87b5d39661 --- /dev/null +++ b/libs/common/src/models/response/identityTokenResponse.ts @@ -0,0 +1,38 @@ +import { KdfType } from "../../enums/kdfType"; + +import { BaseResponse } from "./baseResponse"; + +export class IdentityTokenResponse extends BaseResponse { + accessToken: string; + expiresIn: number; + refreshToken: string; + tokenType: string; + + resetMasterPassword: boolean; + privateKey: string; + key: string; + twoFactorToken: string; + kdf: KdfType; + kdfIterations: number; + forcePasswordReset: boolean; + apiUseKeyConnector: boolean; + keyConnectorUrl: string; + + constructor(response: any) { + super(response); + this.accessToken = response.access_token; + this.expiresIn = response.expires_in; + this.refreshToken = response.refresh_token; + this.tokenType = response.token_type; + + this.resetMasterPassword = this.getResponseProperty("ResetMasterPassword"); + this.privateKey = this.getResponseProperty("PrivateKey"); + this.key = this.getResponseProperty("Key"); + this.twoFactorToken = this.getResponseProperty("TwoFactorToken"); + this.kdf = this.getResponseProperty("Kdf"); + this.kdfIterations = this.getResponseProperty("KdfIterations"); + this.forcePasswordReset = this.getResponseProperty("ForcePasswordReset"); + this.apiUseKeyConnector = this.getResponseProperty("ApiUseKeyConnector"); + this.keyConnectorUrl = this.getResponseProperty("KeyConnectorUrl"); + } +} diff --git a/libs/common/src/models/response/identityTwoFactorResponse.ts b/libs/common/src/models/response/identityTwoFactorResponse.ts new file mode 100644 index 0000000000..dc7dfde725 --- /dev/null +++ b/libs/common/src/models/response/identityTwoFactorResponse.ts @@ -0,0 +1,24 @@ +import { TwoFactorProviderType } from "../../enums/twoFactorProviderType"; + +import { BaseResponse } from "./baseResponse"; + +export class IdentityTwoFactorResponse extends BaseResponse { + twoFactorProviders: TwoFactorProviderType[]; + twoFactorProviders2 = new Map(); + captchaToken: string; + + constructor(response: any) { + super(response); + this.captchaToken = this.getResponseProperty("CaptchaBypassToken"); + this.twoFactorProviders = this.getResponseProperty("TwoFactorProviders"); + const twoFactorProviders2 = this.getResponseProperty("TwoFactorProviders2"); + if (twoFactorProviders2 != null) { + for (const prop in twoFactorProviders2) { + // eslint-disable-next-line + if (twoFactorProviders2.hasOwnProperty(prop)) { + this.twoFactorProviders2.set(parseInt(prop, null), twoFactorProviders2[prop]); + } + } + } + } +} diff --git a/libs/common/src/models/response/keyConnectorUserKeyResponse.ts b/libs/common/src/models/response/keyConnectorUserKeyResponse.ts new file mode 100644 index 0000000000..5183397b5f --- /dev/null +++ b/libs/common/src/models/response/keyConnectorUserKeyResponse.ts @@ -0,0 +1,10 @@ +import { BaseResponse } from "./baseResponse"; + +export class KeyConnectorUserKeyResponse extends BaseResponse { + key: string; + + constructor(response: any) { + super(response); + this.key = this.getResponseProperty("Key"); + } +} diff --git a/libs/common/src/models/response/keysResponse.ts b/libs/common/src/models/response/keysResponse.ts new file mode 100644 index 0000000000..e1e8e5dbe5 --- /dev/null +++ b/libs/common/src/models/response/keysResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class KeysResponse extends BaseResponse { + privateKey: string; + publicKey: string; + + constructor(response: any) { + super(response); + this.privateKey = this.getResponseProperty("PrivateKey"); + this.publicKey = this.getResponseProperty("PublicKey"); + } +} diff --git a/libs/common/src/models/response/listResponse.ts b/libs/common/src/models/response/listResponse.ts new file mode 100644 index 0000000000..e37c6697d4 --- /dev/null +++ b/libs/common/src/models/response/listResponse.ts @@ -0,0 +1,13 @@ +import { BaseResponse } from "./baseResponse"; + +export class ListResponse extends BaseResponse { + data: T[]; + continuationToken: string; + + constructor(response: any, t: new (dataResponse: any) => T) { + super(response); + const data = this.getResponseProperty("Data"); + this.data = data == null ? [] : data.map((dr: any) => new t(dr)); + this.continuationToken = this.getResponseProperty("ContinuationToken"); + } +} diff --git a/libs/common/src/models/response/notificationResponse.ts b/libs/common/src/models/response/notificationResponse.ts new file mode 100644 index 0000000000..f23de8fe8b --- /dev/null +++ b/libs/common/src/models/response/notificationResponse.ts @@ -0,0 +1,98 @@ +import { NotificationType } from "../../enums/notificationType"; + +import { BaseResponse } from "./baseResponse"; + +export class NotificationResponse extends BaseResponse { + contextId: string; + type: NotificationType; + payload: any; + + constructor(response: any) { + super(response); + this.contextId = this.getResponseProperty("ContextId"); + this.type = this.getResponseProperty("Type"); + + const payload = this.getResponseProperty("Payload"); + switch (this.type) { + case NotificationType.SyncCipherCreate: + case NotificationType.SyncCipherDelete: + case NotificationType.SyncCipherUpdate: + case NotificationType.SyncLoginDelete: + this.payload = new SyncCipherNotification(payload); + break; + case NotificationType.SyncFolderCreate: + case NotificationType.SyncFolderDelete: + case NotificationType.SyncFolderUpdate: + this.payload = new SyncFolderNotification(payload); + break; + case NotificationType.SyncVault: + case NotificationType.SyncCiphers: + case NotificationType.SyncOrgKeys: + case NotificationType.SyncSettings: + case NotificationType.LogOut: + this.payload = new UserNotification(payload); + break; + case NotificationType.SyncSendCreate: + case NotificationType.SyncSendUpdate: + case NotificationType.SyncSendDelete: + this.payload = new SyncSendNotification(payload); + break; + default: + break; + } + } +} + +export class SyncCipherNotification extends BaseResponse { + id: string; + userId: string; + organizationId: string; + collectionIds: string[]; + revisionDate: Date; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.userId = this.getResponseProperty("UserId"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.collectionIds = this.getResponseProperty("CollectionIds"); + this.revisionDate = new Date(this.getResponseProperty("RevisionDate")); + } +} + +export class SyncFolderNotification extends BaseResponse { + id: string; + userId: string; + revisionDate: Date; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.userId = this.getResponseProperty("UserId"); + this.revisionDate = new Date(this.getResponseProperty("RevisionDate")); + } +} + +export class UserNotification extends BaseResponse { + userId: string; + date: Date; + + constructor(response: any) { + super(response); + this.userId = this.getResponseProperty("UserId"); + this.date = new Date(this.getResponseProperty("Date")); + } +} + +export class SyncSendNotification extends BaseResponse { + id: string; + userId: string; + revisionDate: Date; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.userId = this.getResponseProperty("UserId"); + this.revisionDate = new Date(this.getResponseProperty("RevisionDate")); + } +} diff --git a/libs/common/src/models/response/organization/organizationSsoResponse.ts b/libs/common/src/models/response/organization/organizationSsoResponse.ts new file mode 100644 index 0000000000..abe6b72063 --- /dev/null +++ b/libs/common/src/models/response/organization/organizationSsoResponse.ts @@ -0,0 +1,35 @@ +import { SsoConfigApi } from "../../api/ssoConfigApi"; +import { BaseResponse } from "../baseResponse"; + +export class OrganizationSsoResponse extends BaseResponse { + enabled: boolean; + data: SsoConfigApi; + urls: SsoUrls; + + constructor(response: any) { + super(response); + this.enabled = this.getResponseProperty("Enabled"); + this.data = + this.getResponseProperty("Data") != null + ? new SsoConfigApi(this.getResponseProperty("Data")) + : null; + this.urls = new SsoUrls(this.getResponseProperty("Urls")); + } +} + +class SsoUrls extends BaseResponse { + callbackPath: string; + signedOutCallbackPath: string; + spEntityId: string; + spMetadataUrl: string; + spAcsUrl: string; + + constructor(response: any) { + super(response); + this.callbackPath = this.getResponseProperty("CallbackPath"); + this.signedOutCallbackPath = this.getResponseProperty("SignedOutCallbackPath"); + this.spEntityId = this.getResponseProperty("SpEntityId"); + this.spMetadataUrl = this.getResponseProperty("SpMetadataUrl"); + this.spAcsUrl = this.getResponseProperty("SpAcsUrl"); + } +} diff --git a/libs/common/src/models/response/organizationApiKeyInformationResponse.ts b/libs/common/src/models/response/organizationApiKeyInformationResponse.ts new file mode 100644 index 0000000000..16ed725128 --- /dev/null +++ b/libs/common/src/models/response/organizationApiKeyInformationResponse.ts @@ -0,0 +1,12 @@ +import { OrganizationApiKeyType } from "../../enums/organizationApiKeyType"; + +import { BaseResponse } from "./baseResponse"; + +export class OrganizationApiKeyInformationResponse extends BaseResponse { + keyType: OrganizationApiKeyType; + + constructor(response: any) { + super(response); + this.keyType = this.getResponseProperty("KeyType"); + } +} diff --git a/libs/common/src/models/response/organizationAutoEnrollStatusResponse.ts b/libs/common/src/models/response/organizationAutoEnrollStatusResponse.ts new file mode 100644 index 0000000000..d960463e2f --- /dev/null +++ b/libs/common/src/models/response/organizationAutoEnrollStatusResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class OrganizationAutoEnrollStatusResponse extends BaseResponse { + id: string; + resetPasswordEnabled: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.resetPasswordEnabled = this.getResponseProperty("ResetPasswordEnabled"); + } +} diff --git a/libs/common/src/models/response/organizationConnectionResponse.ts b/libs/common/src/models/response/organizationConnectionResponse.ts new file mode 100644 index 0000000000..954afaed3a --- /dev/null +++ b/libs/common/src/models/response/organizationConnectionResponse.ts @@ -0,0 +1,28 @@ +import { OrganizationConnectionType } from "jslib-common/enums/organizationConnectionType"; + +import { BillingSyncConfigApi } from "../api/billingSyncConfigApi"; + +import { BaseResponse } from "./baseResponse"; + +/**API response config types for OrganizationConnectionResponse */ +export type OrganizationConnectionConfigApis = BillingSyncConfigApi; + +export class OrganizationConnectionResponse< + TConfig extends OrganizationConnectionConfigApis +> extends BaseResponse { + id: string; + type: OrganizationConnectionType; + organizationId: string; + enabled: boolean; + config: TConfig; + + constructor(response: any, configType: { new (response: any): TConfig }) { + super(response); + this.id = this.getResponseProperty("Id"); + this.type = this.getResponseProperty("Type"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.enabled = this.getResponseProperty("Enabled"); + const rawConfig = this.getResponseProperty("Config"); + this.config = rawConfig == null ? null : new configType(rawConfig); + } +} diff --git a/libs/common/src/models/response/organizationKeysResponse.ts b/libs/common/src/models/response/organizationKeysResponse.ts new file mode 100644 index 0000000000..3d5c0d2986 --- /dev/null +++ b/libs/common/src/models/response/organizationKeysResponse.ts @@ -0,0 +1,7 @@ +import { KeysResponse } from "./keysResponse"; + +export class OrganizationKeysResponse extends KeysResponse { + constructor(response: any) { + super(response); + } +} diff --git a/libs/common/src/models/response/organizationResponse.ts b/libs/common/src/models/response/organizationResponse.ts new file mode 100644 index 0000000000..addb2a2839 --- /dev/null +++ b/libs/common/src/models/response/organizationResponse.ts @@ -0,0 +1,60 @@ +import { PlanType } from "../../enums/planType"; + +import { BaseResponse } from "./baseResponse"; +import { PlanResponse } from "./planResponse"; + +export class OrganizationResponse extends BaseResponse { + id: string; + identifier: string; + name: string; + businessName: string; + businessAddress1: string; + businessAddress2: string; + businessAddress3: string; + businessCountry: string; + businessTaxNumber: string; + billingEmail: string; + plan: PlanResponse; + planType: PlanType; + seats: number; + maxAutoscaleSeats: number; + maxCollections: number; + maxStorageGb: number; + useGroups: boolean; + useDirectory: boolean; + useEvents: boolean; + useTotp: boolean; + use2fa: boolean; + useApi: boolean; + useResetPassword: boolean; + hasPublicAndPrivateKeys: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.identifier = this.getResponseProperty("Identifier"); + this.name = this.getResponseProperty("Name"); + this.businessName = this.getResponseProperty("BusinessName"); + this.businessAddress1 = this.getResponseProperty("BusinessAddress1"); + this.businessAddress2 = this.getResponseProperty("BusinessAddress2"); + this.businessAddress3 = this.getResponseProperty("BusinessAddress3"); + this.businessCountry = this.getResponseProperty("BusinessCountry"); + this.businessTaxNumber = this.getResponseProperty("BusinessTaxNumber"); + this.billingEmail = this.getResponseProperty("BillingEmail"); + const plan = this.getResponseProperty("Plan"); + this.plan = plan == null ? null : new PlanResponse(plan); + this.planType = this.getResponseProperty("PlanType"); + this.seats = this.getResponseProperty("Seats"); + this.maxAutoscaleSeats = this.getResponseProperty("MaxAutoscaleSeats"); + this.maxCollections = this.getResponseProperty("MaxCollections"); + this.maxStorageGb = this.getResponseProperty("MaxStorageGb"); + this.useGroups = this.getResponseProperty("UseGroups"); + this.useDirectory = this.getResponseProperty("UseDirectory"); + this.useEvents = this.getResponseProperty("UseEvents"); + this.useTotp = this.getResponseProperty("UseTotp"); + this.use2fa = this.getResponseProperty("Use2fa"); + this.useApi = this.getResponseProperty("UseApi"); + this.useResetPassword = this.getResponseProperty("UseResetPassword"); + this.hasPublicAndPrivateKeys = this.getResponseProperty("HasPublicAndPrivateKeys"); + } +} diff --git a/libs/common/src/models/response/organizationSponsorshipSyncStatusResponse.ts b/libs/common/src/models/response/organizationSponsorshipSyncStatusResponse.ts new file mode 100644 index 0000000000..b0af451b36 --- /dev/null +++ b/libs/common/src/models/response/organizationSponsorshipSyncStatusResponse.ts @@ -0,0 +1,13 @@ +import { BaseResponse } from "./baseResponse"; + +export class OrganizationSponsorshipSyncStatusResponse extends BaseResponse { + lastSyncDate?: Date; + + constructor(response: any) { + super(response); + const lastSyncDate = this.getResponseProperty("LastSyncDate"); + if (lastSyncDate) { + this.lastSyncDate = new Date(lastSyncDate); + } + } +} diff --git a/libs/common/src/models/response/organizationSubscriptionResponse.ts b/libs/common/src/models/response/organizationSubscriptionResponse.ts new file mode 100644 index 0000000000..1985dc6eec --- /dev/null +++ b/libs/common/src/models/response/organizationSubscriptionResponse.ts @@ -0,0 +1,27 @@ +import { OrganizationResponse } from "./organizationResponse"; +import { + BillingSubscriptionResponse, + BillingSubscriptionUpcomingInvoiceResponse, +} from "./subscriptionResponse"; + +export class OrganizationSubscriptionResponse extends OrganizationResponse { + storageName: string; + storageGb: number; + subscription: BillingSubscriptionResponse; + upcomingInvoice: BillingSubscriptionUpcomingInvoiceResponse; + expiration: string; + + constructor(response: any) { + super(response); + this.storageName = this.getResponseProperty("StorageName"); + this.storageGb = this.getResponseProperty("StorageGb"); + const subscription = this.getResponseProperty("Subscription"); + this.subscription = subscription == null ? null : new BillingSubscriptionResponse(subscription); + const upcomingInvoice = this.getResponseProperty("UpcomingInvoice"); + this.upcomingInvoice = + upcomingInvoice == null + ? null + : new BillingSubscriptionUpcomingInvoiceResponse(upcomingInvoice); + this.expiration = this.getResponseProperty("Expiration"); + } +} diff --git a/libs/common/src/models/response/organizationUserBulkPublicKeyResponse.ts b/libs/common/src/models/response/organizationUserBulkPublicKeyResponse.ts new file mode 100644 index 0000000000..1b77e0367c --- /dev/null +++ b/libs/common/src/models/response/organizationUserBulkPublicKeyResponse.ts @@ -0,0 +1,14 @@ +import { BaseResponse } from "./baseResponse"; + +export class OrganizationUserBulkPublicKeyResponse extends BaseResponse { + id: string; + userId: string; + key: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.userId = this.getResponseProperty("UserId"); + this.key = this.getResponseProperty("Key"); + } +} diff --git a/libs/common/src/models/response/organizationUserBulkResponse.ts b/libs/common/src/models/response/organizationUserBulkResponse.ts new file mode 100644 index 0000000000..15c6f371a4 --- /dev/null +++ b/libs/common/src/models/response/organizationUserBulkResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class OrganizationUserBulkResponse extends BaseResponse { + id: string; + error: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.error = this.getResponseProperty("Error"); + } +} diff --git a/libs/common/src/models/response/organizationUserResponse.ts b/libs/common/src/models/response/organizationUserResponse.ts new file mode 100644 index 0000000000..3e49375b90 --- /dev/null +++ b/libs/common/src/models/response/organizationUserResponse.ts @@ -0,0 +1,70 @@ +import { KdfType } from "../../enums/kdfType"; +import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType"; +import { OrganizationUserType } from "../../enums/organizationUserType"; +import { PermissionsApi } from "../api/permissionsApi"; + +import { BaseResponse } from "./baseResponse"; +import { SelectionReadOnlyResponse } from "./selectionReadOnlyResponse"; + +export class OrganizationUserResponse extends BaseResponse { + id: string; + userId: string; + type: OrganizationUserType; + status: OrganizationUserStatusType; + accessAll: boolean; + permissions: PermissionsApi; + resetPasswordEnrolled: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.userId = this.getResponseProperty("UserId"); + this.type = this.getResponseProperty("Type"); + this.status = this.getResponseProperty("Status"); + this.permissions = new PermissionsApi(this.getResponseProperty("Permissions")); + this.accessAll = this.getResponseProperty("AccessAll"); + this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled"); + } +} + +export class OrganizationUserUserDetailsResponse extends OrganizationUserResponse { + name: string; + email: string; + twoFactorEnabled: boolean; + usesKeyConnector: boolean; + + constructor(response: any) { + super(response); + this.name = this.getResponseProperty("Name"); + this.email = this.getResponseProperty("Email"); + this.twoFactorEnabled = this.getResponseProperty("TwoFactorEnabled"); + this.usesKeyConnector = this.getResponseProperty("UsesKeyConnector") ?? false; + } +} + +export class OrganizationUserDetailsResponse extends OrganizationUserResponse { + collections: SelectionReadOnlyResponse[] = []; + + constructor(response: any) { + super(response); + const collections = this.getResponseProperty("Collections"); + if (collections != null) { + this.collections = collections.map((c: any) => new SelectionReadOnlyResponse(c)); + } + } +} + +export class OrganizationUserResetPasswordDetailsReponse extends BaseResponse { + kdf: KdfType; + kdfIterations: number; + resetPasswordKey: string; + encryptedPrivateKey: string; + + constructor(response: any) { + super(response); + this.kdf = this.getResponseProperty("Kdf"); + this.kdfIterations = this.getResponseProperty("KdfIterations"); + this.resetPasswordKey = this.getResponseProperty("ResetPasswordKey"); + this.encryptedPrivateKey = this.getResponseProperty("EncryptedPrivateKey"); + } +} diff --git a/libs/common/src/models/response/passwordHistoryResponse.ts b/libs/common/src/models/response/passwordHistoryResponse.ts new file mode 100644 index 0000000000..f3a8a13324 --- /dev/null +++ b/libs/common/src/models/response/passwordHistoryResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class PasswordHistoryResponse extends BaseResponse { + password: string; + lastUsedDate: string; + + constructor(response: any) { + super(response); + this.password = this.getResponseProperty("Password"); + this.lastUsedDate = this.getResponseProperty("LastUsedDate"); + } +} diff --git a/libs/common/src/models/response/paymentResponse.ts b/libs/common/src/models/response/paymentResponse.ts new file mode 100644 index 0000000000..ec4977cd52 --- /dev/null +++ b/libs/common/src/models/response/paymentResponse.ts @@ -0,0 +1,18 @@ +import { BaseResponse } from "./baseResponse"; +import { ProfileResponse } from "./profileResponse"; + +export class PaymentResponse extends BaseResponse { + userProfile: ProfileResponse; + paymentIntentClientSecret: string; + success: boolean; + + constructor(response: any) { + super(response); + const userProfile = this.getResponseProperty("UserProfile"); + if (userProfile != null) { + this.userProfile = new ProfileResponse(userProfile); + } + this.paymentIntentClientSecret = this.getResponseProperty("PaymentIntentClientSecret"); + this.success = this.getResponseProperty("Success"); + } +} diff --git a/libs/common/src/models/response/planResponse.ts b/libs/common/src/models/response/planResponse.ts new file mode 100644 index 0000000000..04652542c9 --- /dev/null +++ b/libs/common/src/models/response/planResponse.ts @@ -0,0 +1,95 @@ +import { PlanType } from "../../enums/planType"; +import { ProductType } from "../../enums/productType"; + +import { BaseResponse } from "./baseResponse"; + +export class PlanResponse extends BaseResponse { + type: PlanType; + product: ProductType; + name: string; + isAnnual: boolean; + nameLocalizationKey: string; + descriptionLocalizationKey: string; + canBeUsedByBusiness: boolean; + baseSeats: number; + baseStorageGb: number; + maxCollections: number; + maxUsers: number; + + hasAdditionalSeatsOption: boolean; + maxAdditionalSeats: number; + hasAdditionalStorageOption: boolean; + maxAdditionalStorage: number; + hasPremiumAccessOption: boolean; + trialPeriodDays: number; + + hasSelfHost: boolean; + hasPolicies: boolean; + hasGroups: boolean; + hasDirectory: boolean; + hasEvents: boolean; + hasTotp: boolean; + has2fa: boolean; + hasApi: boolean; + hasSso: boolean; + hasResetPassword: boolean; + usersGetPremium: boolean; + + upgradeSortOrder: number; + displaySortOrder: number; + legacyYear: number; + disabled: boolean; + + stripePlanId: string; + stripeSeatPlanId: string; + stripeStoragePlanId: string; + stripePremiumAccessPlanId: string; + basePrice: number; + seatPrice: number; + additionalStoragePricePerGb: number; + premiumAccessOptionPrice: number; + + constructor(response: any) { + super(response); + this.type = this.getResponseProperty("Type"); + this.product = this.getResponseProperty("Product"); + this.name = this.getResponseProperty("Name"); + this.isAnnual = this.getResponseProperty("IsAnnual"); + this.nameLocalizationKey = this.getResponseProperty("NameLocalizationKey"); + this.descriptionLocalizationKey = this.getResponseProperty("DescriptionLocalizationKey"); + this.canBeUsedByBusiness = this.getResponseProperty("CanBeUsedByBusiness"); + this.baseSeats = this.getResponseProperty("BaseSeats"); + this.baseStorageGb = this.getResponseProperty("BaseStorageGb"); + this.maxCollections = this.getResponseProperty("MaxCollections"); + this.maxUsers = this.getResponseProperty("MaxUsers"); + this.hasAdditionalSeatsOption = this.getResponseProperty("HasAdditionalSeatsOption"); + this.maxAdditionalSeats = this.getResponseProperty("MaxAdditionalSeats"); + this.hasAdditionalStorageOption = this.getResponseProperty("HasAdditionalStorageOption"); + this.maxAdditionalStorage = this.getResponseProperty("MaxAdditionalStorage"); + this.hasPremiumAccessOption = this.getResponseProperty("HasPremiumAccessOption"); + this.trialPeriodDays = this.getResponseProperty("TrialPeriodDays"); + this.hasSelfHost = this.getResponseProperty("HasSelfHost"); + this.hasPolicies = this.getResponseProperty("HasPolicies"); + this.hasGroups = this.getResponseProperty("HasGroups"); + this.hasDirectory = this.getResponseProperty("HasDirectory"); + this.hasEvents = this.getResponseProperty("HasEvents"); + this.hasTotp = this.getResponseProperty("HasTotp"); + this.has2fa = this.getResponseProperty("Has2fa"); + this.hasApi = this.getResponseProperty("HasApi"); + this.hasSso = this.getResponseProperty("HasSso"); + this.hasResetPassword = this.getResponseProperty("HasResetPassword"); + this.usersGetPremium = this.getResponseProperty("UsersGetPremium"); + this.upgradeSortOrder = this.getResponseProperty("UpgradeSortOrder"); + this.displaySortOrder = this.getResponseProperty("SortOrder"); + this.legacyYear = this.getResponseProperty("LegacyYear"); + this.disabled = this.getResponseProperty("Disabled"); + this.stripePlanId = this.getResponseProperty("StripePlanId"); + this.stripeSeatPlanId = this.getResponseProperty("StripeSeatPlanId"); + this.stripeStoragePlanId = this.getResponseProperty("StripeStoragePlanId"); + this.stripePremiumAccessPlanId = this.getResponseProperty("StripePremiumAccessPlanId"); + this.basePrice = this.getResponseProperty("BasePrice"); + this.seatPrice = this.getResponseProperty("SeatPrice"); + this.additionalStoragePricePerGb = this.getResponseProperty("AdditionalStoragePricePerGb"); + this.premiumAccessOptionPrice = this.getResponseProperty("PremiumAccessOptionPrice"); + } +} diff --git a/libs/common/src/models/response/policyResponse.ts b/libs/common/src/models/response/policyResponse.ts new file mode 100644 index 0000000000..d38375efad --- /dev/null +++ b/libs/common/src/models/response/policyResponse.ts @@ -0,0 +1,20 @@ +import { PolicyType } from "../../enums/policyType"; + +import { BaseResponse } from "./baseResponse"; + +export class PolicyResponse extends BaseResponse { + id: string; + organizationId: string; + type: PolicyType; + data: any; + enabled: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.type = this.getResponseProperty("Type"); + this.data = this.getResponseProperty("Data"); + this.enabled = this.getResponseProperty("Enabled"); + } +} diff --git a/libs/common/src/models/response/preloginResponse.ts b/libs/common/src/models/response/preloginResponse.ts new file mode 100644 index 0000000000..7756f8ed3a --- /dev/null +++ b/libs/common/src/models/response/preloginResponse.ts @@ -0,0 +1,14 @@ +import { KdfType } from "../../enums/kdfType"; + +import { BaseResponse } from "./baseResponse"; + +export class PreloginResponse extends BaseResponse { + kdf: KdfType; + kdfIterations: number; + + constructor(response: any) { + super(response); + this.kdf = this.getResponseProperty("Kdf"); + this.kdfIterations = this.getResponseProperty("KdfIterations"); + } +} diff --git a/libs/common/src/models/response/profileOrganizationResponse.ts b/libs/common/src/models/response/profileOrganizationResponse.ts new file mode 100644 index 0000000000..39b7644caa --- /dev/null +++ b/libs/common/src/models/response/profileOrganizationResponse.ts @@ -0,0 +1,97 @@ +import { OrganizationUserStatusType } from "../../enums/organizationUserStatusType"; +import { OrganizationUserType } from "../../enums/organizationUserType"; +import { ProductType } from "../../enums/productType"; +import { PermissionsApi } from "../api/permissionsApi"; + +import { BaseResponse } from "./baseResponse"; + +export class ProfileOrganizationResponse extends BaseResponse { + id: string; + name: string; + usePolicies: boolean; + useGroups: boolean; + useDirectory: boolean; + useEvents: boolean; + useTotp: boolean; + use2fa: boolean; + useApi: boolean; + useSso: boolean; + useKeyConnector: boolean; + useResetPassword: boolean; + selfHost: boolean; + usersGetPremium: boolean; + seats: number; + maxCollections: number; + maxStorageGb?: number; + key: string; + hasPublicAndPrivateKeys: boolean; + status: OrganizationUserStatusType; + type: OrganizationUserType; + enabled: boolean; + ssoBound: boolean; + identifier: string; + permissions: PermissionsApi; + resetPasswordEnrolled: boolean; + userId: string; + providerId: string; + providerName: string; + familySponsorshipFriendlyName: string; + familySponsorshipAvailable: boolean; + planProductType: ProductType; + keyConnectorEnabled: boolean; + keyConnectorUrl: string; + familySponsorshipLastSyncDate?: Date; + familySponsorshipValidUntil?: Date; + familySponsorshipToDelete?: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.name = this.getResponseProperty("Name"); + this.usePolicies = this.getResponseProperty("UsePolicies"); + this.useGroups = this.getResponseProperty("UseGroups"); + this.useDirectory = this.getResponseProperty("UseDirectory"); + this.useEvents = this.getResponseProperty("UseEvents"); + this.useTotp = this.getResponseProperty("UseTotp"); + this.use2fa = this.getResponseProperty("Use2fa"); + this.useApi = this.getResponseProperty("UseApi"); + this.useSso = this.getResponseProperty("UseSso"); + this.useKeyConnector = this.getResponseProperty("UseKeyConnector") ?? false; + this.useResetPassword = this.getResponseProperty("UseResetPassword"); + this.selfHost = this.getResponseProperty("SelfHost"); + this.usersGetPremium = this.getResponseProperty("UsersGetPremium"); + this.seats = this.getResponseProperty("Seats"); + this.maxCollections = this.getResponseProperty("MaxCollections"); + this.maxStorageGb = this.getResponseProperty("MaxStorageGb"); + this.key = this.getResponseProperty("Key"); + this.hasPublicAndPrivateKeys = this.getResponseProperty("HasPublicAndPrivateKeys"); + this.status = this.getResponseProperty("Status"); + this.type = this.getResponseProperty("Type"); + this.enabled = this.getResponseProperty("Enabled"); + this.ssoBound = this.getResponseProperty("SsoBound"); + this.identifier = this.getResponseProperty("Identifier"); + this.permissions = new PermissionsApi(this.getResponseProperty("permissions")); + this.resetPasswordEnrolled = this.getResponseProperty("ResetPasswordEnrolled"); + this.userId = this.getResponseProperty("UserId"); + this.providerId = this.getResponseProperty("ProviderId"); + this.providerName = this.getResponseProperty("ProviderName"); + this.familySponsorshipFriendlyName = this.getResponseProperty("FamilySponsorshipFriendlyName"); + this.familySponsorshipAvailable = this.getResponseProperty("FamilySponsorshipAvailable"); + this.planProductType = this.getResponseProperty("PlanProductType"); + this.keyConnectorEnabled = this.getResponseProperty("KeyConnectorEnabled") ?? false; + this.keyConnectorUrl = this.getResponseProperty("KeyConnectorUrl"); + const familySponsorshipLastSyncDateString = this.getResponseProperty( + "FamilySponsorshipLastSyncDate" + ); + if (familySponsorshipLastSyncDateString) { + this.familySponsorshipLastSyncDate = new Date(familySponsorshipLastSyncDateString); + } + const familySponsorshipValidUntilString = this.getResponseProperty( + "FamilySponsorshipValidUntil" + ); + if (familySponsorshipValidUntilString) { + this.familySponsorshipValidUntil = new Date(familySponsorshipValidUntilString); + } + this.familySponsorshipToDelete = this.getResponseProperty("FamilySponsorshipToDelete"); + } +} diff --git a/libs/common/src/models/response/profileProviderOrganizationResponse.ts b/libs/common/src/models/response/profileProviderOrganizationResponse.ts new file mode 100644 index 0000000000..74b74c0033 --- /dev/null +++ b/libs/common/src/models/response/profileProviderOrganizationResponse.ts @@ -0,0 +1,8 @@ +import { ProfileOrganizationResponse } from "./profileOrganizationResponse"; + +export class ProfileProviderOrganizationResponse extends ProfileOrganizationResponse { + constructor(response: any) { + super(response); + this.keyConnectorEnabled = false; + } +} diff --git a/libs/common/src/models/response/profileProviderResponse.ts b/libs/common/src/models/response/profileProviderResponse.ts new file mode 100644 index 0000000000..84e8bbf67c --- /dev/null +++ b/libs/common/src/models/response/profileProviderResponse.ts @@ -0,0 +1,30 @@ +import { ProviderUserStatusType } from "../../enums/providerUserStatusType"; +import { ProviderUserType } from "../../enums/providerUserType"; +import { PermissionsApi } from "../api/permissionsApi"; + +import { BaseResponse } from "./baseResponse"; + +export class ProfileProviderResponse extends BaseResponse { + id: string; + name: string; + key: string; + status: ProviderUserStatusType; + type: ProviderUserType; + enabled: boolean; + permissions: PermissionsApi; + userId: string; + useEvents: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.name = this.getResponseProperty("Name"); + this.key = this.getResponseProperty("Key"); + this.status = this.getResponseProperty("Status"); + this.type = this.getResponseProperty("Type"); + this.enabled = this.getResponseProperty("Enabled"); + this.permissions = new PermissionsApi(this.getResponseProperty("permissions")); + this.userId = this.getResponseProperty("UserId"); + this.useEvents = this.getResponseProperty("UseEvents"); + } +} diff --git a/libs/common/src/models/response/profileResponse.ts b/libs/common/src/models/response/profileResponse.ts new file mode 100644 index 0000000000..2c3e66fb20 --- /dev/null +++ b/libs/common/src/models/response/profileResponse.ts @@ -0,0 +1,55 @@ +import { BaseResponse } from "./baseResponse"; +import { ProfileOrganizationResponse } from "./profileOrganizationResponse"; +import { ProfileProviderOrganizationResponse } from "./profileProviderOrganizationResponse"; +import { ProfileProviderResponse } from "./profileProviderResponse"; + +export class ProfileResponse extends BaseResponse { + id: string; + name: string; + email: string; + emailVerified: boolean; + masterPasswordHint: string; + premium: boolean; + culture: string; + twoFactorEnabled: boolean; + key: string; + privateKey: string; + securityStamp: string; + forcePasswordReset: boolean; + usesKeyConnector: boolean; + organizations: ProfileOrganizationResponse[] = []; + providers: ProfileProviderResponse[] = []; + providerOrganizations: ProfileProviderOrganizationResponse[] = []; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.name = this.getResponseProperty("Name"); + this.email = this.getResponseProperty("Email"); + this.emailVerified = this.getResponseProperty("EmailVerified"); + this.masterPasswordHint = this.getResponseProperty("MasterPasswordHint"); + this.premium = this.getResponseProperty("Premium"); + this.culture = this.getResponseProperty("Culture"); + this.twoFactorEnabled = this.getResponseProperty("TwoFactorEnabled"); + this.key = this.getResponseProperty("Key"); + this.privateKey = this.getResponseProperty("PrivateKey"); + this.securityStamp = this.getResponseProperty("SecurityStamp"); + this.forcePasswordReset = this.getResponseProperty("ForcePasswordReset") ?? false; + this.usesKeyConnector = this.getResponseProperty("UsesKeyConnector") ?? false; + + const organizations = this.getResponseProperty("Organizations"); + if (organizations != null) { + this.organizations = organizations.map((o: any) => new ProfileOrganizationResponse(o)); + } + const providers = this.getResponseProperty("Providers"); + if (providers != null) { + this.providers = providers.map((o: any) => new ProfileProviderResponse(o)); + } + const providerOrganizations = this.getResponseProperty("ProviderOrganizations"); + if (providerOrganizations != null) { + this.providerOrganizations = providerOrganizations.map( + (o: any) => new ProfileProviderOrganizationResponse(o) + ); + } + } +} diff --git a/libs/common/src/models/response/provider/providerOrganizationResponse.ts b/libs/common/src/models/response/provider/providerOrganizationResponse.ts new file mode 100644 index 0000000000..d733362a24 --- /dev/null +++ b/libs/common/src/models/response/provider/providerOrganizationResponse.ts @@ -0,0 +1,31 @@ +import { BaseResponse } from "../baseResponse"; + +export class ProviderOrganizationResponse extends BaseResponse { + id: string; + providerId: string; + organizationId: string; + key: string; + settings: string; + creationDate: string; + revisionDate: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.providerId = this.getResponseProperty("ProviderId"); + this.organizationId = this.getResponseProperty("OrganizationId"); + this.key = this.getResponseProperty("Key"); + this.settings = this.getResponseProperty("Settings"); + this.creationDate = this.getResponseProperty("CreationDate"); + this.revisionDate = this.getResponseProperty("RevisionDate"); + } +} + +export class ProviderOrganizationOrganizationDetailsResponse extends ProviderOrganizationResponse { + organizationName: string; + + constructor(response: any) { + super(response); + this.organizationName = this.getResponseProperty("OrganizationName"); + } +} diff --git a/libs/common/src/models/response/provider/providerResponse.ts b/libs/common/src/models/response/provider/providerResponse.ts new file mode 100644 index 0000000000..2b8729fa9c --- /dev/null +++ b/libs/common/src/models/response/provider/providerResponse.ts @@ -0,0 +1,16 @@ +import { BaseResponse } from "../baseResponse"; + +export class ProviderResponse extends BaseResponse { + id: string; + name: string; + businessName: string; + billingEmail: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.name = this.getResponseProperty("Name"); + this.businessName = this.getResponseProperty("BusinessName"); + this.billingEmail = this.getResponseProperty("BillingEmail"); + } +} diff --git a/libs/common/src/models/response/provider/providerUserBulkPublicKeyResponse.ts b/libs/common/src/models/response/provider/providerUserBulkPublicKeyResponse.ts new file mode 100644 index 0000000000..ad078f9821 --- /dev/null +++ b/libs/common/src/models/response/provider/providerUserBulkPublicKeyResponse.ts @@ -0,0 +1,3 @@ +import { OrganizationUserBulkPublicKeyResponse } from "../organizationUserBulkPublicKeyResponse"; + +export class ProviderUserBulkPublicKeyResponse extends OrganizationUserBulkPublicKeyResponse {} diff --git a/libs/common/src/models/response/provider/providerUserBulkResponse.ts b/libs/common/src/models/response/provider/providerUserBulkResponse.ts new file mode 100644 index 0000000000..6cf12f96c4 --- /dev/null +++ b/libs/common/src/models/response/provider/providerUserBulkResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "../baseResponse"; + +export class ProviderUserBulkResponse extends BaseResponse { + id: string; + error: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.error = this.getResponseProperty("Error"); + } +} diff --git a/libs/common/src/models/response/provider/providerUserResponse.ts b/libs/common/src/models/response/provider/providerUserResponse.ts new file mode 100644 index 0000000000..cf1a181c00 --- /dev/null +++ b/libs/common/src/models/response/provider/providerUserResponse.ts @@ -0,0 +1,32 @@ +import { ProviderUserStatusType } from "../../../enums/providerUserStatusType"; +import { ProviderUserType } from "../../../enums/providerUserType"; +import { PermissionsApi } from "../../api/permissionsApi"; +import { BaseResponse } from "../baseResponse"; + +export class ProviderUserResponse extends BaseResponse { + id: string; + userId: string; + type: ProviderUserType; + status: ProviderUserStatusType; + permissions: PermissionsApi; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.userId = this.getResponseProperty("UserId"); + this.type = this.getResponseProperty("Type"); + this.status = this.getResponseProperty("Status"); + this.permissions = new PermissionsApi(this.getResponseProperty("Permissions")); + } +} + +export class ProviderUserUserDetailsResponse extends ProviderUserResponse { + name: string; + email: string; + + constructor(response: any) { + super(response); + this.name = this.getResponseProperty("Name"); + this.email = this.getResponseProperty("Email"); + } +} diff --git a/libs/common/src/models/response/selectionReadOnlyResponse.ts b/libs/common/src/models/response/selectionReadOnlyResponse.ts new file mode 100644 index 0000000000..cee9361c50 --- /dev/null +++ b/libs/common/src/models/response/selectionReadOnlyResponse.ts @@ -0,0 +1,14 @@ +import { BaseResponse } from "./baseResponse"; + +export class SelectionReadOnlyResponse extends BaseResponse { + id: string; + readOnly: boolean; + hidePasswords: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.readOnly = this.getResponseProperty("ReadOnly"); + this.hidePasswords = this.getResponseProperty("HidePasswords"); + } +} diff --git a/libs/common/src/models/response/sendAccessResponse.ts b/libs/common/src/models/response/sendAccessResponse.ts new file mode 100644 index 0000000000..e98a9d057d --- /dev/null +++ b/libs/common/src/models/response/sendAccessResponse.ts @@ -0,0 +1,35 @@ +import { SendType } from "../../enums/sendType"; +import { SendFileApi } from "../api/sendFileApi"; +import { SendTextApi } from "../api/sendTextApi"; + +import { BaseResponse } from "./baseResponse"; + +export class SendAccessResponse extends BaseResponse { + id: string; + type: SendType; + name: string; + file: SendFileApi; + text: SendTextApi; + expirationDate: Date; + creatorIdentifier: string; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.type = this.getResponseProperty("Type"); + this.name = this.getResponseProperty("Name"); + + const text = this.getResponseProperty("Text"); + if (text != null) { + this.text = new SendTextApi(text); + } + + const file = this.getResponseProperty("File"); + if (file != null) { + this.file = new SendFileApi(file); + } + + this.expirationDate = this.getResponseProperty("ExpirationDate"); + this.creatorIdentifier = this.getResponseProperty("CreatorIdentifier"); + } +} diff --git a/libs/common/src/models/response/sendFileDownloadDataResponse.ts b/libs/common/src/models/response/sendFileDownloadDataResponse.ts new file mode 100644 index 0000000000..ca2575a24c --- /dev/null +++ b/libs/common/src/models/response/sendFileDownloadDataResponse.ts @@ -0,0 +1,11 @@ +import { BaseResponse } from "./baseResponse"; + +export class SendFileDownloadDataResponse extends BaseResponse { + id: string = null; + url: string = null; + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.url = this.getResponseProperty("Url"); + } +} diff --git a/libs/common/src/models/response/sendFileUploadDataResponse.ts b/libs/common/src/models/response/sendFileUploadDataResponse.ts new file mode 100644 index 0000000000..b787f2ccc7 --- /dev/null +++ b/libs/common/src/models/response/sendFileUploadDataResponse.ts @@ -0,0 +1,17 @@ +import { FileUploadType } from "../../enums/fileUploadType"; + +import { BaseResponse } from "./baseResponse"; +import { SendResponse } from "./sendResponse"; + +export class SendFileUploadDataResponse extends BaseResponse { + fileUploadType: FileUploadType; + sendResponse: SendResponse; + url: string = null; + constructor(response: any) { + super(response); + this.fileUploadType = this.getResponseProperty("FileUploadType"); + const sendResponse = this.getResponseProperty("SendResponse"); + this.sendResponse = sendResponse == null ? null : new SendResponse(sendResponse); + this.url = this.getResponseProperty("Url"); + } +} diff --git a/libs/common/src/models/response/sendResponse.ts b/libs/common/src/models/response/sendResponse.ts new file mode 100644 index 0000000000..287507250e --- /dev/null +++ b/libs/common/src/models/response/sendResponse.ts @@ -0,0 +1,52 @@ +import { SendType } from "../../enums/sendType"; +import { SendFileApi } from "../api/sendFileApi"; +import { SendTextApi } from "../api/sendTextApi"; + +import { BaseResponse } from "./baseResponse"; + +export class SendResponse extends BaseResponse { + id: string; + accessId: string; + type: SendType; + name: string; + notes: string; + file: SendFileApi; + text: SendTextApi; + key: string; + maxAccessCount?: number; + accessCount: number; + revisionDate: string; + expirationDate: string; + deletionDate: string; + password: string; + disable: boolean; + hideEmail: boolean; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.accessId = this.getResponseProperty("AccessId"); + this.type = this.getResponseProperty("Type"); + this.name = this.getResponseProperty("Name"); + this.notes = this.getResponseProperty("Notes"); + this.key = this.getResponseProperty("Key"); + this.maxAccessCount = this.getResponseProperty("MaxAccessCount"); + this.accessCount = this.getResponseProperty("AccessCount"); + this.revisionDate = this.getResponseProperty("RevisionDate"); + this.expirationDate = this.getResponseProperty("ExpirationDate"); + this.deletionDate = this.getResponseProperty("DeletionDate"); + this.password = this.getResponseProperty("Password"); + this.disable = this.getResponseProperty("Disabled") || false; + this.hideEmail = this.getResponseProperty("HideEmail") || false; + + const text = this.getResponseProperty("Text"); + if (text != null) { + this.text = new SendTextApi(text); + } + + const file = this.getResponseProperty("File"); + if (file != null) { + this.file = new SendFileApi(file); + } + } +} diff --git a/libs/common/src/models/response/ssoPreValidateResponse.ts b/libs/common/src/models/response/ssoPreValidateResponse.ts new file mode 100644 index 0000000000..1b403e522c --- /dev/null +++ b/libs/common/src/models/response/ssoPreValidateResponse.ts @@ -0,0 +1,10 @@ +import { BaseResponse } from "./baseResponse"; + +export class SsoPreValidateResponse extends BaseResponse { + token: string; + + constructor(response: any) { + super(response); + this.token = this.getResponseProperty("Token"); + } +} diff --git a/libs/common/src/models/response/subscriptionResponse.ts b/libs/common/src/models/response/subscriptionResponse.ts new file mode 100644 index 0000000000..fc5570c3e0 --- /dev/null +++ b/libs/common/src/models/response/subscriptionResponse.ts @@ -0,0 +1,85 @@ +import { BaseResponse } from "./baseResponse"; + +export class SubscriptionResponse extends BaseResponse { + storageName: string; + storageGb: number; + maxStorageGb: number; + subscription: BillingSubscriptionResponse; + upcomingInvoice: BillingSubscriptionUpcomingInvoiceResponse; + license: any; + expiration: string; + usingInAppPurchase: boolean; + + constructor(response: any) { + super(response); + this.storageName = this.getResponseProperty("StorageName"); + this.storageGb = this.getResponseProperty("StorageGb"); + this.maxStorageGb = this.getResponseProperty("MaxStorageGb"); + this.license = this.getResponseProperty("License"); + this.expiration = this.getResponseProperty("Expiration"); + this.usingInAppPurchase = this.getResponseProperty("UsingInAppPurchase"); + const subscription = this.getResponseProperty("Subscription"); + const upcomingInvoice = this.getResponseProperty("UpcomingInvoice"); + this.subscription = subscription == null ? null : new BillingSubscriptionResponse(subscription); + this.upcomingInvoice = + upcomingInvoice == null + ? null + : new BillingSubscriptionUpcomingInvoiceResponse(upcomingInvoice); + } +} + +export class BillingSubscriptionResponse extends BaseResponse { + trialStartDate: string; + trialEndDate: string; + periodStartDate: string; + periodEndDate: string; + cancelledDate: string; + cancelAtEndDate: boolean; + status: string; + cancelled: boolean; + items: BillingSubscriptionItemResponse[] = []; + + constructor(response: any) { + super(response); + this.trialEndDate = this.getResponseProperty("TrialStartDate"); + this.trialEndDate = this.getResponseProperty("TrialEndDate"); + this.periodStartDate = this.getResponseProperty("PeriodStartDate"); + this.periodEndDate = this.getResponseProperty("PeriodEndDate"); + this.cancelledDate = this.getResponseProperty("CancelledDate"); + this.cancelAtEndDate = this.getResponseProperty("CancelAtEndDate"); + this.status = this.getResponseProperty("Status"); + this.cancelled = this.getResponseProperty("Cancelled"); + const items = this.getResponseProperty("Items"); + if (items != null) { + this.items = items.map((i: any) => new BillingSubscriptionItemResponse(i)); + } + } +} + +export class BillingSubscriptionItemResponse extends BaseResponse { + name: string; + amount: number; + quantity: number; + interval: string; + sponsoredSubscriptionItem: boolean; + + constructor(response: any) { + super(response); + this.name = this.getResponseProperty("Name"); + this.amount = this.getResponseProperty("Amount"); + this.quantity = this.getResponseProperty("Quantity"); + this.interval = this.getResponseProperty("Interval"); + this.sponsoredSubscriptionItem = this.getResponseProperty("SponsoredSubscriptionItem"); + } +} + +export class BillingSubscriptionUpcomingInvoiceResponse extends BaseResponse { + date: string; + amount: number; + + constructor(response: any) { + super(response); + this.date = this.getResponseProperty("Date"); + this.amount = this.getResponseProperty("Amount"); + } +} diff --git a/libs/common/src/models/response/syncResponse.ts b/libs/common/src/models/response/syncResponse.ts new file mode 100644 index 0000000000..cab3ff2e7f --- /dev/null +++ b/libs/common/src/models/response/syncResponse.ts @@ -0,0 +1,57 @@ +import { BaseResponse } from "./baseResponse"; +import { CipherResponse } from "./cipherResponse"; +import { CollectionDetailsResponse } from "./collectionResponse"; +import { DomainsResponse } from "./domainsResponse"; +import { FolderResponse } from "./folderResponse"; +import { PolicyResponse } from "./policyResponse"; +import { ProfileResponse } from "./profileResponse"; +import { SendResponse } from "./sendResponse"; + +export class SyncResponse extends BaseResponse { + profile?: ProfileResponse; + folders: FolderResponse[] = []; + collections: CollectionDetailsResponse[] = []; + ciphers: CipherResponse[] = []; + domains?: DomainsResponse; + policies?: PolicyResponse[] = []; + sends: SendResponse[] = []; + + constructor(response: any) { + super(response); + + const profile = this.getResponseProperty("Profile"); + if (profile != null) { + this.profile = new ProfileResponse(profile); + } + + const folders = this.getResponseProperty("Folders"); + if (folders != null) { + this.folders = folders.map((f: any) => new FolderResponse(f)); + } + + const collections = this.getResponseProperty("Collections"); + if (collections != null) { + this.collections = collections.map((c: any) => new CollectionDetailsResponse(c)); + } + + const ciphers = this.getResponseProperty("Ciphers"); + if (ciphers != null) { + this.ciphers = ciphers.map((c: any) => new CipherResponse(c)); + } + + const domains = this.getResponseProperty("Domains"); + if (domains != null) { + this.domains = new DomainsResponse(domains); + } + + const policies = this.getResponseProperty("Policies"); + if (policies != null) { + this.policies = policies.map((p: any) => new PolicyResponse(p)); + } + + const sends = this.getResponseProperty("Sends"); + if (sends != null) { + this.sends = sends.map((s: any) => new SendResponse(s)); + } + } +} diff --git a/libs/common/src/models/response/taxInfoResponse.ts b/libs/common/src/models/response/taxInfoResponse.ts new file mode 100644 index 0000000000..bb4693ca66 --- /dev/null +++ b/libs/common/src/models/response/taxInfoResponse.ts @@ -0,0 +1,24 @@ +import { BaseResponse } from "./baseResponse"; + +export class TaxInfoResponse extends BaseResponse { + taxId: string; + taxIdType: string; + line1: string; + line2: string; + city: string; + state: string; + country: string; + postalCode: string; + + constructor(response: any) { + super(response); + this.taxId = this.getResponseProperty("TaxIdNumber"); + this.taxIdType = this.getResponseProperty("TaxIdType"); + this.line1 = this.getResponseProperty("Line1"); + this.line2 = this.getResponseProperty("Line2"); + this.city = this.getResponseProperty("City"); + this.state = this.getResponseProperty("State"); + this.postalCode = this.getResponseProperty("PostalCode"); + this.country = this.getResponseProperty("Country"); + } +} diff --git a/libs/common/src/models/response/taxRateResponse.ts b/libs/common/src/models/response/taxRateResponse.ts new file mode 100644 index 0000000000..28274a50f6 --- /dev/null +++ b/libs/common/src/models/response/taxRateResponse.ts @@ -0,0 +1,18 @@ +import { BaseResponse } from "./baseResponse"; + +export class TaxRateResponse extends BaseResponse { + id: string; + country: string; + state: string; + postalCode: string; + rate: number; + + constructor(response: any) { + super(response); + this.id = this.getResponseProperty("Id"); + this.country = this.getResponseProperty("Country"); + this.state = this.getResponseProperty("State"); + this.postalCode = this.getResponseProperty("PostalCode"); + this.rate = this.getResponseProperty("Rate"); + } +} diff --git a/libs/common/src/models/response/twoFactorAuthenticatorResponse.ts b/libs/common/src/models/response/twoFactorAuthenticatorResponse.ts new file mode 100644 index 0000000000..8eb73eaa93 --- /dev/null +++ b/libs/common/src/models/response/twoFactorAuthenticatorResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class TwoFactorAuthenticatorResponse extends BaseResponse { + enabled: boolean; + key: string; + + constructor(response: any) { + super(response); + this.enabled = this.getResponseProperty("Enabled"); + this.key = this.getResponseProperty("Key"); + } +} diff --git a/libs/common/src/models/response/twoFactorDuoResponse.ts b/libs/common/src/models/response/twoFactorDuoResponse.ts new file mode 100644 index 0000000000..401de79688 --- /dev/null +++ b/libs/common/src/models/response/twoFactorDuoResponse.ts @@ -0,0 +1,16 @@ +import { BaseResponse } from "./baseResponse"; + +export class TwoFactorDuoResponse extends BaseResponse { + enabled: boolean; + host: string; + secretKey: string; + integrationKey: string; + + constructor(response: any) { + super(response); + this.enabled = this.getResponseProperty("Enabled"); + this.host = this.getResponseProperty("Host"); + this.secretKey = this.getResponseProperty("SecretKey"); + this.integrationKey = this.getResponseProperty("IntegrationKey"); + } +} diff --git a/libs/common/src/models/response/twoFactorEmailResponse.ts b/libs/common/src/models/response/twoFactorEmailResponse.ts new file mode 100644 index 0000000000..ad1936d33c --- /dev/null +++ b/libs/common/src/models/response/twoFactorEmailResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class TwoFactorEmailResponse extends BaseResponse { + enabled: boolean; + email: string; + + constructor(response: any) { + super(response); + this.enabled = this.getResponseProperty("Enabled"); + this.email = this.getResponseProperty("Email"); + } +} diff --git a/libs/common/src/models/response/twoFactorProviderResponse.ts b/libs/common/src/models/response/twoFactorProviderResponse.ts new file mode 100644 index 0000000000..4ccd86cb6d --- /dev/null +++ b/libs/common/src/models/response/twoFactorProviderResponse.ts @@ -0,0 +1,14 @@ +import { TwoFactorProviderType } from "../../enums/twoFactorProviderType"; + +import { BaseResponse } from "./baseResponse"; + +export class TwoFactorProviderResponse extends BaseResponse { + enabled: boolean; + type: TwoFactorProviderType; + + constructor(response: any) { + super(response); + this.enabled = this.getResponseProperty("Enabled"); + this.type = this.getResponseProperty("Type"); + } +} diff --git a/libs/common/src/models/response/twoFactorRescoverResponse.ts b/libs/common/src/models/response/twoFactorRescoverResponse.ts new file mode 100644 index 0000000000..0e26db9b53 --- /dev/null +++ b/libs/common/src/models/response/twoFactorRescoverResponse.ts @@ -0,0 +1,10 @@ +import { BaseResponse } from "./baseResponse"; + +export class TwoFactorRecoverResponse extends BaseResponse { + code: string; + + constructor(response: any) { + super(response); + this.code = this.getResponseProperty("Code"); + } +} diff --git a/libs/common/src/models/response/twoFactorWebAuthnResponse.ts b/libs/common/src/models/response/twoFactorWebAuthnResponse.ts new file mode 100644 index 0000000000..21ab66a036 --- /dev/null +++ b/libs/common/src/models/response/twoFactorWebAuthnResponse.ts @@ -0,0 +1,60 @@ +import { Utils } from "../../misc/utils"; + +import { BaseResponse } from "./baseResponse"; + +export class TwoFactorWebAuthnResponse extends BaseResponse { + enabled: boolean; + keys: KeyResponse[]; + + constructor(response: any) { + super(response); + this.enabled = this.getResponseProperty("Enabled"); + const keys = this.getResponseProperty("Keys"); + this.keys = keys == null ? null : keys.map((k: any) => new KeyResponse(k)); + } +} + +export class KeyResponse extends BaseResponse { + name: string; + id: number; + migrated: boolean; + + constructor(response: any) { + super(response); + this.name = this.getResponseProperty("Name"); + this.id = this.getResponseProperty("Id"); + this.migrated = this.getResponseProperty("Migrated"); + } +} + +export class ChallengeResponse extends BaseResponse implements PublicKeyCredentialCreationOptions { + attestation?: AttestationConveyancePreference; + authenticatorSelection?: AuthenticatorSelectionCriteria; + challenge: BufferSource; + excludeCredentials?: PublicKeyCredentialDescriptor[]; + extensions?: AuthenticationExtensionsClientInputs; + pubKeyCredParams: PublicKeyCredentialParameters[]; + rp: PublicKeyCredentialRpEntity; + timeout?: number; + user: PublicKeyCredentialUserEntity; + + constructor(response: any) { + super(response); + this.attestation = this.getResponseProperty("attestation"); + this.authenticatorSelection = this.getResponseProperty("authenticatorSelection"); + this.challenge = Utils.fromUrlB64ToArray(this.getResponseProperty("challenge")); + this.excludeCredentials = this.getResponseProperty("excludeCredentials").map((c: any) => { + c.id = Utils.fromUrlB64ToArray(c.id).buffer; + return c; + }); + this.extensions = this.getResponseProperty("extensions"); + this.pubKeyCredParams = this.getResponseProperty("pubKeyCredParams"); + this.rp = this.getResponseProperty("rp"); + this.timeout = this.getResponseProperty("timeout"); + + const user = this.getResponseProperty("user"); + user.id = Utils.fromUrlB64ToArray(user.id); + + this.user = user; + } +} diff --git a/libs/common/src/models/response/twoFactorYubiKeyResponse.ts b/libs/common/src/models/response/twoFactorYubiKeyResponse.ts new file mode 100644 index 0000000000..ee75074b24 --- /dev/null +++ b/libs/common/src/models/response/twoFactorYubiKeyResponse.ts @@ -0,0 +1,22 @@ +import { BaseResponse } from "./baseResponse"; + +export class TwoFactorYubiKeyResponse extends BaseResponse { + enabled: boolean; + key1: string; + key2: string; + key3: string; + key4: string; + key5: string; + nfc: boolean; + + constructor(response: any) { + super(response); + this.enabled = this.getResponseProperty("Enabled"); + this.key1 = this.getResponseProperty("Key1"); + this.key2 = this.getResponseProperty("Key2"); + this.key3 = this.getResponseProperty("Key3"); + this.key4 = this.getResponseProperty("Key4"); + this.key5 = this.getResponseProperty("Key5"); + this.nfc = this.getResponseProperty("Nfc"); + } +} diff --git a/libs/common/src/models/response/userKeyResponse.ts b/libs/common/src/models/response/userKeyResponse.ts new file mode 100644 index 0000000000..5550abdf08 --- /dev/null +++ b/libs/common/src/models/response/userKeyResponse.ts @@ -0,0 +1,12 @@ +import { BaseResponse } from "./baseResponse"; + +export class UserKeyResponse extends BaseResponse { + userId: string; + publicKey: string; + + constructor(response: any) { + super(response); + this.userId = this.getResponseProperty("UserId"); + this.publicKey = this.getResponseProperty("PublicKey"); + } +} diff --git a/libs/common/src/models/view/attachmentView.ts b/libs/common/src/models/view/attachmentView.ts new file mode 100644 index 0000000000..4ebbec7ee8 --- /dev/null +++ b/libs/common/src/models/view/attachmentView.ts @@ -0,0 +1,35 @@ +import { Attachment } from "../domain/attachment"; +import { SymmetricCryptoKey } from "../domain/symmetricCryptoKey"; + +import { View } from "./view"; + +export class AttachmentView implements View { + id: string = null; + url: string = null; + size: string = null; + sizeName: string = null; + fileName: string = null; + key: SymmetricCryptoKey = null; + + constructor(a?: Attachment) { + if (!a) { + return; + } + + this.id = a.id; + this.url = a.url; + this.size = a.size; + this.sizeName = a.sizeName; + } + + get fileSize(): number { + try { + if (this.size != null) { + return parseInt(this.size, null); + } + } catch { + // Invalid file size. + } + return 0; + } +} diff --git a/libs/common/src/models/view/cardView.ts b/libs/common/src/models/view/cardView.ts new file mode 100644 index 0000000000..769fa4402f --- /dev/null +++ b/libs/common/src/models/view/cardView.ts @@ -0,0 +1,82 @@ +import { CardLinkedId as LinkedId } from "../../enums/linkedIdType"; +import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator"; + +import { ItemView } from "./itemView"; + +export class CardView extends ItemView { + @linkedFieldOption(LinkedId.CardholderName) + cardholderName: string = null; + @linkedFieldOption(LinkedId.ExpMonth, "expirationMonth") + expMonth: string = null; + @linkedFieldOption(LinkedId.ExpYear, "expirationYear") + expYear: string = null; + @linkedFieldOption(LinkedId.Code, "securityCode") + code: string = null; + + private _brand: string = null; + private _number: string = null; + private _subTitle: string = null; + + constructor() { + super(); + } + + get maskedCode(): string { + return this.code != null ? "•".repeat(this.code.length) : null; + } + + get maskedNumber(): string { + return this.number != null ? "•".repeat(this.number.length) : null; + } + + @linkedFieldOption(LinkedId.Brand) + get brand(): string { + return this._brand; + } + set brand(value: string) { + this._brand = value; + this._subTitle = null; + } + + @linkedFieldOption(LinkedId.Number) + get number(): string { + return this._number; + } + set number(value: string) { + this._number = value; + this._subTitle = null; + } + + get subTitle(): string { + if (this._subTitle == null) { + this._subTitle = this.brand; + if (this.number != null && this.number.length >= 4) { + if (this._subTitle != null && this._subTitle !== "") { + this._subTitle += ", "; + } else { + this._subTitle = ""; + } + + // Show last 5 on amex, last 4 for all others + const count = + this.number.length >= 5 && this.number.match(new RegExp("^3[47]")) != null ? 5 : 4; + this._subTitle += "*" + this.number.substr(this.number.length - count); + } + } + return this._subTitle; + } + + get expiration(): string { + if (!this.expMonth && !this.expYear) { + return null; + } + + let exp = this.expMonth != null ? ("0" + this.expMonth).slice(-2) : "__"; + exp += " / " + (this.expYear != null ? this.formatYear(this.expYear) : "____"); + return exp; + } + + private formatYear(year: string): string { + return year.length === 2 ? "20" + year : year; + } +} diff --git a/libs/common/src/models/view/cipherView.ts b/libs/common/src/models/view/cipherView.ts new file mode 100644 index 0000000000..3d1f16c14f --- /dev/null +++ b/libs/common/src/models/view/cipherView.ts @@ -0,0 +1,134 @@ +import { CipherRepromptType } from "../../enums/cipherRepromptType"; +import { CipherType } from "../../enums/cipherType"; +import { LinkedIdType } from "../../enums/linkedIdType"; +import { Cipher } from "../domain/cipher"; + +import { AttachmentView } from "./attachmentView"; +import { CardView } from "./cardView"; +import { FieldView } from "./fieldView"; +import { IdentityView } from "./identityView"; +import { LoginView } from "./loginView"; +import { PasswordHistoryView } from "./passwordHistoryView"; +import { SecureNoteView } from "./secureNoteView"; +import { View } from "./view"; + +export class CipherView implements View { + id: string = null; + organizationId: string = null; + folderId: string = null; + name: string = null; + notes: string = null; + type: CipherType = null; + favorite = false; + organizationUseTotp = false; + edit = false; + viewPassword = true; + localData: any; + login = new LoginView(); + identity = new IdentityView(); + card = new CardView(); + secureNote = new SecureNoteView(); + attachments: AttachmentView[] = null; + fields: FieldView[] = null; + passwordHistory: PasswordHistoryView[] = null; + collectionIds: string[] = null; + revisionDate: Date = null; + deletedDate: Date = null; + reprompt: CipherRepromptType = CipherRepromptType.None; + + constructor(c?: Cipher) { + if (!c) { + return; + } + + this.id = c.id; + this.organizationId = c.organizationId; + this.folderId = c.folderId; + this.favorite = c.favorite; + this.organizationUseTotp = c.organizationUseTotp; + this.edit = c.edit; + this.viewPassword = c.viewPassword; + this.type = c.type; + this.localData = c.localData; + this.collectionIds = c.collectionIds; + this.revisionDate = c.revisionDate; + this.deletedDate = c.deletedDate; + // Old locally stored ciphers might have reprompt == null. If so set it to None. + this.reprompt = c.reprompt ?? CipherRepromptType.None; + } + + private get item() { + switch (this.type) { + case CipherType.Login: + return this.login; + case CipherType.SecureNote: + return this.secureNote; + case CipherType.Card: + return this.card; + case CipherType.Identity: + return this.identity; + default: + break; + } + + return null; + } + + get subTitle(): string { + return this.item.subTitle; + } + + get hasPasswordHistory(): boolean { + return this.passwordHistory && this.passwordHistory.length > 0; + } + + get hasAttachments(): boolean { + return this.attachments && this.attachments.length > 0; + } + + get hasOldAttachments(): boolean { + if (this.hasAttachments) { + for (let i = 0; i < this.attachments.length; i++) { + if (this.attachments[i].key == null) { + return true; + } + } + } + return false; + } + + get hasFields(): boolean { + return this.fields && this.fields.length > 0; + } + + get passwordRevisionDisplayDate(): Date { + if (this.type !== CipherType.Login || this.login == null) { + return null; + } else if (this.login.password == null || this.login.password === "") { + return null; + } + return this.login.passwordRevisionDate; + } + + get isDeleted(): boolean { + return this.deletedDate != null; + } + + get linkedFieldOptions() { + return this.item.linkedFieldOptions; + } + + linkedFieldValue(id: LinkedIdType) { + const linkedFieldOption = this.linkedFieldOptions?.get(id); + if (linkedFieldOption == null) { + return null; + } + + const item = this.item; + return this.item[linkedFieldOption.propertyKey as keyof typeof item]; + } + + linkedFieldI18nKey(id: LinkedIdType): string { + return this.linkedFieldOptions.get(id)?.i18nKey; + } +} diff --git a/libs/common/src/models/view/collectionView.ts b/libs/common/src/models/view/collectionView.ts new file mode 100644 index 0000000000..d230e591f3 --- /dev/null +++ b/libs/common/src/models/view/collectionView.ts @@ -0,0 +1,28 @@ +import { Collection } from "../domain/collection"; +import { ITreeNodeObject } from "../domain/treeNode"; +import { CollectionGroupDetailsResponse } from "../response/collectionResponse"; + +import { View } from "./view"; + +export class CollectionView implements View, ITreeNodeObject { + id: string = null; + organizationId: string = null; + name: string = null; + externalId: string = null; + readOnly: boolean = null; + hidePasswords: boolean = null; + + constructor(c?: Collection | CollectionGroupDetailsResponse) { + if (!c) { + return; + } + + this.id = c.id; + this.organizationId = c.organizationId; + this.externalId = c.externalId; + if (c instanceof Collection) { + this.readOnly = c.readOnly; + this.hidePasswords = c.hidePasswords; + } + } +} diff --git a/libs/common/src/models/view/eventView.ts b/libs/common/src/models/view/eventView.ts new file mode 100644 index 0000000000..56bf5c309e --- /dev/null +++ b/libs/common/src/models/view/eventView.ts @@ -0,0 +1,29 @@ +import { EventType } from "../../enums/eventType"; + +export class EventView { + message: string; + humanReadableMessage: string; + appIcon: string; + appName: string; + userId: string; + userName: string; + userEmail: string; + date: string; + ip: string; + type: EventType; + installationId: string; + + constructor(data: Required) { + this.message = data.message; + this.humanReadableMessage = data.humanReadableMessage; + this.appIcon = data.appIcon; + this.appName = data.appName; + this.userId = data.userId; + this.userName = data.userName; + this.userEmail = data.userEmail; + this.date = data.date; + this.ip = data.ip; + this.type = data.type; + this.installationId = data.installationId; + } +} diff --git a/libs/common/src/models/view/fieldView.ts b/libs/common/src/models/view/fieldView.ts new file mode 100644 index 0000000000..51e3aaef35 --- /dev/null +++ b/libs/common/src/models/view/fieldView.ts @@ -0,0 +1,28 @@ +import { FieldType } from "../../enums/fieldType"; +import { LinkedIdType } from "../../enums/linkedIdType"; +import { Field } from "../domain/field"; + +import { View } from "./view"; + +export class FieldView implements View { + name: string = null; + value: string = null; + type: FieldType = null; + newField = false; // Marks if the field is new and hasn't been saved + showValue = false; + showCount = false; + linkedId: LinkedIdType = null; + + constructor(f?: Field) { + if (!f) { + return; + } + + this.type = f.type; + this.linkedId = f.linkedId; + } + + get maskedValue(): string { + return this.value != null ? "••••••••" : null; + } +} diff --git a/libs/common/src/models/view/folderView.ts b/libs/common/src/models/view/folderView.ts new file mode 100644 index 0000000000..731acffba4 --- /dev/null +++ b/libs/common/src/models/view/folderView.ts @@ -0,0 +1,19 @@ +import { Folder } from "../domain/folder"; +import { ITreeNodeObject } from "../domain/treeNode"; + +import { View } from "./view"; + +export class FolderView implements View, ITreeNodeObject { + id: string = null; + name: string = null; + revisionDate: Date = null; + + constructor(f?: Folder) { + if (!f) { + return; + } + + this.id = f.id; + this.revisionDate = f.revisionDate; + } +} diff --git a/libs/common/src/models/view/identityView.ts b/libs/common/src/models/view/identityView.ts new file mode 100644 index 0000000000..2630563609 --- /dev/null +++ b/libs/common/src/models/view/identityView.ts @@ -0,0 +1,142 @@ +import { IdentityLinkedId as LinkedId } from "../../enums/linkedIdType"; +import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator"; +import { Utils } from "../../misc/utils"; + +import { ItemView } from "./itemView"; + +export class IdentityView extends ItemView { + @linkedFieldOption(LinkedId.Title) + title: string = null; + @linkedFieldOption(LinkedId.MiddleName) + middleName: string = null; + @linkedFieldOption(LinkedId.Address1) + address1: string = null; + @linkedFieldOption(LinkedId.Address2) + address2: string = null; + @linkedFieldOption(LinkedId.Address3) + address3: string = null; + @linkedFieldOption(LinkedId.City, "cityTown") + city: string = null; + @linkedFieldOption(LinkedId.State, "stateProvince") + state: string = null; + @linkedFieldOption(LinkedId.PostalCode, "zipPostalCode") + postalCode: string = null; + @linkedFieldOption(LinkedId.Country) + country: string = null; + @linkedFieldOption(LinkedId.Company) + company: string = null; + @linkedFieldOption(LinkedId.Email) + email: string = null; + @linkedFieldOption(LinkedId.Phone) + phone: string = null; + @linkedFieldOption(LinkedId.Ssn) + ssn: string = null; + @linkedFieldOption(LinkedId.Username) + username: string = null; + @linkedFieldOption(LinkedId.PassportNumber) + passportNumber: string = null; + @linkedFieldOption(LinkedId.LicenseNumber) + licenseNumber: string = null; + + private _firstName: string = null; + private _lastName: string = null; + private _subTitle: string = null; + + constructor() { + super(); + } + + @linkedFieldOption(LinkedId.FirstName) + get firstName(): string { + return this._firstName; + } + set firstName(value: string) { + this._firstName = value; + this._subTitle = null; + } + + @linkedFieldOption(LinkedId.LastName) + get lastName(): string { + return this._lastName; + } + set lastName(value: string) { + this._lastName = value; + this._subTitle = null; + } + + get subTitle(): string { + if (this._subTitle == null && (this.firstName != null || this.lastName != null)) { + this._subTitle = ""; + if (this.firstName != null) { + this._subTitle = this.firstName; + } + if (this.lastName != null) { + if (this._subTitle !== "") { + this._subTitle += " "; + } + this._subTitle += this.lastName; + } + } + + return this._subTitle; + } + + @linkedFieldOption(LinkedId.FullName) + get fullName(): string { + if ( + this.title != null || + this.firstName != null || + this.middleName != null || + this.lastName != null + ) { + let name = ""; + if (this.title != null) { + name += this.title + " "; + } + if (this.firstName != null) { + name += this.firstName + " "; + } + if (this.middleName != null) { + name += this.middleName + " "; + } + if (this.lastName != null) { + name += this.lastName; + } + return name.trim(); + } + + return null; + } + + get fullAddress(): string { + let address = this.address1; + if (!Utils.isNullOrWhitespace(this.address2)) { + if (!Utils.isNullOrWhitespace(address)) { + address += ", "; + } + address += this.address2; + } + if (!Utils.isNullOrWhitespace(this.address3)) { + if (!Utils.isNullOrWhitespace(address)) { + address += ", "; + } + address += this.address3; + } + return address; + } + + get fullAddressPart2(): string { + if (this.city == null && this.state == null && this.postalCode == null) { + return null; + } + const city = this.city || "-"; + const state = this.state; + const postalCode = this.postalCode || "-"; + let addressPart2 = city; + if (!Utils.isNullOrWhitespace(state)) { + addressPart2 += ", " + state; + } + addressPart2 += ", " + postalCode; + return addressPart2; + } +} diff --git a/libs/common/src/models/view/itemView.ts b/libs/common/src/models/view/itemView.ts new file mode 100644 index 0000000000..3a557ffa85 --- /dev/null +++ b/libs/common/src/models/view/itemView.ts @@ -0,0 +1,8 @@ +import { LinkedMetadata } from "../../misc/linkedFieldOption.decorator"; + +import { View } from "./view"; + +export abstract class ItemView implements View { + linkedFieldOptions: Map; + abstract get subTitle(): string; +} diff --git a/libs/common/src/models/view/loginUriView.ts b/libs/common/src/models/view/loginUriView.ts new file mode 100644 index 0000000000..cca9520df1 --- /dev/null +++ b/libs/common/src/models/view/loginUriView.ts @@ -0,0 +1,127 @@ +import { UriMatchType } from "../../enums/uriMatchType"; +import { Utils } from "../../misc/utils"; +import { LoginUri } from "../domain/loginUri"; + +import { View } from "./view"; + +const CanLaunchWhitelist = [ + "https://", + "http://", + "ssh://", + "ftp://", + "sftp://", + "irc://", + "vnc://", + // https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-uri + "rdp://", // Legacy RDP URI scheme + "ms-rd:", // Preferred RDP URI scheme + "chrome://", + "iosapp://", + "androidapp://", +]; + +export class LoginUriView implements View { + match: UriMatchType = null; + + private _uri: string = null; + private _domain: string = null; + private _hostname: string = null; + private _host: string = null; + private _canLaunch: boolean = null; + + constructor(u?: LoginUri) { + if (!u) { + return; + } + + this.match = u.match; + } + + get uri(): string { + return this._uri; + } + set uri(value: string) { + this._uri = value; + this._domain = null; + this._canLaunch = null; + } + + get domain(): string { + if (this._domain == null && this.uri != null) { + this._domain = Utils.getDomain(this.uri); + if (this._domain === "") { + this._domain = null; + } + } + + return this._domain; + } + + get hostname(): string { + if (this.match === UriMatchType.RegularExpression) { + return null; + } + if (this._hostname == null && this.uri != null) { + this._hostname = Utils.getHostname(this.uri); + if (this._hostname === "") { + this._hostname = null; + } + } + + return this._hostname; + } + + get host(): string { + if (this.match === UriMatchType.RegularExpression) { + return null; + } + if (this._host == null && this.uri != null) { + this._host = Utils.getHost(this.uri); + if (this._host === "") { + this._host = null; + } + } + + return this._host; + } + + get hostnameOrUri(): string { + return this.hostname != null ? this.hostname : this.uri; + } + + get hostOrUri(): string { + return this.host != null ? this.host : this.uri; + } + + get isWebsite(): boolean { + return ( + this.uri != null && + (this.uri.indexOf("http://") === 0 || + this.uri.indexOf("https://") === 0 || + (this.uri.indexOf("://") < 0 && Utils.tldEndingRegex.test(this.uri))) + ); + } + + get canLaunch(): boolean { + if (this._canLaunch != null) { + return this._canLaunch; + } + if (this.uri != null && this.match !== UriMatchType.RegularExpression) { + const uri = this.launchUri; + for (let i = 0; i < CanLaunchWhitelist.length; i++) { + if (uri.indexOf(CanLaunchWhitelist[i]) === 0) { + this._canLaunch = true; + return this._canLaunch; + } + } + } + this._canLaunch = false; + return this._canLaunch; + } + + get launchUri(): string { + return this.uri.indexOf("://") < 0 && Utils.tldEndingRegex.test(this.uri) + ? "http://" + this.uri + : this.uri; + } +} diff --git a/libs/common/src/models/view/loginView.ts b/libs/common/src/models/view/loginView.ts new file mode 100644 index 0000000000..e86dd14b2f --- /dev/null +++ b/libs/common/src/models/view/loginView.ts @@ -0,0 +1,63 @@ +import { LoginLinkedId as LinkedId } from "../../enums/linkedIdType"; +import { linkedFieldOption } from "../../misc/linkedFieldOption.decorator"; +import { Utils } from "../../misc/utils"; +import { Login } from "../domain/login"; + +import { ItemView } from "./itemView"; +import { LoginUriView } from "./loginUriView"; + +export class LoginView extends ItemView { + @linkedFieldOption(LinkedId.Username) + username: string = null; + @linkedFieldOption(LinkedId.Password) + password: string = null; + + passwordRevisionDate?: Date = null; + totp: string = null; + uris: LoginUriView[] = null; + autofillOnPageLoad: boolean = null; + + constructor(l?: Login) { + super(); + if (!l) { + return; + } + + this.passwordRevisionDate = l.passwordRevisionDate; + this.autofillOnPageLoad = l.autofillOnPageLoad; + } + + get uri(): string { + return this.hasUris ? this.uris[0].uri : null; + } + + get maskedPassword(): string { + return this.password != null ? "••••••••" : null; + } + + get subTitle(): string { + return this.username; + } + + get canLaunch(): boolean { + return this.hasUris && this.uris.some((u) => u.canLaunch); + } + + get hasTotp(): boolean { + return !Utils.isNullOrWhitespace(this.totp); + } + + get launchUri(): string { + if (this.hasUris) { + const uri = this.uris.find((u) => u.canLaunch); + if (uri != null) { + return uri.launchUri; + } + } + return null; + } + + get hasUris(): boolean { + return this.uris != null && this.uris.length > 0; + } +} diff --git a/libs/common/src/models/view/passwordHistoryView.ts b/libs/common/src/models/view/passwordHistoryView.ts new file mode 100644 index 0000000000..aa780079d3 --- /dev/null +++ b/libs/common/src/models/view/passwordHistoryView.ts @@ -0,0 +1,16 @@ +import { Password } from "../domain/password"; + +import { View } from "./view"; + +export class PasswordHistoryView implements View { + password: string = null; + lastUsedDate: Date = null; + + constructor(ph?: Password) { + if (!ph) { + return; + } + + this.lastUsedDate = ph.lastUsedDate; + } +} diff --git a/libs/common/src/models/view/secureNoteView.ts b/libs/common/src/models/view/secureNoteView.ts new file mode 100644 index 0000000000..c324b07ebb --- /dev/null +++ b/libs/common/src/models/view/secureNoteView.ts @@ -0,0 +1,21 @@ +import { SecureNoteType } from "../../enums/secureNoteType"; +import { SecureNote } from "../domain/secureNote"; + +import { ItemView } from "./itemView"; + +export class SecureNoteView extends ItemView { + type: SecureNoteType = null; + + constructor(n?: SecureNote) { + super(); + if (!n) { + return; + } + + this.type = n.type; + } + + get subTitle(): string { + return null; + } +} diff --git a/libs/common/src/models/view/sendAccessView.ts b/libs/common/src/models/view/sendAccessView.ts new file mode 100644 index 0000000000..71e5276a98 --- /dev/null +++ b/libs/common/src/models/view/sendAccessView.ts @@ -0,0 +1,27 @@ +import { SendType } from "../../enums/sendType"; +import { SendAccess } from "../domain/sendAccess"; + +import { SendFileView } from "./sendFileView"; +import { SendTextView } from "./sendTextView"; +import { View } from "./view"; + +export class SendAccessView implements View { + id: string = null; + name: string = null; + type: SendType = null; + text = new SendTextView(); + file = new SendFileView(); + expirationDate: Date = null; + creatorIdentifier: string = null; + + constructor(s?: SendAccess) { + if (!s) { + return; + } + + this.id = s.id; + this.type = s.type; + this.expirationDate = s.expirationDate; + this.creatorIdentifier = s.creatorIdentifier; + } +} diff --git a/libs/common/src/models/view/sendFileView.ts b/libs/common/src/models/view/sendFileView.ts new file mode 100644 index 0000000000..7d37f2def8 --- /dev/null +++ b/libs/common/src/models/view/sendFileView.ts @@ -0,0 +1,31 @@ +import { SendFile } from "../domain/sendFile"; + +import { View } from "./view"; + +export class SendFileView implements View { + id: string = null; + size: string = null; + sizeName: string = null; + fileName: string = null; + + constructor(f?: SendFile) { + if (!f) { + return; + } + + this.id = f.id; + this.size = f.size; + this.sizeName = f.sizeName; + } + + get fileSize(): number { + try { + if (this.size != null) { + return parseInt(this.size, null); + } + } catch { + // Invalid file size. + } + return 0; + } +} diff --git a/libs/common/src/models/view/sendTextView.ts b/libs/common/src/models/view/sendTextView.ts new file mode 100644 index 0000000000..a2c6b5711f --- /dev/null +++ b/libs/common/src/models/view/sendTextView.ts @@ -0,0 +1,20 @@ +import { SendText } from "../domain/sendText"; + +import { View } from "./view"; + +export class SendTextView implements View { + text: string = null; + hidden: boolean; + + constructor(t?: SendText) { + if (!t) { + return; + } + + this.hidden = t.hidden; + } + + get maskedText(): string { + return this.text != null ? "••••••••" : null; + } +} diff --git a/libs/common/src/models/view/sendView.ts b/libs/common/src/models/view/sendView.ts new file mode 100644 index 0000000000..1a2a214fc8 --- /dev/null +++ b/libs/common/src/models/view/sendView.ts @@ -0,0 +1,68 @@ +import { SendType } from "../../enums/sendType"; +import { Utils } from "../../misc/utils"; +import { Send } from "../domain/send"; +import { SymmetricCryptoKey } from "../domain/symmetricCryptoKey"; + +import { SendFileView } from "./sendFileView"; +import { SendTextView } from "./sendTextView"; +import { View } from "./view"; + +export class SendView implements View { + id: string = null; + accessId: string = null; + name: string = null; + notes: string = null; + key: ArrayBuffer; + cryptoKey: SymmetricCryptoKey; + type: SendType = null; + text = new SendTextView(); + file = new SendFileView(); + maxAccessCount?: number = null; + accessCount = 0; + revisionDate: Date = null; + deletionDate: Date = null; + expirationDate: Date = null; + password: string = null; + disabled = false; + hideEmail = false; + + constructor(s?: Send) { + if (!s) { + return; + } + + this.id = s.id; + this.accessId = s.accessId; + this.type = s.type; + this.maxAccessCount = s.maxAccessCount; + this.accessCount = s.accessCount; + this.revisionDate = s.revisionDate; + this.deletionDate = s.deletionDate; + this.expirationDate = s.expirationDate; + this.disabled = s.disabled; + this.password = s.password; + this.hideEmail = s.hideEmail; + } + + get urlB64Key(): string { + return Utils.fromBufferToUrlB64(this.key); + } + + get maxAccessCountReached(): boolean { + if (this.maxAccessCount == null) { + return false; + } + return this.accessCount >= this.maxAccessCount; + } + + get expired(): boolean { + if (this.expirationDate == null) { + return false; + } + return this.expirationDate <= new Date(); + } + + get pendingDelete(): boolean { + return this.deletionDate <= new Date(); + } +} diff --git a/libs/common/src/models/view/ssoConfigView.ts b/libs/common/src/models/view/ssoConfigView.ts new file mode 100644 index 0000000000..b4784c363c --- /dev/null +++ b/libs/common/src/models/view/ssoConfigView.ts @@ -0,0 +1,104 @@ +import { + OpenIdConnectRedirectBehavior, + Saml2BindingType, + Saml2NameIdFormat, + Saml2SigningBehavior, + SsoType, +} from "../../enums/ssoEnums"; +import { SsoConfigApi } from "../api/ssoConfigApi"; + +import { View } from "./view"; + +export class SsoConfigView extends View { + configType: SsoType; + + keyConnectorEnabled: boolean; + keyConnectorUrl: string; + + openId: { + authority: string; + clientId: string; + clientSecret: string; + metadataAddress: string; + redirectBehavior: OpenIdConnectRedirectBehavior; + getClaimsFromUserInfoEndpoint: boolean; + additionalScopes: string; + additionalUserIdClaimTypes: string; + additionalEmailClaimTypes: string; + additionalNameClaimTypes: string; + acrValues: string; + expectedReturnAcrValue: string; + }; + + saml: { + spNameIdFormat: Saml2NameIdFormat; + spOutboundSigningAlgorithm: string; + spSigningBehavior: Saml2SigningBehavior; + spMinIncomingSigningAlgorithm: boolean; + spWantAssertionsSigned: boolean; + spValidateCertificates: boolean; + + idpEntityId: string; + idpBindingType: Saml2BindingType; + idpSingleSignOnServiceUrl: string; + idpSingleLogoutServiceUrl: string; + idpX509PublicCert: string; + idpOutboundSigningAlgorithm: string; + idpAllowUnsolicitedAuthnResponse: boolean; + idpAllowOutboundLogoutRequests: boolean; + idpWantAuthnRequestsSigned: boolean; + }; + + constructor(api: SsoConfigApi) { + super(); + if (api == null) { + return; + } + + this.configType = api.configType; + + this.keyConnectorEnabled = api.keyConnectorEnabled; + this.keyConnectorUrl = api.keyConnectorUrl; + + if (this.configType === SsoType.OpenIdConnect) { + this.openId = { + authority: api.authority, + clientId: api.clientId, + clientSecret: api.clientSecret, + metadataAddress: api.metadataAddress, + redirectBehavior: api.redirectBehavior, + getClaimsFromUserInfoEndpoint: api.getClaimsFromUserInfoEndpoint, + additionalScopes: api.additionalScopes, + additionalUserIdClaimTypes: api.additionalUserIdClaimTypes, + additionalEmailClaimTypes: api.additionalEmailClaimTypes, + additionalNameClaimTypes: api.additionalNameClaimTypes, + acrValues: api.acrValues, + expectedReturnAcrValue: api.expectedReturnAcrValue, + }; + } else if (this.configType === SsoType.Saml2) { + this.saml = { + spNameIdFormat: api.spNameIdFormat, + spOutboundSigningAlgorithm: api.spOutboundSigningAlgorithm, + spSigningBehavior: api.spSigningBehavior, + spMinIncomingSigningAlgorithm: api.spMinIncomingSigningAlgorithm, + spWantAssertionsSigned: api.spWantAssertionsSigned, + spValidateCertificates: api.spValidateCertificates, + + idpEntityId: api.idpEntityId, + idpBindingType: api.idpBindingType, + idpSingleSignOnServiceUrl: api.idpSingleSignOnServiceUrl, + idpSingleLogoutServiceUrl: api.idpSingleLogoutServiceUrl, + idpX509PublicCert: api.idpX509PublicCert, + idpOutboundSigningAlgorithm: api.idpOutboundSigningAlgorithm, + idpAllowUnsolicitedAuthnResponse: api.idpAllowUnsolicitedAuthnResponse, + idpWantAuthnRequestsSigned: api.idpWantAuthnRequestsSigned, + + // Value is inverted in the view model (allow instead of disable) + idpAllowOutboundLogoutRequests: + api.idpDisableOutboundLogoutRequests == null + ? null + : !api.idpDisableOutboundLogoutRequests, + }; + } + } +} diff --git a/libs/common/src/models/view/view.ts b/libs/common/src/models/view/view.ts new file mode 100644 index 0000000000..1f16b3d595 --- /dev/null +++ b/libs/common/src/models/view/view.ts @@ -0,0 +1 @@ +export class View {} diff --git a/libs/common/src/services/api.service.ts b/libs/common/src/services/api.service.ts new file mode 100644 index 0000000000..2e0e3b92cf --- /dev/null +++ b/libs/common/src/services/api.service.ts @@ -0,0 +1,2626 @@ +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { OrganizationConnectionType } from "jslib-common/enums/organizationConnectionType"; +import { DeviceRequest } from "jslib-common/models/request/deviceRequest"; +import { TokenRequestTwoFactor } from "jslib-common/models/request/identityToken/tokenRequestTwoFactor"; +import { OrganizationConnectionRequest } from "jslib-common/models/request/organizationConnectionRequest"; +import { BillingHistoryResponse } from "jslib-common/models/response/billingHistoryResponse"; +import { BillingPaymentResponse } from "jslib-common/models/response/billingPaymentResponse"; +import { + OrganizationConnectionConfigApis, + OrganizationConnectionResponse, +} from "jslib-common/models/response/organizationConnectionResponse"; +import { SsoPreValidateResponse } from "jslib-common/models/response/ssoPreValidateResponse"; + +import { ApiService as ApiServiceAbstraction } from "../abstractions/api.service"; +import { EnvironmentService } from "../abstractions/environment.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; +import { TokenService } from "../abstractions/token.service"; +import { DeviceType } from "../enums/deviceType"; +import { PolicyType } from "../enums/policyType"; +import { Utils } from "../misc/utils"; +import { SetKeyConnectorKeyRequest } from "../models/request/account/setKeyConnectorKeyRequest"; +import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest"; +import { AttachmentRequest } from "../models/request/attachmentRequest"; +import { BitPayInvoiceRequest } from "../models/request/bitPayInvoiceRequest"; +import { CipherBulkDeleteRequest } from "../models/request/cipherBulkDeleteRequest"; +import { CipherBulkMoveRequest } from "../models/request/cipherBulkMoveRequest"; +import { CipherBulkShareRequest } from "../models/request/cipherBulkShareRequest"; +import { CipherCollectionsRequest } from "../models/request/cipherCollectionsRequest"; +import { CipherCreateRequest } from "../models/request/cipherCreateRequest"; +import { CipherRequest } from "../models/request/cipherRequest"; +import { CipherShareRequest } from "../models/request/cipherShareRequest"; +import { CollectionRequest } from "../models/request/collectionRequest"; +import { DeleteRecoverRequest } from "../models/request/deleteRecoverRequest"; +import { EmailRequest } from "../models/request/emailRequest"; +import { EmailTokenRequest } from "../models/request/emailTokenRequest"; +import { EmergencyAccessAcceptRequest } from "../models/request/emergencyAccessAcceptRequest"; +import { EmergencyAccessConfirmRequest } from "../models/request/emergencyAccessConfirmRequest"; +import { EmergencyAccessInviteRequest } from "../models/request/emergencyAccessInviteRequest"; +import { EmergencyAccessPasswordRequest } from "../models/request/emergencyAccessPasswordRequest"; +import { EmergencyAccessUpdateRequest } from "../models/request/emergencyAccessUpdateRequest"; +import { EventRequest } from "../models/request/eventRequest"; +import { FolderRequest } from "../models/request/folderRequest"; +import { GroupRequest } from "../models/request/groupRequest"; +import { IapCheckRequest } from "../models/request/iapCheckRequest"; +import { ApiTokenRequest } from "../models/request/identityToken/apiTokenRequest"; +import { PasswordTokenRequest } from "../models/request/identityToken/passwordTokenRequest"; +import { SsoTokenRequest } from "../models/request/identityToken/ssoTokenRequest"; +import { ImportCiphersRequest } from "../models/request/importCiphersRequest"; +import { ImportDirectoryRequest } from "../models/request/importDirectoryRequest"; +import { ImportOrganizationCiphersRequest } from "../models/request/importOrganizationCiphersRequest"; +import { KdfRequest } from "../models/request/kdfRequest"; +import { KeyConnectorUserKeyRequest } from "../models/request/keyConnectorUserKeyRequest"; +import { KeysRequest } from "../models/request/keysRequest"; +import { OrganizationSponsorshipCreateRequest } from "../models/request/organization/organizationSponsorshipCreateRequest"; +import { OrganizationSponsorshipRedeemRequest } from "../models/request/organization/organizationSponsorshipRedeemRequest"; +import { OrganizationSsoRequest } from "../models/request/organization/organizationSsoRequest"; +import { OrganizationApiKeyRequest } from "../models/request/organizationApiKeyRequest"; +import { OrganizationCreateRequest } from "../models/request/organizationCreateRequest"; +import { OrganizationImportRequest } from "../models/request/organizationImportRequest"; +import { OrganizationKeysRequest } from "../models/request/organizationKeysRequest"; +import { OrganizationSubscriptionUpdateRequest } from "../models/request/organizationSubscriptionUpdateRequest"; +import { OrganizationTaxInfoUpdateRequest } from "../models/request/organizationTaxInfoUpdateRequest"; +import { OrganizationUpdateRequest } from "../models/request/organizationUpdateRequest"; +import { OrganizationUpgradeRequest } from "../models/request/organizationUpgradeRequest"; +import { OrganizationUserAcceptRequest } from "../models/request/organizationUserAcceptRequest"; +import { OrganizationUserBulkConfirmRequest } from "../models/request/organizationUserBulkConfirmRequest"; +import { OrganizationUserBulkRequest } from "../models/request/organizationUserBulkRequest"; +import { OrganizationUserConfirmRequest } from "../models/request/organizationUserConfirmRequest"; +import { OrganizationUserInviteRequest } from "../models/request/organizationUserInviteRequest"; +import { OrganizationUserResetPasswordEnrollmentRequest } from "../models/request/organizationUserResetPasswordEnrollmentRequest"; +import { OrganizationUserResetPasswordRequest } from "../models/request/organizationUserResetPasswordRequest"; +import { OrganizationUserUpdateGroupsRequest } from "../models/request/organizationUserUpdateGroupsRequest"; +import { OrganizationUserUpdateRequest } from "../models/request/organizationUserUpdateRequest"; +import { PasswordHintRequest } from "../models/request/passwordHintRequest"; +import { PasswordRequest } from "../models/request/passwordRequest"; +import { PaymentRequest } from "../models/request/paymentRequest"; +import { PolicyRequest } from "../models/request/policyRequest"; +import { PreloginRequest } from "../models/request/preloginRequest"; +import { ProviderAddOrganizationRequest } from "../models/request/provider/providerAddOrganizationRequest"; +import { ProviderOrganizationCreateRequest } from "../models/request/provider/providerOrganizationCreateRequest"; +import { ProviderSetupRequest } from "../models/request/provider/providerSetupRequest"; +import { ProviderUpdateRequest } from "../models/request/provider/providerUpdateRequest"; +import { ProviderUserAcceptRequest } from "../models/request/provider/providerUserAcceptRequest"; +import { ProviderUserBulkConfirmRequest } from "../models/request/provider/providerUserBulkConfirmRequest"; +import { ProviderUserBulkRequest } from "../models/request/provider/providerUserBulkRequest"; +import { ProviderUserConfirmRequest } from "../models/request/provider/providerUserConfirmRequest"; +import { ProviderUserInviteRequest } from "../models/request/provider/providerUserInviteRequest"; +import { ProviderUserUpdateRequest } from "../models/request/provider/providerUserUpdateRequest"; +import { RegisterRequest } from "../models/request/registerRequest"; +import { SeatRequest } from "../models/request/seatRequest"; +import { SecretVerificationRequest } from "../models/request/secretVerificationRequest"; +import { SelectionReadOnlyRequest } from "../models/request/selectionReadOnlyRequest"; +import { SendAccessRequest } from "../models/request/sendAccessRequest"; +import { SendRequest } from "../models/request/sendRequest"; +import { SetPasswordRequest } from "../models/request/setPasswordRequest"; +import { StorageRequest } from "../models/request/storageRequest"; +import { TaxInfoUpdateRequest } from "../models/request/taxInfoUpdateRequest"; +import { TwoFactorEmailRequest } from "../models/request/twoFactorEmailRequest"; +import { TwoFactorProviderRequest } from "../models/request/twoFactorProviderRequest"; +import { TwoFactorRecoveryRequest } from "../models/request/twoFactorRecoveryRequest"; +import { UpdateDomainsRequest } from "../models/request/updateDomainsRequest"; +import { UpdateKeyRequest } from "../models/request/updateKeyRequest"; +import { UpdateProfileRequest } from "../models/request/updateProfileRequest"; +import { UpdateTempPasswordRequest } from "../models/request/updateTempPasswordRequest"; +import { UpdateTwoFactorAuthenticatorRequest } from "../models/request/updateTwoFactorAuthenticatorRequest"; +import { UpdateTwoFactorDuoRequest } from "../models/request/updateTwoFactorDuoRequest"; +import { UpdateTwoFactorEmailRequest } from "../models/request/updateTwoFactorEmailRequest"; +import { UpdateTwoFactorWebAuthnDeleteRequest } from "../models/request/updateTwoFactorWebAuthnDeleteRequest"; +import { UpdateTwoFactorWebAuthnRequest } from "../models/request/updateTwoFactorWebAuthnRequest"; +import { UpdateTwoFactorYubioOtpRequest } from "../models/request/updateTwoFactorYubioOtpRequest"; +import { VerifyBankRequest } from "../models/request/verifyBankRequest"; +import { VerifyDeleteRecoverRequest } from "../models/request/verifyDeleteRecoverRequest"; +import { VerifyEmailRequest } from "../models/request/verifyEmailRequest"; +import { ApiKeyResponse } from "../models/response/apiKeyResponse"; +import { AttachmentResponse } from "../models/response/attachmentResponse"; +import { AttachmentUploadDataResponse } from "../models/response/attachmentUploadDataResponse"; +import { BillingResponse } from "../models/response/billingResponse"; +import { BreachAccountResponse } from "../models/response/breachAccountResponse"; +import { CipherResponse } from "../models/response/cipherResponse"; +import { + CollectionGroupDetailsResponse, + CollectionResponse, +} from "../models/response/collectionResponse"; +import { DomainsResponse } from "../models/response/domainsResponse"; +import { + EmergencyAccessGranteeDetailsResponse, + EmergencyAccessGrantorDetailsResponse, + EmergencyAccessTakeoverResponse, + EmergencyAccessViewResponse, +} from "../models/response/emergencyAccessResponse"; +import { ErrorResponse } from "../models/response/errorResponse"; +import { EventResponse } from "../models/response/eventResponse"; +import { FolderResponse } from "../models/response/folderResponse"; +import { GroupDetailsResponse, GroupResponse } from "../models/response/groupResponse"; +import { IdentityCaptchaResponse } from "../models/response/identityCaptchaResponse"; +import { IdentityTokenResponse } from "../models/response/identityTokenResponse"; +import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse"; +import { KeyConnectorUserKeyResponse } from "../models/response/keyConnectorUserKeyResponse"; +import { ListResponse } from "../models/response/listResponse"; +import { OrganizationSsoResponse } from "../models/response/organization/organizationSsoResponse"; +import { OrganizationApiKeyInformationResponse } from "../models/response/organizationApiKeyInformationResponse"; +import { OrganizationAutoEnrollStatusResponse } from "../models/response/organizationAutoEnrollStatusResponse"; +import { OrganizationKeysResponse } from "../models/response/organizationKeysResponse"; +import { OrganizationResponse } from "../models/response/organizationResponse"; +import { OrganizationSponsorshipSyncStatusResponse } from "../models/response/organizationSponsorshipSyncStatusResponse"; +import { OrganizationSubscriptionResponse } from "../models/response/organizationSubscriptionResponse"; +import { OrganizationUserBulkPublicKeyResponse } from "../models/response/organizationUserBulkPublicKeyResponse"; +import { OrganizationUserBulkResponse } from "../models/response/organizationUserBulkResponse"; +import { + OrganizationUserDetailsResponse, + OrganizationUserResetPasswordDetailsReponse, + OrganizationUserUserDetailsResponse, +} from "../models/response/organizationUserResponse"; +import { PaymentResponse } from "../models/response/paymentResponse"; +import { PlanResponse } from "../models/response/planResponse"; +import { PolicyResponse } from "../models/response/policyResponse"; +import { PreloginResponse } from "../models/response/preloginResponse"; +import { ProfileResponse } from "../models/response/profileResponse"; +import { + ProviderOrganizationOrganizationDetailsResponse, + ProviderOrganizationResponse, +} from "../models/response/provider/providerOrganizationResponse"; +import { ProviderResponse } from "../models/response/provider/providerResponse"; +import { ProviderUserBulkPublicKeyResponse } from "../models/response/provider/providerUserBulkPublicKeyResponse"; +import { ProviderUserBulkResponse } from "../models/response/provider/providerUserBulkResponse"; +import { + ProviderUserResponse, + ProviderUserUserDetailsResponse, +} from "../models/response/provider/providerUserResponse"; +import { SelectionReadOnlyResponse } from "../models/response/selectionReadOnlyResponse"; +import { SendAccessResponse } from "../models/response/sendAccessResponse"; +import { SendFileDownloadDataResponse } from "../models/response/sendFileDownloadDataResponse"; +import { SendFileUploadDataResponse } from "../models/response/sendFileUploadDataResponse"; +import { SendResponse } from "../models/response/sendResponse"; +import { SubscriptionResponse } from "../models/response/subscriptionResponse"; +import { SyncResponse } from "../models/response/syncResponse"; +import { TaxInfoResponse } from "../models/response/taxInfoResponse"; +import { TaxRateResponse } from "../models/response/taxRateResponse"; +import { TwoFactorAuthenticatorResponse } from "../models/response/twoFactorAuthenticatorResponse"; +import { TwoFactorDuoResponse } from "../models/response/twoFactorDuoResponse"; +import { TwoFactorEmailResponse } from "../models/response/twoFactorEmailResponse"; +import { TwoFactorProviderResponse } from "../models/response/twoFactorProviderResponse"; +import { TwoFactorRecoverResponse } from "../models/response/twoFactorRescoverResponse"; +import { + TwoFactorWebAuthnResponse, + ChallengeResponse, +} from "../models/response/twoFactorWebAuthnResponse"; +import { TwoFactorYubiKeyResponse } from "../models/response/twoFactorYubiKeyResponse"; +import { UserKeyResponse } from "../models/response/userKeyResponse"; +import { SendAccessView } from "../models/view/sendAccessView"; + +export class ApiService implements ApiServiceAbstraction { + private device: DeviceType; + private deviceType: string; + private isWebClient = false; + private isDesktopClient = false; + + constructor( + private tokenService: TokenService, + private platformUtilsService: PlatformUtilsService, + private environmentService: EnvironmentService, + private appIdService: AppIdService, + private logoutCallback: (expired: boolean) => Promise, + private customUserAgent: string = null + ) { + this.device = platformUtilsService.getDevice(); + this.deviceType = this.device.toString(); + this.isWebClient = + this.device === DeviceType.IEBrowser || + this.device === DeviceType.ChromeBrowser || + this.device === DeviceType.EdgeBrowser || + this.device === DeviceType.FirefoxBrowser || + this.device === DeviceType.OperaBrowser || + this.device === DeviceType.SafariBrowser || + this.device === DeviceType.UnknownBrowser || + this.device === DeviceType.VivaldiBrowser; + this.isDesktopClient = + this.device === DeviceType.WindowsDesktop || + this.device === DeviceType.MacOsDesktop || + this.device === DeviceType.LinuxDesktop; + } + + // Auth APIs + + async postIdentityToken( + request: ApiTokenRequest | PasswordTokenRequest | SsoTokenRequest + ): Promise { + const headers = new Headers({ + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + Accept: "application/json", + "Device-Type": this.deviceType, + }); + if (this.customUserAgent != null) { + headers.set("User-Agent", this.customUserAgent); + } + request.alterIdentityTokenHeaders(headers); + + const identityToken = + request instanceof ApiTokenRequest + ? request.toIdentityToken() + : request.toIdentityToken(this.platformUtilsService.getClientType()); + + const response = await this.fetch( + new Request(this.environmentService.getIdentityUrl() + "/connect/token", { + body: this.qsStringify(identityToken), + credentials: this.getCredentials(), + cache: "no-store", + headers: headers, + method: "POST", + }) + ); + + let responseJson: any = null; + if (this.isJsonResponse(response)) { + responseJson = await response.json(); + } + + if (responseJson != null) { + if (response.status === 200) { + return new IdentityTokenResponse(responseJson); + } else if ( + response.status === 400 && + responseJson.TwoFactorProviders2 && + Object.keys(responseJson.TwoFactorProviders2).length + ) { + await this.tokenService.clearTwoFactorToken(); + return new IdentityTwoFactorResponse(responseJson); + } else if ( + response.status === 400 && + responseJson.HCaptcha_SiteKey && + Object.keys(responseJson.HCaptcha_SiteKey).length + ) { + return new IdentityCaptchaResponse(responseJson); + } + } + + return Promise.reject(new ErrorResponse(responseJson, response.status, true)); + } + + async refreshIdentityToken(): Promise { + try { + await this.doAuthRefresh(); + } catch (e) { + return Promise.reject(null); + } + } + + // Account APIs + + async getProfile(): Promise { + const r = await this.send("GET", "/accounts/profile", null, true, true); + return new ProfileResponse(r); + } + + async getUserSubscription(): Promise { + const r = await this.send("GET", "/accounts/subscription", null, true, true); + return new SubscriptionResponse(r); + } + + async getTaxInfo(): Promise { + const r = await this.send("GET", "/accounts/tax", null, true, true); + return new TaxInfoResponse(r); + } + + async putProfile(request: UpdateProfileRequest): Promise { + const r = await this.send("PUT", "/accounts/profile", request, true, true); + return new ProfileResponse(r); + } + + putTaxInfo(request: TaxInfoUpdateRequest): Promise { + return this.send("PUT", "/accounts/tax", request, true, false); + } + + async postPrelogin(request: PreloginRequest): Promise { + const r = await this.send( + "POST", + "/accounts/prelogin", + request, + false, + true, + this.platformUtilsService.isDev() + ? this.environmentService.getIdentityUrl() + : this.environmentService.getApiUrl() + ); + return new PreloginResponse(r); + } + + postEmailToken(request: EmailTokenRequest): Promise { + return this.send("POST", "/accounts/email-token", request, true, false); + } + + postEmail(request: EmailRequest): Promise { + return this.send("POST", "/accounts/email", request, true, false); + } + + postPassword(request: PasswordRequest): Promise { + return this.send("POST", "/accounts/password", request, true, false); + } + + setPassword(request: SetPasswordRequest): Promise { + return this.send("POST", "/accounts/set-password", request, true, false); + } + + postSetKeyConnectorKey(request: SetKeyConnectorKeyRequest): Promise { + return this.send("POST", "/accounts/set-key-connector-key", request, true, false); + } + + postSecurityStamp(request: SecretVerificationRequest): Promise { + return this.send("POST", "/accounts/security-stamp", request, true, false); + } + + deleteAccount(request: SecretVerificationRequest): Promise { + return this.send("DELETE", "/accounts", request, true, false); + } + + async getAccountRevisionDate(): Promise { + const r = await this.send("GET", "/accounts/revision-date", null, true, true); + return r as number; + } + + postPasswordHint(request: PasswordHintRequest): Promise { + return this.send("POST", "/accounts/password-hint", request, false, false); + } + + postRegister(request: RegisterRequest): Promise { + return this.send( + "POST", + "/accounts/register", + request, + false, + false, + this.platformUtilsService.isDev() + ? this.environmentService.getIdentityUrl() + : this.environmentService.getApiUrl() + ); + } + + async postPremium(data: FormData): Promise { + const r = await this.send("POST", "/accounts/premium", data, true, true); + return new PaymentResponse(r); + } + + async postIapCheck(request: IapCheckRequest): Promise { + return this.send("POST", "/accounts/iap-check", request, true, false); + } + + postReinstatePremium(): Promise { + return this.send("POST", "/accounts/reinstate-premium", null, true, false); + } + + postCancelPremium(): Promise { + return this.send("POST", "/accounts/cancel-premium", null, true, false); + } + + async postAccountStorage(request: StorageRequest): Promise { + const r = await this.send("POST", "/accounts/storage", request, true, true); + return new PaymentResponse(r); + } + + postAccountPayment(request: PaymentRequest): Promise { + return this.send("POST", "/accounts/payment", request, true, false); + } + + postAccountLicense(data: FormData): Promise { + return this.send("POST", "/accounts/license", data, true, false); + } + + postAccountKeys(request: KeysRequest): Promise { + return this.send("POST", "/accounts/keys", request, true, false); + } + + postAccountKey(request: UpdateKeyRequest): Promise { + return this.send("POST", "/accounts/key", request, true, false); + } + + postAccountVerifyEmail(): Promise { + return this.send("POST", "/accounts/verify-email", null, true, false); + } + + postAccountVerifyEmailToken(request: VerifyEmailRequest): Promise { + return this.send("POST", "/accounts/verify-email-token", request, false, false); + } + + postAccountVerifyPassword(request: SecretVerificationRequest): Promise { + return this.send("POST", "/accounts/verify-password", request, true, false); + } + + postAccountRecoverDelete(request: DeleteRecoverRequest): Promise { + return this.send("POST", "/accounts/delete-recover", request, false, false); + } + + postAccountRecoverDeleteToken(request: VerifyDeleteRecoverRequest): Promise { + return this.send("POST", "/accounts/delete-recover-token", request, false, false); + } + + postAccountKdf(request: KdfRequest): Promise { + return this.send("POST", "/accounts/kdf", request, true, false); + } + + async deleteSsoUser(organizationId: string): Promise { + return this.send("DELETE", "/accounts/sso/" + organizationId, null, true, false); + } + + async getSsoUserIdentifier(): Promise { + return this.send("GET", "/accounts/sso/user-identifier", null, true, true); + } + + async postUserApiKey(id: string, request: SecretVerificationRequest): Promise { + const r = await this.send("POST", "/accounts/api-key", request, true, true); + return new ApiKeyResponse(r); + } + + async postUserRotateApiKey( + id: string, + request: SecretVerificationRequest + ): Promise { + const r = await this.send("POST", "/accounts/rotate-api-key", request, true, true); + return new ApiKeyResponse(r); + } + + putUpdateTempPassword(request: UpdateTempPasswordRequest): Promise { + return this.send("PUT", "/accounts/update-temp-password", request, true, false); + } + + postAccountRequestOTP(): Promise { + return this.send("POST", "/accounts/request-otp", null, true, false); + } + + postAccountVerifyOTP(request: VerifyOTPRequest): Promise { + return this.send("POST", "/accounts/verify-otp", request, true, false); + } + + postConvertToKeyConnector(): Promise { + return this.send("POST", "/accounts/convert-to-key-connector", null, true, false); + } + + // Account Billing APIs + + async getUserBillingHistory(): Promise { + const r = await this.send("GET", "/accounts/billing/history", null, true, true); + return new BillingHistoryResponse(r); + } + + async getUserBillingPayment(): Promise { + const r = await this.send("GET", "/accounts/billing/payment-method", null, true, true); + return new BillingPaymentResponse(r); + } + + // Folder APIs + + async getFolder(id: string): Promise { + const r = await this.send("GET", "/folders/" + id, null, true, true); + return new FolderResponse(r); + } + + async postFolder(request: FolderRequest): Promise { + const r = await this.send("POST", "/folders", request, true, true); + return new FolderResponse(r); + } + + async putFolder(id: string, request: FolderRequest): Promise { + const r = await this.send("PUT", "/folders/" + id, request, true, true); + return new FolderResponse(r); + } + + deleteFolder(id: string): Promise { + return this.send("DELETE", "/folders/" + id, null, true, false); + } + + // Send APIs + + async getSend(id: string): Promise { + const r = await this.send("GET", "/sends/" + id, null, true, true); + return new SendResponse(r); + } + + async postSendAccess( + id: string, + request: SendAccessRequest, + apiUrl?: string + ): Promise { + const addSendIdHeader = (headers: Headers) => { + headers.set("Send-Id", id); + }; + const r = await this.send( + "POST", + "/sends/access/" + id, + request, + false, + true, + apiUrl, + addSendIdHeader + ); + return new SendAccessResponse(r); + } + + async getSendFileDownloadData( + send: SendAccessView, + request: SendAccessRequest, + apiUrl?: string + ): Promise { + const addSendIdHeader = (headers: Headers) => { + headers.set("Send-Id", send.id); + }; + const r = await this.send( + "POST", + "/sends/" + send.id + "/access/file/" + send.file.id, + request, + false, + true, + apiUrl, + addSendIdHeader + ); + return new SendFileDownloadDataResponse(r); + } + + async getSends(): Promise> { + const r = await this.send("GET", "/sends", null, true, true); + return new ListResponse(r, SendResponse); + } + + async postSend(request: SendRequest): Promise { + const r = await this.send("POST", "/sends", request, true, true); + return new SendResponse(r); + } + + async postFileTypeSend(request: SendRequest): Promise { + const r = await this.send("POST", "/sends/file/v2", request, true, true); + return new SendFileUploadDataResponse(r); + } + + async renewSendFileUploadUrl( + sendId: string, + fileId: string + ): Promise { + const r = await this.send("GET", "/sends/" + sendId + "/file/" + fileId, null, true, true); + return new SendFileUploadDataResponse(r); + } + + postSendFile(sendId: string, fileId: string, data: FormData): Promise { + return this.send("POST", "/sends/" + sendId + "/file/" + fileId, data, true, false); + } + + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + async postSendFileLegacy(data: FormData): Promise { + const r = await this.send("POST", "/sends/file", data, true, true); + return new SendResponse(r); + } + + async putSend(id: string, request: SendRequest): Promise { + const r = await this.send("PUT", "/sends/" + id, request, true, true); + return new SendResponse(r); + } + + async putSendRemovePassword(id: string): Promise { + const r = await this.send("PUT", "/sends/" + id + "/remove-password", null, true, true); + return new SendResponse(r); + } + + deleteSend(id: string): Promise { + return this.send("DELETE", "/sends/" + id, null, true, false); + } + + // Cipher APIs + + async getCipher(id: string): Promise { + const r = await this.send("GET", "/ciphers/" + id, null, true, true); + return new CipherResponse(r); + } + + async getCipherAdmin(id: string): Promise { + const r = await this.send("GET", "/ciphers/" + id + "/admin", null, true, true); + return new CipherResponse(r); + } + + async getCiphersOrganization(organizationId: string): Promise> { + const r = await this.send( + "GET", + "/ciphers/organization-details?organizationId=" + organizationId, + null, + true, + true + ); + return new ListResponse(r, CipherResponse); + } + + async postCipher(request: CipherRequest): Promise { + const r = await this.send("POST", "/ciphers", request, true, true); + return new CipherResponse(r); + } + + async postCipherCreate(request: CipherCreateRequest): Promise { + const r = await this.send("POST", "/ciphers/create", request, true, true); + return new CipherResponse(r); + } + + async postCipherAdmin(request: CipherCreateRequest): Promise { + const r = await this.send("POST", "/ciphers/admin", request, true, true); + return new CipherResponse(r); + } + + async putCipher(id: string, request: CipherRequest): Promise { + const r = await this.send("PUT", "/ciphers/" + id, request, true, true); + return new CipherResponse(r); + } + + async putCipherAdmin(id: string, request: CipherRequest): Promise { + const r = await this.send("PUT", "/ciphers/" + id + "/admin", request, true, true); + return new CipherResponse(r); + } + + deleteCipher(id: string): Promise { + return this.send("DELETE", "/ciphers/" + id, null, true, false); + } + + deleteCipherAdmin(id: string): Promise { + return this.send("DELETE", "/ciphers/" + id + "/admin", null, true, false); + } + + deleteManyCiphers(request: CipherBulkDeleteRequest): Promise { + return this.send("DELETE", "/ciphers", request, true, false); + } + + deleteManyCiphersAdmin(request: CipherBulkDeleteRequest): Promise { + return this.send("DELETE", "/ciphers/admin", request, true, false); + } + + putMoveCiphers(request: CipherBulkMoveRequest): Promise { + return this.send("PUT", "/ciphers/move", request, true, false); + } + + async putShareCipher(id: string, request: CipherShareRequest): Promise { + const r = await this.send("PUT", "/ciphers/" + id + "/share", request, true, true); + return new CipherResponse(r); + } + + putShareCiphers(request: CipherBulkShareRequest): Promise { + return this.send("PUT", "/ciphers/share", request, true, false); + } + + putCipherCollections(id: string, request: CipherCollectionsRequest): Promise { + return this.send("PUT", "/ciphers/" + id + "/collections", request, true, false); + } + + putCipherCollectionsAdmin(id: string, request: CipherCollectionsRequest): Promise { + return this.send("PUT", "/ciphers/" + id + "/collections-admin", request, true, false); + } + + postPurgeCiphers( + request: SecretVerificationRequest, + organizationId: string = null + ): Promise { + let path = "/ciphers/purge"; + if (organizationId != null) { + path += "?organizationId=" + organizationId; + } + return this.send("POST", path, request, true, false); + } + + postImportCiphers(request: ImportCiphersRequest): Promise { + return this.send("POST", "/ciphers/import", request, true, false); + } + + postImportOrganizationCiphers( + organizationId: string, + request: ImportOrganizationCiphersRequest + ): Promise { + return this.send( + "POST", + "/ciphers/import-organization?organizationId=" + organizationId, + request, + true, + false + ); + } + + putDeleteCipher(id: string): Promise { + return this.send("PUT", "/ciphers/" + id + "/delete", null, true, false); + } + + putDeleteCipherAdmin(id: string): Promise { + return this.send("PUT", "/ciphers/" + id + "/delete-admin", null, true, false); + } + + putDeleteManyCiphers(request: CipherBulkDeleteRequest): Promise { + return this.send("PUT", "/ciphers/delete", request, true, false); + } + + putDeleteManyCiphersAdmin(request: CipherBulkDeleteRequest): Promise { + return this.send("PUT", "/ciphers/delete-admin", request, true, false); + } + + async putRestoreCipher(id: string): Promise { + const r = await this.send("PUT", "/ciphers/" + id + "/restore", null, true, true); + return new CipherResponse(r); + } + + async putRestoreCipherAdmin(id: string): Promise { + const r = await this.send("PUT", "/ciphers/" + id + "/restore-admin", null, true, true); + return new CipherResponse(r); + } + + async putRestoreManyCiphers( + request: CipherBulkDeleteRequest + ): Promise> { + const r = await this.send("PUT", "/ciphers/restore", request, true, true); + return new ListResponse(r, CipherResponse); + } + + // Attachments APIs + + async getAttachmentData( + cipherId: string, + attachmentId: string, + emergencyAccessId?: string + ): Promise { + const path = + (emergencyAccessId != null ? "/emergency-access/" + emergencyAccessId + "/" : "/ciphers/") + + cipherId + + "/attachment/" + + attachmentId; + const r = await this.send("GET", path, null, true, true); + return new AttachmentResponse(r); + } + + async postCipherAttachment( + id: string, + request: AttachmentRequest + ): Promise { + const r = await this.send("POST", "/ciphers/" + id + "/attachment/v2", request, true, true); + return new AttachmentUploadDataResponse(r); + } + + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + async postCipherAttachmentLegacy(id: string, data: FormData): Promise { + const r = await this.send("POST", "/ciphers/" + id + "/attachment", data, true, true); + return new CipherResponse(r); + } + + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + async postCipherAttachmentAdminLegacy(id: string, data: FormData): Promise { + const r = await this.send("POST", "/ciphers/" + id + "/attachment-admin", data, true, true); + return new CipherResponse(r); + } + + deleteCipherAttachment(id: string, attachmentId: string): Promise { + return this.send("DELETE", "/ciphers/" + id + "/attachment/" + attachmentId, null, true, false); + } + + deleteCipherAttachmentAdmin(id: string, attachmentId: string): Promise { + return this.send( + "DELETE", + "/ciphers/" + id + "/attachment/" + attachmentId + "/admin", + null, + true, + false + ); + } + + postShareCipherAttachment( + id: string, + attachmentId: string, + data: FormData, + organizationId: string + ): Promise { + return this.send( + "POST", + "/ciphers/" + id + "/attachment/" + attachmentId + "/share?organizationId=" + organizationId, + data, + true, + false + ); + } + + async renewAttachmentUploadUrl( + id: string, + attachmentId: string + ): Promise { + const r = await this.send( + "GET", + "/ciphers/" + id + "/attachment/" + attachmentId + "/renew", + null, + true, + true + ); + return new AttachmentUploadDataResponse(r); + } + + postAttachmentFile(id: string, attachmentId: string, data: FormData): Promise { + return this.send("POST", "/ciphers/" + id + "/attachment/" + attachmentId, data, true, false); + } + + // Collections APIs + + async getCollectionDetails( + organizationId: string, + id: string + ): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/collections/" + id + "/details", + null, + true, + true + ); + return new CollectionGroupDetailsResponse(r); + } + + async getUserCollections(): Promise> { + const r = await this.send("GET", "/collections", null, true, true); + return new ListResponse(r, CollectionResponse); + } + + async getCollections(organizationId: string): Promise> { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/collections", + null, + true, + true + ); + return new ListResponse(r, CollectionResponse); + } + + async getCollectionUsers( + organizationId: string, + id: string + ): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/collections/" + id + "/users", + null, + true, + true + ); + return r.map((dr: any) => new SelectionReadOnlyResponse(dr)); + } + + async postCollection( + organizationId: string, + request: CollectionRequest + ): Promise { + const r = await this.send( + "POST", + "/organizations/" + organizationId + "/collections", + request, + true, + true + ); + return new CollectionResponse(r); + } + + async putCollection( + organizationId: string, + id: string, + request: CollectionRequest + ): Promise { + const r = await this.send( + "PUT", + "/organizations/" + organizationId + "/collections/" + id, + request, + true, + true + ); + return new CollectionResponse(r); + } + + async putCollectionUsers( + organizationId: string, + id: string, + request: SelectionReadOnlyRequest[] + ): Promise { + await this.send( + "PUT", + "/organizations/" + organizationId + "/collections/" + id + "/users", + request, + true, + false + ); + } + + deleteCollection(organizationId: string, id: string): Promise { + return this.send( + "DELETE", + "/organizations/" + organizationId + "/collections/" + id, + null, + true, + false + ); + } + + deleteCollectionUser( + organizationId: string, + id: string, + organizationUserId: string + ): Promise { + return this.send( + "DELETE", + "/organizations/" + organizationId + "/collections/" + id + "/user/" + organizationUserId, + null, + true, + false + ); + } + + // Groups APIs + + async getGroupDetails(organizationId: string, id: string): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/groups/" + id + "/details", + null, + true, + true + ); + return new GroupDetailsResponse(r); + } + + async getGroups(organizationId: string): Promise> { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/groups", + null, + true, + true + ); + return new ListResponse(r, GroupResponse); + } + + async getGroupUsers(organizationId: string, id: string): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/groups/" + id + "/users", + null, + true, + true + ); + return r; + } + + async postGroup(organizationId: string, request: GroupRequest): Promise { + const r = await this.send( + "POST", + "/organizations/" + organizationId + "/groups", + request, + true, + true + ); + return new GroupResponse(r); + } + + async putGroup( + organizationId: string, + id: string, + request: GroupRequest + ): Promise { + const r = await this.send( + "PUT", + "/organizations/" + organizationId + "/groups/" + id, + request, + true, + true + ); + return new GroupResponse(r); + } + + async putGroupUsers(organizationId: string, id: string, request: string[]): Promise { + await this.send( + "PUT", + "/organizations/" + organizationId + "/groups/" + id + "/users", + request, + true, + false + ); + } + + deleteGroup(organizationId: string, id: string): Promise { + return this.send( + "DELETE", + "/organizations/" + organizationId + "/groups/" + id, + null, + true, + false + ); + } + + deleteGroupUser(organizationId: string, id: string, organizationUserId: string): Promise { + return this.send( + "DELETE", + "/organizations/" + organizationId + "/groups/" + id + "/user/" + organizationUserId, + null, + true, + false + ); + } + + // Policy APIs + + async getPolicy(organizationId: string, type: PolicyType): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/policies/" + type, + null, + true, + true + ); + return new PolicyResponse(r); + } + + async getPolicies(organizationId: string): Promise> { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/policies", + null, + true, + true + ); + return new ListResponse(r, PolicyResponse); + } + + async getPoliciesByToken( + organizationId: string, + token: string, + email: string, + organizationUserId: string + ): Promise> { + const r = await this.send( + "GET", + "/organizations/" + + organizationId + + "/policies/token?" + + "token=" + + encodeURIComponent(token) + + "&email=" + + encodeURIComponent(email) + + "&organizationUserId=" + + organizationUserId, + null, + false, + true + ); + return new ListResponse(r, PolicyResponse); + } + + async getPoliciesByInvitedUser( + organizationId: string, + userId: string + ): Promise> { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/policies/invited-user?" + "userId=" + userId, + null, + false, + true + ); + return new ListResponse(r, PolicyResponse); + } + + async putPolicy( + organizationId: string, + type: PolicyType, + request: PolicyRequest + ): Promise { + const r = await this.send( + "PUT", + "/organizations/" + organizationId + "/policies/" + type, + request, + true, + true + ); + return new PolicyResponse(r); + } + + // Organization User APIs + + async getOrganizationUser( + organizationId: string, + id: string + ): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/users/" + id, + null, + true, + true + ); + return new OrganizationUserDetailsResponse(r); + } + + async getOrganizationUserGroups(organizationId: string, id: string): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/users/" + id + "/groups", + null, + true, + true + ); + return r; + } + + async getOrganizationUsers( + organizationId: string + ): Promise> { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/users", + null, + true, + true + ); + return new ListResponse(r, OrganizationUserUserDetailsResponse); + } + + async getOrganizationUserResetPasswordDetails( + organizationId: string, + id: string + ): Promise { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/users/" + id + "/reset-password-details", + null, + true, + true + ); + return new OrganizationUserResetPasswordDetailsReponse(r); + } + + async getOrganizationAutoEnrollStatus( + identifier: string + ): Promise { + const r = await this.send( + "GET", + "/organizations/" + identifier + "/auto-enroll-status", + null, + true, + true + ); + return new OrganizationAutoEnrollStatusResponse(r); + } + + postOrganizationUserInvite( + organizationId: string, + request: OrganizationUserInviteRequest + ): Promise { + return this.send( + "POST", + "/organizations/" + organizationId + "/users/invite", + request, + true, + false + ); + } + + postOrganizationUserReinvite(organizationId: string, id: string): Promise { + return this.send( + "POST", + "/organizations/" + organizationId + "/users/" + id + "/reinvite", + null, + true, + false + ); + } + + async postManyOrganizationUserReinvite( + organizationId: string, + request: OrganizationUserBulkRequest + ): Promise> { + const r = await this.send( + "POST", + "/organizations/" + organizationId + "/users/reinvite", + request, + true, + true + ); + return new ListResponse(r, OrganizationUserBulkResponse); + } + + postOrganizationUserAccept( + organizationId: string, + id: string, + request: OrganizationUserAcceptRequest + ): Promise { + return this.send( + "POST", + "/organizations/" + organizationId + "/users/" + id + "/accept", + request, + true, + false + ); + } + + postOrganizationUserConfirm( + organizationId: string, + id: string, + request: OrganizationUserConfirmRequest + ): Promise { + return this.send( + "POST", + "/organizations/" + organizationId + "/users/" + id + "/confirm", + request, + true, + false + ); + } + + async postOrganizationUsersPublicKey( + organizationId: string, + request: OrganizationUserBulkRequest + ): Promise> { + const r = await this.send( + "POST", + "/organizations/" + organizationId + "/users/public-keys", + request, + true, + true + ); + return new ListResponse(r, OrganizationUserBulkPublicKeyResponse); + } + + async postOrganizationUserBulkConfirm( + organizationId: string, + request: OrganizationUserBulkConfirmRequest + ): Promise> { + const r = await this.send( + "POST", + "/organizations/" + organizationId + "/users/confirm", + request, + true, + true + ); + return new ListResponse(r, OrganizationUserBulkResponse); + } + + putOrganizationUser( + organizationId: string, + id: string, + request: OrganizationUserUpdateRequest + ): Promise { + return this.send( + "PUT", + "/organizations/" + organizationId + "/users/" + id, + request, + true, + false + ); + } + + putOrganizationUserGroups( + organizationId: string, + id: string, + request: OrganizationUserUpdateGroupsRequest + ): Promise { + return this.send( + "PUT", + "/organizations/" + organizationId + "/users/" + id + "/groups", + request, + true, + false + ); + } + + putOrganizationUserResetPasswordEnrollment( + organizationId: string, + userId: string, + request: OrganizationUserResetPasswordEnrollmentRequest + ): Promise { + return this.send( + "PUT", + "/organizations/" + organizationId + "/users/" + userId + "/reset-password-enrollment", + request, + true, + false + ); + } + + putOrganizationUserResetPassword( + organizationId: string, + id: string, + request: OrganizationUserResetPasswordRequest + ): Promise { + return this.send( + "PUT", + "/organizations/" + organizationId + "/users/" + id + "/reset-password", + request, + true, + false + ); + } + + deleteOrganizationUser(organizationId: string, id: string): Promise { + return this.send( + "DELETE", + "/organizations/" + organizationId + "/users/" + id, + null, + true, + false + ); + } + + async deleteManyOrganizationUsers( + organizationId: string, + request: OrganizationUserBulkRequest + ): Promise> { + const r = await this.send( + "DELETE", + "/organizations/" + organizationId + "/users", + request, + true, + true + ); + return new ListResponse(r, OrganizationUserBulkResponse); + } + + // Plan APIs + + async getPlans(): Promise> { + const r = await this.send("GET", "/plans/", null, true, true); + return new ListResponse(r, PlanResponse); + } + + async postImportDirectory(organizationId: string, request: ImportDirectoryRequest): Promise { + return this.send("POST", "/organizations/" + organizationId + "/import", request, true, false); + } + + async postPublicImportDirectory(request: OrganizationImportRequest): Promise { + return this.send("POST", "/public/organization/import", request, true, false); + } + + async getTaxRates(): Promise> { + const r = await this.send("GET", "/plans/sales-tax-rates/", null, true, true); + return new ListResponse(r, TaxRateResponse); + } + + // Settings APIs + + async getSettingsDomains(): Promise { + const r = await this.send("GET", "/settings/domains", null, true, true); + return new DomainsResponse(r); + } + + async putSettingsDomains(request: UpdateDomainsRequest): Promise { + const r = await this.send("PUT", "/settings/domains", request, true, true); + return new DomainsResponse(r); + } + + // Sync APIs + + async getSync(): Promise { + const path = this.isDesktopClient || this.isWebClient ? "/sync?excludeDomains=true" : "/sync"; + const r = await this.send("GET", path, null, true, true); + return new SyncResponse(r); + } + + // Two-factor APIs + + async getTwoFactorProviders(): Promise> { + const r = await this.send("GET", "/two-factor", null, true, true); + return new ListResponse(r, TwoFactorProviderResponse); + } + + async getTwoFactorOrganizationProviders( + organizationId: string + ): Promise> { + const r = await this.send( + "GET", + "/organizations/" + organizationId + "/two-factor", + null, + true, + true + ); + return new ListResponse(r, TwoFactorProviderResponse); + } + + async getTwoFactorAuthenticator( + request: SecretVerificationRequest + ): Promise { + const r = await this.send("POST", "/two-factor/get-authenticator", request, true, true); + return new TwoFactorAuthenticatorResponse(r); + } + + async getTwoFactorEmail(request: SecretVerificationRequest): Promise { + const r = await this.send("POST", "/two-factor/get-email", request, true, true); + return new TwoFactorEmailResponse(r); + } + + async getTwoFactorDuo(request: SecretVerificationRequest): Promise { + const r = await this.send("POST", "/two-factor/get-duo", request, true, true); + return new TwoFactorDuoResponse(r); + } + + async getTwoFactorOrganizationDuo( + organizationId: string, + request: SecretVerificationRequest + ): Promise { + const r = await this.send( + "POST", + "/organizations/" + organizationId + "/two-factor/get-duo", + request, + true, + true + ); + return new TwoFactorDuoResponse(r); + } + + async getTwoFactorYubiKey(request: SecretVerificationRequest): Promise { + const r = await this.send("POST", "/two-factor/get-yubikey", request, true, true); + return new TwoFactorYubiKeyResponse(r); + } + + async getTwoFactorWebAuthn( + request: SecretVerificationRequest + ): Promise { + const r = await this.send("POST", "/two-factor/get-webauthn", request, true, true); + return new TwoFactorWebAuthnResponse(r); + } + + async getTwoFactorWebAuthnChallenge( + request: SecretVerificationRequest + ): Promise { + const r = await this.send("POST", "/two-factor/get-webauthn-challenge", request, true, true); + return new ChallengeResponse(r); + } + + async getTwoFactorRecover(request: SecretVerificationRequest): Promise { + const r = await this.send("POST", "/two-factor/get-recover", request, true, true); + return new TwoFactorRecoverResponse(r); + } + + async putTwoFactorAuthenticator( + request: UpdateTwoFactorAuthenticatorRequest + ): Promise { + const r = await this.send("PUT", "/two-factor/authenticator", request, true, true); + return new TwoFactorAuthenticatorResponse(r); + } + + async putTwoFactorEmail(request: UpdateTwoFactorEmailRequest): Promise { + const r = await this.send("PUT", "/two-factor/email", request, true, true); + return new TwoFactorEmailResponse(r); + } + + async putTwoFactorDuo(request: UpdateTwoFactorDuoRequest): Promise { + const r = await this.send("PUT", "/two-factor/duo", request, true, true); + return new TwoFactorDuoResponse(r); + } + + async putTwoFactorOrganizationDuo( + organizationId: string, + request: UpdateTwoFactorDuoRequest + ): Promise { + const r = await this.send( + "PUT", + "/organizations/" + organizationId + "/two-factor/duo", + request, + true, + true + ); + return new TwoFactorDuoResponse(r); + } + + async putTwoFactorYubiKey( + request: UpdateTwoFactorYubioOtpRequest + ): Promise { + const r = await this.send("PUT", "/two-factor/yubikey", request, true, true); + return new TwoFactorYubiKeyResponse(r); + } + + async putTwoFactorWebAuthn( + request: UpdateTwoFactorWebAuthnRequest + ): Promise { + const response = request.deviceResponse.response as AuthenticatorAttestationResponse; + const data: any = Object.assign({}, request); + + data.deviceResponse = { + id: request.deviceResponse.id, + rawId: btoa(request.deviceResponse.id), + type: request.deviceResponse.type, + extensions: request.deviceResponse.getClientExtensionResults(), + response: { + AttestationObject: Utils.fromBufferToB64(response.attestationObject), + clientDataJson: Utils.fromBufferToB64(response.clientDataJSON), + }, + }; + + const r = await this.send("PUT", "/two-factor/webauthn", data, true, true); + return new TwoFactorWebAuthnResponse(r); + } + + async deleteTwoFactorWebAuthn( + request: UpdateTwoFactorWebAuthnDeleteRequest + ): Promise { + const r = await this.send("DELETE", "/two-factor/webauthn", request, true, true); + return new TwoFactorWebAuthnResponse(r); + } + + async putTwoFactorDisable(request: TwoFactorProviderRequest): Promise { + const r = await this.send("PUT", "/two-factor/disable", request, true, true); + return new TwoFactorProviderResponse(r); + } + + async putTwoFactorOrganizationDisable( + organizationId: string, + request: TwoFactorProviderRequest + ): Promise { + const r = await this.send( + "PUT", + "/organizations/" + organizationId + "/two-factor/disable", + request, + true, + true + ); + return new TwoFactorProviderResponse(r); + } + + postTwoFactorRecover(request: TwoFactorRecoveryRequest): Promise { + return this.send("POST", "/two-factor/recover", request, false, false); + } + + postTwoFactorEmailSetup(request: TwoFactorEmailRequest): Promise { + return this.send("POST", "/two-factor/send-email", request, true, false); + } + + postTwoFactorEmail(request: TwoFactorEmailRequest): Promise { + return this.send("POST", "/two-factor/send-email-login", request, false, false); + } + + // Emergency Access APIs + + async getEmergencyAccessTrusted(): Promise> { + const r = await this.send("GET", "/emergency-access/trusted", null, true, true); + return new ListResponse(r, EmergencyAccessGranteeDetailsResponse); + } + + async getEmergencyAccessGranted(): Promise> { + const r = await this.send("GET", "/emergency-access/granted", null, true, true); + return new ListResponse(r, EmergencyAccessGrantorDetailsResponse); + } + + async getEmergencyAccess(id: string): Promise { + const r = await this.send("GET", "/emergency-access/" + id, null, true, true); + return new EmergencyAccessGranteeDetailsResponse(r); + } + + async getEmergencyGrantorPolicies(id: string): Promise> { + const r = await this.send("GET", "/emergency-access/" + id + "/policies", null, true, true); + return new ListResponse(r, PolicyResponse); + } + + putEmergencyAccess(id: string, request: EmergencyAccessUpdateRequest): Promise { + return this.send("PUT", "/emergency-access/" + id, request, true, false); + } + + deleteEmergencyAccess(id: string): Promise { + return this.send("DELETE", "/emergency-access/" + id, null, true, false); + } + + postEmergencyAccessInvite(request: EmergencyAccessInviteRequest): Promise { + return this.send("POST", "/emergency-access/invite", request, true, false); + } + + postEmergencyAccessReinvite(id: string): Promise { + return this.send("POST", "/emergency-access/" + id + "/reinvite", null, true, false); + } + + postEmergencyAccessAccept(id: string, request: EmergencyAccessAcceptRequest): Promise { + return this.send("POST", "/emergency-access/" + id + "/accept", request, true, false); + } + + postEmergencyAccessConfirm(id: string, request: EmergencyAccessConfirmRequest): Promise { + return this.send("POST", "/emergency-access/" + id + "/confirm", request, true, false); + } + + postEmergencyAccessInitiate(id: string): Promise { + return this.send("POST", "/emergency-access/" + id + "/initiate", null, true, false); + } + + postEmergencyAccessApprove(id: string): Promise { + return this.send("POST", "/emergency-access/" + id + "/approve", null, true, false); + } + + postEmergencyAccessReject(id: string): Promise { + return this.send("POST", "/emergency-access/" + id + "/reject", null, true, false); + } + + async postEmergencyAccessTakeover(id: string): Promise { + const r = await this.send("POST", "/emergency-access/" + id + "/takeover", null, true, true); + return new EmergencyAccessTakeoverResponse(r); + } + + async postEmergencyAccessPassword( + id: string, + request: EmergencyAccessPasswordRequest + ): Promise { + await this.send("POST", "/emergency-access/" + id + "/password", request, true, true); + } + + async postEmergencyAccessView(id: string): Promise { + const r = await this.send("POST", "/emergency-access/" + id + "/view", null, true, true); + return new EmergencyAccessViewResponse(r); + } + + // Organization APIs + + async getOrganization(id: string): Promise { + const r = await this.send("GET", "/organizations/" + id, null, true, true); + return new OrganizationResponse(r); + } + + async getOrganizationBilling(id: string): Promise { + const r = await this.send("GET", "/organizations/" + id + "/billing", null, true, true); + return new BillingResponse(r); + } + + async getOrganizationSubscription(id: string): Promise { + const r = await this.send("GET", "/organizations/" + id + "/subscription", null, true, true); + return new OrganizationSubscriptionResponse(r); + } + + async getCloudCommunicationsEnabled(): Promise { + const r = await this.send("GET", "/organizations/connections/enabled", null, true, true); + return r as boolean; + } + + async getOrganizationConnection( + id: string, + type: OrganizationConnectionType, + configType: { new (response: any): TConfig } + ): Promise> { + const r = await this.send("GET", `/organizations/connections/${id}/${type}`, null, true, true); + return new OrganizationConnectionResponse(r, configType); + } + + async createOrganizationConnection( + request: OrganizationConnectionRequest, + configType: { new (response: any): TConfig } + ): Promise> { + const r = await this.send("POST", "/organizations/connections/", request, true, true); + return new OrganizationConnectionResponse(r, configType); + } + + async updateOrganizationConnection( + request: OrganizationConnectionRequest, + configType: { new (response: any): TConfig }, + organizationConnectionId?: string + ): Promise> { + const r = await this.send( + "PUT", + "/organizations/connections/" + organizationConnectionId, + request, + true, + true + ); + return new OrganizationConnectionResponse(r, configType); + } + + async deleteOrganizationConnection(id: string): Promise { + return this.send("DELETE", "/organizations/connections/" + id, null, true, false); + } + + async getOrganizationLicense(id: string, installationId: string): Promise { + return this.send( + "GET", + "/organizations/" + id + "/license?installationId=" + installationId, + null, + true, + true + ); + } + + async getOrganizationTaxInfo(id: string): Promise { + const r = await this.send("GET", "/organizations/" + id + "/tax", null, true, true); + return new TaxInfoResponse(r); + } + + async getOrganizationSso(id: string): Promise { + const r = await this.send("GET", "/organizations/" + id + "/sso", null, true, true); + return new OrganizationSsoResponse(r); + } + + async postOrganization(request: OrganizationCreateRequest): Promise { + const r = await this.send("POST", "/organizations", request, true, true); + return new OrganizationResponse(r); + } + + async putOrganization( + id: string, + request: OrganizationUpdateRequest + ): Promise { + const r = await this.send("PUT", "/organizations/" + id, request, true, true); + return new OrganizationResponse(r); + } + + async putOrganizationTaxInfo( + id: string, + request: OrganizationTaxInfoUpdateRequest + ): Promise { + return this.send("PUT", "/organizations/" + id + "/tax", request, true, false); + } + + postLeaveOrganization(id: string): Promise { + return this.send("POST", "/organizations/" + id + "/leave", null, true, false); + } + + async postOrganizationLicense(data: FormData): Promise { + const r = await this.send("POST", "/organizations/license", data, true, true); + return new OrganizationResponse(r); + } + + async postOrganizationLicenseUpdate(id: string, data: FormData): Promise { + return this.send("POST", "/organizations/" + id + "/license", data, true, false); + } + + async postOrganizationApiKey( + id: string, + request: OrganizationApiKeyRequest + ): Promise { + const r = await this.send("POST", "/organizations/" + id + "/api-key", request, true, true); + return new ApiKeyResponse(r); + } + + async getOrganizationApiKeyInformation( + id: string + ): Promise> { + const r = await this.send( + "GET", + "/organizations/" + id + "/api-key-information", + null, + true, + true + ); + return new ListResponse(r, OrganizationApiKeyInformationResponse); + } + + async postOrganizationRotateApiKey( + id: string, + request: OrganizationApiKeyRequest + ): Promise { + const r = await this.send( + "POST", + "/organizations/" + id + "/rotate-api-key", + request, + true, + true + ); + return new ApiKeyResponse(r); + } + + async postOrganizationSso( + id: string, + request: OrganizationSsoRequest + ): Promise { + const r = await this.send("POST", "/organizations/" + id + "/sso", request, true, true); + return new OrganizationSsoResponse(r); + } + + async postOrganizationUpgrade( + id: string, + request: OrganizationUpgradeRequest + ): Promise { + const r = await this.send("POST", "/organizations/" + id + "/upgrade", request, true, true); + return new PaymentResponse(r); + } + + async postOrganizationUpdateSubscription( + id: string, + request: OrganizationSubscriptionUpdateRequest + ): Promise { + return this.send("POST", "/organizations/" + id + "/subscription", request, true, false); + } + + async postOrganizationSeat(id: string, request: SeatRequest): Promise { + const r = await this.send("POST", "/organizations/" + id + "/seat", request, true, true); + return new PaymentResponse(r); + } + + async postOrganizationStorage(id: string, request: StorageRequest): Promise { + const r = await this.send("POST", "/organizations/" + id + "/storage", request, true, true); + return new PaymentResponse(r); + } + + postOrganizationPayment(id: string, request: PaymentRequest): Promise { + return this.send("POST", "/organizations/" + id + "/payment", request, true, false); + } + + postOrganizationVerifyBank(id: string, request: VerifyBankRequest): Promise { + return this.send("POST", "/organizations/" + id + "/verify-bank", request, true, false); + } + + postOrganizationCancel(id: string): Promise { + return this.send("POST", "/organizations/" + id + "/cancel", null, true, false); + } + + postOrganizationReinstate(id: string): Promise { + return this.send("POST", "/organizations/" + id + "/reinstate", null, true, false); + } + + deleteOrganization(id: string, request: SecretVerificationRequest): Promise { + return this.send("DELETE", "/organizations/" + id, request, true, false); + } + + async getOrganizationKeys(id: string): Promise { + const r = await this.send("GET", "/organizations/" + id + "/keys", null, true, true); + return new OrganizationKeysResponse(r); + } + + async postOrganizationKeys( + id: string, + request: OrganizationKeysRequest + ): Promise { + const r = await this.send("POST", "/organizations/" + id + "/keys", request, true, true); + return new OrganizationKeysResponse(r); + } + + // Provider APIs + + async postProviderSetup(id: string, request: ProviderSetupRequest) { + const r = await this.send("POST", "/providers/" + id + "/setup", request, true, true); + return new ProviderResponse(r); + } + + async getProvider(id: string) { + const r = await this.send("GET", "/providers/" + id, null, true, true); + return new ProviderResponse(r); + } + + async putProvider(id: string, request: ProviderUpdateRequest) { + const r = await this.send("PUT", "/providers/" + id, request, true, true); + return new ProviderResponse(r); + } + + // Provider User APIs + + async getProviderUsers( + providerId: string + ): Promise> { + const r = await this.send("GET", "/providers/" + providerId + "/users", null, true, true); + return new ListResponse(r, ProviderUserUserDetailsResponse); + } + + async getProviderUser(providerId: string, id: string): Promise { + const r = await this.send("GET", "/providers/" + providerId + "/users/" + id, null, true, true); + return new ProviderUserResponse(r); + } + + postProviderUserInvite(providerId: string, request: ProviderUserInviteRequest): Promise { + return this.send("POST", "/providers/" + providerId + "/users/invite", request, true, false); + } + + postProviderUserReinvite(providerId: string, id: string): Promise { + return this.send( + "POST", + "/providers/" + providerId + "/users/" + id + "/reinvite", + null, + true, + false + ); + } + + async postManyProviderUserReinvite( + providerId: string, + request: ProviderUserBulkRequest + ): Promise> { + const r = await this.send( + "POST", + "/providers/" + providerId + "/users/reinvite", + request, + true, + true + ); + return new ListResponse(r, ProviderUserBulkResponse); + } + + async postProviderUserBulkConfirm( + providerId: string, + request: ProviderUserBulkConfirmRequest + ): Promise> { + const r = await this.send( + "POST", + "/providers/" + providerId + "/users/confirm", + request, + true, + true + ); + return new ListResponse(r, ProviderUserBulkResponse); + } + + async deleteManyProviderUsers( + providerId: string, + request: ProviderUserBulkRequest + ): Promise> { + const r = await this.send("DELETE", "/providers/" + providerId + "/users", request, true, true); + return new ListResponse(r, ProviderUserBulkResponse); + } + + postProviderUserAccept( + providerId: string, + id: string, + request: ProviderUserAcceptRequest + ): Promise { + return this.send( + "POST", + "/providers/" + providerId + "/users/" + id + "/accept", + request, + true, + false + ); + } + + postProviderUserConfirm( + providerId: string, + id: string, + request: ProviderUserConfirmRequest + ): Promise { + return this.send( + "POST", + "/providers/" + providerId + "/users/" + id + "/confirm", + request, + true, + false + ); + } + + async postProviderUsersPublicKey( + providerId: string, + request: ProviderUserBulkRequest + ): Promise> { + const r = await this.send( + "POST", + "/providers/" + providerId + "/users/public-keys", + request, + true, + true + ); + return new ListResponse(r, ProviderUserBulkPublicKeyResponse); + } + + putProviderUser( + providerId: string, + id: string, + request: ProviderUserUpdateRequest + ): Promise { + return this.send("PUT", "/providers/" + providerId + "/users/" + id, request, true, false); + } + + deleteProviderUser(providerId: string, id: string): Promise { + return this.send("DELETE", "/providers/" + providerId + "/users/" + id, null, true, false); + } + + // Provider Organization APIs + + async getProviderClients( + providerId: string + ): Promise> { + const r = await this.send( + "GET", + "/providers/" + providerId + "/organizations", + null, + true, + true + ); + return new ListResponse(r, ProviderOrganizationOrganizationDetailsResponse); + } + + postProviderAddOrganization( + providerId: string, + request: ProviderAddOrganizationRequest + ): Promise { + return this.send( + "POST", + "/providers/" + providerId + "/organizations/add", + request, + true, + false + ); + } + + async postProviderCreateOrganization( + providerId: string, + request: ProviderOrganizationCreateRequest + ): Promise { + const r = await this.send( + "POST", + "/providers/" + providerId + "/organizations", + request, + true, + true + ); + return new ProviderOrganizationResponse(r); + } + + deleteProviderOrganization(providerId: string, id: string): Promise { + return this.send( + "DELETE", + "/providers/" + providerId + "/organizations/" + id, + null, + true, + false + ); + } + + // Event APIs + + async getEvents(start: string, end: string, token: string): Promise> { + const r = await this.send( + "GET", + this.addEventParameters("/events", start, end, token), + null, + true, + true + ); + return new ListResponse(r, EventResponse); + } + + async getEventsCipher( + id: string, + start: string, + end: string, + token: string + ): Promise> { + const r = await this.send( + "GET", + this.addEventParameters("/ciphers/" + id + "/events", start, end, token), + null, + true, + true + ); + return new ListResponse(r, EventResponse); + } + + async getEventsOrganization( + id: string, + start: string, + end: string, + token: string + ): Promise> { + const r = await this.send( + "GET", + this.addEventParameters("/organizations/" + id + "/events", start, end, token), + null, + true, + true + ); + return new ListResponse(r, EventResponse); + } + + async getEventsOrganizationUser( + organizationId: string, + id: string, + start: string, + end: string, + token: string + ): Promise> { + const r = await this.send( + "GET", + this.addEventParameters( + "/organizations/" + organizationId + "/users/" + id + "/events", + start, + end, + token + ), + null, + true, + true + ); + return new ListResponse(r, EventResponse); + } + + async getEventsProvider( + id: string, + start: string, + end: string, + token: string + ): Promise> { + const r = await this.send( + "GET", + this.addEventParameters("/providers/" + id + "/events", start, end, token), + null, + true, + true + ); + return new ListResponse(r, EventResponse); + } + + async getEventsProviderUser( + providerId: string, + id: string, + start: string, + end: string, + token: string + ): Promise> { + const r = await this.send( + "GET", + this.addEventParameters( + "/providers/" + providerId + "/users/" + id + "/events", + start, + end, + token + ), + null, + true, + true + ); + return new ListResponse(r, EventResponse); + } + + async postEventsCollect(request: EventRequest[]): Promise { + const authHeader = await this.getActiveBearerToken(); + const headers = new Headers({ + "Device-Type": this.deviceType, + Authorization: "Bearer " + authHeader, + "Content-Type": "application/json; charset=utf-8", + }); + if (this.customUserAgent != null) { + headers.set("User-Agent", this.customUserAgent); + } + const response = await this.fetch( + new Request(this.environmentService.getEventsUrl() + "/collect", { + cache: "no-store", + credentials: this.getCredentials(), + method: "POST", + body: JSON.stringify(request), + headers: headers, + }) + ); + if (response.status !== 200) { + return Promise.reject("Event post failed."); + } + } + + // User APIs + + async getUserPublicKey(id: string): Promise { + const r = await this.send("GET", "/users/" + id + "/public-key", null, true, true); + return new UserKeyResponse(r); + } + + // HIBP APIs + + async getHibpBreach(username: string): Promise { + const r = await this.send("GET", "/hibp/breach?username=" + username, null, true, true); + return r.map((a: any) => new BreachAccountResponse(a)); + } + + // Misc + + async postBitPayInvoice(request: BitPayInvoiceRequest): Promise { + const r = await this.send("POST", "/bitpay-invoice", request, true, true); + return r as string; + } + + async postSetupPayment(): Promise { + const r = await this.send("POST", "/setup-payment", null, true, true); + return r as string; + } + + // Key Connector + + async getUserKeyFromKeyConnector(keyConnectorUrl: string): Promise { + const authHeader = await this.getActiveBearerToken(); + + const response = await this.fetch( + new Request(keyConnectorUrl + "/user-keys", { + cache: "no-store", + method: "GET", + headers: new Headers({ + Accept: "application/json", + Authorization: "Bearer " + authHeader, + }), + }) + ); + + if (response.status !== 200) { + const error = await this.handleError(response, false, true); + return Promise.reject(error); + } + + return new KeyConnectorUserKeyResponse(await response.json()); + } + + async postUserKeyToKeyConnector( + keyConnectorUrl: string, + request: KeyConnectorUserKeyRequest + ): Promise { + const authHeader = await this.getActiveBearerToken(); + + const response = await this.fetch( + new Request(keyConnectorUrl + "/user-keys", { + cache: "no-store", + method: "POST", + headers: new Headers({ + Accept: "application/json", + Authorization: "Bearer " + authHeader, + "Content-Type": "application/json; charset=utf-8", + }), + body: JSON.stringify(request), + }) + ); + + if (response.status !== 200) { + const error = await this.handleError(response, false, true); + return Promise.reject(error); + } + } + + async getKeyConnectorAlive(keyConnectorUrl: string) { + const response = await this.fetch( + new Request(keyConnectorUrl + "/alive", { + cache: "no-store", + method: "GET", + headers: new Headers({ + Accept: "application/json", + "Content-Type": "application/json; charset=utf-8", + }), + }) + ); + + if (response.status !== 200) { + const error = await this.handleError(response, false, true); + return Promise.reject(error); + } + } + + // Helpers + + async getActiveBearerToken(): Promise { + let accessToken = await this.tokenService.getToken(); + if (await this.tokenService.tokenNeedsRefresh()) { + await this.doAuthRefresh(); + accessToken = await this.tokenService.getToken(); + } + return accessToken; + } + + async fetch(request: Request): Promise { + if (request.method === "GET") { + request.headers.set("Cache-Control", "no-store"); + request.headers.set("Pragma", "no-cache"); + } + request.headers.set("Bitwarden-Client-Name", this.platformUtilsService.getClientType()); + request.headers.set( + "Bitwarden-Client-Version", + await this.platformUtilsService.getApplicationVersion() + ); + return this.nativeFetch(request); + } + + nativeFetch(request: Request): Promise { + return fetch(request); + } + + async preValidateSso(identifier: string): Promise { + if (identifier == null || identifier === "") { + throw new Error("Organization Identifier was not provided."); + } + const headers = new Headers({ + Accept: "application/json", + "Device-Type": this.deviceType, + }); + if (this.customUserAgent != null) { + headers.set("User-Agent", this.customUserAgent); + } + + const path = `/account/prevalidate?domainHint=${encodeURIComponent(identifier)}`; + const response = await this.fetch( + new Request(this.environmentService.getIdentityUrl() + path, { + cache: "no-store", + credentials: this.getCredentials(), + headers: headers, + method: "GET", + }) + ); + + if (response.status === 200) { + const body = await response.json(); + return new SsoPreValidateResponse(body); + } else { + const error = await this.handleError(response, false, true); + return Promise.reject(error); + } + } + + async postCreateSponsorship( + sponsoredOrgId: string, + request: OrganizationSponsorshipCreateRequest + ): Promise { + return await this.send( + "POST", + "/organization/sponsorship/" + + (this.platformUtilsService.isSelfHost() ? "self-hosted/" : "") + + sponsoredOrgId + + "/families-for-enterprise", + request, + true, + false + ); + } + + async getSponsorshipSyncStatus( + sponsoredOrgId: string + ): Promise { + const response = await this.send( + "GET", + "/organization/sponsorship/" + sponsoredOrgId + "/sync-status", + null, + true, + true + ); + return new OrganizationSponsorshipSyncStatusResponse(response); + } + + async deleteRevokeSponsorship(sponsoringOrganizationId: string): Promise { + return await this.send( + "DELETE", + "/organization/sponsorship/" + + (this.platformUtilsService.isSelfHost() ? "self-hosted/" : "") + + sponsoringOrganizationId, + null, + true, + false + ); + } + + async deleteRemoveSponsorship(sponsoringOrgId: string): Promise { + return await this.send( + "DELETE", + "/organization/sponsorship/sponsored/" + sponsoringOrgId, + null, + true, + false + ); + } + + async postPreValidateSponsorshipToken(sponsorshipToken: string): Promise { + const r = await this.send( + "POST", + "/organization/sponsorship/validate-token?sponsorshipToken=" + + encodeURIComponent(sponsorshipToken), + null, + true, + true + ); + return r as boolean; + } + + async postRedeemSponsorship( + sponsorshipToken: string, + request: OrganizationSponsorshipRedeemRequest + ): Promise { + return await this.send( + "POST", + "/organization/sponsorship/redeem?sponsorshipToken=" + encodeURIComponent(sponsorshipToken), + request, + true, + false + ); + } + + async postResendSponsorshipOffer(sponsoringOrgId: string): Promise { + return await this.send( + "POST", + "/organization/sponsorship/" + sponsoringOrgId + "/families-for-enterprise/resend", + null, + true, + false + ); + } + + protected async doAuthRefresh(): Promise { + const refreshToken = await this.tokenService.getRefreshToken(); + if (refreshToken != null && refreshToken !== "") { + return this.doRefreshToken(); + } + + const clientId = await this.tokenService.getClientId(); + const clientSecret = await this.tokenService.getClientSecret(); + if (!Utils.isNullOrWhitespace(clientId) && !Utils.isNullOrWhitespace(clientSecret)) { + return this.doApiTokenRefresh(); + } + + throw new Error("Cannot refresh token, no refresh token or api keys are stored"); + } + + protected async doRefreshToken(): Promise { + const refreshToken = await this.tokenService.getRefreshToken(); + if (refreshToken == null || refreshToken === "") { + throw new Error(); + } + const headers = new Headers({ + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8", + Accept: "application/json", + "Device-Type": this.deviceType, + }); + if (this.customUserAgent != null) { + headers.set("User-Agent", this.customUserAgent); + } + + const decodedToken = await this.tokenService.decodeToken(); + const response = await this.fetch( + new Request(this.environmentService.getIdentityUrl() + "/connect/token", { + body: this.qsStringify({ + grant_type: "refresh_token", + client_id: decodedToken.client_id, + refresh_token: refreshToken, + }), + cache: "no-store", + credentials: this.getCredentials(), + headers: headers, + method: "POST", + }) + ); + + if (response.status === 200) { + const responseJson = await response.json(); + const tokenResponse = new IdentityTokenResponse(responseJson); + await this.tokenService.setTokens( + tokenResponse.accessToken, + tokenResponse.refreshToken, + null + ); + } else { + const error = await this.handleError(response, true, true); + return Promise.reject(error); + } + } + + protected async doApiTokenRefresh(): Promise { + const clientId = await this.tokenService.getClientId(); + const clientSecret = await this.tokenService.getClientSecret(); + + const appId = await this.appIdService.getAppId(); + const deviceRequest = new DeviceRequest(appId, this.platformUtilsService); + + const tokenRequest = new ApiTokenRequest( + clientId, + clientSecret, + new TokenRequestTwoFactor(), + deviceRequest + ); + + const response = await this.postIdentityToken(tokenRequest); + if (!(response instanceof IdentityTokenResponse)) { + throw new Error("Invalid response received when refreshing api token"); + } + + await this.tokenService.setToken(response.accessToken); + } + + private async send( + method: "GET" | "POST" | "PUT" | "DELETE", + path: string, + body: any, + authed: boolean, + hasResponse: boolean, + apiUrl?: string, + alterHeaders?: (headers: Headers) => void + ): Promise { + apiUrl = Utils.isNullOrWhitespace(apiUrl) ? this.environmentService.getApiUrl() : apiUrl; + + const requestUrl = apiUrl + path; + // Prevent directory traversal from malicious paths + if (new URL(requestUrl).href !== requestUrl) { + return Promise.reject("Invalid request url path."); + } + + const headers = new Headers({ + "Device-Type": this.deviceType, + }); + if (this.customUserAgent != null) { + headers.set("User-Agent", this.customUserAgent); + } + + const requestInit: RequestInit = { + cache: "no-store", + credentials: this.getCredentials(), + method: method, + }; + + if (authed) { + const authHeader = await this.getActiveBearerToken(); + headers.set("Authorization", "Bearer " + authHeader); + } + if (body != null) { + if (typeof body === "string") { + requestInit.body = body; + headers.set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); + } else if (typeof body === "object") { + if (body instanceof FormData) { + requestInit.body = body; + } else { + headers.set("Content-Type", "application/json; charset=utf-8"); + requestInit.body = JSON.stringify(body); + } + } + } + if (hasResponse) { + headers.set("Accept", "application/json"); + } + if (alterHeaders != null) { + alterHeaders(headers); + } + + requestInit.headers = headers; + const response = await this.fetch(new Request(requestUrl, requestInit)); + + if (hasResponse && response.status === 200) { + const responseJson = await response.json(); + return responseJson; + } else if (response.status !== 200) { + const error = await this.handleError(response, false, authed); + return Promise.reject(error); + } + } + + private async handleError( + response: Response, + tokenError: boolean, + authed: boolean + ): Promise { + if ( + authed && + ((tokenError && response.status === 400) || + response.status === 401 || + response.status === 403) + ) { + await this.logoutCallback(true); + return null; + } + + let responseJson: any = null; + if (this.isJsonResponse(response)) { + responseJson = await response.json(); + } else if (this.isTextResponse(response)) { + responseJson = { Message: await response.text() }; + } + + return new ErrorResponse(responseJson, response.status, tokenError); + } + + private qsStringify(params: any): string { + return Object.keys(params) + .map((key) => { + return encodeURIComponent(key) + "=" + encodeURIComponent(params[key]); + }) + .join("&"); + } + + private getCredentials(): RequestCredentials { + if (!this.isWebClient || this.environmentService.hasBaseUrl()) { + return "include"; + } + return undefined; + } + + private addEventParameters(base: string, start: string, end: string, token: string) { + if (start != null) { + base += "?start=" + start; + } + if (end != null) { + base += base.indexOf("?") > -1 ? "&" : "?"; + base += "end=" + end; + } + if (token != null) { + base += base.indexOf("?") > -1 ? "&" : "?"; + base += "continuationToken=" + token; + } + return base; + } + + private isJsonResponse(response: Response): boolean { + const typeHeader = response.headers.get("content-type"); + return typeHeader != null && typeHeader.indexOf("application/json") > -1; + } + + private isTextResponse(response: Response): boolean { + const typeHeader = response.headers.get("content-type"); + return typeHeader != null && typeHeader.indexOf("text") > -1; + } +} diff --git a/libs/common/src/services/appId.service.ts b/libs/common/src/services/appId.service.ts new file mode 100644 index 0000000000..a6406fdc83 --- /dev/null +++ b/libs/common/src/services/appId.service.ts @@ -0,0 +1,31 @@ +import { AppIdService as AppIdServiceAbstraction } from "../abstractions/appId.service"; +import { StorageService } from "../abstractions/storage.service"; +import { HtmlStorageLocation } from "../enums/htmlStorageLocation"; +import { Utils } from "../misc/utils"; + +export class AppIdService implements AppIdServiceAbstraction { + constructor(private storageService: StorageService) {} + + getAppId(): Promise { + return this.makeAndGetAppId("appId"); + } + + getAnonymousAppId(): Promise { + return this.makeAndGetAppId("anonymousAppId"); + } + + private async makeAndGetAppId(key: string) { + const existingId = await this.storageService.get(key, { + htmlStorageLocation: HtmlStorageLocation.Local, + }); + if (existingId != null) { + return existingId; + } + + const guid = Utils.newGuid(); + await this.storageService.save(key, guid, { + htmlStorageLocation: HtmlStorageLocation.Local, + }); + return guid; + } +} diff --git a/libs/common/src/services/audit.service.ts b/libs/common/src/services/audit.service.ts new file mode 100644 index 0000000000..4ceebf6746 --- /dev/null +++ b/libs/common/src/services/audit.service.ts @@ -0,0 +1,44 @@ +import { ApiService } from "../abstractions/api.service"; +import { AuditService as AuditServiceAbstraction } from "../abstractions/audit.service"; +import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; +import { throttle } from "../misc/throttle"; +import { Utils } from "../misc/utils"; +import { BreachAccountResponse } from "../models/response/breachAccountResponse"; +import { ErrorResponse } from "../models/response/errorResponse"; + +const PwnedPasswordsApi = "https://api.pwnedpasswords.com/range/"; + +export class AuditService implements AuditServiceAbstraction { + constructor( + private cryptoFunctionService: CryptoFunctionService, + private apiService: ApiService + ) {} + + @throttle(100, () => "passwordLeaked") + async passwordLeaked(password: string): Promise { + const hashBytes = await this.cryptoFunctionService.hash(password, "sha1"); + const hash = Utils.fromBufferToHex(hashBytes).toUpperCase(); + const hashStart = hash.substr(0, 5); + const hashEnding = hash.substr(5); + + const response = await this.apiService.nativeFetch(new Request(PwnedPasswordsApi + hashStart)); + const leakedHashes = await response.text(); + const match = leakedHashes.split(/\r?\n/).find((v) => { + return v.split(":")[0] === hashEnding; + }); + + return match != null ? parseInt(match.split(":")[1], 10) : 0; + } + + async breachedAccounts(username: string): Promise { + try { + return await this.apiService.getHibpBreach(username); + } catch (e) { + const error = e as ErrorResponse; + if (error.statusCode === 404) { + return []; + } + throw new Error(); + } + } +} diff --git a/libs/common/src/services/auth.service.ts b/libs/common/src/services/auth.service.ts new file mode 100644 index 0000000000..6f77bca20b --- /dev/null +++ b/libs/common/src/services/auth.service.ts @@ -0,0 +1,225 @@ +import { ApiService } from "../abstractions/api.service"; +import { AppIdService } from "../abstractions/appId.service"; +import { AuthService as AuthServiceAbstraction } from "../abstractions/auth.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { EnvironmentService } from "../abstractions/environment.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { KeyConnectorService } from "../abstractions/keyConnector.service"; +import { LogService } from "../abstractions/log.service"; +import { MessagingService } from "../abstractions/messaging.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; +import { StateService } from "../abstractions/state.service"; +import { TokenService } from "../abstractions/token.service"; +import { TwoFactorService } from "../abstractions/twoFactor.service"; +import { AuthenticationStatus } from "../enums/authenticationStatus"; +import { AuthenticationType } from "../enums/authenticationType"; +import { KdfType } from "../enums/kdfType"; +import { KeySuffixOptions } from "../enums/keySuffixOptions"; +import { ApiLogInStrategy } from "../misc/logInStrategies/apiLogin.strategy"; +import { PasswordLogInStrategy } from "../misc/logInStrategies/passwordLogin.strategy"; +import { SsoLogInStrategy } from "../misc/logInStrategies/ssoLogin.strategy"; +import { AuthResult } from "../models/domain/authResult"; +import { + ApiLogInCredentials, + PasswordLogInCredentials, + SsoLogInCredentials, +} from "../models/domain/logInCredentials"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { TokenRequestTwoFactor } from "../models/request/identityToken/tokenRequestTwoFactor"; +import { PreloginRequest } from "../models/request/preloginRequest"; +import { ErrorResponse } from "../models/response/errorResponse"; + +const sessionTimeoutLength = 2 * 60 * 1000; // 2 minutes + +export class AuthService implements AuthServiceAbstraction { + get email(): string { + return this.logInStrategy instanceof PasswordLogInStrategy ? this.logInStrategy.email : null; + } + + get masterPasswordHash(): string { + return this.logInStrategy instanceof PasswordLogInStrategy + ? this.logInStrategy.masterPasswordHash + : null; + } + + private logInStrategy: ApiLogInStrategy | PasswordLogInStrategy | SsoLogInStrategy; + private sessionTimeout: any; + + constructor( + protected cryptoService: CryptoService, + protected apiService: ApiService, + protected tokenService: TokenService, + protected appIdService: AppIdService, + protected platformUtilsService: PlatformUtilsService, + protected messagingService: MessagingService, + protected logService: LogService, + protected keyConnectorService: KeyConnectorService, + protected environmentService: EnvironmentService, + protected stateService: StateService, + protected twoFactorService: TwoFactorService, + protected i18nService: I18nService + ) {} + + async logIn( + credentials: ApiLogInCredentials | PasswordLogInCredentials | SsoLogInCredentials + ): Promise { + this.clearState(); + + let strategy: ApiLogInStrategy | PasswordLogInStrategy | SsoLogInStrategy; + + if (credentials.type === AuthenticationType.Password) { + strategy = new PasswordLogInStrategy( + this.cryptoService, + this.apiService, + this.tokenService, + this.appIdService, + this.platformUtilsService, + this.messagingService, + this.logService, + this.stateService, + this.twoFactorService, + this + ); + } else if (credentials.type === AuthenticationType.Sso) { + strategy = new SsoLogInStrategy( + this.cryptoService, + this.apiService, + this.tokenService, + this.appIdService, + this.platformUtilsService, + this.messagingService, + this.logService, + this.stateService, + this.twoFactorService, + this.keyConnectorService + ); + } else if (credentials.type === AuthenticationType.Api) { + strategy = new ApiLogInStrategy( + this.cryptoService, + this.apiService, + this.tokenService, + this.appIdService, + this.platformUtilsService, + this.messagingService, + this.logService, + this.stateService, + this.twoFactorService, + this.environmentService, + this.keyConnectorService + ); + } + + const result = await strategy.logIn(credentials as any); + + if (result?.requiresTwoFactor) { + this.saveState(strategy); + } + return result; + } + + async logInTwoFactor( + twoFactor: TokenRequestTwoFactor, + captchaResponse: string + ): Promise { + if (this.logInStrategy == null) { + throw new Error(this.i18nService.t("sessionTimeout")); + } + + try { + const result = await this.logInStrategy.logInTwoFactor(twoFactor, captchaResponse); + + // Only clear state if 2FA token has been accepted, otherwise we need to be able to try again + if (!result.requiresTwoFactor && !result.requiresCaptcha) { + this.clearState(); + } + return result; + } catch (e) { + // API exceptions are okay, but if there are any unhandled client-side errors then clear state to be safe + if (!(e instanceof ErrorResponse)) { + this.clearState(); + } + throw e; + } + } + + logOut(callback: () => void) { + callback(); + this.messagingService.send("loggedOut"); + } + + authingWithApiKey(): boolean { + return this.logInStrategy instanceof ApiLogInStrategy; + } + + authingWithSso(): boolean { + return this.logInStrategy instanceof SsoLogInStrategy; + } + + authingWithPassword(): boolean { + return this.logInStrategy instanceof PasswordLogInStrategy; + } + + async getAuthStatus(userId?: string): Promise { + const isAuthenticated = await this.stateService.getIsAuthenticated({ userId: userId }); + if (!isAuthenticated) { + return AuthenticationStatus.LoggedOut; + } + + // Keys aren't stored for a device that is locked or logged out + // Make sure we're logged in before checking this, otherwise we could mix up those states + const neverLock = + (await this.cryptoService.hasKeyStored(KeySuffixOptions.Auto, userId)) && + !(await this.stateService.getEverBeenUnlocked({ userId: userId })); + if (neverLock) { + // TODO: This also _sets_ the key so when we check memory in the next line it finds a key. + // We should refactor here. + await this.cryptoService.getKey(KeySuffixOptions.Auto, userId); + } + + const hasKeyInMemory = await this.cryptoService.hasKeyInMemory(userId); + if (!hasKeyInMemory) { + return AuthenticationStatus.Locked; + } + + return AuthenticationStatus.Unlocked; + } + + async makePreloginKey(masterPassword: string, email: string): Promise { + email = email.trim().toLowerCase(); + let kdf: KdfType = null; + let kdfIterations: number = null; + try { + const preloginResponse = await this.apiService.postPrelogin(new PreloginRequest(email)); + if (preloginResponse != null) { + kdf = preloginResponse.kdf; + kdfIterations = preloginResponse.kdfIterations; + } + } catch (e) { + if (e == null || e.statusCode !== 404) { + throw e; + } + } + return this.cryptoService.makeKey(masterPassword, email, kdf, kdfIterations); + } + + private saveState(strategy: ApiLogInStrategy | PasswordLogInStrategy | SsoLogInStrategy) { + this.logInStrategy = strategy; + this.startSessionTimeout(); + } + + private clearState() { + this.logInStrategy = null; + this.clearSessionTimeout(); + } + + private startSessionTimeout() { + this.clearSessionTimeout(); + this.sessionTimeout = setTimeout(() => this.clearState(), sessionTimeoutLength); + } + + private clearSessionTimeout() { + if (this.sessionTimeout != null) { + clearTimeout(this.sessionTimeout); + } + } +} diff --git a/libs/common/src/services/azureFileUpload.service.ts b/libs/common/src/services/azureFileUpload.service.ts new file mode 100644 index 0000000000..d7017bfb69 --- /dev/null +++ b/libs/common/src/services/azureFileUpload.service.ts @@ -0,0 +1,214 @@ +import { LogService } from "../abstractions/log.service"; +import { Utils } from "../misc/utils"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; + +const MAX_SINGLE_BLOB_UPLOAD_SIZE = 256 * 1024 * 1024; // 256 MiB +const MAX_BLOCKS_PER_BLOB = 50000; + +export class AzureFileUploadService { + constructor(private logService: LogService) {} + + async upload(url: string, data: EncArrayBuffer, renewalCallback: () => Promise) { + if (data.buffer.byteLength <= MAX_SINGLE_BLOB_UPLOAD_SIZE) { + return await this.azureUploadBlob(url, data); + } else { + return await this.azureUploadBlocks(url, data, renewalCallback); + } + } + private async azureUploadBlob(url: string, data: EncArrayBuffer) { + const urlObject = Utils.getUrl(url); + const headers = new Headers({ + "x-ms-date": new Date().toUTCString(), + "x-ms-version": urlObject.searchParams.get("sv"), + "Content-Length": data.buffer.byteLength.toString(), + "x-ms-blob-type": "BlockBlob", + }); + + const request = new Request(url, { + body: data.buffer, + cache: "no-store", + method: "PUT", + headers: headers, + }); + + const blobResponse = await fetch(request); + + if (blobResponse.status !== 201) { + throw new Error(`Failed to create Azure blob: ${blobResponse.status}`); + } + } + private async azureUploadBlocks( + url: string, + data: EncArrayBuffer, + renewalCallback: () => Promise + ) { + const baseUrl = Utils.getUrl(url); + const blockSize = this.getMaxBlockSize(baseUrl.searchParams.get("sv")); + let blockIndex = 0; + const numBlocks = Math.ceil(data.buffer.byteLength / blockSize); + const blocksStaged: string[] = []; + + if (numBlocks > MAX_BLOCKS_PER_BLOB) { + throw new Error( + `Cannot upload file, exceeds maximum size of ${blockSize * MAX_BLOCKS_PER_BLOB}` + ); + } + + // eslint-disable-next-line + try { + while (blockIndex < numBlocks) { + url = await this.renewUrlIfNecessary(url, renewalCallback); + const blockUrl = Utils.getUrl(url); + const blockId = this.encodedBlockId(blockIndex); + blockUrl.searchParams.append("comp", "block"); + blockUrl.searchParams.append("blockid", blockId); + const start = blockIndex * blockSize; + const blockData = data.buffer.slice(start, start + blockSize); + const blockHeaders = new Headers({ + "x-ms-date": new Date().toUTCString(), + "x-ms-version": blockUrl.searchParams.get("sv"), + "Content-Length": blockData.byteLength.toString(), + }); + + const blockRequest = new Request(blockUrl.toString(), { + body: blockData, + cache: "no-store", + method: "PUT", + headers: blockHeaders, + }); + + const blockResponse = await fetch(blockRequest); + + if (blockResponse.status !== 201) { + const message = `Unsuccessful block PUT. Received status ${blockResponse.status}`; + this.logService.error(message + "\n" + (await blockResponse.json())); + throw new Error(message); + } + + blocksStaged.push(blockId); + blockIndex++; + } + + url = await this.renewUrlIfNecessary(url, renewalCallback); + const blockListUrl = Utils.getUrl(url); + const blockListXml = this.blockListXml(blocksStaged); + blockListUrl.searchParams.append("comp", "blocklist"); + const headers = new Headers({ + "x-ms-date": new Date().toUTCString(), + "x-ms-version": blockListUrl.searchParams.get("sv"), + "Content-Length": blockListXml.length.toString(), + }); + + const request = new Request(blockListUrl.toString(), { + body: blockListXml, + cache: "no-store", + method: "PUT", + headers: headers, + }); + + const response = await fetch(request); + + if (response.status !== 201) { + const message = `Unsuccessful block list PUT. Received status ${response.status}`; + this.logService.error(message + "\n" + (await response.json())); + throw new Error(message); + } + } catch (e) { + throw e; + } + } + + private async renewUrlIfNecessary( + url: string, + renewalCallback: () => Promise + ): Promise { + const urlObject = Utils.getUrl(url); + const expiry = new Date(urlObject.searchParams.get("se") ?? ""); + + if (isNaN(expiry.getTime())) { + expiry.setTime(Date.now() + 3600000); + } + + if (expiry.getTime() < Date.now() + 1000) { + return await renewalCallback(); + } + return url; + } + + private encodedBlockId(blockIndex: number) { + // Encoded blockId max size is 64, so pre-encoding max size is 48 + const utfBlockId = ( + "000000000000000000000000000000000000000000000000" + blockIndex.toString() + ).slice(-48); + return Utils.fromUtf8ToB64(utfBlockId); + } + + private blockListXml(blockIdList: string[]) { + let xml = ''; + blockIdList.forEach((blockId) => { + xml += `${blockId}`; + }); + xml += ""; + return xml; + } + + private getMaxBlockSize(version: string) { + if (Version.compare(version, "2019-12-12") >= 0) { + return 4000 * 1024 * 1024; // 4000 MiB + } else if (Version.compare(version, "2016-05-31") >= 0) { + return 100 * 1024 * 1024; // 100 MiB + } else { + return 4 * 1024 * 1024; // 4 MiB + } + } +} + +class Version { + /** + * Compares two Azure Versions against each other + * @param a Version to compare + * @param b Version to compare + * @returns a number less than zero if b is newer than a, 0 if equal, + * and greater than zero if a is newer than b + */ + static compare(a: Required | string, b: Required | string) { + if (typeof a === "string") { + a = new Version(a); + } + + if (typeof b === "string") { + b = new Version(b); + } + + return a.year !== b.year + ? a.year - b.year + : a.month !== b.month + ? a.month - b.month + : a.day !== b.day + ? a.day - b.day + : 0; + } + year = 0; + month = 0; + day = 0; + + constructor(version: string) { + try { + const parts = version.split("-").map((v) => Number.parseInt(v, 10)); + this.year = parts[0]; + this.month = parts[1]; + this.day = parts[2]; + } catch { + // Ignore error + } + } + /** + * Compares two Azure Versions against each other + * @param compareTo Version to compare against + * @returns a number less than zero if compareTo is newer, 0 if equal, + * and greater than zero if this is greater than compareTo + */ + compare(compareTo: Required | string) { + return Version.compare(this, compareTo); + } +} diff --git a/libs/common/src/services/bitwardenFileUpload.service.ts b/libs/common/src/services/bitwardenFileUpload.service.ts new file mode 100644 index 0000000000..dd189e3e54 --- /dev/null +++ b/libs/common/src/services/bitwardenFileUpload.service.ts @@ -0,0 +1,34 @@ +import { ApiService } from "../abstractions/api.service"; +import { Utils } from "../misc/utils"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; + +export class BitwardenFileUploadService { + constructor(private apiService: ApiService) {} + + async upload( + encryptedFileName: string, + encryptedFileData: EncArrayBuffer, + apiCall: (fd: FormData) => Promise + ) { + const fd = new FormData(); + try { + const blob = new Blob([encryptedFileData.buffer], { type: "application/octet-stream" }); + fd.append("data", blob, encryptedFileName); + } catch (e) { + if (Utils.isNode && !Utils.isBrowser) { + fd.append( + "data", + Buffer.from(encryptedFileData.buffer) as any, + { + filepath: encryptedFileName, + contentType: "application/octet-stream", + } as any + ); + } else { + throw e; + } + } + + await apiCall(fd); + } +} diff --git a/libs/common/src/services/broadcaster.service.ts b/libs/common/src/services/broadcaster.service.ts new file mode 100644 index 0000000000..999fbe4bb6 --- /dev/null +++ b/libs/common/src/services/broadcaster.service.ts @@ -0,0 +1,28 @@ +import { BroadcasterService as BroadcasterServiceAbstraction } from "../abstractions/broadcaster.service"; + +export class BroadcasterService implements BroadcasterServiceAbstraction { + subscribers: Map any> = new Map any>(); + + send(message: any, id?: string) { + if (id != null) { + if (this.subscribers.has(id)) { + this.subscribers.get(id)(message); + } + return; + } + + this.subscribers.forEach((value) => { + value(message); + }); + } + + subscribe(id: string, messageCallback: (message: any) => any) { + this.subscribers.set(id, messageCallback); + } + + unsubscribe(id: string) { + if (this.subscribers.has(id)) { + this.subscribers.delete(id); + } + } +} diff --git a/libs/common/src/services/cipher.service.ts b/libs/common/src/services/cipher.service.ts new file mode 100644 index 0000000000..7482828f67 --- /dev/null +++ b/libs/common/src/services/cipher.service.ts @@ -0,0 +1,1273 @@ +import { ApiService } from "../abstractions/api.service"; +import { CipherService as CipherServiceAbstraction } from "../abstractions/cipher.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { FileUploadService } from "../abstractions/fileUpload.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { LogService } from "../abstractions/log.service"; +import { SearchService } from "../abstractions/search.service"; +import { SettingsService } from "../abstractions/settings.service"; +import { StateService } from "../abstractions/state.service"; +import { CipherType } from "../enums/cipherType"; +import { FieldType } from "../enums/fieldType"; +import { UriMatchType } from "../enums/uriMatchType"; +import { sequentialize } from "../misc/sequentialize"; +import { Utils } from "../misc/utils"; +import { CipherData } from "../models/data/cipherData"; +import { Attachment } from "../models/domain/attachment"; +import { Card } from "../models/domain/card"; +import { Cipher } from "../models/domain/cipher"; +import Domain from "../models/domain/domainBase"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; +import { EncString } from "../models/domain/encString"; +import { Field } from "../models/domain/field"; +import { Identity } from "../models/domain/identity"; +import { Login } from "../models/domain/login"; +import { LoginUri } from "../models/domain/loginUri"; +import { Password } from "../models/domain/password"; +import { SecureNote } from "../models/domain/secureNote"; +import { SortedCiphersCache } from "../models/domain/sortedCiphersCache"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { AttachmentRequest } from "../models/request/attachmentRequest"; +import { CipherBulkDeleteRequest } from "../models/request/cipherBulkDeleteRequest"; +import { CipherBulkMoveRequest } from "../models/request/cipherBulkMoveRequest"; +import { CipherBulkRestoreRequest } from "../models/request/cipherBulkRestoreRequest"; +import { CipherBulkShareRequest } from "../models/request/cipherBulkShareRequest"; +import { CipherCollectionsRequest } from "../models/request/cipherCollectionsRequest"; +import { CipherCreateRequest } from "../models/request/cipherCreateRequest"; +import { CipherRequest } from "../models/request/cipherRequest"; +import { CipherShareRequest } from "../models/request/cipherShareRequest"; +import { CipherResponse } from "../models/response/cipherResponse"; +import { ErrorResponse } from "../models/response/errorResponse"; +import { AttachmentView } from "../models/view/attachmentView"; +import { CipherView } from "../models/view/cipherView"; +import { FieldView } from "../models/view/fieldView"; +import { PasswordHistoryView } from "../models/view/passwordHistoryView"; +import { View } from "../models/view/view"; + +const DomainMatchBlacklist = new Map>([ + ["google.com", new Set(["script.google.com"])], +]); + +export class CipherService implements CipherServiceAbstraction { + private sortedCiphersCache: SortedCiphersCache = new SortedCiphersCache( + this.sortCiphersByLastUsed + ); + + constructor( + private cryptoService: CryptoService, + private settingsService: SettingsService, + private apiService: ApiService, + private fileUploadService: FileUploadService, + private i18nService: I18nService, + private searchService: () => SearchService, + private logService: LogService, + private stateService: StateService + ) {} + + async getDecryptedCipherCache(): Promise { + const decryptedCiphers = await this.stateService.getDecryptedCiphers(); + return decryptedCiphers; + } + + async setDecryptedCipherCache(value: CipherView[]) { + await this.stateService.setDecryptedCiphers(value); + if (this.searchService != null) { + if (value == null) { + this.searchService().clearIndex(); + } else { + this.searchService().indexCiphers(); + } + } + } + + async clearCache(userId?: string): Promise { + await this.clearDecryptedCiphersState(userId); + } + + async encrypt( + model: CipherView, + key?: SymmetricCryptoKey, + originalCipher: Cipher = null + ): Promise { + // Adjust password history + if (model.id != null) { + if (originalCipher == null) { + originalCipher = await this.get(model.id); + } + if (originalCipher != null) { + const existingCipher = await originalCipher.decrypt(); + model.passwordHistory = existingCipher.passwordHistory || []; + if (model.type === CipherType.Login && existingCipher.type === CipherType.Login) { + if ( + existingCipher.login.password != null && + existingCipher.login.password !== "" && + existingCipher.login.password !== model.login.password + ) { + const ph = new PasswordHistoryView(); + ph.password = existingCipher.login.password; + ph.lastUsedDate = model.login.passwordRevisionDate = new Date(); + model.passwordHistory.splice(0, 0, ph); + } else { + model.login.passwordRevisionDate = existingCipher.login.passwordRevisionDate; + } + } + if (existingCipher.hasFields) { + const existingHiddenFields = existingCipher.fields.filter( + (f) => + f.type === FieldType.Hidden && + f.name != null && + f.name !== "" && + f.value != null && + f.value !== "" + ); + const hiddenFields = + model.fields == null + ? [] + : model.fields.filter( + (f) => f.type === FieldType.Hidden && f.name != null && f.name !== "" + ); + existingHiddenFields.forEach((ef) => { + const matchedField = hiddenFields.find((f) => f.name === ef.name); + if (matchedField == null || matchedField.value !== ef.value) { + const ph = new PasswordHistoryView(); + ph.password = ef.name + ": " + ef.value; + ph.lastUsedDate = new Date(); + model.passwordHistory.splice(0, 0, ph); + } + }); + } + } + if (model.passwordHistory != null && model.passwordHistory.length === 0) { + model.passwordHistory = null; + } else if (model.passwordHistory != null && model.passwordHistory.length > 5) { + // only save last 5 history + model.passwordHistory = model.passwordHistory.slice(0, 5); + } + } + + const cipher = new Cipher(); + cipher.id = model.id; + cipher.folderId = model.folderId; + cipher.favorite = model.favorite; + cipher.organizationId = model.organizationId; + cipher.type = model.type; + cipher.collectionIds = model.collectionIds; + cipher.revisionDate = model.revisionDate; + cipher.reprompt = model.reprompt; + + if (key == null && cipher.organizationId != null) { + key = await this.cryptoService.getOrgKey(cipher.organizationId); + if (key == null) { + throw new Error("Cannot encrypt cipher for organization. No key."); + } + } + await Promise.all([ + this.encryptObjProperty( + model, + cipher, + { + name: null, + notes: null, + }, + key + ), + this.encryptCipherData(cipher, model, key), + this.encryptFields(model.fields, key).then((fields) => { + cipher.fields = fields; + }), + this.encryptPasswordHistories(model.passwordHistory, key).then((ph) => { + cipher.passwordHistory = ph; + }), + this.encryptAttachments(model.attachments, key).then((attachments) => { + cipher.attachments = attachments; + }), + ]); + + return cipher; + } + + async encryptAttachments( + attachmentsModel: AttachmentView[], + key: SymmetricCryptoKey + ): Promise { + if (attachmentsModel == null || attachmentsModel.length === 0) { + return null; + } + + const promises: Promise[] = []; + const encAttachments: Attachment[] = []; + attachmentsModel.forEach(async (model) => { + const attachment = new Attachment(); + attachment.id = model.id; + attachment.size = model.size; + attachment.sizeName = model.sizeName; + attachment.url = model.url; + const promise = this.encryptObjProperty( + model, + attachment, + { + fileName: null, + }, + key + ).then(async () => { + if (model.key != null) { + attachment.key = await this.cryptoService.encrypt(model.key.key, key); + } + encAttachments.push(attachment); + }); + promises.push(promise); + }); + + await Promise.all(promises); + return encAttachments; + } + + async encryptFields(fieldsModel: FieldView[], key: SymmetricCryptoKey): Promise { + if (!fieldsModel || !fieldsModel.length) { + return null; + } + + const self = this; + const encFields: Field[] = []; + await fieldsModel.reduce(async (promise, field) => { + await promise; + const encField = await self.encryptField(field, key); + encFields.push(encField); + }, Promise.resolve()); + + return encFields; + } + + async encryptField(fieldModel: FieldView, key: SymmetricCryptoKey): Promise { + const field = new Field(); + field.type = fieldModel.type; + field.linkedId = fieldModel.linkedId; + // normalize boolean type field values + if (fieldModel.type === FieldType.Boolean && fieldModel.value !== "true") { + fieldModel.value = "false"; + } + + await this.encryptObjProperty( + fieldModel, + field, + { + name: null, + value: null, + }, + key + ); + + return field; + } + + async encryptPasswordHistories( + phModels: PasswordHistoryView[], + key: SymmetricCryptoKey + ): Promise { + if (!phModels || !phModels.length) { + return null; + } + + const self = this; + const encPhs: Password[] = []; + await phModels.reduce(async (promise, ph) => { + await promise; + const encPh = await self.encryptPasswordHistory(ph, key); + encPhs.push(encPh); + }, Promise.resolve()); + + return encPhs; + } + + async encryptPasswordHistory( + phModel: PasswordHistoryView, + key: SymmetricCryptoKey + ): Promise { + const ph = new Password(); + ph.lastUsedDate = phModel.lastUsedDate; + + await this.encryptObjProperty( + phModel, + ph, + { + password: null, + }, + key + ); + + return ph; + } + + async get(id: string): Promise { + const ciphers = await this.stateService.getEncryptedCiphers(); + // eslint-disable-next-line + if (ciphers == null || !ciphers.hasOwnProperty(id)) { + return null; + } + + const localData = await this.stateService.getLocalData(); + return new Cipher(ciphers[id], localData ? localData[id] : null); + } + + async getAll(): Promise { + const localData = await this.stateService.getLocalData(); + const ciphers = await this.stateService.getEncryptedCiphers(); + const response: Cipher[] = []; + for (const id in ciphers) { + // eslint-disable-next-line + if (ciphers.hasOwnProperty(id)) { + response.push(new Cipher(ciphers[id], localData ? localData[id] : null)); + } + } + return response; + } + + @sequentialize(() => "getAllDecrypted") + async getAllDecrypted(): Promise { + const userId = await this.stateService.getUserId(); + if ((await this.getDecryptedCipherCache()) != null) { + if ( + this.searchService != null && + (this.searchService().indexedEntityId ?? userId) !== userId + ) { + await this.searchService().indexCiphers(userId, await this.getDecryptedCipherCache()); + } + return await this.getDecryptedCipherCache(); + } + + const decCiphers: CipherView[] = []; + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + throw new Error("No key."); + } + + const promises: any[] = []; + const ciphers = await this.getAll(); + ciphers.forEach(async (cipher) => { + promises.push(cipher.decrypt().then((c) => decCiphers.push(c))); + }); + + await Promise.all(promises); + decCiphers.sort(this.getLocaleSortingFunction()); + await this.setDecryptedCipherCache(decCiphers); + return decCiphers; + } + + async getAllDecryptedForGrouping(groupingId: string, folder = true): Promise { + const ciphers = await this.getAllDecrypted(); + + return ciphers.filter((cipher) => { + if (cipher.isDeleted) { + return false; + } + if (folder && cipher.folderId === groupingId) { + return true; + } else if ( + !folder && + cipher.collectionIds != null && + cipher.collectionIds.indexOf(groupingId) > -1 + ) { + return true; + } + + return false; + }); + } + + async getAllDecryptedForUrl( + url: string, + includeOtherTypes?: CipherType[], + defaultMatch: UriMatchType = null + ): Promise { + if (url == null && includeOtherTypes == null) { + return Promise.resolve([]); + } + + const domain = Utils.getDomain(url); + const eqDomainsPromise = + domain == null + ? Promise.resolve([]) + : this.settingsService.getEquivalentDomains().then((eqDomains: any[][]) => { + let matches: any[] = []; + eqDomains.forEach((eqDomain) => { + if (eqDomain.length && eqDomain.indexOf(domain) >= 0) { + matches = matches.concat(eqDomain); + } + }); + + if (!matches.length) { + matches.push(domain); + } + + return matches; + }); + + const result = await Promise.all([eqDomainsPromise, this.getAllDecrypted()]); + const matchingDomains = result[0]; + const ciphers = result[1]; + + if (defaultMatch == null) { + defaultMatch = await this.stateService.getDefaultUriMatch(); + if (defaultMatch == null) { + defaultMatch = UriMatchType.Domain; + } + } + + return ciphers.filter((cipher) => { + if (cipher.deletedDate != null) { + return false; + } + if (includeOtherTypes != null && includeOtherTypes.indexOf(cipher.type) > -1) { + return true; + } + + if (url != null && cipher.type === CipherType.Login && cipher.login.uris != null) { + for (let i = 0; i < cipher.login.uris.length; i++) { + const u = cipher.login.uris[i]; + if (u.uri == null) { + continue; + } + + const match = u.match == null ? defaultMatch : u.match; + switch (match) { + case UriMatchType.Domain: + if (domain != null && u.domain != null && matchingDomains.indexOf(u.domain) > -1) { + if (DomainMatchBlacklist.has(u.domain)) { + const domainUrlHost = Utils.getHost(url); + if (!DomainMatchBlacklist.get(u.domain).has(domainUrlHost)) { + return true; + } + } else { + return true; + } + } + break; + case UriMatchType.Host: { + const urlHost = Utils.getHost(url); + if (urlHost != null && urlHost === Utils.getHost(u.uri)) { + return true; + } + break; + } + case UriMatchType.Exact: + if (url === u.uri) { + return true; + } + break; + case UriMatchType.StartsWith: + if (url.startsWith(u.uri)) { + return true; + } + break; + case UriMatchType.RegularExpression: + try { + const regex = new RegExp(u.uri, "i"); + if (regex.test(url)) { + return true; + } + } catch (e) { + this.logService.error(e); + } + break; + case UriMatchType.Never: + default: + break; + } + } + } + + return false; + }); + } + + async getAllFromApiForOrganization(organizationId: string): Promise { + const ciphers = await this.apiService.getCiphersOrganization(organizationId); + if (ciphers != null && ciphers.data != null && ciphers.data.length) { + const decCiphers: CipherView[] = []; + const promises: any[] = []; + ciphers.data.forEach((r) => { + const data = new CipherData(r); + const cipher = new Cipher(data); + promises.push(cipher.decrypt().then((c) => decCiphers.push(c))); + }); + await Promise.all(promises); + decCiphers.sort(this.getLocaleSortingFunction()); + return decCiphers; + } else { + return []; + } + } + + async getLastUsedForUrl(url: string, autofillOnPageLoad = false): Promise { + return this.getCipherForUrl(url, true, false, autofillOnPageLoad); + } + + async getLastLaunchedForUrl(url: string, autofillOnPageLoad = false): Promise { + return this.getCipherForUrl(url, false, true, autofillOnPageLoad); + } + + async getNextCipherForUrl(url: string): Promise { + return this.getCipherForUrl(url, false, false, false); + } + + updateLastUsedIndexForUrl(url: string) { + this.sortedCiphersCache.updateLastUsedIndex(url); + } + + async updateLastUsedDate(id: string): Promise { + let ciphersLocalData = await this.stateService.getLocalData(); + if (!ciphersLocalData) { + ciphersLocalData = {}; + } + + if (ciphersLocalData[id]) { + ciphersLocalData[id].lastUsedDate = new Date().getTime(); + } else { + ciphersLocalData[id] = { + lastUsedDate: new Date().getTime(), + }; + } + + await this.stateService.setLocalData(ciphersLocalData); + + const decryptedCipherCache = await this.stateService.getDecryptedCiphers(); + if (!decryptedCipherCache) { + return; + } + + for (let i = 0; i < decryptedCipherCache.length; i++) { + const cached = decryptedCipherCache[i]; + if (cached.id === id) { + cached.localData = ciphersLocalData[id]; + break; + } + } + await this.stateService.setDecryptedCiphers(decryptedCipherCache); + } + + async updateLastLaunchedDate(id: string): Promise { + let ciphersLocalData = await this.stateService.getLocalData(); + if (!ciphersLocalData) { + ciphersLocalData = {}; + } + + if (ciphersLocalData[id]) { + ciphersLocalData[id].lastLaunched = new Date().getTime(); + } else { + ciphersLocalData[id] = { + lastUsedDate: new Date().getTime(), + }; + } + + await this.stateService.setLocalData(ciphersLocalData); + + const decryptedCipherCache = await this.stateService.getDecryptedCiphers(); + if (!decryptedCipherCache) { + return; + } + + for (let i = 0; i < decryptedCipherCache.length; i++) { + const cached = decryptedCipherCache[i]; + if (cached.id === id) { + cached.localData = ciphersLocalData[id]; + break; + } + } + await this.stateService.setDecryptedCiphers(decryptedCipherCache); + } + + async saveNeverDomain(domain: string): Promise { + if (domain == null) { + return; + } + + let domains = await this.stateService.getNeverDomains(); + if (!domains) { + domains = {}; + } + domains[domain] = null; + await this.stateService.setNeverDomains(domains); + } + + async saveWithServer(cipher: Cipher): Promise { + let response: CipherResponse; + if (cipher.id == null) { + if (cipher.collectionIds != null) { + const request = new CipherCreateRequest(cipher); + response = await this.apiService.postCipherCreate(request); + } else { + const request = new CipherRequest(cipher); + response = await this.apiService.postCipher(request); + } + cipher.id = response.id; + } else { + const request = new CipherRequest(cipher); + response = await this.apiService.putCipher(cipher.id, request); + } + + const data = new CipherData(response, cipher.collectionIds); + await this.upsert(data); + } + + async shareWithServer( + cipher: CipherView, + organizationId: string, + collectionIds: string[] + ): Promise { + const attachmentPromises: Promise[] = []; + if (cipher.attachments != null) { + cipher.attachments.forEach((attachment) => { + if (attachment.key == null) { + attachmentPromises.push( + this.shareAttachmentWithServer(attachment, cipher.id, organizationId) + ); + } + }); + } + await Promise.all(attachmentPromises); + + cipher.organizationId = organizationId; + cipher.collectionIds = collectionIds; + const encCipher = await this.encrypt(cipher); + const request = new CipherShareRequest(encCipher); + const response = await this.apiService.putShareCipher(cipher.id, request); + const data = new CipherData(response, collectionIds); + await this.upsert(data); + } + + async shareManyWithServer( + ciphers: CipherView[], + organizationId: string, + collectionIds: string[] + ): Promise { + const promises: Promise[] = []; + const encCiphers: Cipher[] = []; + for (const cipher of ciphers) { + cipher.organizationId = organizationId; + cipher.collectionIds = collectionIds; + promises.push( + this.encrypt(cipher).then((c) => { + encCiphers.push(c); + }) + ); + } + await Promise.all(promises); + const request = new CipherBulkShareRequest(encCiphers, collectionIds); + try { + await this.apiService.putShareCiphers(request); + } catch (e) { + for (const cipher of ciphers) { + cipher.organizationId = null; + cipher.collectionIds = null; + } + throw e; + } + await this.upsert(encCiphers.map((c) => c.toCipherData())); + } + + saveAttachmentWithServer(cipher: Cipher, unencryptedFile: any, admin = false): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsArrayBuffer(unencryptedFile); + reader.onload = async (evt: any) => { + try { + const cData = await this.saveAttachmentRawWithServer( + cipher, + unencryptedFile.name, + evt.target.result, + admin + ); + resolve(cData); + } catch (e) { + reject(e); + } + }; + reader.onerror = () => { + reject("Error reading file."); + }; + }); + } + + async saveAttachmentRawWithServer( + cipher: Cipher, + filename: string, + data: ArrayBuffer, + admin = false + ): Promise { + const key = await this.cryptoService.getOrgKey(cipher.organizationId); + const encFileName = await this.cryptoService.encrypt(filename, key); + + const dataEncKey = await this.cryptoService.makeEncKey(key); + const encData = await this.cryptoService.encryptToBytes(data, dataEncKey[0]); + + const request: AttachmentRequest = { + key: dataEncKey[1].encryptedString, + fileName: encFileName.encryptedString, + fileSize: encData.buffer.byteLength, + adminRequest: admin, + }; + + let response: CipherResponse; + try { + const uploadDataResponse = await this.apiService.postCipherAttachment(cipher.id, request); + response = admin ? uploadDataResponse.cipherMiniResponse : uploadDataResponse.cipherResponse; + await this.fileUploadService.uploadCipherAttachment( + admin, + uploadDataResponse, + encFileName, + encData + ); + } catch (e) { + if ( + (e instanceof ErrorResponse && (e as ErrorResponse).statusCode === 404) || + (e as ErrorResponse).statusCode === 405 + ) { + response = await this.legacyServerAttachmentFileUpload( + admin, + cipher.id, + encFileName, + encData, + dataEncKey[1] + ); + } else if (e instanceof ErrorResponse) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } else { + throw e; + } + } + + const cData = new CipherData(response, cipher.collectionIds); + if (!admin) { + await this.upsert(cData); + } + return new Cipher(cData); + } + + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + async legacyServerAttachmentFileUpload( + admin: boolean, + cipherId: string, + encFileName: EncString, + encData: EncArrayBuffer, + key: EncString + ) { + const fd = new FormData(); + try { + const blob = new Blob([encData.buffer], { type: "application/octet-stream" }); + fd.append("key", key.encryptedString); + fd.append("data", blob, encFileName.encryptedString); + } catch (e) { + if (Utils.isNode && !Utils.isBrowser) { + fd.append("key", key.encryptedString); + fd.append( + "data", + Buffer.from(encData.buffer) as any, + { + filepath: encFileName.encryptedString, + contentType: "application/octet-stream", + } as any + ); + } else { + throw e; + } + } + + let response: CipherResponse; + try { + if (admin) { + response = await this.apiService.postCipherAttachmentAdminLegacy(cipherId, fd); + } else { + response = await this.apiService.postCipherAttachmentLegacy(cipherId, fd); + } + } catch (e) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } + + return response; + } + + async saveCollectionsWithServer(cipher: Cipher): Promise { + const request = new CipherCollectionsRequest(cipher.collectionIds); + await this.apiService.putCipherCollections(cipher.id, request); + const data = cipher.toCipherData(); + await this.upsert(data); + } + + async upsert(cipher: CipherData | CipherData[]): Promise { + let ciphers = await this.stateService.getEncryptedCiphers(); + if (ciphers == null) { + ciphers = {}; + } + + if (cipher instanceof CipherData) { + const c = cipher as CipherData; + ciphers[c.id] = c; + } else { + (cipher as CipherData[]).forEach((c) => { + ciphers[c.id] = c; + }); + } + + await this.replace(ciphers); + } + + async replace(ciphers: { [id: string]: CipherData }): Promise { + await this.clearDecryptedCiphersState(); + await this.stateService.setEncryptedCiphers(ciphers); + } + + async clear(userId?: string): Promise { + await this.clearEncryptedCiphersState(userId); + await this.clearCache(userId); + } + + async moveManyWithServer(ids: string[], folderId: string): Promise { + await this.apiService.putMoveCiphers(new CipherBulkMoveRequest(ids, folderId)); + + let ciphers = await this.stateService.getEncryptedCiphers(); + if (ciphers == null) { + ciphers = {}; + } + + ids.forEach((id) => { + // eslint-disable-next-line + if (ciphers.hasOwnProperty(id)) { + ciphers[id].folderId = folderId; + } + }); + + await this.clearCache(); + await this.stateService.setEncryptedCiphers(ciphers); + } + + async delete(id: string | string[]): Promise { + const ciphers = await this.stateService.getEncryptedCiphers(); + if (ciphers == null) { + return; + } + + if (typeof id === "string") { + if (ciphers[id] == null) { + return; + } + delete ciphers[id]; + } else { + (id as string[]).forEach((i) => { + delete ciphers[i]; + }); + } + + await this.clearCache(); + await this.stateService.setEncryptedCiphers(ciphers); + } + + async deleteWithServer(id: string): Promise { + await this.apiService.deleteCipher(id); + await this.delete(id); + } + + async deleteManyWithServer(ids: string[]): Promise { + await this.apiService.deleteManyCiphers(new CipherBulkDeleteRequest(ids)); + await this.delete(ids); + } + + async deleteAttachment(id: string, attachmentId: string): Promise { + const ciphers = await this.stateService.getEncryptedCiphers(); + + // eslint-disable-next-line + if (ciphers == null || !ciphers.hasOwnProperty(id) || ciphers[id].attachments == null) { + return; + } + + for (let i = 0; i < ciphers[id].attachments.length; i++) { + if (ciphers[id].attachments[i].id === attachmentId) { + ciphers[id].attachments.splice(i, 1); + } + } + + await this.clearCache(); + await this.stateService.setEncryptedCiphers(ciphers); + } + + async deleteAttachmentWithServer(id: string, attachmentId: string): Promise { + try { + await this.apiService.deleteCipherAttachment(id, attachmentId); + } catch (e) { + return Promise.reject((e as ErrorResponse).getSingleMessage()); + } + await this.deleteAttachment(id, attachmentId); + } + + sortCiphersByLastUsed(a: CipherView, b: CipherView): number { + const aLastUsed = + a.localData && a.localData.lastUsedDate ? (a.localData.lastUsedDate as number) : null; + const bLastUsed = + b.localData && b.localData.lastUsedDate ? (b.localData.lastUsedDate as number) : null; + + const bothNotNull = aLastUsed != null && bLastUsed != null; + if (bothNotNull && aLastUsed < bLastUsed) { + return 1; + } + if (aLastUsed != null && bLastUsed == null) { + return -1; + } + + if (bothNotNull && aLastUsed > bLastUsed) { + return -1; + } + if (bLastUsed != null && aLastUsed == null) { + return 1; + } + + return 0; + } + + sortCiphersByLastUsedThenName(a: CipherView, b: CipherView): number { + const result = this.sortCiphersByLastUsed(a, b); + if (result !== 0) { + return result; + } + + return this.getLocaleSortingFunction()(a, b); + } + + getLocaleSortingFunction(): (a: CipherView, b: CipherView) => number { + return (a, b) => { + let aName = a.name; + let bName = b.name; + + if (aName == null && bName != null) { + return -1; + } + if (aName != null && bName == null) { + return 1; + } + if (aName == null && bName == null) { + return 0; + } + + const result = this.i18nService.collator + ? this.i18nService.collator.compare(aName, bName) + : aName.localeCompare(bName); + + if (result !== 0 || a.type !== CipherType.Login || b.type !== CipherType.Login) { + return result; + } + + if (a.login.username != null) { + aName += a.login.username; + } + + if (b.login.username != null) { + bName += b.login.username; + } + + return this.i18nService.collator + ? this.i18nService.collator.compare(aName, bName) + : aName.localeCompare(bName); + }; + } + + async softDelete(id: string | string[]): Promise { + const ciphers = await this.stateService.getEncryptedCiphers(); + if (ciphers == null) { + return; + } + + const setDeletedDate = (cipherId: string) => { + if (ciphers[cipherId] == null) { + return; + } + ciphers[cipherId].deletedDate = new Date().toISOString(); + }; + + if (typeof id === "string") { + setDeletedDate(id); + } else { + (id as string[]).forEach(setDeletedDate); + } + + await this.clearCache(); + await this.stateService.setEncryptedCiphers(ciphers); + } + + async softDeleteWithServer(id: string): Promise { + await this.apiService.putDeleteCipher(id); + await this.softDelete(id); + } + + async softDeleteManyWithServer(ids: string[]): Promise { + await this.apiService.putDeleteManyCiphers(new CipherBulkDeleteRequest(ids)); + await this.softDelete(ids); + } + + async restore( + cipher: { id: string; revisionDate: string } | { id: string; revisionDate: string }[] + ) { + const ciphers = await this.stateService.getEncryptedCiphers(); + if (ciphers == null) { + return; + } + + const clearDeletedDate = (c: { id: string; revisionDate: string }) => { + if (ciphers[c.id] == null) { + return; + } + ciphers[c.id].deletedDate = null; + ciphers[c.id].revisionDate = c.revisionDate; + }; + + if (cipher.constructor.name === Array.name) { + (cipher as { id: string; revisionDate: string }[]).forEach(clearDeletedDate); + } else { + clearDeletedDate(cipher as { id: string; revisionDate: string }); + } + + await this.clearCache(); + await this.stateService.setEncryptedCiphers(ciphers); + } + + async restoreWithServer(id: string): Promise { + const response = await this.apiService.putRestoreCipher(id); + await this.restore({ id: id, revisionDate: response.revisionDate }); + } + + async restoreManyWithServer(ids: string[]): Promise { + const response = await this.apiService.putRestoreManyCiphers(new CipherBulkRestoreRequest(ids)); + const restores: { id: string; revisionDate: string }[] = []; + for (const cipher of response.data) { + restores.push({ id: cipher.id, revisionDate: cipher.revisionDate }); + } + await this.restore(restores); + } + + // Helpers + + private async shareAttachmentWithServer( + attachmentView: AttachmentView, + cipherId: string, + organizationId: string + ): Promise { + const attachmentResponse = await this.apiService.nativeFetch( + new Request(attachmentView.url, { cache: "no-store" }) + ); + if (attachmentResponse.status !== 200) { + throw Error("Failed to download attachment: " + attachmentResponse.status.toString()); + } + + const buf = await attachmentResponse.arrayBuffer(); + const decBuf = await this.cryptoService.decryptFromBytes(buf, null); + const key = await this.cryptoService.getOrgKey(organizationId); + const encFileName = await this.cryptoService.encrypt(attachmentView.fileName, key); + + const dataEncKey = await this.cryptoService.makeEncKey(key); + const encData = await this.cryptoService.encryptToBytes(decBuf, dataEncKey[0]); + + const fd = new FormData(); + try { + const blob = new Blob([encData.buffer], { type: "application/octet-stream" }); + fd.append("key", dataEncKey[1].encryptedString); + fd.append("data", blob, encFileName.encryptedString); + } catch (e) { + if (Utils.isNode && !Utils.isBrowser) { + fd.append("key", dataEncKey[1].encryptedString); + fd.append( + "data", + Buffer.from(encData.buffer) as any, + { + filepath: encFileName.encryptedString, + contentType: "application/octet-stream", + } as any + ); + } else { + throw e; + } + } + + try { + await this.apiService.postShareCipherAttachment( + cipherId, + attachmentView.id, + fd, + organizationId + ); + } catch (e) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } + } + + private async encryptObjProperty( + model: V, + obj: D, + map: any, + key: SymmetricCryptoKey + ): Promise { + const promises = []; + const self = this; + + for (const prop in map) { + // eslint-disable-next-line + if (!map.hasOwnProperty(prop)) { + continue; + } + + (function (theProp, theObj) { + const p = Promise.resolve() + .then(() => { + const modelProp = (model as any)[map[theProp] || theProp]; + if (modelProp && modelProp !== "") { + return self.cryptoService.encrypt(modelProp, key); + } + return null; + }) + .then((val: EncString) => { + (theObj as any)[theProp] = val; + }); + promises.push(p); + })(prop, obj); + } + + await Promise.all(promises); + } + + private async encryptCipherData(cipher: Cipher, model: CipherView, key: SymmetricCryptoKey) { + switch (cipher.type) { + case CipherType.Login: + cipher.login = new Login(); + cipher.login.passwordRevisionDate = model.login.passwordRevisionDate; + cipher.login.autofillOnPageLoad = model.login.autofillOnPageLoad; + await this.encryptObjProperty( + model.login, + cipher.login, + { + username: null, + password: null, + totp: null, + }, + key + ); + + if (model.login.uris != null) { + cipher.login.uris = []; + for (let i = 0; i < model.login.uris.length; i++) { + const loginUri = new LoginUri(); + loginUri.match = model.login.uris[i].match; + await this.encryptObjProperty( + model.login.uris[i], + loginUri, + { + uri: null, + }, + key + ); + cipher.login.uris.push(loginUri); + } + } + return; + case CipherType.SecureNote: + cipher.secureNote = new SecureNote(); + cipher.secureNote.type = model.secureNote.type; + return; + case CipherType.Card: + cipher.card = new Card(); + await this.encryptObjProperty( + model.card, + cipher.card, + { + cardholderName: null, + brand: null, + number: null, + expMonth: null, + expYear: null, + code: null, + }, + key + ); + return; + case CipherType.Identity: + cipher.identity = new Identity(); + await this.encryptObjProperty( + model.identity, + cipher.identity, + { + title: null, + firstName: null, + middleName: null, + lastName: null, + address1: null, + address2: null, + address3: null, + city: null, + state: null, + postalCode: null, + country: null, + company: null, + email: null, + phone: null, + ssn: null, + username: null, + passportNumber: null, + licenseNumber: null, + }, + key + ); + return; + default: + throw new Error("Unknown cipher type."); + } + } + + private async getCipherForUrl( + url: string, + lastUsed: boolean, + lastLaunched: boolean, + autofillOnPageLoad: boolean + ): Promise { + const cacheKey = autofillOnPageLoad ? "autofillOnPageLoad-" + url : url; + + if (!this.sortedCiphersCache.isCached(cacheKey)) { + let ciphers = await this.getAllDecryptedForUrl(url); + if (!ciphers) { + return null; + } + + if (autofillOnPageLoad) { + const autofillOnPageLoadDefault = await this.stateService.getAutoFillOnPageLoadDefault(); + ciphers = ciphers.filter( + (cipher) => + cipher.login.autofillOnPageLoad || + (cipher.login.autofillOnPageLoad == null && autofillOnPageLoadDefault !== false) + ); + if (ciphers.length === 0) { + return null; + } + } + + this.sortedCiphersCache.addCiphers(cacheKey, ciphers); + } + + if (lastLaunched) { + return this.sortedCiphersCache.getLastLaunched(cacheKey); + } else if (lastUsed) { + return this.sortedCiphersCache.getLastUsed(cacheKey); + } else { + return this.sortedCiphersCache.getNext(cacheKey); + } + } + + private async clearEncryptedCiphersState(userId?: string) { + await this.stateService.setEncryptedCiphers(null, { userId: userId }); + } + + private async clearDecryptedCiphersState(userId?: string) { + await this.stateService.setDecryptedCiphers(null, { userId: userId }); + this.clearSortedCiphers(); + } + + private clearSortedCiphers() { + this.sortedCiphersCache.clear(); + } +} diff --git a/libs/common/src/services/collection.service.ts b/libs/common/src/services/collection.service.ts new file mode 100644 index 0000000000..4d3563d7c5 --- /dev/null +++ b/libs/common/src/services/collection.service.ts @@ -0,0 +1,157 @@ +import { CollectionService as CollectionServiceAbstraction } from "../abstractions/collection.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { StateService } from "../abstractions/state.service"; +import { ServiceUtils } from "../misc/serviceUtils"; +import { Utils } from "../misc/utils"; +import { CollectionData } from "../models/data/collectionData"; +import { Collection } from "../models/domain/collection"; +import { TreeNode } from "../models/domain/treeNode"; +import { CollectionView } from "../models/view/collectionView"; + +const NestingDelimiter = "/"; + +export class CollectionService implements CollectionServiceAbstraction { + constructor( + private cryptoService: CryptoService, + private i18nService: I18nService, + private stateService: StateService + ) {} + + async clearCache(userId?: string): Promise { + await this.stateService.setDecryptedCollections(null, { userId: userId }); + } + + async encrypt(model: CollectionView): Promise { + if (model.organizationId == null) { + throw new Error("Collection has no organization id."); + } + const key = await this.cryptoService.getOrgKey(model.organizationId); + if (key == null) { + throw new Error("No key for this collection's organization."); + } + const collection = new Collection(); + collection.id = model.id; + collection.organizationId = model.organizationId; + collection.readOnly = model.readOnly; + collection.name = await this.cryptoService.encrypt(model.name, key); + return collection; + } + + async decryptMany(collections: Collection[]): Promise { + if (collections == null) { + return []; + } + const decCollections: CollectionView[] = []; + const promises: Promise[] = []; + collections.forEach((collection) => { + promises.push(collection.decrypt().then((c) => decCollections.push(c))); + }); + await Promise.all(promises); + return decCollections.sort(Utils.getSortFunction(this.i18nService, "name")); + } + + async get(id: string): Promise { + const collections = await this.stateService.getEncryptedCollections(); + // eslint-disable-next-line + if (collections == null || !collections.hasOwnProperty(id)) { + return null; + } + + return new Collection(collections[id]); + } + + async getAll(): Promise { + const collections = await this.stateService.getEncryptedCollections(); + const response: Collection[] = []; + for (const id in collections) { + // eslint-disable-next-line + if (collections.hasOwnProperty(id)) { + response.push(new Collection(collections[id])); + } + } + return response; + } + + async getAllDecrypted(): Promise { + let decryptedCollections = await this.stateService.getDecryptedCollections(); + if (decryptedCollections != null) { + return decryptedCollections; + } + + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + throw new Error("No key."); + } + + const collections = await this.getAll(); + decryptedCollections = await this.decryptMany(collections); + await this.stateService.setDecryptedCollections(decryptedCollections); + return decryptedCollections; + } + + async getAllNested(collections: CollectionView[] = null): Promise[]> { + if (collections == null) { + collections = await this.getAllDecrypted(); + } + const nodes: TreeNode[] = []; + collections.forEach((c) => { + const collectionCopy = new CollectionView(); + collectionCopy.id = c.id; + collectionCopy.organizationId = c.organizationId; + const parts = c.name != null ? c.name.replace(/^\/+|\/+$/g, "").split(NestingDelimiter) : []; + ServiceUtils.nestedTraverse(nodes, 0, parts, collectionCopy, null, NestingDelimiter); + }); + return nodes; + } + + async getNested(id: string): Promise> { + const collections = await this.getAllNested(); + return ServiceUtils.getTreeNodeObject(collections, id) as TreeNode; + } + + async upsert(collection: CollectionData | CollectionData[]): Promise { + let collections = await this.stateService.getEncryptedCollections(); + if (collections == null) { + collections = {}; + } + + if (collection instanceof CollectionData) { + const c = collection as CollectionData; + collections[c.id] = c; + } else { + (collection as CollectionData[]).forEach((c) => { + collections[c.id] = c; + }); + } + + await this.replace(collections); + } + + async replace(collections: { [id: string]: CollectionData }): Promise { + await this.clearCache(); + await this.stateService.setEncryptedCollections(collections); + } + + async clear(userId?: string): Promise { + await this.clearCache(userId); + await this.stateService.setEncryptedCollections(null, { userId: userId }); + } + + async delete(id: string | string[]): Promise { + const collections = await this.stateService.getEncryptedCollections(); + if (collections == null) { + return; + } + + if (typeof id === "string") { + delete collections[id]; + } else { + (id as string[]).forEach((i) => { + delete collections[i]; + }); + } + + await this.replace(collections); + } +} diff --git a/libs/common/src/services/consoleLog.service.ts b/libs/common/src/services/consoleLog.service.ts new file mode 100644 index 0000000000..9959ef6229 --- /dev/null +++ b/libs/common/src/services/consoleLog.service.ts @@ -0,0 +1,72 @@ +import * as hrtime from "browser-hrtime"; + +import { LogService as LogServiceAbstraction } from "../abstractions/log.service"; +import { LogLevelType } from "../enums/logLevelType"; + +export class ConsoleLogService implements LogServiceAbstraction { + protected timersMap: Map = new Map(); + + constructor( + protected isDev: boolean, + protected filter: (level: LogLevelType) => boolean = null + ) {} + + debug(message: string) { + if (!this.isDev) { + return; + } + this.write(LogLevelType.Debug, message); + } + + info(message: string) { + this.write(LogLevelType.Info, message); + } + + warning(message: string) { + this.write(LogLevelType.Warning, message); + } + + error(message: string) { + this.write(LogLevelType.Error, message); + } + + write(level: LogLevelType, message: string) { + if (this.filter != null && this.filter(level)) { + return; + } + + switch (level) { + case LogLevelType.Debug: + // eslint-disable-next-line + console.log(message); + break; + case LogLevelType.Info: + // eslint-disable-next-line + console.log(message); + break; + case LogLevelType.Warning: + // eslint-disable-next-line + console.warn(message); + break; + case LogLevelType.Error: + // eslint-disable-next-line + console.error(message); + break; + default: + break; + } + } + + time(label = "default") { + if (!this.timersMap.has(label)) { + this.timersMap.set(label, hrtime()); + } + } + + timeEnd(label = "default"): [number, number] { + const elapsed = hrtime(this.timersMap.get(label)); + this.timersMap.delete(label); + this.write(LogLevelType.Info, `${label}: ${elapsed[0] * 1000 + elapsed[1] / 10e6}ms`); + return elapsed; + } +} diff --git a/libs/common/src/services/container.service.ts b/libs/common/src/services/container.service.ts new file mode 100644 index 0000000000..2880e7c780 --- /dev/null +++ b/libs/common/src/services/container.service.ts @@ -0,0 +1,20 @@ +import { CryptoService } from "../abstractions/crypto.service"; + +export class ContainerService { + constructor(private cryptoService: CryptoService) {} + + // deprecated, use attachToGlobal instead + attachToWindow(win: any) { + this.attachToGlobal(win); + } + + attachToGlobal(global: any) { + if (!global.bitwardenContainerService) { + global.bitwardenContainerService = this; + } + } + + getCryptoService(): CryptoService { + return this.cryptoService; + } +} diff --git a/libs/common/src/services/crypto.service.ts b/libs/common/src/services/crypto.service.ts new file mode 100644 index 0000000000..c49d7763e3 --- /dev/null +++ b/libs/common/src/services/crypto.service.ts @@ -0,0 +1,969 @@ +import * as bigInt from "big-integer"; + +import { CryptoService as CryptoServiceAbstraction } from "../abstractions/crypto.service"; +import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; +import { LogService } from "../abstractions/log.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; +import { StateService } from "../abstractions/state.service"; +import { EncryptionType } from "../enums/encryptionType"; +import { HashPurpose } from "../enums/hashPurpose"; +import { KdfType } from "../enums/kdfType"; +import { KeySuffixOptions } from "../enums/keySuffixOptions"; +import { sequentialize } from "../misc/sequentialize"; +import { Utils } from "../misc/utils"; +import { EEFLongWordList } from "../misc/wordlist"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; +import { EncString } from "../models/domain/encString"; +import { EncryptedObject } from "../models/domain/encryptedObject"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { ProfileOrganizationResponse } from "../models/response/profileOrganizationResponse"; +import { ProfileProviderOrganizationResponse } from "../models/response/profileProviderOrganizationResponse"; +import { ProfileProviderResponse } from "../models/response/profileProviderResponse"; + +export class CryptoService implements CryptoServiceAbstraction { + constructor( + private cryptoFunctionService: CryptoFunctionService, + protected platformUtilService: PlatformUtilsService, + protected logService: LogService, + protected stateService: StateService + ) {} + + async setKey(key: SymmetricCryptoKey, userId?: string): Promise { + await this.stateService.setCryptoMasterKey(key, { userId: userId }); + await this.storeKey(key, userId); + } + + async setKeyHash(keyHash: string): Promise { + await this.stateService.setKeyHash(keyHash); + } + + async setEncKey(encKey: string): Promise { + if (encKey == null) { + return; + } + + await this.stateService.setDecryptedCryptoSymmetricKey(null); + await this.stateService.setEncryptedCryptoSymmetricKey(encKey); + } + + async setEncPrivateKey(encPrivateKey: string): Promise { + if (encPrivateKey == null) { + return; + } + + await this.stateService.setDecryptedPrivateKey(null); + await this.stateService.setEncryptedPrivateKey(encPrivateKey); + } + + async setOrgKeys( + orgs: ProfileOrganizationResponse[], + providerOrgs: ProfileProviderOrganizationResponse[] + ): Promise { + const orgKeys: any = {}; + orgs.forEach((org) => { + orgKeys[org.id] = org.key; + }); + + for (const providerOrg of providerOrgs) { + // Convert provider encrypted keys to user encrypted. + const providerKey = await this.getProviderKey(providerOrg.providerId); + const decValue = await this.decryptToBytes(new EncString(providerOrg.key), providerKey); + orgKeys[providerOrg.id] = (await this.rsaEncrypt(decValue)).encryptedString; + } + + await this.stateService.setDecryptedOrganizationKeys(null); + return await this.stateService.setEncryptedOrganizationKeys(orgKeys); + } + + async setProviderKeys(providers: ProfileProviderResponse[]): Promise { + const providerKeys: any = {}; + providers.forEach((provider) => { + providerKeys[provider.id] = provider.key; + }); + + await this.stateService.setDecryptedProviderKeys(null); + return await this.stateService.setEncryptedProviderKeys(providerKeys); + } + + async getKey(keySuffix?: KeySuffixOptions, userId?: string): Promise { + const inMemoryKey = await this.stateService.getCryptoMasterKey({ userId: userId }); + + if (inMemoryKey != null) { + return inMemoryKey; + } + + keySuffix ||= KeySuffixOptions.Auto; + const symmetricKey = await this.getKeyFromStorage(keySuffix, userId); + + if (symmetricKey != null) { + // TODO: Refactor here so get key doesn't also set key + this.setKey(symmetricKey, userId); + } + + return symmetricKey; + } + + async getKeyFromStorage( + keySuffix: KeySuffixOptions, + userId?: string + ): Promise { + const key = await this.retrieveKeyFromStorage(keySuffix, userId); + if (key != null) { + const symmetricKey = new SymmetricCryptoKey(Utils.fromB64ToArray(key).buffer); + + if (!(await this.validateKey(symmetricKey))) { + this.logService.warning("Wrong key, throwing away stored key"); + await this.clearSecretKeyStore(userId); + return null; + } + + return symmetricKey; + } + return null; + } + + async getKeyHash(): Promise { + return await this.stateService.getKeyHash(); + } + + async compareAndUpdateKeyHash(masterPassword: string, key: SymmetricCryptoKey): Promise { + const storedKeyHash = await this.getKeyHash(); + if (masterPassword != null && storedKeyHash != null) { + const localKeyHash = await this.hashPassword( + masterPassword, + key, + HashPurpose.LocalAuthorization + ); + if (localKeyHash != null && storedKeyHash === localKeyHash) { + return true; + } + + // TODO: remove serverKeyHash check in 1-2 releases after everyone's keyHash has been updated + const serverKeyHash = await this.hashPassword( + masterPassword, + key, + HashPurpose.ServerAuthorization + ); + if (serverKeyHash != null && storedKeyHash === serverKeyHash) { + await this.setKeyHash(localKeyHash); + return true; + } + } + + return false; + } + + @sequentialize(() => "getEncKey") + getEncKey(key: SymmetricCryptoKey = null): Promise { + return this.getEncKeyHelper(key); + } + + async getPublicKey(): Promise { + const inMemoryPublicKey = await this.stateService.getPublicKey(); + if (inMemoryPublicKey != null) { + return inMemoryPublicKey; + } + + const privateKey = await this.getPrivateKey(); + if (privateKey == null) { + return null; + } + + const publicKey = await this.cryptoFunctionService.rsaExtractPublicKey(privateKey); + await this.stateService.setPublicKey(publicKey); + return publicKey; + } + + async getPrivateKey(): Promise { + const decryptedPrivateKey = await this.stateService.getDecryptedPrivateKey(); + if (decryptedPrivateKey != null) { + return decryptedPrivateKey; + } + + const encPrivateKey = await this.stateService.getEncryptedPrivateKey(); + if (encPrivateKey == null) { + return null; + } + + const privateKey = await this.decryptToBytes(new EncString(encPrivateKey), null); + await this.stateService.setDecryptedPrivateKey(privateKey); + return privateKey; + } + + async getFingerprint(userId: string, publicKey?: ArrayBuffer): Promise { + if (publicKey == null) { + publicKey = await this.getPublicKey(); + } + if (publicKey === null) { + throw new Error("No public key available."); + } + const keyFingerprint = await this.cryptoFunctionService.hash(publicKey, "sha256"); + const userFingerprint = await this.cryptoFunctionService.hkdfExpand( + keyFingerprint, + userId, + 32, + "sha256" + ); + return this.hashPhrase(userFingerprint); + } + + @sequentialize(() => "getOrgKeys") + async getOrgKeys(): Promise> { + const orgKeys: Map = new Map(); + const decryptedOrganizationKeys = await this.stateService.getDecryptedOrganizationKeys(); + if (decryptedOrganizationKeys != null && decryptedOrganizationKeys.size > 0) { + return decryptedOrganizationKeys; + } + + const encOrgKeys = await this.stateService.getEncryptedOrganizationKeys(); + if (encOrgKeys == null) { + return null; + } + + let setKey = false; + + for (const orgId in encOrgKeys) { + // eslint-disable-next-line + if (!encOrgKeys.hasOwnProperty(orgId)) { + continue; + } + + const decValue = await this.rsaDecrypt(encOrgKeys[orgId]); + orgKeys.set(orgId, new SymmetricCryptoKey(decValue)); + setKey = true; + } + + if (setKey) { + await this.stateService.setDecryptedOrganizationKeys(orgKeys); + } + + return orgKeys; + } + + async getOrgKey(orgId: string): Promise { + if (orgId == null) { + return null; + } + + const orgKeys = await this.getOrgKeys(); + if (orgKeys == null || !orgKeys.has(orgId)) { + return null; + } + + return orgKeys.get(orgId); + } + + @sequentialize(() => "getProviderKeys") + async getProviderKeys(): Promise> { + const providerKeys: Map = new Map(); + const decryptedProviderKeys = await this.stateService.getDecryptedProviderKeys(); + if (decryptedProviderKeys != null && decryptedProviderKeys.size > 0) { + return decryptedProviderKeys; + } + + const encProviderKeys = await this.stateService.getEncryptedProviderKeys(); + if (encProviderKeys == null) { + return null; + } + + let setKey = false; + + for (const orgId in encProviderKeys) { + // eslint-disable-next-line + if (!encProviderKeys.hasOwnProperty(orgId)) { + continue; + } + + const decValue = await this.rsaDecrypt(encProviderKeys[orgId]); + providerKeys.set(orgId, new SymmetricCryptoKey(decValue)); + setKey = true; + } + + if (setKey) { + await this.stateService.setDecryptedProviderKeys(providerKeys); + } + + return providerKeys; + } + + async getProviderKey(providerId: string): Promise { + if (providerId == null) { + return null; + } + + const providerKeys = await this.getProviderKeys(); + if (providerKeys == null || !providerKeys.has(providerId)) { + return null; + } + + return providerKeys.get(providerId); + } + + async hasKey(): Promise { + return ( + (await this.hasKeyInMemory()) || + (await this.hasKeyStored(KeySuffixOptions.Auto)) || + (await this.hasKeyStored(KeySuffixOptions.Biometric)) + ); + } + + async hasKeyInMemory(userId?: string): Promise { + return (await this.stateService.getCryptoMasterKey({ userId: userId })) != null; + } + + async hasKeyStored(keySuffix: KeySuffixOptions, userId?: string): Promise { + switch (keySuffix) { + case KeySuffixOptions.Auto: + return (await this.stateService.getCryptoMasterKeyAuto({ userId: userId })) != null; + case KeySuffixOptions.Biometric: + return (await this.stateService.hasCryptoMasterKeyBiometric({ userId: userId })) === true; + default: + return false; + } + } + + async hasEncKey(): Promise { + return (await this.stateService.getEncryptedCryptoSymmetricKey()) != null; + } + + async clearKey(clearSecretStorage = true, userId?: string): Promise { + await this.stateService.setCryptoMasterKey(null, { userId: userId }); + await this.stateService.setLegacyEtmKey(null, { userId: userId }); + if (clearSecretStorage) { + await this.clearSecretKeyStore(userId); + } + } + + async clearStoredKey(keySuffix: KeySuffixOptions) { + keySuffix === KeySuffixOptions.Auto + ? await this.stateService.setCryptoMasterKeyAuto(null) + : await this.stateService.setCryptoMasterKeyBiometric(null); + } + + async clearKeyHash(userId?: string): Promise { + return await this.stateService.setKeyHash(null, { userId: userId }); + } + + async clearEncKey(memoryOnly?: boolean, userId?: string): Promise { + await this.stateService.setDecryptedCryptoSymmetricKey(null, { userId: userId }); + if (!memoryOnly) { + await this.stateService.setEncryptedCryptoSymmetricKey(null, { userId: userId }); + } + } + + async clearKeyPair(memoryOnly?: boolean, userId?: string): Promise { + const keysToClear: Promise[] = [ + this.stateService.setDecryptedPrivateKey(null, { userId: userId }), + this.stateService.setPublicKey(null, { userId: userId }), + ]; + if (!memoryOnly) { + keysToClear.push(this.stateService.setEncryptedPrivateKey(null, { userId: userId })); + } + return Promise.all(keysToClear); + } + + async clearOrgKeys(memoryOnly?: boolean, userId?: string): Promise { + await this.stateService.setDecryptedOrganizationKeys(null, { userId: userId }); + if (!memoryOnly) { + await this.stateService.setEncryptedOrganizationKeys(null, { userId: userId }); + } + } + + async clearProviderKeys(memoryOnly?: boolean, userId?: string): Promise { + await this.stateService.setDecryptedProviderKeys(null, { userId: userId }); + if (!memoryOnly) { + await this.stateService.setEncryptedProviderKeys(null, { userId: userId }); + } + } + + async clearPinProtectedKey(userId?: string): Promise { + return await this.stateService.setEncryptedPinProtected(null, { userId: userId }); + } + + async clearKeys(userId?: string): Promise { + await this.clearKey(true, userId); + await this.clearKeyHash(userId); + await this.clearOrgKeys(false, userId); + await this.clearProviderKeys(false, userId); + await this.clearEncKey(false, userId); + await this.clearKeyPair(false, userId); + await this.clearPinProtectedKey(userId); + } + + async toggleKey(): Promise { + const key = await this.getKey(); + + await this.setKey(key); + } + + async makeKey( + password: string, + salt: string, + kdf: KdfType, + kdfIterations: number + ): Promise { + let key: ArrayBuffer = null; + if (kdf == null || kdf === KdfType.PBKDF2_SHA256) { + if (kdfIterations == null) { + kdfIterations = 5000; + } else if (kdfIterations < 5000) { + throw new Error("PBKDF2 iteration minimum is 5000."); + } + key = await this.cryptoFunctionService.pbkdf2(password, salt, "sha256", kdfIterations); + } else { + throw new Error("Unknown Kdf."); + } + return new SymmetricCryptoKey(key); + } + + async makeKeyFromPin( + pin: string, + salt: string, + kdf: KdfType, + kdfIterations: number, + protectedKeyCs: EncString = null + ): Promise { + if (protectedKeyCs == null) { + const pinProtectedKey = await this.stateService.getEncryptedPinProtected(); + if (pinProtectedKey == null) { + throw new Error("No PIN protected key found."); + } + protectedKeyCs = new EncString(pinProtectedKey); + } + const pinKey = await this.makePinKey(pin, salt, kdf, kdfIterations); + const decKey = await this.decryptToBytes(protectedKeyCs, pinKey); + return new SymmetricCryptoKey(decKey); + } + + async makeShareKey(): Promise<[EncString, SymmetricCryptoKey]> { + const shareKey = await this.cryptoFunctionService.randomBytes(64); + const publicKey = await this.getPublicKey(); + const encShareKey = await this.rsaEncrypt(shareKey, publicKey); + return [encShareKey, new SymmetricCryptoKey(shareKey)]; + } + + async makeKeyPair(key?: SymmetricCryptoKey): Promise<[string, EncString]> { + const keyPair = await this.cryptoFunctionService.rsaGenerateKeyPair(2048); + const publicB64 = Utils.fromBufferToB64(keyPair[0]); + const privateEnc = await this.encrypt(keyPair[1], key); + return [publicB64, privateEnc]; + } + + async makePinKey( + pin: string, + salt: string, + kdf: KdfType, + kdfIterations: number + ): Promise { + const pinKey = await this.makeKey(pin, salt, kdf, kdfIterations); + return await this.stretchKey(pinKey); + } + + async makeSendKey(keyMaterial: ArrayBuffer): Promise { + const sendKey = await this.cryptoFunctionService.hkdf( + keyMaterial, + "bitwarden-send", + "send", + 64, + "sha256" + ); + return new SymmetricCryptoKey(sendKey); + } + + async hashPassword( + password: string, + key: SymmetricCryptoKey, + hashPurpose?: HashPurpose + ): Promise { + if (key == null) { + key = await this.getKey(); + } + if (password == null || key == null) { + throw new Error("Invalid parameters."); + } + + const iterations = hashPurpose === HashPurpose.LocalAuthorization ? 2 : 1; + const hash = await this.cryptoFunctionService.pbkdf2(key.key, password, "sha256", iterations); + return Utils.fromBufferToB64(hash); + } + + async makeEncKey(key: SymmetricCryptoKey): Promise<[SymmetricCryptoKey, EncString]> { + const theKey = await this.getKeyForEncryption(key); + const encKey = await this.cryptoFunctionService.randomBytes(64); + return this.buildEncKey(theKey, encKey); + } + + async remakeEncKey( + key: SymmetricCryptoKey, + encKey?: SymmetricCryptoKey + ): Promise<[SymmetricCryptoKey, EncString]> { + if (encKey == null) { + encKey = await this.getEncKey(); + } + return this.buildEncKey(key, encKey.key); + } + + async encrypt(plainValue: string | ArrayBuffer, key?: SymmetricCryptoKey): Promise { + if (plainValue == null) { + return Promise.resolve(null); + } + + let plainBuf: ArrayBuffer; + if (typeof plainValue === "string") { + plainBuf = Utils.fromUtf8ToArray(plainValue).buffer; + } else { + plainBuf = plainValue; + } + + const encObj = await this.aesEncrypt(plainBuf, key); + const iv = Utils.fromBufferToB64(encObj.iv); + const data = Utils.fromBufferToB64(encObj.data); + const mac = encObj.mac != null ? Utils.fromBufferToB64(encObj.mac) : null; + return new EncString(encObj.key.encType, data, iv, mac); + } + + async encryptToBytes(plainValue: ArrayBuffer, key?: SymmetricCryptoKey): Promise { + const encValue = await this.aesEncrypt(plainValue, key); + let macLen = 0; + if (encValue.mac != null) { + macLen = encValue.mac.byteLength; + } + + const encBytes = new Uint8Array(1 + encValue.iv.byteLength + macLen + encValue.data.byteLength); + encBytes.set([encValue.key.encType]); + encBytes.set(new Uint8Array(encValue.iv), 1); + if (encValue.mac != null) { + encBytes.set(new Uint8Array(encValue.mac), 1 + encValue.iv.byteLength); + } + + encBytes.set(new Uint8Array(encValue.data), 1 + encValue.iv.byteLength + macLen); + return new EncArrayBuffer(encBytes.buffer); + } + + async rsaEncrypt(data: ArrayBuffer, publicKey?: ArrayBuffer): Promise { + if (publicKey == null) { + publicKey = await this.getPublicKey(); + } + if (publicKey == null) { + throw new Error("Public key unavailable."); + } + + const encBytes = await this.cryptoFunctionService.rsaEncrypt(data, publicKey, "sha1"); + return new EncString(EncryptionType.Rsa2048_OaepSha1_B64, Utils.fromBufferToB64(encBytes)); + } + + async rsaDecrypt(encValue: string, privateKeyValue?: ArrayBuffer): Promise { + const headerPieces = encValue.split("."); + let encType: EncryptionType = null; + let encPieces: string[]; + + if (headerPieces.length === 1) { + encType = EncryptionType.Rsa2048_OaepSha256_B64; + encPieces = [headerPieces[0]]; + } else if (headerPieces.length === 2) { + try { + encType = parseInt(headerPieces[0], null); + encPieces = headerPieces[1].split("|"); + } catch (e) { + this.logService.error(e); + } + } + + switch (encType) { + case EncryptionType.Rsa2048_OaepSha256_B64: + case EncryptionType.Rsa2048_OaepSha1_B64: + case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: // HmacSha256 types are deprecated + case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: + break; + default: + throw new Error("encType unavailable."); + } + + if (encPieces == null || encPieces.length <= 0) { + throw new Error("encPieces unavailable."); + } + + const data = Utils.fromB64ToArray(encPieces[0]).buffer; + const privateKey = privateKeyValue ?? (await this.getPrivateKey()); + if (privateKey == null) { + throw new Error("No private key."); + } + + let alg: "sha1" | "sha256" = "sha1"; + switch (encType) { + case EncryptionType.Rsa2048_OaepSha256_B64: + case EncryptionType.Rsa2048_OaepSha256_HmacSha256_B64: + alg = "sha256"; + break; + case EncryptionType.Rsa2048_OaepSha1_B64: + case EncryptionType.Rsa2048_OaepSha1_HmacSha256_B64: + break; + default: + throw new Error("encType unavailable."); + } + + return this.cryptoFunctionService.rsaDecrypt(data, privateKey, alg); + } + + async decryptToBytes(encString: EncString, key?: SymmetricCryptoKey): Promise { + const iv = Utils.fromB64ToArray(encString.iv).buffer; + const data = Utils.fromB64ToArray(encString.data).buffer; + const mac = encString.mac ? Utils.fromB64ToArray(encString.mac).buffer : null; + const decipher = await this.aesDecryptToBytes(encString.encryptionType, data, iv, mac, key); + if (decipher == null) { + return null; + } + + return decipher; + } + + async decryptToUtf8(encString: EncString, key?: SymmetricCryptoKey): Promise { + return await this.aesDecryptToUtf8( + encString.encryptionType, + encString.data, + encString.iv, + encString.mac, + key + ); + } + + async decryptFromBytes(encBuf: ArrayBuffer, key: SymmetricCryptoKey): Promise { + if (encBuf == null) { + throw new Error("no encBuf."); + } + + const encBytes = new Uint8Array(encBuf); + const encType = encBytes[0]; + let ctBytes: Uint8Array = null; + let ivBytes: Uint8Array = null; + let macBytes: Uint8Array = null; + + switch (encType) { + case EncryptionType.AesCbc128_HmacSha256_B64: + case EncryptionType.AesCbc256_HmacSha256_B64: + if (encBytes.length <= 49) { + // 1 + 16 + 32 + ctLength + return null; + } + + ivBytes = encBytes.slice(1, 17); + macBytes = encBytes.slice(17, 49); + ctBytes = encBytes.slice(49); + break; + case EncryptionType.AesCbc256_B64: + if (encBytes.length <= 17) { + // 1 + 16 + ctLength + return null; + } + + ivBytes = encBytes.slice(1, 17); + ctBytes = encBytes.slice(17); + break; + default: + return null; + } + + return await this.aesDecryptToBytes( + encType, + ctBytes.buffer, + ivBytes.buffer, + macBytes != null ? macBytes.buffer : null, + key + ); + } + + // EFForg/OpenWireless + // ref https://github.com/EFForg/OpenWireless/blob/master/app/js/diceware.js + async randomNumber(min: number, max: number): Promise { + let rval = 0; + const range = max - min + 1; + const bitsNeeded = Math.ceil(Math.log2(range)); + if (bitsNeeded > 53) { + throw new Error("We cannot generate numbers larger than 53 bits."); + } + + const bytesNeeded = Math.ceil(bitsNeeded / 8); + const mask = Math.pow(2, bitsNeeded) - 1; + // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 + + // Fill a byte array with N random numbers + const byteArray = new Uint8Array(await this.cryptoFunctionService.randomBytes(bytesNeeded)); + + let p = (bytesNeeded - 1) * 8; + for (let i = 0; i < bytesNeeded; i++) { + rval += byteArray[i] * Math.pow(2, p); + p -= 8; + } + + // Use & to apply the mask and reduce the number of recursive lookups + rval = rval & mask; + + if (rval >= range) { + // Integer out of acceptable range + return this.randomNumber(min, max); + } + + // Return an integer that falls within the range + return min + rval; + } + + async validateKey(key: SymmetricCryptoKey) { + try { + const encPrivateKey = await this.stateService.getEncryptedPrivateKey(); + const encKey = await this.getEncKeyHelper(key); + if (encPrivateKey == null || encKey == null) { + return false; + } + + const privateKey = await this.decryptToBytes(new EncString(encPrivateKey), encKey); + await this.cryptoFunctionService.rsaExtractPublicKey(privateKey); + } catch (e) { + return false; + } + + return true; + } + + // Helpers + protected async storeKey(key: SymmetricCryptoKey, userId?: string) { + if (await this.shouldStoreKey(KeySuffixOptions.Auto, userId)) { + await this.stateService.setCryptoMasterKeyAuto(key.keyB64, { userId: userId }); + } else if (await this.shouldStoreKey(KeySuffixOptions.Biometric, userId)) { + await this.stateService.setCryptoMasterKeyBiometric(key.keyB64, { userId: userId }); + } else { + await this.stateService.setCryptoMasterKeyAuto(null, { userId: userId }); + await this.stateService.setCryptoMasterKeyBiometric(null, { userId: userId }); + } + } + + protected async shouldStoreKey(keySuffix: KeySuffixOptions, userId?: string) { + let shouldStoreKey = false; + if (keySuffix === KeySuffixOptions.Auto) { + const vaultTimeout = await this.stateService.getVaultTimeout({ userId: userId }); + shouldStoreKey = vaultTimeout == null; + } else if (keySuffix === KeySuffixOptions.Biometric) { + const biometricUnlock = await this.stateService.getBiometricUnlock({ userId: userId }); + shouldStoreKey = biometricUnlock && this.platformUtilService.supportsSecureStorage(); + } + return shouldStoreKey; + } + + protected async retrieveKeyFromStorage(keySuffix: KeySuffixOptions, userId?: string) { + return keySuffix === KeySuffixOptions.Auto + ? await this.stateService.getCryptoMasterKeyAuto({ userId: userId }) + : await this.stateService.getCryptoMasterKeyBiometric({ userId: userId }); + } + + private async aesEncrypt(data: ArrayBuffer, key: SymmetricCryptoKey): Promise { + const obj = new EncryptedObject(); + obj.key = await this.getKeyForEncryption(key); + obj.iv = await this.cryptoFunctionService.randomBytes(16); + obj.data = await this.cryptoFunctionService.aesEncrypt(data, obj.iv, obj.key.encKey); + + if (obj.key.macKey != null) { + const macData = new Uint8Array(obj.iv.byteLength + obj.data.byteLength); + macData.set(new Uint8Array(obj.iv), 0); + macData.set(new Uint8Array(obj.data), obj.iv.byteLength); + obj.mac = await this.cryptoFunctionService.hmac(macData.buffer, obj.key.macKey, "sha256"); + } + + return obj; + } + + private async aesDecryptToUtf8( + encType: EncryptionType, + data: string, + iv: string, + mac: string, + key: SymmetricCryptoKey + ): Promise { + const keyForEnc = await this.getKeyForEncryption(key); + const theKey = await this.resolveLegacyKey(encType, keyForEnc); + + if (theKey.macKey != null && mac == null) { + this.logService.error("mac required."); + return null; + } + + if (theKey.encType !== encType) { + this.logService.error("encType unavailable."); + return null; + } + + const fastParams = this.cryptoFunctionService.aesDecryptFastParameters(data, iv, mac, theKey); + if (fastParams.macKey != null && fastParams.mac != null) { + const computedMac = await this.cryptoFunctionService.hmacFast( + fastParams.macData, + fastParams.macKey, + "sha256" + ); + const macsEqual = await this.cryptoFunctionService.compareFast(fastParams.mac, computedMac); + if (!macsEqual) { + this.logService.error("mac failed."); + return null; + } + } + + return this.cryptoFunctionService.aesDecryptFast(fastParams); + } + + private async aesDecryptToBytes( + encType: EncryptionType, + data: ArrayBuffer, + iv: ArrayBuffer, + mac: ArrayBuffer, + key: SymmetricCryptoKey + ): Promise { + const keyForEnc = await this.getKeyForEncryption(key); + const theKey = await this.resolveLegacyKey(encType, keyForEnc); + + if (theKey.macKey != null && mac == null) { + return null; + } + + if (theKey.encType !== encType) { + return null; + } + + if (theKey.macKey != null && mac != null) { + const macData = new Uint8Array(iv.byteLength + data.byteLength); + macData.set(new Uint8Array(iv), 0); + macData.set(new Uint8Array(data), iv.byteLength); + const computedMac = await this.cryptoFunctionService.hmac( + macData.buffer, + theKey.macKey, + "sha256" + ); + if (computedMac === null) { + return null; + } + + const macsMatch = await this.cryptoFunctionService.compare(mac, computedMac); + if (!macsMatch) { + this.logService.error("mac failed."); + return null; + } + } + + return await this.cryptoFunctionService.aesDecrypt(data, iv, theKey.encKey); + } + + private async getKeyForEncryption(key?: SymmetricCryptoKey): Promise { + if (key != null) { + return key; + } + + const encKey = await this.getEncKey(); + if (encKey != null) { + return encKey; + } + + return await this.getKey(); + } + + private async resolveLegacyKey( + encType: EncryptionType, + key: SymmetricCryptoKey + ): Promise { + if ( + encType === EncryptionType.AesCbc128_HmacSha256_B64 && + key.encType === EncryptionType.AesCbc256_B64 + ) { + // Old encrypt-then-mac scheme, make a new key + let legacyKey = await this.stateService.getLegacyEtmKey(); + if (legacyKey == null) { + legacyKey = new SymmetricCryptoKey(key.key, EncryptionType.AesCbc128_HmacSha256_B64); + await this.stateService.setLegacyEtmKey(legacyKey); + } + return legacyKey; + } + + return key; + } + + private async stretchKey(key: SymmetricCryptoKey): Promise { + const newKey = new Uint8Array(64); + const encKey = await this.cryptoFunctionService.hkdfExpand(key.key, "enc", 32, "sha256"); + const macKey = await this.cryptoFunctionService.hkdfExpand(key.key, "mac", 32, "sha256"); + newKey.set(new Uint8Array(encKey)); + newKey.set(new Uint8Array(macKey), 32); + return new SymmetricCryptoKey(newKey.buffer); + } + + private async hashPhrase(hash: ArrayBuffer, minimumEntropy = 64) { + const entropyPerWord = Math.log(EEFLongWordList.length) / Math.log(2); + let numWords = Math.ceil(minimumEntropy / entropyPerWord); + + const hashArr = Array.from(new Uint8Array(hash)); + const entropyAvailable = hashArr.length * 4; + if (numWords * entropyPerWord > entropyAvailable) { + throw new Error("Output entropy of hash function is too small"); + } + + const phrase: string[] = []; + let hashNumber = bigInt.fromArray(hashArr, 256); + while (numWords--) { + const remainder = hashNumber.mod(EEFLongWordList.length); + hashNumber = hashNumber.divide(EEFLongWordList.length); + phrase.push(EEFLongWordList[remainder as any]); + } + return phrase; + } + + private async buildEncKey( + key: SymmetricCryptoKey, + encKey: ArrayBuffer + ): Promise<[SymmetricCryptoKey, EncString]> { + let encKeyEnc: EncString = null; + if (key.key.byteLength === 32) { + const newKey = await this.stretchKey(key); + encKeyEnc = await this.encrypt(encKey, newKey); + } else if (key.key.byteLength === 64) { + encKeyEnc = await this.encrypt(encKey, key); + } else { + throw new Error("Invalid key size."); + } + return [new SymmetricCryptoKey(encKey), encKeyEnc]; + } + + private async clearSecretKeyStore(userId?: string): Promise { + await this.stateService.setCryptoMasterKeyAuto(null, { userId: userId }); + await this.stateService.setCryptoMasterKeyBiometric(null, { userId: userId }); + } + + private async getEncKeyHelper(key: SymmetricCryptoKey = null): Promise { + const inMemoryKey = await this.stateService.getDecryptedCryptoSymmetricKey(); + if (inMemoryKey != null) { + return inMemoryKey; + } + + const encKey = await this.stateService.getEncryptedCryptoSymmetricKey(); + if (encKey == null) { + return null; + } + + if (key == null) { + key = await this.getKey(); + } + if (key == null) { + return null; + } + + let decEncKey: ArrayBuffer; + const encKeyCipher = new EncString(encKey); + if (encKeyCipher.encryptionType === EncryptionType.AesCbc256_B64) { + decEncKey = await this.decryptToBytes(encKeyCipher, key); + } else if (encKeyCipher.encryptionType === EncryptionType.AesCbc256_HmacSha256_B64) { + const newKey = await this.stretchKey(key); + decEncKey = await this.decryptToBytes(encKeyCipher, newKey); + } else { + throw new Error("Unsupported encKey type."); + } + if (decEncKey == null) { + return null; + } + const symmetricCryptoKey = new SymmetricCryptoKey(decEncKey); + await this.stateService.setDecryptedCryptoSymmetricKey(symmetricCryptoKey); + return symmetricCryptoKey; + } +} diff --git a/libs/common/src/services/environment.service.ts b/libs/common/src/services/environment.service.ts new file mode 100644 index 0000000000..b13afd59ac --- /dev/null +++ b/libs/common/src/services/environment.service.ts @@ -0,0 +1,188 @@ +import { Observable, Subject } from "rxjs"; + +import { + EnvironmentService as EnvironmentServiceAbstraction, + Urls, +} from "../abstractions/environment.service"; +import { StateService } from "../abstractions/state.service"; +import { EnvironmentUrls } from "../models/domain/environmentUrls"; + +export class EnvironmentService implements EnvironmentServiceAbstraction { + private readonly urlsSubject = new Subject(); + urls: Observable = this.urlsSubject; + + private baseUrl: string; + private webVaultUrl: string; + private apiUrl: string; + private identityUrl: string; + private iconsUrl: string; + private notificationsUrl: string; + private eventsUrl: string; + private keyConnectorUrl: string; + + constructor(private stateService: StateService) { + this.stateService.activeAccount.subscribe(async () => { + await this.setUrlsFromStorage(); + }); + } + + hasBaseUrl() { + return this.baseUrl != null; + } + + getNotificationsUrl() { + if (this.notificationsUrl != null) { + return this.notificationsUrl; + } + + if (this.baseUrl != null) { + return this.baseUrl + "/notifications"; + } + + return "https://notifications.bitwarden.com"; + } + + getWebVaultUrl() { + if (this.webVaultUrl != null) { + return this.webVaultUrl; + } + + if (this.baseUrl) { + return this.baseUrl; + } + return "https://vault.bitwarden.com"; + } + + getSendUrl() { + return this.getWebVaultUrl() === "https://vault.bitwarden.com" + ? "https://send.bitwarden.com/#" + : this.getWebVaultUrl() + "/#/send/"; + } + + getIconsUrl() { + if (this.iconsUrl != null) { + return this.iconsUrl; + } + + if (this.baseUrl) { + return this.baseUrl + "/icons"; + } + + return "https://icons.bitwarden.net"; + } + + getApiUrl() { + if (this.apiUrl != null) { + return this.apiUrl; + } + + if (this.baseUrl) { + return this.baseUrl + "/api"; + } + + return "https://api.bitwarden.com"; + } + + getIdentityUrl() { + if (this.identityUrl != null) { + return this.identityUrl; + } + + if (this.baseUrl) { + return this.baseUrl + "/identity"; + } + + return "https://identity.bitwarden.com"; + } + + getEventsUrl() { + if (this.eventsUrl != null) { + return this.eventsUrl; + } + + if (this.baseUrl) { + return this.baseUrl + "/events"; + } + + return "https://events.bitwarden.com"; + } + + getKeyConnectorUrl() { + return this.keyConnectorUrl; + } + + async setUrlsFromStorage(): Promise { + const urls: any = await this.stateService.getEnvironmentUrls(); + const envUrls = new EnvironmentUrls(); + + this.baseUrl = envUrls.base = urls.base; + this.webVaultUrl = urls.webVault; + this.apiUrl = envUrls.api = urls.api; + this.identityUrl = envUrls.identity = urls.identity; + this.iconsUrl = urls.icons; + this.notificationsUrl = urls.notifications; + this.eventsUrl = envUrls.events = urls.events; + this.keyConnectorUrl = urls.keyConnector; + } + + async setUrls(urls: Urls): Promise { + urls.base = this.formatUrl(urls.base); + urls.webVault = this.formatUrl(urls.webVault); + urls.api = this.formatUrl(urls.api); + urls.identity = this.formatUrl(urls.identity); + urls.icons = this.formatUrl(urls.icons); + urls.notifications = this.formatUrl(urls.notifications); + urls.events = this.formatUrl(urls.events); + urls.keyConnector = this.formatUrl(urls.keyConnector); + + await this.stateService.setEnvironmentUrls({ + base: urls.base, + api: urls.api, + identity: urls.identity, + webVault: urls.webVault, + icons: urls.icons, + notifications: urls.notifications, + events: urls.events, + keyConnector: urls.keyConnector, + }); + + this.baseUrl = urls.base; + this.webVaultUrl = urls.webVault; + this.apiUrl = urls.api; + this.identityUrl = urls.identity; + this.iconsUrl = urls.icons; + this.notificationsUrl = urls.notifications; + this.eventsUrl = urls.events; + this.keyConnectorUrl = urls.keyConnector; + + this.urlsSubject.next(urls); + + return urls; + } + + getUrls() { + return { + base: this.baseUrl, + webVault: this.webVaultUrl, + api: this.apiUrl, + identity: this.identityUrl, + icons: this.iconsUrl, + notifications: this.notificationsUrl, + events: this.eventsUrl, + keyConnector: this.keyConnectorUrl, + }; + } + + private formatUrl(url: string): string { + if (url == null || url === "") { + return null; + } + + url = url.replace(/\/+$/g, ""); + if (!url.startsWith("http://") && !url.startsWith("https://")) { + url = "https://" + url; + } + + return url.trim(); + } +} diff --git a/libs/common/src/services/event.service.ts b/libs/common/src/services/event.service.ts new file mode 100644 index 0000000000..c0024d49ea --- /dev/null +++ b/libs/common/src/services/event.service.ts @@ -0,0 +1,99 @@ +import { ApiService } from "../abstractions/api.service"; +import { CipherService } from "../abstractions/cipher.service"; +import { EventService as EventServiceAbstraction } from "../abstractions/event.service"; +import { LogService } from "../abstractions/log.service"; +import { OrganizationService } from "../abstractions/organization.service"; +import { StateService } from "../abstractions/state.service"; +import { EventType } from "../enums/eventType"; +import { EventData } from "../models/data/eventData"; +import { EventRequest } from "../models/request/eventRequest"; + +export class EventService implements EventServiceAbstraction { + private inited = false; + + constructor( + private apiService: ApiService, + private cipherService: CipherService, + private stateService: StateService, + private logService: LogService, + private organizationService: OrganizationService + ) {} + + init(checkOnInterval: boolean) { + if (this.inited) { + return; + } + + this.inited = true; + if (checkOnInterval) { + this.uploadEvents(); + setInterval(() => this.uploadEvents(), 60 * 1000); // check every 60 seconds + } + } + + async collect( + eventType: EventType, + cipherId: string = null, + uploadImmediately = false + ): Promise { + const authed = await this.stateService.getIsAuthenticated(); + if (!authed) { + return; + } + const organizations = await this.organizationService.getAll(); + if (organizations == null) { + return; + } + const orgIds = new Set(organizations.filter((o) => o.useEvents).map((o) => o.id)); + if (orgIds.size === 0) { + return; + } + if (cipherId != null) { + const cipher = await this.cipherService.get(cipherId); + if (cipher == null || cipher.organizationId == null || !orgIds.has(cipher.organizationId)) { + return; + } + } + let eventCollection = await this.stateService.getEventCollection(); + if (eventCollection == null) { + eventCollection = []; + } + const event = new EventData(); + event.type = eventType; + event.cipherId = cipherId; + event.date = new Date().toISOString(); + eventCollection.push(event); + await this.stateService.setEventCollection(eventCollection); + if (uploadImmediately) { + await this.uploadEvents(); + } + } + + async uploadEvents(userId?: string): Promise { + const authed = await this.stateService.getIsAuthenticated({ userId: userId }); + if (!authed) { + return; + } + const eventCollection = await this.stateService.getEventCollection({ userId: userId }); + if (eventCollection == null || eventCollection.length === 0) { + return; + } + const request = eventCollection.map((e) => { + const req = new EventRequest(); + req.type = e.type; + req.cipherId = e.cipherId; + req.date = e.date; + return req; + }); + try { + await this.apiService.postEventsCollect(request); + this.clearEvents(userId); + } catch (e) { + this.logService.error(e); + } + } + + async clearEvents(userId?: string): Promise { + await this.stateService.setEventCollection(null, { userId: userId }); + } +} diff --git a/libs/common/src/services/export.service.ts b/libs/common/src/services/export.service.ts new file mode 100644 index 0000000000..c6f08be6d2 --- /dev/null +++ b/libs/common/src/services/export.service.ts @@ -0,0 +1,444 @@ +import * as papa from "papaparse"; + +import { ApiService } from "../abstractions/api.service"; +import { CipherService } from "../abstractions/cipher.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; +import { + ExportFormat, + ExportService as ExportServiceAbstraction, +} from "../abstractions/export.service"; +import { FolderService } from "../abstractions/folder.service"; +import { CipherType } from "../enums/cipherType"; +import { DEFAULT_KDF_ITERATIONS, KdfType } from "../enums/kdfType"; +import { Utils } from "../misc/utils"; +import { CipherData } from "../models/data/cipherData"; +import { CollectionData } from "../models/data/collectionData"; +import { Cipher } from "../models/domain/cipher"; +import { Collection } from "../models/domain/collection"; +import { Folder } from "../models/domain/folder"; +import { CipherWithIdExport as CipherExport } from "../models/export/cipherWithIdsExport"; +import { CollectionWithIdExport as CollectionExport } from "../models/export/collectionWithIdExport"; +import { EventExport } from "../models/export/eventExport"; +import { FolderWithIdExport as FolderExport } from "../models/export/folderWithIdExport"; +import { CollectionDetailsResponse } from "../models/response/collectionResponse"; +import { CipherView } from "../models/view/cipherView"; +import { CollectionView } from "../models/view/collectionView"; +import { EventView } from "../models/view/eventView"; +import { FolderView } from "../models/view/folderView"; + +export class ExportService implements ExportServiceAbstraction { + constructor( + private folderService: FolderService, + private cipherService: CipherService, + private apiService: ApiService, + private cryptoService: CryptoService, + private cryptoFunctionService: CryptoFunctionService + ) {} + + async getExport(format: ExportFormat = "csv", organizationId?: string): Promise { + if (organizationId) { + return await this.getOrganizationExport(organizationId, format); + } + + if (format === "encrypted_json") { + return this.getEncryptedExport(); + } else { + return this.getDecryptedExport(format); + } + } + + async getPasswordProtectedExport(password: string, organizationId?: string): Promise { + const clearText = organizationId + ? await this.getOrganizationExport(organizationId, "json") + : await this.getExport("json"); + + const salt = Utils.fromBufferToB64(await this.cryptoFunctionService.randomBytes(16)); + const kdfIterations = DEFAULT_KDF_ITERATIONS; + const key = await this.cryptoService.makePinKey( + password, + salt, + KdfType.PBKDF2_SHA256, + kdfIterations + ); + + const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid(), key); + const encText = await this.cryptoService.encrypt(clearText, key); + + const jsonDoc: any = { + encrypted: true, + passwordProtected: true, + salt: salt, + kdfIterations: kdfIterations, + kdfType: KdfType.PBKDF2_SHA256, + encKeyValidation_DO_NOT_EDIT: encKeyValidation.encryptedString, + data: encText.encryptedString, + }; + + return JSON.stringify(jsonDoc, null, " "); + } + + async getOrganizationExport( + organizationId: string, + format: ExportFormat = "csv" + ): Promise { + if (format === "encrypted_json") { + return this.getOrganizationEncryptedExport(organizationId); + } else { + return this.getOrganizationDecryptedExport(organizationId, format); + } + } + + async getEventExport(events: EventView[]): Promise { + return papa.unparse(events.map((e) => new EventExport(e))); + } + + getFileName(prefix: string = null, extension = "csv"): string { + const now = new Date(); + const dateString = + now.getFullYear() + + "" + + this.padNumber(now.getMonth() + 1, 2) + + "" + + this.padNumber(now.getDate(), 2) + + this.padNumber(now.getHours(), 2) + + "" + + this.padNumber(now.getMinutes(), 2) + + this.padNumber(now.getSeconds(), 2); + + return "bitwarden" + (prefix ? "_" + prefix : "") + "_export_" + dateString + "." + extension; + } + + private async getDecryptedExport(format: "json" | "csv"): Promise { + let decFolders: FolderView[] = []; + let decCiphers: CipherView[] = []; + const promises = []; + + promises.push( + this.folderService.getAllDecrypted().then((folders) => { + decFolders = folders; + }) + ); + + promises.push( + this.cipherService.getAllDecrypted().then((ciphers) => { + decCiphers = ciphers.filter((f) => f.deletedDate == null); + }) + ); + + await Promise.all(promises); + + if (format === "csv") { + const foldersMap = new Map(); + decFolders.forEach((f) => { + if (f.id != null) { + foldersMap.set(f.id, f); + } + }); + + const exportCiphers: any[] = []; + decCiphers.forEach((c) => { + // only export logins and secure notes + if (c.type !== CipherType.Login && c.type !== CipherType.SecureNote) { + return; + } + if (c.organizationId != null) { + return; + } + + const cipher: any = {}; + cipher.folder = + c.folderId != null && foldersMap.has(c.folderId) ? foldersMap.get(c.folderId).name : null; + cipher.favorite = c.favorite ? 1 : null; + this.buildCommonCipher(cipher, c); + exportCiphers.push(cipher); + }); + + return papa.unparse(exportCiphers); + } else { + const jsonDoc: any = { + encrypted: false, + folders: [], + items: [], + }; + + decFolders.forEach((f) => { + if (f.id == null) { + return; + } + const folder = new FolderExport(); + folder.build(f); + jsonDoc.folders.push(folder); + }); + + decCiphers.forEach((c) => { + if (c.organizationId != null) { + return; + } + const cipher = new CipherExport(); + cipher.build(c); + cipher.collectionIds = null; + jsonDoc.items.push(cipher); + }); + + return JSON.stringify(jsonDoc, null, " "); + } + } + + private async getEncryptedExport(): Promise { + let folders: Folder[] = []; + let ciphers: Cipher[] = []; + const promises = []; + + promises.push( + this.folderService.getAll().then((f) => { + folders = f; + }) + ); + + promises.push( + this.cipherService.getAll().then((c) => { + ciphers = c.filter((f) => f.deletedDate == null); + }) + ); + + await Promise.all(promises); + + const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid()); + + const jsonDoc: any = { + encrypted: true, + encKeyValidation_DO_NOT_EDIT: encKeyValidation.encryptedString, + folders: [], + items: [], + }; + + folders.forEach((f) => { + if (f.id == null) { + return; + } + const folder = new FolderExport(); + folder.build(f); + jsonDoc.folders.push(folder); + }); + + ciphers.forEach((c) => { + if (c.organizationId != null) { + return; + } + const cipher = new CipherExport(); + cipher.build(c); + cipher.collectionIds = null; + jsonDoc.items.push(cipher); + }); + + return JSON.stringify(jsonDoc, null, " "); + } + + private async getOrganizationDecryptedExport( + organizationId: string, + format: "json" | "csv" + ): Promise { + const decCollections: CollectionView[] = []; + const decCiphers: CipherView[] = []; + const promises = []; + + promises.push( + this.apiService.getCollections(organizationId).then((collections) => { + const collectionPromises: any = []; + if (collections != null && collections.data != null && collections.data.length > 0) { + collections.data.forEach((c) => { + const collection = new Collection(new CollectionData(c as CollectionDetailsResponse)); + collectionPromises.push( + collection.decrypt().then((decCol) => { + decCollections.push(decCol); + }) + ); + }); + } + return Promise.all(collectionPromises); + }) + ); + + promises.push( + this.apiService.getCiphersOrganization(organizationId).then((ciphers) => { + const cipherPromises: any = []; + if (ciphers != null && ciphers.data != null && ciphers.data.length > 0) { + ciphers.data + .filter((c) => c.deletedDate === null) + .forEach((c) => { + const cipher = new Cipher(new CipherData(c)); + cipherPromises.push( + cipher.decrypt().then((decCipher) => { + decCiphers.push(decCipher); + }) + ); + }); + } + return Promise.all(cipherPromises); + }) + ); + + await Promise.all(promises); + + if (format === "csv") { + const collectionsMap = new Map(); + decCollections.forEach((c) => { + collectionsMap.set(c.id, c); + }); + + const exportCiphers: any[] = []; + decCiphers.forEach((c) => { + // only export logins and secure notes + if (c.type !== CipherType.Login && c.type !== CipherType.SecureNote) { + return; + } + + const cipher: any = {}; + cipher.collections = []; + if (c.collectionIds != null) { + cipher.collections = c.collectionIds + .filter((id) => collectionsMap.has(id)) + .map((id) => collectionsMap.get(id).name); + } + this.buildCommonCipher(cipher, c); + exportCiphers.push(cipher); + }); + + return papa.unparse(exportCiphers); + } else { + const jsonDoc: any = { + encrypted: false, + collections: [], + items: [], + }; + + decCollections.forEach((c) => { + const collection = new CollectionExport(); + collection.build(c); + jsonDoc.collections.push(collection); + }); + + decCiphers.forEach((c) => { + const cipher = new CipherExport(); + cipher.build(c); + jsonDoc.items.push(cipher); + }); + return JSON.stringify(jsonDoc, null, " "); + } + } + + private async getOrganizationEncryptedExport(organizationId: string): Promise { + const collections: Collection[] = []; + const ciphers: Cipher[] = []; + const promises = []; + + promises.push( + this.apiService.getCollections(organizationId).then((c) => { + const collectionPromises: any = []; + if (c != null && c.data != null && c.data.length > 0) { + c.data.forEach((r) => { + const collection = new Collection(new CollectionData(r as CollectionDetailsResponse)); + collections.push(collection); + }); + } + return Promise.all(collectionPromises); + }) + ); + + promises.push( + this.apiService.getCiphersOrganization(organizationId).then((c) => { + const cipherPromises: any = []; + if (c != null && c.data != null && c.data.length > 0) { + c.data + .filter((item) => item.deletedDate === null) + .forEach((item) => { + const cipher = new Cipher(new CipherData(item)); + ciphers.push(cipher); + }); + } + return Promise.all(cipherPromises); + }) + ); + + await Promise.all(promises); + + const orgKey = await this.cryptoService.getOrgKey(organizationId); + const encKeyValidation = await this.cryptoService.encrypt(Utils.newGuid(), orgKey); + + const jsonDoc: any = { + encrypted: true, + encKeyValidation_DO_NOT_EDIT: encKeyValidation.encryptedString, + collections: [], + items: [], + }; + + collections.forEach((c) => { + const collection = new CollectionExport(); + collection.build(c); + jsonDoc.collections.push(collection); + }); + + ciphers.forEach((c) => { + const cipher = new CipherExport(); + cipher.build(c); + jsonDoc.items.push(cipher); + }); + return JSON.stringify(jsonDoc, null, " "); + } + + private padNumber(num: number, width: number, padCharacter = "0"): string { + const numString = num.toString(); + return numString.length >= width + ? numString + : new Array(width - numString.length + 1).join(padCharacter) + numString; + } + + private buildCommonCipher(cipher: any, c: CipherView) { + cipher.type = null; + cipher.name = c.name; + cipher.notes = c.notes; + cipher.fields = null; + cipher.reprompt = c.reprompt; + // Login props + cipher.login_uri = null; + cipher.login_username = null; + cipher.login_password = null; + cipher.login_totp = null; + + if (c.fields) { + c.fields.forEach((f: any) => { + if (!cipher.fields) { + cipher.fields = ""; + } else { + cipher.fields += "\n"; + } + + cipher.fields += (f.name || "") + ": " + f.value; + }); + } + + switch (c.type) { + case CipherType.Login: + cipher.type = "login"; + cipher.login_username = c.login.username; + cipher.login_password = c.login.password; + cipher.login_totp = c.login.totp; + + if (c.login.uris) { + cipher.login_uri = []; + c.login.uris.forEach((u) => { + cipher.login_uri.push(u.uri); + }); + } + break; + case CipherType.SecureNote: + cipher.type = "note"; + break; + default: + return; + } + + return cipher; + } +} diff --git a/libs/common/src/services/fileUpload.service.ts b/libs/common/src/services/fileUpload.service.ts new file mode 100644 index 0000000000..6fc0af35f7 --- /dev/null +++ b/libs/common/src/services/fileUpload.service.ts @@ -0,0 +1,108 @@ +import { ApiService } from "../abstractions/api.service"; +import { FileUploadService as FileUploadServiceAbstraction } from "../abstractions/fileUpload.service"; +import { LogService } from "../abstractions/log.service"; +import { FileUploadType } from "../enums/fileUploadType"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; +import { EncString } from "../models/domain/encString"; +import { AttachmentUploadDataResponse } from "../models/response/attachmentUploadDataResponse"; +import { SendFileUploadDataResponse } from "../models/response/sendFileUploadDataResponse"; + +import { AzureFileUploadService } from "./azureFileUpload.service"; +import { BitwardenFileUploadService } from "./bitwardenFileUpload.service"; + +export class FileUploadService implements FileUploadServiceAbstraction { + private azureFileUploadService: AzureFileUploadService; + private bitwardenFileUploadService: BitwardenFileUploadService; + + constructor(private logService: LogService, private apiService: ApiService) { + this.azureFileUploadService = new AzureFileUploadService(logService); + this.bitwardenFileUploadService = new BitwardenFileUploadService(apiService); + } + + async uploadSendFile( + uploadData: SendFileUploadDataResponse, + fileName: EncString, + encryptedFileData: EncArrayBuffer + ) { + try { + switch (uploadData.fileUploadType) { + case FileUploadType.Direct: + await this.bitwardenFileUploadService.upload( + fileName.encryptedString, + encryptedFileData, + (fd) => + this.apiService.postSendFile( + uploadData.sendResponse.id, + uploadData.sendResponse.file.id, + fd + ) + ); + break; + case FileUploadType.Azure: { + const renewalCallback = async () => { + const renewalResponse = await this.apiService.renewSendFileUploadUrl( + uploadData.sendResponse.id, + uploadData.sendResponse.file.id + ); + return renewalResponse.url; + }; + await this.azureFileUploadService.upload( + uploadData.url, + encryptedFileData, + renewalCallback + ); + break; + } + default: + throw new Error("Unknown file upload type"); + } + } catch (e) { + await this.apiService.deleteSend(uploadData.sendResponse.id); + throw e; + } + } + + async uploadCipherAttachment( + admin: boolean, + uploadData: AttachmentUploadDataResponse, + encryptedFileName: EncString, + encryptedFileData: EncArrayBuffer + ) { + const response = admin ? uploadData.cipherMiniResponse : uploadData.cipherResponse; + try { + switch (uploadData.fileUploadType) { + case FileUploadType.Direct: + await this.bitwardenFileUploadService.upload( + encryptedFileName.encryptedString, + encryptedFileData, + (fd) => this.apiService.postAttachmentFile(response.id, uploadData.attachmentId, fd) + ); + break; + case FileUploadType.Azure: { + const renewalCallback = async () => { + const renewalResponse = await this.apiService.renewAttachmentUploadUrl( + response.id, + uploadData.attachmentId + ); + return renewalResponse.url; + }; + await this.azureFileUploadService.upload( + uploadData.url, + encryptedFileData, + renewalCallback + ); + break; + } + default: + throw new Error("Unknown file upload type."); + } + } catch (e) { + if (admin) { + await this.apiService.deleteCipherAttachmentAdmin(response.id, uploadData.attachmentId); + } else { + await this.apiService.deleteCipherAttachment(response.id, uploadData.attachmentId); + } + throw e; + } + } +} diff --git a/libs/common/src/services/folder.service.ts b/libs/common/src/services/folder.service.ts new file mode 100644 index 0000000000..f791c07f4d --- /dev/null +++ b/libs/common/src/services/folder.service.ts @@ -0,0 +1,193 @@ +import { ApiService } from "../abstractions/api.service"; +import { CipherService } from "../abstractions/cipher.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { FolderService as FolderServiceAbstraction } from "../abstractions/folder.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { StateService } from "../abstractions/state.service"; +import { ServiceUtils } from "../misc/serviceUtils"; +import { Utils } from "../misc/utils"; +import { CipherData } from "../models/data/cipherData"; +import { FolderData } from "../models/data/folderData"; +import { Folder } from "../models/domain/folder"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { TreeNode } from "../models/domain/treeNode"; +import { FolderRequest } from "../models/request/folderRequest"; +import { FolderResponse } from "../models/response/folderResponse"; +import { FolderView } from "../models/view/folderView"; + +const NestingDelimiter = "/"; + +export class FolderService implements FolderServiceAbstraction { + constructor( + private cryptoService: CryptoService, + private apiService: ApiService, + private i18nService: I18nService, + private cipherService: CipherService, + private stateService: StateService + ) {} + + async clearCache(userId?: string): Promise { + await this.stateService.setDecryptedFolders(null, { userId: userId }); + } + + async encrypt(model: FolderView, key?: SymmetricCryptoKey): Promise { + const folder = new Folder(); + folder.id = model.id; + folder.name = await this.cryptoService.encrypt(model.name, key); + return folder; + } + + async get(id: string): Promise { + const folders = await this.stateService.getEncryptedFolders(); + // eslint-disable-next-line + if (folders == null || !folders.hasOwnProperty(id)) { + return null; + } + + return new Folder(folders[id]); + } + + async getAll(): Promise { + const folders = await this.stateService.getEncryptedFolders(); + const response: Folder[] = []; + for (const id in folders) { + // eslint-disable-next-line + if (folders.hasOwnProperty(id)) { + response.push(new Folder(folders[id])); + } + } + return response; + } + + async getAllDecrypted(): Promise { + const decryptedFolders = await this.stateService.getDecryptedFolders(); + if (decryptedFolders != null) { + return decryptedFolders; + } + + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + throw new Error("No key."); + } + + const decFolders: FolderView[] = []; + const promises: Promise[] = []; + const folders = await this.getAll(); + folders.forEach((folder) => { + promises.push(folder.decrypt().then((f) => decFolders.push(f))); + }); + + await Promise.all(promises); + decFolders.sort(Utils.getSortFunction(this.i18nService, "name")); + + const noneFolder = new FolderView(); + noneFolder.name = this.i18nService.t("noneFolder"); + decFolders.push(noneFolder); + + await this.stateService.setDecryptedFolders(decFolders); + return decFolders; + } + + async getAllNested(folders?: FolderView[]): Promise[]> { + folders = folders ?? (await this.getAllDecrypted()); + const nodes: TreeNode[] = []; + folders.forEach((f) => { + const folderCopy = new FolderView(); + folderCopy.id = f.id; + folderCopy.revisionDate = f.revisionDate; + const parts = f.name != null ? f.name.replace(/^\/+|\/+$/g, "").split(NestingDelimiter) : []; + ServiceUtils.nestedTraverse(nodes, 0, parts, folderCopy, null, NestingDelimiter); + }); + return nodes; + } + + async getNested(id: string): Promise> { + const folders = await this.getAllNested(); + return ServiceUtils.getTreeNodeObject(folders, id) as TreeNode; + } + + async saveWithServer(folder: Folder): Promise { + const request = new FolderRequest(folder); + + let response: FolderResponse; + if (folder.id == null) { + response = await this.apiService.postFolder(request); + folder.id = response.id; + } else { + response = await this.apiService.putFolder(folder.id, request); + } + + const data = new FolderData(response); + await this.upsert(data); + } + + async upsert(folder: FolderData | FolderData[]): Promise { + let folders = await this.stateService.getEncryptedFolders(); + if (folders == null) { + folders = {}; + } + + if (folder instanceof FolderData) { + const f = folder as FolderData; + folders[f.id] = f; + } else { + (folder as FolderData[]).forEach((f) => { + folders[f.id] = f; + }); + } + + await this.stateService.setDecryptedFolders(null); + await this.stateService.setEncryptedFolders(folders); + } + + async replace(folders: { [id: string]: FolderData }): Promise { + await this.stateService.setDecryptedFolders(null); + await this.stateService.setEncryptedFolders(folders); + } + + async clear(userId?: string): Promise { + await this.stateService.setDecryptedFolders(null, { userId: userId }); + await this.stateService.setEncryptedFolders(null, { userId: userId }); + } + + async delete(id: string | string[]): Promise { + const folders = await this.stateService.getEncryptedFolders(); + if (folders == null) { + return; + } + + if (typeof id === "string") { + if (folders[id] == null) { + return; + } + delete folders[id]; + } else { + (id as string[]).forEach((i) => { + delete folders[i]; + }); + } + + await this.stateService.setDecryptedFolders(null); + await this.stateService.setEncryptedFolders(folders); + + // Items in a deleted folder are re-assigned to "No Folder" + const ciphers = await this.stateService.getEncryptedCiphers(); + if (ciphers != null) { + const updates: CipherData[] = []; + for (const cId in ciphers) { + if (ciphers[cId].folderId === id) { + ciphers[cId].folderId = null; + updates.push(ciphers[cId]); + } + } + if (updates.length > 0) { + this.cipherService.upsert(updates); + } + } + } + + async deleteWithServer(id: string): Promise { + await this.apiService.deleteFolder(id); + await this.delete(id); + } +} diff --git a/libs/common/src/services/i18n.service.ts b/libs/common/src/services/i18n.service.ts new file mode 100644 index 0000000000..fda8f839ea --- /dev/null +++ b/libs/common/src/services/i18n.service.ts @@ -0,0 +1,175 @@ +import { I18nService as I18nServiceAbstraction } from "../abstractions/i18n.service"; + +export class I18nService implements I18nServiceAbstraction { + locale: string; + // First locale is the default (English) + supportedTranslationLocales: string[] = ["en"]; + translationLocale: string; + collator: Intl.Collator; + localeNames = new Map([ + ["af", "Afrikaans"], + ["az", "Azərbaycanca"], + ["be", "Беларуская"], + ["bg", "български"], + ["bn", "বাংলা"], + ["bs", "bosanski jezik"], + ["ca", "català"], + ["cs", "čeština"], + ["da", "dansk"], + ["de", "Deutsch"], + ["el", "Ελληνικά"], + ["en", "English"], + ["en-GB", "English (British)"], + ["en-IN", "English (India)"], + ["eo", "Esperanto"], + ["es", "español"], + ["et", "eesti"], + ["fa", "فارسی"], + ["fi", "suomi"], + ["fil", "Wikang Filipino"], + ["fr", "français"], + ["he", "עברית"], + ["hi", "हिन्दी"], + ["hr", "hrvatski"], + ["hu", "magyar"], + ["id", "Bahasa Indonesia"], + ["it", "italiano"], + ["ja", "日本語"], + ["ka", "ქართული"], + ["km", "ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ"], + ["kn", "ಕನ್ನಡ"], + ["ko", "한국어"], + ["lt", "lietuvių kalba"], + ["lv", "Latvietis"], + ["me", "црногорски"], + ["ml", "മലയാളം"], + ["nb", "norsk (bokmål)"], + ["nl", "Nederlands"], + ["nn", "Norsk Nynorsk"], + ["pl", "polski"], + ["pt-BR", "português do Brasil"], + ["pt-PT", "português"], + ["ro", "română"], + ["ru", "русский"], + ["si", "සිංහල"], + ["sk", "slovenčina"], + ["sl", "Slovenski jezik, Slovenščina"], + ["sr", "Српски"], + ["sv", "svenska"], + ["th", "ไทย"], + ["tr", "Türkçe"], + ["uk", "українська"], + ["vi", "Tiếng Việt"], + ["zh-CN", "中文(中国大陆)"], + ["zh-TW", "中文(台灣)"], + ]); + + protected inited: boolean; + protected defaultMessages: any = {}; + protected localeMessages: any = {}; + + constructor( + protected systemLanguage: string, + protected localesDirectory: string, + protected getLocalesJson: (formattedLocale: string) => Promise + ) { + this.systemLanguage = systemLanguage.replace("_", "-"); + } + + async init(locale?: string) { + if (this.inited) { + throw new Error("i18n already initialized."); + } + if (this.supportedTranslationLocales == null || this.supportedTranslationLocales.length === 0) { + throw new Error("supportedTranslationLocales not set."); + } + + this.inited = true; + this.locale = this.translationLocale = locale != null ? locale : this.systemLanguage; + + try { + this.collator = new Intl.Collator(this.locale, { numeric: true, sensitivity: "base" }); + } catch { + this.collator = null; + } + + if (this.supportedTranslationLocales.indexOf(this.translationLocale) === -1) { + this.translationLocale = this.translationLocale.slice(0, 2); + + if (this.supportedTranslationLocales.indexOf(this.translationLocale) === -1) { + this.translationLocale = this.supportedTranslationLocales[0]; + } + } + + if (this.localesDirectory != null) { + await this.loadMessages(this.translationLocale, this.localeMessages); + if (this.translationLocale !== this.supportedTranslationLocales[0]) { + await this.loadMessages(this.supportedTranslationLocales[0], this.defaultMessages); + } + } + } + + t(id: string, p1?: string, p2?: string, p3?: string): string { + return this.translate(id, p1, p2, p3); + } + + translate(id: string, p1?: string, p2?: string, p3?: string): string { + let result: string; + // eslint-disable-next-line + if (this.localeMessages.hasOwnProperty(id) && this.localeMessages[id]) { + result = this.localeMessages[id]; + // eslint-disable-next-line + } else if (this.defaultMessages.hasOwnProperty(id) && this.defaultMessages[id]) { + result = this.defaultMessages[id]; + } else { + result = ""; + } + + if (result !== "") { + if (p1 != null) { + result = result.split("__$1__").join(p1); + } + if (p2 != null) { + result = result.split("__$2__").join(p2); + } + if (p3 != null) { + result = result.split("__$3__").join(p3); + } + } + + return result; + } + + private async loadMessages(locale: string, messagesObj: any): Promise { + const formattedLocale = locale.replace("-", "_"); + const locales = await this.getLocalesJson(formattedLocale); + for (const prop in locales) { + // eslint-disable-next-line + if (!locales.hasOwnProperty(prop)) { + continue; + } + messagesObj[prop] = locales[prop].message; + + if (locales[prop].placeholders) { + for (const placeProp in locales[prop].placeholders) { + if ( + !locales[prop].placeholders.hasOwnProperty(placeProp) || // eslint-disable-line + !locales[prop].placeholders[placeProp].content + ) { + continue; + } + + const replaceToken = "\\$" + placeProp.toUpperCase() + "\\$"; + let replaceContent = locales[prop].placeholders[placeProp].content; + if (replaceContent === "$1" || replaceContent === "$2" || replaceContent === "$3") { + replaceContent = "__$" + replaceContent + "__"; + } + messagesObj[prop] = messagesObj[prop].replace( + new RegExp(replaceToken, "g"), + replaceContent + ); + } + } + } + } +} diff --git a/libs/common/src/services/import.service.ts b/libs/common/src/services/import.service.ts new file mode 100644 index 0000000000..86226d7d6a --- /dev/null +++ b/libs/common/src/services/import.service.ts @@ -0,0 +1,382 @@ +import { ApiService } from "../abstractions/api.service"; +import { CipherService } from "../abstractions/cipher.service"; +import { CollectionService } from "../abstractions/collection.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { FolderService } from "../abstractions/folder.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { ImportService as ImportServiceAbstraction } from "../abstractions/import.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; +import { CipherType } from "../enums/cipherType"; +import { + featuredImportOptions, + ImportOption, + ImportType, + regularImportOptions, +} from "../enums/importOptions"; +import { AscendoCsvImporter } from "../importers/ascendoCsvImporter"; +import { AvastCsvImporter } from "../importers/avastCsvImporter"; +import { AvastJsonImporter } from "../importers/avastJsonImporter"; +import { AviraCsvImporter } from "../importers/aviraCsvImporter"; +import { BitwardenCsvImporter } from "../importers/bitwardenCsvImporter"; +import { BitwardenJsonImporter } from "../importers/bitwardenJsonImporter"; +import { BitwardenPasswordProtectedImporter } from "../importers/bitwardenPasswordProtectedImporter"; +import { BlackBerryCsvImporter } from "../importers/blackBerryCsvImporter"; +import { BlurCsvImporter } from "../importers/blurCsvImporter"; +import { ButtercupCsvImporter } from "../importers/buttercupCsvImporter"; +import { ChromeCsvImporter } from "../importers/chromeCsvImporter"; +import { ClipperzHtmlImporter } from "../importers/clipperzHtmlImporter"; +import { CodebookCsvImporter } from "../importers/codebookCsvImporter"; +import { DashlaneCsvImporter } from "../importers/dashlaneImporters/dashlaneCsvImporter"; +import { DashlaneJsonImporter } from "../importers/dashlaneImporters/dashlaneJsonImporter"; +import { EncryptrCsvImporter } from "../importers/encryptrCsvImporter"; +import { EnpassCsvImporter } from "../importers/enpassCsvImporter"; +import { EnpassJsonImporter } from "../importers/enpassJsonImporter"; +import { FirefoxCsvImporter } from "../importers/firefoxCsvImporter"; +import { FSecureFskImporter } from "../importers/fsecureFskImporter"; +import { GnomeJsonImporter } from "../importers/gnomeJsonImporter"; +import { ImportError } from "../importers/importError"; +import { Importer } from "../importers/importer"; +import { KasperskyTxtImporter } from "../importers/kasperskyTxtImporter"; +import { KeePass2XmlImporter } from "../importers/keepass2XmlImporter"; +import { KeePassXCsvImporter } from "../importers/keepassxCsvImporter"; +import { KeeperCsvImporter } from "../importers/keeperImporters/keeperCsvImporter"; +import { LastPassCsvImporter } from "../importers/lastpassCsvImporter"; +import { LogMeOnceCsvImporter } from "../importers/logMeOnceCsvImporter"; +import { MeldiumCsvImporter } from "../importers/meldiumCsvImporter"; +import { MSecureCsvImporter } from "../importers/msecureCsvImporter"; +import { MykiCsvImporter } from "../importers/mykiCsvImporter"; +import { NordPassCsvImporter } from "../importers/nordpassCsvImporter"; +import { OnePassword1PifImporter } from "../importers/onepasswordImporters/onepassword1PifImporter"; +import { OnePassword1PuxImporter } from "../importers/onepasswordImporters/onepassword1PuxImporter"; +import { OnePasswordMacCsvImporter } from "../importers/onepasswordImporters/onepasswordMacCsvImporter"; +import { OnePasswordWinCsvImporter } from "../importers/onepasswordImporters/onepasswordWinCsvImporter"; +import { PadlockCsvImporter } from "../importers/padlockCsvImporter"; +import { PassKeepCsvImporter } from "../importers/passkeepCsvImporter"; +import { PassmanJsonImporter } from "../importers/passmanJsonImporter"; +import { PasspackCsvImporter } from "../importers/passpackCsvImporter"; +import { PasswordAgentCsvImporter } from "../importers/passwordAgentCsvImporter"; +import { PasswordBossJsonImporter } from "../importers/passwordBossJsonImporter"; +import { PasswordDragonXmlImporter } from "../importers/passwordDragonXmlImporter"; +import { PasswordSafeXmlImporter } from "../importers/passwordSafeXmlImporter"; +import { PasswordWalletTxtImporter } from "../importers/passwordWalletTxtImporter"; +import { RememBearCsvImporter } from "../importers/rememBearCsvImporter"; +import { RoboFormCsvImporter } from "../importers/roboformCsvImporter"; +import { SafariCsvImporter } from "../importers/safariCsvImporter"; +import { SafeInCloudXmlImporter } from "../importers/safeInCloudXmlImporter"; +import { SaferPassCsvImporter } from "../importers/saferpassCsvImport"; +import { SecureSafeCsvImporter } from "../importers/secureSafeCsvImporter"; +import { SplashIdCsvImporter } from "../importers/splashIdCsvImporter"; +import { StickyPasswordXmlImporter } from "../importers/stickyPasswordXmlImporter"; +import { TrueKeyCsvImporter } from "../importers/truekeyCsvImporter"; +import { UpmCsvImporter } from "../importers/upmCsvImporter"; +import { YotiCsvImporter } from "../importers/yotiCsvImporter"; +import { ZohoVaultCsvImporter } from "../importers/zohoVaultCsvImporter"; +import { Utils } from "../misc/utils"; +import { ImportResult } from "../models/domain/importResult"; +import { CipherRequest } from "../models/request/cipherRequest"; +import { CollectionRequest } from "../models/request/collectionRequest"; +import { FolderRequest } from "../models/request/folderRequest"; +import { ImportCiphersRequest } from "../models/request/importCiphersRequest"; +import { ImportOrganizationCiphersRequest } from "../models/request/importOrganizationCiphersRequest"; +import { KvpRequest } from "../models/request/kvpRequest"; +import { ErrorResponse } from "../models/response/errorResponse"; +import { CipherView } from "../models/view/cipherView"; + +export class ImportService implements ImportServiceAbstraction { + featuredImportOptions = featuredImportOptions as readonly ImportOption[]; + + regularImportOptions = regularImportOptions as readonly ImportOption[]; + + constructor( + private cipherService: CipherService, + private folderService: FolderService, + private apiService: ApiService, + private i18nService: I18nService, + private collectionService: CollectionService, + private platformUtilsService: PlatformUtilsService, + private cryptoService: CryptoService + ) {} + + getImportOptions(): ImportOption[] { + return this.featuredImportOptions.concat(this.regularImportOptions); + } + + async import( + importer: Importer, + fileContents: string, + organizationId: string = null + ): Promise { + const importResult = await importer.parse(fileContents); + if (importResult.success) { + if (importResult.folders.length === 0 && importResult.ciphers.length === 0) { + return new ImportError(this.i18nService.t("importNothingError")); + } else if (importResult.ciphers.length > 0) { + const halfway = Math.floor(importResult.ciphers.length / 2); + const last = importResult.ciphers.length - 1; + + if ( + this.badData(importResult.ciphers[0]) && + this.badData(importResult.ciphers[halfway]) && + this.badData(importResult.ciphers[last]) + ) { + return new ImportError(this.i18nService.t("importFormatError")); + } + } + try { + await this.postImport(importResult, organizationId); + } catch (error) { + const errorResponse = new ErrorResponse(error, 400); + return this.handleServerError(errorResponse, importResult); + } + return null; + } else { + if (!Utils.isNullOrWhitespace(importResult.errorMessage)) { + return new ImportError(importResult.errorMessage, importResult.missingPassword); + } else { + return new ImportError( + this.i18nService.t("importFormatError"), + importResult.missingPassword + ); + } + } + } + + getImporter( + format: ImportType | "bitwardenpasswordprotected", + organizationId: string = null, + password: string = null + ): Importer { + const importer = this.getImporterInstance(format, password); + if (importer == null) { + return null; + } + importer.organizationId = organizationId; + return importer; + } + + private getImporterInstance(format: ImportType | "bitwardenpasswordprotected", password: string) { + if (format == null) { + return null; + } + + switch (format) { + case "bitwardencsv": + return new BitwardenCsvImporter(); + case "bitwardenjson": + return new BitwardenJsonImporter(this.cryptoService, this.i18nService); + case "bitwardenpasswordprotected": + return new BitwardenPasswordProtectedImporter( + this.cryptoService, + this.i18nService, + password + ); + case "lastpasscsv": + case "passboltcsv": + return new LastPassCsvImporter(); + case "keepassxcsv": + return new KeePassXCsvImporter(); + case "aviracsv": + return new AviraCsvImporter(); + case "blurcsv": + return new BlurCsvImporter(); + case "safeincloudxml": + return new SafeInCloudXmlImporter(); + case "padlockcsv": + return new PadlockCsvImporter(); + case "keepass2xml": + return new KeePass2XmlImporter(); + case "chromecsv": + case "operacsv": + case "vivaldicsv": + return new ChromeCsvImporter(); + case "firefoxcsv": + return new FirefoxCsvImporter(); + case "upmcsv": + return new UpmCsvImporter(); + case "saferpasscsv": + return new SaferPassCsvImporter(); + case "safaricsv": + return new SafariCsvImporter(); + case "meldiumcsv": + return new MeldiumCsvImporter(); + case "1password1pif": + return new OnePassword1PifImporter(); + case "1password1pux": + return new OnePassword1PuxImporter(); + case "1passwordwincsv": + return new OnePasswordWinCsvImporter(); + case "1passwordmaccsv": + return new OnePasswordMacCsvImporter(); + case "keepercsv": + return new KeeperCsvImporter(); + // case "keeperjson": + // return new KeeperJsonImporter(); + case "passworddragonxml": + return new PasswordDragonXmlImporter(); + case "enpasscsv": + return new EnpassCsvImporter(); + case "enpassjson": + return new EnpassJsonImporter(); + case "pwsafexml": + return new PasswordSafeXmlImporter(); + case "dashlanecsv": + return new DashlaneCsvImporter(); + case "dashlanejson": + return new DashlaneJsonImporter(); + case "msecurecsv": + return new MSecureCsvImporter(); + case "stickypasswordxml": + return new StickyPasswordXmlImporter(); + case "truekeycsv": + return new TrueKeyCsvImporter(); + case "clipperzhtml": + return new ClipperzHtmlImporter(); + case "roboformcsv": + return new RoboFormCsvImporter(); + case "ascendocsv": + return new AscendoCsvImporter(); + case "passwordbossjson": + return new PasswordBossJsonImporter(); + case "zohovaultcsv": + return new ZohoVaultCsvImporter(); + case "splashidcsv": + return new SplashIdCsvImporter(); + case "passkeepcsv": + return new PassKeepCsvImporter(); + case "gnomejson": + return new GnomeJsonImporter(); + case "passwordagentcsv": + return new PasswordAgentCsvImporter(); + case "passpackcsv": + return new PasspackCsvImporter(); + case "passmanjson": + return new PassmanJsonImporter(); + case "avastcsv": + return new AvastCsvImporter(); + case "avastjson": + return new AvastJsonImporter(); + case "fsecurefsk": + return new FSecureFskImporter(); + case "kasperskytxt": + return new KasperskyTxtImporter(); + case "remembearcsv": + return new RememBearCsvImporter(); + case "passwordwallettxt": + return new PasswordWalletTxtImporter(); + case "mykicsv": + return new MykiCsvImporter(); + case "securesafecsv": + return new SecureSafeCsvImporter(); + case "logmeoncecsv": + return new LogMeOnceCsvImporter(); + case "blackberrycsv": + return new BlackBerryCsvImporter(); + case "buttercupcsv": + return new ButtercupCsvImporter(); + case "codebookcsv": + return new CodebookCsvImporter(); + case "encryptrcsv": + return new EncryptrCsvImporter(); + case "yoticsv": + return new YotiCsvImporter(); + case "nordpasscsv": + return new NordPassCsvImporter(); + default: + return null; + } + } + + private async postImport(importResult: ImportResult, organizationId: string = null) { + if (organizationId == null) { + const request = new ImportCiphersRequest(); + for (let i = 0; i < importResult.ciphers.length; i++) { + const c = await this.cipherService.encrypt(importResult.ciphers[i]); + request.ciphers.push(new CipherRequest(c)); + } + if (importResult.folders != null) { + for (let i = 0; i < importResult.folders.length; i++) { + const f = await this.folderService.encrypt(importResult.folders[i]); + request.folders.push(new FolderRequest(f)); + } + } + if (importResult.folderRelationships != null) { + importResult.folderRelationships.forEach((r) => + request.folderRelationships.push(new KvpRequest(r[0], r[1])) + ); + } + return await this.apiService.postImportCiphers(request); + } else { + const request = new ImportOrganizationCiphersRequest(); + for (let i = 0; i < importResult.ciphers.length; i++) { + importResult.ciphers[i].organizationId = organizationId; + const c = await this.cipherService.encrypt(importResult.ciphers[i]); + request.ciphers.push(new CipherRequest(c)); + } + if (importResult.collections != null) { + for (let i = 0; i < importResult.collections.length; i++) { + importResult.collections[i].organizationId = organizationId; + const c = await this.collectionService.encrypt(importResult.collections[i]); + request.collections.push(new CollectionRequest(c)); + } + } + if (importResult.collectionRelationships != null) { + importResult.collectionRelationships.forEach((r) => + request.collectionRelationships.push(new KvpRequest(r[0], r[1])) + ); + } + return await this.apiService.postImportOrganizationCiphers(organizationId, request); + } + } + + private badData(c: CipherView) { + return ( + (c.name == null || c.name === "--") && + c.type === CipherType.Login && + c.login != null && + Utils.isNullOrWhitespace(c.login.password) + ); + } + + private handleServerError(errorResponse: ErrorResponse, importResult: ImportResult): ImportError { + if (errorResponse.validationErrors == null) { + return new ImportError(errorResponse.message); + } + + let errorMessage = ""; + + Object.entries(errorResponse.validationErrors).forEach(([key, value], index) => { + let item; + let itemType; + const i = Number(key.match(/[0-9]+/)[0]); + + switch (key.match(/^\w+/)[0]) { + case "Ciphers": + item = importResult.ciphers[i]; + itemType = CipherType[item.type]; + break; + case "Folders": + item = importResult.folders[i]; + itemType = "Folder"; + break; + case "Collections": + item = importResult.collections[i]; + itemType = "Collection"; + break; + default: + return; + } + + if (index > 0) { + errorMessage += "\n\n"; + } + + if (itemType !== "Folder" && itemType !== "Collection") { + errorMessage += "[" + (i + 1) + "] "; + } + + errorMessage += "[" + itemType + '] "' + item.name + '": ' + value; + }); + + return new ImportError(errorMessage); + } +} diff --git a/libs/common/src/services/keyConnector.service.ts b/libs/common/src/services/keyConnector.service.ts new file mode 100644 index 0000000000..8be5993528 --- /dev/null +++ b/libs/common/src/services/keyConnector.service.ts @@ -0,0 +1,142 @@ +import { ApiService } from "../abstractions/api.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; +import { KeyConnectorService as KeyConnectorServiceAbstraction } from "../abstractions/keyConnector.service"; +import { LogService } from "../abstractions/log.service"; +import { OrganizationService } from "../abstractions/organization.service"; +import { StateService } from "../abstractions/state.service"; +import { TokenService } from "../abstractions/token.service"; +import { OrganizationUserType } from "../enums/organizationUserType"; +import { Utils } from "../misc/utils"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { SetKeyConnectorKeyRequest } from "../models/request/account/setKeyConnectorKeyRequest"; +import { KeyConnectorUserKeyRequest } from "../models/request/keyConnectorUserKeyRequest"; +import { KeysRequest } from "../models/request/keysRequest"; +import { IdentityTokenResponse } from "../models/response/identityTokenResponse"; + +export class KeyConnectorService implements KeyConnectorServiceAbstraction { + constructor( + private stateService: StateService, + private cryptoService: CryptoService, + private apiService: ApiService, + private tokenService: TokenService, + private logService: LogService, + private organizationService: OrganizationService, + private cryptoFunctionService: CryptoFunctionService, + private logoutCallback: (expired: boolean, userId?: string) => void + ) {} + + setUsesKeyConnector(usesKeyConnector: boolean) { + return this.stateService.setUsesKeyConnector(usesKeyConnector); + } + + async getUsesKeyConnector(): Promise { + return await this.stateService.getUsesKeyConnector(); + } + + async userNeedsMigration() { + const loggedInUsingSso = await this.tokenService.getIsExternal(); + const requiredByOrganization = (await this.getManagingOrganization()) != null; + const userIsNotUsingKeyConnector = !(await this.getUsesKeyConnector()); + + return loggedInUsingSso && requiredByOrganization && userIsNotUsingKeyConnector; + } + + async migrateUser() { + const organization = await this.getManagingOrganization(); + const key = await this.cryptoService.getKey(); + const keyConnectorRequest = new KeyConnectorUserKeyRequest(key.encKeyB64); + + try { + await this.apiService.postUserKeyToKeyConnector( + organization.keyConnectorUrl, + keyConnectorRequest + ); + } catch (e) { + this.handleKeyConnectorError(e); + } + + await this.apiService.postConvertToKeyConnector(); + } + + async getAndSetKey(url: string) { + try { + const userKeyResponse = await this.apiService.getUserKeyFromKeyConnector(url); + const keyArr = Utils.fromB64ToArray(userKeyResponse.key); + const k = new SymmetricCryptoKey(keyArr); + await this.cryptoService.setKey(k); + } catch (e) { + this.handleKeyConnectorError(e); + } + } + + async getManagingOrganization() { + const orgs = await this.organizationService.getAll(); + return orgs.find( + (o) => + o.keyConnectorEnabled && + o.type !== OrganizationUserType.Admin && + o.type !== OrganizationUserType.Owner && + !o.isProviderUser + ); + } + + async convertNewSsoUserToKeyConnector(tokenResponse: IdentityTokenResponse, orgId: string) { + const { kdf, kdfIterations, keyConnectorUrl } = tokenResponse; + const password = await this.cryptoFunctionService.randomBytes(64); + + const k = await this.cryptoService.makeKey( + Utils.fromBufferToB64(password), + await this.tokenService.getEmail(), + kdf, + kdfIterations + ); + const keyConnectorRequest = new KeyConnectorUserKeyRequest(k.encKeyB64); + await this.cryptoService.setKey(k); + + const encKey = await this.cryptoService.makeEncKey(k); + await this.cryptoService.setEncKey(encKey[1].encryptedString); + + const [pubKey, privKey] = await this.cryptoService.makeKeyPair(); + + try { + await this.apiService.postUserKeyToKeyConnector(keyConnectorUrl, keyConnectorRequest); + } catch (e) { + this.handleKeyConnectorError(e); + } + + const keys = new KeysRequest(pubKey, privKey.encryptedString); + const setPasswordRequest = new SetKeyConnectorKeyRequest( + encKey[1].encryptedString, + kdf, + kdfIterations, + orgId, + keys + ); + await this.apiService.postSetKeyConnectorKey(setPasswordRequest); + } + + async setConvertAccountRequired(status: boolean) { + await this.stateService.setConvertAccountToKeyConnector(status); + } + + async getConvertAccountRequired(): Promise { + return await this.stateService.getConvertAccountToKeyConnector(); + } + + async removeConvertAccountRequired() { + await this.stateService.setConvertAccountToKeyConnector(null); + } + + async clear() { + await this.removeConvertAccountRequired(); + } + + private handleKeyConnectorError(e: any) { + this.logService.error(e); + if (this.logoutCallback != null) { + this.logoutCallback(false); + } + throw new Error("Key Connector error"); + } +} diff --git a/libs/common/src/services/noopMessaging.service.ts b/libs/common/src/services/noopMessaging.service.ts new file mode 100644 index 0000000000..d1a60bc5bc --- /dev/null +++ b/libs/common/src/services/noopMessaging.service.ts @@ -0,0 +1,7 @@ +import { MessagingService } from "../abstractions/messaging.service"; + +export class NoopMessagingService implements MessagingService { + send(subscriber: string, arg: any = {}) { + // Do nothing... + } +} diff --git a/libs/common/src/services/notifications.service.ts b/libs/common/src/services/notifications.service.ts new file mode 100644 index 0000000000..39e2df541f --- /dev/null +++ b/libs/common/src/services/notifications.service.ts @@ -0,0 +1,229 @@ +import * as signalR from "@microsoft/signalr"; +import * as signalRMsgPack from "@microsoft/signalr-protocol-msgpack"; + +import { ApiService } from "../abstractions/api.service"; +import { AppIdService } from "../abstractions/appId.service"; +import { AuthService } from "../abstractions/auth.service"; +import { EnvironmentService } from "../abstractions/environment.service"; +import { LogService } from "../abstractions/log.service"; +import { NotificationsService as NotificationsServiceAbstraction } from "../abstractions/notifications.service"; +import { StateService } from "../abstractions/state.service"; +import { SyncService } from "../abstractions/sync.service"; +import { AuthenticationStatus } from "../enums/authenticationStatus"; +import { NotificationType } from "../enums/notificationType"; +import { + NotificationResponse, + SyncCipherNotification, + SyncFolderNotification, + SyncSendNotification, +} from "../models/response/notificationResponse"; + +export class NotificationsService implements NotificationsServiceAbstraction { + private signalrConnection: signalR.HubConnection; + private url: string; + private connected = false; + private inited = false; + private inactive = false; + private reconnectTimer: any = null; + + constructor( + private syncService: SyncService, + private appIdService: AppIdService, + private apiService: ApiService, + private environmentService: EnvironmentService, + private logoutCallback: (expired: boolean) => Promise, + private logService: LogService, + private stateService: StateService, + private authService: AuthService + ) { + this.environmentService.urls.subscribe(() => { + if (!this.inited) { + return; + } + + this.init(); + }); + } + + async init(): Promise { + this.inited = false; + this.url = this.environmentService.getNotificationsUrl(); + + // Set notifications server URL to `https://-` to effectively disable communication + // with the notifications server from the client app + if (this.url === "https://-") { + return; + } + + if (this.signalrConnection != null) { + this.signalrConnection.off("ReceiveMessage"); + this.signalrConnection.off("Heartbeat"); + await this.signalrConnection.stop(); + this.connected = false; + this.signalrConnection = null; + } + + this.signalrConnection = new signalR.HubConnectionBuilder() + .withUrl(this.url + "/hub", { + accessTokenFactory: () => this.apiService.getActiveBearerToken(), + skipNegotiation: true, + transport: signalR.HttpTransportType.WebSockets, + }) + .withHubProtocol(new signalRMsgPack.MessagePackHubProtocol() as signalR.IHubProtocol) + // .configureLogging(signalR.LogLevel.Trace) + .build(); + + this.signalrConnection.on("ReceiveMessage", (data: any) => + this.processNotification(new NotificationResponse(data)) + ); + // eslint-disable-next-line + this.signalrConnection.on("Heartbeat", (data: any) => { + /*console.log('Heartbeat!');*/ + }); + this.signalrConnection.onclose(() => { + this.connected = false; + this.reconnect(true); + }); + this.inited = true; + if (await this.isAuthedAndUnlocked()) { + await this.reconnect(false); + } + } + + async updateConnection(sync = false): Promise { + if (!this.inited) { + return; + } + try { + if (await this.isAuthedAndUnlocked()) { + await this.reconnect(sync); + } else { + await this.signalrConnection.stop(); + } + } catch (e) { + this.logService.error(e.toString()); + } + } + + async reconnectFromActivity(): Promise { + this.inactive = false; + if (this.inited && !this.connected) { + await this.reconnect(true); + } + } + + async disconnectFromInactivity(): Promise { + this.inactive = true; + if (this.inited && this.connected) { + await this.signalrConnection.stop(); + } + } + + private async processNotification(notification: NotificationResponse) { + const appId = await this.appIdService.getAppId(); + if (notification == null || notification.contextId === appId) { + return; + } + + const isAuthenticated = await this.stateService.getIsAuthenticated(); + const payloadUserId = notification.payload.userId || notification.payload.UserId; + const myUserId = await this.stateService.getUserId(); + if (isAuthenticated && payloadUserId != null && payloadUserId !== myUserId) { + return; + } + + switch (notification.type) { + case NotificationType.SyncCipherCreate: + case NotificationType.SyncCipherUpdate: + await this.syncService.syncUpsertCipher( + notification.payload as SyncCipherNotification, + notification.type === NotificationType.SyncCipherUpdate + ); + break; + case NotificationType.SyncCipherDelete: + case NotificationType.SyncLoginDelete: + await this.syncService.syncDeleteCipher(notification.payload as SyncCipherNotification); + break; + case NotificationType.SyncFolderCreate: + case NotificationType.SyncFolderUpdate: + await this.syncService.syncUpsertFolder( + notification.payload as SyncFolderNotification, + notification.type === NotificationType.SyncFolderUpdate + ); + break; + case NotificationType.SyncFolderDelete: + await this.syncService.syncDeleteFolder(notification.payload as SyncFolderNotification); + break; + case NotificationType.SyncVault: + case NotificationType.SyncCiphers: + case NotificationType.SyncSettings: + if (isAuthenticated) { + await this.syncService.fullSync(false); + } + break; + case NotificationType.SyncOrgKeys: + if (isAuthenticated) { + await this.syncService.fullSync(true); + // Stop so a reconnect can be made + await this.signalrConnection.stop(); + } + break; + case NotificationType.LogOut: + if (isAuthenticated) { + this.logoutCallback(true); + } + break; + case NotificationType.SyncSendCreate: + case NotificationType.SyncSendUpdate: + await this.syncService.syncUpsertSend( + notification.payload as SyncSendNotification, + notification.type === NotificationType.SyncSendUpdate + ); + break; + case NotificationType.SyncSendDelete: + await this.syncService.syncDeleteSend(notification.payload as SyncSendNotification); + break; + default: + break; + } + } + + private async reconnect(sync: boolean) { + if (this.reconnectTimer != null) { + clearTimeout(this.reconnectTimer); + this.reconnectTimer = null; + } + if (this.connected || !this.inited || this.inactive) { + return; + } + const authedAndUnlocked = await this.isAuthedAndUnlocked(); + if (!authedAndUnlocked) { + return; + } + + try { + await this.signalrConnection.start(); + this.connected = true; + if (sync) { + await this.syncService.fullSync(false); + } + } catch (e) { + this.logService.error(e); + } + + if (!this.connected) { + this.reconnectTimer = setTimeout(() => this.reconnect(sync), this.random(120000, 300000)); + } + } + + private async isAuthedAndUnlocked() { + const authStatus = await this.authService.getAuthStatus(); + return authStatus >= AuthenticationStatus.Unlocked; + } + + private random(min: number, max: number) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; + } +} diff --git a/libs/common/src/services/organization.service.ts b/libs/common/src/services/organization.service.ts new file mode 100644 index 0000000000..0ff32e8167 --- /dev/null +++ b/libs/common/src/services/organization.service.ts @@ -0,0 +1,55 @@ +import { OrganizationService as OrganizationServiceAbstraction } from "../abstractions/organization.service"; +import { StateService } from "../abstractions/state.service"; +import { OrganizationData } from "../models/data/organizationData"; +import { Organization } from "../models/domain/organization"; + +export class OrganizationService implements OrganizationServiceAbstraction { + constructor(private stateService: StateService) {} + + async get(id: string): Promise { + const organizations = await this.stateService.getOrganizations(); + // eslint-disable-next-line + if (organizations == null || !organizations.hasOwnProperty(id)) { + return null; + } + + return new Organization(organizations[id]); + } + + async getByIdentifier(identifier: string): Promise { + const organizations = await this.getAll(); + if (organizations == null || organizations.length === 0) { + return null; + } + + return organizations.find((o) => o.identifier === identifier); + } + + async getAll(userId?: string): Promise { + const organizations = await this.stateService.getOrganizations({ userId: userId }); + const response: Organization[] = []; + for (const id in organizations) { + // eslint-disable-next-line + if (organizations.hasOwnProperty(id) && !organizations[id].isProviderUser) { + response.push(new Organization(organizations[id])); + } + } + return response; + } + + async save(organizations: { [id: string]: OrganizationData }) { + return await this.stateService.setOrganizations(organizations); + } + + async canManageSponsorships(): Promise { + const orgs = await this.getAll(); + return orgs.some( + (o) => o.familySponsorshipAvailable || o.familySponsorshipFriendlyName !== null + ); + } + + async hasOrganizations(userId?: string): Promise { + const organizations = await this.getAll(userId); + return organizations.length > 0; + } +} diff --git a/libs/common/src/services/passwordGeneration.service.ts b/libs/common/src/services/passwordGeneration.service.ts new file mode 100644 index 0000000000..c752fcd98b --- /dev/null +++ b/libs/common/src/services/passwordGeneration.service.ts @@ -0,0 +1,572 @@ +import * as zxcvbn from "zxcvbn"; + +import { CryptoService } from "../abstractions/crypto.service"; +import { PasswordGenerationService as PasswordGenerationServiceAbstraction } from "../abstractions/passwordGeneration.service"; +import { PolicyService } from "../abstractions/policy.service"; +import { StateService } from "../abstractions/state.service"; +import { PolicyType } from "../enums/policyType"; +import { EEFLongWordList } from "../misc/wordlist"; +import { EncString } from "../models/domain/encString"; +import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory"; +import { PasswordGeneratorPolicyOptions } from "../models/domain/passwordGeneratorPolicyOptions"; +import { Policy } from "../models/domain/policy"; + +const DefaultOptions = { + length: 14, + ambiguous: false, + number: true, + minNumber: 1, + uppercase: true, + minUppercase: 0, + lowercase: true, + minLowercase: 0, + special: false, + minSpecial: 1, + type: "password", + numWords: 3, + wordSeparator: "-", + capitalize: false, + includeNumber: false, +}; + +const MaxPasswordsInHistory = 100; + +export class PasswordGenerationService implements PasswordGenerationServiceAbstraction { + constructor( + private cryptoService: CryptoService, + private policyService: PolicyService, + private stateService: StateService + ) {} + + async generatePassword(options: any): Promise { + // overload defaults with given options + const o = Object.assign({}, DefaultOptions, options); + + if (o.type === "passphrase") { + return this.generatePassphrase(options); + } + + // sanitize + this.sanitizePasswordLength(o, true); + + const minLength: number = o.minUppercase + o.minLowercase + o.minNumber + o.minSpecial; + if (o.length < minLength) { + o.length = minLength; + } + + const positions: string[] = []; + if (o.lowercase && o.minLowercase > 0) { + for (let i = 0; i < o.minLowercase; i++) { + positions.push("l"); + } + } + if (o.uppercase && o.minUppercase > 0) { + for (let i = 0; i < o.minUppercase; i++) { + positions.push("u"); + } + } + if (o.number && o.minNumber > 0) { + for (let i = 0; i < o.minNumber; i++) { + positions.push("n"); + } + } + if (o.special && o.minSpecial > 0) { + for (let i = 0; i < o.minSpecial; i++) { + positions.push("s"); + } + } + while (positions.length < o.length) { + positions.push("a"); + } + + // shuffle + await this.shuffleArray(positions); + + // build out the char sets + let allCharSet = ""; + + let lowercaseCharSet = "abcdefghijkmnopqrstuvwxyz"; + if (o.ambiguous) { + lowercaseCharSet += "l"; + } + if (o.lowercase) { + allCharSet += lowercaseCharSet; + } + + let uppercaseCharSet = "ABCDEFGHJKLMNPQRSTUVWXYZ"; + if (o.ambiguous) { + uppercaseCharSet += "IO"; + } + if (o.uppercase) { + allCharSet += uppercaseCharSet; + } + + let numberCharSet = "23456789"; + if (o.ambiguous) { + numberCharSet += "01"; + } + if (o.number) { + allCharSet += numberCharSet; + } + + const specialCharSet = "!@#$%^&*"; + if (o.special) { + allCharSet += specialCharSet; + } + + let password = ""; + for (let i = 0; i < o.length; i++) { + let positionChars: string; + switch (positions[i]) { + case "l": + positionChars = lowercaseCharSet; + break; + case "u": + positionChars = uppercaseCharSet; + break; + case "n": + positionChars = numberCharSet; + break; + case "s": + positionChars = specialCharSet; + break; + case "a": + positionChars = allCharSet; + break; + default: + break; + } + + const randomCharIndex = await this.cryptoService.randomNumber(0, positionChars.length - 1); + password += positionChars.charAt(randomCharIndex); + } + + return password; + } + + async generatePassphrase(options: any): Promise { + const o = Object.assign({}, DefaultOptions, options); + + if (o.numWords == null || o.numWords <= 2) { + o.numWords = DefaultOptions.numWords; + } + if (o.wordSeparator == null || o.wordSeparator.length === 0 || o.wordSeparator.length > 1) { + o.wordSeparator = " "; + } + if (o.capitalize == null) { + o.capitalize = false; + } + if (o.includeNumber == null) { + o.includeNumber = false; + } + + const listLength = EEFLongWordList.length - 1; + const wordList = new Array(o.numWords); + for (let i = 0; i < o.numWords; i++) { + const wordIndex = await this.cryptoService.randomNumber(0, listLength); + if (o.capitalize) { + wordList[i] = this.capitalize(EEFLongWordList[wordIndex]); + } else { + wordList[i] = EEFLongWordList[wordIndex]; + } + } + + if (o.includeNumber) { + await this.appendRandomNumberToRandomWord(wordList); + } + return wordList.join(o.wordSeparator); + } + + async getOptions(): Promise<[any, PasswordGeneratorPolicyOptions]> { + let options = await this.stateService.getPasswordGenerationOptions(); + if (options == null) { + options = Object.assign({}, DefaultOptions); + } else { + options = Object.assign({}, DefaultOptions, options); + } + await this.stateService.setPasswordGenerationOptions(options); + const enforcedOptions = await this.enforcePasswordGeneratorPoliciesOnOptions(options); + options = enforcedOptions[0]; + return [options, enforcedOptions[1]]; + } + + async enforcePasswordGeneratorPoliciesOnOptions( + options: any + ): Promise<[any, PasswordGeneratorPolicyOptions]> { + let enforcedPolicyOptions = await this.getPasswordGeneratorPolicyOptions(); + if (enforcedPolicyOptions != null) { + if (options.length < enforcedPolicyOptions.minLength) { + options.length = enforcedPolicyOptions.minLength; + } + + if (enforcedPolicyOptions.useUppercase) { + options.uppercase = true; + } + + if (enforcedPolicyOptions.useLowercase) { + options.lowercase = true; + } + + if (enforcedPolicyOptions.useNumbers) { + options.number = true; + } + + if (options.minNumber < enforcedPolicyOptions.numberCount) { + options.minNumber = enforcedPolicyOptions.numberCount; + } + + if (enforcedPolicyOptions.useSpecial) { + options.special = true; + } + + if (options.minSpecial < enforcedPolicyOptions.specialCount) { + options.minSpecial = enforcedPolicyOptions.specialCount; + } + + // Must normalize these fields because the receiving call expects all options to pass the current rules + if (options.minSpecial + options.minNumber > options.length) { + options.minSpecial = options.length - options.minNumber; + } + + if (options.numWords < enforcedPolicyOptions.minNumberWords) { + options.numWords = enforcedPolicyOptions.minNumberWords; + } + + if (enforcedPolicyOptions.capitalize) { + options.capitalize = true; + } + + if (enforcedPolicyOptions.includeNumber) { + options.includeNumber = true; + } + + // Force default type if password/passphrase selected via policy + if ( + enforcedPolicyOptions.defaultType === "password" || + enforcedPolicyOptions.defaultType === "passphrase" + ) { + options.type = enforcedPolicyOptions.defaultType; + } + } else { + // UI layer expects an instantiated object to prevent more explicit null checks + enforcedPolicyOptions = new PasswordGeneratorPolicyOptions(); + } + return [options, enforcedPolicyOptions]; + } + + async getPasswordGeneratorPolicyOptions(): Promise { + const policies: Policy[] = + this.policyService == null + ? null + : await this.policyService.getAll(PolicyType.PasswordGenerator); + let enforcedOptions: PasswordGeneratorPolicyOptions = null; + + if (policies == null || policies.length === 0) { + return enforcedOptions; + } + + policies.forEach((currentPolicy) => { + if (!currentPolicy.enabled || currentPolicy.data == null) { + return; + } + + if (enforcedOptions == null) { + enforcedOptions = new PasswordGeneratorPolicyOptions(); + } + + // Password wins in multi-org collisions + if (currentPolicy.data.defaultType != null && enforcedOptions.defaultType !== "password") { + enforcedOptions.defaultType = currentPolicy.data.defaultType; + } + + if ( + currentPolicy.data.minLength != null && + currentPolicy.data.minLength > enforcedOptions.minLength + ) { + enforcedOptions.minLength = currentPolicy.data.minLength; + } + + if (currentPolicy.data.useUpper) { + enforcedOptions.useUppercase = true; + } + + if (currentPolicy.data.useLower) { + enforcedOptions.useLowercase = true; + } + + if (currentPolicy.data.useNumbers) { + enforcedOptions.useNumbers = true; + } + + if ( + currentPolicy.data.minNumbers != null && + currentPolicy.data.minNumbers > enforcedOptions.numberCount + ) { + enforcedOptions.numberCount = currentPolicy.data.minNumbers; + } + + if (currentPolicy.data.useSpecial) { + enforcedOptions.useSpecial = true; + } + + if ( + currentPolicy.data.minSpecial != null && + currentPolicy.data.minSpecial > enforcedOptions.specialCount + ) { + enforcedOptions.specialCount = currentPolicy.data.minSpecial; + } + + if ( + currentPolicy.data.minNumberWords != null && + currentPolicy.data.minNumberWords > enforcedOptions.minNumberWords + ) { + enforcedOptions.minNumberWords = currentPolicy.data.minNumberWords; + } + + if (currentPolicy.data.capitalize) { + enforcedOptions.capitalize = true; + } + + if (currentPolicy.data.includeNumber) { + enforcedOptions.includeNumber = true; + } + }); + + return enforcedOptions; + } + + async saveOptions(options: any) { + await this.stateService.setPasswordGenerationOptions(options); + } + + async getHistory(): Promise { + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + return new Array(); + } + + if ((await this.stateService.getDecryptedPasswordGenerationHistory()) == null) { + const encrypted = await this.stateService.getEncryptedPasswordGenerationHistory(); + const decrypted = await this.decryptHistory(encrypted); + await this.stateService.setDecryptedPasswordGenerationHistory(decrypted); + } + + const passwordGenerationHistory = + await this.stateService.getDecryptedPasswordGenerationHistory(); + return passwordGenerationHistory != null + ? passwordGenerationHistory + : new Array(); + } + + async addHistory(password: string): Promise { + // Cannot add new history if no key is available + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + return; + } + + const currentHistory = await this.getHistory(); + + // Prevent duplicates + if (this.matchesPrevious(password, currentHistory)) { + return; + } + + currentHistory.unshift(new GeneratedPasswordHistory(password, Date.now())); + + // Remove old items. + if (currentHistory.length > MaxPasswordsInHistory) { + currentHistory.pop(); + } + + const newHistory = await this.encryptHistory(currentHistory); + return await this.stateService.setEncryptedPasswordGenerationHistory(newHistory); + } + + async clear(userId?: string): Promise { + await this.stateService.setEncryptedPasswordGenerationHistory(null, { userId: userId }); + await this.stateService.setDecryptedPasswordGenerationHistory(null, { userId: userId }); + } + + passwordStrength(password: string, userInputs: string[] = null): zxcvbn.ZXCVBNResult { + if (password == null || password.length === 0) { + return null; + } + let globalUserInputs = ["bitwarden", "bit", "warden"]; + if (userInputs != null && userInputs.length > 0) { + globalUserInputs = globalUserInputs.concat(userInputs); + } + // Use a hash set to get rid of any duplicate user inputs + const finalUserInputs = Array.from(new Set(globalUserInputs)); + const result = zxcvbn(password, finalUserInputs); + return result; + } + + normalizeOptions(options: any, enforcedPolicyOptions: PasswordGeneratorPolicyOptions) { + options.minLowercase = 0; + options.minUppercase = 0; + + if (!options.length || options.length < 5) { + options.length = 5; + } else if (options.length > 128) { + options.length = 128; + } + + if (options.length < enforcedPolicyOptions.minLength) { + options.length = enforcedPolicyOptions.minLength; + } + + if (!options.minNumber) { + options.minNumber = 0; + } else if (options.minNumber > options.length) { + options.minNumber = options.length; + } else if (options.minNumber > 9) { + options.minNumber = 9; + } + + if (options.minNumber < enforcedPolicyOptions.numberCount) { + options.minNumber = enforcedPolicyOptions.numberCount; + } + + if (!options.minSpecial) { + options.minSpecial = 0; + } else if (options.minSpecial > options.length) { + options.minSpecial = options.length; + } else if (options.minSpecial > 9) { + options.minSpecial = 9; + } + + if (options.minSpecial < enforcedPolicyOptions.specialCount) { + options.minSpecial = enforcedPolicyOptions.specialCount; + } + + if (options.minSpecial + options.minNumber > options.length) { + options.minSpecial = options.length - options.minNumber; + } + + if (options.numWords == null || options.length < 3) { + options.numWords = 3; + } else if (options.numWords > 20) { + options.numWords = 20; + } + + if (options.numWords < enforcedPolicyOptions.minNumberWords) { + options.numWords = enforcedPolicyOptions.minNumberWords; + } + + if (options.wordSeparator != null && options.wordSeparator.length > 1) { + options.wordSeparator = options.wordSeparator[0]; + } + + this.sanitizePasswordLength(options, false); + } + + private capitalize(str: string) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + + private async appendRandomNumberToRandomWord(wordList: string[]) { + if (wordList == null || wordList.length <= 0) { + return; + } + const index = await this.cryptoService.randomNumber(0, wordList.length - 1); + const num = await this.cryptoService.randomNumber(0, 9); + wordList[index] = wordList[index] + num; + } + + private async encryptHistory( + history: GeneratedPasswordHistory[] + ): Promise { + if (history == null || history.length === 0) { + return Promise.resolve([]); + } + + const promises = history.map(async (item) => { + const encrypted = await this.cryptoService.encrypt(item.password); + return new GeneratedPasswordHistory(encrypted.encryptedString, item.date); + }); + + return await Promise.all(promises); + } + + private async decryptHistory( + history: GeneratedPasswordHistory[] + ): Promise { + if (history == null || history.length === 0) { + return Promise.resolve([]); + } + + const promises = history.map(async (item) => { + const decrypted = await this.cryptoService.decryptToUtf8(new EncString(item.password)); + return new GeneratedPasswordHistory(decrypted, item.date); + }); + + return await Promise.all(promises); + } + + private matchesPrevious(password: string, history: GeneratedPasswordHistory[]): boolean { + if (history == null || history.length === 0) { + return false; + } + + return history[history.length - 1].password === password; + } + + // ref: https://stackoverflow.com/a/12646864/1090359 + private async shuffleArray(array: string[]) { + for (let i = array.length - 1; i > 0; i--) { + const j = await this.cryptoService.randomNumber(0, i); + [array[i], array[j]] = [array[j], array[i]]; + } + } + + private sanitizePasswordLength(options: any, forGeneration: boolean) { + let minUppercaseCalc = 0; + let minLowercaseCalc = 0; + let minNumberCalc: number = options.minNumber; + let minSpecialCalc: number = options.minSpecial; + + if (options.uppercase && options.minUppercase <= 0) { + minUppercaseCalc = 1; + } else if (!options.uppercase) { + minUppercaseCalc = 0; + } + + if (options.lowercase && options.minLowercase <= 0) { + minLowercaseCalc = 1; + } else if (!options.lowercase) { + minLowercaseCalc = 0; + } + + if (options.number && options.minNumber <= 0) { + minNumberCalc = 1; + } else if (!options.number) { + minNumberCalc = 0; + } + + if (options.special && options.minSpecial <= 0) { + minSpecialCalc = 1; + } else if (!options.special) { + minSpecialCalc = 0; + } + + // This should never happen but is a final safety net + if (!options.length || options.length < 1) { + options.length = 10; + } + + const minLength: number = minUppercaseCalc + minLowercaseCalc + minNumberCalc + minSpecialCalc; + // Normalize and Generation both require this modification + if (options.length < minLength) { + options.length = minLength; + } + + // Apply other changes if the options object passed in is for generation + if (forGeneration) { + options.minUppercase = minUppercaseCalc; + options.minLowercase = minLowercaseCalc; + options.minNumber = minNumberCalc; + options.minSpecial = minSpecialCalc; + } + } +} diff --git a/libs/common/src/services/policy.service.ts b/libs/common/src/services/policy.service.ts new file mode 100644 index 0000000000..91ab864b37 --- /dev/null +++ b/libs/common/src/services/policy.service.ts @@ -0,0 +1,247 @@ +import { ApiService } from "../abstractions/api.service"; +import { OrganizationService } from "../abstractions/organization.service"; +import { PolicyService as PolicyServiceAbstraction } from "../abstractions/policy.service"; +import { StateService } from "../abstractions/state.service"; +import { OrganizationUserStatusType } from "../enums/organizationUserStatusType"; +import { OrganizationUserType } from "../enums/organizationUserType"; +import { PolicyType } from "../enums/policyType"; +import { PolicyData } from "../models/data/policyData"; +import { MasterPasswordPolicyOptions } from "../models/domain/masterPasswordPolicyOptions"; +import { Organization } from "../models/domain/organization"; +import { Policy } from "../models/domain/policy"; +import { ResetPasswordPolicyOptions } from "../models/domain/resetPasswordPolicyOptions"; +import { ListResponse } from "../models/response/listResponse"; +import { PolicyResponse } from "../models/response/policyResponse"; + +export class PolicyService implements PolicyServiceAbstraction { + policyCache: Policy[]; + + constructor( + private stateService: StateService, + private organizationService: OrganizationService, + private apiService: ApiService + ) {} + + async clearCache(): Promise { + await this.stateService.setDecryptedPolicies(null); + } + + async getAll(type?: PolicyType, userId?: string): Promise { + let response: Policy[] = []; + const decryptedPolicies = await this.stateService.getDecryptedPolicies({ userId: userId }); + if (decryptedPolicies != null) { + response = decryptedPolicies; + } else { + const diskPolicies = await this.stateService.getEncryptedPolicies({ userId: userId }); + for (const id in diskPolicies) { + // eslint-disable-next-line + if (diskPolicies.hasOwnProperty(id)) { + response.push(new Policy(diskPolicies[id])); + } + } + await this.stateService.setDecryptedPolicies(response, { userId: userId }); + } + if (type != null) { + return response.filter((policy) => policy.type === type); + } else { + return response; + } + } + + async getPolicyForOrganization(policyType: PolicyType, organizationId: string): Promise { + const org = await this.organizationService.get(organizationId); + if (org?.isProviderUser) { + const orgPolicies = await this.apiService.getPolicies(organizationId); + const policy = orgPolicies.data.find((p) => p.organizationId === organizationId); + + if (policy == null) { + return null; + } + + return new Policy(new PolicyData(policy)); + } + + const policies = await this.getAll(policyType); + return policies.find((p) => p.organizationId === organizationId); + } + + async replace(policies: { [id: string]: PolicyData }): Promise { + await this.stateService.setDecryptedPolicies(null); + await this.stateService.setEncryptedPolicies(policies); + } + + async clear(userId?: string): Promise { + await this.stateService.setDecryptedPolicies(null, { userId: userId }); + await this.stateService.setEncryptedPolicies(null, { userId: userId }); + } + + async getMasterPasswordPoliciesForInvitedUsers( + orgId: string + ): Promise { + const userId = await this.stateService.getUserId(); + const response = await this.apiService.getPoliciesByInvitedUser(orgId, userId); + const policies = await this.mapPoliciesFromToken(response); + return this.getMasterPasswordPolicyOptions(policies); + } + + async getMasterPasswordPolicyOptions(policies?: Policy[]): Promise { + let enforcedOptions: MasterPasswordPolicyOptions = null; + + if (policies == null) { + policies = await this.getAll(PolicyType.MasterPassword); + } else { + policies = policies.filter((p) => p.type === PolicyType.MasterPassword); + } + + if (policies == null || policies.length === 0) { + return enforcedOptions; + } + + policies.forEach((currentPolicy) => { + if (!currentPolicy.enabled || currentPolicy.data == null) { + return; + } + + if (enforcedOptions == null) { + enforcedOptions = new MasterPasswordPolicyOptions(); + } + + if ( + currentPolicy.data.minComplexity != null && + currentPolicy.data.minComplexity > enforcedOptions.minComplexity + ) { + enforcedOptions.minComplexity = currentPolicy.data.minComplexity; + } + + if ( + currentPolicy.data.minLength != null && + currentPolicy.data.minLength > enforcedOptions.minLength + ) { + enforcedOptions.minLength = currentPolicy.data.minLength; + } + + if (currentPolicy.data.requireUpper) { + enforcedOptions.requireUpper = true; + } + + if (currentPolicy.data.requireLower) { + enforcedOptions.requireLower = true; + } + + if (currentPolicy.data.requireNumbers) { + enforcedOptions.requireNumbers = true; + } + + if (currentPolicy.data.requireSpecial) { + enforcedOptions.requireSpecial = true; + } + }); + + return enforcedOptions; + } + + evaluateMasterPassword( + passwordStrength: number, + newPassword: string, + enforcedPolicyOptions: MasterPasswordPolicyOptions + ): boolean { + if (enforcedPolicyOptions == null) { + return true; + } + + if ( + enforcedPolicyOptions.minComplexity > 0 && + enforcedPolicyOptions.minComplexity > passwordStrength + ) { + return false; + } + + if ( + enforcedPolicyOptions.minLength > 0 && + enforcedPolicyOptions.minLength > newPassword.length + ) { + return false; + } + + if (enforcedPolicyOptions.requireUpper && newPassword.toLocaleLowerCase() === newPassword) { + return false; + } + + if (enforcedPolicyOptions.requireLower && newPassword.toLocaleUpperCase() === newPassword) { + return false; + } + + if (enforcedPolicyOptions.requireNumbers && !/[0-9]/.test(newPassword)) { + return false; + } + + // eslint-disable-next-line + if (enforcedPolicyOptions.requireSpecial && !/[!@#$%\^&*]/g.test(newPassword)) { + return false; + } + + return true; + } + + getResetPasswordPolicyOptions( + policies: Policy[], + orgId: string + ): [ResetPasswordPolicyOptions, boolean] { + const resetPasswordPolicyOptions = new ResetPasswordPolicyOptions(); + + if (policies == null || orgId == null) { + return [resetPasswordPolicyOptions, false]; + } + + const policy = policies.find( + (p) => p.organizationId === orgId && p.type === PolicyType.ResetPassword && p.enabled + ); + resetPasswordPolicyOptions.autoEnrollEnabled = policy?.data?.autoEnrollEnabled ?? false; + + return [resetPasswordPolicyOptions, policy?.enabled ?? false]; + } + + mapPoliciesFromToken(policiesResponse: ListResponse): Policy[] { + if (policiesResponse == null || policiesResponse.data == null) { + return null; + } + + const policiesData = policiesResponse.data.map((p) => new PolicyData(p)); + return policiesData.map((p) => new Policy(p)); + } + + async policyAppliesToUser( + policyType: PolicyType, + policyFilter?: (policy: Policy) => boolean, + userId?: string + ) { + const policies = await this.getAll(policyType, userId); + const organizations = await this.organizationService.getAll(userId); + let filteredPolicies; + + if (policyFilter != null) { + filteredPolicies = policies.filter((p) => p.enabled && policyFilter(p)); + } else { + filteredPolicies = policies.filter((p) => p.enabled); + } + + const policySet = new Set(filteredPolicies.map((p) => p.organizationId)); + + return organizations.some( + (o) => + o.enabled && + o.status >= OrganizationUserStatusType.Accepted && + o.usePolicies && + !this.isExcemptFromPolicies(o, policyType) && + policySet.has(o.id) + ); + } + + private isExcemptFromPolicies(organization: Organization, policyType: PolicyType) { + if (policyType === PolicyType.MaximumVaultTimeout) { + return organization.type === OrganizationUserType.Owner; + } + + return organization.isExemptFromPolicies; + } +} diff --git a/libs/common/src/services/provider.service.ts b/libs/common/src/services/provider.service.ts new file mode 100644 index 0000000000..53f095424b --- /dev/null +++ b/libs/common/src/services/provider.service.ts @@ -0,0 +1,34 @@ +import { ProviderService as ProviderServiceAbstraction } from "../abstractions/provider.service"; +import { StateService } from "../abstractions/state.service"; +import { ProviderData } from "../models/data/providerData"; +import { Provider } from "../models/domain/provider"; + +export class ProviderService implements ProviderServiceAbstraction { + constructor(private stateService: StateService) {} + + async get(id: string): Promise { + const providers = await this.stateService.getProviders(); + // eslint-disable-next-line + if (providers == null || !providers.hasOwnProperty(id)) { + return null; + } + + return new Provider(providers[id]); + } + + async getAll(): Promise { + const providers = await this.stateService.getProviders(); + const response: Provider[] = []; + for (const id in providers) { + // eslint-disable-next-line + if (providers.hasOwnProperty(id)) { + response.push(new Provider(providers[id])); + } + } + return response; + } + + async save(providers: { [id: string]: ProviderData }) { + await this.stateService.setProviders(providers); + } +} diff --git a/libs/common/src/services/search.service.ts b/libs/common/src/services/search.service.ts new file mode 100644 index 0000000000..1db39e2524 --- /dev/null +++ b/libs/common/src/services/search.service.ts @@ -0,0 +1,308 @@ +import * as lunr from "lunr"; + +import { CipherService } from "../abstractions/cipher.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { LogService } from "../abstractions/log.service"; +import { SearchService as SearchServiceAbstraction } from "../abstractions/search.service"; +import { CipherType } from "../enums/cipherType"; +import { FieldType } from "../enums/fieldType"; +import { UriMatchType } from "../enums/uriMatchType"; +import { CipherView } from "../models/view/cipherView"; +import { SendView } from "../models/view/sendView"; + +export class SearchService implements SearchServiceAbstraction { + indexedEntityId?: string = null; + private indexing = false; + private index: lunr.Index = null; + private searchableMinLength = 2; + + constructor( + private cipherService: CipherService, + private logService: LogService, + private i18nService: I18nService + ) { + if (["zh-CN", "zh-TW"].indexOf(i18nService.locale) !== -1) { + this.searchableMinLength = 1; + } + //register lunr pipeline function + lunr.Pipeline.registerFunction(this.normalizeAccentsPipelineFunction, "normalizeAccents"); + } + + clearIndex(): void { + this.indexedEntityId = null; + this.index = null; + } + + isSearchable(query: string): boolean { + query = SearchService.normalizeSearchQuery(query); + const notSearchable = + query == null || + (this.index == null && query.length < this.searchableMinLength) || + (this.index != null && query.length < this.searchableMinLength && query.indexOf(">") !== 0); + return !notSearchable; + } + + async indexCiphers(indexedEntityId?: string, ciphers?: CipherView[]): Promise { + if (this.indexing) { + return; + } + + this.logService.time("search indexing"); + this.indexing = true; + this.indexedEntityId = indexedEntityId; + this.index = null; + const builder = new lunr.Builder(); + builder.pipeline.add(this.normalizeAccentsPipelineFunction); + builder.ref("id"); + builder.field("shortid", { boost: 100, extractor: (c: CipherView) => c.id.substr(0, 8) }); + builder.field("name", { + boost: 10, + }); + builder.field("subtitle", { + boost: 5, + extractor: (c: CipherView) => { + if (c.subTitle != null && c.type === CipherType.Card) { + return c.subTitle.replace(/\*/g, ""); + } + return c.subTitle; + }, + }); + builder.field("notes"); + builder.field("login.username", { + extractor: (c: CipherView) => + c.type === CipherType.Login && c.login != null ? c.login.username : null, + }); + builder.field("login.uris", { boost: 2, extractor: (c: CipherView) => this.uriExtractor(c) }); + builder.field("fields", { extractor: (c: CipherView) => this.fieldExtractor(c, false) }); + builder.field("fields_joined", { extractor: (c: CipherView) => this.fieldExtractor(c, true) }); + builder.field("attachments", { + extractor: (c: CipherView) => this.attachmentExtractor(c, false), + }); + builder.field("attachments_joined", { + extractor: (c: CipherView) => this.attachmentExtractor(c, true), + }); + builder.field("organizationid", { extractor: (c: CipherView) => c.organizationId }); + ciphers = ciphers || (await this.cipherService.getAllDecrypted()); + ciphers.forEach((c) => builder.add(c)); + this.index = builder.build(); + + this.indexing = false; + + this.logService.timeEnd("search indexing"); + } + + async searchCiphers( + query: string, + filter: ((cipher: CipherView) => boolean) | ((cipher: CipherView) => boolean)[] = null, + ciphers: CipherView[] = null + ): Promise { + const results: CipherView[] = []; + if (query != null) { + query = SearchService.normalizeSearchQuery(query.trim().toLowerCase()); + } + if (query === "") { + query = null; + } + + if (ciphers == null) { + ciphers = await this.cipherService.getAllDecrypted(); + } + + if (filter != null && Array.isArray(filter) && filter.length > 0) { + ciphers = ciphers.filter((c) => filter.every((f) => f == null || f(c))); + } else if (filter != null) { + ciphers = ciphers.filter(filter as (cipher: CipherView) => boolean); + } + + if (!this.isSearchable(query)) { + return ciphers; + } + + if (this.indexing) { + await new Promise((r) => setTimeout(r, 250)); + if (this.indexing) { + await new Promise((r) => setTimeout(r, 500)); + } + } + + const index = this.getIndexForSearch(); + if (index == null) { + // Fall back to basic search if index is not available + return this.searchCiphersBasic(ciphers, query); + } + + const ciphersMap = new Map(); + ciphers.forEach((c) => ciphersMap.set(c.id, c)); + + let searchResults: lunr.Index.Result[] = null; + const isQueryString = query != null && query.length > 1 && query.indexOf(">") === 0; + if (isQueryString) { + try { + searchResults = index.search(query.substr(1).trim()); + } catch (e) { + this.logService.error(e); + } + } else { + const soWild = lunr.Query.wildcard.LEADING | lunr.Query.wildcard.TRAILING; + searchResults = index.query((q) => { + lunr.tokenizer(query).forEach((token) => { + const t = token.toString(); + q.term(t, { fields: ["name"], wildcard: soWild }); + q.term(t, { fields: ["subtitle"], wildcard: soWild }); + q.term(t, { fields: ["login.uris"], wildcard: soWild }); + q.term(t, {}); + }); + }); + } + + if (searchResults != null) { + searchResults.forEach((r) => { + if (ciphersMap.has(r.ref)) { + results.push(ciphersMap.get(r.ref)); + } + }); + } + return results; + } + + searchCiphersBasic(ciphers: CipherView[], query: string, deleted = false) { + query = SearchService.normalizeSearchQuery(query.trim().toLowerCase()); + return ciphers.filter((c) => { + if (deleted !== c.isDeleted) { + return false; + } + if (c.name != null && c.name.toLowerCase().indexOf(query) > -1) { + return true; + } + if (query.length >= 8 && c.id.startsWith(query)) { + return true; + } + if (c.subTitle != null && c.subTitle.toLowerCase().indexOf(query) > -1) { + return true; + } + if (c.login && c.login.uri != null && c.login.uri.toLowerCase().indexOf(query) > -1) { + return true; + } + return false; + }); + } + + searchSends(sends: SendView[], query: string) { + query = SearchService.normalizeSearchQuery(query.trim().toLocaleLowerCase()); + if (query === null) { + return sends; + } + const sendsMatched: SendView[] = []; + const lowPriorityMatched: SendView[] = []; + sends.forEach((s) => { + if (s.name != null && s.name.toLowerCase().indexOf(query) > -1) { + sendsMatched.push(s); + } else if ( + query.length >= 8 && + (s.id.startsWith(query) || + s.accessId.toLocaleLowerCase().startsWith(query) || + (s.file?.id != null && s.file.id.startsWith(query))) + ) { + lowPriorityMatched.push(s); + } else if (s.notes != null && s.notes.toLowerCase().indexOf(query) > -1) { + lowPriorityMatched.push(s); + } else if (s.text?.text != null && s.text.text.toLowerCase().indexOf(query) > -1) { + lowPriorityMatched.push(s); + } else if (s.file?.fileName != null && s.file.fileName.toLowerCase().indexOf(query) > -1) { + lowPriorityMatched.push(s); + } + }); + return sendsMatched.concat(lowPriorityMatched); + } + + getIndexForSearch(): lunr.Index { + return this.index; + } + + private fieldExtractor(c: CipherView, joined: boolean) { + if (!c.hasFields) { + return null; + } + let fields: string[] = []; + c.fields.forEach((f) => { + if (f.name != null) { + fields.push(f.name); + } + if (f.type === FieldType.Text && f.value != null) { + fields.push(f.value); + } + }); + fields = fields.filter((f) => f.trim() !== ""); + if (fields.length === 0) { + return null; + } + return joined ? fields.join(" ") : fields; + } + + private attachmentExtractor(c: CipherView, joined: boolean) { + if (!c.hasAttachments) { + return null; + } + let attachments: string[] = []; + c.attachments.forEach((a) => { + if (a != null && a.fileName != null) { + if (joined && a.fileName.indexOf(".") > -1) { + attachments.push(a.fileName.substr(0, a.fileName.lastIndexOf("."))); + } else { + attachments.push(a.fileName); + } + } + }); + attachments = attachments.filter((f) => f.trim() !== ""); + if (attachments.length === 0) { + return null; + } + return joined ? attachments.join(" ") : attachments; + } + + private uriExtractor(c: CipherView) { + if (c.type !== CipherType.Login || c.login == null || !c.login.hasUris) { + return null; + } + const uris: string[] = []; + c.login.uris.forEach((u) => { + if (u.uri == null || u.uri === "") { + return; + } + if (u.hostname != null) { + uris.push(u.hostname); + return; + } + let uri = u.uri; + if (u.match !== UriMatchType.RegularExpression) { + const protocolIndex = uri.indexOf("://"); + if (protocolIndex > -1) { + uri = uri.substr(protocolIndex + 3); + } + const queryIndex = uri.search(/\?|&|#/); + if (queryIndex > -1) { + uri = uri.substring(0, queryIndex); + } + } + uris.push(uri); + }); + return uris.length > 0 ? uris : null; + } + + private normalizeAccentsPipelineFunction(token: lunr.Token): any { + const searchableFields = ["name", "login.username", "subtitle", "notes"]; + const fields = (token as any).metadata["fields"]; + const checkFields = fields.every((i: any) => searchableFields.includes(i)); + + if (checkFields) { + return SearchService.normalizeSearchQuery(token.toString()); + } + + return token; + } + + // Remove accents/diacritics characters from text. This regex is equivalent to the Diacritic unicode property escape, i.e. it will match all diacritic characters. + static normalizeSearchQuery(query: string): string { + return query?.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + } +} diff --git a/libs/common/src/services/send.service.ts b/libs/common/src/services/send.service.ts new file mode 100644 index 0000000000..3d8daa3a69 --- /dev/null +++ b/libs/common/src/services/send.service.ts @@ -0,0 +1,295 @@ +import { ApiService } from "../abstractions/api.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; +import { FileUploadService } from "../abstractions/fileUpload.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { SendService as SendServiceAbstraction } from "../abstractions/send.service"; +import { StateService } from "../abstractions/state.service"; +import { SEND_KDF_ITERATIONS } from "../enums/kdfType"; +import { SendType } from "../enums/sendType"; +import { Utils } from "../misc/utils"; +import { SendData } from "../models/data/sendData"; +import { EncArrayBuffer } from "../models/domain/encArrayBuffer"; +import { EncString } from "../models/domain/encString"; +import { Send } from "../models/domain/send"; +import { SendFile } from "../models/domain/sendFile"; +import { SendText } from "../models/domain/sendText"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { SendRequest } from "../models/request/sendRequest"; +import { ErrorResponse } from "../models/response/errorResponse"; +import { SendResponse } from "../models/response/sendResponse"; +import { SendView } from "../models/view/sendView"; + +export class SendService implements SendServiceAbstraction { + constructor( + private cryptoService: CryptoService, + private apiService: ApiService, + private fileUploadService: FileUploadService, + private i18nService: I18nService, + private cryptoFunctionService: CryptoFunctionService, + private stateService: StateService + ) {} + + async clearCache(): Promise { + await this.stateService.setDecryptedSends(null); + } + + async encrypt( + model: SendView, + file: File | ArrayBuffer, + password: string, + key?: SymmetricCryptoKey + ): Promise<[Send, EncArrayBuffer]> { + let fileData: EncArrayBuffer = null; + const send = new Send(); + send.id = model.id; + send.type = model.type; + send.disabled = model.disabled; + send.hideEmail = model.hideEmail; + send.maxAccessCount = model.maxAccessCount; + if (model.key == null) { + model.key = await this.cryptoFunctionService.randomBytes(16); + model.cryptoKey = await this.cryptoService.makeSendKey(model.key); + } + if (password != null) { + const passwordHash = await this.cryptoFunctionService.pbkdf2( + password, + model.key, + "sha256", + SEND_KDF_ITERATIONS + ); + send.password = Utils.fromBufferToB64(passwordHash); + } + send.key = await this.cryptoService.encrypt(model.key, key); + send.name = await this.cryptoService.encrypt(model.name, model.cryptoKey); + send.notes = await this.cryptoService.encrypt(model.notes, model.cryptoKey); + if (send.type === SendType.Text) { + send.text = new SendText(); + send.text.text = await this.cryptoService.encrypt(model.text.text, model.cryptoKey); + send.text.hidden = model.text.hidden; + } else if (send.type === SendType.File) { + send.file = new SendFile(); + if (file != null) { + if (file instanceof ArrayBuffer) { + const [name, data] = await this.encryptFileData( + model.file.fileName, + file, + model.cryptoKey + ); + send.file.fileName = name; + fileData = data; + } else { + fileData = await this.parseFile(send, file, model.cryptoKey); + } + } + } + + return [send, fileData]; + } + + async get(id: string): Promise { + const sends = await this.stateService.getEncryptedSends(); + // eslint-disable-next-line + if (sends == null || !sends.hasOwnProperty(id)) { + return null; + } + + return new Send(sends[id]); + } + + async getAll(): Promise { + const sends = await this.stateService.getEncryptedSends(); + const response: Send[] = []; + for (const id in sends) { + // eslint-disable-next-line + if (sends.hasOwnProperty(id)) { + response.push(new Send(sends[id])); + } + } + return response; + } + + async getAllDecrypted(): Promise { + let decSends = await this.stateService.getDecryptedSends(); + if (decSends != null) { + return decSends; + } + + decSends = []; + const hasKey = await this.cryptoService.hasKey(); + if (!hasKey) { + throw new Error("No key."); + } + + const promises: Promise[] = []; + const sends = await this.getAll(); + sends.forEach((send) => { + promises.push(send.decrypt().then((f) => decSends.push(f))); + }); + + await Promise.all(promises); + decSends.sort(Utils.getSortFunction(this.i18nService, "name")); + + await this.stateService.setDecryptedSends(decSends); + return decSends; + } + + async saveWithServer(sendData: [Send, EncArrayBuffer]): Promise { + const request = new SendRequest(sendData[0], sendData[1]?.buffer.byteLength); + let response: SendResponse; + if (sendData[0].id == null) { + if (sendData[0].type === SendType.Text) { + response = await this.apiService.postSend(request); + } else { + try { + const uploadDataResponse = await this.apiService.postFileTypeSend(request); + response = uploadDataResponse.sendResponse; + + await this.fileUploadService.uploadSendFile( + uploadDataResponse, + sendData[0].file.fileName, + sendData[1] + ); + } catch (e) { + if (e instanceof ErrorResponse && (e as ErrorResponse).statusCode === 404) { + response = await this.legacyServerSendFileUpload(sendData, request); + } else if (e instanceof ErrorResponse) { + throw new Error((e as ErrorResponse).getSingleMessage()); + } else { + throw e; + } + } + } + sendData[0].id = response.id; + sendData[0].accessId = response.accessId; + } else { + response = await this.apiService.putSend(sendData[0].id, request); + } + + const data = new SendData(response); + await this.upsert(data); + } + + /** + * @deprecated Mar 25 2021: This method has been deprecated in favor of direct uploads. + * This method still exists for backward compatibility with old server versions. + */ + async legacyServerSendFileUpload( + sendData: [Send, EncArrayBuffer], + request: SendRequest + ): Promise { + const fd = new FormData(); + try { + const blob = new Blob([sendData[1].buffer], { type: "application/octet-stream" }); + fd.append("model", JSON.stringify(request)); + fd.append("data", blob, sendData[0].file.fileName.encryptedString); + } catch (e) { + if (Utils.isNode && !Utils.isBrowser) { + fd.append("model", JSON.stringify(request)); + fd.append( + "data", + Buffer.from(sendData[1].buffer) as any, + { + filepath: sendData[0].file.fileName.encryptedString, + contentType: "application/octet-stream", + } as any + ); + } else { + throw e; + } + } + return await this.apiService.postSendFileLegacy(fd); + } + + async upsert(send: SendData | SendData[]): Promise { + let sends = await this.stateService.getEncryptedSends(); + if (sends == null) { + sends = {}; + } + + if (send instanceof SendData) { + const s = send as SendData; + sends[s.id] = s; + } else { + (send as SendData[]).forEach((s) => { + sends[s.id] = s; + }); + } + + await this.replace(sends); + } + + async replace(sends: { [id: string]: SendData }): Promise { + await this.stateService.setDecryptedSends(null); + await this.stateService.setEncryptedSends(sends); + } + + async clear(): Promise { + await this.stateService.setDecryptedSends(null); + await this.stateService.setEncryptedSends(null); + } + + async delete(id: string | string[]): Promise { + const sends = await this.stateService.getEncryptedSends(); + if (sends == null) { + return; + } + + if (typeof id === "string") { + if (sends[id] == null) { + return; + } + delete sends[id]; + } else { + (id as string[]).forEach((i) => { + delete sends[i]; + }); + } + + await this.replace(sends); + } + + async deleteWithServer(id: string): Promise { + await this.apiService.deleteSend(id); + await this.delete(id); + } + + async removePasswordWithServer(id: string): Promise { + const response = await this.apiService.putSendRemovePassword(id); + const data = new SendData(response); + await this.upsert(data); + } + + private parseFile(send: Send, file: File, key: SymmetricCryptoKey): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsArrayBuffer(file); + reader.onload = async (evt) => { + try { + const [name, data] = await this.encryptFileData( + file.name, + evt.target.result as ArrayBuffer, + key + ); + send.file.fileName = name; + resolve(data); + } catch (e) { + reject(e); + } + }; + reader.onerror = () => { + reject("Error reading file."); + }; + }); + } + + private async encryptFileData( + fileName: string, + data: ArrayBuffer, + key: SymmetricCryptoKey + ): Promise<[EncString, EncArrayBuffer]> { + const encFileName = await this.cryptoService.encrypt(fileName, key); + const encFileData = await this.cryptoService.encryptToBytes(data, key); + return [encFileName, encFileData]; + } +} diff --git a/libs/common/src/services/settings.service.ts b/libs/common/src/services/settings.service.ts new file mode 100644 index 0000000000..7f5131b0f3 --- /dev/null +++ b/libs/common/src/services/settings.service.ts @@ -0,0 +1,56 @@ +import { SettingsService as SettingsServiceAbstraction } from "../abstractions/settings.service"; +import { StateService } from "../abstractions/state.service"; + +const Keys = { + settingsPrefix: "settings_", + equivalentDomains: "equivalentDomains", +}; + +export class SettingsService implements SettingsServiceAbstraction { + constructor(private stateService: StateService) {} + + async clearCache(): Promise { + await this.stateService.setSettings(null); + } + + getEquivalentDomains(): Promise { + return this.getSettingsKey(Keys.equivalentDomains); + } + + async setEquivalentDomains(equivalentDomains: string[][]): Promise { + await this.setSettingsKey(Keys.equivalentDomains, equivalentDomains); + } + + async clear(userId?: string): Promise { + await this.stateService.setSettings(null, { userId: userId }); + } + + // Helpers + + private async getSettings(): Promise { + const settings = await this.stateService.getSettings(); + if (settings == null) { + // eslint-disable-next-line + const userId = await this.stateService.getUserId(); + } + return settings; + } + + private async getSettingsKey(key: string): Promise { + const settings = await this.getSettings(); + if (settings != null && settings[key]) { + return settings[key]; + } + return null; + } + + private async setSettingsKey(key: string, value: any): Promise { + let settings = await this.getSettings(); + if (!settings) { + settings = {}; + } + + settings[key] = value; + await this.stateService.setSettings(settings); + } +} diff --git a/libs/common/src/services/state.service.ts b/libs/common/src/services/state.service.ts new file mode 100644 index 0000000000..73d4c1b73c --- /dev/null +++ b/libs/common/src/services/state.service.ts @@ -0,0 +1,2534 @@ +import { BehaviorSubject } from "rxjs"; + +import { LogService } from "../abstractions/log.service"; +import { StateService as StateServiceAbstraction } from "../abstractions/state.service"; +import { StateMigrationService } from "../abstractions/stateMigration.service"; +import { StorageService } from "../abstractions/storage.service"; +import { HtmlStorageLocation } from "../enums/htmlStorageLocation"; +import { KdfType } from "../enums/kdfType"; +import { StorageLocation } from "../enums/storageLocation"; +import { ThemeType } from "../enums/themeType"; +import { UriMatchType } from "../enums/uriMatchType"; +import { StateFactory } from "../factories/stateFactory"; +import { CipherData } from "../models/data/cipherData"; +import { CollectionData } from "../models/data/collectionData"; +import { EventData } from "../models/data/eventData"; +import { FolderData } from "../models/data/folderData"; +import { OrganizationData } from "../models/data/organizationData"; +import { PolicyData } from "../models/data/policyData"; +import { ProviderData } from "../models/data/providerData"; +import { SendData } from "../models/data/sendData"; +import { Account, AccountData } from "../models/domain/account"; +import { EncString } from "../models/domain/encString"; +import { EnvironmentUrls } from "../models/domain/environmentUrls"; +import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory"; +import { GlobalState } from "../models/domain/globalState"; +import { Policy } from "../models/domain/policy"; +import { State } from "../models/domain/state"; +import { StorageOptions } from "../models/domain/storageOptions"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; +import { WindowState } from "../models/domain/windowState"; +import { CipherView } from "../models/view/cipherView"; +import { CollectionView } from "../models/view/collectionView"; +import { FolderView } from "../models/view/folderView"; +import { SendView } from "../models/view/sendView"; + +const keys = { + global: "global", + authenticatedAccounts: "authenticatedAccounts", + activeUserId: "activeUserId", + tempAccountSettings: "tempAccountSettings", // used to hold account specific settings (i.e clear clipboard) between initial migration and first account authentication + accountActivity: "accountActivity", +}; + +const partialKeys = { + autoKey: "_masterkey_auto", + biometricKey: "_masterkey_biometric", + masterKey: "_masterkey", +}; + +export class StateService< + TGlobalState extends GlobalState = GlobalState, + TAccount extends Account = Account +> implements StateServiceAbstraction +{ + accounts = new BehaviorSubject<{ [userId: string]: TAccount }>({}); + activeAccount = new BehaviorSubject(null); + + protected state: State = new State( + this.createGlobals() + ); + + private hasBeenInited = false; + + private accountDiskCache: Map; + + constructor( + protected storageService: StorageService, + protected secureStorageService: StorageService, + protected logService: LogService, + protected stateMigrationService: StateMigrationService, + protected stateFactory: StateFactory, + protected useAccountCache: boolean = true + ) { + this.accountDiskCache = new Map(); + } + + async init(): Promise { + if (this.hasBeenInited) { + return; + } + + if (await this.stateMigrationService.needsMigration()) { + await this.stateMigrationService.migrate(); + } + + await this.initAccountState(); + this.hasBeenInited = true; + } + + async initAccountState() { + this.state.authenticatedAccounts = + (await this.storageService.get(keys.authenticatedAccounts)) ?? []; + for (const i in this.state.authenticatedAccounts) { + if (i != null) { + await this.syncAccountFromDisk(this.state.authenticatedAccounts[i]); + } + } + const storedActiveUser = await this.storageService.get(keys.activeUserId); + if (storedActiveUser != null) { + this.state.activeUserId = storedActiveUser; + } + await this.pushAccounts(); + this.activeAccount.next(this.state.activeUserId); + } + + async syncAccountFromDisk(userId: string) { + if (userId == null) { + return; + } + this.state.accounts[userId] = this.createAccount(); + const diskAccount = await this.getAccountFromDisk({ userId: userId }); + this.state.accounts[userId].profile = diskAccount.profile; + } + + async addAccount(account: TAccount) { + account = await this.setAccountEnvironmentUrls(account); + this.state.authenticatedAccounts.push(account.profile.userId); + await this.storageService.save(keys.authenticatedAccounts, this.state.authenticatedAccounts); + this.state.accounts[account.profile.userId] = account; + await this.scaffoldNewAccountStorage(account); + await this.setLastActive(new Date().getTime(), { userId: account.profile.userId }); + await this.setActiveUser(account.profile.userId); + this.activeAccount.next(account.profile.userId); + } + + async setActiveUser(userId: string): Promise { + this.clearDecryptedDataForActiveUser(); + this.state.activeUserId = userId; + await this.storageService.save(keys.activeUserId, userId); + this.activeAccount.next(this.state.activeUserId); + await this.pushAccounts(); + } + + async clean(options?: StorageOptions): Promise { + options = this.reconcileOptions(options, this.defaultInMemoryOptions); + await this.deAuthenticateAccount(options.userId); + if (options.userId === this.state.activeUserId) { + await this.dynamicallySetActiveUser(); + } + + await this.removeAccountFromDisk(options?.userId); + this.removeAccountFromMemory(options?.userId); + await this.pushAccounts(); + } + + async getAccessToken(options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + return (await this.getAccount(options))?.tokens?.accessToken; + } + + async setAccessToken(value: string, options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + const account = await this.getAccount(options); + account.tokens.accessToken = value; + await this.saveAccount(account, options); + } + + async getAddEditCipherInfo(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.data?.addEditCipherInfo; + } + + async setAddEditCipherInfo(value: any, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.data.addEditCipherInfo = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getAlwaysShowDock(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.alwaysShowDock ?? false + ); + } + + async setAlwaysShowDock(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.alwaysShowDock = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getApiKeyClientId(options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + return (await this.getAccount(options))?.profile?.apiKeyClientId; + } + + async setApiKeyClientId(value: string, options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + const account = await this.getAccount(options); + account.profile.apiKeyClientId = value; + await this.saveAccount(account, options); + } + + async getApiKeyClientSecret(options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + return (await this.getAccount(options))?.keys?.apiKeyClientSecret; + } + + async setApiKeyClientSecret(value: string, options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + const account = await this.getAccount(options); + account.keys.apiKeyClientSecret = value; + await this.saveAccount(account, options); + } + + async getAutoConfirmFingerPrints(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.autoConfirmFingerPrints ?? false + ); + } + + async setAutoConfirmFingerprints(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.autoConfirmFingerPrints = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getAutoFillOnPageLoadDefault(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.autoFillOnPageLoadDefault ?? true + ); + } + + async setAutoFillOnPageLoadDefault(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.autoFillOnPageLoadDefault = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getBiometricAwaitingAcceptance(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.biometricAwaitingAcceptance ?? false + ); + } + + async setBiometricAwaitingAcceptance(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.biometricAwaitingAcceptance = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getBiometricFingerprintValidated(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.biometricFingerprintValidated ?? false + ); + } + + async setBiometricFingerprintValidated(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.biometricFingerprintValidated = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getBiometricLocked(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions)))?.settings + ?.biometricLocked ?? false + ); + } + + async setBiometricLocked(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.settings.biometricLocked = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getBiometricText(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.biometricText; + } + + async setBiometricText(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.biometricText = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getBiometricUnlock(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.biometricUnlock ?? false + ); + } + + async setBiometricUnlock(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.biometricUnlock = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getCanAccessPremium(options?: StorageOptions): Promise { + if (!(await this.getIsAuthenticated(options))) { + return false; + } + + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + if (account.profile.hasPremiumPersonally) { + return true; + } + + const organizations = await this.getOrganizations(options); + if (organizations == null) { + return false; + } + + for (const id of Object.keys(organizations)) { + const o = organizations[id]; + if (o.enabled && o.usersGetPremium && !o.isProviderUser) { + return true; + } + } + + return false; + } + + async setCanAccessPremium(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.profile.hasPremiumPersonally = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getClearClipboard(options?: StorageOptions): Promise { + return ( + ( + await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ) + )?.settings?.clearClipboard ?? null + ); + } + + async setClearClipboard(value: number, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.settings.clearClipboard = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getCollapsedGroupings(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.settings?.collapsedGroupings; + } + + async setCollapsedGroupings(value: string[], options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.settings.collapsedGroupings = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getConvertAccountToKeyConnector(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.profile?.convertAccountToKeyConnector; + } + + async setConvertAccountToKeyConnector(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.profile.convertAccountToKeyConnector = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getCryptoMasterKey(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.keys?.cryptoMasterKey; + } + + async setCryptoMasterKey(value: SymmetricCryptoKey, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.keys.cryptoMasterKey = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getCryptoMasterKeyAuto(options?: StorageOptions): Promise { + options = this.reconcileOptions( + this.reconcileOptions(options, { keySuffix: "auto" }), + await this.defaultSecureStorageOptions() + ); + if (options?.userId == null) { + return null; + } + return await this.secureStorageService.get(`${options.userId}${partialKeys.autoKey}`, options); + } + + async setCryptoMasterKeyAuto(value: string, options?: StorageOptions): Promise { + options = this.reconcileOptions( + this.reconcileOptions(options, { keySuffix: "auto" }), + await this.defaultSecureStorageOptions() + ); + if (options?.userId == null) { + return; + } + await this.saveSecureStorageKey(partialKeys.autoKey, value, options); + } + + async getCryptoMasterKeyB64(options?: StorageOptions): Promise { + options = this.reconcileOptions(options, await this.defaultSecureStorageOptions()); + if (options?.userId == null) { + return null; + } + return await this.secureStorageService.get( + `${options?.userId}${partialKeys.masterKey}`, + options + ); + } + + async setCryptoMasterKeyB64(value: string, options?: StorageOptions): Promise { + options = this.reconcileOptions(options, await this.defaultSecureStorageOptions()); + if (options?.userId == null) { + return; + } + await this.saveSecureStorageKey(partialKeys.masterKey, value, options); + } + + async getCryptoMasterKeyBiometric(options?: StorageOptions): Promise { + options = this.reconcileOptions( + this.reconcileOptions(options, { keySuffix: "biometric" }), + await this.defaultSecureStorageOptions() + ); + if (options?.userId == null) { + return null; + } + return await this.secureStorageService.get( + `${options.userId}${partialKeys.biometricKey}`, + options + ); + } + + async hasCryptoMasterKeyBiometric(options?: StorageOptions): Promise { + options = this.reconcileOptions( + this.reconcileOptions(options, { keySuffix: "biometric" }), + await this.defaultSecureStorageOptions() + ); + if (options?.userId == null) { + return false; + } + return await this.secureStorageService.has( + `${options.userId}${partialKeys.biometricKey}`, + options + ); + } + + async setCryptoMasterKeyBiometric(value: string, options?: StorageOptions): Promise { + options = this.reconcileOptions( + this.reconcileOptions(options, { keySuffix: "biometric" }), + await this.defaultSecureStorageOptions() + ); + if (options?.userId == null) { + return; + } + await this.saveSecureStorageKey(partialKeys.biometricKey, value, options); + } + + async getDecodedToken(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.tokens?.decodedToken; + } + + async setDecodedToken(value: any, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.tokens.decodedToken = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedCiphers(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.data?.ciphers?.decrypted; + } + + async setDecryptedCiphers(value: CipherView[], options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.data.ciphers.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedCollections(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.data?.collections?.decrypted; + } + + async setDecryptedCollections(value: CollectionView[], options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.data.collections.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedCryptoSymmetricKey(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.keys?.cryptoSymmetricKey?.decrypted; + } + + async setDecryptedCryptoSymmetricKey( + value: SymmetricCryptoKey, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.keys.cryptoSymmetricKey.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedFolders(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.data?.folders?.decrypted; + } + + async setDecryptedFolders(value: FolderView[], options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.data.folders.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedOrganizationKeys( + options?: StorageOptions + ): Promise> { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.keys?.organizationKeys?.decrypted; + } + + async setDecryptedOrganizationKeys( + value: Map, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.keys.organizationKeys.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedPasswordGenerationHistory( + options?: StorageOptions + ): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.data?.passwordGenerationHistory?.decrypted; + } + + async setDecryptedPasswordGenerationHistory( + value: GeneratedPasswordHistory[], + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.data.passwordGenerationHistory.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedPinProtected(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.settings?.pinProtected?.decrypted; + } + + async setDecryptedPinProtected(value: EncString, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.settings.pinProtected.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedPolicies(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.data?.policies?.decrypted; + } + + async setDecryptedPolicies(value: Policy[], options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.data.policies.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedPrivateKey(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.keys?.privateKey?.decrypted; + } + + async setDecryptedPrivateKey(value: ArrayBuffer, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.keys.privateKey.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedProviderKeys( + options?: StorageOptions + ): Promise> { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.keys?.providerKeys?.decrypted; + } + + async setDecryptedProviderKeys( + value: Map, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.keys.providerKeys.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDecryptedSends(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.data?.sends?.decrypted; + } + + async setDecryptedSends(value: SendView[], options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.data.sends.decrypted = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getDefaultUriMatch(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.defaultUriMatch; + } + + async setDefaultUriMatch(value: UriMatchType, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.defaultUriMatch = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDisableAddLoginNotification(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.disableAddLoginNotification ?? false + ); + } + + async setDisableAddLoginNotification(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.disableAddLoginNotification = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDisableAutoBiometricsPrompt(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.disableAutoBiometricsPrompt ?? false + ); + } + + async setDisableAutoBiometricsPrompt(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.disableAutoBiometricsPrompt = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDisableAutoTotpCopy(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.disableAutoTotpCopy ?? false + ); + } + + async setDisableAutoTotpCopy(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.disableAutoTotpCopy = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDisableBadgeCounter(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.disableBadgeCounter ?? false + ); + } + + async setDisableBadgeCounter(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.disableBadgeCounter = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDisableChangedPasswordNotification(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.disableChangedPasswordNotification ?? false + ); + } + + async setDisableChangedPasswordNotification( + value: boolean, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.disableChangedPasswordNotification = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDisableContextMenuItem(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.disableContextMenuItem ?? false + ); + } + + async setDisableContextMenuItem(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.disableContextMenuItem = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDisableFavicon(options?: StorageOptions): Promise { + return ( + ( + await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ) + )?.disableFavicon ?? false + ); + } + + async setDisableFavicon(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + globals.disableFavicon = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getDisableGa(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.disableGa ?? false + ); + } + + async setDisableGa(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.disableGa = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDontShowCardsCurrentTab(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.dontShowCardsCurrentTab ?? false + ); + } + + async setDontShowCardsCurrentTab(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.dontShowCardsCurrentTab = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getDontShowIdentitiesCurrentTab(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.dontShowIdentitiesCurrentTab ?? false + ); + } + + async setDontShowIdentitiesCurrentTab(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.dontShowIdentitiesCurrentTab = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEmail(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.profile?.email; + } + + async setEmail(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.profile.email = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getEmailVerified(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.profile.emailVerified ?? false + ); + } + + async setEmailVerified(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.profile.emailVerified = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableAlwaysOnTop(options?: StorageOptions): Promise { + const accountPreference = ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.enableAlwaysOnTop; + const globalPreference = ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.enableAlwaysOnTop; + return accountPreference ?? globalPreference ?? false; + } + + async setEnableAlwaysOnTop(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.enableAlwaysOnTop = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableAlwaysOnTop = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableAutoFillOnPageLoad(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.enableAutoFillOnPageLoad ?? false + ); + } + + async setEnableAutoFillOnPageLoad(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.enableAutoFillOnPageLoad = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableBiometric(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.enableBiometrics ?? false + ); + } + + async setEnableBiometric(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableBiometrics = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableBrowserIntegration(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.enableBrowserIntegration ?? false + ); + } + + async setEnableBrowserIntegration(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableBrowserIntegration = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableBrowserIntegrationFingerprint(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.enableBrowserIntegrationFingerprint ?? false + ); + } + + async setEnableBrowserIntegrationFingerprint( + value: boolean, + options?: StorageOptions + ): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableBrowserIntegrationFingerprint = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableCloseToTray(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.enableCloseToTray ?? false + ); + } + + async setEnableCloseToTray(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableCloseToTray = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableFullWidth(options?: StorageOptions): Promise { + return ( + ( + await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ) + )?.settings?.enableFullWidth ?? false + ); + } + + async setEnableFullWidth(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.settings.enableFullWidth = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getEnableGravitars(options?: StorageOptions): Promise { + return ( + ( + await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ) + )?.settings?.enableGravitars ?? false + ); + } + + async setEnableGravitars(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.settings.enableGravitars = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getEnableMinimizeToTray(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.enableMinimizeToTray ?? false + ); + } + + async setEnableMinimizeToTray(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableMinimizeToTray = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableStartToTray(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.enableStartToTray ?? false + ); + } + + async setEnableStartToTray(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableStartToTray = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEnableTray(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.enableTray ?? false + ); + } + + async setEnableTray(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.enableTray = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedCiphers(options?: StorageOptions): Promise<{ [id: string]: CipherData }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions())) + )?.data?.ciphers?.encrypted; + } + + async setEncryptedCiphers( + value: { [id: string]: CipherData }, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + account.data.ciphers.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + } + + async getEncryptedCollections( + options?: StorageOptions + ): Promise<{ [id: string]: CollectionData }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions())) + )?.data?.collections?.encrypted; + } + + async setEncryptedCollections( + value: { [id: string]: CollectionData }, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + account.data.collections.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + } + + async getEncryptedCryptoSymmetricKey(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.keys.cryptoSymmetricKey.encrypted; + } + + async setEncryptedCryptoSymmetricKey(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.keys.cryptoSymmetricKey.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedFolders(options?: StorageOptions): Promise<{ [id: string]: FolderData }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions())) + )?.data?.folders?.encrypted; + } + + async setEncryptedFolders( + value: { [id: string]: FolderData }, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + account.data.folders.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + } + + async getEncryptedOrganizationKeys(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.keys?.organizationKeys.encrypted; + } + + async setEncryptedOrganizationKeys( + value: Map, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.keys.organizationKeys.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedPasswordGenerationHistory( + options?: StorageOptions + ): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.data?.passwordGenerationHistory?.encrypted; + } + + async setEncryptedPasswordGenerationHistory( + value: GeneratedPasswordHistory[], + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.data.passwordGenerationHistory.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedPinProtected(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.pinProtected?.encrypted; + } + + async setEncryptedPinProtected(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.pinProtected.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedPolicies(options?: StorageOptions): Promise<{ [id: string]: PolicyData }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.data?.policies?.encrypted; + } + + async setEncryptedPolicies( + value: { [id: string]: PolicyData }, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.data.policies.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedPrivateKey(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.keys?.privateKey?.encrypted; + } + + async setEncryptedPrivateKey(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.keys.privateKey.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedProviderKeys(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.keys?.providerKeys?.encrypted; + } + + async setEncryptedProviderKeys(value: any, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.keys.providerKeys.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEncryptedSends(options?: StorageOptions): Promise<{ [id: string]: SendData }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions())) + )?.data?.sends.encrypted; + } + + async setEncryptedSends( + value: { [id: string]: SendData }, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + account.data.sends.encrypted = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + } + + async getEntityId(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.profile?.entityId; + } + + async setEntityId(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.profile.entityId = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getEntityType(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.profile?.entityType; + } + + async setEntityType(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.profile.entityType = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getEnvironmentUrls(options?: StorageOptions): Promise { + if (this.state.activeUserId == null) { + return await this.getGlobalEnvironmentUrls(options); + } + options = this.reconcileOptions(options, await this.defaultOnDiskOptions()); + return (await this.getAccount(options))?.settings?.environmentUrls ?? new EnvironmentUrls(); + } + + async setEnvironmentUrls(value: EnvironmentUrls, options?: StorageOptions): Promise { + // Global values are set on each change and the current global settings are passed to any newly authed accounts. + // This is to allow setting environement values before an account is active, while still allowing individual accounts to have their own environments. + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.environmentUrls = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEquivalentDomains(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.equivalentDomains; + } + + async setEquivalentDomains(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.equivalentDomains = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEventCollection(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.data?.eventCollection; + } + + async setEventCollection(value: EventData[], options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.data.eventCollection = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getEverBeenUnlocked(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions)))?.profile + ?.everBeenUnlocked ?? false + ); + } + + async setEverBeenUnlocked(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.profile.everBeenUnlocked = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getForcePasswordReset(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions)))?.profile + ?.forcePasswordReset ?? false + ); + } + + async setForcePasswordReset(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.profile.forcePasswordReset = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getInstalledVersion(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.installedVersion; + } + + async setInstalledVersion(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.installedVersion = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getIsAuthenticated(options?: StorageOptions): Promise { + return (await this.getAccessToken(options)) != null && (await this.getUserId(options)) != null; + } + + async getKdfIterations(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.profile?.kdfIterations; + } + + async setKdfIterations(value: number, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.profile.kdfIterations = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getKdfType(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.profile?.kdfType; + } + + async setKdfType(value: KdfType, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.profile.kdfType = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getKeyHash(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.profile?.keyHash; + } + + async setKeyHash(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.profile.keyHash = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getLastActive(options?: StorageOptions): Promise { + options = this.reconcileOptions(options, await this.defaultOnDiskOptions()); + + const accountActivity = await this.storageService.get<{ [userId: string]: number }>( + keys.accountActivity, + options + ); + + if (accountActivity == null || Object.keys(accountActivity).length < 1) { + return null; + } + + return accountActivity[options.userId]; + } + + async setLastActive(value: number, options?: StorageOptions): Promise { + options = this.reconcileOptions(options, await this.defaultOnDiskOptions()); + if (options.userId == null) { + return; + } + const accountActivity = + (await this.storageService.get<{ [userId: string]: number }>( + keys.accountActivity, + options + )) ?? {}; + accountActivity[options.userId] = value; + await this.storageService.save(keys.accountActivity, accountActivity, options); + } + + async getLastSync(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions())) + )?.profile?.lastSync; + } + + async setLastSync(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + account.profile.lastSync = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + } + + async getLegacyEtmKey(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.keys?.legacyEtmKey; + } + + async setLegacyEtmKey(value: SymmetricCryptoKey, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.keys.legacyEtmKey = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getLocalData(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.data?.localData; + } + async setLocalData(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.data.localData = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getLocale(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.locale; + } + + async setLocale(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + globals.locale = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getMainWindowSize(options?: StorageOptions): Promise { + return (await this.getGlobals(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.mainWindowSize; + } + + async setMainWindowSize(value: number, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + globals.mainWindowSize = value; + await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getMinimizeOnCopyToClipboard(options?: StorageOptions): Promise { + return ( + (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.settings?.minimizeOnCopyToClipboard ?? false + ); + } + + async setMinimizeOnCopyToClipboard(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.minimizeOnCopyToClipboard = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getNeverDomains(options?: StorageOptions): Promise<{ [id: string]: any }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.neverDomains; + } + + async setNeverDomains(value: { [id: string]: any }, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.neverDomains = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getNoAutoPromptBiometrics(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.noAutoPromptBiometrics ?? false + ); + } + + async setNoAutoPromptBiometrics(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.noAutoPromptBiometrics = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getNoAutoPromptBiometricsText(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.noAutoPromptBiometricsText; + } + + async setNoAutoPromptBiometricsText(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.noAutoPromptBiometricsText = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getOpenAtLogin(options?: StorageOptions): Promise { + return ( + (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) + ?.openAtLogin ?? false + ); + } + + async setOpenAtLogin(value: boolean, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.openAtLogin = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getOrganizationInvitation(options?: StorageOptions): Promise { + return (await this.getGlobals(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.organizationInvitation; + } + + async setOrganizationInvitation(value: any, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + globals.organizationInvitation = value; + await this.saveGlobals(globals, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getOrganizations(options?: StorageOptions): Promise<{ [id: string]: OrganizationData }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.data?.organizations; + } + + async setOrganizations( + value: { [id: string]: OrganizationData }, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.data.organizations = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getPasswordGenerationOptions(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.passwordGenerationOptions; + } + + async setPasswordGenerationOptions(value: any, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.passwordGenerationOptions = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getUsernameGenerationOptions(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.usernameGenerationOptions; + } + + async setUsernameGenerationOptions(value: any, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.usernameGenerationOptions = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getGeneratorOptions(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.generatorOptions; + } + + async setGeneratorOptions(value: any, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.generatorOptions = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getProtectedPin(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.settings?.protectedPin; + } + + async setProtectedPin(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.settings.protectedPin = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getProviders(options?: StorageOptions): Promise<{ [id: string]: ProviderData }> { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.data?.providers; + } + + async setProviders( + value: { [id: string]: ProviderData }, + options?: StorageOptions + ): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.data.providers = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getPublicKey(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.keys?.publicKey; + } + + async setPublicKey(value: ArrayBuffer, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.keys.publicKey = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getRefreshToken(options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + return (await this.getAccount(options))?.tokens?.refreshToken; + } + + async setRefreshToken(value: string, options?: StorageOptions): Promise { + options = await this.getTimeoutBasedStorageOptions(options); + const account = await this.getAccount(options); + account.tokens.refreshToken = value; + await this.saveAccount(account, options); + } + + async getRememberedEmail(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.rememberedEmail; + } + + async setRememberedEmail(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + globals.rememberedEmail = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getSecurityStamp(options?: StorageOptions): Promise { + return (await this.getAccount(this.reconcileOptions(options, this.defaultInMemoryOptions))) + ?.tokens?.securityStamp; + } + + async setSecurityStamp(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, this.defaultInMemoryOptions) + ); + account.tokens.securityStamp = value; + await this.saveAccount(account, this.reconcileOptions(options, this.defaultInMemoryOptions)); + } + + async getSettings(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions())) + )?.settings?.settings; + } + + async setSettings(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + account.settings.settings = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskMemoryOptions()) + ); + } + + async getSsoCodeVerifier(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.ssoCodeVerifier; + } + + async setSsoCodeVerifier(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.ssoCodeVerifier = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getSsoOrgIdentifier(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.ssoOrganizationIdentifier; + } + + async setSsoOrganizationIdentifier(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + globals.ssoOrganizationIdentifier = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getSsoState(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.ssoState; + } + + async setSsoState(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.ssoState = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getTheme(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.theme; + } + + async setTheme(value: ThemeType, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + globals.theme = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getTwoFactorToken(options?: StorageOptions): Promise { + return ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.twoFactorToken; + } + + async setTwoFactorToken(value: string, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + globals.twoFactorToken = value; + await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getUserId(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.profile?.userId; + } + + async getUsesKeyConnector(options?: StorageOptions): Promise { + return ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions())) + )?.profile?.usesKeyConnector; + } + + async setUsesKeyConnector(value: boolean, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + account.profile.usesKeyConnector = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + async getVaultTimeout(options?: StorageOptions): Promise { + const accountVaultTimeout = ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.settings?.vaultTimeout; + return accountVaultTimeout; + } + + async setVaultTimeout(value: number, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.settings.vaultTimeout = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getVaultTimeoutAction(options?: StorageOptions): Promise { + const accountVaultTimeoutAction = ( + await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.settings?.vaultTimeoutAction; + const globalVaultTimeoutAction = ( + await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskLocalOptions())) + )?.vaultTimeoutAction; + return accountVaultTimeoutAction ?? globalVaultTimeoutAction; + } + + async setVaultTimeoutAction(value: string, options?: StorageOptions): Promise { + const account = await this.getAccount( + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + account.settings.vaultTimeoutAction = value; + await this.saveAccount( + account, + this.reconcileOptions(options, await this.defaultOnDiskLocalOptions()) + ); + } + + async getStateVersion(): Promise { + return (await this.getGlobals(await this.defaultOnDiskLocalOptions())).stateVersion ?? 1; + } + + async setStateVersion(value: number): Promise { + const globals = await this.getGlobals(await this.defaultOnDiskOptions()); + globals.stateVersion = value; + await this.saveGlobals(globals, await this.defaultOnDiskOptions()); + } + + async getWindow(): Promise { + const globals = await this.getGlobals(await this.defaultOnDiskOptions()); + return globals?.window != null && Object.keys(globals.window).length > 0 + ? globals.window + : new WindowState(); + } + + async setWindow(value: WindowState, options?: StorageOptions): Promise { + const globals = await this.getGlobals( + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + globals.window = value; + return await this.saveGlobals( + globals, + this.reconcileOptions(options, await this.defaultOnDiskOptions()) + ); + } + + protected async getGlobals(options: StorageOptions): Promise { + let globals: TGlobalState; + if (this.useMemory(options.storageLocation)) { + globals = this.getGlobalsFromMemory(); + } + + if (this.useDisk && globals == null) { + globals = await this.getGlobalsFromDisk(options); + } + + return globals ?? this.createGlobals(); + } + + protected async saveGlobals(globals: TGlobalState, options: StorageOptions) { + return this.useMemory(options.storageLocation) + ? this.saveGlobalsToMemory(globals) + : await this.saveGlobalsToDisk(globals, options); + } + + protected getGlobalsFromMemory(): TGlobalState { + return this.state.globals; + } + + protected async getGlobalsFromDisk(options: StorageOptions): Promise { + return await this.storageService.get(keys.global, options); + } + + protected saveGlobalsToMemory(globals: TGlobalState): void { + this.state.globals = globals; + } + + protected async saveGlobalsToDisk(globals: TGlobalState, options: StorageOptions): Promise { + if (options.useSecureStorage) { + await this.secureStorageService.save(keys.global, globals, options); + } else { + await this.storageService.save(keys.global, globals, options); + } + } + + protected async getAccount(options: StorageOptions): Promise { + try { + let account: TAccount; + if (this.useMemory(options.storageLocation)) { + account = this.getAccountFromMemory(options); + } + + if (this.useDisk(options.storageLocation) && account == null) { + account = await this.getAccountFromDisk(options); + } + + return account; + } catch (e) { + this.logService.error(e); + } + } + + protected getAccountFromMemory(options: StorageOptions): TAccount { + if (this.state.accounts == null) { + return null; + } + return this.state.accounts[this.getUserIdFromMemory(options)]; + } + + protected getUserIdFromMemory(options: StorageOptions): string { + return options?.userId != null + ? this.state.accounts[options.userId]?.profile?.userId + : this.state.activeUserId; + } + + protected async getAccountFromDisk(options: StorageOptions): Promise { + if (options?.userId == null && this.state.activeUserId == null) { + return null; + } + + if (this.useAccountCache) { + const cachedAccount = this.accountDiskCache.get(options.userId); + if (cachedAccount != null) { + return cachedAccount; + } + } + + const account = options?.useSecureStorage + ? (await this.secureStorageService.get(options.userId, options)) ?? + (await this.storageService.get( + options.userId, + this.reconcileOptions(options, { htmlStorageLocation: HtmlStorageLocation.Local }) + )) + : await this.storageService.get(options.userId, options); + + if (this.useAccountCache) { + this.accountDiskCache.set(options.userId, account); + } + return account; + } + + protected useMemory(storageLocation: StorageLocation) { + return storageLocation === StorageLocation.Memory || storageLocation === StorageLocation.Both; + } + + protected useDisk(storageLocation: StorageLocation) { + return storageLocation === StorageLocation.Disk || storageLocation === StorageLocation.Both; + } + + protected async saveAccount( + account: TAccount, + options: StorageOptions = { + storageLocation: StorageLocation.Both, + useSecureStorage: false, + } + ) { + return this.useMemory(options.storageLocation) + ? await this.saveAccountToMemory(account) + : await this.saveAccountToDisk(account, options); + } + + protected async saveAccountToDisk(account: TAccount, options: StorageOptions): Promise { + const storageLocation = options.useSecureStorage + ? this.secureStorageService + : this.storageService; + + await storageLocation.save(`${options.userId}`, account, options); + + if (this.useAccountCache) { + this.accountDiskCache.delete(options.userId); + } + } + + protected async saveAccountToMemory(account: TAccount): Promise { + if (this.getAccountFromMemory({ userId: account.profile.userId }) !== null) { + this.state.accounts[account.profile.userId] = account; + } + await this.pushAccounts(); + } + + protected async scaffoldNewAccountStorage(account: TAccount): Promise { + // We don't want to manipulate the referenced in memory account + const deepClone = JSON.parse(JSON.stringify(account)); + await this.scaffoldNewAccountLocalStorage(deepClone); + await this.scaffoldNewAccountSessionStorage(deepClone); + await this.scaffoldNewAccountMemoryStorage(deepClone); + } + + // TODO: There is a tech debt item for splitting up these methods - only Web uses multiple storage locations in its storageService. + // For now these methods exist with some redundancy to facilitate this special web requirement. + protected async scaffoldNewAccountLocalStorage(account: TAccount): Promise { + const storedAccount = await this.getAccount( + this.reconcileOptions( + { userId: account.profile.userId }, + await this.defaultOnDiskLocalOptions() + ) + ); + // EnvironmentUrls are set before authenticating and should override whatever is stored from any previous session + const environmentUrls = account.settings.environmentUrls; + if (storedAccount?.settings != null) { + account.settings = storedAccount.settings; + } else if (await this.storageService.has(keys.tempAccountSettings)) { + account.settings = await this.storageService.get(keys.tempAccountSettings); + await this.storageService.remove(keys.tempAccountSettings); + } + account.settings.environmentUrls = environmentUrls; + if (account.settings.vaultTimeoutAction === "logOut" && account.settings.vaultTimeout != null) { + account.tokens.accessToken = null; + account.tokens.refreshToken = null; + account.profile.apiKeyClientId = null; + account.keys.apiKeyClientSecret = null; + } + await this.saveAccount( + account, + this.reconcileOptions( + { userId: account.profile.userId }, + await this.defaultOnDiskLocalOptions() + ) + ); + } + + protected async scaffoldNewAccountMemoryStorage(account: TAccount): Promise { + const storedAccount = await this.getAccount( + this.reconcileOptions( + { userId: account.profile.userId }, + await this.defaultOnDiskMemoryOptions() + ) + ); + if (storedAccount?.settings != null) { + storedAccount.settings.environmentUrls = account.settings.environmentUrls; + account.settings = storedAccount.settings; + } + await this.storageService.save( + account.profile.userId, + account, + await this.defaultOnDiskMemoryOptions() + ); + await this.saveAccount( + account, + this.reconcileOptions( + { userId: account.profile.userId }, + await this.defaultOnDiskMemoryOptions() + ) + ); + } + + protected async scaffoldNewAccountSessionStorage(account: TAccount): Promise { + const storedAccount = await this.getAccount( + this.reconcileOptions({ userId: account.profile.userId }, await this.defaultOnDiskOptions()) + ); + if (storedAccount?.settings != null) { + storedAccount.settings.environmentUrls = account.settings.environmentUrls; + account.settings = storedAccount.settings; + } + await this.storageService.save( + account.profile.userId, + account, + await this.defaultOnDiskMemoryOptions() + ); + await this.saveAccount( + account, + this.reconcileOptions({ userId: account.profile.userId }, await this.defaultOnDiskOptions()) + ); + } + // + + protected async pushAccounts(): Promise { + await this.pruneInMemoryAccounts(); + if (this.state?.accounts == null || Object.keys(this.state.accounts).length < 1) { + this.accounts.next(null); + return; + } + + this.accounts.next(this.state.accounts); + } + + protected reconcileOptions( + requestedOptions: StorageOptions, + defaultOptions: StorageOptions + ): StorageOptions { + if (requestedOptions == null) { + return defaultOptions; + } + requestedOptions.userId = requestedOptions?.userId ?? defaultOptions.userId; + requestedOptions.storageLocation = + requestedOptions?.storageLocation ?? defaultOptions.storageLocation; + requestedOptions.useSecureStorage = + requestedOptions?.useSecureStorage ?? defaultOptions.useSecureStorage; + requestedOptions.htmlStorageLocation = + requestedOptions?.htmlStorageLocation ?? defaultOptions.htmlStorageLocation; + requestedOptions.keySuffix = requestedOptions?.keySuffix ?? defaultOptions.keySuffix; + return requestedOptions; + } + + protected get defaultInMemoryOptions(): StorageOptions { + return { storageLocation: StorageLocation.Memory, userId: this.state.activeUserId }; + } + + protected async defaultOnDiskOptions(): Promise { + return { + storageLocation: StorageLocation.Disk, + htmlStorageLocation: HtmlStorageLocation.Session, + userId: this.state.activeUserId ?? (await this.getActiveUserIdFromStorage()), + useSecureStorage: false, + }; + } + + protected async defaultOnDiskLocalOptions(): Promise { + return { + storageLocation: StorageLocation.Disk, + htmlStorageLocation: HtmlStorageLocation.Local, + userId: this.state.activeUserId ?? (await this.getActiveUserIdFromStorage()), + useSecureStorage: false, + }; + } + + protected async defaultOnDiskMemoryOptions(): Promise { + return { + storageLocation: StorageLocation.Disk, + htmlStorageLocation: HtmlStorageLocation.Memory, + userId: this.state.activeUserId ?? (await this.getUserId()), + useSecureStorage: false, + }; + } + + protected async defaultSecureStorageOptions(): Promise { + return { + storageLocation: StorageLocation.Disk, + useSecureStorage: true, + userId: this.state.activeUserId ?? (await this.getActiveUserIdFromStorage()), + }; + } + + protected async getActiveUserIdFromStorage(): Promise { + return await this.storageService.get(keys.activeUserId); + } + + protected async removeAccountFromLocalStorage( + userId: string = this.state.activeUserId + ): Promise { + const storedAccount = await this.getAccount( + this.reconcileOptions({ userId: userId }, await this.defaultOnDiskLocalOptions()) + ); + await this.saveAccount( + this.resetAccount(storedAccount), + this.reconcileOptions({ userId: userId }, await this.defaultOnDiskLocalOptions()) + ); + } + + protected async removeAccountFromSessionStorage( + userId: string = this.state.activeUserId + ): Promise { + const storedAccount = await this.getAccount( + this.reconcileOptions({ userId: userId }, await this.defaultOnDiskOptions()) + ); + await this.saveAccount( + this.resetAccount(storedAccount), + this.reconcileOptions({ userId: userId }, await this.defaultOnDiskOptions()) + ); + } + + protected async removeAccountFromSecureStorage( + userId: string = this.state.activeUserId + ): Promise { + await this.setCryptoMasterKeyAuto(null, { userId: userId }); + await this.setCryptoMasterKeyBiometric(null, { userId: userId }); + await this.setCryptoMasterKeyB64(null, { userId: userId }); + } + + protected removeAccountFromMemory(userId: string = this.state.activeUserId): void { + delete this.state.accounts[userId]; + if (this.useAccountCache) { + this.accountDiskCache.delete(userId); + } + } + + protected async pruneInMemoryAccounts() { + // We preserve settings for logged out accounts, but we don't want to consider them when thinking about active account state + for (const userId in this.state.accounts) { + if (!(await this.getIsAuthenticated({ userId: userId }))) { + this.removeAccountFromMemory(userId); + } + } + } + + // settings persist even on reset, and are not effected by this method + protected resetAccount(account: TAccount) { + const persistentAccountInformation = { settings: account.settings }; + return Object.assign(this.createAccount(), persistentAccountInformation); + } + + protected async setAccountEnvironmentUrls(account: TAccount): Promise { + account.settings.environmentUrls = await this.getGlobalEnvironmentUrls(); + return account; + } + + protected async getGlobalEnvironmentUrls(options?: StorageOptions): Promise { + options = this.reconcileOptions(options, await this.defaultOnDiskOptions()); + return (await this.getGlobals(options)).environmentUrls ?? new EnvironmentUrls(); + } + + protected clearDecryptedDataForActiveUser() { + const userId = this.state.activeUserId; + if (userId == null || this.state?.accounts[userId]?.data == null) { + return; + } + this.state.accounts[userId].data = new AccountData(); + } + + protected createAccount(init: Partial = null): TAccount { + return this.stateFactory.createAccount(init); + } + + protected createGlobals(init: Partial = null): TGlobalState { + return this.stateFactory.createGlobal(init); + } + + protected async deAuthenticateAccount(userId: string) { + await this.setAccessToken(null, { userId: userId }); + await this.setLastActive(null, { userId: userId }); + this.state.authenticatedAccounts = this.state.authenticatedAccounts.filter( + (activeUserId) => activeUserId !== userId + ); + await this.storageService.save(keys.authenticatedAccounts, this.state.authenticatedAccounts); + } + + protected async removeAccountFromDisk(userId: string) { + await this.removeAccountFromSessionStorage(userId); + await this.removeAccountFromLocalStorage(userId); + await this.removeAccountFromSecureStorage(userId); + } + + protected async dynamicallySetActiveUser() { + if (this.state.accounts == null || Object.keys(this.state.accounts).length < 1) { + await this.setActiveUser(null); + return; + } + for (const userId in this.state.accounts) { + if (userId == null) { + continue; + } + if (await this.getIsAuthenticated({ userId: userId })) { + await this.setActiveUser(userId); + break; + } + await this.setActiveUser(null); + } + } + + private async getTimeoutBasedStorageOptions(options?: StorageOptions): Promise { + const timeoutAction = await this.getVaultTimeoutAction({ userId: options?.userId }); + const timeout = await this.getVaultTimeout({ userId: options?.userId }); + const defaultOptions = + timeoutAction === "logOut" && timeout != null + ? this.defaultInMemoryOptions + : await this.defaultOnDiskOptions(); + return this.reconcileOptions(options, defaultOptions); + } + + private async saveSecureStorageKey(key: string, value: string, options?: StorageOptions) { + return value == null + ? await this.secureStorageService.remove(`${options.userId}${key}`, options) + : await this.secureStorageService.save(`${options.userId}${key}`, value, options); + } +} diff --git a/libs/common/src/services/stateMigration.service.ts b/libs/common/src/services/stateMigration.service.ts new file mode 100644 index 0000000000..2b299898a3 --- /dev/null +++ b/libs/common/src/services/stateMigration.service.ts @@ -0,0 +1,513 @@ +import { StorageService } from "../abstractions/storage.service"; +import { HtmlStorageLocation } from "../enums/htmlStorageLocation"; +import { KdfType } from "../enums/kdfType"; +import { StateVersion } from "../enums/stateVersion"; +import { ThemeType } from "../enums/themeType"; +import { StateFactory } from "../factories/stateFactory"; +import { CipherData } from "../models/data/cipherData"; +import { CollectionData } from "../models/data/collectionData"; +import { EventData } from "../models/data/eventData"; +import { FolderData } from "../models/data/folderData"; +import { OrganizationData } from "../models/data/organizationData"; +import { PolicyData } from "../models/data/policyData"; +import { ProviderData } from "../models/data/providerData"; +import { SendData } from "../models/data/sendData"; +import { Account, AccountSettings } from "../models/domain/account"; +import { EnvironmentUrls } from "../models/domain/environmentUrls"; +import { GeneratedPasswordHistory } from "../models/domain/generatedPasswordHistory"; +import { GlobalState } from "../models/domain/globalState"; +import { StorageOptions } from "../models/domain/storageOptions"; + +import { TokenService } from "./token.service"; + +// Originally (before January 2022) storage was handled as a flat key/value pair store. +// With the move to a typed object for state storage these keys should no longer be in use anywhere outside of this migration. +const v1Keys: { [key: string]: string } = { + accessToken: "accessToken", + alwaysShowDock: "alwaysShowDock", + autoConfirmFingerprints: "autoConfirmFingerprints", + autoFillOnPageLoadDefault: "autoFillOnPageLoadDefault", + biometricAwaitingAcceptance: "biometricAwaitingAcceptance", + biometricFingerprintValidated: "biometricFingerprintValidated", + biometricText: "biometricText", + biometricUnlock: "biometric", + clearClipboard: "clearClipboardKey", + clientId: "apikey_clientId", + clientSecret: "apikey_clientSecret", + collapsedGroupings: "collapsedGroupings", + convertAccountToKeyConnector: "convertAccountToKeyConnector", + defaultUriMatch: "defaultUriMatch", + disableAddLoginNotification: "disableAddLoginNotification", + disableAutoBiometricsPrompt: "noAutoPromptBiometrics", + disableAutoTotpCopy: "disableAutoTotpCopy", + disableBadgeCounter: "disableBadgeCounter", + disableChangedPasswordNotification: "disableChangedPasswordNotification", + disableContextMenuItem: "disableContextMenuItem", + disableFavicon: "disableFavicon", + disableGa: "disableGa", + dontShowCardsCurrentTab: "dontShowCardsCurrentTab", + dontShowIdentitiesCurrentTab: "dontShowIdentitiesCurrentTab", + emailVerified: "emailVerified", + enableAlwaysOnTop: "enableAlwaysOnTopKey", + enableAutoFillOnPageLoad: "enableAutoFillOnPageLoad", + enableBiometric: "enabledBiometric", + enableBrowserIntegration: "enableBrowserIntegration", + enableBrowserIntegrationFingerprint: "enableBrowserIntegrationFingerprint", + enableCloseToTray: "enableCloseToTray", + enableFullWidth: "enableFullWidth", + enableGravatars: "enableGravatars", + enableMinimizeToTray: "enableMinimizeToTray", + enableStartToTray: "enableStartToTrayKey", + enableTray: "enableTray", + encKey: "encKey", // Generated Symmetric Key + encOrgKeys: "encOrgKeys", + encPrivate: "encPrivateKey", + encProviderKeys: "encProviderKeys", + entityId: "entityId", + entityType: "entityType", + environmentUrls: "environmentUrls", + equivalentDomains: "equivalentDomains", + eventCollection: "eventCollection", + forcePasswordReset: "forcePasswordReset", + history: "generatedPasswordHistory", + installedVersion: "installedVersion", + kdf: "kdf", + kdfIterations: "kdfIterations", + key: "key", // Master Key + keyHash: "keyHash", + lastActive: "lastActive", + localData: "sitesLocalData", + locale: "locale", + mainWindowSize: "mainWindowSize", + minimizeOnCopyToClipboard: "minimizeOnCopyToClipboardKey", + neverDomains: "neverDomains", + noAutoPromptBiometricsText: "noAutoPromptBiometricsText", + openAtLogin: "openAtLogin", + passwordGenerationOptions: "passwordGenerationOptions", + pinProtected: "pinProtectedKey", + protectedPin: "protectedPin", + refreshToken: "refreshToken", + ssoCodeVerifier: "ssoCodeVerifier", + ssoIdentifier: "ssoOrgIdentifier", + ssoState: "ssoState", + stamp: "securityStamp", + theme: "theme", + userEmail: "userEmail", + userId: "userId", + usesConnector: "usesKeyConnector", + vaultTimeoutAction: "vaultTimeoutAction", + vaultTimeout: "lockOption", + rememberedEmail: "rememberedEmail", +}; + +const v1KeyPrefixes: { [key: string]: string } = { + ciphers: "ciphers_", + collections: "collections_", + folders: "folders_", + lastSync: "lastSync_", + policies: "policies_", + twoFactorToken: "twoFactorToken_", + organizations: "organizations_", + providers: "providers_", + sends: "sends_", + settings: "settings_", +}; + +const keys = { + global: "global", + authenticatedAccounts: "authenticatedAccounts", + activeUserId: "activeUserId", + tempAccountSettings: "tempAccountSettings", // used to hold account specific settings (i.e clear clipboard) between initial migration and first account authentication + accountActivity: "accountActivity", +}; + +const partialKeys = { + autoKey: "_masterkey_auto", + biometricKey: "_masterkey_biometric", + masterKey: "_masterkey", +}; + +export class StateMigrationService< + TGlobalState extends GlobalState = GlobalState, + TAccount extends Account = Account +> { + constructor( + protected storageService: StorageService, + protected secureStorageService: StorageService, + protected stateFactory: StateFactory + ) {} + + async needsMigration(): Promise { + const currentStateVersion = await this.getCurrentStateVersion(); + return currentStateVersion == null || currentStateVersion < StateVersion.Latest; + } + + async migrate(): Promise { + let currentStateVersion = await this.getCurrentStateVersion(); + while (currentStateVersion < StateVersion.Latest) { + switch (currentStateVersion) { + case StateVersion.One: + await this.migrateStateFrom1To2(); + break; + case StateVersion.Two: + await this.migrateStateFrom2To3(); + break; + case StateVersion.Three: + await this.migrateStateFrom3To4(); + break; + } + + currentStateVersion += 1; + } + } + + protected async migrateStateFrom1To2(): Promise { + const clearV1Keys = async (clearingUserId?: string) => { + for (const key in v1Keys) { + if (key == null) { + continue; + } + await this.set(v1Keys[key], null); + } + if (clearingUserId != null) { + for (const keyPrefix in v1KeyPrefixes) { + if (keyPrefix == null) { + continue; + } + await this.set(v1KeyPrefixes[keyPrefix] + userId, null); + } + } + }; + + // Some processes, like biometrics, may have already defined a value before migrations are run. + // We don't want to null out those values if they don't exist in the old storage scheme (like for new installs) + // So, the OOO for migration is that we: + // 1. Check for an existing storage value from the old storage structure OR + // 2. Check for a value already set by processes that run before migration OR + // 3. Assign the default value + const globals = + (await this.get(keys.global)) ?? this.stateFactory.createGlobal(null); + globals.stateVersion = StateVersion.Two; + globals.environmentUrls = + (await this.get(v1Keys.environmentUrls)) ?? globals.environmentUrls; + globals.locale = (await this.get(v1Keys.locale)) ?? globals.locale; + globals.noAutoPromptBiometrics = + (await this.get(v1Keys.disableAutoBiometricsPrompt)) ?? + globals.noAutoPromptBiometrics; + globals.noAutoPromptBiometricsText = + (await this.get(v1Keys.noAutoPromptBiometricsText)) ?? + globals.noAutoPromptBiometricsText; + globals.ssoCodeVerifier = + (await this.get(v1Keys.ssoCodeVerifier)) ?? globals.ssoCodeVerifier; + globals.ssoOrganizationIdentifier = + (await this.get(v1Keys.ssoIdentifier)) ?? globals.ssoOrganizationIdentifier; + globals.ssoState = (await this.get(v1Keys.ssoState)) ?? globals.ssoState; + globals.rememberedEmail = + (await this.get(v1Keys.rememberedEmail)) ?? globals.rememberedEmail; + globals.theme = (await this.get(v1Keys.theme)) ?? globals.theme; + globals.vaultTimeout = (await this.get(v1Keys.vaultTimeout)) ?? globals.vaultTimeout; + globals.vaultTimeoutAction = + (await this.get(v1Keys.vaultTimeoutAction)) ?? globals.vaultTimeoutAction; + globals.window = (await this.get(v1Keys.mainWindowSize)) ?? globals.window; + globals.enableTray = (await this.get(v1Keys.enableTray)) ?? globals.enableTray; + globals.enableMinimizeToTray = + (await this.get(v1Keys.enableMinimizeToTray)) ?? globals.enableMinimizeToTray; + globals.enableCloseToTray = + (await this.get(v1Keys.enableCloseToTray)) ?? globals.enableCloseToTray; + globals.enableStartToTray = + (await this.get(v1Keys.enableStartToTray)) ?? globals.enableStartToTray; + globals.openAtLogin = (await this.get(v1Keys.openAtLogin)) ?? globals.openAtLogin; + globals.alwaysShowDock = + (await this.get(v1Keys.alwaysShowDock)) ?? globals.alwaysShowDock; + globals.enableBrowserIntegration = + (await this.get(v1Keys.enableBrowserIntegration)) ?? + globals.enableBrowserIntegration; + globals.enableBrowserIntegrationFingerprint = + (await this.get(v1Keys.enableBrowserIntegrationFingerprint)) ?? + globals.enableBrowserIntegrationFingerprint; + + const userId = + (await this.get(v1Keys.userId)) ?? (await this.get(v1Keys.entityId)); + + const defaultAccount = this.stateFactory.createAccount(null); + const accountSettings: AccountSettings = { + autoConfirmFingerPrints: + (await this.get(v1Keys.autoConfirmFingerprints)) ?? + defaultAccount.settings.autoConfirmFingerPrints, + autoFillOnPageLoadDefault: + (await this.get(v1Keys.autoFillOnPageLoadDefault)) ?? + defaultAccount.settings.autoFillOnPageLoadDefault, + biometricLocked: null, + biometricUnlock: + (await this.get(v1Keys.biometricUnlock)) ?? + defaultAccount.settings.biometricUnlock, + clearClipboard: + (await this.get(v1Keys.clearClipboard)) ?? defaultAccount.settings.clearClipboard, + defaultUriMatch: + (await this.get(v1Keys.defaultUriMatch)) ?? defaultAccount.settings.defaultUriMatch, + disableAddLoginNotification: + (await this.get(v1Keys.disableAddLoginNotification)) ?? + defaultAccount.settings.disableAddLoginNotification, + disableAutoBiometricsPrompt: + (await this.get(v1Keys.disableAutoBiometricsPrompt)) ?? + defaultAccount.settings.disableAutoBiometricsPrompt, + disableAutoTotpCopy: + (await this.get(v1Keys.disableAutoTotpCopy)) ?? + defaultAccount.settings.disableAutoTotpCopy, + disableBadgeCounter: + (await this.get(v1Keys.disableBadgeCounter)) ?? + defaultAccount.settings.disableBadgeCounter, + disableChangedPasswordNotification: + (await this.get(v1Keys.disableChangedPasswordNotification)) ?? + defaultAccount.settings.disableChangedPasswordNotification, + disableContextMenuItem: + (await this.get(v1Keys.disableContextMenuItem)) ?? + defaultAccount.settings.disableContextMenuItem, + disableGa: (await this.get(v1Keys.disableGa)) ?? defaultAccount.settings.disableGa, + dontShowCardsCurrentTab: + (await this.get(v1Keys.dontShowCardsCurrentTab)) ?? + defaultAccount.settings.dontShowCardsCurrentTab, + dontShowIdentitiesCurrentTab: + (await this.get(v1Keys.dontShowIdentitiesCurrentTab)) ?? + defaultAccount.settings.dontShowIdentitiesCurrentTab, + enableAlwaysOnTop: + (await this.get(v1Keys.enableAlwaysOnTop)) ?? + defaultAccount.settings.enableAlwaysOnTop, + enableAutoFillOnPageLoad: + (await this.get(v1Keys.enableAutoFillOnPageLoad)) ?? + defaultAccount.settings.enableAutoFillOnPageLoad, + enableBiometric: + (await this.get(v1Keys.enableBiometric)) ?? + defaultAccount.settings.enableBiometric, + enableFullWidth: + (await this.get(v1Keys.enableFullWidth)) ?? + defaultAccount.settings.enableFullWidth, + enableGravitars: + (await this.get(v1Keys.enableGravatars)) ?? + defaultAccount.settings.enableGravitars, + environmentUrls: globals.environmentUrls ?? defaultAccount.settings.environmentUrls, + equivalentDomains: + (await this.get(v1Keys.equivalentDomains)) ?? + defaultAccount.settings.equivalentDomains, + minimizeOnCopyToClipboard: + (await this.get(v1Keys.minimizeOnCopyToClipboard)) ?? + defaultAccount.settings.minimizeOnCopyToClipboard, + neverDomains: + (await this.get(v1Keys.neverDomains)) ?? defaultAccount.settings.neverDomains, + passwordGenerationOptions: + (await this.get(v1Keys.passwordGenerationOptions)) ?? + defaultAccount.settings.passwordGenerationOptions, + pinProtected: { + decrypted: null, + encrypted: await this.get(v1Keys.pinProtected), + }, + protectedPin: await this.get(v1Keys.protectedPin), + settings: userId == null ? null : await this.get(v1KeyPrefixes.settings + userId), + vaultTimeout: + (await this.get(v1Keys.vaultTimeout)) ?? defaultAccount.settings.vaultTimeout, + vaultTimeoutAction: + (await this.get(v1Keys.vaultTimeoutAction)) ?? + defaultAccount.settings.vaultTimeoutAction, + }; + + // (userId == null) = no logged in user (so no known userId) and we need to temporarily store account specific settings in state to migrate on first auth + // (userId != null) = we have a currently authed user (so known userId) with encrypted data and other key settings we can move, no need to temporarily store account settings + if (userId == null) { + await this.set(keys.tempAccountSettings, accountSettings); + await this.set(keys.global, globals); + await this.set(keys.authenticatedAccounts, []); + await this.set(keys.activeUserId, null); + await clearV1Keys(); + return; + } + + globals.twoFactorToken = await this.get(v1KeyPrefixes.twoFactorToken + userId); + await this.set(keys.global, globals); + await this.set(userId, { + data: { + addEditCipherInfo: null, + ciphers: { + decrypted: null, + encrypted: await this.get<{ [id: string]: CipherData }>(v1KeyPrefixes.ciphers + userId), + }, + collapsedGroupings: null, + collections: { + decrypted: null, + encrypted: await this.get<{ [id: string]: CollectionData }>( + v1KeyPrefixes.collections + userId + ), + }, + eventCollection: await this.get(v1Keys.eventCollection), + folders: { + decrypted: null, + encrypted: await this.get<{ [id: string]: FolderData }>(v1KeyPrefixes.folders + userId), + }, + localData: null, + organizations: await this.get<{ [id: string]: OrganizationData }>( + v1KeyPrefixes.organizations + userId + ), + passwordGenerationHistory: { + decrypted: null, + encrypted: await this.get(v1Keys.history), + }, + policies: { + decrypted: null, + encrypted: await this.get<{ [id: string]: PolicyData }>(v1KeyPrefixes.policies + userId), + }, + providers: await this.get<{ [id: string]: ProviderData }>(v1KeyPrefixes.providers + userId), + sends: { + decrypted: null, + encrypted: await this.get<{ [id: string]: SendData }>(v1KeyPrefixes.sends + userId), + }, + }, + keys: { + apiKeyClientSecret: await this.get(v1Keys.clientSecret), + cryptoMasterKey: null, + cryptoMasterKeyAuto: null, + cryptoMasterKeyB64: null, + cryptoMasterKeyBiometric: null, + cryptoSymmetricKey: { + encrypted: await this.get(v1Keys.encKey), + decrypted: null, + }, + legacyEtmKey: null, + organizationKeys: { + decrypted: null, + encrypted: await this.get(v1Keys.encOrgKeys), + }, + privateKey: { + decrypted: null, + encrypted: await this.get(v1Keys.encPrivate), + }, + providerKeys: { + decrypted: null, + encrypted: await this.get(v1Keys.encProviderKeys), + }, + publicKey: null, + }, + profile: { + apiKeyClientId: await this.get(v1Keys.clientId), + authenticationStatus: null, + convertAccountToKeyConnector: await this.get(v1Keys.convertAccountToKeyConnector), + email: await this.get(v1Keys.userEmail), + emailVerified: await this.get(v1Keys.emailVerified), + entityId: null, + entityType: null, + everBeenUnlocked: null, + forcePasswordReset: null, + hasPremiumPersonally: null, + kdfIterations: await this.get(v1Keys.kdfIterations), + kdfType: await this.get(v1Keys.kdf), + keyHash: await this.get(v1Keys.keyHash), + lastSync: null, + userId: userId, + usesKeyConnector: null, + }, + settings: accountSettings, + tokens: { + accessToken: await this.get(v1Keys.accessToken), + decodedToken: null, + refreshToken: await this.get(v1Keys.refreshToken), + securityStamp: null, + }, + }); + + await this.set(keys.authenticatedAccounts, [userId]); + await this.set(keys.activeUserId, userId); + + const accountActivity: { [userId: string]: number } = { + [userId]: await this.get(v1Keys.lastActive), + }; + accountActivity[userId] = await this.get(v1Keys.lastActive); + await this.set(keys.accountActivity, accountActivity); + + await clearV1Keys(userId); + + if (await this.secureStorageService.has(v1Keys.key, { keySuffix: "biometric" })) { + await this.secureStorageService.save( + `${userId}${partialKeys.biometricKey}`, + await this.secureStorageService.get(v1Keys.key, { keySuffix: "biometric" }), + { keySuffix: "biometric" } + ); + await this.secureStorageService.remove(v1Keys.key, { keySuffix: "biometric" }); + } + + if (await this.secureStorageService.has(v1Keys.key, { keySuffix: "auto" })) { + await this.secureStorageService.save( + `${userId}${partialKeys.autoKey}`, + await this.secureStorageService.get(v1Keys.key, { keySuffix: "auto" }), + { keySuffix: "auto" } + ); + await this.secureStorageService.remove(v1Keys.key, { keySuffix: "auto" }); + } + + if (await this.secureStorageService.has(v1Keys.key)) { + await this.secureStorageService.save( + `${userId}${partialKeys.masterKey}`, + await this.secureStorageService.get(v1Keys.key) + ); + await this.secureStorageService.remove(v1Keys.key); + } + } + + protected async migrateStateFrom2To3(): Promise { + const authenticatedUserIds = await this.get(keys.authenticatedAccounts); + await Promise.all( + authenticatedUserIds.map(async (userId) => { + const account = await this.get(userId); + if ( + account?.profile?.hasPremiumPersonally === null && + account.tokens?.accessToken != null + ) { + const decodedToken = await TokenService.decodeToken(account.tokens.accessToken); + account.profile.hasPremiumPersonally = decodedToken.premium; + await this.set(userId, account); + } + }) + ); + + const globals = await this.getGlobals(); + globals.stateVersion = StateVersion.Three; + await this.set(keys.global, globals); + } + + protected async migrateStateFrom3To4(): Promise { + const authenticatedUserIds = await this.get(keys.authenticatedAccounts); + await Promise.all( + authenticatedUserIds.map(async (userId) => { + const account = await this.get(userId); + if (account?.profile?.everBeenUnlocked != null) { + delete account.profile.everBeenUnlocked; + return this.set(userId, account); + } + }) + ); + + const globals = await this.getGlobals(); + globals.stateVersion = StateVersion.Four; + await this.set(keys.global, globals); + } + + protected get options(): StorageOptions { + return { htmlStorageLocation: HtmlStorageLocation.Local }; + } + + protected get(key: string): Promise { + return this.storageService.get(key, this.options); + } + + protected set(key: string, value: any): Promise { + if (value == null) { + return this.storageService.remove(key, this.options); + } + return this.storageService.save(key, value, this.options); + } + + protected async getGlobals(): Promise { + return await this.get(keys.global); + } + + protected async getCurrentStateVersion(): Promise { + return (await this.getGlobals())?.stateVersion ?? StateVersion.One; + } +} diff --git a/libs/common/src/services/sync.service.ts b/libs/common/src/services/sync.service.ts new file mode 100644 index 0000000000..14a2ed5d2d --- /dev/null +++ b/libs/common/src/services/sync.service.ts @@ -0,0 +1,397 @@ +import { ApiService } from "../abstractions/api.service"; +import { CipherService } from "../abstractions/cipher.service"; +import { CollectionService } from "../abstractions/collection.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { FolderService } from "../abstractions/folder.service"; +import { KeyConnectorService } from "../abstractions/keyConnector.service"; +import { LogService } from "../abstractions/log.service"; +import { MessagingService } from "../abstractions/messaging.service"; +import { OrganizationService } from "../abstractions/organization.service"; +import { PolicyService } from "../abstractions/policy.service"; +import { ProviderService } from "../abstractions/provider.service"; +import { SendService } from "../abstractions/send.service"; +import { SettingsService } from "../abstractions/settings.service"; +import { StateService } from "../abstractions/state.service"; +import { SyncService as SyncServiceAbstraction } from "../abstractions/sync.service"; +import { sequentialize } from "../misc/sequentialize"; +import { CipherData } from "../models/data/cipherData"; +import { CollectionData } from "../models/data/collectionData"; +import { FolderData } from "../models/data/folderData"; +import { OrganizationData } from "../models/data/organizationData"; +import { PolicyData } from "../models/data/policyData"; +import { ProviderData } from "../models/data/providerData"; +import { SendData } from "../models/data/sendData"; +import { CipherResponse } from "../models/response/cipherResponse"; +import { CollectionDetailsResponse } from "../models/response/collectionResponse"; +import { DomainsResponse } from "../models/response/domainsResponse"; +import { FolderResponse } from "../models/response/folderResponse"; +import { + SyncCipherNotification, + SyncFolderNotification, + SyncSendNotification, +} from "../models/response/notificationResponse"; +import { PolicyResponse } from "../models/response/policyResponse"; +import { ProfileResponse } from "../models/response/profileResponse"; +import { SendResponse } from "../models/response/sendResponse"; + +export class SyncService implements SyncServiceAbstraction { + syncInProgress = false; + + constructor( + private apiService: ApiService, + private settingsService: SettingsService, + private folderService: FolderService, + private cipherService: CipherService, + private cryptoService: CryptoService, + private collectionService: CollectionService, + private messagingService: MessagingService, + private policyService: PolicyService, + private sendService: SendService, + private logService: LogService, + private keyConnectorService: KeyConnectorService, + private stateService: StateService, + private organizationService: OrganizationService, + private providerService: ProviderService, + private logoutCallback: (expired: boolean) => Promise + ) {} + + async getLastSync(): Promise { + if ((await this.stateService.getUserId()) == null) { + return null; + } + + const lastSync = await this.stateService.getLastSync(); + if (lastSync) { + return new Date(lastSync); + } + + return null; + } + + async setLastSync(date: Date, userId?: string): Promise { + await this.stateService.setLastSync(date.toJSON(), { userId: userId }); + } + + @sequentialize(() => "fullSync") + async fullSync(forceSync: boolean, allowThrowOnError = false): Promise { + this.syncStarted(); + const isAuthenticated = await this.stateService.getIsAuthenticated(); + if (!isAuthenticated) { + return this.syncCompleted(false); + } + + const now = new Date(); + let needsSync = false; + try { + needsSync = await this.needsSyncing(forceSync); + } catch (e) { + if (allowThrowOnError) { + throw e; + } + } + + if (!needsSync) { + await this.setLastSync(now); + return this.syncCompleted(false); + } + + try { + await this.apiService.refreshIdentityToken(); + const response = await this.apiService.getSync(); + + await this.syncProfile(response.profile); + await this.syncFolders(response.folders); + await this.syncCollections(response.collections); + await this.syncCiphers(response.ciphers); + await this.syncSends(response.sends); + await this.syncSettings(response.domains); + await this.syncPolicies(response.policies); + + await this.setLastSync(now); + return this.syncCompleted(true); + } catch (e) { + if (allowThrowOnError) { + throw e; + } else { + return this.syncCompleted(false); + } + } + } + + async syncUpsertFolder(notification: SyncFolderNotification, isEdit: boolean): Promise { + this.syncStarted(); + if (await this.stateService.getIsAuthenticated()) { + try { + const localFolder = await this.folderService.get(notification.id); + if ( + (!isEdit && localFolder == null) || + (isEdit && localFolder != null && localFolder.revisionDate < notification.revisionDate) + ) { + const remoteFolder = await this.apiService.getFolder(notification.id); + if (remoteFolder != null) { + await this.folderService.upsert(new FolderData(remoteFolder)); + this.messagingService.send("syncedUpsertedFolder", { folderId: notification.id }); + return this.syncCompleted(true); + } + } + } catch (e) { + this.logService.error(e); + } + } + return this.syncCompleted(false); + } + + async syncDeleteFolder(notification: SyncFolderNotification): Promise { + this.syncStarted(); + if (await this.stateService.getIsAuthenticated()) { + await this.folderService.delete(notification.id); + this.messagingService.send("syncedDeletedFolder", { folderId: notification.id }); + this.syncCompleted(true); + return true; + } + return this.syncCompleted(false); + } + + async syncUpsertCipher(notification: SyncCipherNotification, isEdit: boolean): Promise { + this.syncStarted(); + if (await this.stateService.getIsAuthenticated()) { + try { + let shouldUpdate = true; + const localCipher = await this.cipherService.get(notification.id); + if (localCipher != null && localCipher.revisionDate >= notification.revisionDate) { + shouldUpdate = false; + } + + let checkCollections = false; + if (shouldUpdate) { + if (isEdit) { + shouldUpdate = localCipher != null; + checkCollections = true; + } else { + if (notification.collectionIds == null || notification.organizationId == null) { + shouldUpdate = localCipher == null; + } else { + shouldUpdate = false; + checkCollections = true; + } + } + } + + if ( + !shouldUpdate && + checkCollections && + notification.organizationId != null && + notification.collectionIds != null && + notification.collectionIds.length > 0 + ) { + const collections = await this.collectionService.getAll(); + if (collections != null) { + for (let i = 0; i < collections.length; i++) { + if (notification.collectionIds.indexOf(collections[i].id) > -1) { + shouldUpdate = true; + break; + } + } + } + } + + if (shouldUpdate) { + const remoteCipher = await this.apiService.getCipher(notification.id); + if (remoteCipher != null) { + await this.cipherService.upsert(new CipherData(remoteCipher)); + this.messagingService.send("syncedUpsertedCipher", { cipherId: notification.id }); + return this.syncCompleted(true); + } + } + } catch (e) { + if (e != null && e.statusCode === 404 && isEdit) { + await this.cipherService.delete(notification.id); + this.messagingService.send("syncedDeletedCipher", { cipherId: notification.id }); + return this.syncCompleted(true); + } + } + } + return this.syncCompleted(false); + } + + async syncDeleteCipher(notification: SyncCipherNotification): Promise { + this.syncStarted(); + if (await this.stateService.getIsAuthenticated()) { + await this.cipherService.delete(notification.id); + this.messagingService.send("syncedDeletedCipher", { cipherId: notification.id }); + return this.syncCompleted(true); + } + return this.syncCompleted(false); + } + + async syncUpsertSend(notification: SyncSendNotification, isEdit: boolean): Promise { + this.syncStarted(); + if (await this.stateService.getIsAuthenticated()) { + try { + const localSend = await this.sendService.get(notification.id); + if ( + (!isEdit && localSend == null) || + (isEdit && localSend != null && localSend.revisionDate < notification.revisionDate) + ) { + const remoteSend = await this.apiService.getSend(notification.id); + if (remoteSend != null) { + await this.sendService.upsert(new SendData(remoteSend)); + this.messagingService.send("syncedUpsertedSend", { sendId: notification.id }); + return this.syncCompleted(true); + } + } + } catch (e) { + this.logService.error(e); + } + } + return this.syncCompleted(false); + } + + async syncDeleteSend(notification: SyncSendNotification): Promise { + this.syncStarted(); + if (await this.stateService.getIsAuthenticated()) { + await this.sendService.delete(notification.id); + this.messagingService.send("syncedDeletedSend", { sendId: notification.id }); + this.syncCompleted(true); + return true; + } + return this.syncCompleted(false); + } + + // Helpers + + private syncStarted() { + this.syncInProgress = true; + this.messagingService.send("syncStarted"); + } + + private syncCompleted(successfully: boolean): boolean { + this.syncInProgress = false; + this.messagingService.send("syncCompleted", { successfully: successfully }); + return successfully; + } + + private async needsSyncing(forceSync: boolean) { + if (forceSync) { + return true; + } + + const lastSync = await this.getLastSync(); + if (lastSync == null || lastSync.getTime() === 0) { + return true; + } + + const response = await this.apiService.getAccountRevisionDate(); + if (new Date(response) <= lastSync) { + return false; + } + return true; + } + + private async syncProfile(response: ProfileResponse) { + const stamp = await this.stateService.getSecurityStamp(); + if (stamp != null && stamp !== response.securityStamp) { + if (this.logoutCallback != null) { + await this.logoutCallback(true); + } + + throw new Error("Stamp has changed"); + } + + await this.cryptoService.setEncKey(response.key); + await this.cryptoService.setEncPrivateKey(response.privateKey); + await this.cryptoService.setProviderKeys(response.providers); + await this.cryptoService.setOrgKeys(response.organizations, response.providerOrganizations); + await this.stateService.setSecurityStamp(response.securityStamp); + await this.stateService.setEmailVerified(response.emailVerified); + await this.stateService.setCanAccessPremium(response.premium); + await this.stateService.setForcePasswordReset(response.forcePasswordReset); + await this.keyConnectorService.setUsesKeyConnector(response.usesKeyConnector); + + const organizations: { [id: string]: OrganizationData } = {}; + response.organizations.forEach((o) => { + organizations[o.id] = new OrganizationData(o); + }); + + const providers: { [id: string]: ProviderData } = {}; + response.providers.forEach((p) => { + providers[p.id] = new ProviderData(p); + }); + + response.providerOrganizations.forEach((o) => { + if (organizations[o.id] == null) { + organizations[o.id] = new OrganizationData(o); + organizations[o.id].isProviderUser = true; + } + }); + + await this.organizationService.save(organizations); + await this.providerService.save(providers); + + if (await this.keyConnectorService.userNeedsMigration()) { + await this.keyConnectorService.setConvertAccountRequired(true); + this.messagingService.send("convertAccountToKeyConnector"); + } else { + this.keyConnectorService.removeConvertAccountRequired(); + } + } + + private async syncFolders(response: FolderResponse[]) { + const folders: { [id: string]: FolderData } = {}; + response.forEach((f) => { + folders[f.id] = new FolderData(f); + }); + return await this.folderService.replace(folders); + } + + private async syncCollections(response: CollectionDetailsResponse[]) { + const collections: { [id: string]: CollectionData } = {}; + response.forEach((c) => { + collections[c.id] = new CollectionData(c); + }); + return await this.collectionService.replace(collections); + } + + private async syncCiphers(response: CipherResponse[]) { + const ciphers: { [id: string]: CipherData } = {}; + response.forEach((c) => { + ciphers[c.id] = new CipherData(c); + }); + return await this.cipherService.replace(ciphers); + } + + private async syncSends(response: SendResponse[]) { + const sends: { [id: string]: SendData } = {}; + response.forEach((s) => { + sends[s.id] = new SendData(s); + }); + return await this.sendService.replace(sends); + } + + private async syncSettings(response: DomainsResponse) { + let eqDomains: string[][] = []; + if (response != null && response.equivalentDomains != null) { + eqDomains = eqDomains.concat(response.equivalentDomains); + } + + if (response != null && response.globalEquivalentDomains != null) { + response.globalEquivalentDomains.forEach((global) => { + if (global.domains.length > 0) { + eqDomains.push(global.domains); + } + }); + } + + return this.settingsService.setEquivalentDomains(eqDomains); + } + + private async syncPolicies(response: PolicyResponse[]) { + const policies: { [id: string]: PolicyData } = {}; + if (response != null) { + response.forEach((p) => { + policies[p.id] = new PolicyData(p); + }); + } + return await this.policyService.replace(policies); + } +} diff --git a/libs/common/src/services/system.service.ts b/libs/common/src/services/system.service.ts new file mode 100644 index 0000000000..949b8ca40e --- /dev/null +++ b/libs/common/src/services/system.service.ts @@ -0,0 +1,90 @@ +import { MessagingService } from "../abstractions/messaging.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; +import { StateService } from "../abstractions/state.service"; +import { SystemService as SystemServiceAbstraction } from "../abstractions/system.service"; +import { Utils } from "../misc/utils"; + +export class SystemService implements SystemServiceAbstraction { + private reloadInterval: any = null; + private clearClipboardTimeout: any = null; + private clearClipboardTimeoutFunction: () => Promise = null; + + constructor( + private messagingService: MessagingService, + private platformUtilsService: PlatformUtilsService, + private reloadCallback: () => Promise = null, + private stateService: StateService + ) {} + + async startProcessReload(): Promise { + if ( + (await this.stateService.getDecryptedPinProtected()) != null || + (await this.stateService.getBiometricLocked()) || + this.reloadInterval != null + ) { + return; + } + this.cancelProcessReload(); + this.reloadInterval = setInterval(async () => { + let doRefresh = false; + const lastActive = await this.stateService.getLastActive(); + if (lastActive != null) { + const diffSeconds = new Date().getTime() - lastActive; + // Don't refresh if they are still active in the window + doRefresh = diffSeconds >= 5000; + } + const biometricLockedFingerprintValidated = + (await this.stateService.getBiometricFingerprintValidated()) && + (await this.stateService.getBiometricLocked()); + if (doRefresh && !biometricLockedFingerprintValidated) { + clearInterval(this.reloadInterval); + this.reloadInterval = null; + this.messagingService.send("reloadProcess"); + if (this.reloadCallback != null) { + await this.reloadCallback(); + } + } + }, 10000); + } + + cancelProcessReload(): void { + if (this.reloadInterval != null) { + clearInterval(this.reloadInterval); + this.reloadInterval = null; + } + } + + async clearClipboard(clipboardValue: string, timeoutMs: number = null): Promise { + if (this.clearClipboardTimeout != null) { + clearTimeout(this.clearClipboardTimeout); + this.clearClipboardTimeout = null; + } + if (Utils.isNullOrWhitespace(clipboardValue)) { + return; + } + await this.stateService.getClearClipboard().then((clearSeconds) => { + if (clearSeconds == null) { + return; + } + if (timeoutMs == null) { + timeoutMs = clearSeconds * 1000; + } + this.clearClipboardTimeoutFunction = async () => { + const clipboardValueNow = await this.platformUtilsService.readFromClipboard(); + if (clipboardValue === clipboardValueNow) { + this.platformUtilsService.copyToClipboard("", { clearing: true }); + } + }; + this.clearClipboardTimeout = setTimeout(async () => { + await this.clearPendingClipboard(); + }, timeoutMs); + }); + } + + async clearPendingClipboard() { + if (this.clearClipboardTimeoutFunction != null) { + await this.clearClipboardTimeoutFunction(); + this.clearClipboardTimeoutFunction = null; + } + } +} diff --git a/libs/common/src/services/token.service.ts b/libs/common/src/services/token.service.ts new file mode 100644 index 0000000000..a47cca7c38 --- /dev/null +++ b/libs/common/src/services/token.service.ts @@ -0,0 +1,195 @@ +import { StateService } from "../abstractions/state.service"; +import { TokenService as TokenServiceAbstraction } from "../abstractions/token.service"; +import { Utils } from "../misc/utils"; +import { IdentityTokenResponse } from "../models/response/identityTokenResponse"; + +export class TokenService implements TokenServiceAbstraction { + static decodeToken(token: string): Promise { + if (token == null) { + throw new Error("Token not provided."); + } + + const parts = token.split("."); + if (parts.length !== 3) { + throw new Error("JWT must have 3 parts"); + } + + const decoded = Utils.fromUrlB64ToUtf8(parts[1]); + if (decoded == null) { + throw new Error("Cannot decode the token"); + } + + const decodedToken = JSON.parse(decoded); + return decodedToken; + } + + constructor(private stateService: StateService) {} + + async setTokens( + accessToken: string, + refreshToken: string, + clientIdClientSecret: [string, string] + ): Promise { + await this.setToken(accessToken); + await this.setRefreshToken(refreshToken); + if (clientIdClientSecret != null) { + await this.setClientId(clientIdClientSecret[0]); + await this.setClientSecret(clientIdClientSecret[1]); + } + } + + async setClientId(clientId: string): Promise { + return await this.stateService.setApiKeyClientId(clientId); + } + + async getClientId(): Promise { + return await this.stateService.getApiKeyClientId(); + } + + async setClientSecret(clientSecret: string): Promise { + return await this.stateService.setApiKeyClientSecret(clientSecret); + } + + async getClientSecret(): Promise { + return await this.stateService.getApiKeyClientSecret(); + } + + async setToken(token: string): Promise { + await this.stateService.setAccessToken(token); + } + + async getToken(): Promise { + return await this.stateService.getAccessToken(); + } + + async setRefreshToken(refreshToken: string): Promise { + return await this.stateService.setRefreshToken(refreshToken); + } + + async getRefreshToken(): Promise { + return await this.stateService.getRefreshToken(); + } + + async setTwoFactorToken(tokenResponse: IdentityTokenResponse): Promise { + return await this.stateService.setTwoFactorToken(tokenResponse.twoFactorToken); + } + + async getTwoFactorToken(): Promise { + return await this.stateService.getTwoFactorToken(); + } + + async clearTwoFactorToken(): Promise { + return await this.stateService.setTwoFactorToken(null); + } + + async clearToken(userId?: string): Promise { + await this.stateService.setAccessToken(null, { userId: userId }); + await this.stateService.setRefreshToken(null, { userId: userId }); + await this.stateService.setApiKeyClientId(null, { userId: userId }); + await this.stateService.setApiKeyClientSecret(null, { userId: userId }); + } + + // jwthelper methods + // ref https://github.com/auth0/angular-jwt/blob/master/src/angularJwt/services/jwt.js + + async decodeToken(token?: string): Promise { + const storedToken = await this.stateService.getDecodedToken(); + if (token === null && storedToken != null) { + return storedToken; + } + + token = token ?? (await this.stateService.getAccessToken()); + + if (token == null) { + throw new Error("Token not found."); + } + + return TokenService.decodeToken(token); + } + + async getTokenExpirationDate(): Promise { + const decoded = await this.decodeToken(); + if (typeof decoded.exp === "undefined") { + return null; + } + + const d = new Date(0); // The 0 here is the key, which sets the date to the epoch + d.setUTCSeconds(decoded.exp); + return d; + } + + async tokenSecondsRemaining(offsetSeconds = 0): Promise { + const d = await this.getTokenExpirationDate(); + if (d == null) { + return 0; + } + + const msRemaining = d.valueOf() - (new Date().valueOf() + offsetSeconds * 1000); + return Math.round(msRemaining / 1000); + } + + async tokenNeedsRefresh(minutes = 5): Promise { + const sRemaining = await this.tokenSecondsRemaining(); + return sRemaining < 60 * minutes; + } + + async getUserId(): Promise { + const decoded = await this.decodeToken(); + if (typeof decoded.sub === "undefined") { + throw new Error("No user id found"); + } + + return decoded.sub as string; + } + + async getEmail(): Promise { + const decoded = await this.decodeToken(); + if (typeof decoded.email === "undefined") { + throw new Error("No email found"); + } + + return decoded.email as string; + } + + async getEmailVerified(): Promise { + const decoded = await this.decodeToken(); + if (typeof decoded.email_verified === "undefined") { + throw new Error("No email verification found"); + } + + return decoded.email_verified as boolean; + } + + async getName(): Promise { + const decoded = await this.decodeToken(); + if (typeof decoded.name === "undefined") { + return null; + } + + return decoded.name as string; + } + + async getPremium(): Promise { + const decoded = await this.decodeToken(); + if (typeof decoded.premium === "undefined") { + return false; + } + + return decoded.premium as boolean; + } + + async getIssuer(): Promise { + const decoded = await this.decodeToken(); + if (typeof decoded.iss === "undefined") { + throw new Error("No issuer found"); + } + + return decoded.iss as string; + } + + async getIsExternal(): Promise { + const decoded = await this.decodeToken(); + + return Array.isArray(decoded.amr) && decoded.amr.includes("external"); + } +} diff --git a/libs/common/src/services/totp.service.ts b/libs/common/src/services/totp.service.ts new file mode 100644 index 0000000000..730587c77f --- /dev/null +++ b/libs/common/src/services/totp.service.ts @@ -0,0 +1,174 @@ +import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; +import { LogService } from "../abstractions/log.service"; +import { StateService } from "../abstractions/state.service"; +import { TotpService as TotpServiceAbstraction } from "../abstractions/totp.service"; +import { Utils } from "../misc/utils"; + +const B32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; +const SteamChars = "23456789BCDFGHJKMNPQRTVWXY"; + +export class TotpService implements TotpServiceAbstraction { + constructor( + private cryptoFunctionService: CryptoFunctionService, + private logService: LogService, + private stateService: StateService + ) {} + + async getCode(key: string): Promise { + if (key == null) { + return null; + } + let period = 30; + let alg: "sha1" | "sha256" | "sha512" = "sha1"; + let digits = 6; + let keyB32 = key; + const isOtpAuth = key.toLowerCase().indexOf("otpauth://") === 0; + const isSteamAuth = !isOtpAuth && key.toLowerCase().indexOf("steam://") === 0; + if (isOtpAuth) { + const params = Utils.getQueryParams(key); + if (params.has("digits") && params.get("digits") != null) { + try { + const digitParams = parseInt(params.get("digits").trim(), null); + if (digitParams > 10) { + digits = 10; + } else if (digitParams > 0) { + digits = digitParams; + } + } catch { + this.logService.error("Invalid digits param."); + } + } + if (params.has("period") && params.get("period") != null) { + try { + const periodParam = parseInt(params.get("period").trim(), null); + if (periodParam > 0) { + period = periodParam; + } + } catch { + this.logService.error("Invalid period param."); + } + } + if (params.has("secret") && params.get("secret") != null) { + keyB32 = params.get("secret"); + } + if (params.has("algorithm") && params.get("algorithm") != null) { + const algParam = params.get("algorithm").toLowerCase(); + if (algParam === "sha1" || algParam === "sha256" || algParam === "sha512") { + alg = algParam; + } + } + } else if (isSteamAuth) { + keyB32 = key.substr("steam://".length); + digits = 5; + } + + const epoch = Math.round(new Date().getTime() / 1000.0); + const timeHex = this.leftPad(this.decToHex(Math.floor(epoch / period)), 16, "0"); + const timeBytes = Utils.fromHexToArray(timeHex); + const keyBytes = this.b32ToBytes(keyB32); + + if (!keyBytes.length || !timeBytes.length) { + return null; + } + + const hash = await this.sign(keyBytes, timeBytes, alg); + if (hash.length === 0) { + return null; + } + + const offset = hash[hash.length - 1] & 0xf; + const binary = + ((hash[offset] & 0x7f) << 24) | + ((hash[offset + 1] & 0xff) << 16) | + ((hash[offset + 2] & 0xff) << 8) | + (hash[offset + 3] & 0xff); + + let otp = ""; + if (isSteamAuth) { + let fullCode = binary & 0x7fffffff; + for (let i = 0; i < digits; i++) { + otp += SteamChars[fullCode % SteamChars.length]; + fullCode = Math.trunc(fullCode / SteamChars.length); + } + } else { + otp = (binary % Math.pow(10, digits)).toString(); + otp = this.leftPad(otp, digits, "0"); + } + + return otp; + } + + getTimeInterval(key: string): number { + let period = 30; + if (key != null && key.toLowerCase().indexOf("otpauth://") === 0) { + const params = Utils.getQueryParams(key); + if (params.has("period") && params.get("period") != null) { + try { + period = parseInt(params.get("period").trim(), null); + } catch { + this.logService.error("Invalid period param."); + } + } + } + return period; + } + + async isAutoCopyEnabled(): Promise { + return !(await this.stateService.getDisableAutoTotpCopy()); + } + + // Helpers + + private leftPad(s: string, l: number, p: string): string { + if (l + 1 >= s.length) { + s = Array(l + 1 - s.length).join(p) + s; + } + return s; + } + + private decToHex(d: number): string { + return (d < 15.5 ? "0" : "") + Math.round(d).toString(16); + } + + private b32ToHex(s: string): string { + s = s.toUpperCase(); + let cleanedInput = ""; + + for (let i = 0; i < s.length; i++) { + if (B32Chars.indexOf(s[i]) < 0) { + continue; + } + + cleanedInput += s[i]; + } + s = cleanedInput; + + let bits = ""; + let hex = ""; + for (let i = 0; i < s.length; i++) { + const byteIndex = B32Chars.indexOf(s.charAt(i)); + if (byteIndex < 0) { + continue; + } + bits += this.leftPad(byteIndex.toString(2), 5, "0"); + } + for (let i = 0; i + 4 <= bits.length; i += 4) { + const chunk = bits.substr(i, 4); + hex = hex + parseInt(chunk, 2).toString(16); + } + return hex; + } + + private b32ToBytes(s: string): Uint8Array { + return Utils.fromHexToArray(this.b32ToHex(s)); + } + + private async sign( + keyBytes: Uint8Array, + timeBytes: Uint8Array, + alg: "sha1" | "sha256" | "sha512" + ) { + const signature = await this.cryptoFunctionService.hmac(timeBytes.buffer, keyBytes.buffer, alg); + return new Uint8Array(signature); + } +} diff --git a/libs/common/src/services/twoFactor.service.ts b/libs/common/src/services/twoFactor.service.ts new file mode 100644 index 0000000000..7720d9bec9 --- /dev/null +++ b/libs/common/src/services/twoFactor.service.ts @@ -0,0 +1,186 @@ +import { I18nService } from "../abstractions/i18n.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; +import { + TwoFactorProviderDetails, + TwoFactorService as TwoFactorServiceAbstraction, +} from "../abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "../enums/twoFactorProviderType"; +import { IdentityTwoFactorResponse } from "../models/response/identityTwoFactorResponse"; + +export const TwoFactorProviders: Partial> = + { + [TwoFactorProviderType.Authenticator]: { + type: TwoFactorProviderType.Authenticator, + name: null as string, + description: null as string, + priority: 1, + sort: 1, + premium: false, + }, + [TwoFactorProviderType.Yubikey]: { + type: TwoFactorProviderType.Yubikey, + name: null as string, + description: null as string, + priority: 3, + sort: 2, + premium: true, + }, + [TwoFactorProviderType.Duo]: { + type: TwoFactorProviderType.Duo, + name: "Duo", + description: null as string, + priority: 2, + sort: 3, + premium: true, + }, + [TwoFactorProviderType.OrganizationDuo]: { + type: TwoFactorProviderType.OrganizationDuo, + name: "Duo (Organization)", + description: null as string, + priority: 10, + sort: 4, + premium: false, + }, + [TwoFactorProviderType.Email]: { + type: TwoFactorProviderType.Email, + name: null as string, + description: null as string, + priority: 0, + sort: 6, + premium: false, + }, + [TwoFactorProviderType.WebAuthn]: { + type: TwoFactorProviderType.WebAuthn, + name: null as string, + description: null as string, + priority: 4, + sort: 5, + premium: true, + }, + }; + +export class TwoFactorService implements TwoFactorServiceAbstraction { + private twoFactorProvidersData: Map; + private selectedTwoFactorProviderType: TwoFactorProviderType = null; + + constructor( + private i18nService: I18nService, + private platformUtilsService: PlatformUtilsService + ) {} + + init() { + TwoFactorProviders[TwoFactorProviderType.Email].name = this.i18nService.t("emailTitle"); + TwoFactorProviders[TwoFactorProviderType.Email].description = this.i18nService.t("emailDesc"); + + TwoFactorProviders[TwoFactorProviderType.Authenticator].name = + this.i18nService.t("authenticatorAppTitle"); + TwoFactorProviders[TwoFactorProviderType.Authenticator].description = + this.i18nService.t("authenticatorAppDesc"); + + TwoFactorProviders[TwoFactorProviderType.Duo].description = this.i18nService.t("duoDesc"); + + TwoFactorProviders[TwoFactorProviderType.OrganizationDuo].name = + "Duo (" + this.i18nService.t("organization") + ")"; + TwoFactorProviders[TwoFactorProviderType.OrganizationDuo].description = + this.i18nService.t("duoOrganizationDesc"); + + TwoFactorProviders[TwoFactorProviderType.WebAuthn].name = this.i18nService.t("webAuthnTitle"); + TwoFactorProviders[TwoFactorProviderType.WebAuthn].description = + this.i18nService.t("webAuthnDesc"); + + TwoFactorProviders[TwoFactorProviderType.Yubikey].name = this.i18nService.t("yubiKeyTitle"); + TwoFactorProviders[TwoFactorProviderType.Yubikey].description = + this.i18nService.t("yubiKeyDesc"); + } + + getSupportedProviders(win: Window): TwoFactorProviderDetails[] { + const providers: any[] = []; + if (this.twoFactorProvidersData == null) { + return providers; + } + + if ( + this.twoFactorProvidersData.has(TwoFactorProviderType.OrganizationDuo) && + this.platformUtilsService.supportsDuo() + ) { + providers.push(TwoFactorProviders[TwoFactorProviderType.OrganizationDuo]); + } + + if (this.twoFactorProvidersData.has(TwoFactorProviderType.Authenticator)) { + providers.push(TwoFactorProviders[TwoFactorProviderType.Authenticator]); + } + + if (this.twoFactorProvidersData.has(TwoFactorProviderType.Yubikey)) { + providers.push(TwoFactorProviders[TwoFactorProviderType.Yubikey]); + } + + if ( + this.twoFactorProvidersData.has(TwoFactorProviderType.Duo) && + this.platformUtilsService.supportsDuo() + ) { + providers.push(TwoFactorProviders[TwoFactorProviderType.Duo]); + } + + if ( + this.twoFactorProvidersData.has(TwoFactorProviderType.WebAuthn) && + this.platformUtilsService.supportsWebAuthn(win) + ) { + providers.push(TwoFactorProviders[TwoFactorProviderType.WebAuthn]); + } + + if (this.twoFactorProvidersData.has(TwoFactorProviderType.Email)) { + providers.push(TwoFactorProviders[TwoFactorProviderType.Email]); + } + + return providers; + } + + getDefaultProvider(webAuthnSupported: boolean): TwoFactorProviderType { + if (this.twoFactorProvidersData == null) { + return null; + } + + if ( + this.selectedTwoFactorProviderType != null && + this.twoFactorProvidersData.has(this.selectedTwoFactorProviderType) + ) { + return this.selectedTwoFactorProviderType; + } + + let providerType: TwoFactorProviderType = null; + let providerPriority = -1; + this.twoFactorProvidersData.forEach((_value, type) => { + const provider = (TwoFactorProviders as any)[type]; + if (provider != null && provider.priority > providerPriority) { + if (type === TwoFactorProviderType.WebAuthn && !webAuthnSupported) { + return; + } + + providerType = type; + providerPriority = provider.priority; + } + }); + + return providerType; + } + + setSelectedProvider(type: TwoFactorProviderType) { + this.selectedTwoFactorProviderType = type; + } + + clearSelectedProvider() { + this.selectedTwoFactorProviderType = null; + } + + setProviders(response: IdentityTwoFactorResponse) { + this.twoFactorProvidersData = response.twoFactorProviders2; + } + + clearProviders() { + this.twoFactorProvidersData = null; + } + + getProviders() { + return this.twoFactorProvidersData; + } +} diff --git a/libs/common/src/services/userVerification.service.ts b/libs/common/src/services/userVerification.service.ts new file mode 100644 index 0000000000..65207ac0a9 --- /dev/null +++ b/libs/common/src/services/userVerification.service.ts @@ -0,0 +1,88 @@ +import { ApiService } from "../abstractions/api.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { I18nService } from "../abstractions/i18n.service"; +import { UserVerificationService as UserVerificationServiceAbstraction } from "../abstractions/userVerification.service"; +import { VerificationType } from "../enums/verificationType"; +import { VerifyOTPRequest } from "../models/request/account/verifyOTPRequest"; +import { SecretVerificationRequest } from "../models/request/secretVerificationRequest"; +import { Verification } from "../types/verification"; + +/** + * Used for general-purpose user verification throughout the app. + * Use it to verify the input collected by UserVerificationComponent. + */ +export class UserVerificationService implements UserVerificationServiceAbstraction { + constructor( + private cryptoService: CryptoService, + private i18nService: I18nService, + private apiService: ApiService + ) {} + + /** + * Create a new request model to be used for server-side verification + * @param verification User-supplied verification data (Master Password or OTP) + * @param requestClass The request model to create + * @param alreadyHashed Whether the master password is already hashed + */ + async buildRequest( + verification: Verification, + requestClass?: new () => T, + alreadyHashed?: boolean + ) { + this.validateInput(verification); + + const request = + requestClass != null ? new requestClass() : (new SecretVerificationRequest() as T); + + if (verification.type === VerificationType.OTP) { + request.otp = verification.secret; + } else { + request.masterPasswordHash = alreadyHashed + ? verification.secret + : await this.cryptoService.hashPassword(verification.secret, null); + } + + return request; + } + + /** + * Used to verify the Master Password client-side, or send the OTP to the server for verification (with no other data) + * Generally used for client-side verification only. + * @param verification User-supplied verification data (Master Password or OTP) + */ + async verifyUser(verification: Verification): Promise { + this.validateInput(verification); + + if (verification.type === VerificationType.OTP) { + const request = new VerifyOTPRequest(verification.secret); + try { + await this.apiService.postAccountVerifyOTP(request); + } catch (e) { + throw new Error(this.i18nService.t("invalidVerificationCode")); + } + } else { + const passwordValid = await this.cryptoService.compareAndUpdateKeyHash( + verification.secret, + null + ); + if (!passwordValid) { + throw new Error(this.i18nService.t("invalidMasterPassword")); + } + } + return true; + } + + async requestOTP() { + await this.apiService.postAccountRequestOTP(); + } + + private validateInput(verification: Verification) { + if (verification?.secret == null || verification.secret === "") { + if (verification.type === VerificationType.OTP) { + throw new Error(this.i18nService.t("verificationCodeRequired")); + } else { + throw new Error(this.i18nService.t("masterPassRequired")); + } + } + } +} diff --git a/libs/common/src/services/usernameGeneration.service.ts b/libs/common/src/services/usernameGeneration.service.ts new file mode 100644 index 0000000000..cde3365292 --- /dev/null +++ b/libs/common/src/services/usernameGeneration.service.ts @@ -0,0 +1,277 @@ +import { ApiService } from "../abstractions/api.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { StateService } from "../abstractions/state.service"; +import { UsernameGenerationService as BaseUsernameGenerationService } from "../abstractions/usernameGeneration.service"; +import { EEFLongWordList } from "../misc/wordlist"; + +const DefaultOptions = { + type: "word", + wordCapitalize: true, + wordIncludeNumber: true, + subaddressType: "random", + catchallType: "random", + forwardedService: "simplelogin", + forwardedAnonAddyDomain: "anonaddy.me", +}; + +export class UsernameGenerationService implements BaseUsernameGenerationService { + constructor( + private cryptoService: CryptoService, + private stateService: StateService, + private apiService: ApiService + ) {} + + generateUsername(options: any): Promise { + if (options.type === "catchall") { + return this.generateCatchall(options); + } else if (options.type === "subaddress") { + return this.generateSubaddress(options); + } else if (options.type === "forwarded") { + return this.generateForwarded(options); + } else { + return this.generateWord(options); + } + } + + async generateWord(options: any): Promise { + const o = Object.assign({}, DefaultOptions, options); + + if (o.wordCapitalize == null) { + o.wordCapitalize = true; + } + if (o.wordIncludeNumber == null) { + o.wordIncludeNumber = true; + } + + const wordIndex = await this.cryptoService.randomNumber(0, EEFLongWordList.length - 1); + let word = EEFLongWordList[wordIndex]; + if (o.wordCapitalize) { + word = word.charAt(0).toUpperCase() + word.slice(1); + } + if (o.wordIncludeNumber) { + const num = await this.cryptoService.randomNumber(1, 9999); + word = word + this.zeroPad(num.toString(), 4); + } + return word; + } + + async generateSubaddress(options: any): Promise { + const o = Object.assign({}, DefaultOptions, options); + + const subaddressEmail = o.subaddressEmail; + if (subaddressEmail == null || subaddressEmail.length < 3) { + return o.subaddressEmail; + } + const atIndex = subaddressEmail.indexOf("@"); + if (atIndex < 1 || atIndex >= subaddressEmail.length - 1) { + return subaddressEmail; + } + if (o.subaddressType == null) { + o.subaddressType = "random"; + } + + const emailBeginning = subaddressEmail.substr(0, atIndex); + const emailEnding = subaddressEmail.substr(atIndex + 1, subaddressEmail.length); + + let subaddressString = ""; + if (o.subaddressType === "random") { + subaddressString = await this.randomString(8); + } else if (o.subaddressType === "website-name") { + subaddressString = o.website; + } + return emailBeginning + "+" + subaddressString + "@" + emailEnding; + } + + async generateCatchall(options: any): Promise { + const o = Object.assign({}, DefaultOptions, options); + + if (o.catchallDomain == null || o.catchallDomain === "") { + return null; + } + if (o.catchallType == null) { + o.catchallType = "random"; + } + + let startString = ""; + if (o.catchallType === "random") { + startString = await this.randomString(8); + } else if (o.catchallType === "website-name") { + startString = o.website; + } + return startString + "@" + o.catchallDomain; + } + + async generateForwarded(options: any): Promise { + const o = Object.assign({}, DefaultOptions, options); + + if (o.forwardedService == null) { + return null; + } + + if (o.forwardedService === "simplelogin") { + if (o.forwardedSimpleLoginApiKey == null || o.forwardedSimpleLoginApiKey === "") { + return null; + } + return this.generateSimpleLoginAlias(o.forwardedSimpleLoginApiKey, o.website); + } else if (o.forwardedService === "anonaddy") { + if ( + o.forwardedAnonAddyApiToken == null || + o.forwardedAnonAddyApiToken === "" || + o.forwardedAnonAddyDomain == null || + o.forwardedAnonAddyDomain == "" + ) { + return null; + } + return this.generateAnonAddyAlias( + o.forwardedAnonAddyApiToken, + o.forwardedAnonAddyDomain, + o.website + ); + } else if (o.forwardedService === "firefoxrelay") { + if (o.forwardedFirefoxApiToken == null || o.forwardedFirefoxApiToken === "") { + return null; + } + return this.generateFirefoxRelayAlias(o.forwardedFirefoxApiToken, o.website); + } + + return null; + } + + async getOptions(): Promise { + let options = await this.stateService.getUsernameGenerationOptions(); + if (options == null) { + options = Object.assign({}, DefaultOptions); + } else { + options = Object.assign({}, DefaultOptions, options); + } + await this.stateService.setUsernameGenerationOptions(options); + return options; + } + + async saveOptions(options: any) { + await this.stateService.setUsernameGenerationOptions(options); + } + + private async randomString(length: number) { + let str = ""; + const charSet = "abcdefghijklmnopqrstuvwxyz1234567890"; + for (let i = 0; i < length; i++) { + const randomCharIndex = await this.cryptoService.randomNumber(0, charSet.length - 1); + str += charSet.charAt(randomCharIndex); + } + return str; + } + + // ref: https://stackoverflow.com/a/10073788 + private zeroPad(number: string, width: number) { + return number.length >= width + ? number + : new Array(width - number.length + 1).join("0") + number; + } + + private async generateSimpleLoginAlias(apiKey: string, website: string): Promise { + if (apiKey == null || apiKey === "") { + throw "Invalid SimpleLogin API key."; + } + const requestInit: RequestInit = { + redirect: "manual", + cache: "no-store", + method: "POST", + headers: new Headers({ + Authentication: apiKey, + "Content-Type": "application/json", + }), + }; + let url = "https://app.simplelogin.io/api/alias/random/new"; + if (website != null) { + url += "?hostname=" + website; + } + requestInit.body = JSON.stringify({ + note: (website != null ? "Website: " + website + ". " : "") + "Generated by Bitwarden.", + }); + const request = new Request(url, requestInit); + const response = await this.apiService.nativeFetch(request); + if (response.status === 200 || response.status === 201) { + const json = await response.json(); + return json.alias; + } + if (response.status === 401) { + throw "Invalid SimpleLogin API key."; + } + try { + const json = await response.json(); + if (json?.error != null) { + throw "SimpleLogin error:" + json.error; + } + } catch { + // Do nothing... + } + throw "Unknown SimpleLogin error occurred."; + } + + private async generateAnonAddyAlias( + apiToken: string, + domain: string, + websiteNote: string + ): Promise { + if (apiToken == null || apiToken === "") { + throw "Invalid AnonAddy API token."; + } + const requestInit: RequestInit = { + redirect: "manual", + cache: "no-store", + method: "POST", + headers: new Headers({ + Authorization: "Bearer " + apiToken, + "Content-Type": "application/json", + }), + }; + const url = "https://app.anonaddy.com/api/v1/aliases"; + requestInit.body = JSON.stringify({ + domain: domain, + description: + (websiteNote != null ? "Website: " + websiteNote + ". " : "") + "Generated by Bitwarden.", + }); + const request = new Request(url, requestInit); + const response = await this.apiService.nativeFetch(request); + if (response.status === 200 || response.status === 201) { + const json = await response.json(); + return json?.data?.email; + } + if (response.status === 401) { + throw "Invalid AnonAddy API token."; + } + throw "Unknown AnonAddy error occurred."; + } + + private async generateFirefoxRelayAlias(apiToken: string, website: string): Promise { + if (apiToken == null || apiToken === "") { + throw "Invalid Firefox Relay API token."; + } + const requestInit: RequestInit = { + redirect: "manual", + cache: "no-store", + method: "POST", + headers: new Headers({ + Authorization: "Token " + apiToken, + "Content-Type": "application/json", + }), + }; + const url = "https://relay.firefox.com/api/v1/relayaddresses/"; + requestInit.body = JSON.stringify({ + enabled: true, + generated_for: website, + description: (website != null ? website + " - " : "") + "Generated by Bitwarden.", + }); + const request = new Request(url, requestInit); + const response = await this.apiService.nativeFetch(request); + if (response.status === 200 || response.status === 201) { + const json = await response.json(); + return json?.full_address; + } + if (response.status === 401) { + throw "Invalid Firefox Relay API token."; + } + throw "Unknown Firefox Relay error occurred."; + } +} diff --git a/libs/common/src/services/vaultTimeout.service.ts b/libs/common/src/services/vaultTimeout.service.ts new file mode 100644 index 0000000000..935c55d8e6 --- /dev/null +++ b/libs/common/src/services/vaultTimeout.service.ts @@ -0,0 +1,206 @@ +import { AuthService } from "../abstractions/auth.service"; +import { CipherService } from "../abstractions/cipher.service"; +import { CollectionService } from "../abstractions/collection.service"; +import { CryptoService } from "../abstractions/crypto.service"; +import { FolderService } from "../abstractions/folder.service"; +import { KeyConnectorService } from "../abstractions/keyConnector.service"; +import { MessagingService } from "../abstractions/messaging.service"; +import { PlatformUtilsService } from "../abstractions/platformUtils.service"; +import { PolicyService } from "../abstractions/policy.service"; +import { SearchService } from "../abstractions/search.service"; +import { StateService } from "../abstractions/state.service"; +import { TokenService } from "../abstractions/token.service"; +import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "../abstractions/vaultTimeout.service"; +import { AuthenticationStatus } from "../enums/authenticationStatus"; +import { PolicyType } from "../enums/policyType"; + +export class VaultTimeoutService implements VaultTimeoutServiceAbstraction { + private inited = false; + + constructor( + private cipherService: CipherService, + private folderService: FolderService, + private collectionService: CollectionService, + private cryptoService: CryptoService, + protected platformUtilsService: PlatformUtilsService, + private messagingService: MessagingService, + private searchService: SearchService, + private tokenService: TokenService, + private policyService: PolicyService, + private keyConnectorService: KeyConnectorService, + private stateService: StateService, + private authService: AuthService, + private lockedCallback: (userId?: string) => Promise = null, + private loggedOutCallback: (expired: boolean, userId?: string) => Promise = null + ) {} + + init(checkOnInterval: boolean) { + if (this.inited) { + return; + } + + this.inited = true; + if (checkOnInterval) { + this.startCheck(); + } + } + + startCheck() { + this.checkVaultTimeout(); + setInterval(() => this.checkVaultTimeout(), 10 * 1000); // check every 10 seconds + } + + async checkVaultTimeout(): Promise { + if (await this.platformUtilsService.isViewOpen()) { + return; + } + + for (const userId in this.stateService.accounts.getValue()) { + if (userId != null && (await this.shouldLock(userId))) { + await this.executeTimeoutAction(userId); + } + } + } + + async lock(allowSoftLock = false, userId?: string): Promise { + const authed = await this.stateService.getIsAuthenticated({ userId: userId }); + if (!authed) { + return; + } + + if (await this.keyConnectorService.getUsesKeyConnector()) { + const pinSet = await this.isPinLockSet(); + const pinLock = + (pinSet[0] && (await this.stateService.getDecryptedPinProtected()) != null) || pinSet[1]; + + if (!pinLock && !(await this.isBiometricLockSet())) { + await this.logOut(userId); + } + } + + if (userId == null || userId === (await this.stateService.getUserId())) { + this.searchService.clearIndex(); + } + + await this.stateService.setEverBeenUnlocked(true, { userId: userId }); + await this.stateService.setBiometricLocked(true, { userId: userId }); + await this.stateService.setCryptoMasterKeyAuto(null, { userId: userId }); + + await this.cryptoService.clearKey(false, userId); + await this.cryptoService.clearOrgKeys(true, userId); + await this.cryptoService.clearKeyPair(true, userId); + await this.cryptoService.clearEncKey(true, userId); + + await this.folderService.clearCache(userId); + await this.cipherService.clearCache(userId); + await this.collectionService.clearCache(userId); + + this.messagingService.send("locked", { userId: userId }); + + if (this.lockedCallback != null) { + await this.lockedCallback(userId); + } + } + + async logOut(userId?: string): Promise { + if (this.loggedOutCallback != null) { + await this.loggedOutCallback(false, userId); + } + } + + async setVaultTimeoutOptions(timeout: number, action: string): Promise { + await this.stateService.setVaultTimeout(timeout); + + // We swap these tokens from being on disk for lock actions, and in memory for logout actions + // Get them here to set them to their new location after changing the timeout action and clearing if needed + const token = await this.tokenService.getToken(); + const refreshToken = await this.tokenService.getRefreshToken(); + const clientId = await this.tokenService.getClientId(); + const clientSecret = await this.tokenService.getClientSecret(); + + const currentAction = await this.stateService.getVaultTimeoutAction(); + if ((timeout != null || timeout === 0) && action === "logOut" && action !== currentAction) { + // if we have a vault timeout and the action is log out, reset tokens + await this.tokenService.clearToken(); + } + + await this.stateService.setVaultTimeoutAction(action); + + await this.tokenService.setToken(token); + await this.tokenService.setRefreshToken(refreshToken); + await this.tokenService.setClientId(clientId); + await this.tokenService.setClientSecret(clientSecret); + + await this.cryptoService.toggleKey(); + } + + async isPinLockSet(): Promise<[boolean, boolean]> { + const protectedPin = await this.stateService.getProtectedPin(); + const pinProtectedKey = await this.stateService.getEncryptedPinProtected(); + return [protectedPin != null, pinProtectedKey != null]; + } + + async isBiometricLockSet(): Promise { + return await this.stateService.getBiometricUnlock(); + } + + async getVaultTimeout(userId?: string): Promise { + const vaultTimeout = await this.stateService.getVaultTimeout({ userId: userId }); + + if ( + await this.policyService.policyAppliesToUser(PolicyType.MaximumVaultTimeout, null, userId) + ) { + const policy = await this.policyService.getAll(PolicyType.MaximumVaultTimeout, userId); + // Remove negative values, and ensure it's smaller than maximum allowed value according to policy + let timeout = Math.min(vaultTimeout, policy[0].data.minutes); + + if (vaultTimeout == null || timeout < 0) { + timeout = policy[0].data.minutes; + } + + // We really shouldn't need to set the value here, but multiple services relies on this value being correct. + if (vaultTimeout !== timeout) { + await this.stateService.setVaultTimeout(timeout, { userId: userId }); + } + + return timeout; + } + + return vaultTimeout; + } + + async clear(userId?: string): Promise { + await this.stateService.setEverBeenUnlocked(false, { userId: userId }); + await this.stateService.setDecryptedPinProtected(null, { userId: userId }); + await this.stateService.setProtectedPin(null, { userId: userId }); + } + + private async shouldLock(userId: string): Promise { + const authStatus = await this.authService.getAuthStatus(userId); + if ( + authStatus === AuthenticationStatus.Locked || + authStatus === AuthenticationStatus.LoggedOut + ) { + return false; + } + + const vaultTimeout = await this.getVaultTimeout(userId); + if (vaultTimeout == null || vaultTimeout < 0) { + return false; + } + + const lastActive = await this.stateService.getLastActive({ userId: userId }); + if (lastActive == null) { + return false; + } + + const vaultTimeoutSeconds = vaultTimeout * 60; + const diffSeconds = (new Date().getTime() - lastActive) / 1000; + return diffSeconds >= vaultTimeoutSeconds; + } + + private async executeTimeoutAction(userId: string): Promise { + const timeoutAction = await this.stateService.getVaultTimeoutAction({ userId: userId }); + timeoutAction === "logOut" ? await this.logOut(userId) : await this.lock(true, userId); + } +} diff --git a/libs/common/src/services/webCryptoFunction.service.ts b/libs/common/src/services/webCryptoFunction.service.ts new file mode 100644 index 0000000000..b863f2267c --- /dev/null +++ b/libs/common/src/services/webCryptoFunction.service.ts @@ -0,0 +1,356 @@ +import * as forge from "node-forge"; + +import { CryptoFunctionService } from "../abstractions/cryptoFunction.service"; +import { Utils } from "../misc/utils"; +import { DecryptParameters } from "../models/domain/decryptParameters"; +import { SymmetricCryptoKey } from "../models/domain/symmetricCryptoKey"; + +export class WebCryptoFunctionService implements CryptoFunctionService { + private crypto: Crypto; + private subtle: SubtleCrypto; + + constructor(win: Window) { + this.crypto = typeof win.crypto !== "undefined" ? win.crypto : null; + this.subtle = + !!this.crypto && typeof win.crypto.subtle !== "undefined" ? win.crypto.subtle : null; + } + + async pbkdf2( + password: string | ArrayBuffer, + salt: string | ArrayBuffer, + algorithm: "sha256" | "sha512", + iterations: number + ): Promise { + const wcLen = algorithm === "sha256" ? 256 : 512; + const passwordBuf = this.toBuf(password); + const saltBuf = this.toBuf(salt); + + const pbkdf2Params: Pbkdf2Params = { + name: "PBKDF2", + salt: saltBuf, + iterations: iterations, + hash: { name: this.toWebCryptoAlgorithm(algorithm) }, + }; + + const impKey = await this.subtle.importKey( + "raw", + passwordBuf, + { name: "PBKDF2" } as any, + false, + ["deriveBits"] + ); + return await this.subtle.deriveBits(pbkdf2Params, impKey, wcLen); + } + + async hkdf( + ikm: ArrayBuffer, + salt: string | ArrayBuffer, + info: string | ArrayBuffer, + outputByteSize: number, + algorithm: "sha256" | "sha512" + ): Promise { + const saltBuf = this.toBuf(salt); + const infoBuf = this.toBuf(info); + + const hkdfParams: HkdfParams = { + name: "HKDF", + salt: saltBuf, + info: infoBuf, + hash: { name: this.toWebCryptoAlgorithm(algorithm) }, + }; + + const impKey = await this.subtle.importKey("raw", ikm, { name: "HKDF" } as any, false, [ + "deriveBits", + ]); + return await this.subtle.deriveBits(hkdfParams as any, impKey, outputByteSize * 8); + } + + // ref: https://tools.ietf.org/html/rfc5869 + async hkdfExpand( + prk: ArrayBuffer, + info: string | ArrayBuffer, + outputByteSize: number, + algorithm: "sha256" | "sha512" + ): Promise { + const hashLen = algorithm === "sha256" ? 32 : 64; + if (outputByteSize > 255 * hashLen) { + throw new Error("outputByteSize is too large."); + } + const prkArr = new Uint8Array(prk); + if (prkArr.length < hashLen) { + throw new Error("prk is too small."); + } + const infoBuf = this.toBuf(info); + const infoArr = new Uint8Array(infoBuf); + let runningOkmLength = 0; + let previousT = new Uint8Array(0); + const n = Math.ceil(outputByteSize / hashLen); + const okm = new Uint8Array(n * hashLen); + for (let i = 0; i < n; i++) { + const t = new Uint8Array(previousT.length + infoArr.length + 1); + t.set(previousT); + t.set(infoArr, previousT.length); + t.set([i + 1], t.length - 1); + previousT = new Uint8Array(await this.hmac(t.buffer, prk, algorithm)); + okm.set(previousT, runningOkmLength); + runningOkmLength += previousT.length; + if (runningOkmLength >= outputByteSize) { + break; + } + } + return okm.slice(0, outputByteSize).buffer; + } + + async hash( + value: string | ArrayBuffer, + algorithm: "sha1" | "sha256" | "sha512" | "md5" + ): Promise { + if (algorithm === "md5") { + const md = algorithm === "md5" ? forge.md.md5.create() : forge.md.sha1.create(); + const valueBytes = this.toByteString(value); + md.update(valueBytes, "raw"); + return Utils.fromByteStringToArray(md.digest().data).buffer; + } + + const valueBuf = this.toBuf(value); + return await this.subtle.digest({ name: this.toWebCryptoAlgorithm(algorithm) }, valueBuf); + } + + async hmac( + value: ArrayBuffer, + key: ArrayBuffer, + algorithm: "sha1" | "sha256" | "sha512" + ): Promise { + const signingAlgorithm = { + name: "HMAC", + hash: { name: this.toWebCryptoAlgorithm(algorithm) }, + }; + + const impKey = await this.subtle.importKey("raw", key, signingAlgorithm, false, ["sign"]); + return await this.subtle.sign(signingAlgorithm, impKey, value); + } + + // Safely compare two values in a way that protects against timing attacks (Double HMAC Verification). + // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ + // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy + async compare(a: ArrayBuffer, b: ArrayBuffer): Promise { + const macKey = await this.randomBytes(32); + const signingAlgorithm = { + name: "HMAC", + hash: { name: "SHA-256" }, + }; + const impKey = await this.subtle.importKey("raw", macKey, signingAlgorithm, false, ["sign"]); + const mac1 = await this.subtle.sign(signingAlgorithm, impKey, a); + const mac2 = await this.subtle.sign(signingAlgorithm, impKey, b); + + if (mac1.byteLength !== mac2.byteLength) { + return false; + } + + const arr1 = new Uint8Array(mac1); + const arr2 = new Uint8Array(mac2); + for (let i = 0; i < arr2.length; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + + return true; + } + + hmacFast(value: string, key: string, algorithm: "sha1" | "sha256" | "sha512"): Promise { + const hmac = forge.hmac.create(); + hmac.start(algorithm, key); + hmac.update(value); + const bytes = hmac.digest().getBytes(); + return Promise.resolve(bytes); + } + + async compareFast(a: string, b: string): Promise { + const rand = await this.randomBytes(32); + const bytes = new Uint32Array(rand); + const buffer = forge.util.createBuffer(); + for (let i = 0; i < bytes.length; i++) { + buffer.putInt32(bytes[i]); + } + const macKey = buffer.getBytes(); + + const hmac = forge.hmac.create(); + hmac.start("sha256", macKey); + hmac.update(a); + const mac1 = hmac.digest().getBytes(); + + hmac.start(null, null); + hmac.update(b); + const mac2 = hmac.digest().getBytes(); + + const equals = mac1 === mac2; + return equals; + } + + async aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + const impKey = await this.subtle.importKey("raw", key, { name: "AES-CBC" } as any, false, [ + "encrypt", + ]); + return await this.subtle.encrypt({ name: "AES-CBC", iv: iv }, impKey, data); + } + + aesDecryptFastParameters( + data: string, + iv: string, + mac: string, + key: SymmetricCryptoKey + ): DecryptParameters { + const p = new DecryptParameters(); + if (key.meta != null) { + p.encKey = key.meta.encKeyByteString; + p.macKey = key.meta.macKeyByteString; + } + + if (p.encKey == null) { + p.encKey = forge.util.decode64(key.encKeyB64); + } + p.data = forge.util.decode64(data); + p.iv = forge.util.decode64(iv); + p.macData = p.iv + p.data; + if (p.macKey == null && key.macKeyB64 != null) { + p.macKey = forge.util.decode64(key.macKeyB64); + } + if (mac != null) { + p.mac = forge.util.decode64(mac); + } + + // cache byte string keys for later + if (key.meta == null) { + key.meta = {}; + } + if (key.meta.encKeyByteString == null) { + key.meta.encKeyByteString = p.encKey; + } + if (p.macKey != null && key.meta.macKeyByteString == null) { + key.meta.macKeyByteString = p.macKey; + } + + return p; + } + + aesDecryptFast(parameters: DecryptParameters): Promise { + const dataBuffer = forge.util.createBuffer(parameters.data); + const decipher = forge.cipher.createDecipher("AES-CBC", parameters.encKey); + decipher.start({ iv: parameters.iv }); + decipher.update(dataBuffer); + decipher.finish(); + const val = decipher.output.toString(); + return Promise.resolve(val); + } + + async aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + const impKey = await this.subtle.importKey("raw", key, { name: "AES-CBC" } as any, false, [ + "decrypt", + ]); + return await this.subtle.decrypt({ name: "AES-CBC", iv: iv }, impKey, data); + } + + async rsaEncrypt( + data: ArrayBuffer, + publicKey: ArrayBuffer, + algorithm: "sha1" | "sha256" + ): Promise { + // Note: Edge browser requires that we specify name and hash for both key import and decrypt. + // We cannot use the proper types here. + const rsaParams = { + name: "RSA-OAEP", + hash: { name: this.toWebCryptoAlgorithm(algorithm) }, + }; + const impKey = await this.subtle.importKey("spki", publicKey, rsaParams, false, ["encrypt"]); + return await this.subtle.encrypt(rsaParams, impKey, data); + } + + async rsaDecrypt( + data: ArrayBuffer, + privateKey: ArrayBuffer, + algorithm: "sha1" | "sha256" + ): Promise { + // Note: Edge browser requires that we specify name and hash for both key import and decrypt. + // We cannot use the proper types here. + const rsaParams = { + name: "RSA-OAEP", + hash: { name: this.toWebCryptoAlgorithm(algorithm) }, + }; + const impKey = await this.subtle.importKey("pkcs8", privateKey, rsaParams, false, ["decrypt"]); + return await this.subtle.decrypt(rsaParams, impKey, data); + } + + async rsaExtractPublicKey(privateKey: ArrayBuffer): Promise { + const rsaParams = { + name: "RSA-OAEP", + // Have to specify some algorithm + hash: { name: this.toWebCryptoAlgorithm("sha1") }, + }; + const impPrivateKey = await this.subtle.importKey("pkcs8", privateKey, rsaParams, true, [ + "decrypt", + ]); + const jwkPrivateKey = await this.subtle.exportKey("jwk", impPrivateKey); + const jwkPublicKeyParams = { + kty: "RSA", + e: jwkPrivateKey.e, + n: jwkPrivateKey.n, + alg: "RSA-OAEP", + ext: true, + }; + const impPublicKey = await this.subtle.importKey("jwk", jwkPublicKeyParams, rsaParams, true, [ + "encrypt", + ]); + return await this.subtle.exportKey("spki", impPublicKey); + } + + async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[ArrayBuffer, ArrayBuffer]> { + const rsaParams = { + name: "RSA-OAEP", + modulusLength: length, + publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // 65537 + // Have to specify some algorithm + hash: { name: this.toWebCryptoAlgorithm("sha1") }, + }; + const keyPair = (await this.subtle.generateKey(rsaParams, true, [ + "encrypt", + "decrypt", + ])) as CryptoKeyPair; + const publicKey = await this.subtle.exportKey("spki", keyPair.publicKey); + const privateKey = await this.subtle.exportKey("pkcs8", keyPair.privateKey); + return [publicKey, privateKey]; + } + + randomBytes(length: number): Promise { + const arr = new Uint8Array(length); + this.crypto.getRandomValues(arr); + return Promise.resolve(arr.buffer); + } + + private toBuf(value: string | ArrayBuffer): ArrayBuffer { + let buf: ArrayBuffer; + if (typeof value === "string") { + buf = Utils.fromUtf8ToArray(value).buffer; + } else { + buf = value; + } + return buf; + } + + private toByteString(value: string | ArrayBuffer): string { + let bytes: string; + if (typeof value === "string") { + bytes = forge.util.encodeUtf8(value); + } else { + bytes = Utils.fromBufferToByteString(value); + } + return bytes; + } + + private toWebCryptoAlgorithm(algorithm: "sha1" | "sha256" | "sha512" | "md5"): string { + if (algorithm === "md5") { + throw new Error("MD5 is not supported in WebCrypto."); + } + return algorithm === "sha1" ? "SHA-1" : algorithm === "sha256" ? "SHA-256" : "SHA-512"; + } +} diff --git a/libs/common/src/types/verification.ts b/libs/common/src/types/verification.ts new file mode 100644 index 0000000000..07ca4bbf56 --- /dev/null +++ b/libs/common/src/types/verification.ts @@ -0,0 +1,6 @@ +import { VerificationType } from "../enums/verificationType"; + +export type Verification = { + type: VerificationType; + secret: string; +}; diff --git a/libs/common/tsconfig.json b/libs/common/tsconfig.json new file mode 100644 index 0000000000..0d578efad2 --- /dev/null +++ b/libs/common/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../shared/tsconfig", + "compilerOptions": { + "paths": { + "jslib-common/*": ["./src/*"] + } + }, + "include": ["src", "spec"], + "exclude": ["node_modules", "dist"] +} diff --git a/libs/common/tsconfig.spec.json b/libs/common/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/libs/common/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/libs/components/.browserslistrc b/libs/components/.browserslistrc new file mode 100644 index 0000000000..4f9ac26980 --- /dev/null +++ b/libs/components/.browserslistrc @@ -0,0 +1,16 @@ +# This file is used by the build system to adjust CSS and JS output to support the specified browsers below. +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries + +# For the full list of supported browsers by the Angular framework, please see: +# https://angular.io/guide/browser-support + +# You can see what browsers were selected by your queries by running: +# npx browserslist + +last 1 Chrome version +last 1 Firefox version +last 2 Edge major versions +last 2 Safari major versions +last 2 iOS major versions +Firefox ESR diff --git a/libs/components/.gitignore b/libs/components/.gitignore new file mode 100644 index 0000000000..1edd399c5a --- /dev/null +++ b/libs/components/.gitignore @@ -0,0 +1,44 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# Compiled output +/dist +/tmp +/out-tsc +/bazel-out + +documentation.json + +# Node +/node_modules +npm-debug.log +yarn-error.log + +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# Miscellaneous +/.angular/cache +.sass-cache/ +/connect.lock +/coverage +/libpeerconnection.log +testem.log +/typings + +# System files +.DS_Store +Thumbs.db diff --git a/libs/components/.storybook/main.js b/libs/components/.storybook/main.js new file mode 100644 index 0000000000..bcc8fad8b8 --- /dev/null +++ b/libs/components/.storybook/main.js @@ -0,0 +1,13 @@ +module.exports = { + stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], + addons: [ + "@storybook/addon-links", + "@storybook/addon-essentials", + "@storybook/addon-a11y", + "storybook-addon-designs", + ], + framework: "@storybook/angular", + core: { + builder: "webpack5", + }, +}; diff --git a/libs/components/.storybook/preview.js b/libs/components/.storybook/preview.js new file mode 100644 index 0000000000..8bc2510a08 --- /dev/null +++ b/libs/components/.storybook/preview.js @@ -0,0 +1,33 @@ +import { setCompodocJson } from "@storybook/addon-docs/angular"; +import { componentWrapperDecorator, addDecorator } from "@storybook/angular"; + +import docJson from "../documentation.json"; +setCompodocJson(docJson); + +export const parameters = { + actions: { argTypesRegex: "^on[A-Z].*" }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/, + }, + }, + docs: { inlineStories: true }, +}; + +// ng-template is used to scope any template reference variables and isolate the previews +const decorator = componentWrapperDecorator( + (story) => ` + +
${story}
+
+ +
${story}
+
+ + + +` +); + +addDecorator(decorator); diff --git a/libs/components/.storybook/tsconfig.json b/libs/components/.storybook/tsconfig.json new file mode 100644 index 0000000000..330b58615a --- /dev/null +++ b/libs/components/.storybook/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../tsconfig.app.json", + "compilerOptions": { + "types": ["node"], + "allowSyntheticDefaultImports": true + }, + "exclude": ["../src/test.ts", "../src/**/*.spec.ts", "../projects/**/*.spec.ts"], + "include": ["../src/**/*", "../projects/**/*"], + "files": ["./typings.d.ts"] +} diff --git a/libs/components/.storybook/typings.d.ts b/libs/components/.storybook/typings.d.ts new file mode 100644 index 0000000000..c94d67b1a2 --- /dev/null +++ b/libs/components/.storybook/typings.d.ts @@ -0,0 +1,4 @@ +declare module "*.md" { + const content: string; + export default content; +} diff --git a/libs/components/README.md b/libs/components/README.md new file mode 100644 index 0000000000..ce39c48faf --- /dev/null +++ b/libs/components/README.md @@ -0,0 +1,27 @@ +# Components + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 13.1.3. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/libs/components/angular.json b/libs/components/angular.json new file mode 100644 index 0000000000..90015d56a3 --- /dev/null +++ b/libs/components/angular.json @@ -0,0 +1,81 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "components": { + "projectType": "application", + "schematics": { + "@schematics/angular:application": { + "strict": true + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/components", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "tsconfig.app.json", + "assets": ["src/favicon.ico", "src/assets"], + "styles": ["src/styles.scss", "src/styles.css"], + "stylePreprocessorOptions": { + "includePaths": ["src/styles"] + }, + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "components:build:production" + }, + "development": { + "browserTarget": "components:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "components:build" + } + } + } + } + }, + "defaultProject": "components" +} diff --git a/libs/components/jest.config.js b/libs/components/jest.config.js new file mode 100644 index 0000000000..8aa314bd35 --- /dev/null +++ b/libs/components/jest.config.js @@ -0,0 +1,17 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + name: "angular", + displayName: "libs/components tests", + preset: "jest-preset-angular", + testMatch: ["**/+(*.)+(spec).+(ts)"], + setupFilesAfterEnv: ["/spec/test.ts"], + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), +}; diff --git a/libs/components/package-lock.json b/libs/components/package-lock.json new file mode 100644 index 0000000000..0416561421 --- /dev/null +++ b/libs/components/package-lock.json @@ -0,0 +1,71720 @@ +{ + "name": "components", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "components", + "version": "0.0.0", + "dependencies": { + "@angular/animations": "^12.2.13", + "@angular/cdk": "^12.2.13", + "@angular/common": "^12.2.13", + "@angular/compiler": "^12.2.13", + "@angular/core": "^12.2.13", + "@angular/forms": "^12.2.13", + "@angular/platform-browser": "^12.2.13", + "@angular/platform-browser-dynamic": "^12.2.13", + "@bitwarden/jslib-angular": "file:../angular", + "bootstrap": "4.6.0", + "rxjs": "^7.4.0", + "tslib": "^2.3.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^12.2.13", + "@angular/cli": "^12.2.13", + "@angular/compiler-cli": "^12.2.13", + "@angular/elements": "^12.2.13", + "@babel/core": "^7.16.10", + "@compodoc/compodoc": "^1.1.16", + "@storybook/addon-a11y": "^6.4.19", + "@storybook/addon-actions": "^6.4.18", + "@storybook/addon-essentials": "^6.4.18", + "@storybook/addon-links": "^6.4.18", + "@storybook/angular": "^6.4.18", + "@storybook/builder-webpack5": "^6.4.18", + "@storybook/manager-webpack5": "^6.4.18", + "@types/node": "^16.11.33", + "@webcomponents/custom-elements": "^1.5.0", + "autoprefixer": "^10.4.2", + "babel-loader": "^8.2.3", + "chromatic": "^6.5.2", + "jest-preset-angular": "^11.1.2", + "postcss": "^8.4.6", + "storybook-addon-designs": "^6.2.1", + "tailwindcss": "^3.0.18", + "typescript": "~4.3.5" + } + }, + "../angular": { + "name": "@bitwarden/jslib-angular", + "version": "0.0.0", + "license": "GPL-3.0", + "dependencies": { + "@angular/animations": "^12.2.13", + "@angular/cdk": "^12.2.13", + "@angular/common": "^12.2.13", + "@angular/compiler": "^12.2.13", + "@angular/core": "^12.2.13", + "@angular/forms": "^12.2.13", + "@angular/platform-browser": "^12.2.13", + "@angular/platform-browser-dynamic": "^12.2.13", + "@angular/router": "^12.2.13", + "@bitwarden/jslib-common": "file:../common", + "duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git", + "rxjs": "^7.4.0", + "tldjs": "^2.3.1", + "zone.js": "0.11.4" + }, + "devDependencies": { + "@types/duo_web_sdk": "^2.7.1", + "rimraf": "^3.0.2", + "typescript": "4.3.5" + } + }, + "node_modules/@aduh95/viz.js": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@aduh95/viz.js/-/viz.js-3.5.0.tgz", + "integrity": "sha512-ahLdpRAoGsdgEfy2SGV2wnnHrBSLDHuwA32v+BoNGnz1gqajr8VMzF8y6mIQt28hHi4LQ272wqSi78DK4YdT2g==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-1.0.1.tgz", + "integrity": "sha512-Ta9bMA3EtUHDaZJXqUoT5cn/EecwOp+SXpKJqxDbDuMbLvEMu6YTyDDuvTWeStODfdmXyfMo7LymQyPkN3BicA==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "1.0.0", + "sourcemap-codec": "1.4.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1302.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1302.3.tgz", + "integrity": "sha512-0m8jMKrFfIqsYt33zTUwSmyekyfuS67hna08RQ6USjzWQSE3z4S8ulCUARSjM6AzdMblX+whfy56nJUpT17NSA==", + "dev": true, + "peer": true, + "dependencies": { + "@angular-devkit/core": "13.2.3", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/architect/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "peer": true + }, + "node_modules/@angular-devkit/build-angular": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-12.2.16.tgz", + "integrity": "sha512-0UlSaX3LngsBUp6Da69XlptyeZn7CTt/3sKijQDtkEw/J37vpMcXYD4nUuU7q7mVMoPQwMyPWdF+JBsBFz6f7A==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "1.0.1", + "@angular-devkit/architect": "0.1202.16", + "@angular-devkit/build-optimizer": "0.1202.16", + "@angular-devkit/build-webpack": "0.1202.16", + "@angular-devkit/core": "12.2.16", + "@babel/core": "7.14.8", + "@babel/generator": "7.14.8", + "@babel/helper-annotate-as-pure": "7.14.5", + "@babel/plugin-proposal-async-generator-functions": "7.14.7", + "@babel/plugin-transform-async-to-generator": "7.14.5", + "@babel/plugin-transform-runtime": "7.14.5", + "@babel/preset-env": "7.14.8", + "@babel/runtime": "7.14.8", + "@babel/template": "7.14.5", + "@discoveryjs/json-ext": "0.5.3", + "@jsdevtools/coverage-istanbul-loader": "3.0.5", + "@ngtools/webpack": "12.2.16", + "ansi-colors": "4.1.1", + "babel-loader": "8.2.2", + "browserslist": "^4.9.1", + "cacache": "15.2.0", + "caniuse-lite": "^1.0.30001032", + "circular-dependency-plugin": "5.2.2", + "copy-webpack-plugin": "9.0.1", + "core-js": "3.16.0", + "critters": "0.0.12", + "css-loader": "6.2.0", + "css-minimizer-webpack-plugin": "3.0.2", + "esbuild-wasm": "0.13.8", + "find-cache-dir": "3.3.1", + "glob": "7.1.7", + "https-proxy-agent": "5.0.0", + "inquirer": "8.1.2", + "karma-source-map-support": "1.4.0", + "less": "4.1.1", + "less-loader": "10.0.1", + "license-webpack-plugin": "2.3.20", + "loader-utils": "2.0.0", + "mini-css-extract-plugin": "2.4.2", + "minimatch": "3.0.4", + "open": "8.2.1", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "6.0.1", + "piscina": "3.1.0", + "postcss": "8.3.6", + "postcss-import": "14.0.2", + "postcss-loader": "6.1.1", + "postcss-preset-env": "6.7.0", + "regenerator-runtime": "0.13.9", + "resolve-url-loader": "4.0.0", + "rxjs": "6.6.7", + "sass": "1.36.0", + "sass-loader": "12.1.0", + "semver": "7.3.5", + "source-map-loader": "3.0.0", + "source-map-support": "0.5.19", + "style-loader": "3.2.1", + "stylus": "0.54.8", + "stylus-loader": "6.1.0", + "terser": "5.7.1", + "terser-webpack-plugin": "5.1.4", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.3.0", + "webpack": "5.50.0", + "webpack-dev-middleware": "5.0.0", + "webpack-dev-server": "3.11.3", + "webpack-merge": "5.8.0", + "webpack-subresource-integrity": "1.5.2" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "optionalDependencies": { + "esbuild": "0.13.8" + }, + "peerDependencies": { + "@angular/compiler-cli": "^12.0.0", + "@angular/localize": "^12.0.0", + "@angular/service-worker": "^12.0.0", + "karma": "^6.3.0", + "ng-packagr": "^12.0.0", + "protractor": "^7.0.0", + "tailwindcss": "^2.0.0", + "tslint": "^6.1.0", + "typescript": "~4.2.3 || ~4.3.2" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tailwindcss": { + "optional": true + }, + "tslint": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/architect": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.16.tgz", + "integrity": "sha512-VUGyAr+5RmlcPjo8mZSRJ/wkm3hCPn9PJyorAnc1IzrqD+XkgcDME86HP3YheLsOsc1Mn7j6Zh3T1rAclAWw/w==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "12.2.16", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "dependencies": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/core": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.8.tgz", + "integrity": "sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.8", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.8", + "@babel/helpers": "^7.14.8", + "@babel/parser": "^7.14.8", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.8", + "@babel/types": "^7.14.8", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/babel-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/babel-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/enhanced-resolve": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz", + "integrity": "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/es-module-lexer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.7.1.tgz", + "integrity": "sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/postcss": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.6.tgz", + "integrity": "sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map-js": "^0.6.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.50.0.tgz", + "integrity": "sha512-hqxI7t/KVygs0WRv/kTgUW8Kl3YC81uyWQSo/7WUs5LsuRw0htH/fCwbVBGCuiX/t4s7qzjXFcf41O8Reiypag==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.50", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.0", + "es-module-lexer": "^0.7.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.2.0", + "webpack-sources": "^3.2.0" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@angular-devkit/build-angular/node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@angular-devkit/build-optimizer": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.16.tgz", + "integrity": "sha512-7DO195vDwOnCCHrzjr6ajSNkvCzW6O/ERbVezCA46NZuS9lW9LnWpP3CE9iDnhzup7hjrM336/dXmYJO8Hw1MA==", + "dev": true, + "dependencies": { + "source-map": "0.7.3", + "tslib": "2.3.0", + "typescript": "4.3.5" + }, + "bin": { + "build-optimizer": "src/build-optimizer/cli.js" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^5.30.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-optimizer/node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1202.16.tgz", + "integrity": "sha512-Zhnr0+W1og1rtbfKDPxD7jWDL4cg9LA21ls2pJKXc/h+YXdQ5uj4mFg69npL6aY0yver1w2rIz+Il/wdC/W1gw==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1202.16", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^5.30.0", + "webpack-dev-server": "^3.1.4" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/architect": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.16.tgz", + "integrity": "sha512-VUGyAr+5RmlcPjo8mZSRJ/wkm3hCPn9PJyorAnc1IzrqD+XkgcDME86HP3YheLsOsc1Mn7j6Zh3T1rAclAWw/w==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "12.2.16", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "dependencies": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/build-webpack/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/core": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.3.tgz", + "integrity": "sha512-/47RA8qmWzeS60xSdaprIn1MiSv0Iw83t0M9/ENH7irFS5vMAq62NCcwiWXH59pZmvvLbF+7xy/RgYUZLr4nHQ==", + "dev": true, + "dependencies": { + "ajv": "8.9.0", + "ajv-formats": "2.1.1", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/core/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/core/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular-devkit/schematics": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.16.tgz", + "integrity": "sha512-ToyZBCGilSeeLmhAxmeJ0PykmbKLoME+uK78gC64xJtNu9e3oVnmog8b8g9Ay9hTwZJ96HvNa16po11Gfbbn6A==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "12.2.16", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "dependencies": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular-devkit/schematics/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular/animations": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.16.tgz", + "integrity": "sha512-Kf6C7Ta+fCMq5DvT9JNVhBkcECrqFa3wumiC6ssGo5sNaEzXz+tlep9ZgEbqfxSn7gAN7L1DgsbS9u0O6tbUkg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/core": "12.2.16" + } + }, + "node_modules/@angular/cdk": { + "version": "12.2.13", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.13.tgz", + "integrity": "sha512-zSKRhECyFqhingIeyRInIyTvYErt4gWo+x5DQr0b7YLUbU8DZSwWnG4w76Ke2s4U8T7ry1jpJBHoX/e8YBpGMg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "optionalDependencies": { + "parse5": "^5.0.0" + }, + "peerDependencies": { + "@angular/common": "^12.0.0 || ^13.0.0-0", + "@angular/core": "^12.0.0 || ^13.0.0-0", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/cli": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.16.tgz", + "integrity": "sha512-4DUi8aHIZWzQycw8SN55ziHhRusHVYJ+2rzsfhy0eDgkry7gYVd4wUn+6Q4D8irywA21soNq1S5JjGAZwRDS6g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@angular-devkit/architect": "0.1202.16", + "@angular-devkit/core": "12.2.16", + "@angular-devkit/schematics": "12.2.16", + "@schematics/angular": "12.2.16", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "4.3.2", + "ini": "2.0.0", + "inquirer": "8.1.2", + "jsonc-parser": "3.0.0", + "npm-package-arg": "8.1.5", + "npm-pick-manifest": "6.1.1", + "open": "8.2.1", + "ora": "5.4.1", + "pacote": "12.0.2", + "resolve": "1.20.0", + "semver": "7.3.5", + "symbol-observable": "4.0.0", + "uuid": "8.3.2" + }, + "bin": { + "ng": "bin/ng" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.16.tgz", + "integrity": "sha512-VUGyAr+5RmlcPjo8mZSRJ/wkm3hCPn9PJyorAnc1IzrqD+XkgcDME86HP3YheLsOsc1Mn7j6Zh3T1rAclAWw/w==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "12.2.16", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "dependencies": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/cli/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@angular/cli/node_modules/ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@angular/cli/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@angular/cli/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@angular/common": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.16.tgz", + "integrity": "sha512-FEqTXTEsnbDInqV1yFlm97Tz1OFqZS5t0TUkm8gzXRgpIce/F/jLwAg0u1VQkgOsno6cNm0xTWPoZgu85NI4ug==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/core": "12.2.16", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/compiler": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.16.tgz", + "integrity": "sha512-nsYEw+yu8QyeqPf9nAmG419i1mtGM4v8+U+S3eQHQFXTgJzLymMykWHYu2ETdjUpNSLK6xcIQDBWtWnWSfJjAA==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + } + }, + "node_modules/@angular/compiler-cli": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.16.tgz", + "integrity": "sha512-tlalh8SJvdCWbUPRUR5GamaP+wSc/GuCsoUZpSbcczGKgSlbaEVXUYtVXm8/wuT6Slk2sSEbRs7tXGF2i7qxVw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.11.0", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.2.0", + "yargs": "^17.0.0" + }, + "bin": { + "ivy-ngcc": "ngcc/main-ivy-ngcc.js", + "ng-xi18n": "src/extract_i18n.js", + "ngc": "src/main.js", + "ngcc": "ngcc/main-ngcc.js" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/compiler": "12.2.16", + "typescript": ">=4.2.3 <4.4" + } + }, + "node_modules/@angular/compiler-cli/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@angular/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.16.tgz", + "integrity": "sha512-jsmvaRdAfng99z2a9mAmkfcsCE1wm+tBYVDxnc5JquSXznwtncjzcoc2X0J0dzrkCDvzFfpTsZ9vehylytBc+A==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.0.0", + "zone.js": "~0.11.4" + } + }, + "node_modules/@angular/elements": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-12.2.16.tgz", + "integrity": "sha512-tOTf6FvnxZg/TjrmsbowHjrTYVl6WhTOQk3G4aYicrf+57a67L12F44Illr7I6preIvH5NepHivMTKN5rNBAmg==", + "dev": true, + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/core": "12.2.16", + "@angular/platform-browser": "12.2.16", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/forms": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.16.tgz", + "integrity": "sha512-sb+gpNun5aN7CZfHXS6X7vJcd/0A1P/gRBZpYtQTzBYnqEFCOFIvR62eb05aHQ4JhgKaSPpIXrbz/bAwY/njZw==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/common": "12.2.16", + "@angular/core": "12.2.16", + "@angular/platform-browser": "12.2.16", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/platform-browser": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.16.tgz", + "integrity": "sha512-T855ppLeQO6hRHi7lGf5fwPoUVt+c0h2rgkV5jHElc3ylaGnhecmZc6fnWLX4pw82TMJUgUV88CY8JCFabJWwg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/animations": "12.2.16", + "@angular/common": "12.2.16", + "@angular/core": "12.2.16" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.16.tgz", + "integrity": "sha512-XGxoACAMW/bc3atiVRpaiYwU4LkobYwVzwlxTT/BxOfsdt8ILb5wU8Fx1TMKNECOQHSGdK0qqhch4pTBZ3cb2g==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/common": "12.2.16", + "@angular/compiler": "12.2.16", + "@angular/core": "12.2.16", + "@angular/platform-browser": "12.2.16" + } + }, + "node_modules/@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", + "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.17.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.4.tgz", + "integrity": "sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helpers": "^7.17.2", + "@babel/parser": "^7.17.3", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/core/node_modules/@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/core/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.8.tgz", + "integrity": "sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.8", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", + "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.17.5", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz", + "integrity": "sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz", + "integrity": "sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name/node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", + "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", + "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms/node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", + "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function/node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", + "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.0", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers/node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz", + "integrity": "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.2.tgz", + "integrity": "sha512-WH8Z95CwTq/W8rFbMqb9p3hicpt4RX4f0K659ax2VHxgOyT6qQmUaEVEjIh4WR9Eh9NymkVn5vwsrE68fAQNUw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.17.1", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/plugin-syntax-decorators": "^7.17.0", + "charcodes": "^0.2.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.16.7.tgz", + "integrity": "sha512-+cENpW1rgIjExn+o5c8Jw/4BuH4eGKKYvkMB8/0ZxFQ9mC0t4z09VsPIwNg6waF69QYC81zxGeAsREGuqQoKeg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-default-from": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", + "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.16.7.tgz", + "integrity": "sha512-4C3E4NsrLOgftKaTYTULhHsuQrGv3FHrBzOMDiS7UYKIpgGBkAdawg4h+EI8zPeK9M0fiIIh72hIwsI24K7MbA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", + "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", + "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", + "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz", + "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", + "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", + "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", + "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz", + "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz", + "integrity": "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-jsx": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz", + "integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz", + "integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations/node_modules/@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", + "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.14.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz", + "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", + "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-typescript": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.8.tgz", + "integrity": "sha512-a9aOppDU93oArQ51H+B8M1vH+tayZbuBqzjOhntGetZVa+4tTu5jp+XTwqHGG2lxslqomPYVSjIxQkFwXzgnxg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.14.7", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-async-generator-functions": "^7.14.7", + "@babel/plugin-proposal-class-properties": "^7.14.5", + "@babel/plugin-proposal-class-static-block": "^7.14.5", + "@babel/plugin-proposal-dynamic-import": "^7.14.5", + "@babel/plugin-proposal-export-namespace-from": "^7.14.5", + "@babel/plugin-proposal-json-strings": "^7.14.5", + "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", + "@babel/plugin-proposal-numeric-separator": "^7.14.5", + "@babel/plugin-proposal-object-rest-spread": "^7.14.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", + "@babel/plugin-proposal-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-private-methods": "^7.14.5", + "@babel/plugin-proposal-private-property-in-object": "^7.14.5", + "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.14.5", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/plugin-transform-block-scoped-functions": "^7.14.5", + "@babel/plugin-transform-block-scoping": "^7.14.5", + "@babel/plugin-transform-classes": "^7.14.5", + "@babel/plugin-transform-computed-properties": "^7.14.5", + "@babel/plugin-transform-destructuring": "^7.14.7", + "@babel/plugin-transform-dotall-regex": "^7.14.5", + "@babel/plugin-transform-duplicate-keys": "^7.14.5", + "@babel/plugin-transform-exponentiation-operator": "^7.14.5", + "@babel/plugin-transform-for-of": "^7.14.5", + "@babel/plugin-transform-function-name": "^7.14.5", + "@babel/plugin-transform-literals": "^7.14.5", + "@babel/plugin-transform-member-expression-literals": "^7.14.5", + "@babel/plugin-transform-modules-amd": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.14.5", + "@babel/plugin-transform-modules-systemjs": "^7.14.5", + "@babel/plugin-transform-modules-umd": "^7.14.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7", + "@babel/plugin-transform-new-target": "^7.14.5", + "@babel/plugin-transform-object-super": "^7.14.5", + "@babel/plugin-transform-parameters": "^7.14.5", + "@babel/plugin-transform-property-literals": "^7.14.5", + "@babel/plugin-transform-regenerator": "^7.14.5", + "@babel/plugin-transform-reserved-words": "^7.14.5", + "@babel/plugin-transform-shorthand-properties": "^7.14.5", + "@babel/plugin-transform-spread": "^7.14.6", + "@babel/plugin-transform-sticky-regex": "^7.14.5", + "@babel/plugin-transform-template-literals": "^7.14.5", + "@babel/plugin-transform-typeof-symbol": "^7.14.5", + "@babel/plugin-transform-unicode-escapes": "^7.14.5", + "@babel/plugin-transform-unicode-regex": "^7.14.5", + "@babel/preset-modules": "^0.1.4", + "@babel/types": "^7.14.8", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "core-js-compat": "^3.15.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz", + "integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-react-display-name": "^7.16.7", + "@babel/plugin-transform-react-jsx": "^7.16.7", + "@babel/plugin-transform-react-jsx-development": "^7.16.7", + "@babel/plugin-transform-react-pure-annotations": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", + "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.0.tgz", + "integrity": "sha512-UNZsMAZ7uKoGHo1HlEXfteEOYssf64n/PNLHGqOKq/bgYcu/4LrQWAHJwSCb3BRZK8Hi5gkJdRcwrGTO2wtRCg==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/register/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/register/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/runtime": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", + "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "peer": true + }, + "node_modules/@bitwarden/jslib-angular": { + "resolved": "../angular", + "link": true + }, + "node_modules/@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "dev": true, + "dependencies": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + }, + "bin": { + "watch": "cli.js" + }, + "engines": { + "node": ">=0.1.95" + } + }, + "node_modules/@compodoc/compodoc": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.18.tgz", + "integrity": "sha512-+AFtcj2U3AJq6r8a2+PTdajIlS7m3pgvDhqgoYZJ4Rg/Zp9xvuDvUJU+5oHu8iHCAWwda3NoLUDjOZMNR8uIKg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@angular-devkit/schematics": "^13.1.2", + "@babel/core": "^7.16.7", + "@babel/preset-env": "^7.16.7", + "@compodoc/live-server": "^1.2.3", + "@compodoc/ngd-transformer": "^2.1.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.10", + "chokidar": "^3.5.2", + "colors": "1.4.0", + "commander": "^8.3.0", + "cosmiconfig": "^7.0.1", + "decache": "^4.6.1", + "fancy-log": "^2.0.0", + "findit2": "^2.2.3", + "fs-extra": "^10.0.0", + "glob": "^7.2.0", + "handlebars": "^4.7.7", + "html-entities": "^2.3.2", + "i18next": "^21.6.5", + "inside": "^1.0.0", + "json5": "^2.2.0", + "lodash": "^4.17.21", + "loglevel": "^1.8.0", + "loglevel-plugin-prefix": "^0.8.4", + "lunr": "^2.3.9", + "marked": "^4.0.9", + "minimist": "^1.2.5", + "opencollective-postinstall": "^2.0.3", + "os-name": "4.0.1", + "pdfjs-dist": "^2.12.313", + "pdfmake": "^0.2.4", + "semver": "^7.3.5", + "traverse": "^0.6.6", + "ts-morph": "^13.0.2", + "uuid": "^8.3.2" + }, + "bin": { + "compodoc": "bin/index-cli.js" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/@angular-devkit/schematics": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.3.tgz", + "integrity": "sha512-+dyC4iKV0huvpjiuz4uyjLNK3FsCIp/Ghv5lXvhG6yok/dCAubsJItJOxi6G16aVCzG/E9zbsDfm9fNMyVOkgQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "13.2.3", + "jsonc-parser": "3.0.0", + "magic-string": "0.25.7", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@compodoc/compodoc/node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/@babel/preset-env": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", + "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.16.8", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.16.7", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.16.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.16.8", + "@babel/plugin-transform-modules-systemjs": "^7.16.7", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.16.7", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.16.8", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@compodoc/compodoc/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@compodoc/compodoc/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@compodoc/compodoc/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@compodoc/compodoc/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@compodoc/compodoc/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@compodoc/compodoc/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@compodoc/compodoc/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@compodoc/compodoc/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@compodoc/live-server": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@compodoc/live-server/-/live-server-1.2.3.tgz", + "integrity": "sha512-hDmntVCyjjaxuJzPzBx68orNZ7TW4BtHWMnXlIVn5dqhK7vuFF/11hspO1cMmc+2QTYgqde1TBcb3127S7Zrow==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "colors": "1.4.0", + "connect": "^3.7.0", + "cors": "latest", + "event-stream": "4.0.1", + "faye-websocket": "0.11.x", + "http-auth": "4.1.9", + "http-auth-connect": "^1.0.5", + "morgan": "^1.10.0", + "object-assign": "latest", + "open": "8.4.0", + "proxy-middleware": "latest", + "send": "latest", + "serve-index": "^1.9.1" + }, + "bin": { + "live-server": "live-server.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@compodoc/live-server/node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@compodoc/ngd-core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@compodoc/ngd-core/-/ngd-core-2.1.0.tgz", + "integrity": "sha512-nyBH7J7SJJ2AV6OeZhJ02kRtVB7ALnZJKgShjoL9CNmOFEj8AkdhP9qTBIgjaDrbsW5pF4nx32KQL2fT7RFnqw==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1", + "fancy-log": "^1.3.3", + "typescript": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@compodoc/ngd-core/node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/@compodoc/ngd-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@compodoc/ngd-transformer/-/ngd-transformer-2.1.0.tgz", + "integrity": "sha512-Jo4VCMzIUtgIAdRmhHhOoRRE01gCjc5CyrUERRx0VgEzkkCm1Wmu/XHSsQP6tSpCYHBjERghqaDqH5DabkR2oQ==", + "dev": true, + "dependencies": { + "@aduh95/viz.js": "^3.1.0", + "@compodoc/ngd-core": "~2.1.0", + "dot": "^1.1.3", + "fs-extra": "^9.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@compodoc/ngd-transformer/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", + "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@emotion/cache": { + "version": "10.0.29", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", + "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", + "dev": true, + "dependencies": { + "@emotion/sheet": "0.9.4", + "@emotion/stylis": "0.8.5", + "@emotion/utils": "0.11.3", + "@emotion/weak-memoize": "0.2.5" + } + }, + "node_modules/@emotion/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.3.1.tgz", + "integrity": "sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.5.5", + "@emotion/cache": "^10.0.27", + "@emotion/css": "^10.0.27", + "@emotion/serialize": "^0.11.15", + "@emotion/sheet": "0.9.4", + "@emotion/utils": "0.11.3" + }, + "peerDependencies": { + "react": ">=16.3.0" + } + }, + "node_modules/@emotion/css": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz", + "integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==", + "dev": true, + "dependencies": { + "@emotion/serialize": "^0.11.15", + "@emotion/utils": "0.11.3", + "babel-plugin-emotion": "^10.0.27" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "dev": true + }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "dev": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "dev": true + }, + "node_modules/@emotion/serialize": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", + "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", + "dev": true, + "dependencies": { + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/unitless": "0.7.5", + "@emotion/utils": "0.11.3", + "csstype": "^2.5.7" + } + }, + "node_modules/@emotion/sheet": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz", + "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==", + "dev": true + }, + "node_modules/@emotion/styled": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-10.3.0.tgz", + "integrity": "sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ==", + "dev": true, + "dependencies": { + "@emotion/styled-base": "^10.3.0", + "babel-plugin-emotion": "^10.0.27" + }, + "peerDependencies": { + "@emotion/core": "^10.0.27", + "react": ">=16.3.0" + } + }, + "node_modules/@emotion/styled-base": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@emotion/styled-base/-/styled-base-10.3.0.tgz", + "integrity": "sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.5.5", + "@emotion/is-prop-valid": "0.8.8", + "@emotion/serialize": "^0.11.15", + "@emotion/utils": "0.11.3" + }, + "peerDependencies": { + "@emotion/core": "^10.0.28", + "react": ">=16.3.0" + } + }, + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", + "dev": true + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "dev": true + }, + "node_modules/@emotion/utils": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", + "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==", + "dev": true + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", + "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", + "dev": true + }, + "node_modules/@figspec/components": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@figspec/components/-/components-1.0.0.tgz", + "integrity": "sha512-a8sgP0YLJ3H0g0pdZPYecxfp9JNVQUTaaU3xcSci8duHXTGkJ7X8QPPCBbyhB+MoxMxnsAh8GjkfZHEr9oIoPQ==", + "dev": true, + "dependencies": { + "copy-to-clipboard": "^3.0.0", + "lit-element": "^2.4.0", + "lit-html": "^1.1.1" + } + }, + "node_modules/@figspec/react": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@figspec/react/-/react-1.0.0.tgz", + "integrity": "sha512-BkOu3RsKF5vCtPoqsc6Oeyxw4wr9GesFrB9/wDHFqgjzhWsw8erFxCsPxsjdlJD8d8OWVHoM6SWxAaGe/pLdxg==", + "dev": true, + "dependencies": { + "@figspec/components": "^1.0.0" + }, + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0" + } + }, + "node_modules/@foliojs-fork/fontkit": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.1.tgz", + "integrity": "sha512-U589voc2/ROnvx1CyH9aNzOQWJp127JGU1QAylXGQ7LoEAF6hMmahZLQ4eqAcgHUw+uyW4PjtCItq9qudPkK3A==", + "dev": true, + "dependencies": { + "@foliojs-fork/restructure": "^2.0.2", + "brfs": "^2.0.0", + "brotli": "^1.2.0", + "browserify-optional": "^1.0.1", + "clone": "^1.0.4", + "deep-equal": "^1.0.0", + "dfa": "^1.2.0", + "tiny-inflate": "^1.0.2", + "unicode-properties": "^1.2.2", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/@foliojs-fork/linebreak": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@foliojs-fork/linebreak/-/linebreak-1.1.1.tgz", + "integrity": "sha512-pgY/+53GqGQI+mvDiyprvPWgkTlVBS8cxqee03ejm6gKAQNsR1tCYCIvN9FHy7otZajzMqCgPOgC4cHdt4JPig==", + "dev": true, + "dependencies": { + "base64-js": "1.3.1", + "brfs": "^2.0.2", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/@foliojs-fork/linebreak/node_modules/base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "node_modules/@foliojs-fork/pdfkit": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@foliojs-fork/pdfkit/-/pdfkit-0.13.0.tgz", + "integrity": "sha512-YXeG1fml9k97YNC9K8e292Pj2JzGt9uOIiBFuQFxHsdQ45BlxW+JU3RQK6JAvXU7kjhjP8rCcYvpk36JLD33sQ==", + "dev": true, + "dependencies": { + "@foliojs-fork/fontkit": "^1.9.1", + "@foliojs-fork/linebreak": "^1.1.1", + "crypto-js": "^4.0.0", + "png-js": "^1.0.0" + } + }, + "node_modules/@foliojs-fork/restructure": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@foliojs-fork/restructure/-/restructure-2.0.2.tgz", + "integrity": "sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/@jest/core/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/environment/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/environment/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/environment/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/environment/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/fake-timers/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/fake-timers/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, + "node_modules/@jest/fake-timers/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/fake-timers/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/globals/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/globals/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/globals/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/globals/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "peer": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/@jest/reporters/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@jest/reporters/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "peer": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/test-result/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/test-result/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/test-result/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/test-result/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jest/test-sequencer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/test-sequencer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/test-sequencer/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/@jest/test-sequencer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/test-sequencer/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/@jest/test-sequencer/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.6.2", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.6.2", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-1.0.0.tgz", + "integrity": "sha512-9oLAnygRMi8Q5QkYEU4XWK04B+nuoXoxjRvRxgjuChkLZFBja0YPSgdZ7dZtwhncLBcQe/I/E+fLuk5qxcYVJA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jsdevtools/coverage-istanbul-loader": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", + "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", + "dev": true, + "dependencies": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.3", + "loader-utils": "^2.0.0", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.7.0" + } + }, + "node_modules/@mdx-js/loader": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", + "integrity": "sha512-9CjGwy595NaxAYp0hF9B/A0lH6C8Rms97e2JS9d3jVUtILn6pT5i5IV965ra3lIWc7Rs1GG1tBdVF7dCowYe6Q==", + "dev": true, + "dependencies": { + "@mdx-js/mdx": "1.6.22", + "@mdx-js/react": "1.6.22", + "loader-utils": "2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "dev": true, + "dependencies": { + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/mdx/node_modules/@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@mdx-js/mdx/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@mdx-js/mdx/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@mdx-js/mdx/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@mdx-js/react": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", + "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0" + } + }, + "node_modules/@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "dependencies": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@mrmlnc/readdir-enhanced/node_modules/glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "node_modules/@ngtools/webpack": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.16.tgz", + "integrity": "sha512-Y2wYX0ybpTYCuSXrG7+3FAtL4dSa7D1vMxymeJEmPTf5QcFTbllwcGQ82Q9lzTn3UDxvt6ZqAYfmWZHGp2GQ9w==", + "dev": true, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^12.0.0", + "typescript": "~4.2.3 || ~4.3.2", + "webpack": "^5.30.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/git": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", + "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^6.1.1", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dev": true, + "dependencies": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "installed-package-contents": "index.js" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", + "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==", + "dev": true + }, + "node_modules/@npmcli/promise-spawn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "dev": true, + "dependencies": { + "infer-owner": "^1.0.4" + } + }, + "node_modules/@npmcli/run-script": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-2.0.0.tgz", + "integrity": "sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^1.0.2", + "@npmcli/promise-spawn": "^1.3.2", + "node-gyp": "^8.2.0", + "read-package-json-fast": "^2.0.1" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", + "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@schematics/angular": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.16.tgz", + "integrity": "sha512-EITPMaRE7iCosf0nyZFOpxTDAiPD3qm4QUxHKcwIaJTrzi89nBoUubw8+pFy5/Gtpadww80YD8ODV64B1bPGMA==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "12.2.16", + "@angular-devkit/schematics": "12.2.16", + "jsonc-parser": "3.0.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "dependencies": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@schematics/angular/node_modules/ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@schematics/angular/node_modules/ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@schematics/angular/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@schematics/angular/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/@storybook/addon-a11y": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.4.19.tgz", + "integrity": "sha512-dG6easap6W4AqyggVZPq8lBrhza8StA8J4eYz/GVdoXINSGtq/casV0rkmY3+SUXhPYux5oGavHo86j5I4Q/0Q==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "axe-core": "^4.2.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "react-sizeme": "^3.0.1", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-actions": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.19.tgz", + "integrity": "sha512-GpSvP8xV8GfNkmtGJjfCgaOx6mbjtyTK0aT9FqX9pU0s+KVMmoCTrBh43b7dWrwxxas01yleBK9VpYggzhi/Fw==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "polished": "^4.0.5", + "prop-types": "^15.7.2", + "react-inspector": "^5.1.0", + "regenerator-runtime": "^0.13.7", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "uuid-browser": "^3.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.4.19.tgz", + "integrity": "sha512-yn8MTE7lctO48Rdw+DmmA1wKdf5eyAbA/vrug5ske/U2WPgGc65sApzwT8BItZfuyAMjuT5RnCWwd7o6hGRgGQ==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-controls": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.4.19.tgz", + "integrity": "sha512-JHi5z9i6NsgQLfG5WOeQE1AyOrM+QJLrjT+uOYx40bq+OC1yWHH7qHiphPP8kjJJhCZlaQk1qqXYkkQXgaeHSw==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/node-logger": "6.4.19", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-docs": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.4.19.tgz", + "integrity": "sha512-OEPyx/5ZXmZOPqIAWoPjlIP8Q/YfNjAmBosA8tmA8t5KCSiq/vpLcAvQhxqK6n0wk/B8Xp67Z8RpLfXjU8R3tw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/generator": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/plugin-transform-react-jsx": "^7.12.12", + "@babel/preset-env": "^7.12.11", + "@jest/transform": "^26.6.2", + "@mdx-js/loader": "^1.6.22", + "@mdx-js/mdx": "^1.6.22", + "@mdx-js/react": "^1.6.22", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/builder-webpack4": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/csf-tools": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/postinstall": "6.4.19", + "@storybook/preview-web": "6.4.19", + "@storybook/source-loader": "6.4.19", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "core-js": "^3.8.2", + "doctrine": "^3.0.0", + "escodegen": "^2.0.0", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "html-tags": "^3.1.0", + "js-string-escape": "^1.0.1", + "loader-utils": "^2.0.0", + "lodash": "^4.17.21", + "nanoid": "^3.1.23", + "p-limit": "^3.1.0", + "prettier": ">=2.2.1 <=2.3.0", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^14.3.4", + "regenerator-runtime": "^0.13.7", + "remark-external-links": "^8.0.0", + "remark-slug": "^6.0.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@storybook/angular": "6.4.19", + "@storybook/html": "6.4.19", + "@storybook/react": "6.4.19", + "@storybook/vue": "6.4.19", + "@storybook/vue3": "6.4.19", + "@storybook/web-components": "6.4.19", + "lit": "^2.0.0", + "lit-html": "^1.4.1 || ^2.0.0", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0", + "svelte": "^3.31.2", + "sveltedoc-parser": "^4.1.0", + "vue": "^2.6.10 || ^3.0.0", + "webpack": "*" + }, + "peerDependenciesMeta": { + "@storybook/angular": { + "optional": true + }, + "@storybook/html": { + "optional": true + }, + "@storybook/react": { + "optional": true + }, + "@storybook/vue": { + "optional": true + }, + "@storybook/vue3": { + "optional": true + }, + "@storybook/web-components": { + "optional": true + }, + "lit": { + "optional": true + }, + "lit-html": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "svelte": { + "optional": true + }, + "sveltedoc-parser": { + "optional": true + }, + "vue": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-essentials": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.4.19.tgz", + "integrity": "sha512-vbV8sjepMVEuwhTDBHjO3E6vXluG7RiEeozV1QVuS9lGhjQdvUPdZ9rDNUcP6WHhTdEkS/ffTMaGIy1v8oZd7g==", + "dev": true, + "dependencies": { + "@storybook/addon-actions": "6.4.19", + "@storybook/addon-backgrounds": "6.4.19", + "@storybook/addon-controls": "6.4.19", + "@storybook/addon-docs": "6.4.19", + "@storybook/addon-measure": "6.4.19", + "@storybook/addon-outline": "6.4.19", + "@storybook/addon-toolbars": "6.4.19", + "@storybook/addon-viewport": "6.4.19", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/node-logger": "6.4.19", + "core-js": "^3.8.2", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@babel/core": "^7.9.6", + "@storybook/vue": "6.4.19", + "@storybook/web-components": "6.4.19", + "babel-loader": "^8.0.0", + "lit-html": "^1.4.1 || ^2.0.0-rc.3", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0", + "webpack": "*" + }, + "peerDependenciesMeta": { + "@storybook/vue": { + "optional": true + }, + "@storybook/web-components": { + "optional": true + }, + "lit-html": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-links": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.19.tgz", + "integrity": "sha512-ebFHYlGDQkHSmI5QEJb1NxGNToVOLgjKkxXUe+JXX7AfHvrWiXVrN/57aOtBPZzj4h2jRPRTZgwR5glhPIlfEQ==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/router": "6.4.19", + "@types/qs": "^6.9.5", + "core-js": "^3.8.2", + "global": "^4.4.0", + "prop-types": "^15.7.2", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-measure": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.4.19.tgz", + "integrity": "sha512-PXeU0AlpnGEvnzBQ6snkzmlIpwE0ci8LdFtL1Vz1V1Xk5fbuETWYuEkPuk1oZ7L9igB9cfT32SyJlE5MC1iaGg==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "global": "^4.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-outline": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.4.19.tgz", + "integrity": "sha512-7ZDXo8qrms6dx0KRP9PInXIie82h5g9XCNrGOUdfZkQPvgofJVj0kNv6p+WOiGiaVfKPC5KMgIofqzBTFV+k6Q==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.4.19.tgz", + "integrity": "sha512-2UtuX9yB1rD/CAZv1etnOnunfPTvsEKEg/J2HYMKE1lhenWC5muIUXvDXCXvwDC65WviPJ56nFNKaKK1Zz7JDg==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "regenerator-runtime": "^0.13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.4.19.tgz", + "integrity": "sha512-T1hdImxbLj8suQSTbp6HSA1LLHOlqaNK5jjnqzEOoAxY0O8LNPXMJ2jKIeT2fPQ0v+tWGU3tbwf+3xFq0parVQ==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "prop-types": "^15.7.2", + "regenerator-runtime": "^0.13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/addons": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.19.tgz", + "integrity": "sha512-QNyRYhpqmHV8oJxxTBdkRlLSbDFhpBvfvMfIrIT1UXb/eemdBZTaCGVvXZ9UixoEEI7f8VwAQ44IvkU5B1509w==", + "dev": true, + "dependencies": { + "@storybook/api": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/router": "6.4.19", + "@storybook/theming": "6.4.19", + "@types/webpack-env": "^1.16.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "regenerator-runtime": "^0.13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/angular": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-6.4.19.tgz", + "integrity": "sha512-CyJg9reKbk69gkYK1QJhzPydVMeelJ1Fj2VvK5qKL6xEwHSj9buYmbS631i8AC0c9vIWv5lk2BENCLyGqdPYwQ==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/core": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/node-logger": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@types/webpack-env": "^1.16.0", + "autoprefixer": "^9.8.6", + "core-js": "^3.8.2", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^4.1.6", + "global": "^4.4.0", + "postcss": "^7.0.36", + "postcss-loader": "^4.2.0", + "raw-loader": "^4.0.2", + "react": "16.14.0", + "react-dom": "16.14.0", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "sass-loader": "^10.1.0", + "strip-json-comments": "3.1.1", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "ts-loader": "^8.0.14", + "tsconfig-paths-webpack-plugin": "^3.3.0", + "util-deprecate": "^1.0.2", + "webpack": "4" + }, + "bin": { + "build-storybook": "bin/build.js", + "start-storybook": "bin/index.js", + "storybook-server": "bin/index.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@angular-devkit/architect": ">=0.8.9", + "@angular-devkit/build-angular": ">=0.8.9 || >= 12.0.0", + "@angular-devkit/core": "^0.6.1 || >=7.0.0", + "@angular/cli": ">=6.0.0", + "@angular/common": ">=6.0.0", + "@angular/compiler": ">=6.0.0", + "@angular/compiler-cli": ">=6.0.0", + "@angular/core": ">=6.0.0", + "@angular/forms": ">=6.0.0", + "@angular/platform-browser": ">=6.0.0", + "@angular/platform-browser-dynamic": ">=6.0.0", + "@babel/core": "*", + "@nrwl/workspace": ">=11.1.0", + "rxjs": "^6.0.0 || ^7.4.0", + "typescript": "^3.4.0 || >=4.0.0", + "zone.js": "^0.8.29 || ^0.9.0 || ^0.10.0 || ^0.11.0" + }, + "peerDependenciesMeta": { + "@angular/cli": { + "optional": true + }, + "@nrwl/workspace": { + "optional": true + } + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/angular/node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/angular/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/angular/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/angular/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/angular/node_modules/autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/@storybook/angular/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/@storybook/angular/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/angular/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@storybook/angular/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/angular/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/angular/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@storybook/angular/node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/@storybook/angular/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/angular/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@storybook/angular/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/@storybook/angular/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@storybook/angular/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/angular/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/angular/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/angular/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/angular/node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/angular/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@storybook/angular/node_modules/postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/angular/node_modules/react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + }, + "peerDependencies": { + "react": "^16.14.0" + } + }, + "node_modules/@storybook/angular/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@storybook/angular/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@storybook/angular/node_modules/sass-loader": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.2.1.tgz", + "integrity": "sha512-RRvWl+3K2LSMezIsd008ErK4rk6CulIMSwrcc2aZvjymUgKo/vjXGp1rSWmfTUX7bblEOz8tst4wBwWtCGBqKA==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0", + "sass": "^1.3.0", + "webpack": "^4.36.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/@storybook/angular/node_modules/scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/@storybook/angular/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/angular/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/angular/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/@storybook/angular/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@storybook/angular/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@storybook/angular/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/@storybook/angular/node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@storybook/angular/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/angular/node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/@storybook/angular/node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/@storybook/angular/node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/angular/node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@storybook/angular/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/@storybook/angular/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@storybook/api": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.4.19.tgz", + "integrity": "sha512-aDvea+NpQCBjpNp9YidO1Pr7fzzCp15FSdkG+2ihGQfv5raxrN+IIJnGUXecpe71nvlYiB+29UXBVK7AL0j51Q==", + "dev": true, + "dependencies": { + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "store2": "^2.12.0", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/builder-webpack4": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.19.tgz", + "integrity": "sha512-wxA6SMH11duc9D53aeVVBwrVRemFIoxHp/dOugkkg6ZZFAb4ZmWzf/ENc3vQIZdZpfNRi7IZIZEOfoHc994cmw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-proposal-export-default-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.12", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/preview-web": "6.4.19", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "@storybook/ui": "6.4.19", + "@types/node": "^14.0.10", + "@types/webpack": "^4.41.26", + "autoprefixer": "^9.8.6", + "babel-loader": "^8.0.0", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-polyfill-corejs3": "^0.1.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^3.6.0", + "file-loader": "^6.2.0", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^4.1.6", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "global": "^4.4.0", + "html-webpack-plugin": "^4.0.0", + "pnp-webpack-plugin": "1.6.4", + "postcss": "^7.0.36", + "postcss-flexbugs-fixes": "^4.2.1", + "postcss-loader": "^4.2.0", + "raw-loader": "^4.0.2", + "stable": "^0.1.8", + "style-loader": "^1.3.0", + "terser-webpack-plugin": "^4.2.3", + "ts-dedent": "^2.0.0", + "url-loader": "^4.1.1", + "util-deprecate": "^1.0.2", + "webpack": "4", + "webpack-dev-middleware": "^3.7.3", + "webpack-filter-warnings-plugin": "^1.2.1", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.2.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", + "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", + "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.1.5", + "core-js-compat": "^3.8.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/css-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/css-loader/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/postcss-loader/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "dependencies": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "dependencies": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "dependencies": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "dependencies": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack-filter-warnings-plugin": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz", + "integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==", + "dev": true, + "engines": { + "node": ">= 4.3 < 5.0.0 || >= 5.10" + }, + "peerDependencies": { + "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/@storybook/builder-webpack4/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/@storybook/builder-webpack4/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-6.4.19.tgz", + "integrity": "sha512-AWM4YMN1gPaf7jfntqZTCGpIQ1tF6YRU1JtczPG4ox28rTaO6NMfOBi9aRhBre/59pPOh9bF6u2gu/MIHmRW+w==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-proposal-export-default-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.12", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/preview-web": "6.4.19", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "@types/node": "^14.0.10", + "babel-loader": "^8.0.0", + "babel-plugin-macros": "^3.0.1", + "babel-plugin-polyfill-corejs3": "^0.1.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "html-webpack-plugin": "^5.0.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "stable": "^0.1.8", + "style-loader": "^2.0.0", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.4.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", + "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", + "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.1.5", + "core-js-compat": "^3.8.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/clean-css": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", + "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/html-webpack-plugin/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "acorn": "^8.5.0" + }, + "peerDependenciesMeta": { + "acorn": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= v10.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/webpack-virtual-modules": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", + "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", + "dev": true + }, + "node_modules/@storybook/channel-postmessage": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.19.tgz", + "integrity": "sha512-E5h/itFzQ/6M08LR4kqlgqqmeO3tmavI+nUAlZrkCrotpJFNMHE2i0PQHg0TkFJrRDpYcrwD+AjUW4IwdqrisQ==", + "dev": true, + "dependencies": { + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "qs": "^6.10.0", + "telejson": "^5.3.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/channel-websocket": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.19.tgz", + "integrity": "sha512-cXKwQjIXttfdUyZlcHORelUmJ5nUKswsnCA/qy7IRWpZjD8yQJcNk1dYC+tTHDVqFgdRT89pL0hRRB1rlaaR8Q==", + "dev": true, + "dependencies": { + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "telejson": "^5.3.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/channels": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.19.tgz", + "integrity": "sha512-EwyoncFvTfmIlfsy8jTfayCxo2XchPkZk/9txipugWSmc057HdklMKPLOHWP0z5hLH0IbVIKXzdNISABm36jwQ==", + "dev": true, + "dependencies": { + "core-js": "^3.8.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/client-api": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.19.tgz", + "integrity": "sha512-OCrT5Um3FDvZnimQKwWtwsaI+5agPwq2i8YiqlofrI/NPMKp0I7DEkCGwE5IRD1Q8BIKqHcMo5tTmfYi0AxyOg==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/store": "6.4.19", + "@types/qs": "^6.9.5", + "@types/webpack-env": "^1.16.0", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "store2": "^2.12.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/client-logger": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.19.tgz", + "integrity": "sha512-zmg/2wyc9W3uZrvxaW4BfHcr40J0v7AGslqYXk9H+ERLVwIvrR4NhxQFaS6uITjBENyRDxwzfU3Va634WcmdDQ==", + "dev": true, + "dependencies": { + "core-js": "^3.8.2", + "global": "^4.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/components": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.4.19.tgz", + "integrity": "sha512-q/0V37YAJA7CNc+wSiiefeM9+3XVk8ixBNylY36QCGJgIeGQ5/79vPyUe6K4lLmsQwpmZsIq1s1Ad5+VbboeOA==", + "dev": true, + "dependencies": { + "@popperjs/core": "^2.6.0", + "@storybook/client-logger": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "@types/color-convert": "^2.0.0", + "@types/overlayscrollbars": "^1.12.0", + "@types/react-syntax-highlighter": "11.0.5", + "color-convert": "^2.0.1", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.1.3", + "memoizerific": "^1.11.3", + "overlayscrollbars": "^1.13.1", + "polished": "^4.0.5", + "prop-types": "^15.7.2", + "react-colorful": "^5.1.2", + "react-popper-tooltip": "^3.1.1", + "react-syntax-highlighter": "^13.5.3", + "react-textarea-autosize": "^8.3.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/core": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.4.19.tgz", + "integrity": "sha512-55LOQ/h/kf1jMhjN85t/pIEdIwWEG9yV7bdwv3niVvmoypCxyyjn9/QNK0RKYAeDSUtdm6FVoJ6k5CpxWz2d8w==", + "dev": true, + "dependencies": { + "@storybook/core-client": "6.4.19", + "@storybook/core-server": "6.4.19" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@storybook/builder-webpack5": "6.4.19", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0", + "webpack": "*" + }, + "peerDependenciesMeta": { + "@storybook/builder-webpack5": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/core-client": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.19.tgz", + "integrity": "sha512-rQHRZjhArPleE7/S8ZUolgzwY+hC0smSKX/3PQxO2GcebDjnJj6+iSV3h+aSMHMmTdoCQvjYw9aBpT8scuRe+A==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channel-websocket": "6.4.19", + "@storybook/client-api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/preview-web": "6.4.19", + "@storybook/store": "6.4.19", + "@storybook/ui": "6.4.19", + "airbnb-js-shims": "^2.2.1", + "ansi-to-html": "^0.6.11", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "unfetch": "^4.2.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0", + "webpack": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/core-common": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.19.tgz", + "integrity": "sha512-X1pJJkO48DFxl6iyEemIKqRkJ7j9/cBh3BRBUr+xZHXBvnD0GKDXIocwh0PjSxSC6XSu3UCQnqtKi3PbjRl8Dg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-proposal-export-default-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.12", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@babel/register": "^7.12.1", + "@storybook/node-logger": "6.4.19", + "@storybook/semver": "^7.3.2", + "@types/node": "^14.0.10", + "@types/pretty-hrtime": "^1.0.0", + "babel-loader": "^8.0.0", + "babel-plugin-macros": "^3.0.1", + "babel-plugin-polyfill-corejs3": "^0.1.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "express": "^4.17.1", + "file-system-cache": "^1.0.5", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "handlebars": "^4.7.7", + "interpret": "^2.2.0", + "json5": "^2.1.3", + "lazy-universal-dotenv": "^3.0.1", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "slash": "^3.0.0", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/core-common/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", + "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@storybook/core-common/node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@storybook/core-common/node_modules/@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/core-common/node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/core-common/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/core-common/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/core-common/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/core-common/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/core-common/node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/@storybook/core-common/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", + "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.1.5", + "core-js-compat": "^3.8.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@storybook/core-common/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/@storybook/core-common/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/core-common/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/core-common/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@storybook/core-common/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-common/node_modules/find-cache-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-common/node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-common/node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", + "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/@storybook/core-common/node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/core-common/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/core-common/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/core-common/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/core-common/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/@storybook/core-common/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/core-common/node_modules/loader-utils/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@storybook/core-common/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-common/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@storybook/core-common/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/@storybook/core-common/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@storybook/core-common/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/core-common/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-common/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/core-common/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@storybook/core-common/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@storybook/core-common/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/core-common/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/core-common/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/@storybook/core-common/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@storybook/core-common/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/core-common/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@storybook/core-common/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/@storybook/core-common/node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@storybook/core-common/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-common/node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/@storybook/core-common/node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/@storybook/core-common/node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@storybook/core-common/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/@storybook/core-common/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@storybook/core-events": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.19.tgz", + "integrity": "sha512-KICzUw6XVQUJzFSCXfvhfHAuyhn4Q5J4IZEfuZkcGJS4ODkrO6tmpdYE5Cfr+so95Nfp0ErWiLUuodBsW9/rtA==", + "dev": true, + "dependencies": { + "core-js": "^3.8.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/core-server": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.19.tgz", + "integrity": "sha512-bKsUB9f7hl5ya2JXxpIrErmbDQjoH39FVbzYZWjMo4t/b7+Xyi6vYadwyWcqlpUQmis09ZaSMv8L/Tw0TuwLAA==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.3", + "@storybook/builder-webpack4": "6.4.19", + "@storybook/core-client": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/csf-tools": "6.4.19", + "@storybook/manager-webpack4": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@types/node": "^14.0.10", + "@types/node-fetch": "^2.5.7", + "@types/pretty-hrtime": "^1.0.0", + "@types/webpack": "^4.41.26", + "better-opn": "^2.1.1", + "boxen": "^5.1.2", + "chalk": "^4.1.0", + "cli-table3": "^0.6.1", + "commander": "^6.2.1", + "compression": "^1.7.4", + "core-js": "^3.8.2", + "cpy": "^8.1.2", + "detect-port": "^1.3.0", + "express": "^4.17.1", + "file-system-cache": "^1.0.5", + "fs-extra": "^9.0.1", + "globby": "^11.0.2", + "ip": "^1.1.5", + "lodash": "^4.17.21", + "node-fetch": "^2.6.1", + "pretty-hrtime": "^1.0.3", + "prompts": "^2.4.0", + "regenerator-runtime": "^0.13.7", + "serve-favicon": "^2.5.0", + "slash": "^3.0.0", + "telejson": "^5.3.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "watchpack": "^2.2.0", + "webpack": "4", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@storybook/builder-webpack5": "6.4.19", + "@storybook/manager-webpack5": "6.4.19", + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@storybook/builder-webpack5": { + "optional": true + }, + "@storybook/manager-webpack5": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/core-server/node_modules/@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/core-server/node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/core-server/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/core-server/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/core-server/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/core-server/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/core-server/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/@storybook/core-server/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/core-server/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/core-server/node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/core-server/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@storybook/core-server/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-server/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-server/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/core-server/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/core-server/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/core-server/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@storybook/core-server/node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/@storybook/core-server/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/core-server/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-server/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@storybook/core-server/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/@storybook/core-server/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@storybook/core-server/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/core-server/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-server/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/core-server/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/core-server/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@storybook/core-server/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@storybook/core-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@storybook/core-server/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/core-server/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/@storybook/core-server/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@storybook/core-server/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/core-server/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@storybook/core-server/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/@storybook/core-server/node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/core-server/node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/@storybook/core-server/node_modules/webpack/node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/@storybook/core-server/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/@storybook/core-server/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@storybook/csf": { + "version": "0.0.2--canary.87bc651.0", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.2--canary.87bc651.0.tgz", + "integrity": "sha512-ajk1Uxa+rBpFQHKrCcTmJyQBXZ5slfwHVEaKlkuFaW77it8RgbPJp/ccna3sgoi8oZ7FkkOyvv1Ve4SmwFqRqw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/@storybook/csf-tools": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.19.tgz", + "integrity": "sha512-gf/zRhGoAVsFwSyV2tc+jeJfZQkxF6QsaZgbUSe24/IUvGFCT/PS/jZq1qy7dECAwrTOfykgu8juyBtj6WhWyw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/generator": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/plugin-transform-react-jsx": "^7.12.12", + "@babel/preset-env": "^7.12.11", + "@babel/traverse": "^7.12.11", + "@babel/types": "^7.12.11", + "@mdx-js/mdx": "^1.6.22", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "fs-extra": "^9.0.1", + "global": "^4.4.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.21", + "prettier": ">=2.2.1 <=2.3.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/csf-tools/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/manager-webpack4": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.19.tgz", + "integrity": "sha512-R8ugZjTYqXvlc6gDOcw909L65sIleOmIJLZR+N6/H85MivGXHu39jOwONqB7tVACufRty4FNecn8tEiQL2SAKA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.4.19", + "@storybook/core-client": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/theming": "6.4.19", + "@storybook/ui": "6.4.19", + "@types/node": "^14.0.10", + "@types/webpack": "^4.41.26", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^3.6.0", + "express": "^4.17.1", + "file-loader": "^6.2.0", + "file-system-cache": "^1.0.5", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^4.0.0", + "node-fetch": "^2.6.1", + "pnp-webpack-plugin": "1.6.4", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^1.3.0", + "telejson": "^5.3.2", + "terser-webpack-plugin": "^4.2.3", + "ts-dedent": "^2.0.0", + "url-loader": "^4.1.1", + "util-deprecate": "^1.0.2", + "webpack": "4", + "webpack-dev-middleware": "^3.7.3", + "webpack-virtual-modules": "^0.2.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/css-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "dependencies": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "dependencies": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "dependencies": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "dependencies": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack/node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack/node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/webpack/node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/@storybook/manager-webpack4/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/@storybook/manager-webpack4/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@storybook/manager-webpack5": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack5/-/manager-webpack5-6.4.19.tgz", + "integrity": "sha512-hVjWhWAOgWaymBy0HeRskN+MfKLpqLP4Txfw+3Xqg1qplgexV0w2O4BQrS/SNEH4V/1qF9h8XTsk3L3oQIj3Mg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.4.19", + "@storybook/core-client": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/theming": "6.4.19", + "@storybook/ui": "6.4.19", + "@types/node": "^14.0.10", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "express": "^4.17.1", + "file-system-cache": "^1.0.5", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^5.0.0", + "node-fetch": "^2.6.1", + "process": "^0.11.10", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^2.0.0", + "telejson": "^5.3.2", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-virtual-modules": "^0.4.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@storybook/manager-webpack5/node_modules/@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "node_modules/@storybook/manager-webpack5/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "optional": true, + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/clean-css": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.27.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@storybook/manager-webpack5/node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "acorn": "^8.5.0" + }, + "peerDependenciesMeta": { + "acorn": { + "optional": true + } + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/@storybook/manager-webpack5/node_modules/webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= v10.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/@storybook/manager-webpack5/node_modules/webpack-virtual-modules": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", + "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", + "dev": true + }, + "node_modules/@storybook/node-logger": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.19.tgz", + "integrity": "sha512-hO2Aar3PgPnPtNq2fVgiuGlqo3EEVR6TKVBXMq7foL3tN2k4BQFKLDHbm5qZQQntyYKurKsRUGKPJFPuI1ov/w==", + "dev": true, + "dependencies": { + "@types/npmlog": "^4.1.2", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "npmlog": "^5.0.1", + "pretty-hrtime": "^1.0.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/node-logger/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/node-logger/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/node-logger/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/node-logger/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/postinstall": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.4.19.tgz", + "integrity": "sha512-/0tHHxyIV82zt1rw4BW70GmrQbDVu9IJPAxOqFzGjC1fNojwJ53mK6FfUsOzbhG5mWk5p0Ip5+zr74moP119AA==", + "dev": true, + "dependencies": { + "core-js": "^3.8.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + } + }, + "node_modules/@storybook/preview-web": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.19.tgz", + "integrity": "sha512-jqltoBv5j7lvnxEfV9w8dLX9ASWGuvgz97yg8Yo5FqkftEwrHJenyvMGcTgDJKJPorF+wiz/9aIqnmd3LCAcZQ==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/store": "6.4.19", + "ansi-to-html": "^0.6.11", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "unfetch": "^4.2.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/router": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.4.19.tgz", + "integrity": "sha512-KWWwIzuyeEIWVezkCihwY2A76Il9tUNg0I410g9qT7NrEsKyqXGRYOijWub7c1GGyNjLqz0jtrrehtixMcJkuA==", + "dev": true, + "dependencies": { + "@storybook/client-logger": "6.4.19", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "history": "5.0.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "react-router": "^6.0.0", + "react-router-dom": "^6.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "dependencies": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/semver/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/semver/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/semver/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@storybook/semver/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/source-loader": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.19.tgz", + "integrity": "sha512-XqTsqddRglvfW7mhyjwoqd/B8L6samcBehhO0OEbsFp6FPWa9eXuObCxtRYIcjcSIe+ksbW3D/54ppEs1L/g1Q==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "estraverse": "^5.2.0", + "global": "^4.4.0", + "loader-utils": "^2.0.0", + "lodash": "^4.17.21", + "prettier": ">=2.2.1 <=2.3.0", + "regenerator-runtime": "^0.13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/store": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.4.19.tgz", + "integrity": "sha512-N9/ZjemRHGfT3InPIbqQqc6snkcfnf3Qh9oOr0smbfaVGJol//KOX65kzzobtzFcid0WxtTDZ3HmgFVH+GvuhQ==", + "dev": true, + "dependencies": { + "@storybook/addons": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "slash": "^3.0.0", + "stable": "^0.1.8", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/theming": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.19.tgz", + "integrity": "sha512-V4pWmTvAxmbHR6B3jA4hPkaxZPyExHvCToy7b76DpUTpuHihijNDMAn85KhOQYIeL9q14zP/aiz899tOHsOidg==", + "dev": true, + "dependencies": { + "@emotion/core": "^10.1.1", + "@emotion/is-prop-valid": "^0.8.6", + "@emotion/styled": "^10.0.27", + "@storybook/client-logger": "6.4.19", + "core-js": "^3.8.2", + "deep-object-diff": "^1.1.0", + "emotion-theming": "^10.0.27", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "polished": "^4.0.5", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@storybook/ui": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.19.tgz", + "integrity": "sha512-gFwdn5LA2U6oQ4bfUFLyHZnNasGQ01YVdwjbi+l6yjmnckBNtZfJoVTZ1rzGUbxSE9rK48InJRU+latTsr7xAg==", + "dev": true, + "dependencies": { + "@emotion/core": "^10.1.1", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/theming": "6.4.19", + "copy-to-clipboard": "^3.3.1", + "core-js": "^3.8.2", + "core-js-pure": "^3.8.2", + "downshift": "^6.0.15", + "emotion-theming": "^10.0.27", + "fuse.js": "^3.6.1", + "global": "^4.4.0", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.1.3", + "memoizerific": "^1.11.3", + "polished": "^4.0.5", + "qs": "^6.10.0", + "react-draggable": "^4.4.3", + "react-helmet-async": "^1.0.7", + "react-sizeme": "^3.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "store2": "^2.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@ts-morph/common": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.12.3.tgz", + "integrity": "sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.7", + "minimatch": "^3.0.4", + "mkdirp": "^1.0.4", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/color-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz", + "integrity": "sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==", + "dev": true, + "dependencies": { + "@types/color-name": "*" + } + }, + "node_modules/@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "node_modules/@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", + "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==", + "dev": true + }, + "node_modules/@types/is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "node_modules/@types/mdast": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", + "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "dev": true, + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "16.11.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.33.tgz", + "integrity": "sha512-0PJ0vg+JyU0MIan58IOIFRtSvsb7Ri+7Wltx2qAg94eMOrpg4+uuP3aUHCpxXc1i0jCXiC+zIamSZh3l9AbcQA==", + "dev": true + }, + "node_modules/@types/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/npmlog": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", + "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", + "dev": true + }, + "node_modules/@types/overlayscrollbars": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@types/overlayscrollbars/-/overlayscrollbars-1.12.1.tgz", + "integrity": "sha512-V25YHbSoKQN35UasHf0EKD9U2vcmexRSp78qa8UglxFH8H3D+adEa9zGZwrqpH4TdvqeMrgMqVqsLB4woAryrQ==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", + "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", + "dev": true + }, + "node_modules/@types/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", + "dev": true, + "peer": true + }, + "node_modules/@types/pretty-hrtime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz", + "integrity": "sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==", + "dev": true + }, + "node_modules/@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/react": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", + "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-syntax-highlighter": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.5.tgz", + "integrity": "sha512-VIOi9i2Oj5XsmWWoB72p3KlZoEbdRAcechJa8Ztebw7bDl2YmR+odxIqhtJGp1q2EozHs02US+gzxJ9nuf56qg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react/node_modules/csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, + "node_modules/@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/tapable": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", + "dev": true + }, + "node_modules/@types/uglify-js": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", + "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/@types/uglify-js/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", + "dev": true + }, + "node_modules/@types/webpack": { + "version": "4.41.32", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", + "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@types/webpack-env": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.3.tgz", + "integrity": "sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==", + "dev": true + }, + "node_modules/@types/webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" + } + }, + "node_modules/@types/webpack/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "dependencies": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-code-frame/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-code-frame/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-code-frame/node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-module-context/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-module-context/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@webassemblyjs/wast-parser/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webcomponents/custom-elements": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webcomponents/custom-elements/-/custom-elements-1.5.0.tgz", + "integrity": "sha512-c+7jPQCs9h/BYVcZ2Kna/3tsl3A/9EyXfvWjp5RiTDm1OpTcbZaCa1z4RNcTe/hUtXaqn64JjNW1yrWT+rZ8gg==", + "dev": true + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "dev": true, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.0.tgz", + "integrity": "sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/airbnb-js-shims": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/airbnb-js-shims/-/airbnb-js-shims-2.2.1.tgz", + "integrity": "sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "array.prototype.flatmap": "^1.2.1", + "es5-shim": "^4.5.13", + "es6-shim": "^0.35.5", + "function.prototype.name": "^1.1.0", + "globalthis": "^1.0.0", + "object.entries": "^1.1.0", + "object.fromentries": "^2.0.0 || ^1.0.0", + "object.getownpropertydescriptors": "^2.0.3", + "object.values": "^1.1.0", + "promise.allsettled": "^1.0.0", + "promise.prototype.finally": "^3.1.0", + "string.prototype.matchall": "^4.0.0 || ^3.0.1", + "string.prototype.padend": "^3.0.0", + "string.prototype.padstart": "^3.0.0", + "symbol.prototype.description": "^1.0.0" + } + }, + "node_modules/ajv": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", + "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ansi-styles/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/ansi-to-html": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz", + "integrity": "sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ==", + "dev": true, + "dependencies": { + "entities": "^2.0.0" + }, + "bin": { + "ansi-to-html": "bin/ansi-to-html" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/apache-crypt": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.5.tgz", + "integrity": "sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg==", + "dev": true, + "dependencies": { + "unix-crypt-td-js": "^1.1.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/apache-md5": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.7.tgz", + "integrity": "sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/app-root-dir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", + "integrity": "sha1-OBh+wt6nV3//Az/8sSFyaS/24Rg=", + "dev": true + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", + "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.4.tgz", + "integrity": "sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-transform": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/ast-transform/-/ast-transform-0.0.0.tgz", + "integrity": "sha1-dJRAWIh9goPhidlUYAlHvJj+AGI=", + "dev": true, + "dependencies": { + "escodegen": "~1.2.0", + "esprima": "~1.0.4", + "through": "~2.3.4" + } + }, + "node_modules/ast-transform/node_modules/escodegen": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.2.0.tgz", + "integrity": "sha1-Cd55Z3kcyVi3+Jot220jRRrzJ+E=", + "dev": true, + "dependencies": { + "esprima": "~1.0.4", + "estraverse": "~1.5.0", + "esutils": "~1.0.0" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.4.0" + }, + "optionalDependencies": { + "source-map": "~0.1.30" + } + }, + "node_modules/ast-transform/node_modules/esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ast-transform/node_modules/estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ast-transform/node_modules/esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-transform/node_modules/source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ast-types": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.7.8.tgz", + "integrity": "sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", + "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.19.1", + "caniuse-lite": "^1.0.30001297", + "fraction.js": "^4.1.2", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axe-core": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", + "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-jest/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-jest/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/babel-jest/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-jest/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-jest/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-jest/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", + "integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==", + "dev": true, + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-loader/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/babel-loader/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/babel-loader/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/babel-loader/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-apply-mdx-type-prop": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", + "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "7.10.4", + "@mdx-js/util": "1.6.22" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@babel/core": "^7.11.6" + } + }, + "node_modules/babel-plugin-apply-mdx-type-prop/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-emotion": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz", + "integrity": "sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/serialize": "^0.11.16", + "babel-plugin-macros": "^2.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^1.0.5", + "find-root": "^1.1.0", + "source-map": "^0.5.7" + } + }, + "node_modules/babel-plugin-emotion/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-plugin-extract-import-names": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", + "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "7.10.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/babel-plugin-extract-import-names/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "node_modules/babel-plugin-macros/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz", + "integrity": "sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.2.4", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz", + "integrity": "sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.2.2", + "core-js-compat": "^3.16.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz", + "integrity": "sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.2.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "peer": true, + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "node_modules/batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=", + "dev": true + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=", + "dev": true + }, + "node_modules/better-opn": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", + "integrity": "sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==", + "dev": true, + "dependencies": { + "open": "^7.0.3" + }, + "engines": { + "node": ">8.0.0" + } + }, + "node_modules/better-opn/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/bonjour/node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "node_modules/bootstrap": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", + "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + }, + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.1" + } + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boxen/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brfs": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brfs/-/brfs-2.0.2.tgz", + "integrity": "sha512-IrFjVtwu4eTJZyu8w/V2gxU7iLTtcHih67sgEdzrhjLBMHp2uYefUBfdM4k2UvcuWMgV7PQDZHSLeNWnLFKWVQ==", + "dev": true, + "dependencies": { + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^3.0.2", + "through2": "^2.0.0" + }, + "bin": { + "brfs": "bin/cmd.js" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/brotli": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.2.tgz", + "integrity": "sha1-UlqcrU/LqWR119OI9q7LE+7VL0Y=", + "dev": true, + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "dependencies": { + "resolve": "1.1.7" + } + }, + "node_modules/browser-resolve/node_modules/resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-optional/-/browserify-optional-1.0.1.tgz", + "integrity": "sha1-HhNyLP3g2F8SFnbCpyztUzoBiGk=", + "dev": true, + "dependencies": { + "ast-transform": "0.0.0", + "ast-types": "^0.7.0", + "browser-resolve": "^1.8.1" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", + "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001286", + "electron-to-chromium": "^1.4.17", + "escalade": "^3.1.1", + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "node_modules/builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz", + "integrity": "sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==", + "dev": true, + "dependencies": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "node_modules/callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001312", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", + "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "node_modules/capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "dependencies": { + "rsvp": "^4.8.4" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ccount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", + "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/charcodes": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", + "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dev": true, + "dependencies": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", + "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "css-what": "^5.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0", + "domutils": "^2.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cheerio/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chromatic": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-6.5.2.tgz", + "integrity": "sha512-TiAJAF2we4BUflKEfiXs2CiBFvW6yNWkiXKIuBtlSLl2fj1cuueXlV5dYVVoyMDfzTX5JdEn/Bd5CVlpKCeY6A==", + "dev": true, + "bin": { + "chroma": "bin/main.cjs", + "chromatic": "bin/main.cjs", + "chromatic-cli": "bin/main.cjs" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/circular-dependency-plugin": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz", + "integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "webpack": ">=4.0.1" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true, + "peer": true + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", + "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "colors": "1.4.0" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "peer": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/code-block-writer": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.0.tgz", + "integrity": "sha512-GEqWvEWWsOvER+g9keO4ohFoD3ymwyCnqY3hoTr7GZipYFwEhMHJw+TtV0rfgRhNImM6QWZGO2XYjlJVyYT62w==", + "dev": true, + "dependencies": { + "tslib": "2.3.1" + } + }, + "node_modules/collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true, + "peer": true + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colord": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", + "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", + "dev": true + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-concurrently/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/copy-concurrently/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/copy-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", + "integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==", + "dev": true, + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.0.1.tgz", + "integrity": "sha512-14gHKKdYIxF84jCEgPgYXCPpldbwpxxLbCmA7LReY7gvbaT555DgeBWBgBZM116tv/fO6RRJrsivBqRyRlukhw==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.5", + "glob-parent": "^6.0.0", + "globby": "^11.0.3", + "normalize-path": "^3.0.0", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/core-js": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.0.tgz", + "integrity": "sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", + "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", + "dev": true, + "dependencies": { + "browserslist": "^4.19.1", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-js-pure": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz", + "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cp-file": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz", + "integrity": "sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "nested-error-stacks": "^2.0.0", + "p-event": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cp-file/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cp-file/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/cpy": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/cpy/-/cpy-8.1.2.tgz", + "integrity": "sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg==", + "dev": true, + "dependencies": { + "arrify": "^2.0.1", + "cp-file": "^7.0.0", + "globby": "^9.2.0", + "has-glob": "^1.0.0", + "junk": "^3.1.0", + "nested-error-stacks": "^2.1.0", + "p-all": "^2.1.0", + "p-filter": "^2.1.0", + "p-map": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cpy/node_modules/@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/cpy/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "dependencies": { + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cpy/node_modules/fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "dependencies": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/cpy/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/cpy/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cpy/node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/cpy/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/cpy/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cpy/node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cpy/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cpy/node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cpy/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cpy/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/critters": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.12.tgz", + "integrity": "sha512-ujxKtKc/mWpjrOKeaACTaQ1aP0O31M0ZPWhfl85jZF1smPU4Ivb9va5Ox2poif4zVJQQo0LCFlzGtEZAsCAPcw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^4.1.3", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "postcss": "^8.3.7", + "pretty-bytes": "^5.3.0" + } + }, + "node_modules/critters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/critters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/critters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/critters/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/critters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/cross-spawn/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==", + "dev": true + }, + "node_modules/css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "node_modules/css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5" + }, + "bin": { + "css-blank-pseudo": "cli.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/css-blank-pseudo/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/css-blank-pseudo/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-blank-pseudo/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-declaration-sorter": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz", + "integrity": "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==", + "dev": true, + "dependencies": { + "timsort": "^0.3.0" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "bin": { + "css-has-pseudo": "cli.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/css-has-pseudo/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-has-pseudo/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/css-has-pseudo/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/css-has-pseudo/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", + "integrity": "sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.0.2.tgz", + "integrity": "sha512-B3I5e17RwvKPJwsxjjWcdgpU/zqylzK1bPVghcmpFHRL48DXiBgrtqz1BJsn68+t/zzaLp9kYAaEDvQ7GyanFQ==", + "dev": true, + "dependencies": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "p-limit": "^3.0.2", + "postcss": "^8.3.5", + "schema-utils": "^3.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "dependencies": { + "css": "^2.0.0" + } + }, + "node_modules/css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5" + }, + "bin": { + "css-prefers-color-scheme": "cli.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/css-prefers-color-scheme/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/css-prefers-color-scheme/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-prefers-color-scheme/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==", + "dev": true + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz", + "integrity": "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==", + "dev": true, + "dependencies": { + "cssnano-preset-default": "^5.1.12", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.1.12", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz", + "integrity": "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^6.0.3", + "cssnano-utils": "^3.0.2", + "postcss-calc": "^8.2.0", + "postcss-colormin": "^5.2.5", + "postcss-convert-values": "^5.0.4", + "postcss-discard-comments": "^5.0.3", + "postcss-discard-duplicates": "^5.0.3", + "postcss-discard-empty": "^5.0.3", + "postcss-discard-overridden": "^5.0.4", + "postcss-merge-longhand": "^5.0.6", + "postcss-merge-rules": "^5.0.6", + "postcss-minify-font-values": "^5.0.4", + "postcss-minify-gradients": "^5.0.6", + "postcss-minify-params": "^5.0.5", + "postcss-minify-selectors": "^5.1.3", + "postcss-normalize-charset": "^5.0.3", + "postcss-normalize-display-values": "^5.0.3", + "postcss-normalize-positions": "^5.0.4", + "postcss-normalize-repeat-style": "^5.0.4", + "postcss-normalize-string": "^5.0.4", + "postcss-normalize-timing-functions": "^5.0.3", + "postcss-normalize-unicode": "^5.0.4", + "postcss-normalize-url": "^5.0.5", + "postcss-normalize-whitespace": "^5.0.4", + "postcss-ordered-values": "^5.0.5", + "postcss-reduce-initial": "^5.0.3", + "postcss-reduce-transforms": "^5.0.4", + "postcss-svgo": "^5.0.4", + "postcss-unique-selectors": "^5.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz", + "integrity": "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "2.6.19", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", + "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==", + "dev": true + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dash-ast": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-2.0.1.tgz", + "integrity": "sha512-5TXltWJGc+RdnabUGzhRae1TRq6m4gr+3K2wQX0is5/F2yS6MJXJvLyI3ErAnsAXuJoGqvfVD5icRgim07DrxQ==", + "dev": true + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/data-urls/node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decache": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/decache/-/decache-4.6.1.tgz", + "integrity": "sha512-ohApBM8u9ygepJCjgBrEZSSxPjc0T/PJkD+uNyxXPkqudyUpdXpwJYp0VISm2WrPVzASU6DZyIi6BWdyw7uJ2Q==", + "dev": true, + "dependencies": { + "callsite": "^1.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true, + "peer": true + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deep-object-diff": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.7.tgz", + "integrity": "sha512-QkgBca0mL08P6HiOjoqvmm6xOAl2W6CT2+34Ljhg0OeFan8cwlcdq8jrLKsBBuUFAZLsN5b6y491KdKEoSo9lg==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "node_modules/del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/del/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/del/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/detab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", + "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "dev": true, + "dependencies": { + "repeat-string": "^1.5.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "dev": true, + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "dependencies": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", + "dev": true + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "node_modules/dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz", + "integrity": "sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg==", + "dev": true, + "engines": [ + "node >=0.2.6" + ], + "bin": { + "dottojs": "bin/dot-packer" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/downshift": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.7.tgz", + "integrity": "sha512-cVprZg/9Lvj/uhYRxELzlu1aezRcgPWBjTvspiGTVEU64gF5pRdSRKFVLcxqsZC637cLAGMbL40JavEfWnqgNg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.14.8", + "compute-scroll-into-view": "^1.0.17", + "prop-types": "^15.7.2", + "react-is": "^17.0.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "react": ">=16.12.0" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.4.71", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz", + "integrity": "sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==", + "dev": true + }, + "node_modules/element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "dev": true, + "dependencies": { + "batch-processor": "1.0.0" + } + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/emotion-theming": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emotion-theming/-/emotion-theming-10.3.0.tgz", + "integrity": "sha512-mXiD2Oj7N9b6+h/dC6oLf9hwxbtKHQjoIqtodEyL8CpkN4F3V4IK/BT4D0C7zSs4BBFOu4UlPJbvvBLa88SGEA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.5.5", + "@emotion/weak-memoize": "0.2.5", + "hoist-non-react-statics": "^3.3.0" + }, + "peerDependencies": { + "@emotion/core": "^10.0.27", + "react": ">=16.3.0" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", + "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.0", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@socket.io/base64-arraybuffer": "~1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "dependencies": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "node_modules/es5-shim": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.5.tgz", + "integrity": "sha512-vfQ4UAai8szn0sAubCy97xnZ4sJVDD1gt/Grn736hg8D7540wemIb1YPrYZSTqlM2H69EQX1or4HU/tSwRTI3w==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "node_modules/es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } + }, + "node_modules/es6-set/node_modules/es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/es6-shim": { + "version": "0.35.6", + "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz", + "integrity": "sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA==", + "dev": true + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/esbuild": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.8.tgz", + "integrity": "sha512-A4af7G7YZLfG5OnARJRMtlpEsCkq/zHZQXewgPA864l9D6VjjbH1SuFYK/OSV6BtHwDGkdwyRrX0qQFLnMfUcw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "optionalDependencies": { + "esbuild-android-arm64": "0.13.8", + "esbuild-darwin-64": "0.13.8", + "esbuild-darwin-arm64": "0.13.8", + "esbuild-freebsd-64": "0.13.8", + "esbuild-freebsd-arm64": "0.13.8", + "esbuild-linux-32": "0.13.8", + "esbuild-linux-64": "0.13.8", + "esbuild-linux-arm": "0.13.8", + "esbuild-linux-arm64": "0.13.8", + "esbuild-linux-mips64le": "0.13.8", + "esbuild-linux-ppc64le": "0.13.8", + "esbuild-netbsd-64": "0.13.8", + "esbuild-openbsd-64": "0.13.8", + "esbuild-sunos-64": "0.13.8", + "esbuild-windows-32": "0.13.8", + "esbuild-windows-64": "0.13.8", + "esbuild-windows-arm64": "0.13.8" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.8.tgz", + "integrity": "sha512-AilbChndywpk7CdKkNSZ9klxl+9MboLctXd9LwLo3b0dawmOF/i/t2U5d8LM6SbT1Xw36F8yngSUPrd8yPs2RA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/esbuild-darwin-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.8.tgz", + "integrity": "sha512-b6sdiT84zV5LVaoF+UoMVGJzR/iE2vNUfUDfFQGrm4LBwM/PWXweKpuu6RD9mcyCq18cLxkP6w/LD/w9DtX3ng==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.8.tgz", + "integrity": "sha512-R8YuPiiJayuJJRUBG4H0VwkEKo6AvhJs2m7Tl0JaIer3u1FHHXwGhMxjJDmK+kXwTFPriSysPvcobXC/UrrZCQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.8.tgz", + "integrity": "sha512-zBn6urrn8FnKC+YSgDxdof9jhPCeU8kR/qaamlV4gI8R3KUaUK162WYM7UyFVAlj9N0MyD3AtB+hltzu4cysTw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.8.tgz", + "integrity": "sha512-pWW2slN7lGlkx0MOEBoUGwRX5UgSCLq3dy2c8RIOpiHtA87xAUpDBvZK10MykbT+aMfXc0NI2lu1X+6kI34xng==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/esbuild-linux-32": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.8.tgz", + "integrity": "sha512-T0I0ueeKVO/Is0CAeSEOG9s2jeNNb8jrrMwG9QBIm3UU18MRB60ERgkS2uV3fZ1vP2F8i3Z2e3Zju4lg9dhVmw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.8.tgz", + "integrity": "sha512-Bm8SYmFtvfDCIu9sjKppFXzRXn2BVpuCinU1ChTuMtdKI/7aPpXIrkqBNOgPTOQO9AylJJc1Zw6EvtKORhn64w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.8.tgz", + "integrity": "sha512-4/HfcC40LJ4GPyboHA+db0jpFarTB628D1ifU+/5bunIgY+t6mHkJWyxWxAAE8wl/ZIuRYB9RJFdYpu1AXGPdg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.8.tgz", + "integrity": "sha512-X4pWZ+SL+FJ09chWFgRNO3F+YtvAQRcWh0uxKqZSWKiWodAB20flsW/OWFYLXBKiVCTeoGMvENZS/GeVac7+tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.8.tgz", + "integrity": "sha512-o7e0D+sqHKT31v+mwFircJFjwSKVd2nbkHEn4l9xQ1hLR+Bv8rnt3HqlblY3+sBdlrOTGSwz0ReROlKUMJyldA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.8.tgz", + "integrity": "sha512-eZSQ0ERsWkukJp2px/UWJHVNuy0lMoz/HZcRWAbB6reoaBw7S9vMzYNUnflfL3XA6WDs+dZn3ekHE4Y2uWLGig==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.11.tgz", + "integrity": "sha512-DoThrkzunZ1nfRGoDN6REwmo8ZZWHd2ztniPVIR5RMw/Il9wiWEYBahb8jnMzQaSOxBsGp0PbyJeVLTUatnlcw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.8.tgz", + "integrity": "sha512-gZX4kP7gVvOrvX0ZwgHmbuHczQUwqYppxqtoyC7VNd80t5nBHOFXVhWo2Ad/Lms0E8b+wwgI/WjZFTCpUHOg9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ] + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.8.tgz", + "integrity": "sha512-afzza308X4WmcebexbTzAgfEWt9MUkdTvwIa8xOu4CM2qGbl2LanqEl8/LUs8jh6Gqw6WsicEK52GPrS9wvkcw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/esbuild-sunos-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.8.tgz", + "integrity": "sha512-mWPZibmBbuMKD+LDN23LGcOZ2EawMYBONMXXHmbuxeT0XxCNwadbCVwUQ/2p5Dp5Kvf6mhrlIffcnWOiCBpiVw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ] + }, + "node_modules/esbuild-wasm": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.13.8.tgz", + "integrity": "sha512-UbD+3nloiSpJWXTCInZQrqPe8Y+RLfDkY/5kEHiXsw/lmaEvibe69qTzQu16m5R9je/0bF7VYQ5jaEOq0z9lLA==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.8.tgz", + "integrity": "sha512-QsZ1HnWIcnIEApETZWw8HlOhDSWqdZX2SylU7IzGxOYyVcX7QI06ety/aDcn437mwyO7Ph4RrbhB+2ntM8kX8A==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.8.tgz", + "integrity": "sha512-76Fb57B9eE/JmJi1QmUW0tRLQZfGo0it+JeYoCDTSlbTn7LV44ecOHIMJSSgZADUtRMWT9z0Kz186bnaB3amSg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.8.tgz", + "integrity": "sha512-HW6Mtq5eTudllxY2YgT62MrVcn7oq2o8TAoAvDUhyiEmRmDY8tPwAhb1vxw5/cdkbukM3KdMYtksnUhF/ekWeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-is-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-is-function/-/estree-is-function-1.0.0.tgz", + "integrity": "sha512-nSCWn1jkSq2QAtkaVLJZY2ezwcFO161HVc174zL1KPW3RJ+O6C3eJb8Nx7OXzvhoEv+nLgSR1g71oWUHUDTrJA==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/event-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", + "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.1", + "from": "^0.1.7", + "map-stream": "0.0.7", + "pause-stream": "^0.0.11", + "split": "^1.0.1", + "stream-combiner": "^0.2.2", + "through": "^2.3.8" + } + }, + "node_modules/eventemitter-asyncresource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", + "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/eventsource": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", + "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "dev": true, + "dependencies": { + "original": "^1.0.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/exec-sh": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", + "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", + "dev": true + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/expect/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/expect/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/expect/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/expect/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/expect/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/expect/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/express": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fancy-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-2.0.0.tgz", + "integrity": "sha512-9CzxZbACXMUXW13tS0tI8XsGGmxWzO2DmYrGuBJOJ8k8q2K7hwfJA5qHjuPPe8wtsco33YR9wc+Rlr5wYFvhSA==", + "dev": true, + "dependencies": { + "color-support": "^1.1.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "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.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "dev": true, + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/file-system-cache": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-1.0.5.tgz", + "integrity": "sha1-hCWbNqK7uNPW6xAh0xMv/mTP/08=", + "dev": true, + "dependencies": { + "bluebird": "^3.3.5", + "fs-extra": "^0.30.0", + "ramda": "^0.21.0" + } + }, + "node_modules/file-system-cache/node_modules/fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/file-system-cache/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/file-system-cache/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findit2": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz", + "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=", + "dev": true, + "engines": { + "node": ">=0.8.22" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", + "dev": true + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/flush-write-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/flush-write-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/flush-write-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", + "integrity": "sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.5.5", + "chalk": "^2.4.1", + "micromatch": "^3.1.10", + "minimatch": "^3.0.4", + "semver": "^5.6.0", + "tapable": "^1.0.0", + "worker-rpc": "^0.1.0" + }, + "engines": { + "node": ">=6.11.5", + "yarn": ">=1.0.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz", + "integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "dev": true + }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "node_modules/fs-write-stream-atomic/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/fs-write-stream-atomic/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/fs-write-stream-atomic/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.2.tgz", + "integrity": "sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fuse.js": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.6.1.tgz", + "integrity": "sha512-hT9yh/tiinkmirKrlv4KWOjztdoZo1mx9Qh4KvWqC7isoXwdUY3PNWUxceF4/qO9R6riA2C29jdTOeQOIROjgw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/github-slugger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", + "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", + "dev": true + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-promise": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-3.4.0.tgz", + "integrity": "sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw==", + "dev": true, + "dependencies": { + "@types/glob": "*" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "glob": "*" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", + "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz", + "integrity": "sha1-mqqe7b/7G6OZCnsAEPtnjuAIEgc=", + "dev": true, + "dependencies": { + "is-glob": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-glob/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hast-to-hyperscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", + "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.3", + "comma-separated-tokens": "^1.0.0", + "property-information": "^5.3.0", + "space-separated-tokens": "^1.0.0", + "style-to-object": "^0.3.0", + "unist-util-is": "^4.0.0", + "web-namespaces": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", + "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", + "dev": true, + "dependencies": { + "@types/parse5": "^5.0.0", + "hastscript": "^6.0.0", + "property-information": "^5.0.0", + "vfile": "^4.0.0", + "vfile-location": "^3.2.0", + "web-namespaces": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", + "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", + "dev": true, + "dependencies": { + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^6.0.0", + "hast-util-to-parse5": "^6.0.0", + "html-void-elements": "^1.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^3.0.0", + "vfile": "^4.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/hast-util-to-parse5": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", + "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", + "dev": true, + "dependencies": { + "hast-to-hyperscript": "^9.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "dev": true, + "dependencies": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "dependencies": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "node_modules/hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/history": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.0.0.tgz", + "integrity": "sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.7.6" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "peer": true + }, + "node_modules/html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/html-minifier-terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/html-minifier-terser/node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/html-tags": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", + "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/html-void-elements": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", + "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz", + "integrity": "sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.20", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + }, + "engines": { + "node": ">=6.9" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/html-webpack-plugin/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/html-webpack-plugin/node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-auth": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-4.1.9.tgz", + "integrity": "sha512-kvPYxNGc9EKGTXvOMnTBQw2RZfuiSihK/mLw/a4pbtRueTE45S55Lw/3k5CktIf7Ak0veMKEIteDj4YkNmCzmQ==", + "dev": true, + "dependencies": { + "apache-crypt": "^1.1.2", + "apache-md5": "^1.0.6", + "bcryptjs": "^2.4.3", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/http-auth-connect": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/http-auth-connect/-/http-auth-connect-1.0.5.tgz", + "integrity": "sha512-zykAOKpVAXyzhOLm6+xyB/RtRcfN3uDfH4Al73DIfeSb6B7nr0WToLI6UyyM6ohtcLmbBPksWXzVbEDStz8ObQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz", + "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "dependencies": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/http-proxy-middleware/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-middleware/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/i18next": { + "version": "21.6.11", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.11.tgz", + "integrity": "sha512-tJ2+o0lVO+fhi8bPkCpBAeY1SgkqmQm5NzgPWCQssBrywJw98/o+Kombhty5nxQOpHtvMmsxcOopczUiH6bJxQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.12.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", + "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "dependencies": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.2.tgz", + "integrity": "sha512-DHLKJwLPNgkfwNmsuEUKSejJFbkv0FMO9SMiQbjI3n5NQuCrSIBqP66ggqyz2a6t2qEolKrMjhQ3+W/xXgUQ+Q==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.3.0", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/inside/-/inside-1.0.0.tgz", + "integrity": "sha1-20Xpk1c82z23C5gy6ChbrUZCR3A=", + "dev": true + }, + "node_modules/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "dependencies": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "dependencies": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz", + "integrity": "sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==", + "dev": true, + "dependencies": { + "is-object": "^1.0.1", + "is-window": "^1.0.2" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", + "dev": true + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-window": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz", + "integrity": "sha1-LIlspT25feRdPDMTOmXYyfVjSA0=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "peer": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "peer": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/istanbul-lib-report/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "peer": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "dependencies": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-changed-files/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-changed-files/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "peer": true, + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-changed-files/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/jest-changed-files/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-changed-files/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-changed-files/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-cli/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "peer": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-cli/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-cli/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "peer": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "peer": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "peer": true, + "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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, + "peer": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-environment-jsdom/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-environment-jsdom/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-environment-jsdom/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, + "node_modules/jest-environment-jsdom/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-jsdom/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-environment-node/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-environment-node/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-environment-node/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-environment-node/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "engines": { + "node": ">= 10.14.2" + }, + "optionalDependencies": { + "fsevents": "^2.1.2" + } + }, + "node_modules/jest-haste-map/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-haste-map/node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-haste-map/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-jasmine2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-jasmine2/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-jasmine2/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-jasmine2/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-jasmine2/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-jasmine2/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, + "peer": true, + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-mock/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-mock/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-mock/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-preset-angular": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-11.1.2.tgz", + "integrity": "sha512-qPvOP6wnLP8M01TDVSa3UC3PcDWxoj87T58mWEp5yWlWPrXBJ6rhnTEI+HPmZLyehwlK686+O/49hwFRVXFP0A==", + "dev": true, + "dependencies": { + "bs-logger": "^0.2.6", + "esbuild-wasm": "0.14.11", + "jest-environment-jsdom": "^27.0.0", + "pretty-format": "^27.0.0", + "ts-jest": "^27.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.15.0 || >=16.10.0" + }, + "optionalDependencies": { + "esbuild": "0.14.11" + }, + "peerDependencies": { + "@angular-devkit/build-angular": ">=0.1002.4", + "@angular/compiler-cli": ">=10.0.0", + "@angular/core": ">=10.0.0", + "@angular/platform-browser-dynamic": ">=10.0.0" + } + }, + "node_modules/jest-preset-angular/node_modules/esbuild": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.11.tgz", + "integrity": "sha512-xZvPtVj6yecnDeFb3KjjCM6i7B5TCAQZT77kkW/CpXTMnd6VLnRPKrUB1XHI1pSq6a4Zcy3BGueQ8VljqjDGCg==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "optionalDependencies": { + "esbuild-android-arm64": "0.14.11", + "esbuild-darwin-64": "0.14.11", + "esbuild-darwin-arm64": "0.14.11", + "esbuild-freebsd-64": "0.14.11", + "esbuild-freebsd-arm64": "0.14.11", + "esbuild-linux-32": "0.14.11", + "esbuild-linux-64": "0.14.11", + "esbuild-linux-arm": "0.14.11", + "esbuild-linux-arm64": "0.14.11", + "esbuild-linux-mips64le": "0.14.11", + "esbuild-linux-ppc64le": "0.14.11", + "esbuild-linux-s390x": "0.14.11", + "esbuild-netbsd-64": "0.14.11", + "esbuild-openbsd-64": "0.14.11", + "esbuild-sunos-64": "0.14.11", + "esbuild-windows-32": "0.14.11", + "esbuild-windows-64": "0.14.11", + "esbuild-windows-arm64": "0.14.11" + } + }, + "node_modules/jest-preset-angular/node_modules/esbuild-android-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.11.tgz", + "integrity": "sha512-6iHjgvMnC/SzDH8TefL+/3lgCjYWwAd1LixYfmz/TBPbDQlxcuSkX0yiQgcJB9k+ibZ54yjVXziIwGdlc+6WNw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-darwin-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.11.tgz", + "integrity": "sha512-olq84ikh6TiBcrs3FnM4eR5VPPlcJcdW8BnUz/lNoEWYifYQ+Po5DuYV1oz1CTFMw4k6bQIZl8T3yxL+ZT2uvQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-darwin-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.11.tgz", + "integrity": "sha512-Jj0ieWLREPBYr/TZJrb2GFH8PVzDqiQWavo1pOFFShrcmHWDBDrlDxPzEZ67NF/Un3t6sNNmeI1TUS/fe1xARg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-freebsd-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.11.tgz", + "integrity": "sha512-C5sT3/XIztxxz/zwDjPRHyzj/NJFOnakAanXuyfLDwhwupKPd76/PPHHyJx6Po6NI6PomgVp/zi6GRB8PfrOTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-freebsd-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.11.tgz", + "integrity": "sha512-y3Llu4wbs0bk4cwjsdAtVOesXb6JkdfZDLKMt+v1U3tOEPBdSu6w8796VTksJgPfqvpX22JmPLClls0h5p+L9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-linux-32": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.11.tgz", + "integrity": "sha512-Cg3nVsxArjyLke9EuwictFF3Sva+UlDTwHIuIyx8qpxRYAOUTmxr2LzYrhHyTcGOleLGXUXYsnUVwKqnKAgkcg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-linux-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.11.tgz", + "integrity": "sha512-oeR6dIrrojr8DKVrxtH3xl4eencmjsgI6kPkDCRIIFwv4p+K7ySviM85K66BN01oLjzthpUMvBVfWSJkBLeRbg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-linux-arm": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.11.tgz", + "integrity": "sha512-vcwskfD9g0tojux/ZaTJptJQU3a7YgTYsptK1y6LQ/rJmw7U5QJvboNawqM98Ca3ToYEucfCRGbl66OTNtp6KQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-linux-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.11.tgz", + "integrity": "sha512-+e6ZCgTFQYZlmg2OqLkg1jHLYtkNDksxWDBWNtI4XG4WxuOCUErLqfEt9qWjvzK3XBcCzHImrajkUjO+rRkbMg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-linux-mips64le": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.11.tgz", + "integrity": "sha512-Rrs99L+p54vepmXIb87xTG6ukrQv+CzrM8eoeR+r/OFL2Rg8RlyEtCeshXJ2+Q66MXZOgPJaokXJZb9snq28bw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-linux-ppc64le": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.11.tgz", + "integrity": "sha512-JyzziGAI0D30Vyzt0HDihp4s1IUtJ3ssV2zx9O/c+U/dhUHVP2TmlYjzCfCr2Q6mwXTeloDcLS4qkyvJtYptdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-netbsd-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.11.tgz", + "integrity": "sha512-12luoRQz+6eihKYh1zjrw0CBa2aw3twIiHV/FAfjh2NEBDgJQOY4WCEUEN+Rgon7xmLh4XUxCQjnwrvf8zhACw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-openbsd-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.11.tgz", + "integrity": "sha512-l18TZDjmvwW6cDeR4fmizNoxndyDHamGOOAenwI4SOJbzlJmwfr0jUgjbaXCUuYVOA964siw+Ix+A+bhALWg8Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-sunos-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.11.tgz", + "integrity": "sha512-bmYzDtwASBB8c+0/HVOAiE9diR7+8zLm/i3kEojUH2z0aIs6x/S4KiTuT5/0VKJ4zk69kXel1cNWlHBMkmavQg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-wasm": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.14.11.tgz", + "integrity": "sha512-9e1R6hv0hiU+BkJI2edqUuWfXUbOP2Mox+Ijl/uY1vLLlSsunkrcADqD/4Rz+VCEDzw6ecscJM+uJqR2fRmEUg==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-preset-angular/node_modules/esbuild-windows-32": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.11.tgz", + "integrity": "sha512-J1Ys5hMid8QgdY00OBvIolXgCQn1ARhYtxPnG6ESWNTty3ashtc4+As5nTrsErnv8ZGUcWZe4WzTP/DmEVX1UQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-windows-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.11.tgz", + "integrity": "sha512-h9FmMskMuGeN/9G9+LlHPAoiQk9jlKDUn9yA0MpiGzwLa82E7r1b1u+h2a+InprbSnSLxDq/7p5YGtYVO85Mlg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/jest-preset-angular/node_modules/esbuild-windows-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.11.tgz", + "integrity": "sha512-dZp7Krv13KpwKklt9/1vBFBMqxEQIO6ri7Azf8C+ob4zOegpJmha2XY9VVWP/OyQ0OWk6cEeIzMJwInRZrzBUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "dev": true, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-resolve/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-runner/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-runtime/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-runtime/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "peer": true, + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/jest-runtime/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runtime/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-runtime/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.4" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-snapshot/node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "dev": true, + "dependencies": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jest/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest/node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "peer": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "peer": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest/node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "peer": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jquery": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", + "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==", + "peer": true + }, + "node_modules/js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/junk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", + "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma": { + "version": "6.3.16", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.16.tgz", + "integrity": "sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "colors": "1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "optional": true, + "peer": true, + "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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/lazy-universal-dotenv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz", + "integrity": "sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.5.0", + "app-root-dir": "^1.0.2", + "core-js": "^3.0.4", + "dotenv": "^8.0.0", + "dotenv-expand": "^5.1.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=6.0.0", + "yarn": ">=1.0.0" + } + }, + "node_modules/less": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.1.tgz", + "integrity": "sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^1.10.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^2.5.2", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-10.0.1.tgz", + "integrity": "sha512-Crln//HpW9M5CbtdfWm3IO66Cvx1WhZQvNybXgfB2dD/6Sav9ppw+IWqs/FQKPBFO4B6X0X28Z0WNznshgwUzA==", + "dev": true, + "dependencies": { + "klona": "^2.0.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/less/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/license-webpack-plugin": { + "version": "2.3.20", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.20.tgz", + "integrity": "sha512-AHVueg9clOKACSHkhmEI+PCC9x8+qsQVuKECZD3ETxETK5h/PCv5/MUzyG1gm8OMcip/s1tcNxqo9Qb7WhjGsg==", + "dev": true, + "dependencies": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/license-webpack-plugin/node_modules/@types/webpack-sources": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.9.tgz", + "integrity": "sha512-bvzMnzqoK16PQIC8AYHNdW45eREJQMd6WG/msQWX5V2+vZmODCOPb4TJcbgRljTZZTwTM4wUMcsI8FftNA7new==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" + } + }, + "node_modules/license-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lilconfig": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", + "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lit-element": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.5.1.tgz", + "integrity": "sha512-ogu7PiJTA33bEK0xGu1dmaX5vhcRjBXCFexPja0e7P7jqLhTpNKYRPmE+GmiCaRVAbiQKGkUgkh/i6+bh++dPQ==", + "dev": true, + "dependencies": { + "lit-html": "^1.1.1" + } + }, + "node_modules/lit-html": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.4.1.tgz", + "integrity": "sha512-B9btcSgPYb1q4oSOb/PrOT6Z/H+r6xuNzfH4lFli/AWhYwdtrgQkQWBbIc6mdnf6E2IL3gDXdkkqNktpU0OZQA==", + "dev": true + }, + "node_modules/loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/log4js/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/loglevel-plugin-prefix": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", + "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowlight": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "dev": true, + "dependencies": { + "fault": "^1.0.0", + "highlight.js": "~10.7.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "node_modules/macos-release": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", + "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.4" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha1-beJlMXSt+12e3DPGnT6Sobdvrwg=", + "dev": true + }, + "node_modules/map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/markdown-to-jsx": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.6.tgz", + "integrity": "sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdast-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", + "dev": true, + "dependencies": { + "unist-util-remove": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dev": true, + "dependencies": { + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "dev": true, + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", + "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dev": true, + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/memfs": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", + "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "dev": true, + "dependencies": { + "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha1-fIekZGREwy11Q4VwkF8tvRsagFo=", + "dev": true, + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, + "node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/memory-fs/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/memory-fs/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/memory-fs/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/microevent.ts": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", + "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "dependencies": { + "mime-db": "1.51.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.2.tgz", + "integrity": "sha512-ZmqShkn79D36uerdED+9qdo1ZYG8C1YsWvXu0UMJxurZnSdgz7gQKO2EGv8T55MhDqG3DYmGtizZNpM/UbTlcA==", + "dev": true, + "dependencies": { + "schema-utils": "^3.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dev": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "dependencies": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/move-concurrently/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/move-concurrently/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/move-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "dev": true, + "optional": true + }, + "node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true, + "peer": true + }, + "node_modules/needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "dependencies": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "dev": true, + "optional": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.1.tgz", + "integrity": "sha512-zJ4jePUHR8cceduZ53b6temRalyGpkC2Kc2r3ecNphmL+uWNoJ3YcOcUjpbG6WwoE/Ef6/+aEZz63neI2WIa1Q==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", + "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.0", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/node-libs-browser/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/node-libs-browser/node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "node_modules/node-libs-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/node-libs-browser/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "node_modules/npm-package-arg": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", + "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-packlist": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", + "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", + "dev": true, + "dependencies": { + "glob": "^7.1.6", + "ignore-walk": "^4.0.1", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-pick-manifest": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", + "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", + "dev": true, + "dependencies": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" + } + }, + "node_modules/npm-registry-fetch": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", + "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^9.0.1", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "node_modules/nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", + "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/open/-/open-8.2.1.tgz", + "integrity": "sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true, + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/opn/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "dependencies": { + "url-parse": "^1.4.3" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "node_modules/os-name": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", + "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", + "dev": true, + "dependencies": { + "macos-release": "^2.5.0", + "windows-release": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/overlayscrollbars": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.1.tgz", + "integrity": "sha512-gIQfzgGgu1wy80EB4/6DaJGHMEGmizq27xHIESrzXq0Y/J0Ay1P3DWk6tuVmEPIZH15zaBlxeEJOqdJKmowHCQ==", + "dev": true + }, + "node_modules/p-all": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz", + "integrity": "sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA==", + "dev": true, + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-all/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dev": true, + "dependencies": { + "p-timeout": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "dev": true, + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-filter/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "dependencies": { + "retry": "^0.12.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dev": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-12.0.2.tgz", + "integrity": "sha512-Ar3mhjcxhMzk+OVZ8pbnXdb0l8+pimvlsqBGRNkble2NVgyqOGE3yrCGi/lAYq7E7NRDMz89R1Wx5HIMCGgeYg==", + "dev": true, + "dependencies": { + "@npmcli/git": "^2.1.0", + "@npmcli/installed-package-contents": "^1.0.6", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^2.0.0", + "cacache": "^15.0.5", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.3", + "mkdirp": "^1.0.3", + "npm-package-arg": "^8.0.1", + "npm-packlist": "^3.0.0", + "npm-pick-manifest": "^6.0.0", + "npm-registry-fetch": "^11.0.0", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.0" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "dependencies": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "node_modules/parallel-transform/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/parallel-transform/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/parallel-transform/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dev": true, + "dependencies": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", + "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1", + "parse5-sax-parser": "^6.0.1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-sax-parser": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", + "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", + "dev": true, + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-sax-parser/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pdfjs-dist": { + "version": "2.12.313", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz", + "integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==", + "dev": true, + "peerDependencies": { + "worker-loader": "^3.0.8" + }, + "peerDependenciesMeta": { + "worker-loader": { + "optional": true + } + } + }, + "node_modules/pdfmake": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.4.tgz", + "integrity": "sha512-EM39waHUe/Dg1W9C3XqYbpx6tfhYyU14JHZlI1HaW0AUEY32GbkRBjDLGWo9f7z/k3ea6k1p9yyDrflnvtZS1A==", + "dev": true, + "dependencies": { + "@foliojs-fork/linebreak": "^1.1.1", + "@foliojs-fork/pdfkit": "^0.13.0", + "iconv-lite": "^0.6.3", + "xmldoc": "^1.1.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/pdfmake/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/piscina": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-3.1.0.tgz", + "integrity": "sha512-KTW4sjsCD34MHrUbx9eAAbuUSpVj407hQSgk/6Epkg0pbRBmv4a3UX7Sr8wxm9xYqQLnsN4mFOjqGDzHAdgKQg==", + "dev": true, + "dependencies": { + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0" + }, + "optionalDependencies": { + "nice-napi": "^1.0.2" + } + }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==", + "dev": true + }, + "node_modules/pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "dev": true, + "dependencies": { + "ts-pnp": "^1.1.6" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/polished": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.1.4.tgz", + "integrity": "sha512-Nq5Mbza+Auo7N3sQb1QMFaQiDO+4UexWuSGR7Cjb4Sw11SZIJcrrFtiZ+L0jT9MBsUsxDboHVASbCLbE1rnECg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.16.7" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/polished/node_modules/@babel/runtime": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", + "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", + "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", + "dev": true, + "dependencies": { + "nanoid": "^3.2.0", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" + } + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-attribute-case-insensitive/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-functional-notation/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-color-functional-notation/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-functional-notation/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "dev": true, + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-gray/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-color-gray/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-gray/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-hex-alpha/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-color-hex-alpha/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-hex-alpha/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "dev": true, + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-mod-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-color-mod-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-mod-function/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-rebeccapurple/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-color-rebeccapurple/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-rebeccapurple/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-colormin": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz", + "integrity": "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz", + "integrity": "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-custom-media/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-custom-media/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-custom-media/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-custom-properties/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-custom-properties/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-custom-properties/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-custom-selectors/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-custom-selectors/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-custom-selectors/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-custom-selectors/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-dir-pseudo-class/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-dir-pseudo-class/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz", + "integrity": "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz", + "integrity": "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz", + "integrity": "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz", + "integrity": "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-double-position-gradients/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-double-position-gradients/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-double-position-gradients/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-env-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-env-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-env-function/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-flexbugs-fixes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz", + "integrity": "sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.26" + } + }, + "node_modules/postcss-flexbugs-fixes/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-flexbugs-fixes/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-flexbugs-fixes/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-focus-visible/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-focus-visible/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-focus-visible/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-focus-within/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-focus-within/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-focus-within/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-font-variant": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz", + "integrity": "sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-font-variant/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-font-variant/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-font-variant/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-gap-properties/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-gap-properties/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-gap-properties/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-image-set-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-image-set-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-image-set-function/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-import": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.0.2.tgz", + "integrity": "sha512-BJ2pVK4KhUyMcqjuKs9RijV5tatNzNa73e/32aBVE/ejYPe37iH+6vAu9WvqUkB5OAYgLHzbSvzHnorybJCm9g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-initial": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz", + "integrity": "sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-initial/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-initial/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-initial/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "dev": true, + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-lab-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-lab-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-lab-function/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.3.tgz", + "integrity": "sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.4", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-loader": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.1.1.tgz", + "integrity": "sha512-lBmJMvRh1D40dqpWKr9Rpygwxn8M74U9uaCSeYGNKLGInbk9mXBt1ultHf2dH9Ghk6Ue4UXlXWwGMH9QdUJ5ug==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-logical/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-logical/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-logical/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-media-minmax/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-media-minmax/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-media-minmax/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz", + "integrity": "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.0.3" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz", + "integrity": "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.0.2", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz", + "integrity": "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz", + "integrity": "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==", + "dev": true, + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz", + "integrity": "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "cssnano-utils": "^3.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz", + "integrity": "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-nesting/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-nesting/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-nesting/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz", + "integrity": "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz", + "integrity": "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz", + "integrity": "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz", + "integrity": "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz", + "integrity": "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz", + "integrity": "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz", + "integrity": "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz", + "integrity": "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==", + "dev": true, + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz", + "integrity": "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz", + "integrity": "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==", + "dev": true, + "dependencies": { + "cssnano-utils": "^3.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-overflow-shorthand/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-overflow-shorthand/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-overflow-shorthand/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-page-break/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-page-break/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-page-break/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-place/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-place/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-place/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", + "dev": true, + "dependencies": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-preset-env/node_modules/autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/postcss-preset-env/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-preset-env/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-preset-env/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-pseudo-class-any-link/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz", + "integrity": "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz", + "integrity": "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-replace-overflow-wrap/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-replace-overflow-wrap/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-replace-overflow-wrap/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-selector-matches/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-selector-matches/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-selector-matches/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-selector-not": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz", + "integrity": "sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-selector-not/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-selector-not/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-selector-not/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", + "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz", + "integrity": "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz", + "integrity": "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dev": true, + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/prismjs": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.26.0.tgz", + "integrity": "sha512-HUoH9C5Z3jKkl3UunCyiD5jwk0+Hz0fIgQ2nbwU2Oo/ceuTAQAg+pPVnfdt2TJWRVLcxKh9iuoYDUSc8clb5UQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise.allsettled": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.5.tgz", + "integrity": "sha512-tVDqeZPoBC0SlzJHzWGZ2NKAguVq2oiYj7gbggbiTvH2itHohijTp7njOUA0aQ/nl+0lr/r6egmhoYu63UZ/pQ==", + "dev": true, + "dependencies": { + "array.prototype.map": "^1.0.4", + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "iterate-value": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/promise.prototype.finally": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz", + "integrity": "sha512-EXRF3fC9/0gz4qkt/f5EP5iW4kj9oFpBICNpCNOb/52+8nlHIX07FPLbi/q4qYBQ1xZqivMzTpNQSnArVASolQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "dev": true, + "dependencies": { + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-middleware": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", + "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/quote-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", + "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "dev": true, + "dependencies": { + "buffer-equal": "0.0.1", + "minimist": "^1.1.3", + "through2": "^2.0.0" + }, + "bin": { + "quote-stream": "bin/cmd.js" + } + }, + "node_modules/ramda": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", + "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=", + "dev": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/raw-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/raw-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/raw-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/raw-loader/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", + "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", + "dev": true, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, + "node_modules/react-draggable": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz", + "integrity": "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==", + "dev": true, + "dependencies": { + "clsx": "^1.1.1", + "prop-types": "^15.6.0" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, + "node_modules/react-element-to-jsx-string": { + "version": "14.3.4", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz", + "integrity": "sha512-t4ZwvV6vwNxzujDQ+37bspnLwA4JlgUPWhLjBJWsNIDceAf6ZKUTCjdm08cN6WeZ5pTMKiCJkmAYnpmR4Bm+dg==", + "dev": true, + "dependencies": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "17.0.2" + }, + "peerDependencies": { + "react": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1", + "react-dom": "^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1" + } + }, + "node_modules/react-element-to-jsx-string/node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==", + "dev": true + }, + "node_modules/react-helmet-async": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.2.3.tgz", + "integrity": "sha512-mCk2silF53Tq/YaYdkl2sB+/tDoPnaxN7dFS/6ZLJb/rhUY2EWGI5Xj2b4jHppScMqY45MbgPSwTxDchKpZ5Kw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0", + "react-dom": "^16.6.0 || ^17.0.0" + } + }, + "node_modules/react-inspector": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", + "integrity": "sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.0.0", + "is-dom": "^1.0.0", + "prop-types": "^15.0.0" + }, + "peerDependencies": { + "react": "^16.8.4 || ^17.0.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/react-popper": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz", + "integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==", + "dev": true, + "dependencies": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + }, + "peerDependencies": { + "@popperjs/core": "^2.0.0", + "react": "^16.8.0 || ^17" + } + }, + "node_modules/react-popper-tooltip": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz", + "integrity": "sha512-EnERAnnKRptQBJyaee5GJScWNUKQPDD2ywvzZyUjst/wj5U64C8/CnSYLNEmP2hG0IJ3ZhtDxE8oDN+KOyavXQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@popperjs/core": "^2.5.4", + "react-popper": "^2.2.4" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0", + "react-dom": "^16.6.0 || ^17.0.0" + } + }, + "node_modules/react-router": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz", + "integrity": "sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==", + "dev": true, + "dependencies": { + "history": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz", + "integrity": "sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==", + "dev": true, + "dependencies": { + "history": "^5.2.0", + "react-router": "6.2.1" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-router-dom/node_modules/history": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz", + "integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.7.6" + } + }, + "node_modules/react-router/node_modules/history": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz", + "integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.7.6" + } + }, + "node_modules/react-sizeme": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.2.tgz", + "integrity": "sha512-xOIAOqqSSmKlKFJLO3inBQBdymzDuXx4iuwkNcJmC96jeiOg5ojByvL+g3MW9LPEsojLbC6pf68zOfobK8IPlw==", + "dev": true, + "dependencies": { + "element-resize-detector": "^1.2.2", + "invariant": "^2.2.4", + "shallowequal": "^1.1.0", + "throttle-debounce": "^3.0.1" + } + }, + "node_modules/react-syntax-highlighter": { + "version": "13.5.3", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-13.5.3.tgz", + "integrity": "sha512-crPaF+QGPeHNIblxxCdf2Lg936NAHKhNhuMzRL3F9ct6aYXL3NcZtCL0Rms9+qVo6Y1EQLdXGypBNSbPL/r+qg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.1.1", + "lowlight": "^1.14.0", + "prismjs": "^1.21.0", + "refractor": "^3.1.0" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, + "node_modules/react-textarea-autosize": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz", + "integrity": "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.10.2", + "use-composed-ref": "^1.0.0", + "use-latest": "^1.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", + "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/refractor": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.5.0.tgz", + "integrity": "sha512-QwPJd3ferTZ4cSPPjdP5bsYHMytwWYnAN5EEnLtGvkqp/FCCnGsBgxrm9EuIDnjUC3Uc/kETtvVi7fSIVC74Dg==", + "dev": true, + "dependencies": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.25.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/refractor/node_modules/prismjs": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", + "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==", + "dev": true + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", + "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-external-links": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", + "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "is-absolute-url": "^3.0.0", + "mdast-util-definitions": "^4.0.0", + "space-separated-tokens": "^1.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-footnotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", + "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", + "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "dev": true, + "dependencies": { + "@babel/core": "7.12.9", + "@babel/helper-plugin-utils": "7.10.4", + "@babel/plugin-proposal-object-rest-spread": "7.12.1", + "@babel/plugin-syntax-jsx": "7.12.1", + "@mdx-js/util": "1.6.22", + "is-alphabetical": "1.0.4", + "remark-parse": "8.0.3", + "unified": "9.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx/node_modules/@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/remark-mdx/node_modules/@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "node_modules/remark-mdx/node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/remark-mdx/node_modules/@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/remark-mdx/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/remark-mdx/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "dev": true, + "dependencies": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-slug": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", + "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", + "dev": true, + "dependencies": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", + "dev": true, + "dependencies": { + "mdast-squeeze-paragraphs": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + } + }, + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dev": true, + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } + } + }, + "node_modules/resolve-url-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true, + "engines": { + "node": "6.* || >= 7.*" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1" + } + }, + "node_modules/run-queue/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/rxjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz", + "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "deprecated": "some dependency vulnerabilities fixed, support for node < 10 dropped, and newer ECMAScript syntax/features added", + "dev": true, + "dependencies": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "bin": { + "sane": "src/cli.js" + }, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/sane/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/sane/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/sane/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sane/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sass": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.36.0.tgz", + "integrity": "sha512-fQzEjipfOv5kh930nu3Imzq3ie/sGDc/4KtQMJlt7RRdrkQSfe37Bwi/Rf/gfuYHsIuE1fIlDMvpyMcEwjnPvg==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/sass-loader": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz", + "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0", + "sass": "^1.3.0", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/scope-analyzer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.1.2.tgz", + "integrity": "sha512-5cfCmsTYV/wPaRIItNxatw02ua/MThdIUNnUOCYp+3LSEJvnG804ANw2VLaavNILIfWXF1D1G2KNANkBBvInwQ==", + "dev": true, + "dependencies": { + "array-from": "^2.1.1", + "dash-ast": "^2.0.1", + "es6-map": "^0.1.5", + "es6-set": "^0.1.5", + "es6-symbol": "^3.1.1", + "estree-is-function": "^1.0.0", + "get-assigned-identifiers": "^1.1.0" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "node_modules/selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "dependencies": { + "node-forge": "^0.10.0" + } + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", + "dev": true, + "dependencies": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-favicon/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/serve-favicon/node_modules/safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", + "dev": true + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true, + "optional": true, + "peer": true + }, + "node_modules/socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs-client": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz", + "integrity": "sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==", + "dev": true, + "dependencies": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.5.3" + } + }, + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "dev": true, + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.0.tgz", + "integrity": "sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.2", + "source-map-js": "^0.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader/node_modules/source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/static-eval": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.0.tgz", + "integrity": "sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==", + "dev": true, + "dependencies": { + "escodegen": "^1.11.1" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/static-eval/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-module": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-3.0.4.tgz", + "integrity": "sha512-gb0v0rrgpBkifXCa3yZXxqVmXDVE+ETXj6YlC/jt5VzOnGXR2C15+++eXuMDUYsePnbhf+lwW0pE1UXyOLtGCw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.3.0", + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "^1.11.1", + "has": "^1.0.1", + "magic-string": "0.25.1", + "merge-source-map": "1.0.4", + "object-inspect": "^1.6.0", + "readable-stream": "~2.3.3", + "scope-analyzer": "^2.0.1", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.5", + "through2": "~2.0.3" + } + }, + "node_modules/static-module/node_modules/escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-module/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/static-module/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/static-module/node_modules/magic-string": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", + "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.1" + } + }, + "node_modules/static-module/node_modules/merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "dev": true, + "dependencies": { + "source-map": "^0.5.6" + } + }, + "node_modules/static-module/node_modules/merge-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-module/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/static-module/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-module/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/store2": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/store2/-/store2-2.13.1.tgz", + "integrity": "sha512-iJtHSGmNgAUx0b/MCS6ASGxb//hGrHHRgzvN+K5bvkBTN7A9RTpPSf1WSp+nPGvWCJ1jRnvY7MKnuqfoi3OEqg==", + "dev": true + }, + "node_modules/storybook-addon-designs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/storybook-addon-designs/-/storybook-addon-designs-6.2.1.tgz", + "integrity": "sha512-ihsscab8185HnxqTNZlM4TfrCPVsO7AimVA8BapuqT/sfZQF9m5H9C0plT3kbECdIMh2cmzMBF1Tc9ckWRgpWg==", + "dev": true, + "dependencies": { + "@figspec/react": "^1.0.0" + } + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-browserify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-browserify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "dependencies": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-http/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/stream-http/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-http/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "optional": true, + "peer": true, + "dependencies": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "peer": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz", + "integrity": "sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.padend": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.padstart": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.1.3.tgz", + "integrity": "sha512-NZydyOMtYxpTjGqp0VN5PYUF/tsU15yDMZnUdj16qRUIUiMJkHHSDElYyQFrMu+/WloTpA7MQSiADhBicDfaoA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.2.1.tgz", + "integrity": "sha512-1k9ZosJCRFaRbY6hH49JFlRB0fVSbmnyq1iTPjNxUmGVjBNEmwrrHPenhlp+Lgo51BojHSf6pl2FcqYaN3PfVg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/style-to-object": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", + "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "dev": true, + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/stylehacks": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz", + "integrity": "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "dependencies": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus-loader": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-6.1.0.tgz", + "integrity": "sha512-qKO34QCsOtSJrXxQQmXsPeaVHh6hMumBAFIoJTcsSr2VzrA6o/CW9HCGR8spCjzJhN8oKQHdj/Ytx0wwXyElkw==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.5", + "klona": "^2.0.4", + "normalize-path": "^3.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "stylus": ">=0.52.4", + "webpack": "^5.0.0" + } + }, + "node_modules/stylus/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/stylus/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/stylus/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/symbol.prototype.description": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/symbol.prototype.description/-/symbol.prototype.description-1.0.5.tgz", + "integrity": "sha512-x738iXRYsrAt9WBhRCVG5BtIC3B7CUkFwbHW2zOvGtwM33s7JjrCDyq8V0zgMYVb5ymsL8+qkzzpANH63CPQaQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-symbol-description": "^1.0.0", + "has-symbols": "^1.0.2", + "object.getownpropertydescriptors": "^2.1.2" + }, + "engines": { + "node": ">= 0.11.15" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/synchronous-promise": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.15.tgz", + "integrity": "sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg==", + "dev": true + }, + "node_modules/tailwindcss": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.23.tgz", + "integrity": "sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==", + "dev": true, + "dependencies": { + "arg": "^5.0.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "cosmiconfig": "^7.0.1", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "normalize-path": "^3.0.0", + "object-hash": "^2.2.0", + "postcss": "^8.4.6", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.0", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "autoprefixer": "^10.0.2", + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/tailwindcss/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tailwindcss/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tailwindcss/node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/telejson": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-5.3.3.tgz", + "integrity": "sha512-PjqkJZpzEggA9TBpVtJi1LVptP7tYtXB6rEubwlHap76AMjzvOdKX41CxyaW7ahhzDU1aftXnMCx5kAPDZTQBA==", + "dev": true, + "dependencies": { + "@types/is-function": "^1.0.0", + "global": "^4.4.0", + "is-function": "^1.0.2", + "is-regex": "^1.1.2", + "is-symbol": "^1.0.3", + "isobject": "^4.0.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3" + } + }, + "node_modules/telejson/node_modules/isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", + "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.4.tgz", + "integrity": "sha512-C2WkFwstHDhVEmsmlCxrXUtVklS+Ir1A7twrYzrDrQQOIMOaVAYykaoo/Aq1K0QRkMoY2hhvDQY1cm4jnIMFwA==", + "dev": true, + "dependencies": { + "jest-worker": "^27.0.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true, + "peer": true + }, + "node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "dev": true + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=", + "dev": true + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "node_modules/trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/ts-jest": { + "version": "27.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz", + "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@types/jest": "^27.0.0", + "babel-jest": ">=27.0.0 <28", + "jest": "^27.0.0", + "typescript": ">=3.8 <5.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/ts-jest/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/ts-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-jest/node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, + "node_modules/ts-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-jest/node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/ts-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.3.0.tgz", + "integrity": "sha512-MgGly4I6cStsJy27ViE32UoqxPTN9Xly4anxxVyaIWR+9BGxboV4EyJBGfR3RePV7Ksjj3rHmPZJeIt+7o4Vag==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^2.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "*" + } + }, + "node_modules/ts-loader/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ts-loader/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-loader/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-morph": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-13.0.3.tgz", + "integrity": "sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==", + "dev": true, + "dependencies": { + "@ts-morph/common": "~0.12.3", + "code-block-writer": "^11.0.0" + } + }, + "node_modules/ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz", + "integrity": "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^3.9.0" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/enhanced-resolve": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz", + "integrity": "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "optional": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/uglify-js": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz", + "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", + "dev": true + }, + "node_modules/unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-properties": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.3.1.tgz", + "integrity": "sha512-nIV3Tf3LcUEZttY/2g4ZJtGXhWwSkuLL+rCu0DIAMbjyVPj+8j5gNVz4T/sVbnQybIsd5SFGkPKg/756OY6jlA==", + "dev": true, + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dev": true, + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "node_modules/unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dev": true, + "dependencies": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unist-builder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", + "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-generated": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", + "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", + "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", + "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "dev": true, + "dependencies": { + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", + "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "dev": true, + "dependencies": { + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unix-crypt-td-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz", + "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==", + "dev": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/url-parse": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.7.tgz", + "integrity": "sha512-HxWkieX+STA38EDk7CE9MEryFeHCKzgagxlGvsdS7WBImq9Mk+PGwiT56w82WI3aicwJA8REp42Cxo98c8FZMA==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/use-composed-ref": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz", + "integrity": "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==", + "dev": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz", + "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==", + "dev": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz", + "integrity": "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==", + "dev": true, + "dependencies": { + "use-isomorphic-layout-effect": "^1.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/uuid-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid-browser/-/uuid-browser-3.1.0.tgz", + "integrity": "sha1-DwWkCu90+eWVHiDvv0SxGHHlZBA=", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "dependencies": { + "builtins": "^1.0.3" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "optional": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "dependencies": { + "chokidar": "^2.1.8" + } + }, + "node_modules/watchpack-chokidar2/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/watchpack-chokidar2/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "optional": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, + "node_modules/watchpack-chokidar2/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "node_modules/watchpack-chokidar2/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "optional": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/watchpack-chokidar2/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/watchpack-chokidar2/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/watchpack-chokidar2/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "optional": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-namespaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", + "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/webpack": { + "version": "5.69.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.69.0.tgz", + "integrity": "sha512-E5Fqu89Gu8fR6vejRqu26h8ld/k6/dCVbeGUcuZjc+goQHDfCPU9rER71JmdtBYGmci7Ec2aFEATQ2IVXKy2wg==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.0.0.tgz", + "integrity": "sha512-9zng2Z60pm6A98YoRcA0wSxw1EYn7B7y5owX/Tckyt9KGyULTkLtiavjaXlWqOMkM0YtqGgL3PvMOFgyFLq8vw==", + "dev": true, + "dependencies": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack-dev-middleware/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz", + "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 6.11.5" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/webpack-dev-server/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/webpack-dev-server/node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/webpack-dev-server/node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/webpack-dev-server/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/webpack-dev-server/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/webpack-dev-server/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/webpack-dev-server/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack-dev-server/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/webpack-dev-server/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/webpack-dev-server/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/string-width/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/string-width/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "dependencies": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/webpack-dev-server/node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/webpack-hot-middleware": { + "version": "2.25.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz", + "integrity": "sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==", + "dev": true, + "dependencies": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "querystring": "^0.2.0", + "strip-ansi": "^6.0.0" + } + }, + "node_modules/webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "dependencies": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/webpack-log/node_modules/ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-log/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.2.tgz", + "integrity": "sha512-GBWYBoyalbo5YClwWop9qe6Zclp8CIXYGIz12OPclJhIrSplDxs1Ls1JDMH8xBPPrg1T6ISaTW9Y6zOrwEiAzw==", + "dev": true, + "dependencies": { + "webpack-sources": "^1.3.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 2.21.0 < 5", + "webpack": ">= 1.12.11 < 6" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz", + "integrity": "sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA==", + "dev": true, + "dependencies": { + "debug": "^3.0.0" + } + }, + "node_modules/webpack-virtual-modules/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/webpack/node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/webpack/node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/enhanced-resolve": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz", + "integrity": "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack/node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/windows-release": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", + "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", + "dev": true, + "dependencies": { + "execa": "^4.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/windows-release/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/windows-release/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/windows-release/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/windows-release/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/windows-release/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/windows-release/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/windows-release/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "dependencies": { + "errno": "~0.1.7" + } + }, + "node_modules/worker-rpc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", + "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", + "dev": true, + "dependencies": { + "microevent.ts": "~0.1.1" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/xmldoc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-1.1.2.tgz", + "integrity": "sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ==", + "dev": true, + "dependencies": { + "sax": "^1.2.1" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "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.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zone.js": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.4.tgz", + "integrity": "sha512-DDh2Ab+A/B+9mJyajPjHFPWfYU1H+pdun4wnnk0OcQTNjem1XQSZ2CDW+rfZEUDjv5M19SBqAkjZi0x5wuB5Qw==", + "peer": true, + "dependencies": { + "tslib": "^2.0.0" + } + }, + "node_modules/zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + }, + "dependencies": { + "@aduh95/viz.js": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@aduh95/viz.js/-/viz.js-3.5.0.tgz", + "integrity": "sha512-ahLdpRAoGsdgEfy2SGV2wnnHrBSLDHuwA32v+BoNGnz1gqajr8VMzF8y6mIQt28hHi4LQ272wqSi78DK4YdT2g==", + "dev": true + }, + "@ampproject/remapping": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-1.0.1.tgz", + "integrity": "sha512-Ta9bMA3EtUHDaZJXqUoT5cn/EecwOp+SXpKJqxDbDuMbLvEMu6YTyDDuvTWeStODfdmXyfMo7LymQyPkN3BicA==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "1.0.0", + "sourcemap-codec": "1.4.8" + } + }, + "@angular-devkit/architect": { + "version": "0.1302.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1302.3.tgz", + "integrity": "sha512-0m8jMKrFfIqsYt33zTUwSmyekyfuS67hna08RQ6USjzWQSE3z4S8ulCUARSjM6AzdMblX+whfy56nJUpT17NSA==", + "dev": true, + "peer": true, + "requires": { + "@angular-devkit/core": "13.2.3", + "rxjs": "6.6.7" + }, + "dependencies": { + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "peer": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "peer": true + } + } + }, + "@angular-devkit/build-angular": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-12.2.16.tgz", + "integrity": "sha512-0UlSaX3LngsBUp6Da69XlptyeZn7CTt/3sKijQDtkEw/J37vpMcXYD4nUuU7q7mVMoPQwMyPWdF+JBsBFz6f7A==", + "dev": true, + "requires": { + "@ampproject/remapping": "1.0.1", + "@angular-devkit/architect": "0.1202.16", + "@angular-devkit/build-optimizer": "0.1202.16", + "@angular-devkit/build-webpack": "0.1202.16", + "@angular-devkit/core": "12.2.16", + "@babel/core": "7.14.8", + "@babel/generator": "7.14.8", + "@babel/helper-annotate-as-pure": "7.14.5", + "@babel/plugin-proposal-async-generator-functions": "7.14.7", + "@babel/plugin-transform-async-to-generator": "7.14.5", + "@babel/plugin-transform-runtime": "7.14.5", + "@babel/preset-env": "7.14.8", + "@babel/runtime": "7.14.8", + "@babel/template": "7.14.5", + "@discoveryjs/json-ext": "0.5.3", + "@jsdevtools/coverage-istanbul-loader": "3.0.5", + "@ngtools/webpack": "12.2.16", + "ansi-colors": "4.1.1", + "babel-loader": "8.2.2", + "browserslist": "^4.9.1", + "cacache": "15.2.0", + "caniuse-lite": "^1.0.30001032", + "circular-dependency-plugin": "5.2.2", + "copy-webpack-plugin": "9.0.1", + "core-js": "3.16.0", + "critters": "0.0.12", + "css-loader": "6.2.0", + "css-minimizer-webpack-plugin": "3.0.2", + "esbuild": "0.13.8", + "esbuild-wasm": "0.13.8", + "find-cache-dir": "3.3.1", + "glob": "7.1.7", + "https-proxy-agent": "5.0.0", + "inquirer": "8.1.2", + "karma-source-map-support": "1.4.0", + "less": "4.1.1", + "less-loader": "10.0.1", + "license-webpack-plugin": "2.3.20", + "loader-utils": "2.0.0", + "mini-css-extract-plugin": "2.4.2", + "minimatch": "3.0.4", + "open": "8.2.1", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "6.0.1", + "piscina": "3.1.0", + "postcss": "8.3.6", + "postcss-import": "14.0.2", + "postcss-loader": "6.1.1", + "postcss-preset-env": "6.7.0", + "regenerator-runtime": "0.13.9", + "resolve-url-loader": "4.0.0", + "rxjs": "6.6.7", + "sass": "1.36.0", + "sass-loader": "12.1.0", + "semver": "7.3.5", + "source-map-loader": "3.0.0", + "source-map-support": "0.5.19", + "style-loader": "3.2.1", + "stylus": "0.54.8", + "stylus-loader": "6.1.0", + "terser": "5.7.1", + "terser-webpack-plugin": "5.1.4", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.3.0", + "webpack": "5.50.0", + "webpack-dev-middleware": "5.0.0", + "webpack-dev-server": "3.11.3", + "webpack-merge": "5.8.0", + "webpack-subresource-integrity": "1.5.2" + }, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.16.tgz", + "integrity": "sha512-VUGyAr+5RmlcPjo8mZSRJ/wkm3hCPn9PJyorAnc1IzrqD+XkgcDME86HP3YheLsOsc1Mn7j6Zh3T1rAclAWw/w==", + "dev": true, + "requires": { + "@angular-devkit/core": "12.2.16", + "rxjs": "6.6.7" + } + }, + "@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "requires": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + } + }, + "@babel/core": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.8.tgz", + "integrity": "sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.8", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.8", + "@babel/helpers": "^7.14.8", + "@babel/parser": "^7.14.8", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.8", + "@babel/types": "^7.14.8", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@types/estree": { + "version": "0.0.50", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.50.tgz", + "integrity": "sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw==", + "dev": true + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "enhanced-resolve": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz", + "integrity": "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "es-module-lexer": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.7.1.tgz", + "integrity": "sha512-MgtWFl5No+4S3TmhDmCz2ObFGm6lEpTnzbQi+Dd+pw4mlTIZTmM2iAs5gRlmx5zS9luzobCSBSI90JM/1/JgOw==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "postcss": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.6.tgz", + "integrity": "sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map-js": "^0.6.2" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "dev": true + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + }, + "webpack": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.50.0.tgz", + "integrity": "sha512-hqxI7t/KVygs0WRv/kTgUW8Kl3YC81uyWQSo/7WUs5LsuRw0htH/fCwbVBGCuiX/t4s7qzjXFcf41O8Reiypag==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.0", + "@types/estree": "^0.0.50", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.8.0", + "es-module-lexer": "^0.7.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.4", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.2.0", + "webpack-sources": "^3.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + } + } + }, + "@angular-devkit/build-optimizer": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.1202.16.tgz", + "integrity": "sha512-7DO195vDwOnCCHrzjr6ajSNkvCzW6O/ERbVezCA46NZuS9lW9LnWpP3CE9iDnhzup7hjrM336/dXmYJO8Hw1MA==", + "dev": true, + "requires": { + "source-map": "0.7.3", + "tslib": "2.3.0", + "typescript": "4.3.5" + }, + "dependencies": { + "tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "dev": true + } + } + }, + "@angular-devkit/build-webpack": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1202.16.tgz", + "integrity": "sha512-Zhnr0+W1og1rtbfKDPxD7jWDL4cg9LA21ls2pJKXc/h+YXdQ5uj4mFg69npL6aY0yver1w2rIz+Il/wdC/W1gw==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1202.16", + "rxjs": "6.6.7" + }, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.16.tgz", + "integrity": "sha512-VUGyAr+5RmlcPjo8mZSRJ/wkm3hCPn9PJyorAnc1IzrqD+XkgcDME86HP3YheLsOsc1Mn7j6Zh3T1rAclAWw/w==", + "dev": true, + "requires": { + "@angular-devkit/core": "12.2.16", + "rxjs": "6.6.7" + } + }, + "@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "requires": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + } + }, + "ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@angular-devkit/core": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-13.2.3.tgz", + "integrity": "sha512-/47RA8qmWzeS60xSdaprIn1MiSv0Iw83t0M9/ENH7irFS5vMAq62NCcwiWXH59pZmvvLbF+7xy/RgYUZLr4nHQ==", + "dev": true, + "requires": { + "ajv": "8.9.0", + "ajv-formats": "2.1.1", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + }, + "dependencies": { + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@angular-devkit/schematics": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-12.2.16.tgz", + "integrity": "sha512-ToyZBCGilSeeLmhAxmeJ0PykmbKLoME+uK78gC64xJtNu9e3oVnmog8b8g9Ay9hTwZJ96HvNa16po11Gfbbn6A==", + "dev": true, + "requires": { + "@angular-devkit/core": "12.2.16", + "ora": "5.4.1", + "rxjs": "6.6.7" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "requires": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + } + }, + "ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@angular/animations": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.16.tgz", + "integrity": "sha512-Kf6C7Ta+fCMq5DvT9JNVhBkcECrqFa3wumiC6ssGo5sNaEzXz+tlep9ZgEbqfxSn7gAN7L1DgsbS9u0O6tbUkg==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/cdk": { + "version": "12.2.13", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.13.tgz", + "integrity": "sha512-zSKRhECyFqhingIeyRInIyTvYErt4gWo+x5DQr0b7YLUbU8DZSwWnG4w76Ke2s4U8T7ry1jpJBHoX/e8YBpGMg==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^2.2.0" + } + }, + "@angular/cli": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-12.2.16.tgz", + "integrity": "sha512-4DUi8aHIZWzQycw8SN55ziHhRusHVYJ+2rzsfhy0eDgkry7gYVd4wUn+6Q4D8irywA21soNq1S5JjGAZwRDS6g==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1202.16", + "@angular-devkit/core": "12.2.16", + "@angular-devkit/schematics": "12.2.16", + "@schematics/angular": "12.2.16", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.1", + "debug": "4.3.2", + "ini": "2.0.0", + "inquirer": "8.1.2", + "jsonc-parser": "3.0.0", + "npm-package-arg": "8.1.5", + "npm-pick-manifest": "6.1.1", + "open": "8.2.1", + "ora": "5.4.1", + "pacote": "12.0.2", + "resolve": "1.20.0", + "semver": "7.3.5", + "symbol-observable": "4.0.0", + "uuid": "8.3.2" + }, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.1202.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1202.16.tgz", + "integrity": "sha512-VUGyAr+5RmlcPjo8mZSRJ/wkm3hCPn9PJyorAnc1IzrqD+XkgcDME86HP3YheLsOsc1Mn7j6Zh3T1rAclAWw/w==", + "dev": true, + "requires": { + "@angular-devkit/core": "12.2.16", + "rxjs": "6.6.7" + } + }, + "@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "requires": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + } + }, + "ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@angular/common": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.16.tgz", + "integrity": "sha512-FEqTXTEsnbDInqV1yFlm97Tz1OFqZS5t0TUkm8gzXRgpIce/F/jLwAg0u1VQkgOsno6cNm0xTWPoZgu85NI4ug==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/compiler": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.16.tgz", + "integrity": "sha512-nsYEw+yu8QyeqPf9nAmG419i1mtGM4v8+U+S3eQHQFXTgJzLymMykWHYu2ETdjUpNSLK6xcIQDBWtWnWSfJjAA==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/compiler-cli": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.16.tgz", + "integrity": "sha512-tlalh8SJvdCWbUPRUR5GamaP+wSc/GuCsoUZpSbcczGKgSlbaEVXUYtVXm8/wuT6Slk2sSEbRs7tXGF2i7qxVw==", + "dev": true, + "requires": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.11.0", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.2.0", + "yargs": "^17.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@angular/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.16.tgz", + "integrity": "sha512-jsmvaRdAfng99z2a9mAmkfcsCE1wm+tBYVDxnc5JquSXznwtncjzcoc2X0J0dzrkCDvzFfpTsZ9vehylytBc+A==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/elements": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/elements/-/elements-12.2.16.tgz", + "integrity": "sha512-tOTf6FvnxZg/TjrmsbowHjrTYVl6WhTOQk3G4aYicrf+57a67L12F44Illr7I6preIvH5NepHivMTKN5rNBAmg==", + "dev": true, + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/forms": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.16.tgz", + "integrity": "sha512-sb+gpNun5aN7CZfHXS6X7vJcd/0A1P/gRBZpYtQTzBYnqEFCOFIvR62eb05aHQ4JhgKaSPpIXrbz/bAwY/njZw==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/platform-browser": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.16.tgz", + "integrity": "sha512-T855ppLeQO6hRHi7lGf5fwPoUVt+c0h2rgkV5jHElc3ylaGnhecmZc6fnWLX4pw82TMJUgUV88CY8JCFabJWwg==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.16.tgz", + "integrity": "sha512-XGxoACAMW/bc3atiVRpaiYwU4LkobYwVzwlxTT/BxOfsdt8ILb5wU8Fx1TMKNECOQHSGdK0qqhch4pTBZ3cb2g==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/compat-data": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz", + "integrity": "sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==", + "dev": true + }, + "@babel/core": { + "version": "7.17.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.4.tgz", + "integrity": "sha512-R9x5r4t4+hBqZTmioSnkrW+I6NmbojwjGT8p4G2Gw1thWbXIHGDnmGdLdFw0/7ljucdIrNRp7Npgb4CyBYzzJg==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helpers": "^7.17.2", + "@babel/parser": "^7.17.3", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0" + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", + "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.0" + } + }, + "@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.8.tgz", + "integrity": "sha512-cYDUpvIzhBVnMzRoY1fkSEhK/HmwEVwlyULYgn/tMQYd6Obag3ylCjONle3gdErfXBW61SVTlR9QR7uWlgeIkg==", + "dev": true, + "requires": { + "@babel/types": "^7.14.8", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz", + "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz", + "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.16.4", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.17.5", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.1.tgz", + "integrity": "sha512-JBdSr/LtyYIno/pNnJ75lBcqc3Z1XXujzPanHqjvvrhOA+DTceTFuJi8XjmWTZh4r3fsdfqaCMN0iZemdkxZHQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz", + "integrity": "sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "regexpu-core": "^5.0.1" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz", + "integrity": "sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz", + "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", + "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/helper-get-function-arity": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", + "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz", + "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz", + "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "dependencies": { + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz", + "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz", + "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-wrap-function": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/helper-replace-supers": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz", + "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/traverse": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-simple-access": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz", + "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz", + "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz", + "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8" + }, + "dependencies": { + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/helpers": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz", + "integrity": "sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.0", + "@babel/types": "^7.17.0" + }, + "dependencies": { + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/highlight": { + "version": "7.16.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", + "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz", + "integrity": "sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==", + "dev": true + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz", + "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz", + "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-proposal-optional-chaining": "^7.16.7" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz", + "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz", + "integrity": "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.2.tgz", + "integrity": "sha512-WH8Z95CwTq/W8rFbMqb9p3hicpt4RX4f0K659ax2VHxgOyT6qQmUaEVEjIh4WR9Eh9NymkVn5vwsrE68fAQNUw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.17.1", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/plugin-syntax-decorators": "^7.17.0", + "charcodes": "^0.2.0" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz", + "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-default-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.16.7.tgz", + "integrity": "sha512-+cENpW1rgIjExn+o5c8Jw/4BuH4eGKKYvkMB8/0ZxFQ9mC0t4z09VsPIwNg6waF69QYC81zxGeAsREGuqQoKeg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-default-from": "^7.16.7" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz", + "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz", + "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz", + "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz", + "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz", + "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz", + "integrity": "sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.0", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.16.7" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz", + "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz", + "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz", + "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.10", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz", + "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz", + "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.0.tgz", + "integrity": "sha512-qWe85yCXsvDEluNP0OyeQjH63DlhAR3W7K9BxxU1MvbDb48tgBG+Ao6IJJ6smPDrrVzSQZrbF6donpkFBMcs3A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-default-from": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.16.7.tgz", + "integrity": "sha512-4C3E4NsrLOgftKaTYTULhHsuQrGv3FHrBzOMDiS7UYKIpgGBkAdawg4h+EI8zPeK9M0fiIIh72hIwsI24K7MbA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", + "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz", + "integrity": "sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz", + "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", + "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz", + "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz", + "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz", + "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-optimise-call-expression": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz", + "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz", + "integrity": "sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz", + "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz", + "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz", + "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz", + "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz", + "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz", + "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz", + "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz", + "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz", + "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-simple-access": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz", + "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz", + "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz", + "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz", + "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz", + "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-replace-supers": "^7.16.7" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz", + "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz", + "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-react-display-name": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz", + "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-react-jsx": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz", + "integrity": "sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-jsx": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz", + "integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==", + "dev": true, + "requires": { + "@babel/plugin-transform-react-jsx": "^7.16.7" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz", + "integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + }, + "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz", + "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + } + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", + "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz", + "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz", + "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz", + "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz", + "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz", + "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz", + "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz", + "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz", + "integrity": "sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-typescript": "^7.16.7" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz", + "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz", + "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7" + } + }, + "@babel/preset-env": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.8.tgz", + "integrity": "sha512-a9aOppDU93oArQ51H+B8M1vH+tayZbuBqzjOhntGetZVa+4tTu5jp+XTwqHGG2lxslqomPYVSjIxQkFwXzgnxg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.14.7", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-async-generator-functions": "^7.14.7", + "@babel/plugin-proposal-class-properties": "^7.14.5", + "@babel/plugin-proposal-class-static-block": "^7.14.5", + "@babel/plugin-proposal-dynamic-import": "^7.14.5", + "@babel/plugin-proposal-export-namespace-from": "^7.14.5", + "@babel/plugin-proposal-json-strings": "^7.14.5", + "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", + "@babel/plugin-proposal-numeric-separator": "^7.14.5", + "@babel/plugin-proposal-object-rest-spread": "^7.14.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", + "@babel/plugin-proposal-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-private-methods": "^7.14.5", + "@babel/plugin-proposal-private-property-in-object": "^7.14.5", + "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.14.5", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/plugin-transform-block-scoped-functions": "^7.14.5", + "@babel/plugin-transform-block-scoping": "^7.14.5", + "@babel/plugin-transform-classes": "^7.14.5", + "@babel/plugin-transform-computed-properties": "^7.14.5", + "@babel/plugin-transform-destructuring": "^7.14.7", + "@babel/plugin-transform-dotall-regex": "^7.14.5", + "@babel/plugin-transform-duplicate-keys": "^7.14.5", + "@babel/plugin-transform-exponentiation-operator": "^7.14.5", + "@babel/plugin-transform-for-of": "^7.14.5", + "@babel/plugin-transform-function-name": "^7.14.5", + "@babel/plugin-transform-literals": "^7.14.5", + "@babel/plugin-transform-member-expression-literals": "^7.14.5", + "@babel/plugin-transform-modules-amd": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.14.5", + "@babel/plugin-transform-modules-systemjs": "^7.14.5", + "@babel/plugin-transform-modules-umd": "^7.14.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7", + "@babel/plugin-transform-new-target": "^7.14.5", + "@babel/plugin-transform-object-super": "^7.14.5", + "@babel/plugin-transform-parameters": "^7.14.5", + "@babel/plugin-transform-property-literals": "^7.14.5", + "@babel/plugin-transform-regenerator": "^7.14.5", + "@babel/plugin-transform-reserved-words": "^7.14.5", + "@babel/plugin-transform-shorthand-properties": "^7.14.5", + "@babel/plugin-transform-spread": "^7.14.6", + "@babel/plugin-transform-sticky-regex": "^7.14.5", + "@babel/plugin-transform-template-literals": "^7.14.5", + "@babel/plugin-transform-typeof-symbol": "^7.14.5", + "@babel/plugin-transform-unicode-escapes": "^7.14.5", + "@babel/plugin-transform-unicode-regex": "^7.14.5", + "@babel/preset-modules": "^0.1.4", + "@babel/types": "^7.14.8", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "core-js-compat": "^3.15.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/preset-react": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz", + "integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-react-display-name": "^7.16.7", + "@babel/plugin-transform-react-jsx": "^7.16.7", + "@babel/plugin-transform-react-jsx-development": "^7.16.7", + "@babel/plugin-transform-react-pure-annotations": "^7.16.7" + } + }, + "@babel/preset-typescript": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz", + "integrity": "sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-transform-typescript": "^7.16.7" + } + }, + "@babel/register": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.17.0.tgz", + "integrity": "sha512-UNZsMAZ7uKoGHo1HlEXfteEOYssf64n/PNLHGqOKq/bgYcu/4LrQWAHJwSCb3BRZK8Hi5gkJdRcwrGTO2wtRCg==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.5", + "source-map-support": "^0.5.16" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "@babel/runtime": { + "version": "7.14.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", + "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/traverse": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", + "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.17.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz", + "integrity": "sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@base2/pretty-print-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz", + "integrity": "sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==", + "dev": true + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "peer": true + }, + "@bitwarden/jslib-angular": { + "version": "file:../angular", + "requires": { + "@angular/animations": "^12.2.13", + "@angular/cdk": "^12.2.13", + "@angular/common": "^12.2.13", + "@angular/compiler": "^12.2.13", + "@angular/core": "^12.2.13", + "@angular/forms": "^12.2.13", + "@angular/platform-browser": "^12.2.13", + "@angular/platform-browser-dynamic": "^12.2.13", + "@angular/router": "^12.2.13", + "@bitwarden/jslib-common": "file:../common", + "@types/duo_web_sdk": "^2.7.1", + "duo_web_sdk": "git+https://github.com/duosecurity/duo_web_sdk.git", + "rimraf": "^3.0.2", + "rxjs": "^7.4.0", + "tldjs": "^2.3.1", + "typescript": "4.3.5", + "zone.js": "0.11.4" + } + }, + "@cnakazawa/watch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", + "integrity": "sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ==", + "dev": true, + "requires": { + "exec-sh": "^0.3.2", + "minimist": "^1.2.0" + } + }, + "@compodoc/compodoc": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.18.tgz", + "integrity": "sha512-+AFtcj2U3AJq6r8a2+PTdajIlS7m3pgvDhqgoYZJ4Rg/Zp9xvuDvUJU+5oHu8iHCAWwda3NoLUDjOZMNR8uIKg==", + "dev": true, + "requires": { + "@angular-devkit/schematics": "^13.1.2", + "@babel/core": "^7.16.7", + "@babel/preset-env": "^7.16.7", + "@compodoc/live-server": "^1.2.3", + "@compodoc/ngd-transformer": "^2.1.0", + "chalk": "^4.1.2", + "cheerio": "^1.0.0-rc.10", + "chokidar": "^3.5.2", + "colors": "1.4.0", + "commander": "^8.3.0", + "cosmiconfig": "^7.0.1", + "decache": "^4.6.1", + "fancy-log": "^2.0.0", + "findit2": "^2.2.3", + "fs-extra": "^10.0.0", + "glob": "^7.2.0", + "handlebars": "^4.7.7", + "html-entities": "^2.3.2", + "i18next": "^21.6.5", + "inside": "^1.0.0", + "json5": "^2.2.0", + "lodash": "^4.17.21", + "loglevel": "^1.8.0", + "loglevel-plugin-prefix": "^0.8.4", + "lunr": "^2.3.9", + "marked": "^4.0.9", + "minimist": "^1.2.5", + "opencollective-postinstall": "^2.0.3", + "os-name": "4.0.1", + "pdfjs-dist": "^2.12.313", + "pdfmake": "^0.2.4", + "semver": "^7.3.5", + "traverse": "^0.6.6", + "ts-morph": "^13.0.2", + "uuid": "^8.3.2" + }, + "dependencies": { + "@angular-devkit/schematics": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-13.2.3.tgz", + "integrity": "sha512-+dyC4iKV0huvpjiuz4uyjLNK3FsCIp/Ghv5lXvhG6yok/dCAubsJItJOxi6G16aVCzG/E9zbsDfm9fNMyVOkgQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "13.2.3", + "jsonc-parser": "3.0.0", + "magic-string": "0.25.7", + "ora": "5.4.1", + "rxjs": "6.6.7" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz", + "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz", + "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.16.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz", + "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-remap-async-to-generator": "^7.16.8" + } + }, + "@babel/preset-env": { + "version": "7.16.11", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz", + "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.16.8", + "@babel/helper-compilation-targets": "^7.16.7", + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/helper-validator-option": "^7.16.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-async-generator-functions": "^7.16.8", + "@babel/plugin-proposal-class-properties": "^7.16.7", + "@babel/plugin-proposal-class-static-block": "^7.16.7", + "@babel/plugin-proposal-dynamic-import": "^7.16.7", + "@babel/plugin-proposal-export-namespace-from": "^7.16.7", + "@babel/plugin-proposal-json-strings": "^7.16.7", + "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", + "@babel/plugin-proposal-numeric-separator": "^7.16.7", + "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-proposal-optional-catch-binding": "^7.16.7", + "@babel/plugin-proposal-optional-chaining": "^7.16.7", + "@babel/plugin-proposal-private-methods": "^7.16.11", + "@babel/plugin-proposal-private-property-in-object": "^7.16.7", + "@babel/plugin-proposal-unicode-property-regex": "^7.16.7", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.16.7", + "@babel/plugin-transform-async-to-generator": "^7.16.8", + "@babel/plugin-transform-block-scoped-functions": "^7.16.7", + "@babel/plugin-transform-block-scoping": "^7.16.7", + "@babel/plugin-transform-classes": "^7.16.7", + "@babel/plugin-transform-computed-properties": "^7.16.7", + "@babel/plugin-transform-destructuring": "^7.16.7", + "@babel/plugin-transform-dotall-regex": "^7.16.7", + "@babel/plugin-transform-duplicate-keys": "^7.16.7", + "@babel/plugin-transform-exponentiation-operator": "^7.16.7", + "@babel/plugin-transform-for-of": "^7.16.7", + "@babel/plugin-transform-function-name": "^7.16.7", + "@babel/plugin-transform-literals": "^7.16.7", + "@babel/plugin-transform-member-expression-literals": "^7.16.7", + "@babel/plugin-transform-modules-amd": "^7.16.7", + "@babel/plugin-transform-modules-commonjs": "^7.16.8", + "@babel/plugin-transform-modules-systemjs": "^7.16.7", + "@babel/plugin-transform-modules-umd": "^7.16.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8", + "@babel/plugin-transform-new-target": "^7.16.7", + "@babel/plugin-transform-object-super": "^7.16.7", + "@babel/plugin-transform-parameters": "^7.16.7", + "@babel/plugin-transform-property-literals": "^7.16.7", + "@babel/plugin-transform-regenerator": "^7.16.7", + "@babel/plugin-transform-reserved-words": "^7.16.7", + "@babel/plugin-transform-shorthand-properties": "^7.16.7", + "@babel/plugin-transform-spread": "^7.16.7", + "@babel/plugin-transform-sticky-regex": "^7.16.7", + "@babel/plugin-transform-template-literals": "^7.16.7", + "@babel/plugin-transform-typeof-symbol": "^7.16.7", + "@babel/plugin-transform-unicode-escapes": "^7.16.7", + "@babel/plugin-transform-unicode-regex": "^7.16.7", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.16.8", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "core-js-compat": "^3.20.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz", + "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz", + "integrity": "sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz", + "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@compodoc/live-server": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@compodoc/live-server/-/live-server-1.2.3.tgz", + "integrity": "sha512-hDmntVCyjjaxuJzPzBx68orNZ7TW4BtHWMnXlIVn5dqhK7vuFF/11hspO1cMmc+2QTYgqde1TBcb3127S7Zrow==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "colors": "1.4.0", + "connect": "^3.7.0", + "cors": "latest", + "event-stream": "4.0.1", + "faye-websocket": "0.11.x", + "http-auth": "4.1.9", + "http-auth-connect": "^1.0.5", + "morgan": "^1.10.0", + "object-assign": "latest", + "open": "8.4.0", + "proxy-middleware": "latest", + "send": "latest", + "serve-index": "^1.9.1" + }, + "dependencies": { + "open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + } + } + }, + "@compodoc/ngd-core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@compodoc/ngd-core/-/ngd-core-2.1.0.tgz", + "integrity": "sha512-nyBH7J7SJJ2AV6OeZhJ02kRtVB7ALnZJKgShjoL9CNmOFEj8AkdhP9qTBIgjaDrbsW5pF4nx32KQL2fT7RFnqw==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1", + "fancy-log": "^1.3.3", + "typescript": "^4.0.3" + }, + "dependencies": { + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + } + } + }, + "@compodoc/ngd-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@compodoc/ngd-transformer/-/ngd-transformer-2.1.0.tgz", + "integrity": "sha512-Jo4VCMzIUtgIAdRmhHhOoRRE01gCjc5CyrUERRx0VgEzkkCm1Wmu/XHSsQP6tSpCYHBjERghqaDqH5DabkR2oQ==", + "dev": true, + "requires": { + "@aduh95/viz.js": "^3.1.0", + "@compodoc/ngd-core": "~2.1.0", + "dot": "^1.1.3", + "fs-extra": "^9.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==", + "dev": true + }, + "@discoveryjs/json-ext": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz", + "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", + "dev": true + }, + "@emotion/cache": { + "version": "10.0.29", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-10.0.29.tgz", + "integrity": "sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==", + "dev": true, + "requires": { + "@emotion/sheet": "0.9.4", + "@emotion/stylis": "0.8.5", + "@emotion/utils": "0.11.3", + "@emotion/weak-memoize": "0.2.5" + } + }, + "@emotion/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.3.1.tgz", + "integrity": "sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.5", + "@emotion/cache": "^10.0.27", + "@emotion/css": "^10.0.27", + "@emotion/serialize": "^0.11.15", + "@emotion/sheet": "0.9.4", + "@emotion/utils": "0.11.3" + } + }, + "@emotion/css": { + "version": "10.0.27", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-10.0.27.tgz", + "integrity": "sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==", + "dev": true, + "requires": { + "@emotion/serialize": "^0.11.15", + "@emotion/utils": "0.11.3", + "babel-plugin-emotion": "^10.0.27" + } + }, + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "dev": true + }, + "@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "dev": true, + "requires": { + "@emotion/memoize": "0.7.4" + } + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "dev": true + }, + "@emotion/serialize": { + "version": "0.11.16", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-0.11.16.tgz", + "integrity": "sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==", + "dev": true, + "requires": { + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/unitless": "0.7.5", + "@emotion/utils": "0.11.3", + "csstype": "^2.5.7" + } + }, + "@emotion/sheet": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-0.9.4.tgz", + "integrity": "sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==", + "dev": true + }, + "@emotion/styled": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-10.3.0.tgz", + "integrity": "sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ==", + "dev": true, + "requires": { + "@emotion/styled-base": "^10.3.0", + "babel-plugin-emotion": "^10.0.27" + } + }, + "@emotion/styled-base": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@emotion/styled-base/-/styled-base-10.3.0.tgz", + "integrity": "sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.5", + "@emotion/is-prop-valid": "0.8.8", + "@emotion/serialize": "^0.11.15", + "@emotion/utils": "0.11.3" + } + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", + "dev": true + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "dev": true + }, + "@emotion/utils": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-0.11.3.tgz", + "integrity": "sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==", + "dev": true + }, + "@emotion/weak-memoize": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", + "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==", + "dev": true + }, + "@figspec/components": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@figspec/components/-/components-1.0.0.tgz", + "integrity": "sha512-a8sgP0YLJ3H0g0pdZPYecxfp9JNVQUTaaU3xcSci8duHXTGkJ7X8QPPCBbyhB+MoxMxnsAh8GjkfZHEr9oIoPQ==", + "dev": true, + "requires": { + "copy-to-clipboard": "^3.0.0", + "lit-element": "^2.4.0", + "lit-html": "^1.1.1" + } + }, + "@figspec/react": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@figspec/react/-/react-1.0.0.tgz", + "integrity": "sha512-BkOu3RsKF5vCtPoqsc6Oeyxw4wr9GesFrB9/wDHFqgjzhWsw8erFxCsPxsjdlJD8d8OWVHoM6SWxAaGe/pLdxg==", + "dev": true, + "requires": { + "@figspec/components": "^1.0.0" + } + }, + "@foliojs-fork/fontkit": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@foliojs-fork/fontkit/-/fontkit-1.9.1.tgz", + "integrity": "sha512-U589voc2/ROnvx1CyH9aNzOQWJp127JGU1QAylXGQ7LoEAF6hMmahZLQ4eqAcgHUw+uyW4PjtCItq9qudPkK3A==", + "dev": true, + "requires": { + "@foliojs-fork/restructure": "^2.0.2", + "brfs": "^2.0.0", + "brotli": "^1.2.0", + "browserify-optional": "^1.0.1", + "clone": "^1.0.4", + "deep-equal": "^1.0.0", + "dfa": "^1.2.0", + "tiny-inflate": "^1.0.2", + "unicode-properties": "^1.2.2", + "unicode-trie": "^2.0.0" + } + }, + "@foliojs-fork/linebreak": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@foliojs-fork/linebreak/-/linebreak-1.1.1.tgz", + "integrity": "sha512-pgY/+53GqGQI+mvDiyprvPWgkTlVBS8cxqee03ejm6gKAQNsR1tCYCIvN9FHy7otZajzMqCgPOgC4cHdt4JPig==", + "dev": true, + "requires": { + "base64-js": "1.3.1", + "brfs": "^2.0.2", + "unicode-trie": "^2.0.0" + }, + "dependencies": { + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + } + } + }, + "@foliojs-fork/pdfkit": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@foliojs-fork/pdfkit/-/pdfkit-0.13.0.tgz", + "integrity": "sha512-YXeG1fml9k97YNC9K8e292Pj2JzGt9uOIiBFuQFxHsdQ45BlxW+JU3RQK6JAvXU7kjhjP8rCcYvpk36JLD33sQ==", + "dev": true, + "requires": { + "@foliojs-fork/fontkit": "^1.9.1", + "@foliojs-fork/linebreak": "^1.1.1", + "crypto-js": "^4.0.0", + "png-js": "^1.0.0" + } + }, + "@foliojs-fork/restructure": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@foliojs-fork/restructure/-/restructure-2.0.2.tgz", + "integrity": "sha512-59SgoZ3EXbkfSX7b63tsou/SDGzwUEK6MuB5sKqgVK1/XE0fxmpsOb9DQI8LXW3KfGnAjImCGhhEb7uPPAUVNA==", + "dev": true + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "peer": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "peer": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "peer": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + } + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "peer": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/transform": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz", + "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.6.2", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.6.2", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.6.2", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jridgewell/resolve-uri": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-1.0.0.tgz", + "integrity": "sha512-9oLAnygRMi8Q5QkYEU4XWK04B+nuoXoxjRvRxgjuChkLZFBja0YPSgdZ7dZtwhncLBcQe/I/E+fLuk5qxcYVJA==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", + "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "dependencies": { + "@jridgewell/resolve-uri": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", + "dev": true + } + } + }, + "@jsdevtools/coverage-istanbul-loader": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", + "integrity": "sha512-EUCPEkaRPvmHjWAAZkWMT7JDzpw7FKB00WTISaiXsbNOd5hCHg77XLA8sLYLFDo1zepYLo2w7GstN8YBqRXZfA==", + "dev": true, + "requires": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.3", + "loader-utils": "^2.0.0", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.7.0" + } + }, + "@mdx-js/loader": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", + "integrity": "sha512-9CjGwy595NaxAYp0hF9B/A0lH6C8Rms97e2JS9d3jVUtILn6pT5i5IV965ra3lIWc7Rs1GG1tBdVF7dCowYe6Q==", + "dev": true, + "requires": { + "@mdx-js/mdx": "1.6.22", + "@mdx-js/react": "1.6.22", + "loader-utils": "2.0.0" + } + }, + "@mdx-js/mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-1.6.22.tgz", + "integrity": "sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==", + "dev": true, + "requires": { + "@babel/core": "7.12.9", + "@babel/plugin-syntax-jsx": "7.12.1", + "@babel/plugin-syntax-object-rest-spread": "7.8.3", + "@mdx-js/util": "1.6.22", + "babel-plugin-apply-mdx-type-prop": "1.6.22", + "babel-plugin-extract-import-names": "1.6.22", + "camelcase-css": "2.0.1", + "detab": "2.0.4", + "hast-util-raw": "6.0.1", + "lodash.uniq": "4.5.0", + "mdast-util-to-hast": "10.0.1", + "remark-footnotes": "2.0.0", + "remark-mdx": "1.6.22", + "remark-parse": "8.0.3", + "remark-squeeze-paragraphs": "4.0.0", + "style-to-object": "0.3.0", + "unified": "9.2.0", + "unist-builder": "2.0.3", + "unist-util-visit": "2.0.3" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@mdx-js/react": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", + "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", + "dev": true, + "requires": {} + }, + "@mdx-js/util": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/@mdx-js/util/-/util-1.6.22.tgz", + "integrity": "sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA==", + "dev": true + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + }, + "dependencies": { + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + } + } + }, + "@ngtools/webpack": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.16.tgz", + "integrity": "sha512-Y2wYX0ybpTYCuSXrG7+3FAtL4dSa7D1vMxymeJEmPTf5QcFTbllwcGQ82Q9lzTn3UDxvt6ZqAYfmWZHGp2GQ9w==", + "dev": true, + "requires": {} + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@npmcli/git": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-2.1.0.tgz", + "integrity": "sha512-/hBFX/QG1b+N7PZBFs0bi+evgRZcK9nWBxQKZkGoXUT5hJSwl5c4d7y8/hm+NQZRPhQ67RzFaj5UM9YeyKoryw==", + "dev": true, + "requires": { + "@npmcli/promise-spawn": "^1.3.2", + "lru-cache": "^6.0.0", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^6.1.1", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@npmcli/installed-package-contents": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", + "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "dev": true, + "requires": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@npmcli/node-gyp": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz", + "integrity": "sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==", + "dev": true + }, + "@npmcli/promise-spawn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz", + "integrity": "sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==", + "dev": true, + "requires": { + "infer-owner": "^1.0.4" + } + }, + "@npmcli/run-script": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-2.0.0.tgz", + "integrity": "sha512-fSan/Pu11xS/TdaTpTB0MRn9guwGU8dye+x56mEVgBEd/QsybBbYcAL0phPXi8SGWFEChkQd6M9qL4y6VOpFig==", + "dev": true, + "requires": { + "@npmcli/node-gyp": "^1.0.2", + "@npmcli/promise-spawn": "^1.3.2", + "node-gyp": "^8.2.0", + "read-package-json-fast": "^2.0.1" + } + }, + "@popperjs/core": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.2.tgz", + "integrity": "sha512-92FRmppjjqz29VMJ2dn+xdyXZBrMlE42AV6Kq6BwjWV7CNUW1hs2FtxSNLQE+gJhaZ6AAmYuO9y8dshhcBl7vA==", + "dev": true + }, + "@schematics/angular": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-12.2.16.tgz", + "integrity": "sha512-EITPMaRE7iCosf0nyZFOpxTDAiPD3qm4QUxHKcwIaJTrzi89nBoUubw8+pFy5/Gtpadww80YD8ODV64B1bPGMA==", + "dev": true, + "requires": { + "@angular-devkit/core": "12.2.16", + "@angular-devkit/schematics": "12.2.16", + "jsonc-parser": "3.0.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-12.2.16.tgz", + "integrity": "sha512-cnVtUYSET27B5mRIBp38mpKIX0iHv/hWKiPo74WCGrNwTgwmMHngjgQ4ySn/w1W4s8LL6TDW55ZkRdwyk8TVMQ==", + "dev": true, + "requires": { + "ajv": "8.6.2", + "ajv-formats": "2.1.0", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.6.7", + "source-map": "0.7.3" + } + }, + "ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.0.tgz", + "integrity": "sha512-USH2jBb+C/hIpwD2iRjp0pe0k+MvzG0mlSn/FIdCgQhUb9ALPRjt2KIQdfZDS9r0ZIeUAg7gOu9KL0PFqGqr5Q==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@storybook/addon-a11y": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-a11y/-/addon-a11y-6.4.19.tgz", + "integrity": "sha512-dG6easap6W4AqyggVZPq8lBrhza8StA8J4eYz/GVdoXINSGtq/casV0rkmY3+SUXhPYux5oGavHo86j5I4Q/0Q==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "axe-core": "^4.2.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "react-sizeme": "^3.0.1", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/addon-actions": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.19.tgz", + "integrity": "sha512-GpSvP8xV8GfNkmtGJjfCgaOx6mbjtyTK0aT9FqX9pU0s+KVMmoCTrBh43b7dWrwxxas01yleBK9VpYggzhi/Fw==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "polished": "^4.0.5", + "prop-types": "^15.7.2", + "react-inspector": "^5.1.0", + "regenerator-runtime": "^0.13.7", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "uuid-browser": "^3.1.0" + } + }, + "@storybook/addon-backgrounds": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.4.19.tgz", + "integrity": "sha512-yn8MTE7lctO48Rdw+DmmA1wKdf5eyAbA/vrug5ske/U2WPgGc65sApzwT8BItZfuyAMjuT5RnCWwd7o6hGRgGQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/addon-controls": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.4.19.tgz", + "integrity": "sha512-JHi5z9i6NsgQLfG5WOeQE1AyOrM+QJLrjT+uOYx40bq+OC1yWHH7qHiphPP8kjJJhCZlaQk1qqXYkkQXgaeHSw==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/node-logger": "6.4.19", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "lodash": "^4.17.21", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-docs": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.4.19.tgz", + "integrity": "sha512-OEPyx/5ZXmZOPqIAWoPjlIP8Q/YfNjAmBosA8tmA8t5KCSiq/vpLcAvQhxqK6n0wk/B8Xp67Z8RpLfXjU8R3tw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/generator": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/plugin-transform-react-jsx": "^7.12.12", + "@babel/preset-env": "^7.12.11", + "@jest/transform": "^26.6.2", + "@mdx-js/loader": "^1.6.22", + "@mdx-js/mdx": "^1.6.22", + "@mdx-js/react": "^1.6.22", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/builder-webpack4": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/csf-tools": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/postinstall": "6.4.19", + "@storybook/preview-web": "6.4.19", + "@storybook/source-loader": "6.4.19", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "acorn": "^7.4.1", + "acorn-jsx": "^5.3.1", + "acorn-walk": "^7.2.0", + "core-js": "^3.8.2", + "doctrine": "^3.0.0", + "escodegen": "^2.0.0", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "html-tags": "^3.1.0", + "js-string-escape": "^1.0.1", + "loader-utils": "^2.0.0", + "lodash": "^4.17.21", + "nanoid": "^3.1.23", + "p-limit": "^3.1.0", + "prettier": ">=2.2.1 <=2.3.0", + "prop-types": "^15.7.2", + "react-element-to-jsx-string": "^14.3.4", + "regenerator-runtime": "^0.13.7", + "remark-external-links": "^8.0.0", + "remark-slug": "^6.0.0", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/addon-essentials": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.4.19.tgz", + "integrity": "sha512-vbV8sjepMVEuwhTDBHjO3E6vXluG7RiEeozV1QVuS9lGhjQdvUPdZ9rDNUcP6WHhTdEkS/ffTMaGIy1v8oZd7g==", + "dev": true, + "requires": { + "@storybook/addon-actions": "6.4.19", + "@storybook/addon-backgrounds": "6.4.19", + "@storybook/addon-controls": "6.4.19", + "@storybook/addon-docs": "6.4.19", + "@storybook/addon-measure": "6.4.19", + "@storybook/addon-outline": "6.4.19", + "@storybook/addon-toolbars": "6.4.19", + "@storybook/addon-viewport": "6.4.19", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/node-logger": "6.4.19", + "core-js": "^3.8.2", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-links": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.19.tgz", + "integrity": "sha512-ebFHYlGDQkHSmI5QEJb1NxGNToVOLgjKkxXUe+JXX7AfHvrWiXVrN/57aOtBPZzj4h2jRPRTZgwR5glhPIlfEQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/router": "6.4.19", + "@types/qs": "^6.9.5", + "core-js": "^3.8.2", + "global": "^4.4.0", + "prop-types": "^15.7.2", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-measure": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.4.19.tgz", + "integrity": "sha512-PXeU0AlpnGEvnzBQ6snkzmlIpwE0ci8LdFtL1Vz1V1Xk5fbuETWYuEkPuk1oZ7L9igB9cfT32SyJlE5MC1iaGg==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "global": "^4.4.0" + } + }, + "@storybook/addon-outline": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.4.19.tgz", + "integrity": "sha512-7ZDXo8qrms6dx0KRP9PInXIie82h5g9XCNrGOUdfZkQPvgofJVj0kNv6p+WOiGiaVfKPC5KMgIofqzBTFV+k6Q==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/addon-toolbars": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.4.19.tgz", + "integrity": "sha512-2UtuX9yB1rD/CAZv1etnOnunfPTvsEKEg/J2HYMKE1lhenWC5muIUXvDXCXvwDC65WviPJ56nFNKaKK1Zz7JDg==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "regenerator-runtime": "^0.13.7" + } + }, + "@storybook/addon-viewport": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.4.19.tgz", + "integrity": "sha512-T1hdImxbLj8suQSTbp6HSA1LLHOlqaNK5jjnqzEOoAxY0O8LNPXMJ2jKIeT2fPQ0v+tWGU3tbwf+3xFq0parVQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "prop-types": "^15.7.2", + "regenerator-runtime": "^0.13.7" + } + }, + "@storybook/addons": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.19.tgz", + "integrity": "sha512-QNyRYhpqmHV8oJxxTBdkRlLSbDFhpBvfvMfIrIT1UXb/eemdBZTaCGVvXZ9UixoEEI7f8VwAQ44IvkU5B1509w==", + "dev": true, + "requires": { + "@storybook/api": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/router": "6.4.19", + "@storybook/theming": "6.4.19", + "@types/webpack-env": "^1.16.0", + "core-js": "^3.8.2", + "global": "^4.4.0", + "regenerator-runtime": "^0.13.7" + } + }, + "@storybook/angular": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/angular/-/angular-6.4.19.tgz", + "integrity": "sha512-CyJg9reKbk69gkYK1QJhzPydVMeelJ1Fj2VvK5qKL6xEwHSj9buYmbS631i8AC0c9vIWv5lk2BENCLyGqdPYwQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/core": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/node-logger": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@types/webpack-env": "^1.16.0", + "autoprefixer": "^9.8.6", + "core-js": "^3.8.2", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^4.1.6", + "global": "^4.4.0", + "postcss": "^7.0.36", + "postcss-loader": "^4.2.0", + "raw-loader": "^4.0.2", + "react": "16.14.0", + "react-dom": "16.14.0", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "sass-loader": "^10.1.0", + "strip-json-comments": "3.1.1", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "ts-loader": "^8.0.14", + "tsconfig-paths-webpack-plugin": "^3.3.0", + "util-deprecate": "^1.0.2", + "webpack": "4" + }, + "dependencies": { + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + } + }, + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "sass-loader": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.2.1.tgz", + "integrity": "sha512-RRvWl+3K2LSMezIsd008ErK4rk6CulIMSwrcc2aZvjymUgKo/vjXGp1rSWmfTUX7bblEOz8tst4wBwWtCGBqKA==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "neo-async": "^2.6.2", + "schema-utils": "^3.0.0", + "semver": "^7.3.2" + } + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/api": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.4.19.tgz", + "integrity": "sha512-aDvea+NpQCBjpNp9YidO1Pr7fzzCp15FSdkG+2ihGQfv5raxrN+IIJnGUXecpe71nvlYiB+29UXBVK7AL0j51Q==", + "dev": true, + "requires": { + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/theming": "6.4.19", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "store2": "^2.12.0", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/builder-webpack4": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.19.tgz", + "integrity": "sha512-wxA6SMH11duc9D53aeVVBwrVRemFIoxHp/dOugkkg6ZZFAb4ZmWzf/ENc3vQIZdZpfNRi7IZIZEOfoHc994cmw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-proposal-export-default-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.12", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/preview-web": "6.4.19", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "@storybook/ui": "6.4.19", + "@types/node": "^14.0.10", + "@types/webpack": "^4.41.26", + "autoprefixer": "^9.8.6", + "babel-loader": "^8.0.0", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-polyfill-corejs3": "^0.1.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^3.6.0", + "file-loader": "^6.2.0", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^4.1.6", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "global": "^4.4.0", + "html-webpack-plugin": "^4.0.0", + "pnp-webpack-plugin": "1.6.4", + "postcss": "^7.0.36", + "postcss-flexbugs-fixes": "^4.2.1", + "postcss-loader": "^4.2.0", + "raw-loader": "^4.0.2", + "stable": "^0.1.8", + "style-loader": "^1.3.0", + "terser-webpack-plugin": "^4.2.3", + "ts-dedent": "^2.0.0", + "url-loader": "^4.1.1", + "util-deprecate": "^1.0.2", + "webpack": "4", + "webpack-dev-middleware": "^3.7.3", + "webpack-filter-warnings-plugin": "^1.2.1", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.2.2" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", + "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", + "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.1.5", + "core-js-compat": "^3.8.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "webpack-filter-warnings-plugin": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/webpack-filter-warnings-plugin/-/webpack-filter-warnings-plugin-1.2.1.tgz", + "integrity": "sha512-Ez6ytc9IseDMLPo0qCuNNYzgtUl8NovOqjIq4uAU8LTD4uoa1w1KpZyyzFtLTEMZpkkOkLfL9eN+KGYdk1Qtwg==", + "dev": true, + "requires": {} + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/builder-webpack5": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-6.4.19.tgz", + "integrity": "sha512-AWM4YMN1gPaf7jfntqZTCGpIQ1tF6YRU1JtczPG4ox28rTaO6NMfOBi9aRhBre/59pPOh9bF6u2gu/MIHmRW+w==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-proposal-export-default-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.12", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/preview-web": "6.4.19", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@storybook/theming": "6.4.19", + "@types/node": "^14.0.10", + "babel-loader": "^8.0.0", + "babel-plugin-macros": "^3.0.1", + "babel-plugin-polyfill-corejs3": "^0.1.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "glob": "^7.1.6", + "glob-promise": "^3.4.0", + "html-webpack-plugin": "^5.0.0", + "path-browserify": "^1.0.1", + "process": "^0.11.10", + "stable": "^0.1.8", + "style-loader": "^2.0.0", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-hot-middleware": "^2.25.1", + "webpack-virtual-modules": "^0.4.1" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", + "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "optional": true, + "peer": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", + "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.1.5", + "core-js-compat": "^3.8.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "clean-css": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + } + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", + "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + } + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + } + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "dependencies": { + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + } + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + } + }, + "webpack-virtual-modules": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", + "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", + "dev": true + } + } + }, + "@storybook/channel-postmessage": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.19.tgz", + "integrity": "sha512-E5h/itFzQ/6M08LR4kqlgqqmeO3tmavI+nUAlZrkCrotpJFNMHE2i0PQHg0TkFJrRDpYcrwD+AjUW4IwdqrisQ==", + "dev": true, + "requires": { + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "qs": "^6.10.0", + "telejson": "^5.3.2" + } + }, + "@storybook/channel-websocket": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.19.tgz", + "integrity": "sha512-cXKwQjIXttfdUyZlcHORelUmJ5nUKswsnCA/qy7IRWpZjD8yQJcNk1dYC+tTHDVqFgdRT89pL0hRRB1rlaaR8Q==", + "dev": true, + "requires": { + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "core-js": "^3.8.2", + "global": "^4.4.0", + "telejson": "^5.3.2" + } + }, + "@storybook/channels": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.19.tgz", + "integrity": "sha512-EwyoncFvTfmIlfsy8jTfayCxo2XchPkZk/9txipugWSmc057HdklMKPLOHWP0z5hLH0IbVIKXzdNISABm36jwQ==", + "dev": true, + "requires": { + "core-js": "^3.8.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/client-api": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.19.tgz", + "integrity": "sha512-OCrT5Um3FDvZnimQKwWtwsaI+5agPwq2i8YiqlofrI/NPMKp0I7DEkCGwE5IRD1Q8BIKqHcMo5tTmfYi0AxyOg==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/store": "6.4.19", + "@types/qs": "^6.9.5", + "@types/webpack-env": "^1.16.0", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "store2": "^2.12.0", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/client-logger": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.19.tgz", + "integrity": "sha512-zmg/2wyc9W3uZrvxaW4BfHcr40J0v7AGslqYXk9H+ERLVwIvrR4NhxQFaS6uITjBENyRDxwzfU3Va634WcmdDQ==", + "dev": true, + "requires": { + "core-js": "^3.8.2", + "global": "^4.4.0" + } + }, + "@storybook/components": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.4.19.tgz", + "integrity": "sha512-q/0V37YAJA7CNc+wSiiefeM9+3XVk8ixBNylY36QCGJgIeGQ5/79vPyUe6K4lLmsQwpmZsIq1s1Ad5+VbboeOA==", + "dev": true, + "requires": { + "@popperjs/core": "^2.6.0", + "@storybook/client-logger": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/theming": "6.4.19", + "@types/color-convert": "^2.0.0", + "@types/overlayscrollbars": "^1.12.0", + "@types/react-syntax-highlighter": "11.0.5", + "color-convert": "^2.0.1", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.1.3", + "memoizerific": "^1.11.3", + "overlayscrollbars": "^1.13.1", + "polished": "^4.0.5", + "prop-types": "^15.7.2", + "react-colorful": "^5.1.2", + "react-popper-tooltip": "^3.1.1", + "react-syntax-highlighter": "^13.5.3", + "react-textarea-autosize": "^8.3.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/core": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.4.19.tgz", + "integrity": "sha512-55LOQ/h/kf1jMhjN85t/pIEdIwWEG9yV7bdwv3niVvmoypCxyyjn9/QNK0RKYAeDSUtdm6FVoJ6k5CpxWz2d8w==", + "dev": true, + "requires": { + "@storybook/core-client": "6.4.19", + "@storybook/core-server": "6.4.19" + } + }, + "@storybook/core-client": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.19.tgz", + "integrity": "sha512-rQHRZjhArPleE7/S8ZUolgzwY+hC0smSKX/3PQxO2GcebDjnJj6+iSV3h+aSMHMmTdoCQvjYw9aBpT8scuRe+A==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/channel-websocket": "6.4.19", + "@storybook/client-api": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/preview-web": "6.4.19", + "@storybook/store": "6.4.19", + "@storybook/ui": "6.4.19", + "airbnb-js-shims": "^2.2.1", + "ansi-to-html": "^0.6.11", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0", + "unfetch": "^4.2.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/core-common": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.19.tgz", + "integrity": "sha512-X1pJJkO48DFxl6iyEemIKqRkJ7j9/cBh3BRBUr+xZHXBvnD0GKDXIocwh0PjSxSC6XSu3UCQnqtKi3PbjRl8Dg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-proposal-decorators": "^7.12.12", + "@babel/plugin-proposal-export-default-from": "^7.12.1", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1", + "@babel/plugin-proposal-object-rest-spread": "^7.12.1", + "@babel/plugin-proposal-optional-chaining": "^7.12.7", + "@babel/plugin-proposal-private-methods": "^7.12.1", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.12.1", + "@babel/plugin-transform-block-scoping": "^7.12.12", + "@babel/plugin-transform-classes": "^7.12.1", + "@babel/plugin-transform-destructuring": "^7.12.1", + "@babel/plugin-transform-for-of": "^7.12.1", + "@babel/plugin-transform-parameters": "^7.12.1", + "@babel/plugin-transform-shorthand-properties": "^7.12.1", + "@babel/plugin-transform-spread": "^7.12.1", + "@babel/preset-env": "^7.12.11", + "@babel/preset-react": "^7.12.10", + "@babel/preset-typescript": "^7.12.7", + "@babel/register": "^7.12.1", + "@storybook/node-logger": "6.4.19", + "@storybook/semver": "^7.3.2", + "@types/node": "^14.0.10", + "@types/pretty-hrtime": "^1.0.0", + "babel-loader": "^8.0.0", + "babel-plugin-macros": "^3.0.1", + "babel-plugin-polyfill-corejs3": "^0.1.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "express": "^4.17.1", + "file-system-cache": "^1.0.5", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.0.4", + "fs-extra": "^9.0.1", + "glob": "^7.1.6", + "handlebars": "^4.7.7", + "interpret": "^2.2.0", + "json5": "^2.1.3", + "lazy-universal-dotenv": "^3.0.1", + "picomatch": "^2.3.0", + "pkg-dir": "^5.0.0", + "pretty-hrtime": "^1.0.3", + "resolve-from": "^5.0.0", + "slash": "^3.0.0", + "telejson": "^5.3.2", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "4" + }, + "dependencies": { + "@babel/helper-define-polyfill-provider": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz", + "integrity": "sha512-nXuzCSwlJ/WKr8qxzW816gwyT6VZgiJG17zR40fou70yfAcqjoNyTLl/DQ+FExw5Hx5KNqshmN8Ldl/r2N7cTg==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz", + "integrity": "sha512-u+gbS9bbPhZWEeyy1oR/YaaSpod/KDT07arZHb80aTpl8H5ZBq+uN1nN9/xtX7jQyfLdPfoqI4Rue/MQSWJquw==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.1.5", + "core-js-compat": "^3.8.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "fork-ts-checker-webpack-plugin": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", + "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + } + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/core-events": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.19.tgz", + "integrity": "sha512-KICzUw6XVQUJzFSCXfvhfHAuyhn4Q5J4IZEfuZkcGJS4ODkrO6tmpdYE5Cfr+so95Nfp0ErWiLUuodBsW9/rtA==", + "dev": true, + "requires": { + "core-js": "^3.8.2" + } + }, + "@storybook/core-server": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.19.tgz", + "integrity": "sha512-bKsUB9f7hl5ya2JXxpIrErmbDQjoH39FVbzYZWjMo4t/b7+Xyi6vYadwyWcqlpUQmis09ZaSMv8L/Tw0TuwLAA==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.3", + "@storybook/builder-webpack4": "6.4.19", + "@storybook/core-client": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/csf-tools": "6.4.19", + "@storybook/manager-webpack4": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/store": "6.4.19", + "@types/node": "^14.0.10", + "@types/node-fetch": "^2.5.7", + "@types/pretty-hrtime": "^1.0.0", + "@types/webpack": "^4.41.26", + "better-opn": "^2.1.1", + "boxen": "^5.1.2", + "chalk": "^4.1.0", + "cli-table3": "^0.6.1", + "commander": "^6.2.1", + "compression": "^1.7.4", + "core-js": "^3.8.2", + "cpy": "^8.1.2", + "detect-port": "^1.3.0", + "express": "^4.17.1", + "file-system-cache": "^1.0.5", + "fs-extra": "^9.0.1", + "globby": "^11.0.2", + "ip": "^1.1.5", + "lodash": "^4.17.21", + "node-fetch": "^2.6.1", + "pretty-hrtime": "^1.0.3", + "prompts": "^2.4.0", + "regenerator-runtime": "^0.13.7", + "serve-favicon": "^2.5.0", + "slash": "^3.0.0", + "telejson": "^5.3.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "watchpack": "^2.2.0", + "webpack": "4", + "ws": "^8.2.3" + }, + "dependencies": { + "@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + } + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/csf": { + "version": "0.0.2--canary.87bc651.0", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.2--canary.87bc651.0.tgz", + "integrity": "sha512-ajk1Uxa+rBpFQHKrCcTmJyQBXZ5slfwHVEaKlkuFaW77it8RgbPJp/ccna3sgoi8oZ7FkkOyvv1Ve4SmwFqRqw==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "@storybook/csf-tools": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.19.tgz", + "integrity": "sha512-gf/zRhGoAVsFwSyV2tc+jeJfZQkxF6QsaZgbUSe24/IUvGFCT/PS/jZq1qy7dECAwrTOfykgu8juyBtj6WhWyw==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/generator": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/plugin-transform-react-jsx": "^7.12.12", + "@babel/preset-env": "^7.12.11", + "@babel/traverse": "^7.12.11", + "@babel/types": "^7.12.11", + "@mdx-js/mdx": "^1.6.22", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "fs-extra": "^9.0.1", + "global": "^4.4.0", + "js-string-escape": "^1.0.1", + "lodash": "^4.17.21", + "prettier": ">=2.2.1 <=2.3.0", + "regenerator-runtime": "^0.13.7", + "ts-dedent": "^2.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + } + } + }, + "@storybook/manager-webpack4": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.19.tgz", + "integrity": "sha512-R8ugZjTYqXvlc6gDOcw909L65sIleOmIJLZR+N6/H85MivGXHu39jOwONqB7tVACufRty4FNecn8tEiQL2SAKA==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.4.19", + "@storybook/core-client": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/theming": "6.4.19", + "@storybook/ui": "6.4.19", + "@types/node": "^14.0.10", + "@types/webpack": "^4.41.26", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^3.6.0", + "express": "^4.17.1", + "file-loader": "^6.2.0", + "file-system-cache": "^1.0.5", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^4.0.0", + "node-fetch": "^2.6.1", + "pnp-webpack-plugin": "1.6.4", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^1.3.0", + "telejson": "^5.3.2", + "terser-webpack-plugin": "^4.2.3", + "ts-dedent": "^2.0.0", + "url-loader": "^4.1.1", + "util-deprecate": "^1.0.2", + "webpack": "4", + "webpack-dev-middleware": "^3.7.3", + "webpack-virtual-modules": "^0.2.2" + }, + "dependencies": { + "@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "dependencies": { + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + } + } + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "style-loader": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser-webpack-plugin": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", + "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", + "dev": true, + "requires": { + "cacache": "^15.0.5", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.5.0", + "p-limit": "^3.0.2", + "schema-utils": "^3.0.0", + "serialize-javascript": "^5.0.1", + "source-map": "^0.6.1", + "terser": "^5.3.4", + "webpack-sources": "^1.4.3" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + } + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@storybook/manager-webpack5": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack5/-/manager-webpack5-6.4.19.tgz", + "integrity": "sha512-hVjWhWAOgWaymBy0HeRskN+MfKLpqLP4Txfw+3Xqg1qplgexV0w2O4BQrS/SNEH4V/1qF9h8XTsk3L3oQIj3Mg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.10", + "@babel/plugin-transform-template-literals": "^7.12.1", + "@babel/preset-react": "^7.12.10", + "@storybook/addons": "6.4.19", + "@storybook/core-client": "6.4.19", + "@storybook/core-common": "6.4.19", + "@storybook/node-logger": "6.4.19", + "@storybook/theming": "6.4.19", + "@storybook/ui": "6.4.19", + "@types/node": "^14.0.10", + "babel-loader": "^8.0.0", + "case-sensitive-paths-webpack-plugin": "^2.3.0", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "css-loader": "^5.0.1", + "express": "^4.17.1", + "file-system-cache": "^1.0.5", + "find-up": "^5.0.0", + "fs-extra": "^9.0.1", + "html-webpack-plugin": "^5.0.0", + "node-fetch": "^2.6.1", + "process": "^0.11.10", + "read-pkg-up": "^7.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "style-loader": "^2.0.0", + "telejson": "^5.3.2", + "terser-webpack-plugin": "^5.0.3", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2", + "webpack": "^5.9.0", + "webpack-dev-middleware": "^4.1.0", + "webpack-virtual-modules": "^0.4.1" + }, + "dependencies": { + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "@types/node": { + "version": "14.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.12.tgz", + "integrity": "sha512-q4jlIR71hUpWTnGhXWcakgkZeHa3CCjcQcnuzU8M891BAWA2jHiziiWEPEkdS5pFsz7H9HJiy8BrK7tBRNrY7A==", + "dev": true + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "optional": true, + "peer": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "clean-css": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.2.4.tgz", + "integrity": "sha512-nKseG8wCzEuji/4yrgM/5cthL9oTDc5UOQyFMvW/Q53oP6gLH690o1NbuTh6Y18nujr7BxlsFuS7gXLnLzKJGg==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-loader": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", + "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.5" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + } + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "style-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", + "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "terser": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "webpack-dev-middleware": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz", + "integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.30", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + } + }, + "webpack-virtual-modules": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.3.tgz", + "integrity": "sha512-5NUqC2JquIL2pBAAo/VfBP6KuGkHIZQXW/lNKupLPfhViwh8wNsu0BObtl09yuKZszeEUfbXz8xhrHvSG16Nqw==", + "dev": true + } + } + }, + "@storybook/node-logger": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.19.tgz", + "integrity": "sha512-hO2Aar3PgPnPtNq2fVgiuGlqo3EEVR6TKVBXMq7foL3tN2k4BQFKLDHbm5qZQQntyYKurKsRUGKPJFPuI1ov/w==", + "dev": true, + "requires": { + "@types/npmlog": "^4.1.2", + "chalk": "^4.1.0", + "core-js": "^3.8.2", + "npmlog": "^5.0.1", + "pretty-hrtime": "^1.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@storybook/postinstall": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.4.19.tgz", + "integrity": "sha512-/0tHHxyIV82zt1rw4BW70GmrQbDVu9IJPAxOqFzGjC1fNojwJ53mK6FfUsOzbhG5mWk5p0Ip5+zr74moP119AA==", + "dev": true, + "requires": { + "core-js": "^3.8.2" + } + }, + "@storybook/preview-web": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.19.tgz", + "integrity": "sha512-jqltoBv5j7lvnxEfV9w8dLX9ASWGuvgz97yg8Yo5FqkftEwrHJenyvMGcTgDJKJPorF+wiz/9aIqnmd3LCAcZQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/channel-postmessage": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "@storybook/store": "6.4.19", + "ansi-to-html": "^0.6.11", + "core-js": "^3.8.2", + "global": "^4.4.0", + "lodash": "^4.17.21", + "qs": "^6.10.0", + "regenerator-runtime": "^0.13.7", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "unfetch": "^4.2.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/router": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.4.19.tgz", + "integrity": "sha512-KWWwIzuyeEIWVezkCihwY2A76Il9tUNg0I410g9qT7NrEsKyqXGRYOijWub7c1GGyNjLqz0jtrrehtixMcJkuA==", + "dev": true, + "requires": { + "@storybook/client-logger": "6.4.19", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "history": "5.0.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "qs": "^6.10.0", + "react-router": "^6.0.0", + "react-router-dom": "^6.0.0", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@storybook/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-SWeszlsiPsMI0Ps0jVNtH64cI5c0UF3f7KgjVKJoNP30crQ6wUSddY2hsdeczZXEKVJGEn50Q60flcGsQGIcrg==", + "dev": true, + "requires": { + "core-js": "^3.6.5", + "find-up": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, + "@storybook/source-loader": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.19.tgz", + "integrity": "sha512-XqTsqddRglvfW7mhyjwoqd/B8L6samcBehhO0OEbsFp6FPWa9eXuObCxtRYIcjcSIe+ksbW3D/54ppEs1L/g1Q==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "estraverse": "^5.2.0", + "global": "^4.4.0", + "loader-utils": "^2.0.0", + "lodash": "^4.17.21", + "prettier": ">=2.2.1 <=2.3.0", + "regenerator-runtime": "^0.13.7" + } + }, + "@storybook/store": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.4.19.tgz", + "integrity": "sha512-N9/ZjemRHGfT3InPIbqQqc6snkcfnf3Qh9oOr0smbfaVGJol//KOX65kzzobtzFcid0WxtTDZ3HmgFVH+GvuhQ==", + "dev": true, + "requires": { + "@storybook/addons": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/csf": "0.0.2--canary.87bc651.0", + "core-js": "^3.8.2", + "fast-deep-equal": "^3.1.3", + "global": "^4.4.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3", + "regenerator-runtime": "^0.13.7", + "slash": "^3.0.0", + "stable": "^0.1.8", + "synchronous-promise": "^2.0.15", + "ts-dedent": "^2.0.0", + "util-deprecate": "^1.0.2" + } + }, + "@storybook/theming": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.19.tgz", + "integrity": "sha512-V4pWmTvAxmbHR6B3jA4hPkaxZPyExHvCToy7b76DpUTpuHihijNDMAn85KhOQYIeL9q14zP/aiz899tOHsOidg==", + "dev": true, + "requires": { + "@emotion/core": "^10.1.1", + "@emotion/is-prop-valid": "^0.8.6", + "@emotion/styled": "^10.0.27", + "@storybook/client-logger": "6.4.19", + "core-js": "^3.8.2", + "deep-object-diff": "^1.1.0", + "emotion-theming": "^10.0.27", + "global": "^4.4.0", + "memoizerific": "^1.11.3", + "polished": "^4.0.5", + "resolve-from": "^5.0.0", + "ts-dedent": "^2.0.0" + } + }, + "@storybook/ui": { + "version": "6.4.19", + "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.19.tgz", + "integrity": "sha512-gFwdn5LA2U6oQ4bfUFLyHZnNasGQ01YVdwjbi+l6yjmnckBNtZfJoVTZ1rzGUbxSE9rK48InJRU+latTsr7xAg==", + "dev": true, + "requires": { + "@emotion/core": "^10.1.1", + "@storybook/addons": "6.4.19", + "@storybook/api": "6.4.19", + "@storybook/channels": "6.4.19", + "@storybook/client-logger": "6.4.19", + "@storybook/components": "6.4.19", + "@storybook/core-events": "6.4.19", + "@storybook/router": "6.4.19", + "@storybook/semver": "^7.3.2", + "@storybook/theming": "6.4.19", + "copy-to-clipboard": "^3.3.1", + "core-js": "^3.8.2", + "core-js-pure": "^3.8.2", + "downshift": "^6.0.15", + "emotion-theming": "^10.0.27", + "fuse.js": "^3.6.1", + "global": "^4.4.0", + "lodash": "^4.17.21", + "markdown-to-jsx": "^7.1.3", + "memoizerific": "^1.11.3", + "polished": "^4.0.5", + "qs": "^6.10.0", + "react-draggable": "^4.4.3", + "react-helmet-async": "^1.0.7", + "react-sizeme": "^3.0.1", + "regenerator-runtime": "^0.13.7", + "resolve-from": "^5.0.0", + "store2": "^2.12.0" + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true + }, + "@ts-morph/common": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.12.3.tgz", + "integrity": "sha512-4tUmeLyXJnJWvTFOKtcNJ1yh0a3SsTLi2MUoyj8iUNznFRN1ZquaNe7Oukqrnki2FzZkm0J9adCNLDZxUzvj+w==", + "dev": true, + "requires": { + "fast-glob": "^3.2.7", + "minimatch": "^3.0.4", + "mkdirp": "^1.0.4", + "path-browserify": "^1.0.1" + } + }, + "@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "peer": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "peer": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/color-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz", + "integrity": "sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==", + "dev": true, + "requires": { + "@types/color-name": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true, + "optional": true, + "peer": true + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true, + "optional": true, + "peer": true + }, + "@types/eslint": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.1.tgz", + "integrity": "sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/hast": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", + "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "dev": true, + "requires": { + "@types/unist": "*" + } + }, + "@types/html-minifier-terser": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.2.tgz", + "integrity": "sha512-h4lTMgMJctJybDp8CQrxTUiiYmedihHWkjnF/8Pxseu2S6Nlfcy8kwboQ8yejh456rP2yWoEVm1sS/FVsfM48w==", + "dev": true + }, + "@types/is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha512-A79HEEiwXTFtfY+Bcbo58M2GRYzCr9itHWzbzHVFNEYCcoU/MMGwYYf721gBrnhpj1s6RGVVha/IgNFnR0Iw/Q==", + "dev": true + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@types/mdast": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", + "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "dev": true, + "requires": { + "@types/unist": "*" + } + }, + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "@types/node": { + "version": "16.11.33", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.33.tgz", + "integrity": "sha512-0PJ0vg+JyU0MIan58IOIFRtSvsb7Ri+7Wltx2qAg94eMOrpg4+uuP3aUHCpxXc1i0jCXiC+zIamSZh3l9AbcQA==", + "dev": true + }, + "@types/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "@types/npmlog": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/npmlog/-/npmlog-4.1.4.tgz", + "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", + "dev": true + }, + "@types/overlayscrollbars": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@types/overlayscrollbars/-/overlayscrollbars-1.12.1.tgz", + "integrity": "sha512-V25YHbSoKQN35UasHf0EKD9U2vcmexRSp78qa8UglxFH8H3D+adEa9zGZwrqpH4TdvqeMrgMqVqsLB4woAryrQ==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/parse5": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-5.0.3.tgz", + "integrity": "sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw==", + "dev": true + }, + "@types/prettier": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==", + "dev": true, + "peer": true + }, + "@types/pretty-hrtime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz", + "integrity": "sha512-VjID5MJb1eGKthz2qUerWT8+R4b9N+CHvGCzg9fn4kWZgaF9AhdYikQio3R7wV8YY1NsQKPaCwKz1Yff+aHNUQ==", + "dev": true + }, + "@types/prop-types": { + "version": "15.7.4", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", + "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==", + "dev": true + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/react": { + "version": "17.0.39", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.39.tgz", + "integrity": "sha512-UVavlfAxDd/AgAacMa60Azl7ygyQNRwC/DsHZmKgNvPmRR5p70AJ5Q9EAmL2NWOJmeV+vVUI4IAP7GZrN8h8Ug==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.10.tgz", + "integrity": "sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA==", + "dev": true + } + } + }, + "@types/react-syntax-highlighter": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.5.tgz", + "integrity": "sha512-VIOi9i2Oj5XsmWWoB72p3KlZoEbdRAcechJa8Ztebw7bDl2YmR+odxIqhtJGp1q2EozHs02US+gzxJ9nuf56qg==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/tapable": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz", + "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==", + "dev": true + }, + "@types/uglify-js": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", + "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@types/unist": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz", + "integrity": "sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==", + "dev": true + }, + "@types/webpack": { + "version": "4.41.32", + "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz", + "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@types/webpack-env": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.16.3.tgz", + "integrity": "sha512-9gtOPPkfyNoEqCQgx4qJKkuNm/x0R2hKR7fdl7zvTJyHnIisuE/LfvXOsYWL0o3qq6uiBnKZNNNzi3l0y/X+xw==", + "dev": true + }, + "@types/webpack-sources": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz", + "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.7.3" + } + }, + "@types/yargs": { + "version": "15.0.14", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.14.tgz", + "integrity": "sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "20.2.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", + "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + }, + "dependencies": { + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + } + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + }, + "dependencies": { + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + } + } + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + }, + "dependencies": { + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + } + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webcomponents/custom-elements": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@webcomponents/custom-elements/-/custom-elements-1.5.0.tgz", + "integrity": "sha512-c+7jPQCs9h/BYVcZ2Kna/3tsl3A/9EyXfvWjp5RiTDm1OpTcbZaCa1z4RNcTe/hUtXaqn64JjNW1yrWT+rZ8gg==", + "dev": true + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "abab": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz", + "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==", + "dev": true + }, + "adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + } + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.0.tgz", + "integrity": "sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "airbnb-js-shims": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/airbnb-js-shims/-/airbnb-js-shims-2.2.1.tgz", + "integrity": "sha512-wJNXPH66U2xjgo1Zwyjf9EydvJ2Si94+vSdk6EERcBfB2VZkeltpqIats0cqIZMLCXP3zcyaUKGYQeIBT6XjsQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", + "array.prototype.flatmap": "^1.2.1", + "es5-shim": "^4.5.13", + "es6-shim": "^0.35.5", + "function.prototype.name": "^1.1.0", + "globalthis": "^1.0.0", + "object.entries": "^1.1.0", + "object.fromentries": "^2.0.0 || ^1.0.0", + "object.getownpropertydescriptors": "^2.0.3", + "object.values": "^1.1.0", + "promise.allsettled": "^1.0.0", + "promise.prototype.finally": "^3.1.0", + "string.prototype.matchall": "^4.0.0 || ^3.0.1", + "string.prototype.padend": "^3.0.0", + "string.prototype.padstart": "^3.0.0", + "symbol.prototype.description": "^1.0.0" + } + }, + "ajv": { + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz", + "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, + "requires": {} + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true, + "optional": true + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + } + } + }, + "ansi-to-html": { + "version": "0.6.15", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.15.tgz", + "integrity": "sha512-28ijx2aHJGdzbs+O5SNQF65r6rrKYnkuwTYm8lZlChuoJ9P1vVzIpWO20sQTqTPDXYp6NFwk326vApTtLVFXpQ==", + "dev": true, + "requires": { + "entities": "^2.0.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "apache-crypt": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.5.tgz", + "integrity": "sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg==", + "dev": true, + "requires": { + "unix-crypt-td-js": "^1.1.4" + } + }, + "apache-md5": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.7.tgz", + "integrity": "sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw==", + "dev": true + }, + "app-root-dir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/app-root-dir/-/app-root-dir-1.0.2.tgz", + "integrity": "sha1-OBh+wt6nV3//Az/8sSFyaS/24Rg=", + "dev": true + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "array-includes": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz", + "integrity": "sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "array.prototype.flat": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz", + "integrity": "sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + } + }, + "array.prototype.flatmap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz", + "integrity": "sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0" + } + }, + "array.prototype.map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.4.tgz", + "integrity": "sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-transform": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/ast-transform/-/ast-transform-0.0.0.tgz", + "integrity": "sha1-dJRAWIh9goPhidlUYAlHvJj+AGI=", + "dev": true, + "requires": { + "escodegen": "~1.2.0", + "esprima": "~1.0.4", + "through": "~2.3.4" + }, + "dependencies": { + "escodegen": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.2.0.tgz", + "integrity": "sha1-Cd55Z3kcyVi3+Jot220jRRrzJ+E=", + "dev": true, + "requires": { + "esprima": "~1.0.4", + "estraverse": "~1.5.0", + "esutils": "~1.0.0", + "source-map": "~0.1.30" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "estraverse": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz", + "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=", + "dev": true + }, + "esutils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz", + "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=", + "dev": true + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "optional": true, + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "ast-types": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.7.8.tgz", + "integrity": "sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk=", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autoprefixer": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.2.tgz", + "integrity": "sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==", + "dev": true, + "requires": { + "browserslist": "^4.19.1", + "caniuse-lite": "^1.0.30001297", + "fraction.js": "^4.1.2", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "axe-core": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", + "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", + "dev": true + }, + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "peer": true, + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "babel-loader": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz", + "integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-apply-mdx-type-prop": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.6.22.tgz", + "integrity": "sha512-VefL+8o+F/DfK24lPZMtJctrCVOfgbqLAGZSkxwhazQv4VxPg3Za/i40fu22KR2m8eEda+IfSOlPLUSIiLcnCQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "7.10.4", + "@mdx-js/util": "1.6.22" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-emotion": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.2.2.tgz", + "integrity": "sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@emotion/hash": "0.8.0", + "@emotion/memoize": "0.7.4", + "@emotion/serialize": "^0.11.16", + "babel-plugin-macros": "^2.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^1.0.5", + "find-root": "^1.1.0", + "source-map": "^0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-plugin-extract-import-names": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.6.22.tgz", + "integrity": "sha512-yJ9BsJaISua7d8zNT7oRG1ZLBJCIdZ4PZqmH8qa9N5AK01ifk3fnkc98AXhtzE7UkfCsEumvoQWgoYLhOnJ7jQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + } + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz", + "integrity": "sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.2.4", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.5.tgz", + "integrity": "sha512-ninF5MQNwAX9Z7c9ED+H2pGt1mXdP4TqzlHKyPIYmJIYz0N+++uwdM7RnJukklhzJ54Q84vA4ZJkgs7lu5vqcw==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.2.2", + "core-js-compat": "^3.16.2" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz", + "integrity": "sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.2.4" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "peer": true, + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "optional": true, + "peer": true + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "batch-processor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/batch-processor/-/batch-processor-1.0.0.tgz", + "integrity": "sha1-dclcMrdI4IUNEMKxaPa9vpiRrOg=", + "dev": true + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=", + "dev": true + }, + "better-opn": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz", + "integrity": "sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==", + "dev": true, + "requires": { + "open": "^7.0.3" + }, + "dependencies": { + "open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + } + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "bootstrap": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", + "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==", + "requires": {} + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "brfs": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brfs/-/brfs-2.0.2.tgz", + "integrity": "sha512-IrFjVtwu4eTJZyu8w/V2gxU7iLTtcHih67sgEdzrhjLBMHp2uYefUBfdM4k2UvcuWMgV7PQDZHSLeNWnLFKWVQ==", + "dev": true, + "requires": { + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^3.0.2", + "through2": "^2.0.0" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "brotli": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.2.tgz", + "integrity": "sha1-UlqcrU/LqWR119OI9q7LE+7VL0Y=", + "dev": true, + "requires": { + "base64-js": "^1.1.2" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-optional/-/browserify-optional-1.0.1.tgz", + "integrity": "sha1-HhNyLP3g2F8SFnbCpyztUzoBiGk=", + "dev": true, + "requires": { + "ast-transform": "0.0.0", + "ast-types": "^0.7.0", + "browser-resolve": "^1.8.1" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", + "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001286", + "electron-to-chromium": "^1.4.17", + "escalade": "^3.1.1", + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "builtins": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", + "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.2.0.tgz", + "integrity": "sha512-uKoJSHmnrqXgthDFx/IU6ED/5xd+NNGe+Bb+kLZy7Ku4P+BaiWEUflAKPZ7eAzsYGcsAGASJZsybXp+quEcHTw==", + "dev": true, + "requires": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001312", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz", + "integrity": "sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ==", + "dev": true + }, + "canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "capture-exit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", + "integrity": "sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==", + "dev": true, + "requires": { + "rsvp": "^4.8.4" + } + }, + "case-sensitive-paths-webpack-plugin": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", + "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", + "dev": true + }, + "ccount": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.1.0.tgz", + "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "peer": true + }, + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true + }, + "charcodes": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz", + "integrity": "sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==", + "dev": true + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "dev": true, + "requires": { + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "cheerio-select": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", + "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "css-what": "^5.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0", + "domutils": "^2.7.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.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" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "chromatic": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/chromatic/-/chromatic-6.5.2.tgz", + "integrity": "sha512-TiAJAF2we4BUflKEfiXs2CiBFvW6yNWkiXKIuBtlSLl2fj1cuueXlV5dYVVoyMDfzTX5JdEn/Bd5CVlpKCeY6A==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "circular-dependency-plugin": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz", + "integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==", + "dev": true, + "requires": {} + }, + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true, + "peer": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "clean-css": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz", + "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true + }, + "cli-table3": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.1.tgz", + "integrity": "sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==", + "dev": true, + "requires": { + "colors": "1.4.0", + "string-width": "^4.2.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, + "clsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", + "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "peer": true + }, + "code-block-writer": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.0.tgz", + "integrity": "sha512-GEqWvEWWsOvER+g9keO4ohFoD3ymwyCnqY3hoTr7GZipYFwEhMHJw+TtV0rfgRhNImM6QWZGO2XYjlJVyYT62w==", + "dev": true, + "requires": { + "tslib": "2.3.1" + } + }, + "collapse-white-space": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz", + "integrity": "sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true, + "peer": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colord": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.2.tgz", + "integrity": "sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==", + "dev": true + }, + "colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "dev": true + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "comma-separated-tokens": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz", + "integrity": "sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw==", + "dev": true + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "compute-scroll-into-view": { + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz", + "integrity": "sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "requires": { + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "requires": { + "is-what": "^3.14.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + }, + "dependencies": { + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-to-clipboard": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", + "integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==", + "dev": true, + "requires": { + "toggle-selection": "^1.0.6" + } + }, + "copy-webpack-plugin": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.0.1.tgz", + "integrity": "sha512-14gHKKdYIxF84jCEgPgYXCPpldbwpxxLbCmA7LReY7gvbaT555DgeBWBgBZM116tv/fO6RRJrsivBqRyRlukhw==", + "dev": true, + "requires": { + "fast-glob": "^3.2.5", + "glob-parent": "^6.0.0", + "globby": "^11.0.3", + "normalize-path": "^3.0.0", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "core-js": { + "version": "3.16.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.0.tgz", + "integrity": "sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g==", + "dev": true + }, + "core-js-compat": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.21.1.tgz", + "integrity": "sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==", + "dev": true, + "requires": { + "browserslist": "^4.19.1", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-js-pure": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.21.1.tgz", + "integrity": "sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cp-file": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-7.0.0.tgz", + "integrity": "sha512-0Cbj7gyvFVApzpK/uhCtQ/9kE9UnYpxMzaq5nQQC/Dh4iaj5fxp7iEFIullrYwzj8nf0qnsI1Qsx34hAeAebvw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "nested-error-stacks": "^2.0.0", + "p-event": "^4.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "cpy": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/cpy/-/cpy-8.1.2.tgz", + "integrity": "sha512-dmC4mUesv0OYH2kNFEidtf/skUwv4zePmGeepjyyJ0qTo5+8KhA1o99oIAwVVLzQMAeDJml74d6wPPKb6EZUTg==", + "dev": true, + "requires": { + "arrify": "^2.0.1", + "cp-file": "^7.0.0", + "globby": "^9.2.0", + "has-glob": "^1.0.0", + "junk": "^3.1.0", + "nested-error-stacks": "^2.1.0", + "p-all": "^2.1.0", + "p-filter": "^2.1.0", + "p-map": "^3.0.0" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "critters": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.12.tgz", + "integrity": "sha512-ujxKtKc/mWpjrOKeaACTaQ1aP0O31M0ZPWhfl85jZF1smPU4Ivb9va5Ox2poif4zVJQQo0LCFlzGtEZAsCAPcw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "css-select": "^4.1.3", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "postcss": "^8.3.7", + "pretty-bytes": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==", + "dev": true + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-declaration-sorter": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.1.4.tgz", + "integrity": "sha512-lpfkqS0fctcmZotJGhnxkIyJWvBXgpyi2wsFd4J8VB7wzyrT6Ch/3Q+FMNJpjK4gu1+GN5khOnpU2ZVKrLbhCw==", + "dev": true, + "requires": { + "timsort": "^0.3.0" + } + }, + "css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.2.0.tgz", + "integrity": "sha512-/rvHfYRjIpymZblf49w8jYcRo2y9gj6rV8UroHGmBxKrIyGLokpycyKzp9OkitvqT29ZSpzJ0Ic7SpnJX3sC8g==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.2.15", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.1.0", + "semver": "^7.3.5" + } + }, + "css-minimizer-webpack-plugin": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.0.2.tgz", + "integrity": "sha512-B3I5e17RwvKPJwsxjjWcdgpU/zqylzK1bPVghcmpFHRL48DXiBgrtqz1BJsn68+t/zzaLp9kYAaEDvQ7GyanFQ==", + "dev": true, + "requires": { + "cssnano": "^5.0.6", + "jest-worker": "^27.0.2", + "p-limit": "^3.0.2", + "postcss": "^8.3.5", + "schema-utils": "^3.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "^2.0.0" + } + }, + "css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-select": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", + "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.1.0", + "domhandler": "^4.3.0", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-what": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", + "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "dev": true + }, + "cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssnano": { + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.0.17.tgz", + "integrity": "sha512-fmjLP7k8kL18xSspeXTzRhaFtRI7DL9b8IcXR80JgtnWBpvAzHT7sCR/6qdn0tnxIaINUN6OEQu83wF57Gs3Xw==", + "dev": true, + "requires": { + "cssnano-preset-default": "^5.1.12", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + } + }, + "cssnano-preset-default": { + "version": "5.1.12", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.1.12.tgz", + "integrity": "sha512-rO/JZYyjW1QNkWBxMGV28DW7d98UDLaF759frhli58QFehZ+D/LSmwQ2z/ylBAe2hUlsIWTq6NYGfQPq65EF9w==", + "dev": true, + "requires": { + "css-declaration-sorter": "^6.0.3", + "cssnano-utils": "^3.0.2", + "postcss-calc": "^8.2.0", + "postcss-colormin": "^5.2.5", + "postcss-convert-values": "^5.0.4", + "postcss-discard-comments": "^5.0.3", + "postcss-discard-duplicates": "^5.0.3", + "postcss-discard-empty": "^5.0.3", + "postcss-discard-overridden": "^5.0.4", + "postcss-merge-longhand": "^5.0.6", + "postcss-merge-rules": "^5.0.6", + "postcss-minify-font-values": "^5.0.4", + "postcss-minify-gradients": "^5.0.6", + "postcss-minify-params": "^5.0.5", + "postcss-minify-selectors": "^5.1.3", + "postcss-normalize-charset": "^5.0.3", + "postcss-normalize-display-values": "^5.0.3", + "postcss-normalize-positions": "^5.0.4", + "postcss-normalize-repeat-style": "^5.0.4", + "postcss-normalize-string": "^5.0.4", + "postcss-normalize-timing-functions": "^5.0.3", + "postcss-normalize-unicode": "^5.0.4", + "postcss-normalize-url": "^5.0.5", + "postcss-normalize-whitespace": "^5.0.4", + "postcss-ordered-values": "^5.0.5", + "postcss-reduce-initial": "^5.0.3", + "postcss-reduce-transforms": "^5.0.4", + "postcss-svgo": "^5.0.4", + "postcss-unique-selectors": "^5.0.4" + } + }, + "cssnano-utils": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.0.2.tgz", + "integrity": "sha512-KhprijuQv2sP4kT92sSQwhlK3SJTbDIsxcfIEySB0O+3m9esFOai7dP9bMx5enHAh2MwarVIcnwiWoOm01RIbQ==", + "dev": true, + "requires": {} + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + } + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "csstype": { + "version": "2.6.19", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.19.tgz", + "integrity": "sha512-ZVxXaNy28/k3kJg0Fou5MiYpp88j7H9hLZp8PDC3jV0WFjfH5E9xHb56L0W59cPbKbcHXeP4qyT8PrHp8t6LcQ==", + "dev": true + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true, + "optional": true, + "peer": true + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dash-ast": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-2.0.1.tgz", + "integrity": "sha512-5TXltWJGc+RdnabUGzhRae1TRq6m4gr+3K2wQX0is5/F2yS6MJXJvLyI3ErAnsAXuJoGqvfVD5icRgim07DrxQ==", + "dev": true + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "dependencies": { + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + } + } + }, + "date-format": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.3.tgz", + "integrity": "sha512-7P3FyqDcfeznLZp2b+OMitV9Sz2lUnsT87WaTat9nVwqsBkTzPG3lPLNwW3en6F4pHUiWzr6vb8CLhjdK9bcxQ==", + "dev": true, + "optional": true, + "peer": true + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "decache": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/decache/-/decache-4.6.1.tgz", + "integrity": "sha512-ohApBM8u9ygepJCjgBrEZSSxPjc0T/PJkD+uNyxXPkqudyUpdXpwJYp0VISm2WrPVzASU6DZyIi6BWdyw7uJ2Q==", + "dev": true, + "requires": { + "callsite": "^1.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true, + "peer": true + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deep-object-diff": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.7.tgz", + "integrity": "sha512-QkgBca0mL08P6HiOjoqvmm6xOAl2W6CT2+34Ljhg0OeFan8cwlcdq8jrLKsBBuUFAZLsN5b6y491KdKEoSo9lg==", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detab": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detab/-/detab-2.0.4.tgz", + "integrity": "sha512-8zdsQA5bIkoRECvCrNKPla84lyoR7DSAyf7p0YgXzBO9PDJx8KntPUay7NS6yp+KdxdVtiE5SpHKtbp2ZQyA9g==", + "dev": true, + "requires": { + "repeat-string": "^1.5.4" + } + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "peer": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "detect-port": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.3.0.tgz", + "integrity": "sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==", + "dev": true, + "requires": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "detective": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", + "dev": true, + "requires": { + "acorn-node": "^1.6.1", + "defined": "^1.0.0", + "minimist": "^1.1.1" + } + }, + "dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", + "dev": true + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true, + "optional": true, + "peer": true + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "peer": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, + "domhandler": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz", + "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "dot": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz", + "integrity": "sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg==", + "dev": true + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "downshift": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.7.tgz", + "integrity": "sha512-cVprZg/9Lvj/uhYRxELzlu1aezRcgPWBjTvspiGTVEU64gF5pRdSRKFVLcxqsZC637cLAGMbL40JavEfWnqgNg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.14.8", + "compute-scroll-into-view": "^1.0.17", + "prop-types": "^15.7.2", + "react-is": "^17.0.2", + "tslib": "^2.3.0" + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.71", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.71.tgz", + "integrity": "sha512-Hk61vXXKRb2cd3znPE9F+2pLWdIOmP7GjiTj45y6L3W/lO+hSnUSUhq+6lEaERWBdZOHbk2s3YV5c9xVl3boVw==", + "dev": true + }, + "element-resize-detector": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/element-resize-detector/-/element-resize-detector-1.2.4.tgz", + "integrity": "sha512-Fl5Ftk6WwXE0wqCgNoseKWndjzZlDCwuPTcoVZfCP9R3EHQF8qUtr3YUPNETegRBOKqQKPW3n4kiIWngGi8tKg==", + "dev": true, + "requires": { + "batch-processor": "1.0.0" + } + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, + "peer": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "emotion-theming": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emotion-theming/-/emotion-theming-10.3.0.tgz", + "integrity": "sha512-mXiD2Oj7N9b6+h/dC6oLf9hwxbtKHQjoIqtodEyL8CpkN4F3V4IK/BT4D0C7zSs4BBFOu4UlPJbvvBLa88SGEA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.5", + "@emotion/weak-memoize": "0.2.5", + "hoist-non-react-statics": "^3.3.0" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "dev": true, + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.2.tgz", + "integrity": "sha512-v/7eGHxPvO2AWsksyx2PUsQvBafuvqs0jJJQ0FdmJG1b9qIvgSbqDRGwNhfk2XHaTTbTXiC4quRE8Q9nRjsrQQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.0", + "ws": "~8.2.3" + }, + "dependencies": { + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "optional": true, + "peer": true, + "requires": {} + } + } + }, + "engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@socket.io/base64-arraybuffer": "~1.0.2" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true, + "optional": true, + "peer": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", + "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.1", + "is-string": "^1.0.7", + "is-weakref": "^1.0.1", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-get-iterator": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.2.tgz", + "integrity": "sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.0", + "has-symbols": "^1.0.1", + "is-arguments": "^1.1.0", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + } + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + } + }, + "es5-shim": { + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.5.tgz", + "integrity": "sha512-vfQ4UAai8szn0sAubCy97xnZ4sJVDD1gt/Grn736hg8D7540wemIb1YPrYZSTqlM2H69EQX1or4HU/tSwRTI3w==", + "dev": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + }, + "dependencies": { + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + } + } + }, + "es6-shim": { + "version": "0.35.6", + "resolved": "https://registry.npmjs.org/es6-shim/-/es6-shim-0.35.6.tgz", + "integrity": "sha512-EmTr31wppcaIAgblChZiuN/l9Y7DPyw8Xtbg7fIVngn6zMW+IEBJDJngeKC3x6wr0V/vcA2wqeFnaw1bFJbDdA==", + "dev": true + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "esbuild": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.13.8.tgz", + "integrity": "sha512-A4af7G7YZLfG5OnARJRMtlpEsCkq/zHZQXewgPA864l9D6VjjbH1SuFYK/OSV6BtHwDGkdwyRrX0qQFLnMfUcw==", + "dev": true, + "optional": true, + "requires": { + "esbuild-android-arm64": "0.13.8", + "esbuild-darwin-64": "0.13.8", + "esbuild-darwin-arm64": "0.13.8", + "esbuild-freebsd-64": "0.13.8", + "esbuild-freebsd-arm64": "0.13.8", + "esbuild-linux-32": "0.13.8", + "esbuild-linux-64": "0.13.8", + "esbuild-linux-arm": "0.13.8", + "esbuild-linux-arm64": "0.13.8", + "esbuild-linux-mips64le": "0.13.8", + "esbuild-linux-ppc64le": "0.13.8", + "esbuild-netbsd-64": "0.13.8", + "esbuild-openbsd-64": "0.13.8", + "esbuild-sunos-64": "0.13.8", + "esbuild-windows-32": "0.13.8", + "esbuild-windows-64": "0.13.8", + "esbuild-windows-arm64": "0.13.8" + } + }, + "esbuild-android-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.13.8.tgz", + "integrity": "sha512-AilbChndywpk7CdKkNSZ9klxl+9MboLctXd9LwLo3b0dawmOF/i/t2U5d8LM6SbT1Xw36F8yngSUPrd8yPs2RA==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.13.8.tgz", + "integrity": "sha512-b6sdiT84zV5LVaoF+UoMVGJzR/iE2vNUfUDfFQGrm4LBwM/PWXweKpuu6RD9mcyCq18cLxkP6w/LD/w9DtX3ng==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.13.8.tgz", + "integrity": "sha512-R8YuPiiJayuJJRUBG4H0VwkEKo6AvhJs2m7Tl0JaIer3u1FHHXwGhMxjJDmK+kXwTFPriSysPvcobXC/UrrZCQ==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.13.8.tgz", + "integrity": "sha512-zBn6urrn8FnKC+YSgDxdof9jhPCeU8kR/qaamlV4gI8R3KUaUK162WYM7UyFVAlj9N0MyD3AtB+hltzu4cysTw==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.13.8.tgz", + "integrity": "sha512-pWW2slN7lGlkx0MOEBoUGwRX5UgSCLq3dy2c8RIOpiHtA87xAUpDBvZK10MykbT+aMfXc0NI2lu1X+6kI34xng==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.13.8.tgz", + "integrity": "sha512-T0I0ueeKVO/Is0CAeSEOG9s2jeNNb8jrrMwG9QBIm3UU18MRB60ERgkS2uV3fZ1vP2F8i3Z2e3Zju4lg9dhVmw==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.13.8.tgz", + "integrity": "sha512-Bm8SYmFtvfDCIu9sjKppFXzRXn2BVpuCinU1ChTuMtdKI/7aPpXIrkqBNOgPTOQO9AylJJc1Zw6EvtKORhn64w==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.13.8.tgz", + "integrity": "sha512-4/HfcC40LJ4GPyboHA+db0jpFarTB628D1ifU+/5bunIgY+t6mHkJWyxWxAAE8wl/ZIuRYB9RJFdYpu1AXGPdg==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.13.8.tgz", + "integrity": "sha512-X4pWZ+SL+FJ09chWFgRNO3F+YtvAQRcWh0uxKqZSWKiWodAB20flsW/OWFYLXBKiVCTeoGMvENZS/GeVac7+tQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.13.8.tgz", + "integrity": "sha512-o7e0D+sqHKT31v+mwFircJFjwSKVd2nbkHEn4l9xQ1hLR+Bv8rnt3HqlblY3+sBdlrOTGSwz0ReROlKUMJyldA==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.13.8.tgz", + "integrity": "sha512-eZSQ0ERsWkukJp2px/UWJHVNuy0lMoz/HZcRWAbB6reoaBw7S9vMzYNUnflfL3XA6WDs+dZn3ekHE4Y2uWLGig==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.11.tgz", + "integrity": "sha512-DoThrkzunZ1nfRGoDN6REwmo8ZZWHd2ztniPVIR5RMw/Il9wiWEYBahb8jnMzQaSOxBsGp0PbyJeVLTUatnlcw==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.13.8.tgz", + "integrity": "sha512-gZX4kP7gVvOrvX0ZwgHmbuHczQUwqYppxqtoyC7VNd80t5nBHOFXVhWo2Ad/Lms0E8b+wwgI/WjZFTCpUHOg9Q==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.13.8.tgz", + "integrity": "sha512-afzza308X4WmcebexbTzAgfEWt9MUkdTvwIa8xOu4CM2qGbl2LanqEl8/LUs8jh6Gqw6WsicEK52GPrS9wvkcw==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.13.8.tgz", + "integrity": "sha512-mWPZibmBbuMKD+LDN23LGcOZ2EawMYBONMXXHmbuxeT0XxCNwadbCVwUQ/2p5Dp5Kvf6mhrlIffcnWOiCBpiVw==", + "dev": true, + "optional": true + }, + "esbuild-wasm": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.13.8.tgz", + "integrity": "sha512-UbD+3nloiSpJWXTCInZQrqPe8Y+RLfDkY/5kEHiXsw/lmaEvibe69qTzQu16m5R9je/0bF7VYQ5jaEOq0z9lLA==", + "dev": true + }, + "esbuild-windows-32": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.13.8.tgz", + "integrity": "sha512-QsZ1HnWIcnIEApETZWw8HlOhDSWqdZX2SylU7IzGxOYyVcX7QI06ety/aDcn437mwyO7Ph4RrbhB+2ntM8kX8A==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.13.8.tgz", + "integrity": "sha512-76Fb57B9eE/JmJi1QmUW0tRLQZfGo0it+JeYoCDTSlbTn7LV44ecOHIMJSSgZADUtRMWT9z0Kz186bnaB3amSg==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.13.8", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.13.8.tgz", + "integrity": "sha512-HW6Mtq5eTudllxY2YgT62MrVcn7oq2o8TAoAvDUhyiEmRmDY8tPwAhb1vxw5/cdkbukM3KdMYtksnUhF/ekWeg==", + "dev": true, + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "estree-is-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-is-function/-/estree-is-function-1.0.0.tgz", + "integrity": "sha512-nSCWn1jkSq2QAtkaVLJZY2ezwcFO161HVc174zL1KPW3RJ+O6C3eJb8Nx7OXzvhoEv+nLgSR1g71oWUHUDTrJA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "event-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", + "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "from": "^0.1.7", + "map-stream": "0.0.7", + "pause-stream": "^0.0.11", + "split": "^1.0.1", + "stream-combiner": "^0.2.2", + "through": "^2.3.8" + } + }, + "eventemitter-asyncresource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", + "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "eventsource": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", + "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exec-sh": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.3.6.tgz", + "integrity": "sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true, + "peer": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "express": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", + "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", + "dev": true, + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.19.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.9.7", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.17.2", + "serve-static": "1.14.2", + "setprototypeof": "1.2.0", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + } + } + }, + "fancy-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-2.0.0.tgz", + "integrity": "sha512-9CzxZbACXMUXW13tS0tI8XsGGmxWzO2DmYrGuBJOJ8k8q2K7hwfJA5qHjuPPe8wtsco33YR9wc+Rlr5wYFvhSA==", + "dev": true, + "requires": { + "color-support": "^1.1.3" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fault": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fault/-/fault-1.0.4.tgz", + "integrity": "sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==", + "dev": true, + "requires": { + "format": "^0.2.0" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "file-system-cache": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-1.0.5.tgz", + "integrity": "sha1-hCWbNqK7uNPW6xAh0xMv/mTP/08=", + "dev": true, + "requires": { + "bluebird": "^3.3.5", + "fs-extra": "^0.30.0", + "ramda": "^0.21.0" + }, + "dependencies": { + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "findit2": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/findit2/-/findit2-2.2.3.tgz", + "integrity": "sha1-WKRmaX34piBc39vzlVNri9d3pfY=", + "dev": true + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true, + "optional": true, + "peer": true + }, + "flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "follow-redirects": { + "version": "1.14.8", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz", + "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "fork-ts-checker-webpack-plugin": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-4.1.6.tgz", + "integrity": "sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "chalk": "^2.4.1", + "micromatch": "^3.1.10", + "minimatch": "^3.0.4", + "semver": "^5.6.0", + "tapable": "^1.0.0", + "worker-rpc": "^0.1.0" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", + "dev": true + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fraction.js": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.3.tgz", + "integrity": "sha512-pUHWWt6vHzZZiQJcM6S/0PXfS+g6FM4BF5rj9wZyreivhQPdsh5PpE25VtSNxq80wHS5RfY51Ii+8Z0Zl/pmzg==", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "dev": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.2.tgz", + "integrity": "sha512-bLgc3asbWdwPbx2mNk2S49kmJCuQeu0nfmaOgbs8WIyzzkw3r4htszdIi9Q9EMezDPTYuJx2wvjZ/EwgAthpnA==", + "dev": true + }, + "fuse.js": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-3.6.1.tgz", + "integrity": "sha512-hT9yh/tiinkmirKrlv4KWOjztdoZo1mx9Qh4KvWqC7isoXwdUY3PNWUxceF4/qO9R6riA2C29jdTOeQOIROjgw==", + "dev": true + }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "github-slugger": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.4.0.tgz", + "integrity": "sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ==", + "dev": true + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-promise": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-3.4.0.tgz", + "integrity": "sha512-q08RJ6O+eJn+dVanerAndJwIcumgbDdYiUT7zFQl3Wm1xD6fBKtah7H8ZJChj4wP+8C+QfeVy8xautR7rdmKEw==", + "dev": true, + "requires": { + "@types/glob": "*" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globalthis": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", + "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", + "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==", + "dev": true + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-glob/-/has-glob-1.0.0.tgz", + "integrity": "sha1-mqqe7b/7G6OZCnsAEPtnjuAIEgc=", + "dev": true, + "requires": { + "is-glob": "^3.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hast-to-hyperscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz", + "integrity": "sha512-zQgLKqF+O2F72S1aa4y2ivxzSlko3MAvxkwG8ehGmNiqd98BIN3JM1rAJPmplEyLmGLO2QZYJtIneOSZ2YbJuA==", + "dev": true, + "requires": { + "@types/unist": "^2.0.3", + "comma-separated-tokens": "^1.0.0", + "property-information": "^5.3.0", + "space-separated-tokens": "^1.0.0", + "style-to-object": "^0.3.0", + "unist-util-is": "^4.0.0", + "web-namespaces": "^1.0.0" + } + }, + "hast-util-from-parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz", + "integrity": "sha512-jeJUWiN5pSxW12Rh01smtVkZgZr33wBokLzKLwinYOUfSzm1Nl/c3GUGebDyOKjdsRgMvoVbV0VpAcpjF4NrJA==", + "dev": true, + "requires": { + "@types/parse5": "^5.0.0", + "hastscript": "^6.0.0", + "property-information": "^5.0.0", + "vfile": "^4.0.0", + "vfile-location": "^3.2.0", + "web-namespaces": "^1.0.0" + } + }, + "hast-util-parse-selector": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", + "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ==", + "dev": true + }, + "hast-util-raw": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-6.0.1.tgz", + "integrity": "sha512-ZMuiYA+UF7BXBtsTBNcLBF5HzXzkyE6MLzJnL605LKE8GJylNjGc4jjxazAHUtcwT5/CEt6afRKViYB4X66dig==", + "dev": true, + "requires": { + "@types/hast": "^2.0.0", + "hast-util-from-parse5": "^6.0.0", + "hast-util-to-parse5": "^6.0.0", + "html-void-elements": "^1.0.0", + "parse5": "^6.0.0", + "unist-util-position": "^3.0.0", + "vfile": "^4.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "hast-util-to-parse5": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz", + "integrity": "sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ==", + "dev": true, + "requires": { + "hast-to-hyperscript": "^9.0.0", + "property-information": "^5.0.0", + "web-namespaces": "^1.0.0", + "xtend": "^4.0.0", + "zwitch": "^1.0.0" + } + }, + "hastscript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-6.0.0.tgz", + "integrity": "sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w==", + "dev": true, + "requires": { + "@types/hast": "^2.0.0", + "comma-separated-tokens": "^1.0.0", + "hast-util-parse-selector": "^2.0.0", + "property-information": "^5.0.0", + "space-separated-tokens": "^1.0.0" + } + }, + "hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "requires": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "dev": true + }, + "history": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.0.0.tgz", + "integrity": "sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.6" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "requires": { + "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + } + } + }, + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-entities": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.2.tgz", + "integrity": "sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "peer": true + }, + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", + "dev": true, + "requires": { + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + } + } + }, + "html-tags": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", + "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "dev": true + }, + "html-void-elements": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", + "integrity": "sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w==", + "dev": true + }, + "html-webpack-plugin": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.5.2.tgz", + "integrity": "sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^5.0.0", + "@types/tapable": "^1.0.5", + "@types/webpack": "^4.41.8", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.20", + "pretty-error": "^2.1.1", + "tapable": "^1.1.3", + "util.promisify": "1.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "http-auth": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-4.1.9.tgz", + "integrity": "sha512-kvPYxNGc9EKGTXvOMnTBQw2RZfuiSihK/mLw/a4pbtRueTE45S55Lw/3k5CktIf7Ak0veMKEIteDj4YkNmCzmQ==", + "dev": true, + "requires": { + "apache-crypt": "^1.1.2", + "apache-md5": "^1.0.6", + "bcryptjs": "^2.4.3", + "uuid": "^8.3.2" + } + }, + "http-auth-connect": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/http-auth-connect/-/http-auth-connect-1.0.5.tgz", + "integrity": "sha512-zykAOKpVAXyzhOLm6+xyB/RtRcfN3uDfH4Al73DIfeSb6B7nr0WToLI6UyyM6ohtcLmbBPksWXzVbEDStz8ObQ==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "http-parser-js": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz", + "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "i18next": { + "version": "21.6.11", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-21.6.11.tgz", + "integrity": "sha512-tJ2+o0lVO+fhi8bPkCpBAeY1SgkqmQm5NzgPWCQssBrywJw98/o+Kombhty5nxQOpHtvMmsxcOopczUiH6bJxQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "ignore-walk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-4.0.1.tgz", + "integrity": "sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + }, + "inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "dev": true + }, + "inquirer": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.1.2.tgz", + "integrity": "sha512-DHLKJwLPNgkfwNmsuEUKSejJFbkv0FMO9SMiQbjI3n5NQuCrSIBqP66ggqyz2a6t2qEolKrMjhQ3+W/xXgUQ+Q==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.3.0", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/inside/-/inside-1.0.0.tgz", + "integrity": "sha1-20Xpk1c82z23C5gy6ChbrUZCR3A=", + "dev": true + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", + "dev": true + }, + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", + "dev": true, + "requires": { + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", + "dev": true + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, + "is-dom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz", + "integrity": "sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==", + "dev": true, + "requires": { + "is-object": "^1.0.1", + "is-window": "^1.0.2" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "peer": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=", + "dev": true + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", + "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "is-whitespace-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz", + "integrity": "sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==", + "dev": true + }, + "is-window": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz", + "integrity": "sha1-LIlspT25feRdPDMTOmXYyfVjSA0=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-word-character": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-word-character/-/is-word-character-1.0.4.tgz", + "integrity": "sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "isbinaryfile": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.8.tgz", + "integrity": "sha512-53h6XFniq77YdW+spoRrebh0mnmTxRPTlcuIArO57lmMdq4uBKFKaeTjnb92oYWrSn/LVL+LT+Hap2tFQj8V+w==", + "dev": true, + "optional": true, + "peer": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "peer": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "peer": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "peer": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + } + } + }, + "istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "peer": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "dev": true + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, + "jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "peer": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "peer": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "peer": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "peer": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "peer": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "peer": true, + "requires": { + "resolve-from": "^5.0.0" + } + } + } + }, + "jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "peer": true, + "requires": { + "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" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "peer": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "peer": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "peer": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "peer": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "peer": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "peer": true, + "requires": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "peer": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "peer": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "peer": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "peer": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "peer": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "peer": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "peer": true, + "requires": { + "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-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "peer": true + } + } + }, + "jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "peer": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, + "peer": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz", + "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.6.2", + "jest-util": "^26.6.2", + "jest-worker": "^26.6.2", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, + "peer": true, + "requires": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "peer": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "peer": true, + "requires": {} + }, + "jest-preset-angular": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-11.1.2.tgz", + "integrity": "sha512-qPvOP6wnLP8M01TDVSa3UC3PcDWxoj87T58mWEp5yWlWPrXBJ6rhnTEI+HPmZLyehwlK686+O/49hwFRVXFP0A==", + "dev": true, + "requires": { + "bs-logger": "^0.2.6", + "esbuild": "0.14.11", + "esbuild-wasm": "0.14.11", + "jest-environment-jsdom": "^27.0.0", + "pretty-format": "^27.0.0", + "ts-jest": "^27.0.0" + }, + "dependencies": { + "esbuild": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.11.tgz", + "integrity": "sha512-xZvPtVj6yecnDeFb3KjjCM6i7B5TCAQZT77kkW/CpXTMnd6VLnRPKrUB1XHI1pSq6a4Zcy3BGueQ8VljqjDGCg==", + "dev": true, + "optional": true, + "requires": { + "esbuild-android-arm64": "0.14.11", + "esbuild-darwin-64": "0.14.11", + "esbuild-darwin-arm64": "0.14.11", + "esbuild-freebsd-64": "0.14.11", + "esbuild-freebsd-arm64": "0.14.11", + "esbuild-linux-32": "0.14.11", + "esbuild-linux-64": "0.14.11", + "esbuild-linux-arm": "0.14.11", + "esbuild-linux-arm64": "0.14.11", + "esbuild-linux-mips64le": "0.14.11", + "esbuild-linux-ppc64le": "0.14.11", + "esbuild-linux-s390x": "0.14.11", + "esbuild-netbsd-64": "0.14.11", + "esbuild-openbsd-64": "0.14.11", + "esbuild-sunos-64": "0.14.11", + "esbuild-windows-32": "0.14.11", + "esbuild-windows-64": "0.14.11", + "esbuild-windows-arm64": "0.14.11" + } + }, + "esbuild-android-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.11.tgz", + "integrity": "sha512-6iHjgvMnC/SzDH8TefL+/3lgCjYWwAd1LixYfmz/TBPbDQlxcuSkX0yiQgcJB9k+ibZ54yjVXziIwGdlc+6WNw==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.11.tgz", + "integrity": "sha512-olq84ikh6TiBcrs3FnM4eR5VPPlcJcdW8BnUz/lNoEWYifYQ+Po5DuYV1oz1CTFMw4k6bQIZl8T3yxL+ZT2uvQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.11.tgz", + "integrity": "sha512-Jj0ieWLREPBYr/TZJrb2GFH8PVzDqiQWavo1pOFFShrcmHWDBDrlDxPzEZ67NF/Un3t6sNNmeI1TUS/fe1xARg==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.11.tgz", + "integrity": "sha512-C5sT3/XIztxxz/zwDjPRHyzj/NJFOnakAanXuyfLDwhwupKPd76/PPHHyJx6Po6NI6PomgVp/zi6GRB8PfrOTA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.11.tgz", + "integrity": "sha512-y3Llu4wbs0bk4cwjsdAtVOesXb6JkdfZDLKMt+v1U3tOEPBdSu6w8796VTksJgPfqvpX22JmPLClls0h5p+L9w==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.11.tgz", + "integrity": "sha512-Cg3nVsxArjyLke9EuwictFF3Sva+UlDTwHIuIyx8qpxRYAOUTmxr2LzYrhHyTcGOleLGXUXYsnUVwKqnKAgkcg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.11.tgz", + "integrity": "sha512-oeR6dIrrojr8DKVrxtH3xl4eencmjsgI6kPkDCRIIFwv4p+K7ySviM85K66BN01oLjzthpUMvBVfWSJkBLeRbg==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.11.tgz", + "integrity": "sha512-vcwskfD9g0tojux/ZaTJptJQU3a7YgTYsptK1y6LQ/rJmw7U5QJvboNawqM98Ca3ToYEucfCRGbl66OTNtp6KQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.11.tgz", + "integrity": "sha512-+e6ZCgTFQYZlmg2OqLkg1jHLYtkNDksxWDBWNtI4XG4WxuOCUErLqfEt9qWjvzK3XBcCzHImrajkUjO+rRkbMg==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.11.tgz", + "integrity": "sha512-Rrs99L+p54vepmXIb87xTG6ukrQv+CzrM8eoeR+r/OFL2Rg8RlyEtCeshXJ2+Q66MXZOgPJaokXJZb9snq28bw==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.11.tgz", + "integrity": "sha512-JyzziGAI0D30Vyzt0HDihp4s1IUtJ3ssV2zx9O/c+U/dhUHVP2TmlYjzCfCr2Q6mwXTeloDcLS4qkyvJtYptdQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.11.tgz", + "integrity": "sha512-12luoRQz+6eihKYh1zjrw0CBa2aw3twIiHV/FAfjh2NEBDgJQOY4WCEUEN+Rgon7xmLh4XUxCQjnwrvf8zhACw==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.11.tgz", + "integrity": "sha512-l18TZDjmvwW6cDeR4fmizNoxndyDHamGOOAenwI4SOJbzlJmwfr0jUgjbaXCUuYVOA964siw+Ix+A+bhALWg8Q==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.11.tgz", + "integrity": "sha512-bmYzDtwASBB8c+0/HVOAiE9diR7+8zLm/i3kEojUH2z0aIs6x/S4KiTuT5/0VKJ4zk69kXel1cNWlHBMkmavQg==", + "dev": true, + "optional": true + }, + "esbuild-wasm": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.14.11.tgz", + "integrity": "sha512-9e1R6hv0hiU+BkJI2edqUuWfXUbOP2Mox+Ijl/uY1vLLlSsunkrcADqD/4Rz+VCEDzw6ecscJM+uJqR2fRmEUg==", + "dev": true + }, + "esbuild-windows-32": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.11.tgz", + "integrity": "sha512-J1Ys5hMid8QgdY00OBvIolXgCQn1ARhYtxPnG6ESWNTty3ashtc4+As5nTrsErnv8ZGUcWZe4WzTP/DmEVX1UQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.11.tgz", + "integrity": "sha512-h9FmMskMuGeN/9G9+LlHPAoiQk9jlKDUn9yA0MpiGzwLa82E7r1b1u+h2a+InprbSnSLxDq/7p5YGtYVO85Mlg==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.11", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.11.tgz", + "integrity": "sha512-dZp7Krv13KpwKklt9/1vBFBMqxEQIO6ri7Azf8C+ob4zOegpJmha2XY9VVWP/OyQ0OWk6cEeIzMJwInRZrzBUQ==", + "dev": true, + "optional": true + } + } + }, + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "dev": true + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "peer": true, + "requires": { + "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" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "peer": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "peer": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "peer": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "peer": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "peer": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "jest-serializer": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz", + "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==", + "dev": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.4" + } + }, + "jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "dependencies": { + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-util": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz", + "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==", + "dev": true, + "requires": { + "@jest/types": "^26.6.2", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "peer": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "peer": true, + "requires": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "peer": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "peer": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jquery": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", + "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==", + "peer": true + }, + "js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "dev": true + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "ws": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz", + "integrity": "sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A==", + "dev": true, + "requires": {} + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonc-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", + "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "junk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", + "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "dev": true + }, + "karma": { + "version": "6.3.16", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.16.tgz", + "integrity": "sha512-nEU50jLvDe5yvXqkEJRf8IuvddUkOY2x5Xc4WXHz6dxINgGDrgD2uqQWeVrJs4hbfNaotn+HQ1LZJ4yOXrL7xQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "colors": "1.4.0", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "peer": true + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "rimraf": "^3.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "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-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "optional": true, + "peer": true + } + } + }, + "karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true + }, + "lazy-universal-dotenv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz", + "integrity": "sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.5.0", + "app-root-dir": "^1.0.2", + "core-js": "^3.0.4", + "dotenv": "^8.0.0", + "dotenv-expand": "^5.1.0" + } + }, + "less": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.1.tgz", + "integrity": "sha512-w09o8tZFPThBscl5d0Ggp3RcrKIouBoQscnOMgFH3n5V3kN/CXGHNfCkRPtxJk6nKryDXaV9aHLK55RXuH4sAw==", + "dev": true, + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^2.5.2", + "parse-node-version": "^1.0.1", + "source-map": "~0.6.0", + "tslib": "^1.10.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "less-loader": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-10.0.1.tgz", + "integrity": "sha512-Crln//HpW9M5CbtdfWm3IO66Cvx1WhZQvNybXgfB2dD/6Sav9ppw+IWqs/FQKPBFO4B6X0X28Z0WNznshgwUzA==", + "dev": true, + "requires": { + "klona": "^2.0.4" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "peer": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "license-webpack-plugin": { + "version": "2.3.20", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.3.20.tgz", + "integrity": "sha512-AHVueg9clOKACSHkhmEI+PCC9x8+qsQVuKECZD3ETxETK5h/PCv5/MUzyG1gm8OMcip/s1tcNxqo9Qb7WhjGsg==", + "dev": true, + "requires": { + "@types/webpack-sources": "^0.1.5", + "webpack-sources": "^1.2.0" + }, + "dependencies": { + "@types/webpack-sources": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.9.tgz", + "integrity": "sha512-bvzMnzqoK16PQIC8AYHNdW45eREJQMd6WG/msQWX5V2+vZmODCOPb4TJcbgRljTZZTwTM4wUMcsI8FftNA7new==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "lilconfig": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz", + "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==", + "dev": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "lit-element": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.5.1.tgz", + "integrity": "sha512-ogu7PiJTA33bEK0xGu1dmaX5vhcRjBXCFexPja0e7P7jqLhTpNKYRPmE+GmiCaRVAbiQKGkUgkh/i6+bh++dPQ==", + "dev": true, + "requires": { + "lit-html": "^1.1.1" + } + }, + "lit-html": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.4.1.tgz", + "integrity": "sha512-B9btcSgPYb1q4oSOb/PrOT6Z/H+r6xuNzfH4lFli/AWhYwdtrgQkQWBbIc6mdnf6E2IL3gDXdkkqNktpU0OZQA==", + "dev": true + }, + "loader-runner": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.2.0.tgz", + "integrity": "sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw==", + "dev": true + }, + "loader-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log4js": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + }, + "dependencies": { + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "loglevel": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz", + "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==", + "dev": true + }, + "loglevel-plugin-prefix": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/loglevel-plugin-prefix/-/loglevel-plugin-prefix-0.8.4.tgz", + "integrity": "sha512-WpG9CcFAOjz/FtNht+QJeGpvVl/cdR6P0z6OcXSkr8wFJOsV2GRj2j10JLfjuA4aYkcKCNIEqRGCyTife9R8/g==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "lowlight": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz", + "integrity": "sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==", + "dev": true, + "requires": { + "fault": "^1.0.0", + "highlight.js": "~10.7.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "macos-release": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.5.0.tgz", + "integrity": "sha512-EIgv+QZ9r+814gjJj0Bt5vSLJLzswGmSUbUpbi9AIr/fsN2IWFBl2NucV9PAiek+U1STK468tEkxmVYUtuAN3g==", + "dev": true + }, + "magic-string": { + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dev": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha1-beJlMXSt+12e3DPGnT6Sobdvrwg=", + "dev": true + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-escapes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/markdown-escapes/-/markdown-escapes-1.0.4.tgz", + "integrity": "sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==", + "dev": true + }, + "markdown-to-jsx": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.6.tgz", + "integrity": "sha512-1wrIGZYwIG2gR3yfRmbr4FlQmhaAKoKTpRo4wur4fp9p0njU1Hi7vR8fj0AUKKIcPduiJmPprzmCB5B/GvlC7g==", + "dev": true, + "requires": {} + }, + "marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdast-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-zxdPn69hkQ1rm4J+2Cs2j6wDEv7O17TfXTJ33tl/+JPIoEmtV9t2ZzBM5LPHE8QlHsmVD8t3vPKCyY3oH+H8MQ==", + "dev": true, + "requires": { + "unist-util-remove": "^2.0.0" + } + }, + "mdast-util-definitions": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dev": true, + "requires": { + "unist-util-visit": "^2.0.0" + } + }, + "mdast-util-to-hast": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz", + "integrity": "sha512-BW3LM9SEMnjf4HXXVApZMt8gLQWVNXc3jryK0nJu/rOXPOnlkUjmdkDlmxMirpbU9ILncGFIwLH/ubnWBbcdgA==", + "dev": true, + "requires": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "mdast-util-definitions": "^4.0.0", + "mdurl": "^1.0.0", + "unist-builder": "^2.0.0", + "unist-util-generated": "^1.0.0", + "unist-util-position": "^3.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "mdast-util-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", + "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", + "dev": true + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true + } + } + }, + "memfs": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz", + "integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==", + "dev": true, + "requires": { + "fs-monkey": "1.0.3" + } + }, + "memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha1-fIekZGREwy11Q4VwkF8tvRsagFo=", + "dev": true, + "requires": { + "map-or-similar": "^1.5.0" + } + }, + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "microevent.ts": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", + "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "mime-db": { + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "dev": true + }, + "mime-types": { + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "dev": true, + "requires": { + "mime-db": "1.51.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "requires": { + "dom-walk": "^0.1.0" + } + }, + "mini-css-extract-plugin": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.4.2.tgz", + "integrity": "sha512-ZmqShkn79D36uerdED+9qdo1ZYG8C1YsWvXu0UMJxurZnSdgz7gQKO2EGv8T55MhDqG3DYmGtizZNpM/UbTlcA==", + "dev": true, + "requires": { + "schema-utils": "^3.1.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dev": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dev": true, + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + }, + "dependencies": { + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "dev": true, + "optional": true + }, + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true, + "peer": true + }, + "needle": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz", + "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==", + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "optional": true, + "requires": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true, + "optional": true + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "gauge": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.1.tgz", + "integrity": "sha512-zJ4jePUHR8cceduZ53b6temRalyGpkC2Kc2r3ecNphmL+uWNoJ3YcOcUjpbG6WwoE/Ef6/+aEZz63neI2WIa1Q==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, + "npmlog": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.1.tgz", + "integrity": "sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==", + "dev": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.0", + "set-blocking": "^2.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "node-gyp-build": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.3.0.tgz", + "integrity": "sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==", + "dev": true, + "optional": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "node-releases": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", + "dev": true + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", + "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dev": true, + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "dev": true + }, + "npm-package-arg": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.1.5.tgz", + "integrity": "sha512-LhgZrg0n0VgvzVdSm1oiZworPbTxYHUJCgtsJW8mGvlDpxTM1vSJc3m5QZeUkhAHIzbz3VCHd/R4osi1L1Tg/Q==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "semver": "^7.3.4", + "validate-npm-package-name": "^3.0.0" + } + }, + "npm-packlist": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-3.0.0.tgz", + "integrity": "sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==", + "dev": true, + "requires": { + "glob": "^7.1.6", + "ignore-walk": "^4.0.1", + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-pick-manifest": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.1.1.tgz", + "integrity": "sha512-dBsdBtORT84S8V8UTad1WlUyKIY9iMsAmqxHbLdeEeBNMLQDlDWWra3wYUx9EBEIiG/YwAy0XyNHDd2goAsfuA==", + "dev": true, + "requires": { + "npm-install-checks": "^4.0.0", + "npm-normalize-package-bin": "^1.0.1", + "npm-package-arg": "^8.1.2", + "semver": "^7.3.4" + } + }, + "npm-registry-fetch": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-11.0.0.tgz", + "integrity": "sha512-jmlgSxoDNuhAtxUIG6pVwwtz840i994dL14FoNVZisrmZW5kWd63IUTNv1m/hyRSGSqWjCUp/YZlS1BJyNp9XA==", + "dev": true, + "requires": { + "make-fetch-happen": "^9.0.1", + "minipass": "^3.1.3", + "minipass-fetch": "^1.3.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.0.0", + "npm-package-arg": "^8.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "nth-check": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz", + "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "dev": true + }, + "object-inspect": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz", + "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==", + "dev": true + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.5.tgz", + "integrity": "sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.fromentries": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.5.tgz", + "integrity": "sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz", + "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/open/-/open-8.2.1.tgz", + "integrity": "sha512-rXILpcQlkF/QuFez2BJDf3GsqpjGKbkUUToAIGo9A0Q6ZkoSGogZJulrUdwRkrAsoQvoZsrjCYt8+zblOk7JQQ==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-name": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-4.0.1.tgz", + "integrity": "sha512-xl9MAoU97MH1Xt5K9ERft2YfCAoaO6msy1OBA0ozxEC0x0TmIoE6K3QvgJMMZA9yKGLmHXNY/YZoDbiGDj4zYw==", + "dev": true, + "requires": { + "macos-release": "^2.5.0", + "windows-release": "^4.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "overlayscrollbars": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-1.13.1.tgz", + "integrity": "sha512-gIQfzgGgu1wy80EB4/6DaJGHMEGmizq27xHIESrzXq0Y/J0Ay1P3DWk6tuVmEPIZH15zaBlxeEJOqdJKmowHCQ==", + "dev": true + }, + "p-all": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-all/-/p-all-2.1.0.tgz", + "integrity": "sha512-HbZxz5FONzz/z2gJfk6bFca0BCiSRF8jU3yCsWOen/vR6lZjfPOu/e7L3uFzTW1i0H8TlC3vqQstEJPQL4/uLA==", + "dev": true, + "requires": { + "p-map": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dev": true, + "requires": { + "p-timeout": "^3.1.0" + } + }, + "p-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-2.1.0.tgz", + "integrity": "sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==", + "dev": true, + "requires": { + "p-map": "^2.0.0" + }, + "dependencies": { + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + } + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dev": true, + "requires": { + "p-finally": "^1.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pacote": { + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-12.0.2.tgz", + "integrity": "sha512-Ar3mhjcxhMzk+OVZ8pbnXdb0l8+pimvlsqBGRNkble2NVgyqOGE3yrCGi/lAYq7E7NRDMz89R1Wx5HIMCGgeYg==", + "dev": true, + "requires": { + "@npmcli/git": "^2.1.0", + "@npmcli/installed-package-contents": "^1.0.6", + "@npmcli/promise-spawn": "^1.2.0", + "@npmcli/run-script": "^2.0.0", + "cacache": "^15.0.5", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.3", + "mkdirp": "^1.0.3", + "npm-package-arg": "^8.0.1", + "npm-packlist": "^3.0.0", + "npm-pick-manifest": "^6.0.0", + "npm-registry-fetch": "^11.0.0", + "promise-retry": "^2.0.1", + "read-package-json-fast": "^2.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.1.0" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, + "parse5-html-rewriting-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", + "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", + "dev": true, + "requires": { + "parse5": "^6.0.1", + "parse5-sax-parser": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "parse5-sax-parser": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", + "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", + "dev": true, + "requires": { + "parse5": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pdfjs-dist": { + "version": "2.12.313", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz", + "integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==", + "dev": true, + "requires": {} + }, + "pdfmake": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.4.tgz", + "integrity": "sha512-EM39waHUe/Dg1W9C3XqYbpx6tfhYyU14JHZlI1HaW0AUEY32GbkRBjDLGWo9f7z/k3ea6k1p9yyDrflnvtZS1A==", + "dev": true, + "requires": { + "@foliojs-fork/linebreak": "^1.1.1", + "@foliojs-fork/pdfkit": "^0.13.0", + "iconv-lite": "^0.6.3", + "xmldoc": "^1.1.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true + }, + "piscina": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-3.1.0.tgz", + "integrity": "sha512-KTW4sjsCD34MHrUbx9eAAbuUSpVj407hQSgk/6Epkg0pbRBmv4a3UX7Sr8wxm9xYqQLnsN4mFOjqGDzHAdgKQg==", + "dev": true, + "requires": { + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0", + "nice-napi": "^1.0.2" + } + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==", + "dev": true + }, + "pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", + "dev": true, + "requires": { + "ts-pnp": "^1.1.6" + } + }, + "polished": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.1.4.tgz", + "integrity": "sha512-Nq5Mbza+Auo7N3sQb1QMFaQiDO+4UexWuSGR7Cjb4Sw11SZIJcrrFtiZ+L0jT9MBsUsxDboHVASbCLbE1rnECg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.16.7" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.17.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz", + "integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + } + } + }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "peer": true + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "8.4.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.6.tgz", + "integrity": "sha512-OovjwIzs9Te46vlEx7+uXB0PLijpwjXGKXjVGGPIGubGpq7uh5Xgf6D6FiJ/SzJMBosHDp6a2hiXOS97iBXcaA==", + "dev": true, + "requires": { + "nanoid": "^3.2.0", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "dev": true, + "requires": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-colormin": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.2.5.tgz", + "integrity": "sha512-+X30aDaGYq81mFqwyPpnYInsZQnNpdxMX0ajlY7AExCexEFkPVV+KrO7kXwayqEWL2xwEbNQ4nUO0ZsRWGnevg==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-convert-values": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.0.4.tgz", + "integrity": "sha512-bugzSAyjIexdObovsPZu/sBCTHccImJxLyFgeV0MmNBm/Lw5h5XnjfML6gzEmJ3A6nyfCW7hb1JXzcsA4Zfbdw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "dev": true, + "requires": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.0.3.tgz", + "integrity": "sha512-6W5BemziRoqIdAKT+1QjM4bNcJAQ7z7zk073730NHg4cUXh3/rQHHj7pmYxUB9aGhuRhBiUf0pXvIHkRwhQP0Q==", + "dev": true, + "requires": {} + }, + "postcss-discard-duplicates": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.3.tgz", + "integrity": "sha512-vPtm1Mf+kp7iAENTG7jI1MN1lk+fBqL5y+qxyi4v3H+lzsXEdfS3dwUZD45KVhgzDEgduur8ycB4hMegyMTeRw==", + "dev": true, + "requires": {} + }, + "postcss-discard-empty": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.0.3.tgz", + "integrity": "sha512-xGJugpaXKakwKI7sSdZjUuN4V3zSzb2Y0LOlmTajFbNinEjTfVs9PFW2lmKBaC/E64WwYppfqLD03P8l9BuueA==", + "dev": true, + "requires": {} + }, + "postcss-discard-overridden": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.0.4.tgz", + "integrity": "sha512-3j9QH0Qh1KkdxwiZOW82cId7zdwXVQv/gRXYDnwx5pBtR1sTkU4cXRK9lp5dSdiM0r0OICO/L8J6sV1/7m0kHg==", + "dev": true, + "requires": {} + }, + "postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "dev": true, + "requires": { + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-flexbugs-fixes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.2.1.tgz", + "integrity": "sha512-9SiofaZ9CWpQWxOwRh1b/r85KD5y7GgvsNt1056k6OYLvWUun0czCvogfJgylC22uJTwW1KzY3Gz65NZRlvoiQ==", + "dev": true, + "requires": { + "postcss": "^7.0.26" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-focus-visible": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-font-variant": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz", + "integrity": "sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-import": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.0.2.tgz", + "integrity": "sha512-BJ2pVK4KhUyMcqjuKs9RijV5tatNzNa73e/32aBVE/ejYPe37iH+6vAu9WvqUkB5OAYgLHzbSvzHnorybJCm9g==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-initial": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz", + "integrity": "sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "dev": true, + "requires": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-load-config": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.3.tgz", + "integrity": "sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==", + "dev": true, + "requires": { + "lilconfig": "^2.0.4", + "yaml": "^1.10.2" + } + }, + "postcss-loader": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.1.1.tgz", + "integrity": "sha512-lBmJMvRh1D40dqpWKr9Rpygwxn8M74U9uaCSeYGNKLGInbk9mXBt1ultHf2dH9Ghk6Ue4UXlXWwGMH9QdUJ5ug==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "semver": "^7.3.5" + } + }, + "postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-merge-longhand": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.0.6.tgz", + "integrity": "sha512-rkmoPwQO6ymJSmWsX6l2hHeEBQa7C4kJb9jyi5fZB1sE8nSCv7sqchoYPixRwX/yvLoZP2y6FA5kcjiByeJqDg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.0.3" + } + }, + "postcss-merge-rules": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.0.6.tgz", + "integrity": "sha512-nzJWJ9yXWp8AOEpn/HFAW72WKVGD2bsLiAmgw4hDchSij27bt6TF+sIK0cJUBAYT3SGcjtGGsOR89bwkkMuMgQ==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.0.2", + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-minify-font-values": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.0.4.tgz", + "integrity": "sha512-RN6q3tyuEesvyCYYFCRGJ41J1XFvgV+dvYGHr0CeHv8F00yILlN8Slf4t8XW4IghlfZYCeyRrANO6HpJ948ieA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-gradients": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.0.6.tgz", + "integrity": "sha512-E/dT6oVxB9nLGUTiY/rG5dX9taugv9cbLNTFad3dKxOO+BQg25Q/xo2z2ddG+ZB1CbkZYaVwx5blY8VC7R/43A==", + "dev": true, + "requires": { + "colord": "^2.9.1", + "cssnano-utils": "^3.0.2", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-params": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.0.5.tgz", + "integrity": "sha512-YBNuq3Rz5LfLFNHb9wrvm6t859b8qIqfXsWeK7wROm3jSKNpO1Y5e8cOyBv6Acji15TgSrAwb3JkVNCqNyLvBg==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "cssnano-utils": "^3.0.2", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-minify-selectors": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.1.3.tgz", + "integrity": "sha512-9RJfTiQEKA/kZhMaEXND893nBqmYQ8qYa/G+uPdVnXF6D/FzpfI6kwBtWEcHx5FqDbA79O9n6fQJfrIj6M8jvQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.6" + } + }, + "postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-normalize-charset": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.0.3.tgz", + "integrity": "sha512-iKEplDBco9EfH7sx4ut7R2r/dwTnUqyfACf62Unc9UiyFuI7uUqZZtY+u+qp7g8Qszl/U28HIfcsI3pEABWFfA==", + "dev": true, + "requires": {} + }, + "postcss-normalize-display-values": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.3.tgz", + "integrity": "sha512-FIV5FY/qs4Ja32jiDb5mVj5iWBlS3N8tFcw2yg98+8MkRgyhtnBgSC0lxU+16AMHbjX5fbSJgw5AXLMolonuRQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-positions": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.0.4.tgz", + "integrity": "sha512-qynirjBX0Lc73ROomZE3lzzmXXTu48/QiEzKgMeqh28+MfuHLsuqC9po4kj84igZqqFGovz8F8hf44hA3dPYmQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-repeat-style": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.4.tgz", + "integrity": "sha512-Innt+wctD7YpfeDR7r5Ik6krdyppyAg2HBRpX88fo5AYzC1Ut/l3xaxACG0KsbX49cO2n5EB13clPwuYVt8cMA==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-string": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.0.4.tgz", + "integrity": "sha512-Dfk42l0+A1CDnVpgE606ENvdmksttLynEqTQf5FL3XGQOyqxjbo25+pglCUvziicTxjtI2NLUR6KkxyUWEVubQ==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-timing-functions": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.3.tgz", + "integrity": "sha512-QRfjvFh11moN4PYnJ7hia4uJXeFotyK3t2jjg8lM9mswleGsNw2Lm3I5wO+l4k1FzK96EFwEVn8X8Ojrp2gP4g==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-unicode": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.4.tgz", + "integrity": "sha512-W79Regn+a+eXTzB+oV/8XJ33s3pDyFTND2yDuUCo0Xa3QSy1HtNIfRVPXNubHxjhlqmMFADr3FSCHT84ITW3ig==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-url": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.0.5.tgz", + "integrity": "sha512-Ws3tX+PcekYlXh+ycAt0wyzqGthkvVtZ9SZLutMVvHARxcpu4o7vvXcNoiNKyjKuWecnjS6HDI3fjBuDr5MQxQ==", + "dev": true, + "requires": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-normalize-whitespace": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.4.tgz", + "integrity": "sha512-wsnuHolYZjMwWZJoTC9jeI2AcjA67v4UuidDrPN9RnX8KIZfE+r2Nd6XZRwHVwUiHmRvKQtxiqo64K+h8/imaw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-ordered-values": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.0.5.tgz", + "integrity": "sha512-mfY7lXpq+8bDEHfP+muqibDPhZ5eP9zgBEF9XRvoQgXcQe2Db3G1wcvjbnfjXG6wYsl+0UIjikqq4ym1V2jGMQ==", + "dev": true, + "requires": { + "cssnano-utils": "^3.0.2", + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", + "dev": true, + "requires": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + }, + "dependencies": { + "autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "dev": true, + "requires": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-reduce-initial": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.0.3.tgz", + "integrity": "sha512-c88TkSnQ/Dnwgb4OZbKPOBbCaauwEjbECP5uAuFPOzQ+XdjNjRH7SG0dteXrpp1LlIFEKK76iUGgmw2V0xeieA==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "caniuse-api": "^3.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.4.tgz", + "integrity": "sha512-VIJB9SFSaL8B/B7AXb7KHL6/GNNbbCHslgdzS9UDfBZYIA2nx8NLY7iD/BXFSO/1sRUILzBTfHCoW5inP37C5g==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0" + } + }, + "postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-selector-not": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz", + "integrity": "sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "postcss-selector-parser": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", + "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.0.4.tgz", + "integrity": "sha512-yDKHvULbnZtIrRqhZoA+rxreWpee28JSRH/gy9727u0UCgtpv1M/9WEWY3xySlFa0zQJcqf6oCBJPR5NwkmYpg==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + } + }, + "postcss-unique-selectors": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.0.4.tgz", + "integrity": "sha512-5ampwoSDJCxDPoANBIlMgoBcYUHnhaiuLYJR5pj1DLnYQvMRVyFuTA5C3Bvt+aHtiqWpJkD/lXT50Vo1D0ZsAQ==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.5" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "dev": true, + "requires": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prettier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", + "dev": true + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true + }, + "pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "prismjs": { + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.26.0.tgz", + "integrity": "sha512-HUoH9C5Z3jKkl3UunCyiD5jwk0+Hz0fIgQ2nbwU2Oo/ceuTAQAg+pPVnfdt2TJWRVLcxKh9iuoYDUSc8clb5UQ==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "promise.allsettled": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.5.tgz", + "integrity": "sha512-tVDqeZPoBC0SlzJHzWGZ2NKAguVq2oiYj7gbggbiTvH2itHohijTp7njOUA0aQ/nl+0lr/r6egmhoYu63UZ/pQ==", + "dev": true, + "requires": { + "array.prototype.map": "^1.0.4", + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "iterate-value": "^1.0.2" + } + }, + "promise.prototype.finally": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/promise.prototype.finally/-/promise.prototype.finally-3.1.3.tgz", + "integrity": "sha512-EXRF3fC9/0gz4qkt/f5EP5iW4kj9oFpBICNpCNOb/52+8nlHIX07FPLbi/q4qYBQ1xZqivMzTpNQSnArVASolQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + } + } + }, + "property-information": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-5.6.0.tgz", + "integrity": "sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "proxy-middleware": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", + "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "optional": true, + "peer": true + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "quote-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", + "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", + "dev": true, + "requires": { + "buffer-equal": "0.0.1", + "minimist": "^1.1.3", + "through2": "^2.0.0" + } + }, + "ramda": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", + "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + } + } + }, + "raw-loader": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", + "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "react": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "react-colorful": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.5.1.tgz", + "integrity": "sha512-M1TJH2X3RXEt12sWkpa6hLc/bbYS0H6F4rIqjQZ+RxNBstpY67d9TrFXtqdZwhpmBXcCwEi7stKqFue3ZRkiOg==", + "dev": true, + "requires": {} + }, + "react-dom": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, + "react-draggable": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.4.tgz", + "integrity": "sha512-6e0WdcNLwpBx/YIDpoyd2Xb04PB0elrDrulKUgdrIlwuYvxh5Ok9M+F8cljm8kPXXs43PmMzek9RrB1b7mLMqA==", + "dev": true, + "requires": { + "clsx": "^1.1.1", + "prop-types": "^15.6.0" + } + }, + "react-element-to-jsx-string": { + "version": "14.3.4", + "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz", + "integrity": "sha512-t4ZwvV6vwNxzujDQ+37bspnLwA4JlgUPWhLjBJWsNIDceAf6ZKUTCjdm08cN6WeZ5pTMKiCJkmAYnpmR4Bm+dg==", + "dev": true, + "requires": { + "@base2/pretty-print-object": "1.0.1", + "is-plain-object": "5.0.0", + "react-is": "17.0.2" + }, + "dependencies": { + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + } + } + }, + "react-fast-compare": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==", + "dev": true + }, + "react-helmet-async": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.2.3.tgz", + "integrity": "sha512-mCk2silF53Tq/YaYdkl2sB+/tDoPnaxN7dFS/6ZLJb/rhUY2EWGI5Xj2b4jHppScMqY45MbgPSwTxDchKpZ5Kw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + } + }, + "react-inspector": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz", + "integrity": "sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.0.0", + "is-dom": "^1.0.0", + "prop-types": "^15.0.0" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "react-popper": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.2.5.tgz", + "integrity": "sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==", + "dev": true, + "requires": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + } + }, + "react-popper-tooltip": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz", + "integrity": "sha512-EnERAnnKRptQBJyaee5GJScWNUKQPDD2ywvzZyUjst/wj5U64C8/CnSYLNEmP2hG0IJ3ZhtDxE8oDN+KOyavXQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@popperjs/core": "^2.5.4", + "react-popper": "^2.2.4" + } + }, + "react-router": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.1.tgz", + "integrity": "sha512-2fG0udBtxou9lXtK97eJeET2ki5//UWfQSl1rlJ7quwe6jrktK9FCCc8dQb5QY6jAv3jua8bBQRhhDOM/kVRsg==", + "dev": true, + "requires": { + "history": "^5.2.0" + }, + "dependencies": { + "history": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz", + "integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.6" + } + } + } + }, + "react-router-dom": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.1.tgz", + "integrity": "sha512-I6Zax+/TH/cZMDpj3/4Fl2eaNdcvoxxHoH1tYOREsQ22OKDYofGebrNm6CTPUcvLvZm63NL/vzCYdjf9CUhqmA==", + "dev": true, + "requires": { + "history": "^5.2.0", + "react-router": "6.2.1" + }, + "dependencies": { + "history": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/history/-/history-5.2.0.tgz", + "integrity": "sha512-uPSF6lAJb3nSePJ43hN3eKj1dTWpN9gMod0ZssbFTIsen+WehTmEadgL+kg78xLJFdRfrrC//SavDzmRVdE+Ig==", + "dev": true, + "requires": { + "@babel/runtime": "^7.7.6" + } + } + } + }, + "react-sizeme": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.2.tgz", + "integrity": "sha512-xOIAOqqSSmKlKFJLO3inBQBdymzDuXx4iuwkNcJmC96jeiOg5ojByvL+g3MW9LPEsojLbC6pf68zOfobK8IPlw==", + "dev": true, + "requires": { + "element-resize-detector": "^1.2.2", + "invariant": "^2.2.4", + "shallowequal": "^1.1.0", + "throttle-debounce": "^3.0.1" + } + }, + "react-syntax-highlighter": { + "version": "13.5.3", + "resolved": "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-13.5.3.tgz", + "integrity": "sha512-crPaF+QGPeHNIblxxCdf2Lg936NAHKhNhuMzRL3F9ct6aYXL3NcZtCL0Rms9+qVo6Y1EQLdXGypBNSbPL/r+qg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.3.1", + "highlight.js": "^10.1.1", + "lowlight": "^1.14.0", + "prismjs": "^1.21.0", + "refractor": "^3.1.0" + } + }, + "react-textarea-autosize": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz", + "integrity": "sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ==", + "dev": true, + "requires": { + "@babel/runtime": "^7.10.2", + "use-composed-ref": "^1.0.0", + "use-latest": "^1.0.0" + } + }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=", + "dev": true, + "requires": { + "pify": "^2.3.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "read-package-json-fast": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", + "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "dev": true, + "requires": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "refractor": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/refractor/-/refractor-3.5.0.tgz", + "integrity": "sha512-QwPJd3ferTZ4cSPPjdP5bsYHMytwWYnAN5EEnLtGvkqp/FCCnGsBgxrm9EuIDnjUC3Uc/kETtvVi7fSIVC74Dg==", + "dev": true, + "requires": { + "hastscript": "^6.0.0", + "parse-entities": "^2.0.0", + "prismjs": "~1.25.0" + }, + "dependencies": { + "prismjs": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.25.0.tgz", + "integrity": "sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==", + "dev": true + } + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz", + "integrity": "sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "regexpu-core": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.0.1.tgz", + "integrity": "sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==", + "dev": true, + "requires": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.0.1", + "regjsgen": "^0.6.0", + "regjsparser": "^0.8.2", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.0.0" + } + }, + "regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==", + "dev": true + }, + "regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remark-external-links": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz", + "integrity": "sha512-5vPSX0kHoSsqtdftSHhIYofVINC8qmp0nctkeU9YoJwV3YfiBRiI6cbFRJ0oI/1F9xS+bopXG0m2KS8VFscuKA==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "is-absolute-url": "^3.0.0", + "mdast-util-definitions": "^4.0.0", + "space-separated-tokens": "^1.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "remark-footnotes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/remark-footnotes/-/remark-footnotes-2.0.0.tgz", + "integrity": "sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==", + "dev": true + }, + "remark-mdx": { + "version": "1.6.22", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-1.6.22.tgz", + "integrity": "sha512-phMHBJgeV76uyFkH4rvzCftLfKCr2RZuF+/gmVcaKrpsihyzmhXjA0BEMDaPTXG5y8qZOKPVo83NAOX01LPnOQ==", + "dev": true, + "requires": { + "@babel/core": "7.12.9", + "@babel/helper-plugin-utils": "7.10.4", + "@babel/plugin-proposal-object-rest-spread": "7.12.1", + "@babel/plugin-syntax-jsx": "7.12.1", + "@mdx-js/util": "1.6.22", + "is-alphabetical": "1.0.4", + "remark-parse": "8.0.3", + "unified": "9.2.0" + }, + "dependencies": { + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz", + "integrity": "sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.12.1" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz", + "integrity": "sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "remark-parse": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", + "dev": true, + "requires": { + "ccount": "^1.0.0", + "collapse-white-space": "^1.0.2", + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-whitespace-character": "^1.0.0", + "is-word-character": "^1.0.0", + "markdown-escapes": "^1.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.5.4", + "state-toggle": "^1.0.0", + "trim": "0.0.1", + "trim-trailing-lines": "^1.0.0", + "unherit": "^1.0.4", + "unist-util-remove-position": "^2.0.0", + "vfile-location": "^3.0.0", + "xtend": "^4.0.1" + } + }, + "remark-slug": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/remark-slug/-/remark-slug-6.1.0.tgz", + "integrity": "sha512-oGCxDF9deA8phWvxFuyr3oSJsdyUAxMFbA0mZ7Y1Sas+emILtO+e5WutF9564gDsEN4IXaQXm5pFo6MLH+YmwQ==", + "dev": true, + "requires": { + "github-slugger": "^1.0.0", + "mdast-util-to-string": "^1.0.0", + "unist-util-visit": "^2.0.0" + } + }, + "remark-squeeze-paragraphs": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-4.0.0.tgz", + "integrity": "sha512-8qRqmL9F4nuLPIgl92XUuxI3pFxize+F1H0e/W3llTk0UsjJaj01+RrirkMw7P21RKe4X6goQhYRSvNWX+70Rw==", + "dev": true, + "requires": { + "mdast-squeeze-paragraphs": "^4.0.0" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "peer": true + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true, + "optional": true, + "peer": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + }, + "dependencies": { + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + } + } + }, + "rxjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.4.tgz", + "integrity": "sha512-h5M3Hk78r6wAheJF0a5YahB1yRQKCsZ4MsGdZ5O9ETbVtjPcScGfrMmoOq7EBsCRzd4BDkvDJ7ogP8Sz5tTFiQ==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sane": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz", + "integrity": "sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==", + "dev": true, + "requires": { + "@cnakazawa/watch": "^1.0.3", + "anymatch": "^2.0.0", + "capture-exit": "^2.0.0", + "exec-sh": "^0.3.2", + "execa": "^1.0.0", + "fb-watchman": "^2.0.0", + "micromatch": "^3.1.4", + "minimist": "^1.1.1", + "walker": "~1.0.5" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "sass": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.36.0.tgz", + "integrity": "sha512-fQzEjipfOv5kh930nu3Imzq3ie/sGDc/4KtQMJlt7RRdrkQSfe37Bwi/Rf/gfuYHsIuE1fIlDMvpyMcEwjnPvg==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0" + } + }, + "sass-loader": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.1.0.tgz", + "integrity": "sha512-FVJZ9kxVRYNZTIe2xhw93n3xJNYZADr+q69/s98l9nTCrWASo+DR2Ot0s5xTKQDDEosUkatsGeHxcH4QBp5bSg==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "scheduler": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "dev": true, + "peer": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + } + } + }, + "scope-analyzer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.1.2.tgz", + "integrity": "sha512-5cfCmsTYV/wPaRIItNxatw02ua/MThdIUNnUOCYp+3LSEJvnG804ANw2VLaavNILIfWXF1D1G2KNANkBBvInwQ==", + "dev": true, + "requires": { + "array-from": "^2.1.1", + "dash-ast": "^2.0.1", + "es6-map": "^0.1.5", + "es6-set": "^0.1.5", + "es6-symbol": "^3.1.1", + "estree-is-function": "^1.0.0", + "get-assigned-identifiers": "^1.1.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "send": { + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", + "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "1.8.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-favicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz", + "integrity": "sha1-k10kDN/g9YBTB/3+ln2IlCosvPA=", + "dev": true, + "requires": { + "etag": "~1.8.1", + "fresh": "0.5.2", + "ms": "2.1.1", + "parseurl": "~1.3.2", + "safe-buffer": "5.1.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", + "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shallow-copy": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", + "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", + "dev": true + }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + } + }, + "socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true, + "optional": true, + "peer": true + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "sockjs-client": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz", + "integrity": "sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==", + "dev": true, + "requires": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.5.3" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz", + "integrity": "sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.1", + "socks": "^2.6.1" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.0.tgz", + "integrity": "sha512-GKGWqWvYr04M7tn8dryIWvb0s8YM41z82iQv01yBtIylgxax0CwvSy6gc2Y02iuXwEfGWRlMicH0nvms9UZphw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "iconv-lite": "^0.6.2", + "source-map-js": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "source-map-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz", + "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==", + "dev": true + } + } + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "space-separated-tokens": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", + "integrity": "sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "state-toggle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz", + "integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==", + "dev": true + }, + "static-eval": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.0.tgz", + "integrity": "sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==", + "dev": true, + "requires": { + "escodegen": "^1.11.1" + }, + "dependencies": { + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "static-module": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/static-module/-/static-module-3.0.4.tgz", + "integrity": "sha512-gb0v0rrgpBkifXCa3yZXxqVmXDVE+ETXj6YlC/jt5VzOnGXR2C15+++eXuMDUYsePnbhf+lwW0pE1UXyOLtGCw==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "^1.11.1", + "has": "^1.0.1", + "magic-string": "0.25.1", + "merge-source-map": "1.0.4", + "object-inspect": "^1.6.0", + "readable-stream": "~2.3.3", + "scope-analyzer": "^2.0.1", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.5", + "through2": "~2.0.3" + }, + "dependencies": { + "escodegen": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "magic-string": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", + "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.1" + } + }, + "merge-source-map": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", + "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "dev": true, + "requires": { + "source-map": "^0.5.6" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "store2": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/store2/-/store2-2.13.1.tgz", + "integrity": "sha512-iJtHSGmNgAUx0b/MCS6ASGxb//hGrHHRgzvN+K5bvkBTN7A9RTpPSf1WSp+nPGvWCJ1jRnvY7MKnuqfoi3OEqg==", + "dev": true + }, + "storybook-addon-designs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/storybook-addon-designs/-/storybook-addon-designs-6.2.1.tgz", + "integrity": "sha512-ihsscab8185HnxqTNZlM4TfrCPVsO7AimVA8BapuqT/sfZQF9m5H9C0plT3kbECdIMh2cmzMBF1Tc9ckWRgpWg==", + "dev": true, + "requires": { + "@figspec/react": "^1.0.0" + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "streamroller": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.2.tgz", + "integrity": "sha512-ur6y5S5dopOaRXBuRIZ1u6GC5bcEXHRZKgfBjfCglMhmIf+roVCECjvkEYzNQOXIN2/JPnkMPW/8B3CZoKaEPA==", + "dev": true, + "optional": true, + "peer": true, + "requires": { + "date-format": "^4.0.3", + "debug": "^4.1.1", + "fs-extra": "^10.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "peer": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.matchall": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz", + "integrity": "sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1", + "get-intrinsic": "^1.1.1", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.3.1", + "side-channel": "^1.0.4" + } + }, + "string.prototype.padend": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.3.tgz", + "integrity": "sha512-jNIIeokznm8SD/TZISQsZKYu7RJyheFNt84DUPrh482GC8RVp2MKqm2O5oBRdGxbDQoXrhhWtPIWQOiy20svUg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "string.prototype.padstart": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/string.prototype.padstart/-/string.prototype.padstart-3.1.3.tgz", + "integrity": "sha512-NZydyOMtYxpTjGqp0VN5PYUF/tsU15yDMZnUdj16qRUIUiMJkHHSDElYyQFrMu+/WloTpA7MQSiADhBicDfaoA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "style-loader": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.2.1.tgz", + "integrity": "sha512-1k9ZosJCRFaRbY6hH49JFlRB0fVSbmnyq1iTPjNxUmGVjBNEmwrrHPenhlp+Lgo51BojHSf6pl2FcqYaN3PfVg==", + "dev": true, + "requires": {} + }, + "style-to-object": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", + "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "dev": true, + "requires": { + "inline-style-parser": "0.1.1" + } + }, + "stylehacks": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.0.3.tgz", + "integrity": "sha512-ENcUdpf4yO0E1rubu8rkxI+JGQk4CgjchynZ4bDBJDfqdy+uhTRSWb8/F3Jtu+Bw5MW45Po3/aQGeIyyxgQtxg==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "postcss-selector-parser": "^6.0.4" + } + }, + "stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "requires": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "stylus-loader": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-6.1.0.tgz", + "integrity": "sha512-qKO34QCsOtSJrXxQQmXsPeaVHh6hMumBAFIoJTcsSr2VzrA6o/CW9HCGR8spCjzJhN8oKQHdj/Ytx0wwXyElkw==", + "dev": true, + "requires": { + "fast-glob": "^3.2.5", + "klona": "^2.0.4", + "normalize-path": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dev": true, + "requires": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "dependencies": { + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + } + } + }, + "symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "symbol.prototype.description": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/symbol.prototype.description/-/symbol.prototype.description-1.0.5.tgz", + "integrity": "sha512-x738iXRYsrAt9WBhRCVG5BtIC3B7CUkFwbHW2zOvGtwM33s7JjrCDyq8V0zgMYVb5ymsL8+qkzzpANH63CPQaQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-symbol-description": "^1.0.0", + "has-symbols": "^1.0.2", + "object.getownpropertydescriptors": "^2.1.2" + } + }, + "synchronous-promise": { + "version": "2.0.15", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.15.tgz", + "integrity": "sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg==", + "dev": true + }, + "tailwindcss": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.23.tgz", + "integrity": "sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==", + "dev": true, + "requires": { + "arg": "^5.0.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "cosmiconfig": "^7.0.1", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "normalize-path": "^3.0.0", + "object-hash": "^2.2.0", + "postcss": "^8.4.6", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.0", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "telejson": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-5.3.3.tgz", + "integrity": "sha512-PjqkJZpzEggA9TBpVtJi1LVptP7tYtXB6rEubwlHap76AMjzvOdKX41CxyaW7ahhzDU1aftXnMCx5kAPDZTQBA==", + "dev": true, + "requires": { + "@types/is-function": "^1.0.0", + "global": "^4.4.0", + "is-function": "^1.0.2", + "is-regex": "^1.1.2", + "is-symbol": "^1.0.3", + "isobject": "^4.0.0", + "lodash": "^4.17.21", + "memoizerific": "^1.11.3" + }, + "dependencies": { + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true + } + } + }, + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "peer": true, + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } + }, + "terser": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.1.tgz", + "integrity": "sha512-b3e+d5JbHAe/JSjwsC3Zn55wsBIM7AsHLjKxT31kGCldgbpFePaFo+PiddtO6uwRZWRw7sPXmAN8dTW61xmnSg==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.7.2", + "source-map-support": "~0.5.19" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.1.4.tgz", + "integrity": "sha512-C2WkFwstHDhVEmsmlCxrXUtVklS+Ir1A7twrYzrDrQQOIMOaVAYykaoo/Aq1K0QRkMoY2hhvDQY1cm4jnIMFwA==", + "dev": true, + "requires": { + "jest-worker": "^27.0.2", + "p-limit": "^3.1.0", + "schema-utils": "^3.0.0", + "serialize-javascript": "^6.0.0", + "source-map": "^0.6.1", + "terser": "^5.7.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true, + "peer": true + }, + "throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=", + "dev": true + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "dependencies": { + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=", + "dev": true + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "trim": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", + "integrity": "sha1-WFhUf2spB1fulczMZm+1AITEYN0=", + "dev": true + }, + "trim-trailing-lines": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz", + "integrity": "sha512-rjUWSqnfTNrjbB9NQWfPMH/xRK1deHeGsHoVfpxJ++XeYXE0d6B1En37AHfw3jtfTU7dzMzZL2jjpe8Qb5gLIQ==", + "dev": true + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true + }, + "ts-dedent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.2.0.tgz", + "integrity": "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==", + "dev": true + }, + "ts-jest": { + "version": "27.1.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.4.tgz", + "integrity": "sha512-qjkZlVPWVctAezwsOD1OPzbZ+k7zA5z3oxII4dGdZo5ggX/PL7kvwTM0pXTr10fAtbiVpJaL3bWd502zAhpgSQ==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "dependencies": { + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "ts-loader": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.3.0.tgz", + "integrity": "sha512-MgGly4I6cStsJy27ViE32UoqxPTN9Xly4anxxVyaIWR+9BGxboV4EyJBGfR3RePV7Ksjj3rHmPZJeIt+7o4Vag==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^4.0.0", + "loader-utils": "^2.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "ts-morph": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-13.0.3.tgz", + "integrity": "sha512-pSOfUMx8Ld/WUreoSzvMFQG5i9uEiWIsBYjpU9+TTASOeUa89j5HykomeqVULm1oqWtBdleI3KEFRLrlA3zGIw==", + "dev": true, + "requires": { + "@ts-morph/common": "~0.12.3", + "code-block-writer": "^11.0.0" + } + }, + "ts-pnp": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz", + "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==", + "dev": true + }, + "tsconfig-paths": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz", + "integrity": "sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "tsconfig-paths-webpack-plugin": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz", + "integrity": "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "enhanced-resolve": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz", + "integrity": "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + } + } + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true, + "optional": true, + "peer": true + }, + "uglify-js": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz", + "integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==", + "dev": true, + "optional": true + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", + "dev": true + }, + "unherit": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz", + "integrity": "sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ==", + "dev": true, + "requires": { + "inherits": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "dev": true + }, + "unicode-properties": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.3.1.tgz", + "integrity": "sha512-nIV3Tf3LcUEZttY/2g4ZJtGXhWwSkuLL+rCu0DIAMbjyVPj+8j5gNVz4T/sVbnQybIsd5SFGkPKg/756OY6jlA==", + "dev": true, + "requires": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "dev": true + }, + "unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dev": true, + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + }, + "dependencies": { + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + } + } + }, + "unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", + "dev": true, + "requires": { + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unist-builder": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-2.0.3.tgz", + "integrity": "sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==", + "dev": true + }, + "unist-util-generated": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-1.1.6.tgz", + "integrity": "sha512-cln2Mm1/CZzN5ttGK7vkoGw+RZ8VcUH6BtGbq98DDtRGquAAOXig1mrBQYelOwMXYS8rK+vZDyyojSjp7JX+Lg==", + "dev": true + }, + "unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true + }, + "unist-util-position": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-3.1.0.tgz", + "integrity": "sha512-w+PkwCbYSFw8vpgWD0v7zRCl1FpY3fjDSQ3/N/wNd9Ffa4gPi8+4keqt99N3XW6F99t/mUzp2xAhNmfKWp95QA==", + "dev": true + }, + "unist-util-remove": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-2.1.0.tgz", + "integrity": "sha512-J8NYPyBm4baYLdCbjmf1bhPu45Cr1MWTm77qd9istEkzWpnN6O9tMsEbB2JhNnBCqGENRqEWomQ+He6au0B27Q==", + "dev": true, + "requires": { + "unist-util-is": "^4.0.0" + } + }, + "unist-util-remove-position": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-2.0.1.tgz", + "integrity": "sha512-fDZsLYIe2uT+oGFnuZmy73K6ZxOPG/Qcm+w7jbEjaFcJgbQ6cqjs/eSPzXhsmGpAsWPkqZM9pYjww5QTn3LHMA==", + "dev": true, + "requires": { + "unist-util-visit": "^2.0.0" + } + }, + "unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "requires": { + "@types/unist": "^2.0.2" + } + }, + "unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "unix-crypt-td-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.1.4.tgz", + "integrity": "sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "url-parse": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.7.tgz", + "integrity": "sha512-HxWkieX+STA38EDk7CE9MEryFeHCKzgagxlGvsdS7WBImq9Mk+PGwiT56w82WI3aicwJA8REp42Cxo98c8FZMA==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "use-composed-ref": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.2.1.tgz", + "integrity": "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==", + "dev": true, + "requires": {} + }, + "use-isomorphic-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz", + "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==", + "dev": true, + "requires": {} + }, + "use-latest": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.2.0.tgz", + "integrity": "sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw==", + "dev": true, + "requires": { + "use-isomorphic-layout-effect": "^1.0.0" + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "uuid-browser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid-browser/-/uuid-browser-3.1.0.tgz", + "integrity": "sha1-DwWkCu90+eWVHiDvv0SxGHHlZBA=", + "dev": true + }, + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vfile": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.1.tgz", + "integrity": "sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + } + }, + "vfile-location": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.2.0.tgz", + "integrity": "sha512-aLEIZKv/oxuCDZ8lkJGhuhztf/BW4M+iHdCwglA/eWc+vtuRFJj8EtgceYFX4LRjOhCAAiNHsKGssC6onJ+jbA==", + "dev": true + }, + "vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "optional": true, + "peer": true + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "watchpack": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "optional": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true, + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "optional": true, + "requires": { + "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" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "optional": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "web-namespaces": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz", + "integrity": "sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw==", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "webpack": { + "version": "5.69.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.69.0.tgz", + "integrity": "sha512-E5Fqu89Gu8fR6vejRqu26h8ld/k6/dCVbeGUcuZjc+goQHDfCPU9rER71JmdtBYGmci7Ec2aFEATQ2IVXKy2wg==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.0", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "enhanced-resolve": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.0.tgz", + "integrity": "sha512-weDYmzbBygL7HzGGS26M3hGQx68vehdEg6VUmqSOaFzXExFqlnKuSvsEJCVGQHScS8CQMbrAqftT+AzzHNt/YA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + } + } + }, + "webpack-dev-middleware": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.0.0.tgz", + "integrity": "sha512-9zng2Z60pm6A98YoRcA0wSxw1EYn7B7y5owX/Tckyt9KGyULTkLtiavjaXlWqOMkM0YtqGgL3PvMOFgyFLq8vw==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "mem": "^8.1.1", + "memfs": "^3.2.2", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^3.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "webpack-dev-server": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz", + "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==", + "dev": true, + "requires": { + "ansi-html-community": "0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "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" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-hot-middleware": { + "version": "2.25.1", + "resolved": "https://registry.npmjs.org/webpack-hot-middleware/-/webpack-hot-middleware-2.25.1.tgz", + "integrity": "sha512-Koh0KyU/RPYwel/khxbsDz9ibDivmUbrRuKSSQvW42KSDdO4w23WI3SkHpSUKHE76LrFnnM/L7JCrpBwu8AXYw==", + "dev": true, + "requires": { + "ansi-html-community": "0.0.8", + "html-entities": "^2.1.0", + "querystring": "^0.2.0", + "strip-ansi": "^6.0.0" + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpack-subresource-integrity": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.5.2.tgz", + "integrity": "sha512-GBWYBoyalbo5YClwWop9qe6Zclp8CIXYGIz12OPclJhIrSplDxs1Ls1JDMH8xBPPrg1T6ISaTW9Y6zOrwEiAzw==", + "dev": true, + "requires": { + "webpack-sources": "^1.3.0" + } + }, + "webpack-virtual-modules": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.2.2.tgz", + "integrity": "sha512-kDUmfm3BZrei0y+1NTHJInejzxfhtU8eDj2M7OKb2IWrPFAeO1SOH2KuQ68MSZu9IGEHcxbkKKR1v18FrUSOmA==", + "dev": true, + "requires": { + "debug": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "windows-release": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", + "integrity": "sha512-OxmV4wzDKB1x7AZaZgXMVsdJ1qER1ed83ZrTYd5Bwq2HfJVg3DJS8nqlAG4sMoJ7mu8cuRmLEYyU13BKwctRAg==", + "dev": true, + "requires": { + "execa": "^4.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "worker-rpc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", + "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", + "dev": true, + "requires": { + "microevent.ts": "~0.1.1" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "dev": true, + "requires": {} + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "xmldoc": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-1.1.2.tgz", + "integrity": "sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ==", + "dev": true, + "requires": { + "sax": "^1.2.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yargs": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz", + "integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "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.0.0" + } + }, + "yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + }, + "zone.js": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.4.tgz", + "integrity": "sha512-DDh2Ab+A/B+9mJyajPjHFPWfYU1H+pdun4wnnk0OcQTNjem1XQSZ2CDW+rfZEUDjv5M19SBqAkjZi0x5wuB5Qw==", + "peer": true, + "requires": { + "tslib": "^2.0.0" + } + }, + "zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "dev": true + } + } +} diff --git a/libs/components/package.json b/libs/components/package.json new file mode 100644 index 0000000000..ede92941af --- /dev/null +++ b/libs/components/package.json @@ -0,0 +1,56 @@ +{ + "name": "components", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "jest", + "test:watch": "jest --watch", + "docs:json": "compodoc -p ./tsconfig.json -e json -d .", + "storybook": "npm run docs:json && start-storybook -p 6006", + "build-storybook": "npm run docs:json && build-storybook", + "chromatic": "chromatic --exit-zero-on-changes" + }, + "private": true, + "dependencies": { + "@angular/animations": "^12.2.13", + "@angular/cdk": "^12.2.13", + "@angular/common": "^12.2.13", + "@angular/compiler": "^12.2.13", + "@angular/core": "^12.2.13", + "@angular/forms": "^12.2.13", + "@angular/platform-browser": "^12.2.13", + "@angular/platform-browser-dynamic": "^12.2.13", + "@bitwarden/jslib-angular": "file:../angular", + "bootstrap": "4.6.0", + "rxjs": "^7.4.0", + "tslib": "^2.3.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^12.2.13", + "@angular/cli": "^12.2.13", + "@angular/compiler-cli": "^12.2.13", + "@angular/elements": "^12.2.13", + "@babel/core": "^7.16.10", + "@compodoc/compodoc": "^1.1.16", + "@storybook/addon-a11y": "^6.4.19", + "@storybook/addon-actions": "^6.4.18", + "@storybook/addon-essentials": "^6.4.18", + "@storybook/addon-links": "^6.4.18", + "@storybook/angular": "^6.4.18", + "@storybook/builder-webpack5": "^6.4.18", + "@storybook/manager-webpack5": "^6.4.18", + "@types/node": "^16.11.33", + "@webcomponents/custom-elements": "^1.5.0", + "autoprefixer": "^10.4.2", + "babel-loader": "^8.2.3", + "chromatic": "^6.5.2", + "jest-preset-angular": "^11.1.2", + "postcss": "^8.4.6", + "storybook-addon-designs": "^6.2.1", + "tailwindcss": "^3.0.18", + "typescript": "~4.3.5" + } +} diff --git a/libs/components/spec/test.ts b/libs/components/spec/test.ts new file mode 100644 index 0000000000..a702c63396 --- /dev/null +++ b/libs/components/spec/test.ts @@ -0,0 +1 @@ +import "jest-preset-angular/setup-jest"; diff --git a/libs/components/src/app/app.component.ts b/libs/components/src/app/app.component.ts new file mode 100644 index 0000000000..d4c9ddd2f4 --- /dev/null +++ b/libs/components/src/app/app.component.ts @@ -0,0 +1,9 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "app-root", + template: "", +}) +export class AppComponent { + title = "components"; +} diff --git a/libs/components/src/app/app.module.ts b/libs/components/src/app/app.module.ts new file mode 100644 index 0000000000..9da535ffbe --- /dev/null +++ b/libs/components/src/app/app.module.ts @@ -0,0 +1,13 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; +import { BrowserModule } from "@angular/platform-browser"; + +import { AppComponent } from "./app.component"; + +@NgModule({ + declarations: [AppComponent], + imports: [BrowserModule, CommonModule], + providers: [{ provide: "WINDOW", useValue: window }], + bootstrap: [AppComponent], +}) +export class AppModule {} diff --git a/libs/components/src/badge/badge.directive.ts b/libs/components/src/badge/badge.directive.ts new file mode 100644 index 0000000000..4d949bc681 --- /dev/null +++ b/libs/components/src/badge/badge.directive.ts @@ -0,0 +1,58 @@ +import { Directive, ElementRef, HostBinding, Input } from "@angular/core"; + +type BadgeTypes = "primary" | "secondary" | "success" | "danger" | "warning" | "info"; + +const styles: Record = { + primary: ["tw-bg-primary-500"], + secondary: ["tw-bg-text-muted"], + success: ["tw-bg-success-500"], + danger: ["tw-bg-danger-500"], + warning: ["tw-bg-warning-500"], + info: ["tw-bg-info-500"], +}; + +const hoverStyles: Record = { + primary: ["hover:tw-bg-primary-700"], + secondary: ["hover:tw-bg-secondary-700"], + success: ["hover:tw-bg-success-700"], + danger: ["hover:tw-bg-danger-700"], + warning: ["hover:tw-bg-warning-700"], + info: ["hover:tw-bg-info-700"], +}; + +@Directive({ + selector: "span[bitBadge], a[bitBadge], button[bitBadge]", +}) +export class BadgeDirective { + @HostBinding("class") get classList() { + return [ + "tw-inline-block", + "tw-py-1", + "tw-px-1.5", + "tw-font-bold", + "tw-leading-none", + "tw-text-center", + "!tw-text-contrast", + "tw-rounded", + "tw-border-none", + "tw-box-border", + "tw-whitespace-no-wrap", + "tw-text-xs", + "hover:tw-no-underline", + "focus:tw-outline-none", + "focus:tw-ring", + "focus:tw-ring-offset-2", + "focus:tw-ring-primary-700", + ] + .concat(styles[this.badgeType]) + .concat(this.hasHoverEffects ? hoverStyles[this.badgeType] : []); + } + + @Input() badgeType: BadgeTypes = "primary"; + + private hasHoverEffects = false; + + constructor(el: ElementRef) { + this.hasHoverEffects = el?.nativeElement?.nodeName != "SPAN"; + } +} diff --git a/libs/components/src/badge/badge.module.ts b/libs/components/src/badge/badge.module.ts new file mode 100644 index 0000000000..e1b8292363 --- /dev/null +++ b/libs/components/src/badge/badge.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; + +import { BadgeDirective } from "./badge.directive"; + +@NgModule({ + imports: [CommonModule], + exports: [BadgeDirective], + declarations: [BadgeDirective], +}) +export class BadgeModule {} diff --git a/libs/components/src/badge/badge.stories.ts b/libs/components/src/badge/badge.stories.ts new file mode 100644 index 0000000000..e36b2cd776 --- /dev/null +++ b/libs/components/src/badge/badge.stories.ts @@ -0,0 +1,56 @@ +import { Meta, Story } from "@storybook/angular"; + +import { BadgeDirective } from "./badge.directive"; + +export default { + title: "Jslib/Badge", + component: BadgeDirective, + args: { + badgeType: "primary", + }, + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/file/f32LSg3jaegICkMu7rPARm/Tailwind-Component-Library-Update?node-id=1881%3A16956", + }, + }, +} as Meta; + +const Template: Story = (args: BadgeDirective) => ({ + props: args, + template: ` + Span Badge +

+ Link Badge +

+ Button + `, +}); + +export const Primary = Template.bind({}); +Primary.args = {}; + +export const Secondary = Template.bind({}); +Secondary.args = { + badgeType: "secondary", +}; + +export const Success = Template.bind({}); +Success.args = { + badgeType: "success", +}; + +export const Danger = Template.bind({}); +Danger.args = { + badgeType: "danger", +}; + +export const Warning = Template.bind({}); +Warning.args = { + badgeType: "warning", +}; + +export const Info = Template.bind({}); +Info.args = { + badgeType: "info", +}; diff --git a/libs/components/src/badge/index.ts b/libs/components/src/badge/index.ts new file mode 100644 index 0000000000..6af33a9db9 --- /dev/null +++ b/libs/components/src/badge/index.ts @@ -0,0 +1,2 @@ +export * from "./badge.directive"; +export * from "./badge.module"; diff --git a/libs/components/src/banner/banner.component.html b/libs/components/src/banner/banner.component.html new file mode 100644 index 0000000000..eaf91d1d8d --- /dev/null +++ b/libs/components/src/banner/banner.component.html @@ -0,0 +1,14 @@ +
+ + + + + +
diff --git a/libs/components/src/banner/banner.component.spec.ts b/libs/components/src/banner/banner.component.spec.ts new file mode 100644 index 0000000000..2cb7fdc15b --- /dev/null +++ b/libs/components/src/banner/banner.component.spec.ts @@ -0,0 +1,35 @@ +import { ComponentFixture, TestBed } from "@angular/core/testing"; + +import { BannerComponent } from "./banner.component"; + +describe("BannerComponent", () => { + let component: BannerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [BannerComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(BannerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it("should create with alert", () => { + expect(component.useAlertRole).toBe(true); + const el = fixture.nativeElement.children[0]; + expect(el.getAttribute("role")).toEqual("status"); + expect(el.getAttribute("aria-live")).toEqual("polite"); + }); + + it("useAlertRole=false", () => { + component.useAlertRole = false; + fixture.autoDetectChanges(); + + expect(component.useAlertRole).toBe(false); + const el = fixture.nativeElement.children[0]; + expect(el.getAttribute("role")).toBeNull(); + expect(el.getAttribute("aria-live")).toBeNull(); + }); +}); diff --git a/libs/components/src/banner/banner.component.ts b/libs/components/src/banner/banner.component.ts new file mode 100644 index 0000000000..7565ba3015 --- /dev/null +++ b/libs/components/src/banner/banner.component.ts @@ -0,0 +1,39 @@ +import { Component, Input, OnInit, Output, EventEmitter } from "@angular/core"; + +type BannerTypes = "premium" | "info" | "warning" | "danger"; + +const defaultIcon: Record = { + premium: "bwi-star", + info: "bwi-info-circle", + warning: "bwi-exclamation-triangle", + danger: "bwi-error", +}; + +@Component({ + selector: "bit-banner", + templateUrl: "./banner.component.html", +}) +export class BannerComponent implements OnInit { + @Input("bannerType") bannerType: BannerTypes = "info"; + @Input() icon: string; + @Input() useAlertRole = true; + + @Output() onClose = new EventEmitter(); + + ngOnInit(): void { + this.icon ??= defaultIcon[this.bannerType]; + } + + get bannerClass() { + switch (this.bannerType) { + case "danger": + return "tw-bg-danger-500"; + case "info": + return "tw-bg-info-500"; + case "premium": + return "tw-bg-success-500"; + case "warning": + return "tw-bg-warning-500"; + } + } +} diff --git a/libs/components/src/banner/banner.module.ts b/libs/components/src/banner/banner.module.ts new file mode 100644 index 0000000000..df8c8f29b3 --- /dev/null +++ b/libs/components/src/banner/banner.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; + +import { BannerComponent } from "./banner.component"; + +@NgModule({ + imports: [CommonModule], + exports: [BannerComponent], + declarations: [BannerComponent], +}) +export class BannerModule {} diff --git a/libs/components/src/banner/banner.stories.ts b/libs/components/src/banner/banner.stories.ts new file mode 100644 index 0000000000..88594df3f1 --- /dev/null +++ b/libs/components/src/banner/banner.stories.ts @@ -0,0 +1,38 @@ +import { Meta, Story } from "@storybook/angular"; + +import { BannerComponent } from "./banner.component"; + +export default { + title: "Jslib/Banner", + component: BannerComponent, + args: { + bannerType: "warning", + }, +} as Meta; + +const Template: Story = (args: BannerComponent) => ({ + props: args, + template: ` + Content Really Long Text Lorem Ipsum Ipsum Ipsum + `, +}); + +export const Premium = Template.bind({}); +Premium.args = { + bannerType: "premium", +}; + +export const Info = Template.bind({}); +Info.args = { + bannerType: "info", +}; + +export const Warning = Template.bind({}); +Warning.args = { + bannerType: "warning", +}; + +export const Danger = Template.bind({}); +Danger.args = { + bannerType: "danger", +}; diff --git a/libs/components/src/banner/index.ts b/libs/components/src/banner/index.ts new file mode 100644 index 0000000000..f96f4f8302 --- /dev/null +++ b/libs/components/src/banner/index.ts @@ -0,0 +1,2 @@ +export * from "./banner.component"; +export * from "./banner.module"; diff --git a/libs/components/src/button/button.directive.spec.ts b/libs/components/src/button/button.directive.spec.ts new file mode 100644 index 0000000000..a7c3024e48 --- /dev/null +++ b/libs/components/src/button/button.directive.spec.ts @@ -0,0 +1,75 @@ +import { Component, DebugElement } from "@angular/core"; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; +import { By } from "@angular/platform-browser"; + +import { ButtonModule } from "./index"; + +describe("Button", () => { + let fixture: ComponentFixture; + let testAppComponent: TestApp; + let buttonDebugElement: DebugElement; + let linkDebugElement: DebugElement; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ButtonModule], + declarations: [TestApp], + }); + + TestBed.compileComponents(); + fixture = TestBed.createComponent(TestApp); + testAppComponent = fixture.debugElement.componentInstance; + buttonDebugElement = fixture.debugElement.query(By.css("button")); + linkDebugElement = fixture.debugElement.query(By.css("a")); + })); + + it("should apply classes based on type", () => { + testAppComponent.buttonType = "primary"; + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.classList.contains("tw-bg-primary-500")).toBe(true); + expect(linkDebugElement.nativeElement.classList.contains("tw-bg-primary-500")).toBe(true); + + testAppComponent.buttonType = "secondary"; + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); + expect(linkDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); + + testAppComponent.buttonType = "danger"; + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.classList.contains("tw-border-danger-500")).toBe(true); + expect(linkDebugElement.nativeElement.classList.contains("tw-border-danger-500")).toBe(true); + + testAppComponent.buttonType = null; + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); + expect(linkDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true); + }); + + it("should apply block when true and inline-block when false", () => { + testAppComponent.block = true; + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(true); + expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(true); + expect(buttonDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(false); + expect(linkDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(false); + + testAppComponent.block = false; + fixture.detectChanges(); + expect(buttonDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(true); + expect(linkDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(true); + expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(false); + expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(false); + }); +}); + +@Component({ + selector: "test-app", + template: ` + + Link + `, +}) +class TestApp { + buttonType: string; + block: boolean; +} diff --git a/libs/components/src/button/button.directive.ts b/libs/components/src/button/button.directive.ts new file mode 100644 index 0000000000..c4a4d15898 --- /dev/null +++ b/libs/components/src/button/button.directive.ts @@ -0,0 +1,72 @@ +import { Input, HostBinding, Directive } from "@angular/core"; + +export type ButtonTypes = "primary" | "secondary" | "danger"; + +const buttonStyles: Record = { + primary: [ + "tw-border-primary-500", + "tw-bg-primary-500", + "!tw-text-contrast", + "hover:tw-bg-primary-700", + "hover:tw-border-primary-700", + "focus:tw-bg-primary-700", + "focus:tw-border-primary-700", + ], + secondary: [ + "tw-bg-transparent", + "tw-border-text-muted", + "!tw-text-muted", + "hover:tw-bg-secondary-500", + "hover:tw-border-secondary-500", + "hover:!tw-text-contrast", + "focus:tw-bg-secondary-500", + "focus:tw-border-secondary-500", + "focus:!tw-text-contrast", + ], + danger: [ + "tw-bg-transparent", + "tw-border-danger-500", + "!tw-text-danger", + "hover:tw-bg-danger-500", + "hover:tw-border-danger-500", + "hover:!tw-text-contrast", + "focus:tw-bg-danger-500", + "focus:tw-border-danger-500", + "focus:!tw-text-contrast", + ], +}; + +@Directive({ + selector: "button[bitButton], a[bitButton]", +}) +export class ButtonDirective { + @HostBinding("class") get classList() { + return [ + "tw-font-semibold", + "tw-py-1.5", + "tw-px-3", + "tw-rounded", + "tw-transition", + "tw-border", + "tw-border-solid", + "tw-text-center", + "hover:tw-no-underline", + "disabled:tw-bg-secondary-100", + "disabled:tw-border-secondary-100", + "disabled:!tw-text-main", + "focus:tw-outline-none", + "focus:tw-ring", + "focus:tw-ring-offset-2", + "focus:tw-ring-primary-700", + "focus:tw-z-10", + ] + .concat(this.block ? ["tw-w-full", "tw-block"] : ["tw-inline-block"]) + .concat(buttonStyles[this.buttonType] ?? []); + } + + @Input() + buttonType: ButtonTypes = "secondary"; + + @Input() + block = false; +} diff --git a/libs/components/src/button/button.module.ts b/libs/components/src/button/button.module.ts new file mode 100644 index 0000000000..c9c3822abf --- /dev/null +++ b/libs/components/src/button/button.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; + +import { ButtonDirective } from "./button.directive"; + +@NgModule({ + imports: [CommonModule], + exports: [ButtonDirective], + declarations: [ButtonDirective], +}) +export class ButtonModule {} diff --git a/libs/components/src/button/button.stories.ts b/libs/components/src/button/button.stories.ts new file mode 100644 index 0000000000..fe4e23eede --- /dev/null +++ b/libs/components/src/button/button.stories.ts @@ -0,0 +1,54 @@ +import { Meta, Story } from "@storybook/angular"; + +import { ButtonDirective } from "./button.directive"; + +export default { + title: "Jslib/Button", + component: ButtonDirective, + args: { + buttonType: "primary", + }, + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/file/f32LSg3jaegICkMu7rPARm/Tailwind-Component-Library-Update?node-id=1881%3A16733", + }, + }, +} as Meta; + +const Template: Story = (args: ButtonDirective) => ({ + props: args, + template: ` + + Link + `, +}); + +export const Primary = Template.bind({}); +Primary.args = { + buttonType: "primary", +}; + +export const Secondary = Template.bind({}); +Secondary.args = { + buttonType: "secondary", +}; + +export const Danger = Template.bind({}); +Danger.args = { + buttonType: "danger", +}; + +const DisabledTemplate: Story = (args) => ({ + props: args, + template: ` + + + + `, +}); + +export const Disabled = DisabledTemplate.bind({}); +Disabled.args = { + size: "small", +}; diff --git a/libs/components/src/button/index.ts b/libs/components/src/button/index.ts new file mode 100644 index 0000000000..1bdd62ddbc --- /dev/null +++ b/libs/components/src/button/index.ts @@ -0,0 +1,2 @@ +export * from "./button.directive"; +export * from "./button.module"; diff --git a/libs/components/src/callout/callout.component.html b/libs/components/src/callout/callout.component.html new file mode 100644 index 0000000000..8e84612381 --- /dev/null +++ b/libs/components/src/callout/callout.component.html @@ -0,0 +1,14 @@ +
+

+ + {{ title }} +

+ +
diff --git a/libs/components/src/callout/callout.component.spec.ts b/libs/components/src/callout/callout.component.spec.ts new file mode 100644 index 0000000000..987d2e9669 --- /dev/null +++ b/libs/components/src/callout/callout.component.spec.ts @@ -0,0 +1,64 @@ +import { ComponentFixture, TestBed } from "@angular/core/testing"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { I18nMockService } from "../utils/i18n-mock.service"; + +import { CalloutComponent } from "."; + +describe("Callout", () => { + let component: CalloutComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [CalloutComponent], + providers: [ + { + provide: I18nService, + useFactory: () => + new I18nMockService({ + warning: "Warning", + error: "Error", + }), + }, + ], + }); + fixture = TestBed.createComponent(CalloutComponent); + component = fixture.componentInstance; + }); + + describe("default state", () => { + it("success", () => { + component.type = "success"; + fixture.detectChanges(); + expect(component.title).toBeUndefined(); + expect(component.icon).toBe("bwi-check"); + expect(component.headerClass).toBe("!tw-text-success"); + }); + + it("info", () => { + component.type = "info"; + fixture.detectChanges(); + expect(component.title).toBeUndefined(); + expect(component.icon).toBe("bwi-info-circle"); + expect(component.headerClass).toBe("!tw-text-info"); + }); + + it("warning", () => { + component.type = "warning"; + fixture.detectChanges(); + expect(component.title).toBe("Warning"); + expect(component.icon).toBe("bwi-exclamation-triangle"); + expect(component.headerClass).toBe("!tw-text-warning"); + }); + + it("danger", () => { + component.type = "danger"; + fixture.detectChanges(); + expect(component.title).toBe("Error"); + expect(component.icon).toBe("bwi-error"); + expect(component.headerClass).toBe("!tw-text-danger"); + }); + }); +}); diff --git a/libs/components/src/callout/callout.component.ts b/libs/components/src/callout/callout.component.ts new file mode 100644 index 0000000000..e7f5c51c0e --- /dev/null +++ b/libs/components/src/callout/callout.component.ts @@ -0,0 +1,63 @@ +import { Component, Input, OnInit } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +type CalloutTypes = "success" | "info" | "warning" | "danger"; + +const defaultIcon: Record = { + success: "bwi-check", + info: "bwi-info-circle", + warning: "bwi-exclamation-triangle", + danger: "bwi-error", +}; + +const defaultI18n: Partial> = { + warning: "warning", + danger: "error", +}; + +@Component({ + selector: "bit-callout", + templateUrl: "callout.component.html", +}) +export class CalloutComponent implements OnInit { + @Input() type: CalloutTypes = "info"; + @Input() icon: string; + @Input() title: string; + @Input() useAlertRole = false; + + constructor(private i18nService: I18nService) {} + + ngOnInit() { + this.icon ??= defaultIcon[this.type]; + if (this.title == null && defaultI18n[this.type] != null) { + this.title = this.i18nService.t(defaultI18n[this.type]); + } + } + + get calloutClass() { + switch (this.type) { + case "danger": + return "tw-border-l-danger-500"; + case "info": + return "tw-border-l-info-500"; + case "success": + return "tw-border-l-success-500"; + case "warning": + return "tw-border-l-warning-500"; + } + } + + get headerClass() { + switch (this.type) { + case "danger": + return "!tw-text-danger"; + case "info": + return "!tw-text-info"; + case "success": + return "!tw-text-success"; + case "warning": + return "!tw-text-warning"; + } + } +} diff --git a/libs/components/src/callout/callout.module.ts b/libs/components/src/callout/callout.module.ts new file mode 100644 index 0000000000..fac89dfbcf --- /dev/null +++ b/libs/components/src/callout/callout.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; + +import { CalloutComponent } from "./callout.component"; + +@NgModule({ + imports: [CommonModule], + exports: [CalloutComponent], + declarations: [CalloutComponent], +}) +export class CalloutModule {} diff --git a/libs/components/src/callout/callout.stories.ts b/libs/components/src/callout/callout.stories.ts new file mode 100644 index 0000000000..d2cb0f6962 --- /dev/null +++ b/libs/components/src/callout/callout.stories.ts @@ -0,0 +1,65 @@ +import { Meta, moduleMetadata, Story } from "@storybook/angular"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { I18nMockService } from "../utils/i18n-mock.service"; + +import { CalloutComponent } from "./callout.component"; + +export default { + title: "Jslib/Callout", + component: CalloutComponent, + decorators: [ + moduleMetadata({ + providers: [ + { + provide: I18nService, + useFactory: () => { + return new I18nMockService({ + warning: "Warning", + error: "Error", + }); + }, + }, + ], + }), + ], + args: { + type: "warning", + }, + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/file/f32LSg3jaegICkMu7rPARm/Tailwind-Component-Library-Update?node-id=1881%3A17484", + }, + }, +} as Meta; + +const Template: Story = (args: CalloutComponent) => ({ + props: args, + template: ` + Content + `, +}); + +export const Success = Template.bind({}); +Success.args = { + type: "success", + title: "Success", +}; + +export const Info = Template.bind({}); +Info.args = { + type: "info", + title: "Info", +}; + +export const Warning = Template.bind({}); +Warning.args = { + type: "warning", +}; + +export const Danger = Template.bind({}); +Danger.args = { + type: "danger", +}; diff --git a/libs/components/src/callout/index.ts b/libs/components/src/callout/index.ts new file mode 100644 index 0000000000..b3201946a3 --- /dev/null +++ b/libs/components/src/callout/index.ts @@ -0,0 +1,2 @@ +export * from "./callout.module"; +export * from "./callout.component"; diff --git a/libs/components/src/favicon.ico b/libs/components/src/favicon.ico new file mode 100644 index 0000000000..997406ad22 Binary files /dev/null and b/libs/components/src/favicon.ico differ diff --git a/libs/components/src/form-field/error-summary.component.ts b/libs/components/src/form-field/error-summary.component.ts new file mode 100644 index 0000000000..fd359cc153 --- /dev/null +++ b/libs/components/src/form-field/error-summary.component.ts @@ -0,0 +1,39 @@ +import { Component, Input } from "@angular/core"; +import { AbstractControl, FormGroup } from "@angular/forms"; + +@Component({ + selector: "bit-error-summary", + template: ` + {{ "fieldsNeedAttention" | i18n: errorString }} + `, + host: { + class: "tw-block tw-text-danger tw-mt-2", + "aria-live": "assertive", + }, +}) +export class BitErrorSummary { + @Input() + formGroup: FormGroup; + + get errorCount(): number { + return this.getErrorCount(this.formGroup); + } + + get errorString() { + return this.errorCount.toString(); + } + + private getErrorCount(form: FormGroup): number { + return Object.values(form.controls).reduce((acc: number, control: AbstractControl) => { + if (control instanceof FormGroup) { + return acc + this.getErrorCount(control); + } + + if (control.errors == null) { + return acc; + } + + return acc + Object.keys(control.errors).length; + }, 0); + } +} diff --git a/libs/components/src/form-field/error-summary.stories.ts b/libs/components/src/form-field/error-summary.stories.ts new file mode 100644 index 0000000000..1bd866e589 --- /dev/null +++ b/libs/components/src/form-field/error-summary.stories.ts @@ -0,0 +1,79 @@ +import { FormBuilder, FormsModule, ReactiveFormsModule, Validators } from "@angular/forms"; +import { Meta, moduleMetadata, Story } from "@storybook/angular"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { InputModule } from "src/input/input.module"; +import { I18nMockService } from "src/utils/i18n-mock.service"; + +import { ButtonModule } from "../button"; + +import { BitFormFieldComponent } from "./form-field.component"; +import { FormFieldModule } from "./form-field.module"; + +export default { + title: "Jslib/Form Error Summary", + component: BitFormFieldComponent, + decorators: [ + moduleMetadata({ + imports: [FormsModule, ReactiveFormsModule, FormFieldModule, InputModule, ButtonModule], + providers: [ + { + provide: I18nService, + useFactory: () => { + return new I18nMockService({ + required: "required", + inputRequired: "Input is required.", + inputEmail: "Input is not an email-address.", + fieldsNeedAttention: "$COUNT$ field(s) above need your attention.", + }); + }, + }, + ], + }), + ], + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/file/f32LSg3jaegICkMu7rPARm/Tailwind-Component-Library-Update?node-id=1881%3A17689", + }, + }, +} as Meta; + +const fb = new FormBuilder(); + +const formObj = fb.group({ + name: ["", [Validators.required]], + email: ["", [Validators.required, Validators.email]], +}); + +function submit() { + formObj.markAllAsTouched(); +} + +const Template: Story = (args: BitFormFieldComponent) => ({ + props: { + formObj: formObj, + submit: submit, + ...args, + }, + template: ` + + + Name + + + + + Email + + + + + + + `, +}); + +export const Default = Template.bind({}); +Default.props = {}; diff --git a/libs/components/src/form-field/error.component.ts b/libs/components/src/form-field/error.component.ts new file mode 100644 index 0000000000..72846307ac --- /dev/null +++ b/libs/components/src/form-field/error.component.ts @@ -0,0 +1,38 @@ +import { Component, HostBinding, Input } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +// Increments for each instance of this component +let nextId = 0; + +@Component({ + selector: "bit-error", + template: ` {{ displayError }}`, + host: { + class: "tw-block tw-mt-1 tw-text-danger", + "aria-live": "assertive", + }, +}) +export class BitErrorComponent { + @HostBinding() id = `bit-error-${nextId++}`; + + @Input() error: [string, any]; + + constructor(private i18nService: I18nService) {} + + get displayError() { + switch (this.error[0]) { + case "required": + return this.i18nService.t("inputRequired"); + case "email": + return this.i18nService.t("inputEmail"); + default: + // Attempt to show a custom error message. + if (this.error[1]?.message) { + return this.error[1]?.message; + } + + return this.error; + } + } +} diff --git a/libs/components/src/form-field/form-field.component.html b/libs/components/src/form-field/form-field.component.html new file mode 100644 index 0000000000..00c844c336 --- /dev/null +++ b/libs/components/src/form-field/form-field.component.html @@ -0,0 +1,17 @@ + +
+
+ +
+ +
+ +
+
+ + + + diff --git a/libs/components/src/form-field/form-field.component.ts b/libs/components/src/form-field/form-field.component.ts new file mode 100644 index 0000000000..29c4ba369f --- /dev/null +++ b/libs/components/src/form-field/form-field.component.ts @@ -0,0 +1,53 @@ +import { + AfterContentChecked, + Component, + ContentChild, + ContentChildren, + QueryList, + ViewChild, +} from "@angular/core"; + +import { BitInputDirective } from "../input/input.directive"; + +import { BitErrorComponent } from "./error.component"; +import { BitHintComponent } from "./hint.component"; +import { BitPrefixDirective } from "./prefix.directive"; +import { BitSuffixDirective } from "./suffix.directive"; + +@Component({ + selector: "bit-form-field", + templateUrl: "./form-field.component.html", + host: { + class: "tw-mb-6 tw-block", + }, +}) +export class BitFormFieldComponent implements AfterContentChecked { + @ContentChild(BitInputDirective) input: BitInputDirective; + @ContentChild(BitHintComponent) hint: BitHintComponent; + + @ViewChild(BitErrorComponent) error: BitErrorComponent; + + @ContentChildren(BitPrefixDirective) prefixChildren: QueryList; + @ContentChildren(BitSuffixDirective) suffixChildren: QueryList; + + ngAfterContentChecked(): void { + this.input.hasPrefix = this.prefixChildren.length > 0; + this.input.hasSuffix = this.suffixChildren.length > 0; + + this.prefixChildren.forEach((prefix) => { + prefix.first = prefix == this.prefixChildren.first; + }); + + this.suffixChildren.forEach((suffix) => { + suffix.last = suffix == this.suffixChildren.last; + }); + + if (this.error) { + this.input.ariaDescribedBy = this.error.id; + } else if (this.hint) { + this.input.ariaDescribedBy = this.hint.id; + } else { + this.input.ariaDescribedBy = undefined; + } + } +} diff --git a/libs/components/src/form-field/form-field.module.ts b/libs/components/src/form-field/form-field.module.ts new file mode 100644 index 0000000000..323d5a5269 --- /dev/null +++ b/libs/components/src/form-field/form-field.module.ts @@ -0,0 +1,54 @@ +import { CommonModule } from "@angular/common"; +import { NgModule, Pipe, PipeTransform } from "@angular/core"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { BitInputDirective } from "../input/input.directive"; +import { InputModule } from "../input/input.module"; + +import { BitErrorSummary } from "./error-summary.component"; +import { BitErrorComponent } from "./error.component"; +import { BitFormFieldComponent } from "./form-field.component"; +import { BitHintComponent } from "./hint.component"; +import { BitLabel } from "./label.directive"; +import { BitPrefixDirective } from "./prefix.directive"; +import { BitSuffixDirective } from "./suffix.directive"; + +/** + * Temporarily duplicate this pipe + */ +@Pipe({ + name: "i18n", +}) +export class I18nPipe implements PipeTransform { + constructor(private i18nService: I18nService) {} + + transform(id: string, p1?: string, p2?: string, p3?: string): string { + return this.i18nService.t(id, p1, p2, p3); + } +} + +@NgModule({ + imports: [CommonModule, InputModule], + exports: [ + BitErrorComponent, + BitErrorSummary, + BitFormFieldComponent, + BitHintComponent, + BitInputDirective, + BitLabel, + BitPrefixDirective, + BitSuffixDirective, + ], + declarations: [ + BitErrorComponent, + BitErrorSummary, + BitFormFieldComponent, + BitHintComponent, + BitLabel, + BitPrefixDirective, + BitSuffixDirective, + I18nPipe, + ], +}) +export class FormFieldModule {} diff --git a/libs/components/src/form-field/form-field.stories.ts b/libs/components/src/form-field/form-field.stories.ts new file mode 100644 index 0000000000..ae4d9cf5dd --- /dev/null +++ b/libs/components/src/form-field/form-field.stories.ts @@ -0,0 +1,213 @@ +import { + AbstractControl, + FormBuilder, + FormsModule, + ReactiveFormsModule, + ValidationErrors, + ValidatorFn, + Validators, +} from "@angular/forms"; +import { Meta, moduleMetadata, Story } from "@storybook/angular"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { InputModule } from "src/input/input.module"; +import { I18nMockService } from "src/utils/i18n-mock.service"; + +import { ButtonModule } from "../button"; + +import { BitFormFieldComponent } from "./form-field.component"; +import { FormFieldModule } from "./form-field.module"; + +export default { + title: "Jslib/Form Field", + component: BitFormFieldComponent, + decorators: [ + moduleMetadata({ + imports: [FormsModule, ReactiveFormsModule, FormFieldModule, InputModule, ButtonModule], + providers: [ + { + provide: I18nService, + useFactory: () => { + return new I18nMockService({ + required: "required", + inputRequired: "Input is required.", + inputEmail: "Input is not an email-address.", + }); + }, + }, + ], + }), + ], + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/file/f32LSg3jaegICkMu7rPARm/Tailwind-Component-Library-Update?node-id=1881%3A17689", + }, + }, +} as Meta; + +const fb = new FormBuilder(); +const formObj = fb.group({ + test: [""], + required: ["", [Validators.required]], +}); + +const defaultFormObj = fb.group({ + name: ["", [Validators.required]], + email: ["", [Validators.required, Validators.email, forbiddenNameValidator(/bit/i)]], +}); + +// Custom error message, `message` is shown as the error message +function forbiddenNameValidator(nameRe: RegExp): ValidatorFn { + return (control: AbstractControl): ValidationErrors | null => { + const forbidden = nameRe.test(control.value); + return forbidden ? { forbiddenName: { message: "forbiddenName" } } : null; + }; +} + +function submit() { + defaultFormObj.markAllAsTouched(); +} + +const Template: Story = (args: BitFormFieldComponent) => ({ + props: { + formObj: defaultFormObj, + submit: submit, + ...args, + }, + template: ` +
+ + Name + + + + + Email + + + + +
+ `, +}); + +export const Default = Template.bind({}); +Default.props = {}; + +const RequiredTemplate: Story = (args: BitFormFieldComponent) => ({ + props: { + formObj: formObj, + ...args, + }, + template: ` + + Label + + + + + FormControl + + + `, +}); + +export const Required = RequiredTemplate.bind({}); +Required.props = {}; + +const HintTemplate: Story = (args: BitFormFieldComponent) => ({ + props: { + formObj: formObj, + ...args, + }, + template: ` + + FormControl + + Long hint text + + `, +}); + +export const Hint = HintTemplate.bind({}); +Required.props = {}; + +const DisabledTemplate: Story = (args: BitFormFieldComponent) => ({ + props: args, + template: ` + + Label + + + `, +}); + +export const Disabled = DisabledTemplate.bind({}); +Disabled.args = {}; + +const GroupTemplate: Story = (args: BitFormFieldComponent) => ({ + props: args, + template: ` + + Label + + $ + USD + + `, +}); + +export const InputGroup = GroupTemplate.bind({}); +InputGroup.args = {}; + +const ButtonGroupTemplate: Story = (args: BitFormFieldComponent) => ({ + props: args, + template: ` + + Label + + + + + + + `, +}); + +export const ButtonInputGroup = ButtonGroupTemplate.bind({}); +ButtonInputGroup.args = {}; + +const SelectTemplate: Story = (args: BitFormFieldComponent) => ({ + props: args, + template: ` + + Label + + + `, +}); + +export const Select = SelectTemplate.bind({}); +Select.args = {}; + +const TextareaTemplate: Story = (args: BitFormFieldComponent) => ({ + props: args, + template: ` + + Textarea + + + `, +}); + +export const Textarea = TextareaTemplate.bind({}); +Textarea.args = {}; diff --git a/libs/components/src/form-field/hint.component.ts b/libs/components/src/form-field/hint.component.ts new file mode 100644 index 0000000000..59d01a89da --- /dev/null +++ b/libs/components/src/form-field/hint.component.ts @@ -0,0 +1,14 @@ +import { Directive, HostBinding } from "@angular/core"; + +// Increments for each instance of this component +let nextId = 0; + +@Directive({ + selector: "bit-hint", + host: { + class: "tw-text-muted tw-inline-block tw-mt-1", + }, +}) +export class BitHintComponent { + @HostBinding() id = `bit-hint-${nextId++}`; +} diff --git a/libs/components/src/form-field/index.ts b/libs/components/src/form-field/index.ts new file mode 100644 index 0000000000..f6077fcc8e --- /dev/null +++ b/libs/components/src/form-field/index.ts @@ -0,0 +1,2 @@ +export * from "./form-field.module"; +export * from "./form-field.component"; diff --git a/libs/components/src/form-field/label.directive.ts b/libs/components/src/form-field/label.directive.ts new file mode 100644 index 0000000000..a3a38329d6 --- /dev/null +++ b/libs/components/src/form-field/label.directive.ts @@ -0,0 +1,6 @@ +import { Directive } from "@angular/core"; + +@Directive({ + selector: "bit-label", +}) +export class BitLabel {} diff --git a/libs/components/src/form-field/prefix.directive.ts b/libs/components/src/form-field/prefix.directive.ts new file mode 100644 index 0000000000..28ae6bd970 --- /dev/null +++ b/libs/components/src/form-field/prefix.directive.ts @@ -0,0 +1,28 @@ +import { Directive, HostBinding, Input } from "@angular/core"; + +export const PrefixClasses = [ + "tw-block", + "tw-px-3", + "tw-py-1.5", + "tw-bg-background-alt", + "tw-border", + "tw-border-solid", + "tw-border-secondary-500", + "tw-text-muted", + "tw-rounded", +]; + +@Directive({ + selector: "[bitPrefix]", +}) +export class BitPrefixDirective { + @HostBinding("class") @Input() get classList() { + return PrefixClasses.concat([ + "tw-border-r-0", + "tw-rounded-r-none", + !this.first ? "tw-rounded-l-none" : "", + ]).filter((c) => c != ""); + } + + @Input() first = false; +} diff --git a/libs/components/src/form-field/suffix.directive.ts b/libs/components/src/form-field/suffix.directive.ts new file mode 100644 index 0000000000..c644e80cb2 --- /dev/null +++ b/libs/components/src/form-field/suffix.directive.ts @@ -0,0 +1,18 @@ +import { Directive, HostBinding, Input } from "@angular/core"; + +import { PrefixClasses } from "./prefix.directive"; + +@Directive({ + selector: "[bitSuffix]", +}) +export class BitSuffixDirective { + @HostBinding("class") @Input() get classList() { + return PrefixClasses.concat([ + "tw-rounded-l-none", + "tw-border-l-0", + !this.last ? "tw-rounded-r-none" : "", + ]).filter((c) => c != ""); + } + + @Input() last = false; +} diff --git a/libs/components/src/index.html b/libs/components/src/index.html new file mode 100644 index 0000000000..777f720cd4 --- /dev/null +++ b/libs/components/src/index.html @@ -0,0 +1,13 @@ + + + + + Components + + + + + + + + diff --git a/libs/components/src/index.ts b/libs/components/src/index.ts new file mode 100644 index 0000000000..9a15e43815 --- /dev/null +++ b/libs/components/src/index.ts @@ -0,0 +1,6 @@ +export * from "./badge"; +export * from "./banner"; +export * from "./button"; +export * from "./callout"; +export * from "./form-field"; +export * from "./menu"; diff --git a/libs/components/src/input/input.directive.ts b/libs/components/src/input/input.directive.ts new file mode 100644 index 0000000000..f75e3da61c --- /dev/null +++ b/libs/components/src/input/input.directive.ts @@ -0,0 +1,65 @@ +import { Directive, HostBinding, Input, Optional, Self } from "@angular/core"; +import { NgControl, Validators } from "@angular/forms"; + +// Increments for each instance of this component +let nextId = 0; + +@Directive({ + selector: "input[bitInput], select[bitInput], textarea[bitInput]", +}) +export class BitInputDirective { + @HostBinding("class") @Input() get classList() { + return [ + "tw-block", + "tw-w-full", + "tw-px-3", + "tw-py-1.5", + "tw-bg-background-alt", + "tw-border", + "tw-border-solid", + "tw-rounded", + "tw-text-main", + "tw-placeholder-text-muted", + "focus:tw-outline-none", + "focus:tw-border-primary-700", + "focus:tw-ring-1", + "focus:tw-ring-primary-700", + "focus:tw-z-10", + "disabled:tw-bg-secondary-100", + this.hasPrefix ? "tw-rounded-l-none" : "", + this.hasSuffix ? "tw-rounded-r-none" : "", + this.hasError ? "tw-border-danger-500" : "tw-border-secondary-500", + ].filter((s) => s != ""); + } + + @HostBinding() id = `bit-input-${nextId++}`; + + @HostBinding("attr.aria-describedby") ariaDescribedBy: string; + + @HostBinding("attr.aria-invalid") get ariaInvalid() { + return this.hasError ? true : undefined; + } + + @HostBinding() + @Input() + get required() { + return this._required ?? this.ngControl?.control?.hasValidator(Validators.required) ?? false; + } + set required(value: any) { + this._required = value != null && value !== false; + } + private _required: boolean; + + @Input() hasPrefix = false; + @Input() hasSuffix = false; + + get hasError() { + return this.ngControl?.status === "INVALID" && this.ngControl?.touched; + } + + get error(): [string, any] { + const key = Object.keys(this.ngControl.errors)[0]; + return [key, this.ngControl.errors[key]]; + } + constructor(@Optional() @Self() private ngControl: NgControl) {} +} diff --git a/libs/components/src/input/input.module.ts b/libs/components/src/input/input.module.ts new file mode 100644 index 0000000000..cfc49cefb7 --- /dev/null +++ b/libs/components/src/input/input.module.ts @@ -0,0 +1,11 @@ +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; + +import { BitInputDirective } from "./input.directive"; + +@NgModule({ + imports: [CommonModule], + declarations: [BitInputDirective], + exports: [BitInputDirective], +}) +export class InputModule {} diff --git a/libs/components/src/main.ts b/libs/components/src/main.ts new file mode 100644 index 0000000000..1dd4f8adc6 --- /dev/null +++ b/libs/components/src/main.ts @@ -0,0 +1,7 @@ +import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; + +import { AppModule } from "./app/app.module"; + +platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.error(err)); // eslint-disable-line diff --git a/libs/components/src/menu/index.ts b/libs/components/src/menu/index.ts new file mode 100644 index 0000000000..52c48d2fb8 --- /dev/null +++ b/libs/components/src/menu/index.ts @@ -0,0 +1,5 @@ +export * from "./menu.module"; +export * from "./menu.component"; +export * from "./menu-trigger-for.directive"; +export * from "./menu-item.directive"; +export * from "./menu-divider.component"; diff --git a/libs/components/src/menu/menu-divider.component.html b/libs/components/src/menu/menu-divider.component.html new file mode 100644 index 0000000000..7cc020ef50 --- /dev/null +++ b/libs/components/src/menu/menu-divider.component.html @@ -0,0 +1,4 @@ + diff --git a/libs/components/src/menu/menu-divider.component.ts b/libs/components/src/menu/menu-divider.component.ts new file mode 100644 index 0000000000..194506ee50 --- /dev/null +++ b/libs/components/src/menu/menu-divider.component.ts @@ -0,0 +1,7 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "bit-menu-divider", + templateUrl: "./menu-divider.component.html", +}) +export class MenuDividerComponent {} diff --git a/libs/components/src/menu/menu-item.directive.ts b/libs/components/src/menu/menu-item.directive.ts new file mode 100644 index 0000000000..2a50dd366f --- /dev/null +++ b/libs/components/src/menu/menu-item.directive.ts @@ -0,0 +1,36 @@ +import { FocusableOption } from "@angular/cdk/a11y"; +import { Directive, ElementRef, HostBinding } from "@angular/core"; + +@Directive({ + selector: "[bitMenuItem]", +}) +export class MenuItemDirective implements FocusableOption { + @HostBinding("class") classList = [ + "tw-block", + "tw-py-1", + "tw-px-4", + "!tw-text-main", + "!tw-no-underline", + "tw-cursor-pointer", + "tw-border-none", + "tw-bg-background", + "tw-text-left", + "hover:tw-bg-secondary-100", + "focus:tw-bg-secondary-100", + "focus:tw-z-50", + "focus:tw-outline-none", + "focus:tw-ring", + "focus:tw-ring-offset-2", + "focus:tw-ring-primary-700", + "active:!tw-ring-0", + "active:!tw-ring-offset-0", + ]; + @HostBinding("attr.role") role = "menuitem"; + @HostBinding("tabIndex") tabIndex = "-1"; + + constructor(private elementRef: ElementRef) {} + + focus() { + this.elementRef.nativeElement.focus(); + } +} diff --git a/libs/components/src/menu/menu-trigger-for.directive.ts b/libs/components/src/menu/menu-trigger-for.directive.ts new file mode 100644 index 0000000000..059e6f812e --- /dev/null +++ b/libs/components/src/menu/menu-trigger-for.directive.ts @@ -0,0 +1,119 @@ +import { Overlay, OverlayConfig, OverlayRef } from "@angular/cdk/overlay"; +import { TemplatePortal } from "@angular/cdk/portal"; +import { + Directive, + ElementRef, + HostBinding, + HostListener, + Input, + OnDestroy, + ViewContainerRef, +} from "@angular/core"; +import { Observable, Subscription } from "rxjs"; +import { filter, mergeWith } from "rxjs/operators"; + +import { MenuComponent } from "./menu.component"; + +@Directive({ + selector: "[bitMenuTriggerFor]", +}) +export class MenuTriggerForDirective implements OnDestroy { + @HostBinding("attr.aria-expanded") isOpen = false; + @HostBinding("attr.aria-haspopup") hasPopup = "menu"; + @HostBinding("attr.role") role = "button"; + + @Input("bitMenuTriggerFor") menu: MenuComponent; + + private overlayRef: OverlayRef; + private defaultMenuConfig: OverlayConfig = { + panelClass: "bit-menu-panel", + hasBackdrop: true, + backdropClass: "cdk-overlay-transparent-backdrop", + scrollStrategy: this.overlay.scrollStrategies.reposition(), + positionStrategy: this.overlay + .position() + .flexibleConnectedTo(this.elementRef) + .withPositions([ + { + originX: "start", + originY: "bottom", + overlayX: "start", + overlayY: "top", + }, + { + originX: "end", + originY: "bottom", + overlayX: "end", + overlayY: "top", + }, + ]) + .withLockedPosition(true) + .withFlexibleDimensions(false) + .withPush(false), + }; + private closedEventsSub: Subscription; + private keyDownEventsSub: Subscription; + + constructor( + private elementRef: ElementRef, + private viewContainerRef: ViewContainerRef, + private overlay: Overlay + ) {} + + @HostListener("click") toggleMenu() { + this.isOpen ? this.destroyMenu() : this.openMenu(); + } + + ngOnDestroy() { + this.disposeAll(); + } + + private openMenu() { + if (this.menu == null) { + throw new Error("Cannot find bit-menu element"); + } + + this.isOpen = true; + this.overlayRef = this.overlay.create(this.defaultMenuConfig); + + const templatePortal = new TemplatePortal(this.menu.templateRef, this.viewContainerRef); + this.overlayRef.attach(templatePortal); + + this.closedEventsSub = this.getClosedEvents().subscribe((event: KeyboardEvent | undefined) => { + if (event?.key === "Tab") { + // Required to ensure tab order resumes correctly + this.elementRef.nativeElement.focus(); + } + this.destroyMenu(); + }); + this.keyDownEventsSub = this.overlayRef + .keydownEvents() + .subscribe((event: KeyboardEvent) => this.menu.keyManager.onKeydown(event)); + } + + private destroyMenu() { + if (this.overlayRef == null || !this.isOpen) { + return; + } + + this.isOpen = false; + this.disposeAll(); + } + + private getClosedEvents(): Observable { + const detachments = this.overlayRef.detachments(); + const escKey = this.overlayRef + .keydownEvents() + .pipe(filter((event: KeyboardEvent) => event.key === "Escape" || event.key === "Tab")); + const backdrop = this.overlayRef.backdropClick(); + const menuClosed = this.menu.closed; + + return detachments.pipe(mergeWith(escKey, backdrop, menuClosed)); + } + + private disposeAll() { + this.closedEventsSub?.unsubscribe(); + this.overlayRef?.dispose(); + this.keyDownEventsSub?.unsubscribe(); + } +} diff --git a/libs/components/src/menu/menu.component.html b/libs/components/src/menu/menu.component.html new file mode 100644 index 0000000000..8123c7be40 --- /dev/null +++ b/libs/components/src/menu/menu.component.html @@ -0,0 +1,9 @@ + + + diff --git a/libs/components/src/menu/menu.component.spec.ts b/libs/components/src/menu/menu.component.spec.ts new file mode 100644 index 0000000000..29f3a86069 --- /dev/null +++ b/libs/components/src/menu/menu.component.spec.ts @@ -0,0 +1,75 @@ +import { Component } from "@angular/core"; +import { ComponentFixture, TestBed, waitForAsync } from "@angular/core/testing"; +import { By } from "@angular/platform-browser"; + +import { MenuTriggerForDirective } from "./menu-trigger-for.directive"; + +import { MenuModule } from "./index"; + +describe("Menu", () => { + let fixture: ComponentFixture; + const getMenuTriggerDirective = () => { + const buttonDebugElement = fixture.debugElement.query(By.directive(MenuTriggerForDirective)); + return buttonDebugElement.injector.get(MenuTriggerForDirective); + }; + + // The overlay is created outside the root debugElement, so we need to query its parent + const getBitMenuPanel = () => document.querySelector(".bit-menu-panel"); + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [MenuModule], + declarations: [TestApp], + }); + + TestBed.compileComponents(); + + fixture = TestBed.createComponent(TestApp); + fixture.detectChanges(); + })); + + it("should open when the trigger is clicked", async () => { + const buttonDebugElement = fixture.debugElement.query(By.directive(MenuTriggerForDirective)); + (buttonDebugElement.nativeElement as HTMLButtonElement).click(); + + expect(getBitMenuPanel()).toBeTruthy(); + }); + + it("should close when the trigger is clicked", () => { + getMenuTriggerDirective().toggleMenu(); + + const buttonDebugElement = fixture.debugElement.query(By.directive(MenuTriggerForDirective)); + (buttonDebugElement.nativeElement as HTMLButtonElement).click(); + + expect(getBitMenuPanel()).toBeFalsy(); + }); + + it("should close when a menu item is clicked", () => { + getMenuTriggerDirective().toggleMenu(); + + (document.querySelector("#item1") as HTMLAnchorElement).click(); + + expect(getBitMenuPanel()).toBeFalsy(); + }); + + it("should close when the backdrop is clicked", () => { + getMenuTriggerDirective().toggleMenu(); + + (document.querySelector(".cdk-overlay-backdrop") as HTMLAnchorElement).click(); + + expect(getBitMenuPanel()).toBeFalsy(); + }); +}); + +@Component({ + selector: "test-app", + template: ` + + + + Item 1 + Item 2 + + `, +}) +class TestApp {} diff --git a/libs/components/src/menu/menu.component.ts b/libs/components/src/menu/menu.component.ts new file mode 100644 index 0000000000..72c614d2a8 --- /dev/null +++ b/libs/components/src/menu/menu.component.ts @@ -0,0 +1,30 @@ +import { FocusKeyManager } from "@angular/cdk/a11y"; +import { + Component, + Output, + TemplateRef, + ViewChild, + EventEmitter, + ContentChildren, + QueryList, + AfterContentInit, +} from "@angular/core"; + +import { MenuItemDirective } from "./menu-item.directive"; + +@Component({ + selector: "bit-menu", + templateUrl: "./menu.component.html", + exportAs: "menuComponent", +}) +export class MenuComponent implements AfterContentInit { + @ViewChild(TemplateRef) templateRef: TemplateRef; + @Output() closed = new EventEmitter(); + @ContentChildren(MenuItemDirective, { descendants: true }) + menuItems: QueryList; + keyManager: FocusKeyManager; + + ngAfterContentInit() { + this.keyManager = new FocusKeyManager(this.menuItems).withWrap(); + } +} diff --git a/libs/components/src/menu/menu.module.ts b/libs/components/src/menu/menu.module.ts new file mode 100644 index 0000000000..15ebcde5a9 --- /dev/null +++ b/libs/components/src/menu/menu.module.ts @@ -0,0 +1,15 @@ +import { OverlayModule } from "@angular/cdk/overlay"; +import { CommonModule } from "@angular/common"; +import { NgModule } from "@angular/core"; + +import { MenuDividerComponent } from "./menu-divider.component"; +import { MenuItemDirective } from "./menu-item.directive"; +import { MenuTriggerForDirective } from "./menu-trigger-for.directive"; +import { MenuComponent } from "./menu.component"; + +@NgModule({ + imports: [CommonModule, OverlayModule], + declarations: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent], + exports: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent], +}) +export class MenuModule {} diff --git a/libs/components/src/menu/menu.stories.ts b/libs/components/src/menu/menu.stories.ts new file mode 100644 index 0000000000..fa3c6e69cd --- /dev/null +++ b/libs/components/src/menu/menu.stories.ts @@ -0,0 +1,69 @@ +import { OverlayModule } from "@angular/cdk/overlay"; +import { Meta, moduleMetadata, Story } from "@storybook/angular"; + +import { ButtonModule } from "../button/button.module"; + +import { MenuDividerComponent } from "./menu-divider.component"; +import { MenuItemDirective } from "./menu-item.directive"; +import { MenuTriggerForDirective } from "./menu-trigger-for.directive"; +import { MenuComponent } from "./menu.component"; + +export default { + title: "Jslib/Menu", + component: MenuTriggerForDirective, + decorators: [ + moduleMetadata({ + declarations: [ + MenuTriggerForDirective, + MenuComponent, + MenuItemDirective, + MenuDividerComponent, + ], + imports: [OverlayModule, ButtonModule], + }), + ], + parameters: { + design: { + type: "figma", + url: "https://www.figma.com/file/f32LSg3jaegICkMu7rPARm/Tailwind-Component-Library-Update?node-id=1881%3A17952", + }, + }, +} as Meta; + +const Template: Story = (args: MenuTriggerForDirective) => ({ + props: args, + template: ` + + Anchor link + Another link + + + + + +
+
+ +
+
+ `, +}); + +const TemplateWithButton: Story = (args: MenuTriggerForDirective) => ({ + props: args, + template: ` +
+ +
+ + + Anchor link + Another link + + + + `, +}); + +export const OpenMenu = Template.bind({}); +export const ClosedMenu = TemplateWithButton.bind({}); diff --git a/libs/components/src/polyfills.ts b/libs/components/src/polyfills.ts new file mode 100644 index 0000000000..40a0e9f068 --- /dev/null +++ b/libs/components/src/polyfills.ts @@ -0,0 +1,52 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes recent versions of Safari, Chrome (including + * Opera), Edge on the desktop, and iOS and Chrome on mobile. + * + * Learn more in https://angular.io/guide/browser-support + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + * because those flags need to be set before `zone.js` being loaded, and webpack + * will put import in the top of bundle, so user need to create a separate file + * in this directory (for example: zone-flags.ts), and put the following flags + * into that file, and then add the following code before importing zone.js. + * import './zone-flags'; + * + * The flags allowed in zone-flags.ts are listed here. + * + * The following flags will work for all browsers. + * + * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + * + * (window as any).__Zone_enable_cross_context_check = true; + * + */ + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import "zone.js"; // Included with Angular CLI. + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/libs/components/src/stories/Introduction.stories.mdx b/libs/components/src/stories/Introduction.stories.mdx new file mode 100644 index 0000000000..7b175b415d --- /dev/null +++ b/libs/components/src/stories/Introduction.stories.mdx @@ -0,0 +1,128 @@ +import { Meta } from "@storybook/addon-docs"; + + + + + +# Bitwarden Component Library + +The Bitwarden Component Library is a collection of reusable low level components which empowers designers and +developers to work more efficiently. The primary goal is to ensure a consistent design and behavior across the +different clients and platforms. Currently the primary focus is the web based clients, namely _web_, _browser_ and +_desktop_. + +**Role out status:** we are currently in the process of transitioning the Web Vault to utilize the component library +and the other clients will follow once this work is completed. + +
Configure
+ + + +
Learn
+ + diff --git a/libs/components/src/stories/colors.stories.mdx b/libs/components/src/stories/colors.stories.mdx new file mode 100644 index 0000000000..a75418e457 --- /dev/null +++ b/libs/components/src/stories/colors.stories.mdx @@ -0,0 +1,86 @@ +import { Meta } from "@storybook/addon-docs"; + + + +export const Row = (name) => ( + + {name} + + +); + +export const Table = (args) => ( + + + + + + + + + {Row("background")} + {Row("background-alt")} + {Row("background-alt2")} + + + {Row("primary-300")} + {Row("primary-500")} + {Row("primary-700")} + + + {Row("secondary-100")} + {Row("secondary-300")} + {Row("secondary-500")} + {Row("secondary-700")} + + + {Row("success-500")} + {Row("success-700")} + + + {Row("danger-500")} + {Row("danger-700")} + + + {Row("warning-500")} + {Row("warning-700")} + + + {Row("info-500")} + {Row("info-700")} + + + {Row("text-main")} + {Row("text-muted")} + {Row("text-contrast")} + {Row("text-alt2")} + +
General usage
+); + + + +# Colors + +
+ +
+ diff --git a/libs/components/src/styles.css b/libs/components/src/styles.css new file mode 100644 index 0000000000..6714e5ddde --- /dev/null +++ b/libs/components/src/styles.css @@ -0,0 +1,11 @@ +/* You can add global styles to this file, and also import other style files */ + +@import "./tw-theme.css"; + +@tailwind base; +@tailwind components; +@tailwind utilities; + +body { + font-size: 14px; +} diff --git a/libs/components/src/styles.scss b/libs/components/src/styles.scss new file mode 100644 index 0000000000..401b801e0e --- /dev/null +++ b/libs/components/src/styles.scss @@ -0,0 +1,44 @@ +@import "../../angular/src/scss/webfonts.css"; +@import "./variables"; +@import "../../angular/src/scss/bwicons/styles/style.scss"; +@import "../../angular/src/scss/icons.scss"; + +@import "@angular/cdk/overlay-prebuilt.css"; + +@import "~bootstrap/scss/_functions"; +@import "~bootstrap/scss/_variables"; +@import "~bootstrap/scss/_mixins"; +@import "~bootstrap/scss/_root"; +@import "~bootstrap/scss/_reboot"; +@import "~bootstrap/scss/_type"; +@import "~bootstrap/scss/_images"; +@import "~bootstrap/scss/_code"; +@import "~bootstrap/scss/_grid"; +@import "~bootstrap/scss/_tables"; +@import "~bootstrap/scss/_forms"; +@import "~bootstrap/scss/_buttons"; +@import "~bootstrap/scss/_transitions"; +@import "~bootstrap/scss/_dropdown"; +@import "~bootstrap/scss/_button-group"; +@import "~bootstrap/scss/_input-group"; +@import "~bootstrap/scss/_custom-forms"; +@import "~bootstrap/scss/_nav"; +@import "~bootstrap/scss/_navbar"; +@import "~bootstrap/scss/_card"; +@import "~bootstrap/scss/_breadcrumb"; +@import "~bootstrap/scss/_pagination"; +@import "~bootstrap/scss/_badge"; +@import "~bootstrap/scss/_jumbotron"; +@import "~bootstrap/scss/_alert"; +@import "~bootstrap/scss/_progress"; +@import "~bootstrap/scss/_media"; +@import "~bootstrap/scss/_list-group"; +@import "~bootstrap/scss/_close"; +//@import "~bootstrap/scss/_toasts"; +@import "~bootstrap/scss/_modal"; +@import "~bootstrap/scss/_tooltip"; +@import "~bootstrap/scss/_popover"; +@import "~bootstrap/scss/_carousel"; +@import "~bootstrap/scss/_spinners"; +@import "~bootstrap/scss/_utilities"; +@import "~bootstrap/scss/_print"; diff --git a/libs/components/src/test.ts b/libs/components/src/test.ts new file mode 100644 index 0000000000..06061ec6f0 --- /dev/null +++ b/libs/components/src/test.ts @@ -0,0 +1,28 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files +// eslint-disable-next-line +import "zone.js/testing"; + +import { getTestBed } from "@angular/core/testing"; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from "@angular/platform-browser-dynamic/testing"; + +declare const require: { + context( + path: string, + deep?: boolean, + filter?: RegExp + ): { + (id: string): T; + keys(): string[]; + }; +}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); + +// Then we find all the tests. +const context = require.context("./", true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git a/libs/components/src/tw-theme.css b/libs/components/src/tw-theme.css new file mode 100644 index 0000000000..d41b331d4a --- /dev/null +++ b/libs/components/src/tw-theme.css @@ -0,0 +1,71 @@ +:root { + --color-background: #ffffff; + --color-background-alt: #fbfbfb; + --color-background-alt2: #175ddc; + + --color-primary-300: #6795e8; + --color-primary-500: #175ddc; + --color-primary-700: #1252a3; + + --color-secondary-100: #f0f0f0; + --color-secondary-300: #ced4dc; + --color-secondary-500: #89929f; + --color-secondary-700: #212529; + + --color-success-500: #017e45; + --color-success-700: #00552e; + + --color-danger-500: #c83522; + --color-danger-700: #98291b; + + --color-warning-500: #8b6609; + --color-warning-700: #694d05; + + --color-info-500: #555555; + --color-info-700: #3b3a3a; + + --color-text-main: #212529; + --color-text-muted: #6d757e; + --color-text-contrast: #ffffff; + --color-text-alt2: #ffffff; + + --tw-ring-offset-color: #fff; +} + +.theme_light { + /* should be left empty as white is the default */ +} + +.theme_dark { + --color-background: #1f242e; + --color-background-alt: #161c26; + --color-background-alt2: #2f343d; + + --color-primary-300: #175ddc; + --color-primary-500: #6a99f0; + --color-primary-700: #b4ccf9; + + --color-secondary-100: #2f343d; + --color-secondary-300: #6e7689; + --color-secondary-500: #bac0ce; + --color-secondary-700: #ffffff; + + --color-success-500: #52e07c; + --color-success-700: #a8efbe; + + --color-danger-500: #ff8d85; + --color-danger-700: #ffbfbb; + + --color-warning-500: #ffeb66; + --color-warning-700: #fff5b3; + + --color-info-500: #a4b0c6; + --color-info-700: #d1d7e2; + + --color-text-main: #ffffff; + --color-text-muted: #bac0ce; + --color-text-contrast: #191e26; + --color-text-alt2: #ffffff; + + --tw-ring-offset-color: #1f242e; +} diff --git a/libs/components/src/utils/i18n-mock.service.ts b/libs/components/src/utils/i18n-mock.service.ts new file mode 100644 index 0000000000..9eb200b3d3 --- /dev/null +++ b/libs/components/src/utils/i18n-mock.service.ts @@ -0,0 +1,19 @@ +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +export class I18nMockService implements I18nService { + locale: string; + supportedTranslationLocales: string[]; + translationLocale: string; + collator: Intl.Collator; + localeNames: Map; + + constructor(private lookupTable: Record) {} + + t(id: string, p1?: string, p2?: string, p3?: string) { + return this.lookupTable[id]; + } + + translate(id: string, p1?: string, p2?: string, p3?: string) { + return this.t(id, p1, p2, p3); + } +} diff --git a/libs/components/src/variables.scss b/libs/components/src/variables.scss new file mode 100644 index 0000000000..a0bc2d8852 --- /dev/null +++ b/libs/components/src/variables.scss @@ -0,0 +1,357 @@ +$dark-icon-themes: "theme_dark"; + +$primary: #175ddc; +$primary-accent: #1252a3; +$secondary: #ced4da; +$secondary-alt: #1a3b66; +$success: #00a65a; +$info: #555555; +$warning: #bf7e16; +$danger: #dd4b39; +$white: #ffffff; + +// Bootstrap Variable Overrides + +$theme-colors: ( + "primary-accent": $primary-accent, + "secondary-alt": $secondary-alt, +); + +$body-bg: $white; +$body-color: #333333; + +$font-family-sans-serif: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif, + "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + +$h1-font-size: 1.7rem; +$h2-font-size: 1.3rem; +$h3-font-size: 1rem; +$h4-font-size: 1rem; +$h5-font-size: 1rem; +$h6-font-size: 1rem; + +$small-font-size: 90%; +$font-size-lg: 1.15rem; +$code-font-size: 100%; + +$navbar-padding-y: 0.75rem; +$grid-gutter-width: 20px; +$card-spacer-y: 0.6rem; + +$list-group-item-padding-y: 0.6rem; +$list-group-active-color: $body-color; +$list-group-active-bg: $white; +$list-group-active-border-color: rgba(#000000, 0.125); + +$dropdown-link-color: $body-color; +$dropdown-link-hover-bg: rgba(#000000, 0.06); +$dropdown-link-active-color: $dropdown-link-color; +$dropdown-link-active-bg: rgba(#000000, 0.1); +$dropdown-item-padding-x: 1rem; + +$navbar-brand-font-size: 35px; +$navbar-brand-height: 35px; +$navbar-brand-padding-y: 0; +$navbar-dark-color: rgba($white, 0.7); +$navbar-dark-hover-color: rgba($white, 0.9); +$navbar-nav-link-padding-x: 0.8rem; + +$input-bg: #fbfbfb; +$input-focus-bg: $white; +$input-disabled-bg: #e0e0e0; +$input-placeholder-color: #b4b4b4; + +$table-accent-bg: rgba(#000000, 0.02); +$table-hover-bg: rgba(#000000, 0.03); + +$modal-backdrop-opacity: 0.3; +$btn-font-weight: 600; +$lead-font-weight: normal; + +$grid-breakpoints: ( + xs: 0, + sm: 1px, + md: 2px, + lg: 3px, + xl: 4px, +); + +$border-color: $secondary; + +// MFA Types for logo styling with no dark theme alternative + +$mfaTypes: 0, 2, 3, 4, 6; + +// Theme Variables +// Light + +$lightDangerHover: #c43421; +$lightInputColor: #465057; +$lightInputPlaceholderColor: #b6b8b8; + +// Dark + +$darkPrimary: #6a99f0; +$darkPrimary-alt: #b4ccf9; +$darkDanger: #ff8d85; +$darkDangerHover: #ffbfbb; +$darkSuccess: #52e07c; +$darkWarning: #ffeb66; +$darkInfo: #a4b0c6; +$darkLinks: #6a99f0; +$darkGrey1: #bac0ce; +$darkGrey2: #8d94a5; +$darkBlue1: #4c525f; +$darkBlue2: #3c424e; +$darkDarkBlue1: #2f343d; +$darkDarkBlue2: #1f242e; +$darkInputColor: $white; +$darkInputPlaceholderColor: $darkGrey1; + +$themes: ( + light: ( + primary: $primary, + primaryAlt: $primary-accent, + danger: $danger, + info: #343a40, + success: $success, + warning: $warning, + backgroundColor: $white, + badgeDangerBackground: $danger, + badgeDangerText: $white, + badgeInfoBackground: #555555, + badgeInfoText: $white, + badgePrimaryBackground: $primary, + badgePrimaryBackgroundHover: #134eb9, + badgePrimaryText: $white, + badgeSecondaryBackground: #ced4da, + badgeSecondaryText: #212529, + bgLightColor: #f8f9fa, + bgPrimaryColor: $primary, + borderColor: $border-color, + borderPrimaryColor: $primary, + browserInputIconsFilter: invert(0), + btnDanger: $danger, + btnDangerHover: $lightDangerHover, + btnDangerText: $white, + btnLinkText: $primary, + btnLinkTextHover: #104097, + btnOutlineDangerBackground: $input-bg, + btnOutlineDangerBackgroundHover: $danger, + btnOutlineDangerBorder: #ced4da, + btnOutlineDangerBorderHover: $danger, + btnOutlineDangerText: $danger, + btnOutlineDangerTextHover: $white, + btnOutlinePrimaryBackground: $input-bg, + btnOutlinePrimaryBackgroundHover: $primary, + btnOutlinePrimaryBorder: #ced4da, + btnOutlinePrimaryBorderHover: $primary, + btnOutlinePrimaryText: $primary, + btnOutlinePrimaryTextHover: $white, + btnOutlineSecondaryBackground: $input-bg, + btnOutlineSecondaryBackgroundHover: #ced4da, + btnOutlineSecondaryBorder: #ced4da, + btnOutlineSecondaryBorderHover: #ced4da, + btnOutlineSecondaryText: #6c757d, + btnOutlineSecondaryTextHover: #333333, + btnPrimary: $primary, + btnPrimaryBorderHover: #1249ae, + btnPrimaryHover: #134eb9, + btnPrimaryText: $white, + btnSecondary: $secondary, + btnSecondaryBorder: $secondary, + btnSecondaryBorderHover: #b1bbc4, + btnSecondaryHover: #b8c1ca, + btnSecondaryText: #212529, + btnSecondaryTextHover: #212529, + calloutBackground: #fafafa, + calloutColor: #212529, + cdkDraggingBackground: $white, + codeColor: #e83e8c, + dropdownBackground: $white, + dropdownHover: rgba(0, 0, 0, 0.06), + dropdownTextColor: $body-color, + dropdownTextMuted: #6c757d, + focus: rgb(23 93 220 / 25%), + footerBackgroundColor: #fbfbfb, + foregroundColor: $white, + headerColor: rgba(0, 0, 0, 0.03), + iconColor: #777777, + iconHover: $body-color, + imgFilter: invert(0) grayscale(0), + inputBackgroundColor: $input-bg, + inputBorderColor: $border-color, + inputDisabledBackground: #e0e0e0, + inputDisabledColor: #6c757d, + inputPlaceholderColor: $lightInputPlaceholderColor, + inputTextColor: $lightInputColor, + layoutFrontendColor: #ecf0f5, + learnMoreHover: #104097, + linkColor: $primary, + linkColorHover: #104097, + linkWeight: 400, + listItemActive: $body-color, + listItemBorder: rgba(0, 0, 0, 0.125), + loadingSvg: url("../images/loading.svg"), + logoSuffix: "dark", + mfaLogoSuffix: ".png", + navActiveBackground: $white, + navActiveWeight: 600, + navBackground: $primary, + navBackgroundAlt: $secondary-alt, + navOrgBackgroundColor: #fbfbfb, + navWeight: 600, + pwLetter: $body-color, + pwNumber: #007fde, + pwSpecial: #c40800, + pwStrengthBackground: #e9ecef, + separator: $secondary, + separatorHr: rgb(0, 0, 0, 0.1), + tableColorHover: #333333, + tableLinkColor: $primary, + tableLinkColorHover: #104097, + tableRowHover: rgba(0, 0, 0, 0.03), + tableSeparator: #dee2e6, + textColor: $body-color, + textDangerColor: $white, + textInfoColor: $white, + textHeadingColor: #333333, + textMuted: #6c757d, + textSuccessColor: $white, + textWarningColor: $white, + ), + dark: ( + primary: $darkPrimary, + primaryAlt: $darkPrimary-alt, + danger: $darkDanger, + info: $darkInfo, + success: $darkSuccess, + warning: $darkWarning, + backgroundColor: $darkDarkBlue2, + badgeDangerBackground: $darkDanger, + badgeDangerText: $darkDarkBlue2, + badgeInfoBackground: $darkInfo, + badgeInfoText: $darkDarkBlue2, + badgePrimaryBackground: $darkLinks, + badgePrimaryBackgroundHover: $darkPrimary-alt, + badgePrimaryText: $darkDarkBlue2, + badgeSecondaryBackground: $darkGrey2, + badgeSecondaryText: $darkDarkBlue2, + bgLightColor: $darkDarkBlue2, + bgPrimaryColor: $darkPrimary, + borderColor: $darkBlue1, + borderPrimaryColor: $darkPrimary, + browserInputIconsFilter: invert(1), + btnDanger: $darkDanger, + btnDangerHover: $darkDangerHover, + btnDangerText: $darkDarkBlue2, + btnLinkText: $white, + btnLinkTextHover: $darkGrey1, + btnOutlineDangerBackground: $darkDanger, + btnOutlineDangerBackgroundHover: $darkDangerHover, + btnOutlineDangerBorder: $darkDanger, + btnOutlineDangerBorderHover: $darkDangerHover, + btnOutlineDangerText: $darkDarkBlue2, + btnOutlineDangerTextHover: $darkDarkBlue2, + btnOutlinePrimaryBackground: $darkPrimary, + btnOutlinePrimaryBackgroundHover: $darkPrimary-alt, + btnOutlinePrimaryBorder: $darkPrimary, + btnOutlinePrimaryBorderHover: $darkPrimary-alt, + btnOutlinePrimaryText: $darkDarkBlue2, + btnOutlinePrimaryTextHover: $darkDarkBlue2, + btnOutlineSecondaryBackground: transparent, + btnOutlineSecondaryBackgroundHover: transparent, + btnOutlineSecondaryBorder: $darkGrey1, + btnOutlineSecondaryBorderHover: $darkGrey2, + btnOutlineSecondaryText: $white, + btnOutlineSecondaryTextHover: $darkGrey2, + btnPrimary: $darkLinks, + btnPrimaryBorderHover: $darkPrimary-alt, + btnPrimaryHover: $darkPrimary-alt, + btnPrimaryText: $darkDarkBlue2, + btnSecondary: transparent, + btnSecondaryBorder: $darkGrey1, + btnSecondaryBorderHover: $darkGrey2, + btnSecondaryHover: transparent, + btnSecondaryText: $white, + btnSecondaryTextHover: $darkGrey2, + calloutBackground: $darkBlue2, + calloutColor: $white, + cdkDraggingBackground: $darkDarkBlue1, + codeColor: #e83e8c, + dropdownBackground: $darkDarkBlue1, + dropdownHover: rgba(255, 255, 255, 0.03), + dropdownTextColor: $white, + dropdownTextMuted: #bec6cf, + focus: rgb(106 153 240 / 25%), + footerBackgroundColor: $darkBlue1, + foregroundColor: $darkDarkBlue1, + headerColor: $darkBlue1, + iconColor: #777777, + iconHover: $darkGrey2, + imgFilter: invert(1) grayscale(1), + inputBackgroundColor: transparent, + inputBorderColor: $darkGrey1, + inputDisabledBackground: $darkBlue2, + inputDisabledColor: $darkGrey1, + inputPlaceholderColor: $darkInputPlaceholderColor, + inputTextColor: $darkInputColor, + layoutFrontendColor: $darkDarkBlue2, + learnMoreHover: $darkPrimary-alt, + linkColor: $darkLinks, + linkColorHover: $darkLinks, + linkWeight: 600, + listItemActive: $darkPrimary, + listItemBorder: $darkBlue1, + loadingSvg: url("../images/loading-white.svg"), + logoSuffix: "white", + mfaLogoSuffix: "-w.png", + navActiveBackground: $darkDarkBlue2, + navActiveWeight: 600, + navBackground: $darkDarkBlue1, + navBackgroundAlt: $darkDarkBlue1, + navOrgBackgroundColor: #161c26, + navWeight: 400, + pwLetter: $white, + pwNumber: #52bdfb, + pwSpecial: #ff7c70, + pwStrengthBackground: $darkBlue2, + separator: $darkBlue1, + separatorHr: $darkBlue1, + tableColorHover: $darkGrey1, + tableLinkColor: $white, + tableLinkColorHover: $white, + tableRowHover: rgba(255, 255, 255, 0.03), + tableSeparator: $darkBlue1, + textColor: $darkGrey1, + textDangerColor: $darkDarkBlue2, + textHeadingColor: $white, + textInfoColor: $darkDarkBlue2, + textMuted: $darkGrey1, + textSuccessColor: $darkDarkBlue2, + textWarningColor: $darkDarkBlue2, + ), +); + +@mixin themify($themes: $themes) { + @each $theme, $map in $themes { + html.theme_#{$theme} & { + $theme-map: () !global; + @each $key, $submap in $map { + $value: map-get(map-get($themes, $theme), "#{$key}"); + $theme-map: map-merge( + $theme-map, + ( + $key: $value, + ) + ) !global; + } + @content; + $theme-map: null !global; + } + } +} + +@function themed($key) { + @return map-get($theme-map, $key); +} ; diff --git a/libs/components/tailwind.config.base.js b/libs/components/tailwind.config.base.js new file mode 100644 index 0000000000..fd0caec749 --- /dev/null +++ b/libs/components/tailwind.config.base.js @@ -0,0 +1,71 @@ +/* eslint-disable */ +const colors = require("tailwindcss/colors"); + +module.exports = { + prefix: "tw-", + content: ["./src/**/*.{html,ts}", "../../libs/components/src/**/*.{html,ts}"], + safelist: [], + corePlugins: { preflight: false }, + theme: { + colors: { + transparent: colors.transparent, + current: colors.current, + primary: { + 300: "var(--color-primary-300)", + 500: "var(--color-primary-500)", + 700: "var(--color-primary-700)", + }, + secondary: { + 100: "var(--color-secondary-100)", + 300: "var(--color-secondary-300)", + 500: "var(--color-secondary-500)", + 700: "var(--color-secondary-700)", + }, + success: { + 500: "var(--color-success-500)", + 700: "var(--color-success-700)", + }, + danger: { + 500: "var(--color-danger-500)", + 700: "var(--color-danger-700)", + }, + warning: { + 500: "var(--color-warning-500)", + 700: "var(--color-warning-700)", + }, + info: { + 500: "var(--color-info-500)", + 700: "var(--color-info-700)", + }, + text: { + main: "var(--color-text-main)", + muted: "var(--color-text-muted)", + contrast: "var(--color-text-contrast)", + alt2: "var(--color-text-alt2)", + }, + background: { + DEFAULT: "var(--color-background)", + alt: "var(--color-background-alt)", + alt2: "var(--color-background-alt2)", + }, + }, + textColor: { + main: "var(--color-text-main)", + muted: "var(--color-text-muted)", + contrast: "var(--color-text-contrast)", + alt2: "var(--color-text-alt2)", + success: "var(--color-success-500)", + danger: "var(--color-danger-500)", + warning: "var(--color-warning-500)", + info: "var(--color-info-500)", + primary: { + 300: "var(--color-primary-300)", + }, + }, + ringOffsetColor: ({ theme }) => ({ + DEFAULT: theme("colors.background"), + ...theme("colors"), + }), + }, + plugins: [], +}; diff --git a/libs/components/tailwind.config.js b/libs/components/tailwind.config.js new file mode 100644 index 0000000000..5f7eb29829 --- /dev/null +++ b/libs/components/tailwind.config.js @@ -0,0 +1,11 @@ +/* eslint-disable */ +const config = require("./tailwind.config.base"); + +config.content = ["./src/**/*.{html,ts,mdx}", "./.storybook/preview.js"]; +config.safelist = [ + { + pattern: /tw-bg-(.*)/, + }, +]; + +module.exports = config; diff --git a/libs/components/tsconfig.app.json b/libs/components/tsconfig.app.json new file mode 100644 index 0000000000..2722dbe8c9 --- /dev/null +++ b/libs/components/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": ["src/main.ts", "src/polyfills.ts"], + "include": ["src/**/*.d.ts"], + "exclude": ["**/*.stories.*"] +} diff --git a/libs/components/tsconfig.json b/libs/components/tsconfig.json new file mode 100644 index 0000000000..549eeed211 --- /dev/null +++ b/libs/components/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": false, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "es2017", + "module": "es2020", + "lib": ["es2020", "dom"], + "paths": { + "jslib-common/*": ["../common/src/*"], + "jslib-angular/*": ["../angular/src/*"] + } + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/libs/components/tsconfig.spec.json b/libs/components/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/libs/components/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/libs/electron/jest.config.js b/libs/electron/jest.config.js new file mode 100644 index 0000000000..523c0354e2 --- /dev/null +++ b/libs/electron/jest.config.js @@ -0,0 +1,16 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + preset: "ts-jest", + testEnvironment: "jsdom", + testMatch: ["**/+(*.)+(spec).+(ts)"], + setupFilesAfterEnv: ["/spec/test.ts"], + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), +}; diff --git a/libs/electron/package.json b/libs/electron/package.json new file mode 100644 index 0000000000..fa2a472ada --- /dev/null +++ b/libs/electron/package.json @@ -0,0 +1,23 @@ +{ + "name": "@bitwarden/jslib-electron", + "version": "0.0.0", + "description": "Common code used across Bitwarden JavaScript projects.", + "keywords": [ + "bitwarden" + ], + "author": "Bitwarden Inc.", + "homepage": "https://bitwarden.com", + "repository": { + "type": "git", + "url": "https://github.com/bitwarden/jslib" + }, + "license": "GPL-3.0", + "scripts": { + "clean": "rimraf dist/**/*", + "build": "npm run clean && tsc", + "build:watch": "npm run clean && tsc -watch" + }, + "dependencies": { + "@bitwarden/jslib-common": "file:../common" + } +} diff --git a/libs/electron/spec/services/electronLog.service.spec.ts b/libs/electron/spec/services/electronLog.service.spec.ts new file mode 100644 index 0000000000..5952da4302 --- /dev/null +++ b/libs/electron/spec/services/electronLog.service.spec.ts @@ -0,0 +1,9 @@ +import { ElectronLogService } from "jslib-electron/services/electronLog.service"; + +describe("ElectronLogService", () => { + it("sets dev based on electron method", () => { + process.env.ELECTRON_IS_DEV = "1"; + const logService = new ElectronLogService(); + expect(logService).toEqual(expect.objectContaining({ isDev: true }) as any); + }); +}); diff --git a/libs/electron/spec/test.ts b/libs/electron/spec/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/electron/spec/utils.spec.ts b/libs/electron/spec/utils.spec.ts new file mode 100644 index 0000000000..f9e95a2d96 --- /dev/null +++ b/libs/electron/spec/utils.spec.ts @@ -0,0 +1,27 @@ +import { cleanUserAgent } from "jslib-electron/utils"; + +const expectedUserAgent = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${process.versions.chrome} Safari/537.36`; + +describe("cleanUserAgent", () => { + it("cleans mac agent", () => { + const initialMacAgent = `Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6_0) AppleWebKit/537.36 (KHTML, like Gecko) Bitwarden/${process.version} Chrome/${process.versions.chrome} Electron/${process.versions.electron} Safari/537.36`; + expect(cleanUserAgent(initialMacAgent)).toEqual(expectedUserAgent); + }); + + it("cleans windows agent", () => { + const initialWindowsAgent = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Bitwarden/${process.version} Chrome/${process.versions.chrome} Electron/${process.versions.electron} Safari/537.36`; + expect(cleanUserAgent(initialWindowsAgent)).toEqual(expectedUserAgent); + }); + + it("cleans linux agent", () => { + const initialWindowsAgent = `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Bitwarden/${process.version} Chrome/${process.versions.chrome} Electron/${process.versions.electron} Safari/537.36`; + expect(cleanUserAgent(initialWindowsAgent)).toEqual(expectedUserAgent); + }); + + it("does not change version numbers", () => { + const expected = `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36`; + const initialAgent = `Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Bitwarden/1.28.3 Chrome/87.0.4280.141 Electron/11.4.5 Safari/537.36`; + + expect(cleanUserAgent(initialAgent)).toEqual(expected); + }); +}); diff --git a/libs/electron/src/baseMenu.ts b/libs/electron/src/baseMenu.ts new file mode 100644 index 0000000000..09d47f7ec1 --- /dev/null +++ b/libs/electron/src/baseMenu.ts @@ -0,0 +1,225 @@ +import { Menu, MenuItemConstructorOptions } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { WindowMain } from "./window.main"; + +export class BaseMenu { + protected editMenuItemOptions: MenuItemConstructorOptions; + protected viewSubMenuItemOptions: MenuItemConstructorOptions[]; + protected windowMenuItemOptions: MenuItemConstructorOptions; + protected macAppMenuItemOptions: MenuItemConstructorOptions[]; + protected macWindowSubmenuOptions: MenuItemConstructorOptions[]; + + constructor(protected i18nService: I18nService, protected windowMain: WindowMain) {} + + protected initProperties() { + this.editMenuItemOptions = { + label: this.i18nService.t("edit"), + submenu: [ + { + label: this.i18nService.t("undo"), + role: "undo", + }, + { + label: this.i18nService.t("redo"), + role: "redo", + }, + { type: "separator" }, + { + label: this.i18nService.t("cut"), + role: "cut", + }, + { + label: this.i18nService.t("copy"), + role: "copy", + }, + { + label: this.i18nService.t("paste"), + role: "paste", + }, + { type: "separator" }, + { + label: this.i18nService.t("selectAll"), + role: "selectAll", + }, + ], + }; + + this.viewSubMenuItemOptions = [ + { + label: this.i18nService.t("zoomIn"), + role: "zoomIn", + accelerator: "CmdOrCtrl+=", + }, + { + label: this.i18nService.t("zoomOut"), + role: "zoomOut", + accelerator: "CmdOrCtrl+-", + }, + { + label: this.i18nService.t("resetZoom"), + role: "resetZoom", + accelerator: "CmdOrCtrl+0", + }, + { type: "separator" }, + { + label: this.i18nService.t("toggleFullScreen"), + role: "togglefullscreen", + }, + { type: "separator" }, + { + label: this.i18nService.t("reload"), + role: "forceReload", + }, + { + label: this.i18nService.t("toggleDevTools"), + role: "toggleDevTools", + accelerator: "F12", + }, + ]; + + this.windowMenuItemOptions = { + label: this.i18nService.t("window"), + role: "window", + submenu: [ + { + label: this.i18nService.t("minimize"), + role: "minimize", + }, + { + label: this.i18nService.t("close"), + role: "close", + }, + ], + }; + + if (process.platform === "darwin") { + this.macAppMenuItemOptions = [ + { + label: this.i18nService.t("services"), + role: "services", + submenu: [], + }, + { type: "separator" }, + { + label: this.i18nService.t("hideBitwarden"), + role: "hide", + }, + { + label: this.i18nService.t("hideOthers"), + role: "hideOthers", + }, + { + label: this.i18nService.t("showAll"), + role: "unhide", + }, + { type: "separator" }, + { + label: this.i18nService.t("quitBitwarden"), + role: "quit", + }, + ]; + + this.macWindowSubmenuOptions = [ + { + label: this.i18nService.t("minimize"), + role: "minimize", + }, + { + label: this.i18nService.t("zoom"), + role: "zoom", + }, + { type: "separator" }, + { + label: this.i18nService.t("bringAllToFront"), + role: "front", + }, + { + label: this.i18nService.t("close"), + role: "close", + }, + ]; + } + } + + protected initContextMenu() { + if (this.windowMain.win == null) { + return; + } + + const selectionMenu = Menu.buildFromTemplate([ + { + label: this.i18nService.t("copy"), + role: "copy", + }, + { type: "separator" }, + { + label: this.i18nService.t("selectAll"), + role: "selectAll", + }, + ]); + + const inputMenu = Menu.buildFromTemplate([ + { + label: this.i18nService.t("undo"), + role: "undo", + }, + { + label: this.i18nService.t("redo"), + role: "redo", + }, + { type: "separator" }, + { + label: this.i18nService.t("cut"), + role: "cut", + enabled: false, + }, + { + label: this.i18nService.t("copy"), + role: "copy", + enabled: false, + }, + { + label: this.i18nService.t("paste"), + role: "paste", + }, + { type: "separator" }, + { + label: this.i18nService.t("selectAll"), + role: "selectAll", + }, + ]); + + const inputSelectionMenu = Menu.buildFromTemplate([ + { + label: this.i18nService.t("cut"), + role: "cut", + }, + { + label: this.i18nService.t("copy"), + role: "copy", + }, + { + label: this.i18nService.t("paste"), + role: "paste", + }, + { type: "separator" }, + { + label: this.i18nService.t("selectAll"), + role: "selectAll", + }, + ]); + + this.windowMain.win.webContents.on("context-menu", (e, props) => { + const selected = props.selectionText && props.selectionText.trim() !== ""; + if (props.isEditable && selected) { + inputSelectionMenu.popup({ window: this.windowMain.win }); + } else if (props.isEditable) { + inputMenu.popup({ window: this.windowMain.win }); + } else if (selected) { + selectionMenu.popup({ window: this.windowMain.win }); + } + }); + } +} diff --git a/libs/electron/src/globals.d.ts b/libs/electron/src/globals.d.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/electron/src/services/electronCrypto.service.ts b/libs/electron/src/services/electronCrypto.service.ts new file mode 100644 index 0000000000..36ea813211 --- /dev/null +++ b/libs/electron/src/services/electronCrypto.service.ts @@ -0,0 +1,71 @@ +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { LogService } from "jslib-common/abstractions/log.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { KeySuffixOptions } from "jslib-common/enums/keySuffixOptions"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { CryptoService } from "jslib-common/services/crypto.service"; + +export class ElectronCryptoService extends CryptoService { + constructor( + cryptoFunctionService: CryptoFunctionService, + platformUtilService: PlatformUtilsService, + logService: LogService, + stateService: StateService + ) { + super(cryptoFunctionService, platformUtilService, logService, stateService); + } + + async hasKeyStored(keySuffix: KeySuffixOptions): Promise { + await this.upgradeSecurelyStoredKey(); + return super.hasKeyStored(keySuffix); + } + + protected async storeKey(key: SymmetricCryptoKey, userId?: string) { + if (await this.shouldStoreKey(KeySuffixOptions.Auto, userId)) { + await this.stateService.setCryptoMasterKeyAuto(key.keyB64, { userId: userId }); + } else { + this.clearStoredKey(KeySuffixOptions.Auto); + } + + if (await this.shouldStoreKey(KeySuffixOptions.Biometric, userId)) { + await this.stateService.setCryptoMasterKeyBiometric(key.keyB64, { userId: userId }); + } else { + this.clearStoredKey(KeySuffixOptions.Biometric); + } + } + + protected async retrieveKeyFromStorage(keySuffix: KeySuffixOptions, userId?: string) { + await this.upgradeSecurelyStoredKey(); + return super.retrieveKeyFromStorage(keySuffix, userId); + } + + /** + * @deprecated 4 Jun 2021 This is temporary upgrade method to move from a single shared stored key to + * multiple, unique stored keys for each use, e.g. never logout vs. biometric authentication. + */ + private async upgradeSecurelyStoredKey() { + // attempt key upgrade, but if we fail just delete it. Keys will be stored property upon unlock anyway. + const key = await this.stateService.getCryptoMasterKeyB64(); + + if (key == null) { + return; + } + + try { + if (await this.shouldStoreKey(KeySuffixOptions.Auto)) { + await this.stateService.setCryptoMasterKeyAuto(key); + } + if (await this.shouldStoreKey(KeySuffixOptions.Biometric)) { + await this.stateService.setCryptoMasterKeyBiometric(key); + } + } catch (e) { + this.logService.error( + `Encountered error while upgrading obsolete Bitwarden secure storage item:` + ); + this.logService.error(e); + } + + await this.stateService.setCryptoMasterKeyB64(null); + } +} diff --git a/libs/electron/src/services/electronLog.service.ts b/libs/electron/src/services/electronLog.service.ts new file mode 100644 index 0000000000..c6195416f2 --- /dev/null +++ b/libs/electron/src/services/electronLog.service.ts @@ -0,0 +1,45 @@ +import * as path from "path"; + +import log from "electron-log"; + +import { LogLevelType } from "jslib-common/enums/logLevelType"; +import { ConsoleLogService as BaseLogService } from "jslib-common/services/consoleLog.service"; + +import { isDev } from "../utils"; + +export class ElectronLogService extends BaseLogService { + constructor(protected filter: (level: LogLevelType) => boolean = null, logDir: string = null) { + super(isDev(), filter); + if (log.transports == null) { + return; + } + + log.transports.file.level = "info"; + if (logDir != null) { + log.transports.file.file = path.join(logDir, "app.log"); + } + } + + write(level: LogLevelType, message: string) { + if (this.filter != null && this.filter(level)) { + return; + } + + switch (level) { + case LogLevelType.Debug: + log.debug(message); + break; + case LogLevelType.Info: + log.info(message); + break; + case LogLevelType.Warning: + log.warn(message); + break; + case LogLevelType.Error: + log.error(message); + break; + default: + break; + } + } +} diff --git a/libs/electron/src/services/electronMainMessaging.service.ts b/libs/electron/src/services/electronMainMessaging.service.ts new file mode 100644 index 0000000000..9a6923e84b --- /dev/null +++ b/libs/electron/src/services/electronMainMessaging.service.ts @@ -0,0 +1,69 @@ +import { app, dialog, ipcMain, Menu, MenuItem, nativeTheme, session } from "electron"; + +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { ThemeType } from "jslib-common/enums/themeType"; + +import { RendererMenuItem } from "../utils"; +import { WindowMain } from "../window.main"; + +export class ElectronMainMessagingService implements MessagingService { + constructor(private windowMain: WindowMain, private onMessage: (message: any) => void) { + ipcMain.handle("appVersion", () => { + return app.getVersion(); + }); + + ipcMain.handle("systemTheme", () => { + return nativeTheme.shouldUseDarkColors ? ThemeType.Dark : ThemeType.Light; + }); + + ipcMain.handle("showMessageBox", (event, options) => { + return dialog.showMessageBox(this.windowMain.win, options); + }); + + ipcMain.handle("openContextMenu", (event, options: { menu: RendererMenuItem[] }) => { + return new Promise((resolve) => { + const menu = new Menu(); + options.menu.forEach((m, index) => { + menu.append( + new MenuItem({ + label: m.label, + type: m.type, + click: () => { + resolve(index); + }, + }) + ); + }); + menu.popup({ + window: windowMain.win, + callback: () => { + resolve(-1); + }, + }); + }); + }); + + ipcMain.handle("windowVisible", () => { + return windowMain.win?.isVisible(); + }); + + ipcMain.handle("getCookie", async (event, options) => { + return await session.defaultSession.cookies.get(options); + }); + + nativeTheme.on("updated", () => { + windowMain.win?.webContents.send( + "systemThemeUpdated", + nativeTheme.shouldUseDarkColors ? ThemeType.Dark : ThemeType.Light + ); + }); + } + + send(subscriber: string, arg: any = {}) { + const message = Object.assign({}, { command: subscriber }, arg); + this.onMessage(message); + if (this.windowMain.win != null) { + this.windowMain.win.webContents.send("messagingService", message); + } + } +} diff --git a/libs/electron/src/services/electronPlatformUtils.service.ts b/libs/electron/src/services/electronPlatformUtils.service.ts new file mode 100644 index 0000000000..3774f3c37a --- /dev/null +++ b/libs/electron/src/services/electronPlatformUtils.service.ts @@ -0,0 +1,214 @@ +import { clipboard, ipcRenderer, shell } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { ClientType } from "jslib-common/enums/clientType"; +import { DeviceType } from "jslib-common/enums/deviceType"; +import { ThemeType } from "jslib-common/enums/themeType"; + +import { isDev, isMacAppStore } from "../utils"; + +export class ElectronPlatformUtilsService implements PlatformUtilsService { + private deviceCache: DeviceType = null; + + constructor( + protected i18nService: I18nService, + private messagingService: MessagingService, + private clientType: ClientType.Desktop | ClientType.DirectoryConnector, + private stateService: StateService + ) {} + + getDevice(): DeviceType { + if (!this.deviceCache) { + switch (process.platform) { + case "win32": + this.deviceCache = DeviceType.WindowsDesktop; + break; + case "darwin": + this.deviceCache = DeviceType.MacOsDesktop; + break; + case "linux": + default: + this.deviceCache = DeviceType.LinuxDesktop; + break; + } + } + + return this.deviceCache; + } + + getDeviceString(): string { + const device = DeviceType[this.getDevice()].toLowerCase(); + return device.replace("desktop", ""); + } + + getClientType() { + return this.clientType; + } + + isFirefox(): boolean { + return false; + } + + isChrome(): boolean { + return true; + } + + isEdge(): boolean { + return false; + } + + isOpera(): boolean { + return false; + } + + isVivaldi(): boolean { + return false; + } + + isSafari(): boolean { + return false; + } + + isMacAppStore(): boolean { + return isMacAppStore(); + } + + isViewOpen(): Promise { + return Promise.resolve(false); + } + + launchUri(uri: string, options?: any): void { + shell.openExternal(uri); + } + + saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void { + const blob = new Blob([blobData], blobOptions); + const a = win.document.createElement("a"); + a.href = URL.createObjectURL(blob); + a.download = fileName; + win.document.body.appendChild(a); + a.click(); + win.document.body.removeChild(a); + } + + getApplicationVersion(): Promise { + return ipcRenderer.invoke("appVersion"); + } + + // Temporarily restricted to only Windows until https://github.com/electron/electron/pull/28349 + // has been merged and an updated electron build is available. + supportsWebAuthn(win: Window): boolean { + return process.platform === "win32"; + } + + supportsDuo(): boolean { + return true; + } + + showToast( + type: "error" | "success" | "warning" | "info", + title: string, + text: string | string[], + options?: any + ): void { + this.messagingService.send("showToast", { + text: text, + title: title, + type: type, + options: options, + }); + } + + async showDialog( + text: string, + title?: string, + confirmText?: string, + cancelText?: string, + type?: string + ): Promise { + const buttons = [confirmText == null ? this.i18nService.t("ok") : confirmText]; + if (cancelText != null) { + buttons.push(cancelText); + } + + const result = await ipcRenderer.invoke("showMessageBox", { + type: type, + title: title, + message: title, + detail: text, + buttons: buttons, + cancelId: buttons.length === 2 ? 1 : null, + defaultId: 0, + noLink: true, + }); + + return Promise.resolve(result.response === 0); + } + + isDev(): boolean { + return isDev(); + } + + isSelfHost(): boolean { + return false; + } + + copyToClipboard(text: string, options?: any): void { + const type = options ? options.type : null; + const clearing = options ? !!options.clearing : false; + const clearMs: number = options && options.clearMs ? options.clearMs : null; + clipboard.writeText(text, type); + if (!clearing) { + this.messagingService.send("copiedToClipboard", { + clipboardValue: text, + clearMs: clearMs, + type: type, + clearing: clearing, + }); + } + } + + readFromClipboard(options?: any): Promise { + const type = options ? options.type : null; + return Promise.resolve(clipboard.readText(type)); + } + + async supportsBiometric(): Promise { + return await this.stateService.getEnableBiometric(); + } + + authenticateBiometric(): Promise { + return new Promise((resolve) => { + const val = ipcRenderer.sendSync("biometric", { + action: "authenticate", + }); + resolve(val); + }); + } + + getDefaultSystemTheme() { + return ipcRenderer.invoke("systemTheme"); + } + + onDefaultSystemThemeChange(callback: (theme: ThemeType.Light | ThemeType.Dark) => unknown) { + ipcRenderer.on("systemThemeUpdated", (event, theme: ThemeType.Light | ThemeType.Dark) => + callback(theme) + ); + } + + async getEffectiveTheme() { + const theme = await this.stateService.getTheme(); + if (theme == null || theme === ThemeType.System) { + return this.getDefaultSystemTheme(); + } else { + return theme; + } + } + + supportsSecureStorage(): boolean { + return true; + } +} diff --git a/libs/electron/src/services/electronRendererMessaging.service.ts b/libs/electron/src/services/electronRendererMessaging.service.ts new file mode 100644 index 0000000000..89350a65f2 --- /dev/null +++ b/libs/electron/src/services/electronRendererMessaging.service.ts @@ -0,0 +1,26 @@ +import { ipcRenderer } from "electron"; + +import { BroadcasterService } from "jslib-common/abstractions/broadcaster.service"; +import { MessagingService } from "jslib-common/abstractions/messaging.service"; + +export class ElectronRendererMessagingService implements MessagingService { + constructor(private broadcasterService: BroadcasterService) { + ipcRenderer.on("messagingService", async (event: any, message: any) => { + if (message.command) { + this.sendMessage(message.command, message, false); + } + }); + } + + send(subscriber: string, arg: any = {}) { + this.sendMessage(subscriber, arg, true); + } + + private sendMessage(subscriber: string, arg: any = {}, toMain: boolean) { + const message = Object.assign({}, { command: subscriber }, arg); + this.broadcasterService.send(message); + if (toMain) { + ipcRenderer.send("messagingService", message); + } + } +} diff --git a/libs/electron/src/services/electronRendererSecureStorage.service.ts b/libs/electron/src/services/electronRendererSecureStorage.service.ts new file mode 100644 index 0000000000..5c3f3c7453 --- /dev/null +++ b/libs/electron/src/services/electronRendererSecureStorage.service.ts @@ -0,0 +1,43 @@ +import { ipcRenderer } from "electron"; + +import { StorageService } from "jslib-common/abstractions/storage.service"; +import { StorageOptions } from "jslib-common/models/domain/storageOptions"; + +export class ElectronRendererSecureStorageService implements StorageService { + async get(key: string, options?: StorageOptions): Promise { + const val = ipcRenderer.sendSync("keytar", { + action: "getPassword", + key: key, + keySuffix: options?.keySuffix ?? "", + }); + return Promise.resolve(val != null ? (JSON.parse(val) as T) : null); + } + + async has(key: string, options?: StorageOptions): Promise { + const val = ipcRenderer.sendSync("keytar", { + action: "hasPassword", + key: key, + keySuffix: options?.keySuffix ?? "", + }); + return Promise.resolve(!!val); + } + + async save(key: string, obj: any, options?: StorageOptions): Promise { + ipcRenderer.sendSync("keytar", { + action: "setPassword", + key: key, + keySuffix: options?.keySuffix ?? "", + value: JSON.stringify(obj), + }); + return Promise.resolve(); + } + + async remove(key: string, options?: StorageOptions): Promise { + ipcRenderer.sendSync("keytar", { + action: "deletePassword", + key: key, + keySuffix: options?.keySuffix ?? "", + }); + return Promise.resolve(); + } +} diff --git a/libs/electron/src/services/electronRendererStorage.service.ts b/libs/electron/src/services/electronRendererStorage.service.ts new file mode 100644 index 0000000000..69436bfe1b --- /dev/null +++ b/libs/electron/src/services/electronRendererStorage.service.ts @@ -0,0 +1,34 @@ +import { ipcRenderer } from "electron"; + +import { StorageService } from "jslib-common/abstractions/storage.service"; + +export class ElectronRendererStorageService implements StorageService { + get(key: string): Promise { + return ipcRenderer.invoke("storageService", { + action: "get", + key: key, + }); + } + + has(key: string): Promise { + return ipcRenderer.invoke("storageService", { + action: "has", + key: key, + }); + } + + save(key: string, obj: any): Promise { + return ipcRenderer.invoke("storageService", { + action: "save", + key: key, + obj: obj, + }); + } + + remove(key: string): Promise { + return ipcRenderer.invoke("storageService", { + action: "remove", + key: key, + }); + } +} diff --git a/libs/electron/src/services/electronStorage.service.ts b/libs/electron/src/services/electronStorage.service.ts new file mode 100644 index 0000000000..fdabf2a2ba --- /dev/null +++ b/libs/electron/src/services/electronStorage.service.ts @@ -0,0 +1,60 @@ +import * as fs from "fs"; + +import { ipcMain } from "electron"; + +import { StorageService } from "jslib-common/abstractions/storage.service"; +import { NodeUtils } from "jslib-common/misc/nodeUtils"; + +// eslint-disable-next-line +const Store = require("electron-store"); + +export class ElectronStorageService implements StorageService { + private store: any; + + constructor(dir: string, defaults = {}) { + if (!fs.existsSync(dir)) { + NodeUtils.mkdirpSync(dir, "700"); + } + const storeConfig: any = { + defaults: defaults, + name: "data", + }; + this.store = new Store(storeConfig); + + ipcMain.handle("storageService", (event, options) => { + switch (options.action) { + case "get": + return this.get(options.key); + case "has": + return this.has(options.key); + case "save": + return this.save(options.key, options.obj); + case "remove": + return this.remove(options.key); + } + }); + } + + get(key: string): Promise { + const val = this.store.get(key) as T; + return Promise.resolve(val != null ? val : null); + } + + has(key: string): Promise { + const val = this.store.get(key); + return Promise.resolve(val != null); + } + + save(key: string, obj: any): Promise { + if (obj instanceof Set) { + obj = Array.from(obj); + } + this.store.set(key, obj); + return Promise.resolve(); + } + + remove(key: string): Promise { + this.store.delete(key); + return Promise.resolve(); + } +} diff --git a/libs/electron/src/tray.main.ts b/libs/electron/src/tray.main.ts new file mode 100644 index 0000000000..ebbc56875b --- /dev/null +++ b/libs/electron/src/tray.main.ts @@ -0,0 +1,186 @@ +import * as path from "path"; + +import { app, BrowserWindow, Menu, MenuItemConstructorOptions, nativeImage, Tray } from "electron"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +import { WindowMain } from "./window.main"; + +export class TrayMain { + contextMenu: Menu; + + private appName: string; + private tray: Tray; + private icon: string | Electron.NativeImage; + private pressedIcon: Electron.NativeImage; + + constructor( + private windowMain: WindowMain, + private i18nService: I18nService, + private stateService: StateService + ) { + if (process.platform === "win32") { + this.icon = path.join(__dirname, "/images/icon.ico"); + } else if (process.platform === "darwin") { + const nImage = nativeImage.createFromPath(path.join(__dirname, "/images/icon-template.png")); + nImage.setTemplateImage(true); + this.icon = nImage; + this.pressedIcon = nativeImage.createFromPath( + path.join(__dirname, "/images/icon-highlight.png") + ); + } else { + this.icon = path.join(__dirname, "/images/icon.png"); + } + } + + async init(appName: string, additionalMenuItems: MenuItemConstructorOptions[] = null) { + this.appName = appName; + + const menuItemOptions: MenuItemConstructorOptions[] = [ + { + label: this.i18nService.t("showHide"), + click: () => this.toggleWindow(), + }, + { type: "separator" }, + { + label: this.i18nService.t("exit"), + click: () => this.closeWindow(), + }, + ]; + + if (additionalMenuItems != null) { + menuItemOptions.splice(1, 0, ...additionalMenuItems); + } + + this.contextMenu = Menu.buildFromTemplate(menuItemOptions); + if (await this.stateService.getEnableTray()) { + this.showTray(); + } + } + + setupWindowListeners(win: BrowserWindow) { + win.on("minimize", async (e: Event) => { + if (await this.stateService.getEnableMinimizeToTray()) { + e.preventDefault(); + this.hideToTray(); + } + }); + + win.on("close", async (e: Event) => { + if (await this.stateService.getEnableCloseToTray()) { + if (!this.windowMain.isQuitting) { + e.preventDefault(); + this.hideToTray(); + } + } + }); + + win.on("show", async () => { + const enableTray = await this.stateService.getEnableTray(); + if (!enableTray) { + setTimeout(() => this.removeTray(false), 100); + } + }); + } + + removeTray(showWindow = true) { + // Due to https://github.com/electron/electron/issues/17622 + // we cannot destroy the tray icon on linux. + if (this.tray != null && process.platform !== "linux") { + this.tray.destroy(); + this.tray = null; + } + + if (showWindow && this.windowMain.win != null && !this.windowMain.win.isVisible()) { + this.windowMain.win.show(); + } + } + + async hideToTray() { + this.showTray(); + if (this.windowMain.win != null) { + this.windowMain.win.hide(); + } + if (this.isDarwin() && !(await this.stateService.getAlwaysShowDock())) { + this.hideDock(); + } + } + + restoreFromTray() { + if (this.windowMain.win == null || !this.windowMain.win.isVisible()) { + this.toggleWindow(); + } + } + + showTray() { + if (this.tray != null) { + return; + } + + this.tray = new Tray(this.icon); + this.tray.setToolTip(this.appName); + this.tray.on("click", () => this.toggleWindow()); + this.tray.on("right-click", () => this.tray.popUpContextMenu(this.contextMenu)); + + if (this.pressedIcon != null) { + this.tray.setPressedImage(this.pressedIcon); + } + if (this.contextMenu != null && !this.isDarwin()) { + this.tray.setContextMenu(this.contextMenu); + } + } + + updateContextMenu() { + if (this.contextMenu != null && this.isLinux()) { + this.tray.setContextMenu(this.contextMenu); + } + } + + private hideDock() { + app.dock.hide(); + } + + private showDock() { + app.dock.show(); + } + + private isDarwin() { + return process.platform === "darwin"; + } + + private isLinux() { + return process.platform === "linux"; + } + + private async toggleWindow() { + if (this.windowMain.win == null) { + if (this.isDarwin()) { + // On MacOS, closing the window via the red button destroys the BrowserWindow instance. + this.windowMain.createWindow().then(() => { + this.windowMain.win.show(); + this.showDock(); + }); + } + return; + } + if (this.windowMain.win.isVisible()) { + this.windowMain.win.hide(); + if (this.isDarwin() && !(await this.stateService.getAlwaysShowDock())) { + this.hideDock(); + } + } else { + this.windowMain.win.show(); + if (this.isDarwin()) { + this.showDock(); + } + } + } + + private closeWindow() { + this.windowMain.isQuitting = true; + if (this.windowMain.win != null) { + this.windowMain.win.close(); + } + } +} diff --git a/libs/electron/src/updater.main.ts b/libs/electron/src/updater.main.ts new file mode 100644 index 0000000000..881208f8d3 --- /dev/null +++ b/libs/electron/src/updater.main.ts @@ -0,0 +1,156 @@ +import { dialog, shell } from "electron"; +import log from "electron-log"; +import { autoUpdater } from "electron-updater"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { isAppImage, isDev, isMacAppStore, isWindowsPortable, isWindowsStore } from "./utils"; +import { WindowMain } from "./window.main"; + +const UpdaterCheckInitalDelay = 5 * 1000; // 5 seconds +const UpdaterCheckInterval = 12 * 60 * 60 * 1000; // 12 hours + +export class UpdaterMain { + private doingUpdateCheck = false; + private doingUpdateCheckWithFeedback = false; + private canUpdate = false; + + constructor( + private i18nService: I18nService, + private windowMain: WindowMain, + private gitHubProject: string, + private onCheckingForUpdate: () => void = null, + private onReset: () => void = null, + private onUpdateDownloaded: () => void = null, + private projectName: string + ) { + autoUpdater.logger = log; + + const linuxCanUpdate = process.platform === "linux" && isAppImage(); + const windowsCanUpdate = + process.platform === "win32" && !isWindowsStore() && !isWindowsPortable(); + const macCanUpdate = process.platform === "darwin" && !isMacAppStore(); + this.canUpdate = + process.env.ELECTRON_NO_UPDATER !== "1" && + (linuxCanUpdate || windowsCanUpdate || macCanUpdate); + } + + async init() { + global.setTimeout(async () => await this.checkForUpdate(), UpdaterCheckInitalDelay); + global.setInterval(async () => await this.checkForUpdate(), UpdaterCheckInterval); + + autoUpdater.on("checking-for-update", () => { + if (this.onCheckingForUpdate != null) { + this.onCheckingForUpdate(); + } + this.doingUpdateCheck = true; + }); + + autoUpdater.on("update-available", async () => { + if (this.doingUpdateCheckWithFeedback) { + if (this.windowMain.win == null) { + this.reset(); + return; + } + + const result = await dialog.showMessageBox(this.windowMain.win, { + type: "info", + title: + this.i18nService.t(this.projectName) + " - " + this.i18nService.t("updateAvailable"), + message: this.i18nService.t("updateAvailable"), + detail: this.i18nService.t("updateAvailableDesc"), + buttons: [this.i18nService.t("yes"), this.i18nService.t("no")], + cancelId: 1, + defaultId: 0, + noLink: true, + }); + + if (result.response === 0) { + autoUpdater.downloadUpdate(); + } else { + this.reset(); + } + } + }); + + autoUpdater.on("update-not-available", () => { + if (this.doingUpdateCheckWithFeedback && this.windowMain.win != null) { + dialog.showMessageBox(this.windowMain.win, { + message: this.i18nService.t("noUpdatesAvailable"), + buttons: [this.i18nService.t("ok")], + defaultId: 0, + noLink: true, + }); + } + + this.reset(); + }); + + autoUpdater.on("update-downloaded", async (info) => { + if (this.onUpdateDownloaded != null) { + this.onUpdateDownloaded(); + } + + if (this.windowMain.win == null) { + return; + } + + const result = await dialog.showMessageBox(this.windowMain.win, { + type: "info", + title: this.i18nService.t(this.projectName) + " - " + this.i18nService.t("restartToUpdate"), + message: this.i18nService.t("restartToUpdate"), + detail: this.i18nService.t("restartToUpdateDesc", info.version), + buttons: [this.i18nService.t("restart"), this.i18nService.t("later")], + cancelId: 1, + defaultId: 0, + noLink: true, + }); + + if (result.response === 0) { + // Quit and install have a different window logic, setting `isQuitting` just to be safe. + this.windowMain.isQuitting = true; + autoUpdater.quitAndInstall(true, true); + } + }); + + autoUpdater.on("error", (error) => { + if (this.doingUpdateCheckWithFeedback) { + dialog.showErrorBox( + this.i18nService.t("updateError"), + error == null ? this.i18nService.t("unknown") : (error.stack || error).toString() + ); + } + + this.reset(); + }); + } + + async checkForUpdate(withFeedback = false) { + if (this.doingUpdateCheck || isDev()) { + return; + } + + if (!this.canUpdate) { + if (withFeedback) { + shell.openExternal("https://github.com/bitwarden/" + this.gitHubProject + "/releases"); + } + + return; + } + + this.doingUpdateCheckWithFeedback = withFeedback; + if (withFeedback) { + autoUpdater.autoDownload = false; + } + + await autoUpdater.checkForUpdates(); + } + + private reset() { + if (this.onReset != null) { + this.onReset(); + } + autoUpdater.autoDownload = true; + this.doingUpdateCheck = false; + } +} diff --git a/libs/electron/src/utils.ts b/libs/electron/src/utils.ts new file mode 100644 index 0000000000..603cc1bec1 --- /dev/null +++ b/libs/electron/src/utils.ts @@ -0,0 +1,80 @@ +import { ipcRenderer } from "electron"; + +export type RendererMenuItem = { + label?: string; + type?: "normal" | "separator" | "submenu" | "checkbox" | "radio"; + click?: () => any; +}; + +export function invokeMenu(menu: RendererMenuItem[]) { + const menuWithoutClick = menu.map((m) => { + return { label: m.label, type: m.type }; + }); + ipcRenderer.invoke("openContextMenu", { menu: menuWithoutClick }).then((i: number) => { + if (i !== -1) { + menu[i].click(); + } + }); +} + +export function isDev() { + // ref: https://github.com/sindresorhus/electron-is-dev + if ("ELECTRON_IS_DEV" in process.env) { + return parseInt(process.env.ELECTRON_IS_DEV, 10) === 1; + } + return process.defaultApp || /node_modules[\\/]electron[\\/]/.test(process.execPath); +} + +export function isAppImage() { + return process.platform === "linux" && "APPIMAGE" in process.env; +} + +export function isMac() { + return process.platform === "darwin"; +} + +export function isMacAppStore() { + return isMac() && process.mas === true; +} + +export function isWindowsStore() { + const isWindows = process.platform === "win32"; + let windowsStore = process.windowsStore; + if ( + isWindows && + !windowsStore && + process.resourcesPath.indexOf("8bitSolutionsLLC.bitwardendesktop_") > -1 + ) { + windowsStore = true; + } + return isWindows && windowsStore === true; +} + +export function isSnapStore() { + return process.platform === "linux" && process.env.SNAP_USER_DATA != null; +} + +export function isWindowsPortable() { + return process.platform === "win32" && process.env.PORTABLE_EXECUTABLE_DIR != null; +} + +/** + * Sanitize user agent so external resources used by the app can't built data on our users. + */ +export function cleanUserAgent(userAgent: string): string { + const userAgentItem = (startString: string, endString: string) => { + const startIndex = userAgent.indexOf(startString); + return userAgent.substring(startIndex, userAgent.indexOf(endString, startIndex) + 1); + }; + const systemInformation = "(Windows NT 10.0; Win64; x64)"; + + // Set system information, remove bitwarden, and electron information + return userAgent + .replace(userAgentItem("(", ")"), systemInformation) + .replace(userAgentItem("Bitwarden", " "), "") + .replace(userAgentItem("Electron", " "), ""); +} + +export async function getCookie(url: string, name: string): Promise { + return await ipcRenderer.invoke("getCookie", { url: url, name: name }); +} diff --git a/libs/electron/src/window.main.ts b/libs/electron/src/window.main.ts new file mode 100644 index 0000000000..66d4c78031 --- /dev/null +++ b/libs/electron/src/window.main.ts @@ -0,0 +1,293 @@ +import * as path from "path"; +import * as url from "url"; + +import { app, BrowserWindow, screen } from "electron"; + +import { LogService } from "jslib-common/abstractions/log.service"; +import { StateService } from "jslib-common/abstractions/state.service"; + +import { cleanUserAgent, isDev, isMacAppStore, isSnapStore } from "./utils"; + +const mainWindowSizeKey = "mainWindowSize"; +const WindowEventHandlingDelay = 100; +export class WindowMain { + win: BrowserWindow; + isQuitting = false; + + private windowStateChangeTimer: NodeJS.Timer; + private windowStates: { [key: string]: any } = {}; + private enableAlwaysOnTop = false; + + constructor( + private stateService: StateService, + private logService: LogService, + private hideTitleBar = false, + private defaultWidth = 950, + private defaultHeight = 600, + private argvCallback: (argv: string[]) => void = null, + private createWindowCallback: (win: BrowserWindow) => void + ) {} + + init(): Promise { + return new Promise((resolve, reject) => { + try { + if (!isMacAppStore() && !isSnapStore()) { + const gotTheLock = app.requestSingleInstanceLock(); + if (!gotTheLock) { + app.quit(); + return; + } else { + // eslint-disable-next-line + app.on("second-instance", (event, argv, workingDirectory) => { + // Someone tried to run a second instance, we should focus our window. + if (this.win != null) { + if (this.win.isMinimized() || !this.win.isVisible()) { + this.win.show(); + } + this.win.focus(); + } + if (process.platform === "win32" || process.platform === "linux") { + if (this.argvCallback != null) { + this.argvCallback(argv); + } + } + }); + } + } + + // This method will be called when Electron is shutting + // down the application. + app.on("before-quit", () => { + this.isQuitting = true; + }); + + // This method will be called when Electron has finished + // initialization and is ready to create browser windows. + // Some APIs can only be used after this event occurs. + app.on("ready", async () => { + await this.createWindow(); + resolve(); + if (this.argvCallback != null) { + this.argvCallback(process.argv); + } + }); + + // Quit when all windows are closed. + app.on("window-all-closed", () => { + // On OS X it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== "darwin" || this.isQuitting || isMacAppStore()) { + app.quit(); + } + }); + + app.on("activate", async () => { + // On OS X it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + if (this.win === null) { + await this.createWindow(); + } else { + // Show the window when clicking on Dock icon + this.win.show(); + } + }); + } catch (e) { + // Catch Error + // throw e; + reject(e); + } + }); + } + + async createWindow(): Promise { + this.windowStates[mainWindowSizeKey] = await this.getWindowState( + this.defaultWidth, + this.defaultHeight + ); + this.enableAlwaysOnTop = await this.stateService.getEnableAlwaysOnTop(); + + // Create the browser window. + this.win = new BrowserWindow({ + width: this.windowStates[mainWindowSizeKey].width, + height: this.windowStates[mainWindowSizeKey].height, + minWidth: 680, + minHeight: 500, + x: this.windowStates[mainWindowSizeKey].x, + y: this.windowStates[mainWindowSizeKey].y, + title: app.name, + icon: process.platform === "linux" ? path.join(__dirname, "/images/icon.png") : undefined, + titleBarStyle: this.hideTitleBar && process.platform === "darwin" ? "hiddenInset" : undefined, + show: false, + backgroundColor: "#fff", + alwaysOnTop: this.enableAlwaysOnTop, + webPreferences: { + spellcheck: false, + nodeIntegration: true, + backgroundThrottling: false, + contextIsolation: false, + }, + }); + + if (this.windowStates[mainWindowSizeKey].isMaximized) { + this.win.maximize(); + } + + // Show it later since it might need to be maximized. + this.win.show(); + + // and load the index.html of the app. + this.win.loadURL( + url.format({ + protocol: "file:", + pathname: path.join(__dirname, "/index.html"), + slashes: true, + }), + { + userAgent: cleanUserAgent(this.win.webContents.userAgent), + } + ); + + // Open the DevTools. + if (isDev()) { + this.win.webContents.openDevTools(); + } + + // Emitted when the window is closed. + this.win.on("closed", async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + + // Dereference the window object, usually you would store window + // in an array if your app supports multi windows, this is the time + // when you should delete the corresponding element. + this.win = null; + }); + + this.win.on("close", async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + }); + + this.win.on("maximize", async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + }); + + this.win.on("unmaximize", async () => { + await this.updateWindowState(mainWindowSizeKey, this.win); + }); + + this.win.on("resize", () => { + this.windowStateChangeHandler(mainWindowSizeKey, this.win); + }); + + this.win.on("move", () => { + this.windowStateChangeHandler(mainWindowSizeKey, this.win); + }); + this.win.on("focus", () => { + this.win.webContents.send("messagingService", { + command: "windowIsFocused", + windowIsFocused: true, + }); + }); + + if (this.createWindowCallback) { + this.createWindowCallback(this.win); + } + } + + async toggleAlwaysOnTop() { + this.enableAlwaysOnTop = !this.win.isAlwaysOnTop(); + this.win.setAlwaysOnTop(this.enableAlwaysOnTop); + await this.stateService.setEnableAlwaysOnTop(this.enableAlwaysOnTop); + } + + private windowStateChangeHandler(configKey: string, win: BrowserWindow) { + global.clearTimeout(this.windowStateChangeTimer); + this.windowStateChangeTimer = global.setTimeout(async () => { + await this.updateWindowState(configKey, win); + }, WindowEventHandlingDelay); + } + + private async updateWindowState(configKey: string, win: BrowserWindow) { + if (win == null) { + return; + } + + try { + const bounds = win.getBounds(); + + if (this.windowStates[configKey] == null) { + this.windowStates[configKey] = await this.stateService.getWindow(); + if (this.windowStates[configKey] == null) { + this.windowStates[configKey] = {}; + } + } + + this.windowStates[configKey].isMaximized = win.isMaximized(); + this.windowStates[configKey].displayBounds = screen.getDisplayMatching(bounds).bounds; + + if (!win.isMaximized() && !win.isMinimized() && !win.isFullScreen()) { + this.windowStates[configKey].x = bounds.x; + this.windowStates[configKey].y = bounds.y; + this.windowStates[configKey].width = bounds.width; + this.windowStates[configKey].height = bounds.height; + } + + await this.stateService.setWindow(this.windowStates[configKey]); + } catch (e) { + this.logService.error(e); + } + } + + private async getWindowState(defaultWidth: number, defaultHeight: number) { + const state = await this.stateService.getWindow(); + + const isValid = state != null && (this.stateHasBounds(state) || state.isMaximized); + let displayBounds: Electron.Rectangle = null; + if (!isValid) { + state.width = defaultWidth; + state.height = defaultHeight; + + displayBounds = screen.getPrimaryDisplay().bounds; + } else if (this.stateHasBounds(state) && state.displayBounds) { + // Check if the display where the window was last open is still available + displayBounds = screen.getDisplayMatching(state.displayBounds).bounds; + + if ( + displayBounds.width !== state.displayBounds.width || + displayBounds.height !== state.displayBounds.height || + displayBounds.x !== state.displayBounds.x || + displayBounds.y !== state.displayBounds.y + ) { + state.x = undefined; + state.y = undefined; + displayBounds = screen.getPrimaryDisplay().bounds; + } + } + + if (displayBounds != null) { + if (state.width > displayBounds.width && state.height > displayBounds.height) { + state.isMaximized = true; + } + + if (state.width > displayBounds.width) { + state.width = displayBounds.width - 10; + } + if (state.height > displayBounds.height) { + state.height = displayBounds.height - 10; + } + } + + return state; + } + + private stateHasBounds(state: any): boolean { + return ( + state != null && + Number.isInteger(state.x) && + Number.isInteger(state.y) && + Number.isInteger(state.width) && + state.width > 0 && + Number.isInteger(state.height) && + state.height > 0 + ); + } +} diff --git a/libs/electron/tsconfig.json b/libs/electron/tsconfig.json new file mode 100644 index 0000000000..d5501ab34e --- /dev/null +++ b/libs/electron/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../shared/tsconfig", + "compilerOptions": { + "paths": { + "jslib-common/*": ["../common/src/*"], + "jslib-electron/*": ["./src/*"] + } + }, + "include": ["src", "spec"], + "exclude": ["node_modules", "dist"] +} diff --git a/libs/electron/tsconfig.spec.json b/libs/electron/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/libs/electron/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/libs/jest.config.js b/libs/jest.config.js new file mode 100644 index 0000000000..75028ad26f --- /dev/null +++ b/libs/jest.config.js @@ -0,0 +1,18 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), + projects: [ + "/angular/jest.config.js", + "/common/jest.config.js", + "/electron/jest.config.js", + "/node/jest.config.js", + ], +}; diff --git a/libs/node/jest.config.js b/libs/node/jest.config.js new file mode 100644 index 0000000000..48c4b61d3a --- /dev/null +++ b/libs/node/jest.config.js @@ -0,0 +1,15 @@ +const { pathsToModuleNameMapper } = require("ts-jest"); + +const { compilerOptions } = require("./tsconfig"); + +module.exports = { + preset: "ts-jest", + testMatch: ["**/+(*.)+(spec).+(ts)"], + setupFilesAfterEnv: ["/spec/test.ts"], + collectCoverage: true, + coverageReporters: ["html", "lcov"], + coverageDirectory: "coverage", + moduleNameMapper: pathsToModuleNameMapper(compilerOptions?.paths || {}, { + prefix: "/", + }), +}; diff --git a/libs/node/package.json b/libs/node/package.json new file mode 100644 index 0000000000..1505d924ed --- /dev/null +++ b/libs/node/package.json @@ -0,0 +1,23 @@ +{ + "name": "@bitwarden/jslib-node", + "version": "0.0.0", + "description": "Common code used across Bitwarden JavaScript projects.", + "keywords": [ + "bitwarden" + ], + "author": "Bitwarden Inc.", + "homepage": "https://bitwarden.com", + "repository": { + "type": "git", + "url": "https://github.com/bitwarden/jslib" + }, + "license": "GPL-3.0", + "scripts": { + "clean": "rimraf dist/**/*", + "build": "npm run clean && tsc", + "build:watch": "npm run clean && tsc -watch" + }, + "dependencies": { + "@bitwarden/jslib-common": "file:../common" + } +} diff --git a/libs/node/spec/cli/consoleLog.service.spec.ts b/libs/node/spec/cli/consoleLog.service.spec.ts new file mode 100644 index 0000000000..3c76d5a681 --- /dev/null +++ b/libs/node/spec/cli/consoleLog.service.spec.ts @@ -0,0 +1,45 @@ +import { + interceptConsole, + restoreConsole, +} from "jslib-common/../spec/services/consolelog.service.spec"; + +import { ConsoleLogService } from "jslib-node/cli/services/consoleLog.service"; + +let caughtMessage: any = {}; + +describe("CLI Console log service", () => { + let logService: ConsoleLogService; + beforeEach(() => { + caughtMessage = {}; + interceptConsole(caughtMessage); + logService = new ConsoleLogService(true); + }); + + afterAll(() => { + restoreConsole(); + }); + + it("should redirect all console to error if BW_RESPONSE env is true", () => { + process.env.BW_RESPONSE = "true"; + + logService.debug("this is a debug message"); + expect(caughtMessage).toMatchObject({ + error: { 0: "this is a debug message" }, + }); + }); + + it("should not redirect console to error if BW_RESPONSE != true", () => { + process.env.BW_RESPONSE = "false"; + + logService.debug("debug"); + logService.info("info"); + logService.warning("warning"); + logService.error("error"); + + expect(caughtMessage).toMatchObject({ + log: { 0: "info" }, + warn: { 0: "warning" }, + error: { 0: "error" }, + }); + }); +}); diff --git a/libs/node/spec/services/nodeCryptoFunction.service.spec.ts b/libs/node/spec/services/nodeCryptoFunction.service.spec.ts new file mode 100644 index 0000000000..79572fcc98 --- /dev/null +++ b/libs/node/spec/services/nodeCryptoFunction.service.spec.ts @@ -0,0 +1,518 @@ +import { Utils } from "jslib-common/misc/utils"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; +import { NodeCryptoFunctionService } from "jslib-node/services/nodeCryptoFunction.service"; + +const RsaPublicKey = + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl0Vawl/toXzkEvB82FEtqHP" + + "4xlU2ab/v0crqIfXfIoWF/XXdHGIdrZeilnRXPPJT1B9dTsasttEZNnua/0Rek/cjNDHtzT52irfoZYS7X6HNIfOi54Q+egP" + + "RQ1H7iNHVZz3K8Db9GCSKPeC8MbW6gVCzb15esCe1gGzg6wkMuWYDFYPoh/oBqcIqrGah7firqB1nDedzEjw32heP2DAffVN" + + "084iTDjiWrJNUxBJ2pDD5Z9dT3MzQ2s09ew1yMWK2z37rT3YerC7OgEDmo3WYo3xL3qYJznu3EO2nmrYjiRa40wKSjxsTlUc" + + "xDF+F0uMW8oR9EMUHgepdepfAtLsSAQIDAQAB"; +const RsaPrivateKey = + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS8Hz" + + "YUS2oc/jGVTZpv+/Ryuoh9d8ihYX9dd0cYh2tl6KWdFc88lPUH11Oxqy20Rk2e5r/RF6T9yM0Me3NPnaKt+hlhLtfoc0h86L" + + "nhD56A9FDUfuI0dVnPcrwNv0YJIo94LwxtbqBULNvXl6wJ7WAbODrCQy5ZgMVg+iH+gGpwiqsZqHt+KuoHWcN53MSPDfaF4/" + + "YMB99U3TziJMOOJask1TEEnakMPln11PczNDazT17DXIxYrbPfutPdh6sLs6AQOajdZijfEvepgnOe7cQ7aeatiOJFrjTApK" + + "PGxOVRzEMX4XS4xbyhH0QxQeB6l16l8C0uxIBAgMBAAECggEASaWfeVDA3cVzOPFSpvJm20OTE+R6uGOU+7vh36TX/POq92q" + + "Buwbd0h0oMD32FxsXywd2IxtBDUSiFM9699qufTVuM0Q3tZw6lHDTOVG08+tPdr8qSbMtw7PGFxN79fHLBxejjO4IrM9lapj" + + "WpxEF+11x7r+wM+0xRZQ8sNFYG46aPfIaty4BGbL0I2DQ2y8I57iBCAy69eht59NLMm27fRWGJIWCuBIjlpfzET1j2HLXUIh" + + "5bTBNzqaN039WH49HczGE3mQKVEJZc/efk3HaVd0a1Sjzyn0QY+N1jtZN3jTRbuDWA1AknkX1LX/0tUhuS3/7C3ejHxjw4Dk" + + "1ZLo5/QKBgQDIWvqFn0+IKRSu6Ua2hDsufIHHUNLelbfLUMmFthxabcUn4zlvIscJO00Tq/ezopSRRvbGiqnxjv/mYxucvOU" + + "BeZtlus0Q9RTACBtw9TGoNTmQbEunJ2FOSlqbQxkBBAjgGEppRPt30iGj/VjAhCATq2MYOa/X4dVR51BqQAFIEwKBgQDBSIf" + + "TFKC/hDk6FKZlgwvupWYJyU9RkyfstPErZFmzoKhPkQ3YORo2oeAYmVUbS9I2iIYpYpYQJHX8jMuCbCz4ONxTCuSIXYQYUcU" + + "q4PglCKp31xBAE6TN8SvhfME9/MvuDssnQinAHuF0GDAhF646T3LLS1not6Vszv7brwSoGwKBgQC88v/8cGfi80ssQZeMnVv" + + "q1UTXIeQcQnoY5lGHJl3K8mbS3TnXE6c9j417Fdz+rj8KWzBzwWXQB5pSPflWcdZO886Xu/mVGmy9RWgLuVFhXwCwsVEPjNX" + + "5ramRb0/vY0yzenUCninBsIxFSbIfrPtLUYCc4hpxr+sr2Mg/y6jpvQKBgBezMRRs3xkcuXepuI2R+BCXL1/b02IJTUf1F+1" + + "eLLGd7YV0H+J3fgNc7gGWK51hOrF9JBZHBGeOUPlaukmPwiPdtQZpu4QNE3l37VlIpKTF30E6mb+BqR+nht3rUjarnMXgAoE" + + "Z18y6/KIjpSMpqC92Nnk/EBM9EYe6Cf4eA9ApAoGAeqEUg46UTlJySkBKURGpIs3v1kkf5I0X8DnOhwb+HPxNaiEdmO7ckm8" + + "+tPVgppLcG0+tMdLjigFQiDUQk2y3WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEzXKZ" + + "BokBGnjFnTnKcs7nv/O8="; + +const Sha1Mac = "4d4c223f95dc577b665ec4ccbcb680b80a397038"; +const Sha256Mac = "6be3caa84922e12aaaaa2f16c40d44433bb081ef323db584eb616333ab4e874f"; +const Sha512Mac = + "21910e341fa12106ca35758a2285374509326c9fbe0bd64e7b99c898f841dc948c58ce66d3504d8883c" + + "5ea7817a0b7c5d4d9b00364ccd214669131fc17fe4aca"; + +describe("NodeCrypto Function Service", () => { + describe("pbkdf2", () => { + const regular256Key = "pj9prw/OHPleXI6bRdmlaD+saJS4awrMiQsQiDjeu2I="; + const utf8256Key = "yqvoFXgMRmHR3QPYr5pyR4uVuoHkltv9aHUP63p8n7I="; + const unicode256Key = "ZdeOata6xoRpB4DLp8zHhXz5kLmkWtX5pd+TdRH8w8w="; + + const regular512Key = + "liTi/Ke8LPU1Qv+Vl7NGEVt/XMbsBVJ2kQxtVG/Z1/JFHFKQW3ZkI81qVlwTiCpb+cFXzs+57" + + "eyhhx5wfKo5Cg=="; + const utf8512Key = + "df0KdvIBeCzD/kyXptwQohaqUa4e7IyFUyhFQjXCANu5T+scq55hCcE4dG4T/MhAk2exw8j7ixRN" + + "zXANiVZpnw=="; + const unicode512Key = + "FE+AnUJaxv8jh+zUDtZz4mjjcYk0/PZDZm+SLJe3XtxtnpdqqpblX6JjuMZt/dYYNMOrb2+mD" + + "L3FiQDTROh1lg=="; + + testPbkdf2("sha256", regular256Key, utf8256Key, unicode256Key); + testPbkdf2("sha512", regular512Key, utf8512Key, unicode512Key); + }); + + describe("hkdf", () => { + const regular256Key = "qBUmEYtwTwwGPuw/z6bs/qYXXYNUlocFlyAuuANI8Pw="; + const utf8256Key = "6DfJwW1R3txgiZKkIFTvVAb7qVlG7lKcmJGJoxR2GBU="; + const unicode256Key = "gejGI82xthA+nKtKmIh82kjw+ttHr+ODsUoGdu5sf0A="; + + const regular512Key = "xe5cIG6ZfwGmb1FvsOedM0XKOm21myZkjL/eDeKIqqM="; + const utf8512Key = "XQMVBnxVEhlvjSFDQc77j5GDE9aorvbS0vKnjhRg0LY="; + const unicode512Key = "148GImrTbrjaGAe/iWEpclINM8Ehhko+9lB14+52lqc="; + + testHkdf("sha256", regular256Key, utf8256Key, unicode256Key); + testHkdf("sha512", regular512Key, utf8512Key, unicode512Key); + }); + + describe("hkdfExpand", () => { + const prk16Byte = "criAmKtfzxanbgea5/kelQ=="; + const prk32Byte = "F5h4KdYQnIVH4rKH0P9CZb1GrR4n16/sJrS0PsQEn0Y="; + const prk64Byte = + "ssBK0mRG17VHdtsgt8yo4v25CRNpauH+0r2fwY/E9rLyaFBAOMbIeTry+" + + "gUJ28p8y+hFh3EI9pcrEWaNvFYonQ=="; + + testHkdfExpand("sha256", prk32Byte, 32, "BnIqJlfnHm0e/2iB/15cbHyR19ARPIcWRp4oNS22CD8="); + testHkdfExpand( + "sha256", + prk32Byte, + 64, + "BnIqJlfnHm0e/2iB/15cbHyR19ARPIcWRp4oNS22CD9BV+" + + "/queOZenPNkDhmlVyL2WZ3OSU5+7ISNF5NhNfvZA==" + ); + testHkdfExpand("sha512", prk64Byte, 32, "uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlk="); + testHkdfExpand( + "sha512", + prk64Byte, + 64, + "uLWbMWodSBms5uGJ5WTRTesyW+MD7nlpCZvagvIRXlkY5Pv0sB+" + + "MqvaopmkC6sD/j89zDwTV9Ib2fpucUydO8w==" + ); + + it("should fail with prk too small", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const f = cryptoFunctionService.hkdfExpand( + Utils.fromB64ToArray(prk16Byte), + "info", + 32, + "sha256" + ); + await expect(f).rejects.toEqual(new Error("prk is too small.")); + }); + + it("should fail with outputByteSize is too large", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const f = cryptoFunctionService.hkdfExpand( + Utils.fromB64ToArray(prk32Byte), + "info", + 8161, + "sha256" + ); + await expect(f).rejects.toEqual(new Error("outputByteSize is too large.")); + }); + }); + + describe("hash", () => { + const regular1Hash = "2a241604fb921fad12bf877282457268e1dccb70"; + const utf81Hash = "85672798dc5831e96d6c48655d3d39365a9c88b6"; + const unicode1Hash = "39c975935054a3efc805a9709b60763a823a6ad4"; + + const regular256Hash = "2b8e96031d352a8655d733d7a930b5ffbea69dc25cf65c7bca7dd946278908b2"; + const utf8256Hash = "25fe8440f5b01ed113b0a0e38e721b126d2f3f77a67518c4a04fcde4e33eeb9d"; + const unicode256Hash = "adc1c0c2afd6e92cefdf703f9b6eb2c38e0d6d1a040c83f8505c561fea58852e"; + + const regular512Hash = + "c15cf11d43bde333647e3f559ec4193bb2edeaa0e8b902772f514cdf3f785a3f49a6e02a4b87b3" + + "b47523271ad45b7e0aebb5cdcc1bc54815d256eb5dcb80da9d"; + const utf8512Hash = + "035c31a877a291af09ed2d3a1a293e69c3e079ea2cecc00211f35e6bce10474ca3ad6e30b59e26118" + + "37463f20969c5bc95282965a051a88f8cdf2e166549fcdd"; + const unicode512Hash = + "2b16a5561af8ad6fe414cc103fc8036492e1fc6d9aabe1b655497054f760fe0e34c5d100ac773d" + + "9f3030438284f22dbfa20cb2e9b019f2c98dfe38ce1ef41bae"; + + const regularMd5 = "5eceffa53a5fd58c44134211e2c5f522"; + const utf8Md5 = "3abc9433c09551b939c80aa0aa3174e1"; + const unicodeMd5 = "85ae134072c8d81257933f7045ba17ca"; + + testHash("sha1", regular1Hash, utf81Hash, unicode1Hash); + testHash("sha256", regular256Hash, utf8256Hash, unicode256Hash); + testHash("sha512", regular512Hash, utf8512Hash, unicode512Hash); + testHash("md5", regularMd5, utf8Md5, unicodeMd5); + }); + + describe("hmac", () => { + testHmac("sha1", Sha1Mac); + testHmac("sha256", Sha256Mac); + testHmac("sha512", Sha512Mac); + }); + + describe("compare", () => { + testCompare(false); + }); + + describe("hmacFast", () => { + testHmac("sha1", Sha1Mac, true); + testHmac("sha256", Sha256Mac, true); + testHmac("sha512", Sha512Mac, true); + }); + + describe("compareFast", () => { + testCompare(true); + }); + + describe("aesEncrypt", () => { + it("should successfully encrypt data", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const iv = makeStaticByteArray(16); + const key = makeStaticByteArray(32); + const data = Utils.fromUtf8ToArray("EncryptMe!"); + const encValue = await nodeCryptoFunctionService.aesEncrypt( + data.buffer, + iv.buffer, + key.buffer + ); + expect(Utils.fromBufferToB64(encValue)).toBe("ByUF8vhyX4ddU9gcooznwA=="); + }); + + it("should successfully encrypt and then decrypt data", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const iv = makeStaticByteArray(16); + const key = makeStaticByteArray(32); + const value = "EncryptMe!"; + const data = Utils.fromUtf8ToArray(value); + const encValue = await nodeCryptoFunctionService.aesEncrypt( + data.buffer, + iv.buffer, + key.buffer + ); + const decValue = await nodeCryptoFunctionService.aesDecrypt(encValue, iv.buffer, key.buffer); + expect(Utils.fromBufferToUtf8(decValue)).toBe(value); + }); + }); + + describe("aesDecryptFast", () => { + it("should successfully decrypt data", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const iv = Utils.fromBufferToB64(makeStaticByteArray(16).buffer); + const symKey = new SymmetricCryptoKey(makeStaticByteArray(32).buffer); + const data = "ByUF8vhyX4ddU9gcooznwA=="; + const params = nodeCryptoFunctionService.aesDecryptFastParameters(data, iv, null, symKey); + const decValue = await nodeCryptoFunctionService.aesDecryptFast(params); + expect(decValue).toBe("EncryptMe!"); + }); + }); + + describe("aesDecrypt", () => { + it("should successfully decrypt data", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const iv = makeStaticByteArray(16); + const key = makeStaticByteArray(32); + const data = Utils.fromB64ToArray("ByUF8vhyX4ddU9gcooznwA=="); + const decValue = await nodeCryptoFunctionService.aesDecrypt( + data.buffer, + iv.buffer, + key.buffer + ); + expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!"); + }); + }); + + describe("rsaEncrypt", () => { + it("should successfully encrypt and then decrypt data", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const pubKey = Utils.fromB64ToArray(RsaPublicKey); + const privKey = Utils.fromB64ToArray(RsaPrivateKey); + const value = "EncryptMe!"; + const data = Utils.fromUtf8ToArray(value); + const encValue = await nodeCryptoFunctionService.rsaEncrypt( + data.buffer, + pubKey.buffer, + "sha1" + ); + const decValue = await nodeCryptoFunctionService.rsaDecrypt(encValue, privKey.buffer, "sha1"); + expect(Utils.fromBufferToUtf8(decValue)).toBe(value); + }); + }); + + describe("rsaDecrypt", () => { + it("should successfully decrypt data", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const privKey = Utils.fromB64ToArray(RsaPrivateKey); + const data = Utils.fromB64ToArray( + "A1/p8BQzN9UrbdYxUY2Va5+kPLyfZXF9JsZrjeEXcaclsnHurdxVAJcnbEqYMP3UXV" + + "4YAS/mpf+Rxe6/X0WS1boQdA0MAHSgx95hIlAraZYpiMLLiJRKeo2u8YivCdTM9V5vuAEJwf9Tof/qFsFci3sApdbATkorCT" + + "zFOIEPF2S1zgperEP23M01mr4dWVdYN18B32YF67xdJHMbFhp5dkQwv9CmscoWq7OE5HIfOb+JAh7BEZb+CmKhM3yWJvoR/D" + + "/5jcercUtK2o+XrzNrL4UQ7yLZcFz6Bfwb/j6ICYvqd/YJwXNE6dwlL57OfwJyCdw2rRYf0/qI00t9u8Iitw==" + ); + const decValue = await nodeCryptoFunctionService.rsaDecrypt( + data.buffer, + privKey.buffer, + "sha1" + ); + expect(Utils.fromBufferToUtf8(decValue)).toBe("EncryptMe!"); + }); + }); + + describe("rsaExtractPublicKey", () => { + it("should successfully extract key", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const privKey = Utils.fromB64ToArray(RsaPrivateKey); + const publicKey = await nodeCryptoFunctionService.rsaExtractPublicKey(privKey.buffer); + expect(Utils.fromBufferToB64(publicKey)).toBe(RsaPublicKey); + }); + }); + + describe("rsaGenerateKeyPair", () => { + testRsaGenerateKeyPair(1024); + testRsaGenerateKeyPair(2048); + + // Generating 4096 bit keys is really slow with Forge lib. + // Maybe move to something else if we ever want to generate keys of this size. + // testRsaGenerateKeyPair(4096); + }); + + describe("randomBytes", () => { + it("should make a value of the correct length", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const randomData = await nodeCryptoFunctionService.randomBytes(16); + expect(randomData.byteLength).toBe(16); + }); + + it("should not make the same value twice", async () => { + const nodeCryptoFunctionService = new NodeCryptoFunctionService(); + const randomData = await nodeCryptoFunctionService.randomBytes(16); + const randomData2 = await nodeCryptoFunctionService.randomBytes(16); + expect( + randomData.byteLength === randomData2.byteLength && randomData !== randomData2 + ).toBeTruthy(); + }); + }); +}); + +function testPbkdf2( + algorithm: "sha256" | "sha512", + regularKey: string, + utf8Key: string, + unicodeKey: string +) { + const regularEmail = "user@example.com"; + const utf8Email = "üser@example.com"; + + const regularPassword = "password"; + const utf8Password = "pǻssword"; + const unicodePassword = "😀password🙏"; + + it("should create valid " + algorithm + " key from regular input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2(regularPassword, regularEmail, algorithm, 5000); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); + + it("should create valid " + algorithm + " key from utf8 input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2(utf8Password, utf8Email, algorithm, 5000); + expect(Utils.fromBufferToB64(key)).toBe(utf8Key); + }); + + it("should create valid " + algorithm + " key from unicode input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2(unicodePassword, regularEmail, algorithm, 5000); + expect(Utils.fromBufferToB64(key)).toBe(unicodeKey); + }); + + it("should create valid " + algorithm + " key from array buffer input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.pbkdf2( + Utils.fromUtf8ToArray(regularPassword).buffer, + Utils.fromUtf8ToArray(regularEmail).buffer, + algorithm, + 5000 + ); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); +} + +function testHkdf( + algorithm: "sha256" | "sha512", + regularKey: string, + utf8Key: string, + unicodeKey: string +) { + const ikm = Utils.fromB64ToArray("criAmKtfzxanbgea5/kelQ=="); + + const regularSalt = "salt"; + const utf8Salt = "üser_salt"; + const unicodeSalt = "😀salt🙏"; + + const regularInfo = "info"; + const utf8Info = "üser_info"; + const unicodeInfo = "😀info🙏"; + + it("should create valid " + algorithm + " key from regular input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf(ikm, regularSalt, regularInfo, 32, algorithm); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); + + it("should create valid " + algorithm + " key from utf8 input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf(ikm, utf8Salt, utf8Info, 32, algorithm); + expect(Utils.fromBufferToB64(key)).toBe(utf8Key); + }); + + it("should create valid " + algorithm + " key from unicode input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf(ikm, unicodeSalt, unicodeInfo, 32, algorithm); + expect(Utils.fromBufferToB64(key)).toBe(unicodeKey); + }); + + it("should create valid " + algorithm + " key from array buffer input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const key = await cryptoFunctionService.hkdf( + ikm, + Utils.fromUtf8ToArray(regularSalt).buffer, + Utils.fromUtf8ToArray(regularInfo).buffer, + 32, + algorithm + ); + expect(Utils.fromBufferToB64(key)).toBe(regularKey); + }); +} + +function testHkdfExpand( + algorithm: "sha256" | "sha512", + b64prk: string, + outputByteSize: number, + b64ExpectedOkm: string +) { + const info = "info"; + + it("should create valid " + algorithm + " " + outputByteSize + " byte okm", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const okm = await cryptoFunctionService.hkdfExpand( + Utils.fromB64ToArray(b64prk), + info, + outputByteSize, + algorithm + ); + expect(Utils.fromBufferToB64(okm)).toBe(b64ExpectedOkm); + }); +} + +function testHash( + algorithm: "sha1" | "sha256" | "sha512" | "md5", + regularHash: string, + utf8Hash: string, + unicodeHash: string +) { + const regularValue = "HashMe!!"; + const utf8Value = "HǻshMe!!"; + const unicodeValue = "😀HashMe!!!🙏"; + + it("should create valid " + algorithm + " hash from regular input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const hash = await cryptoFunctionService.hash(regularValue, algorithm); + expect(Utils.fromBufferToHex(hash)).toBe(regularHash); + }); + + it("should create valid " + algorithm + " hash from utf8 input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const hash = await cryptoFunctionService.hash(utf8Value, algorithm); + expect(Utils.fromBufferToHex(hash)).toBe(utf8Hash); + }); + + it("should create valid " + algorithm + " hash from unicode input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const hash = await cryptoFunctionService.hash(unicodeValue, algorithm); + expect(Utils.fromBufferToHex(hash)).toBe(unicodeHash); + }); + + it("should create valid " + algorithm + " hash from array buffer input", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const hash = await cryptoFunctionService.hash( + Utils.fromUtf8ToArray(regularValue).buffer, + algorithm + ); + expect(Utils.fromBufferToHex(hash)).toBe(regularHash); + }); +} + +function testHmac(algorithm: "sha1" | "sha256" | "sha512", mac: string, fast = false) { + it("should create valid " + algorithm + " hmac", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const value = Utils.fromUtf8ToArray("SignMe!!").buffer; + const key = Utils.fromUtf8ToArray("secretkey").buffer; + let computedMac: ArrayBuffer = null; + if (fast) { + computedMac = await cryptoFunctionService.hmacFast(value, key, algorithm); + } else { + computedMac = await cryptoFunctionService.hmac(value, key, algorithm); + } + expect(Utils.fromBufferToHex(computedMac)).toBe(mac); + }); +} + +function testCompare(fast = false) { + it("should successfully compare two of the same values", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const equal = fast + ? await cryptoFunctionService.compareFast(a.buffer, a.buffer) + : await cryptoFunctionService.compare(a.buffer, a.buffer); + expect(equal).toBe(true); + }); + + it("should successfully compare two different values of the same length", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const b = new Uint8Array(2); + b[0] = 3; + b[1] = 4; + const equal = fast + ? await cryptoFunctionService.compareFast(a.buffer, b.buffer) + : await cryptoFunctionService.compare(a.buffer, b.buffer); + expect(equal).toBe(false); + }); + + it("should successfully compare two different values of different lengths", async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const a = new Uint8Array(2); + a[0] = 1; + a[1] = 2; + const b = new Uint8Array(2); + b[0] = 3; + const equal = fast + ? await cryptoFunctionService.compareFast(a.buffer, b.buffer) + : await cryptoFunctionService.compare(a.buffer, b.buffer); + expect(equal).toBe(false); + }); +} + +function testRsaGenerateKeyPair(length: 1024 | 2048 | 4096) { + it( + "should successfully generate a " + length + " bit key pair", + async () => { + const cryptoFunctionService = new NodeCryptoFunctionService(); + const keyPair = await cryptoFunctionService.rsaGenerateKeyPair(length); + expect(keyPair[0] == null || keyPair[1] == null).toBe(false); + const publicKey = await cryptoFunctionService.rsaExtractPublicKey(keyPair[1]); + expect(Utils.fromBufferToB64(keyPair[0])).toBe(Utils.fromBufferToB64(publicKey)); + }, + 30000 + ); +} + +function makeStaticByteArray(length: number) { + const arr = new Uint8Array(length); + for (let i = 0; i < length; i++) { + arr[i] = i; + } + return arr; +} diff --git a/libs/node/spec/test.ts b/libs/node/spec/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/node/src/cli/baseProgram.ts b/libs/node/src/cli/baseProgram.ts new file mode 100644 index 0000000000..4a2ec904a1 --- /dev/null +++ b/libs/node/src/cli/baseProgram.ts @@ -0,0 +1,113 @@ +import * as chalk from "chalk"; + +import { StateService } from "jslib-common/abstractions/state.service"; + +import { Response } from "./models/response"; +import { ListResponse } from "./models/response/listResponse"; +import { MessageResponse } from "./models/response/messageResponse"; +import { StringResponse } from "./models/response/stringResponse"; + +export abstract class BaseProgram { + constructor( + protected stateService: StateService, + private writeLn: (s: string, finalLine: boolean, error: boolean) => void + ) {} + + protected processResponse( + response: Response, + exitImmediately = false, + dataProcessor: () => string = null + ) { + if (!response.success) { + if (process.env.BW_QUIET !== "true") { + if (process.env.BW_RESPONSE === "true") { + this.writeLn(this.getJson(response), true, false); + } else { + this.writeLn(chalk.redBright(response.message), true, true); + } + } + const exitCode = process.env.BW_CLEANEXIT ? 0 : 1; + if (exitImmediately) { + process.exit(exitCode); + } else { + process.exitCode = exitCode; + } + return; + } + + if (process.env.BW_RESPONSE === "true") { + this.writeLn(this.getJson(response), true, false); + } else if (response.data != null) { + let out: string = dataProcessor != null ? dataProcessor() : null; + if (out == null) { + if (response.data.object === "string") { + const data = (response.data as StringResponse).data; + if (data != null) { + out = data; + } + } else if (response.data.object === "list") { + out = this.getJson((response.data as ListResponse).data); + } else if (response.data.object === "message") { + out = this.getMessage(response); + } else { + out = this.getJson(response.data); + } + } + + if (out != null && process.env.BW_QUIET !== "true") { + this.writeLn(out, true, false); + } + } + if (exitImmediately) { + process.exit(0); + } else { + process.exitCode = 0; + } + } + + protected getJson(obj: any): string { + if (process.env.BW_PRETTY === "true") { + return JSON.stringify(obj, null, " "); + } else { + return JSON.stringify(obj); + } + } + + protected getMessage(response: Response): string { + const message = response.data as MessageResponse; + if (process.env.BW_RAW === "true") { + return message.raw; + } + + let out = ""; + if (message.title != null) { + if (message.noColor) { + out = message.title; + } else { + out = chalk.greenBright(message.title); + } + } + if (message.message != null) { + if (message.title != null) { + out += "\n"; + } + out += message.message; + } + return out.trim() === "" ? null : out; + } + + protected async exitIfAuthed() { + const authed = await this.stateService.getIsAuthenticated(); + if (authed) { + const email = await this.stateService.getEmail(); + this.processResponse(Response.error("You are already logged in as " + email + "."), true); + } + } + + protected async exitIfNotAuthed() { + const authed = await this.stateService.getIsAuthenticated(); + if (!authed) { + this.processResponse(Response.error("You are not logged in."), true); + } + } +} diff --git a/libs/node/src/cli/commands/login.command.ts b/libs/node/src/cli/commands/login.command.ts new file mode 100644 index 0000000000..ee6f822845 --- /dev/null +++ b/libs/node/src/cli/commands/login.command.ts @@ -0,0 +1,624 @@ +import * as http from "http"; + +import * as program from "commander"; +import * as inquirer from "inquirer"; +import Separator from "inquirer/lib/objects/separator"; + +import { ApiService } from "jslib-common/abstractions/api.service"; +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { CryptoService } from "jslib-common/abstractions/crypto.service"; +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PasswordGenerationService } from "jslib-common/abstractions/passwordGeneration.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { PolicyService } from "jslib-common/abstractions/policy.service"; +import { StateService } from "jslib-common/abstractions/state.service"; +import { TwoFactorService } from "jslib-common/abstractions/twoFactor.service"; +import { TwoFactorProviderType } from "jslib-common/enums/twoFactorProviderType"; +import { NodeUtils } from "jslib-common/misc/nodeUtils"; +import { Utils } from "jslib-common/misc/utils"; +import { AuthResult } from "jslib-common/models/domain/authResult"; +import { + ApiLogInCredentials, + PasswordLogInCredentials, + SsoLogInCredentials, +} from "jslib-common/models/domain/logInCredentials"; +import { TokenRequestTwoFactor } from "jslib-common/models/request/identityToken/tokenRequestTwoFactor"; +import { TwoFactorEmailRequest } from "jslib-common/models/request/twoFactorEmailRequest"; +import { UpdateTempPasswordRequest } from "jslib-common/models/request/updateTempPasswordRequest"; +import { ErrorResponse } from "jslib-common/models/response/errorResponse"; + +import { Response } from "../models/response"; +import { MessageResponse } from "../models/response/messageResponse"; + +export class LoginCommand { + protected validatedParams: () => Promise; + protected success: () => Promise; + protected logout: () => Promise; + protected canInteract: boolean; + protected clientId: string; + protected clientSecret: string; + protected email: string; + + private ssoRedirectUri: string = null; + + constructor( + protected authService: AuthService, + protected apiService: ApiService, + protected i18nService: I18nService, + protected environmentService: EnvironmentService, + protected passwordGenerationService: PasswordGenerationService, + protected cryptoFunctionService: CryptoFunctionService, + protected platformUtilsService: PlatformUtilsService, + protected stateService: StateService, + protected cryptoService: CryptoService, + protected policyService: PolicyService, + protected twoFactorService: TwoFactorService, + clientId: string + ) { + this.clientId = clientId; + } + + async run(email: string, password: string, options: program.OptionValues) { + this.canInteract = process.env.BW_NOINTERACTION !== "true"; + + let ssoCodeVerifier: string = null; + let ssoCode: string = null; + let orgIdentifier: string = null; + + let clientId: string = null; + let clientSecret: string = null; + + let selectedProvider: any = null; + + if (options.apikey != null) { + const apiIdentifiers = await this.apiIdentifiers(); + clientId = apiIdentifiers.clientId; + clientSecret = apiIdentifiers.clientSecret; + } else if (options.sso != null && this.canInteract) { + const passwordOptions: any = { + type: "password", + length: 64, + uppercase: true, + lowercase: true, + numbers: true, + special: false, + }; + const state = await this.passwordGenerationService.generatePassword(passwordOptions); + ssoCodeVerifier = await this.passwordGenerationService.generatePassword(passwordOptions); + const codeVerifierHash = await this.cryptoFunctionService.hash(ssoCodeVerifier, "sha256"); + const codeChallenge = Utils.fromBufferToUrlB64(codeVerifierHash); + try { + const ssoParams = await this.openSsoPrompt(codeChallenge, state); + ssoCode = ssoParams.ssoCode; + orgIdentifier = ssoParams.orgIdentifier; + } catch { + return Response.badRequest("Something went wrong. Try again."); + } + } else { + if ((email == null || email === "") && this.canInteract) { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "input", + name: "email", + message: "Email address:", + }); + email = answer.email; + } + if (email == null || email.trim() === "") { + return Response.badRequest("Email address is required."); + } + if (email.indexOf("@") === -1) { + return Response.badRequest("Email address is invalid."); + } + this.email = email; + + if (password == null || password === "") { + if (options.passwordfile) { + password = await NodeUtils.readFirstLine(options.passwordfile); + } else if (options.passwordenv && process.env[options.passwordenv]) { + password = process.env[options.passwordenv]; + } else if (this.canInteract) { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "password", + name: "password", + message: "Master password:", + }); + password = answer.password; + } + } + + if (password == null || password === "") { + return Response.badRequest("Master password is required."); + } + } + + let twoFactorToken: string = options.code; + let twoFactorMethod: TwoFactorProviderType = null; + try { + if (options.method != null) { + twoFactorMethod = parseInt(options.method, null); + } + } catch (e) { + return Response.error("Invalid two-step login method."); + } + + const twoFactor = + twoFactorToken == null + ? null + : new TokenRequestTwoFactor(twoFactorMethod, twoFactorToken, false); + + try { + if (this.validatedParams != null) { + await this.validatedParams(); + } + + let response: AuthResult = null; + if (clientId != null && clientSecret != null) { + response = await this.authService.logIn(new ApiLogInCredentials(clientId, clientSecret)); + } else if (ssoCode != null && ssoCodeVerifier != null) { + response = await this.authService.logIn( + new SsoLogInCredentials( + ssoCode, + ssoCodeVerifier, + this.ssoRedirectUri, + orgIdentifier, + twoFactor + ) + ); + } else { + response = await this.authService.logIn( + new PasswordLogInCredentials(email, password, null, twoFactor) + ); + } + if (response.captchaSiteKey) { + const credentials = new PasswordLogInCredentials(email, password); + const handledResponse = await this.handleCaptchaRequired(twoFactor, credentials); + + // Error Response + if (handledResponse instanceof Response) { + return handledResponse; + } else { + response = handledResponse; + } + } + if (response.requiresTwoFactor) { + const twoFactorProviders = this.twoFactorService.getSupportedProviders(null); + if (twoFactorProviders.length === 0) { + return Response.badRequest("No providers available for this client."); + } + + if (twoFactorMethod != null) { + try { + selectedProvider = twoFactorProviders.filter((p) => p.type === twoFactorMethod)[0]; + } catch (e) { + return Response.error("Invalid two-step login method."); + } + } + + if (selectedProvider == null) { + if (twoFactorProviders.length === 1) { + selectedProvider = twoFactorProviders[0]; + } else if (this.canInteract) { + const twoFactorOptions: (string | Separator)[] = twoFactorProviders.map((p) => p.name); + twoFactorOptions.push(new inquirer.Separator()); + twoFactorOptions.push("Cancel"); + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "list", + name: "method", + message: "Two-step login method:", + choices: twoFactorOptions, + }); + const i = twoFactorOptions.indexOf(answer.method); + if (i === twoFactorOptions.length - 1) { + return Response.error("Login failed."); + } + selectedProvider = twoFactorProviders[i]; + } + if (selectedProvider == null) { + return Response.error("Login failed. No provider selected."); + } + } + + if ( + twoFactorToken == null && + response.twoFactorProviders.size > 1 && + selectedProvider.type === TwoFactorProviderType.Email + ) { + const emailReq = new TwoFactorEmailRequest(); + emailReq.email = this.authService.email; + emailReq.masterPasswordHash = this.authService.masterPasswordHash; + await this.apiService.postTwoFactorEmail(emailReq); + } + + if (twoFactorToken == null) { + if (this.canInteract) { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "input", + name: "token", + message: "Two-step login code:", + }); + twoFactorToken = answer.token; + } + if (twoFactorToken == null || twoFactorToken === "") { + return Response.badRequest("Code is required."); + } + } + + response = await this.authService.logInTwoFactor( + new TokenRequestTwoFactor(selectedProvider.type, twoFactorToken), + null + ); + } + + if (response.captchaSiteKey) { + const twoFactorRequest = new TokenRequestTwoFactor(selectedProvider.type, twoFactorToken); + const handledResponse = await this.handleCaptchaRequired(twoFactorRequest); + + // Error Response + if (handledResponse instanceof Response) { + return handledResponse; + } else { + response = handledResponse; + } + } + + if (response.requiresTwoFactor) { + return Response.error("Login failed."); + } + + if (response.resetMasterPassword) { + return Response.error( + "In order to log in with SSO from the CLI, you must first log in" + + " through the web vault to set your master password." + ); + } + + // Handle Updating Temp Password if NOT using an API Key for authentication + if (response.forcePasswordReset && clientId == null && clientSecret == null) { + return await this.updateTempPassword(); + } + + return await this.handleSuccessResponse(); + } catch (e) { + return Response.error(e); + } + } + + private async handleSuccessResponse(): Promise { + if (this.success != null) { + const res = await this.success(); + return Response.success(res); + } else { + const res = new MessageResponse("You are logged in!", null); + return Response.success(res); + } + } + + private async updateTempPassword(error?: string): Promise { + // If no interaction available, alert user to use web vault + if (!this.canInteract) { + await this.logout(); + this.authService.logOut(() => { + /* Do nothing */ + }); + return Response.error( + new MessageResponse( + "An organization administrator recently changed your master password. In order to access the vault, you must update your master password now via the web vault. You have been logged out.", + null + ) + ); + } + + if (this.email == null || this.email === "undefined") { + this.email = await this.stateService.getEmail(); + } + + // Get New Master Password + const baseMessage = + "An organization administrator recently changed your master password. In order to access the vault, you must update your master password now.\n" + + "Master password: "; + const firstMessage = error != null ? error + baseMessage : baseMessage; + const mp: inquirer.Answers = await inquirer.createPromptModule({ output: process.stderr })({ + type: "password", + name: "password", + message: firstMessage, + }); + const masterPassword = mp.password; + + // Master Password Validation + if (masterPassword == null || masterPassword === "") { + return this.updateTempPassword("Master password is required.\n"); + } + + if (masterPassword.length < 8) { + return this.updateTempPassword("Master password must be at least 8 characters long.\n"); + } + + // Strength & Policy Validation + const strengthResult = this.passwordGenerationService.passwordStrength( + masterPassword, + this.getPasswordStrengthUserInput() + ); + + // Get New Master Password Re-type + const reTypeMessage = "Re-type New Master password (Strength: " + strengthResult.score + ")"; + const retype: inquirer.Answers = await inquirer.createPromptModule({ output: process.stderr })({ + type: "password", + name: "password", + message: reTypeMessage, + }); + const masterPasswordRetype = retype.password; + + // Re-type Validation + if (masterPassword !== masterPasswordRetype) { + return this.updateTempPassword("Master password confirmation does not match.\n"); + } + + // Get Hint (optional) + const hint: inquirer.Answers = await inquirer.createPromptModule({ output: process.stderr })({ + type: "input", + name: "input", + message: "Master Password Hint (optional):", + }); + const masterPasswordHint = hint.input; + + // Retrieve details for key generation + const enforcedPolicyOptions = await this.policyService.getMasterPasswordPolicyOptions(); + const kdf = await this.stateService.getKdfType(); + const kdfIterations = await this.stateService.getKdfIterations(); + + if ( + enforcedPolicyOptions != null && + !this.policyService.evaluateMasterPassword( + strengthResult.score, + masterPassword, + enforcedPolicyOptions + ) + ) { + return this.updateTempPassword( + "Your new master password does not meet the policy requirements.\n" + ); + } + + try { + // Create new key and hash new password + const newKey = await this.cryptoService.makeKey( + masterPassword, + this.email.trim().toLowerCase(), + kdf, + kdfIterations + ); + const newPasswordHash = await this.cryptoService.hashPassword(masterPassword, newKey); + + // Grab user's current enc key + const userEncKey = await this.cryptoService.getEncKey(); + + // Create new encKey for the User + const newEncKey = await this.cryptoService.remakeEncKey(newKey, userEncKey); + + // Create request + const request = new UpdateTempPasswordRequest(); + request.key = newEncKey[1].encryptedString; + request.newMasterPasswordHash = newPasswordHash; + request.masterPasswordHint = masterPasswordHint; + + // Update user's password + await this.apiService.putUpdateTempPassword(request); + return this.handleSuccessResponse(); + } catch (e) { + await this.logout(); + this.authService.logOut(() => { + /* Do nothing */ + }); + return Response.error(e); + } + } + + private async handleCaptchaRequired( + twoFactorRequest: TokenRequestTwoFactor, + credentials: PasswordLogInCredentials = null + ): Promise { + const badCaptcha = Response.badRequest( + "Your authentication request has been flagged and will require user interaction to proceed.\n" + + "Please use your API key to validate this request and ensure BW_CLIENTSECRET is correct, if set.\n" + + "(https://bitwarden.com/help/cli-auth-challenges)" + ); + + try { + const captchaClientSecret = await this.apiClientSecret(true); + if (Utils.isNullOrWhitespace(captchaClientSecret)) { + return badCaptcha; + } + + let authResultResponse: AuthResult = null; + if (credentials != null) { + credentials.captchaToken = captchaClientSecret; + credentials.twoFactor = twoFactorRequest; + authResultResponse = await this.authService.logIn(credentials); + } else { + authResultResponse = await this.authService.logInTwoFactor( + twoFactorRequest, + captchaClientSecret + ); + } + + return authResultResponse; + } catch (e) { + if ( + e instanceof ErrorResponse || + (e.constructor.name === ErrorResponse.name && + (e as ErrorResponse).message.includes("Captcha is invalid")) + ) { + return badCaptcha; + } else { + return Response.error(e); + } + } + } + + private getPasswordStrengthUserInput() { + let userInput: string[] = []; + const atPosition = this.email.indexOf("@"); + if (atPosition > -1) { + userInput = userInput.concat( + this.email + .substr(0, atPosition) + .trim() + .toLowerCase() + .split(/[^A-Za-z0-9]/) + ); + } + return userInput; + } + + private async apiClientId(): Promise { + let clientId: string = null; + + const storedClientId: string = process.env.BW_CLIENTID; + if (storedClientId == null) { + if (this.canInteract) { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "input", + name: "clientId", + message: "client_id:", + }); + clientId = answer.clientId; + } else { + clientId = null; + } + } else { + clientId = storedClientId; + } + + return clientId; + } + + private async apiClientSecret(isAdditionalAuthentication = false): Promise { + const additionalAuthenticationMessage = "Additional authentication required.\nAPI key "; + let clientSecret: string = null; + + const storedClientSecret: string = this.clientSecret || process.env.BW_CLIENTSECRET; + if (this.canInteract && storedClientSecret == null) { + const answer: inquirer.Answers = await inquirer.createPromptModule({ + output: process.stderr, + })({ + type: "input", + name: "clientSecret", + message: + (isAdditionalAuthentication ? additionalAuthenticationMessage : "") + "client_secret:", + }); + clientSecret = answer.clientSecret; + } else { + clientSecret = storedClientSecret; + } + + return clientSecret; + } + + private async apiIdentifiers(): Promise<{ clientId: string; clientSecret: string }> { + return { + clientId: await this.apiClientId(), + clientSecret: await this.apiClientSecret(), + }; + } + + private async openSsoPrompt( + codeChallenge: string, + state: string + ): Promise<{ ssoCode: string; orgIdentifier: string }> { + return new Promise((resolve, reject) => { + const callbackServer = http.createServer((req, res) => { + const urlString = "http://localhost" + req.url; + const url = new URL(urlString); + const code = url.searchParams.get("code"); + const receivedState = url.searchParams.get("state"); + const orgIdentifier = this.getOrgIdentifierFromState(receivedState); + res.setHeader("Content-Type", "text/html"); + if (code != null && receivedState != null && this.checkState(receivedState, state)) { + res.writeHead(200); + res.end( + "Success | Bitwarden CLI" + + "

Successfully authenticated with the Bitwarden CLI

" + + "

You may now close this tab and return to the terminal.

" + + "" + ); + callbackServer.close(() => + resolve({ + ssoCode: code, + orgIdentifier: orgIdentifier, + }) + ); + } else { + res.writeHead(400); + res.end( + "Failed | Bitwarden CLI" + + "

Something went wrong logging into the Bitwarden CLI

" + + "

You may now close this tab and return to the terminal.

" + + "" + ); + callbackServer.close(() => reject()); + } + }); + let foundPort = false; + const webUrl = this.environmentService.getWebVaultUrl(); + for (let port = 8065; port <= 8070; port++) { + try { + this.ssoRedirectUri = "http://localhost:" + port; + callbackServer.listen(port, () => { + this.platformUtilsService.launchUri( + webUrl + + "/#/sso?clientId=" + + this.clientId + + "&redirectUri=" + + encodeURIComponent(this.ssoRedirectUri) + + "&state=" + + state + + "&codeChallenge=" + + codeChallenge + ); + }); + foundPort = true; + break; + } catch { + // Ignore error since we run the same command up to 5 times. + } + } + if (!foundPort) { + reject(); + } + }); + } + + private getOrgIdentifierFromState(state: string): string { + if (state === null || state === undefined) { + return null; + } + + const stateSplit = state.split("_identifier="); + return stateSplit.length > 1 ? stateSplit[1] : null; + } + + private checkState(state: string, checkState: string): boolean { + if (state === null || state === undefined) { + return false; + } + if (checkState === null || checkState === undefined) { + return false; + } + + const stateSplit = state.split("_identifier="); + const checkStateSplit = checkState.split("_identifier="); + return stateSplit[0] === checkStateSplit[0]; + } +} diff --git a/libs/node/src/cli/commands/logout.command.ts b/libs/node/src/cli/commands/logout.command.ts new file mode 100644 index 0000000000..6074ba9cf9 --- /dev/null +++ b/libs/node/src/cli/commands/logout.command.ts @@ -0,0 +1,22 @@ +import { AuthService } from "jslib-common/abstractions/auth.service"; +import { I18nService } from "jslib-common/abstractions/i18n.service"; + +import { Response } from "../models/response"; +import { MessageResponse } from "../models/response/messageResponse"; + +export class LogoutCommand { + constructor( + private authService: AuthService, + private i18nService: I18nService, + private logoutCallback: () => Promise + ) {} + + async run() { + await this.logoutCallback(); + this.authService.logOut(() => { + /* Do nothing */ + }); + const res = new MessageResponse("You have logged out.", null); + return Response.success(res); + } +} diff --git a/libs/node/src/cli/commands/update.command.ts b/libs/node/src/cli/commands/update.command.ts new file mode 100644 index 0000000000..1b9408a35f --- /dev/null +++ b/libs/node/src/cli/commands/update.command.ts @@ -0,0 +1,104 @@ +import * as fetch from "node-fetch"; + +import { I18nService } from "jslib-common/abstractions/i18n.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; + +import { Response } from "../models/response"; +import { MessageResponse } from "../models/response/messageResponse"; + +export class UpdateCommand { + inPkg = false; + + constructor( + private platformUtilsService: PlatformUtilsService, + private i18nService: I18nService, + private repoName: string, + private executableName: string, + private showExtendedMessage: boolean + ) { + this.inPkg = !!(process as any).pkg; + } + + async run(): Promise { + const currentVersion = await this.platformUtilsService.getApplicationVersion(); + + const response = await fetch.default( + "https://api.github.com/repos/bitwarden/" + this.repoName + "/releases/latest" + ); + if (response.status === 200) { + const responseJson = await response.json(); + const res = new MessageResponse(null, null); + + const tagName: string = responseJson.tag_name; + if (tagName === "v" + currentVersion) { + res.title = "No update available."; + res.noColor = true; + return Response.success(res); + } + + let downloadUrl: string = null; + if (responseJson.assets != null) { + for (const a of responseJson.assets) { + const download: string = a.browser_download_url; + if (download == null) { + continue; + } + + if (download.indexOf(".zip") === -1) { + continue; + } + + if ( + process.platform === "win32" && + download.indexOf(this.executableName + "-windows") > -1 + ) { + downloadUrl = download; + break; + } else if ( + process.platform === "darwin" && + download.indexOf(this.executableName + "-macos") > -1 + ) { + downloadUrl = download; + break; + } else if ( + process.platform === "linux" && + download.indexOf(this.executableName + "-linux") > -1 + ) { + downloadUrl = download; + break; + } + } + } + + res.title = "A new version is available: " + tagName; + if (downloadUrl == null) { + downloadUrl = "https://github.com/bitwarden/" + this.repoName + "/releases"; + } else { + res.raw = downloadUrl; + } + res.message = ""; + if (responseJson.body != null && responseJson.body !== "") { + res.message = responseJson.body + "\n\n"; + } + + res.message += "You can download this update at " + downloadUrl; + + if (this.showExtendedMessage) { + if (this.inPkg) { + res.message += + "\n\nIf you installed this CLI through a package manager " + + "you should probably update using its update command instead."; + } else { + res.message += + "\n\nIf you installed this CLI through NPM " + + "you should update using `npm install -g @bitwarden/" + + this.repoName + + "`"; + } + } + return Response.success(res); + } else { + return Response.error("Error contacting update API: " + response.status); + } + } +} diff --git a/libs/node/src/cli/models/response.ts b/libs/node/src/cli/models/response.ts new file mode 100644 index 0000000000..d768c51fde --- /dev/null +++ b/libs/node/src/cli/models/response.ts @@ -0,0 +1,50 @@ +import { BaseResponse } from "./response/baseResponse"; + +export class Response { + static error(error: any, data?: any): Response { + const res = new Response(); + res.success = false; + if (typeof error === "string") { + res.message = error; + } else { + res.message = + error.message != null + ? error.message + : error.toString() === "[object Object]" + ? JSON.stringify(error) + : error.toString(); + } + res.data = data; + return res; + } + + static notFound(): Response { + return Response.error("Not found."); + } + + static badRequest(message: string): Response { + return Response.error(message); + } + + static multipleResults(ids: string[]): Response { + let msg = + "More than one result was found. Try getting a specific object by `id` instead. " + + "The following objects were found:"; + ids.forEach((id) => { + msg += "\n" + id; + }); + return Response.error(msg, ids); + } + + static success(data?: BaseResponse): Response { + const res = new Response(); + res.success = true; + res.data = data; + return res; + } + + success: boolean; + message: string; + errorCode: number; + data: BaseResponse; +} diff --git a/libs/node/src/cli/models/response/baseResponse.ts b/libs/node/src/cli/models/response/baseResponse.ts new file mode 100644 index 0000000000..b0cc57da84 --- /dev/null +++ b/libs/node/src/cli/models/response/baseResponse.ts @@ -0,0 +1,3 @@ +export interface BaseResponse { + object: string; +} diff --git a/libs/node/src/cli/models/response/fileResponse.ts b/libs/node/src/cli/models/response/fileResponse.ts new file mode 100644 index 0000000000..c16b56e091 --- /dev/null +++ b/libs/node/src/cli/models/response/fileResponse.ts @@ -0,0 +1,13 @@ +import { BaseResponse } from "./baseResponse"; + +export class FileResponse implements BaseResponse { + object: string; + data: Buffer; + fileName: string; + + constructor(data: Buffer, fileName: string) { + this.object = "file"; + this.data = data; + this.fileName = fileName; + } +} diff --git a/libs/node/src/cli/models/response/listResponse.ts b/libs/node/src/cli/models/response/listResponse.ts new file mode 100644 index 0000000000..db415bcdb3 --- /dev/null +++ b/libs/node/src/cli/models/response/listResponse.ts @@ -0,0 +1,11 @@ +import { BaseResponse } from "./baseResponse"; + +export class ListResponse implements BaseResponse { + object: string; + data: BaseResponse[]; + + constructor(data: BaseResponse[]) { + this.object = "list"; + this.data = data; + } +} diff --git a/libs/node/src/cli/models/response/messageResponse.ts b/libs/node/src/cli/models/response/messageResponse.ts new file mode 100644 index 0000000000..8612841ac1 --- /dev/null +++ b/libs/node/src/cli/models/response/messageResponse.ts @@ -0,0 +1,15 @@ +import { BaseResponse } from "./baseResponse"; + +export class MessageResponse implements BaseResponse { + object: string; + title: string; + message: string; + raw: string; + noColor = false; + + constructor(title: string, message: string) { + this.object = "message"; + this.title = title; + this.message = message; + } +} diff --git a/libs/node/src/cli/models/response/stringResponse.ts b/libs/node/src/cli/models/response/stringResponse.ts new file mode 100644 index 0000000000..f4becfe84c --- /dev/null +++ b/libs/node/src/cli/models/response/stringResponse.ts @@ -0,0 +1,11 @@ +import { BaseResponse } from "./baseResponse"; + +export class StringResponse implements BaseResponse { + object: string; + data: string; + + constructor(data: string) { + this.object = "string"; + this.data = data; + } +} diff --git a/libs/node/src/cli/services/cliPlatformUtils.service.ts b/libs/node/src/cli/services/cliPlatformUtils.service.ts new file mode 100644 index 0000000000..520170c2cc --- /dev/null +++ b/libs/node/src/cli/services/cliPlatformUtils.service.ts @@ -0,0 +1,166 @@ +import * as child_process from "child_process"; + +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { ClientType } from "jslib-common/enums/clientType"; +import { DeviceType } from "jslib-common/enums/deviceType"; +import { ThemeType } from "jslib-common/enums/themeType"; + +// eslint-disable-next-line +const open = require("open"); + +export class CliPlatformUtilsService implements PlatformUtilsService { + clientType: ClientType; + + private deviceCache: DeviceType = null; + + constructor(clientType: ClientType, private packageJson: any) { + this.clientType = clientType; + } + + getDevice(): DeviceType { + if (!this.deviceCache) { + switch (process.platform) { + case "win32": + this.deviceCache = DeviceType.WindowsDesktop; + break; + case "darwin": + this.deviceCache = DeviceType.MacOsDesktop; + break; + case "linux": + default: + this.deviceCache = DeviceType.LinuxDesktop; + break; + } + } + + return this.deviceCache; + } + + getDeviceString(): string { + const device = DeviceType[this.getDevice()].toLowerCase(); + return device.replace("desktop", ""); + } + + getClientType() { + return this.clientType; + } + + isFirefox() { + return false; + } + + isChrome() { + return false; + } + + isEdge() { + return false; + } + + isOpera() { + return false; + } + + isVivaldi() { + return false; + } + + isSafari() { + return false; + } + + isMacAppStore() { + return false; + } + + isViewOpen() { + return Promise.resolve(false); + } + + launchUri(uri: string, options?: any): void { + if (process.platform === "linux") { + child_process.spawnSync("xdg-open", [uri]); + } else { + open(uri); + } + } + + saveFile(win: Window, blobData: any, blobOptions: any, fileName: string): void { + throw new Error("Not implemented."); + } + + getApplicationVersion(): Promise { + return Promise.resolve(this.packageJson.version); + } + + getApplicationVersionSync(): string { + return this.packageJson.version; + } + + supportsWebAuthn(win: Window) { + return false; + } + + supportsDuo(): boolean { + return false; + } + + showToast( + type: "error" | "success" | "warning" | "info", + title: string, + text: string | string[], + options?: any + ): void { + throw new Error("Not implemented."); + } + + showDialog( + text: string, + title?: string, + confirmText?: string, + cancelText?: string, + type?: string + ): Promise { + throw new Error("Not implemented."); + } + + isDev(): boolean { + return process.env.BWCLI_ENV === "development"; + } + + isSelfHost(): boolean { + return false; + } + + copyToClipboard(text: string, options?: any): void { + throw new Error("Not implemented."); + } + + readFromClipboard(options?: any): Promise { + throw new Error("Not implemented."); + } + + supportsBiometric(): Promise { + return Promise.resolve(false); + } + + authenticateBiometric(): Promise { + return Promise.resolve(false); + } + + getDefaultSystemTheme() { + return Promise.resolve(ThemeType.Light as ThemeType.Light | ThemeType.Dark); + } + + onDefaultSystemThemeChange() { + /* noop */ + } + + getEffectiveTheme() { + return Promise.resolve(ThemeType.Light); + } + + supportsSecureStorage(): boolean { + return false; + } +} diff --git a/libs/node/src/cli/services/consoleLog.service.ts b/libs/node/src/cli/services/consoleLog.service.ts new file mode 100644 index 0000000000..73dfcc5540 --- /dev/null +++ b/libs/node/src/cli/services/consoleLog.service.ts @@ -0,0 +1,22 @@ +import { LogLevelType } from "jslib-common/enums/logLevelType"; +import { ConsoleLogService as BaseConsoleLogService } from "jslib-common/services/consoleLog.service"; + +export class ConsoleLogService extends BaseConsoleLogService { + constructor(isDev: boolean, filter: (level: LogLevelType) => boolean = null) { + super(isDev, filter); + } + + write(level: LogLevelType, message: string) { + if (this.filter != null && this.filter(level)) { + return; + } + + if (process.env.BW_RESPONSE === "true") { + // eslint-disable-next-line + console.error(message); + return; + } + + super.write(level, message); + } +} diff --git a/libs/node/src/globals.d.ts b/libs/node/src/globals.d.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/libs/node/src/services/lowdbStorage.service.ts b/libs/node/src/services/lowdbStorage.service.ts new file mode 100644 index 0000000000..e78fe2e49a --- /dev/null +++ b/libs/node/src/services/lowdbStorage.service.ts @@ -0,0 +1,148 @@ +import * as fs from "fs"; +import * as path from "path"; + +import * as lowdb from "lowdb"; +import * as FileSync from "lowdb/adapters/FileSync"; + +import { LogService } from "jslib-common/abstractions/log.service"; +import { StorageService } from "jslib-common/abstractions/storage.service"; +import { NodeUtils } from "jslib-common/misc/nodeUtils"; +import { sequentialize } from "jslib-common/misc/sequentialize"; +import { Utils } from "jslib-common/misc/utils"; + +export class LowdbStorageService implements StorageService { + protected dataFilePath: string; + private db: lowdb.LowdbSync; + private defaults: any; + private ready = false; + + constructor( + protected logService: LogService, + defaults?: any, + private dir?: string, + private allowCache = false + ) { + this.defaults = defaults; + } + + @sequentialize(() => "lowdbStorageInit") + async init() { + if (this.ready) { + return; + } + + this.logService.info("Initializing lowdb storage service."); + let adapter: lowdb.AdapterSync; + if (Utils.isNode && this.dir != null) { + if (!fs.existsSync(this.dir)) { + this.logService.warning(`Could not find dir, "${this.dir}"; creating it instead.`); + NodeUtils.mkdirpSync(this.dir, "700"); + this.logService.info(`Created dir "${this.dir}".`); + } + this.dataFilePath = path.join(this.dir, "data.json"); + if (!fs.existsSync(this.dataFilePath)) { + this.logService.warning( + `Could not find data file, "${this.dataFilePath}"; creating it instead.` + ); + fs.writeFileSync(this.dataFilePath, "", { mode: 0o600 }); + fs.chmodSync(this.dataFilePath, 0o600); + this.logService.info(`Created data file "${this.dataFilePath}" with chmod 600.`); + } else { + this.logService.info(`db file "${this.dataFilePath} already exists"; using existing db`); + } + await this.lockDbFile(() => { + adapter = new FileSync(this.dataFilePath); + }); + } + try { + this.logService.info("Attempting to create lowdb storage adapter."); + this.db = lowdb(adapter); + this.logService.info("Successfully created lowdb storage adapter."); + } catch (e) { + if (e instanceof SyntaxError) { + this.logService.warning( + `Error creating lowdb storage adapter, "${e.message}"; emptying data file.` + ); + if (fs.existsSync(this.dataFilePath)) { + const backupPath = this.dataFilePath + ".bak"; + this.logService.warning(`Writing backup of data file to ${backupPath}`); + await fs.copyFile(this.dataFilePath, backupPath, () => { + this.logService.warning( + `Error while creating data file backup, "${e.message}". No backup may have been created.` + ); + }); + } + adapter.write({}); + this.db = lowdb(adapter); + } else { + this.logService.error(`Error creating lowdb storage adapter, "${e.message}".`); + throw e; + } + } + + if (this.defaults != null) { + this.lockDbFile(() => { + this.logService.info("Writing defaults."); + this.readForNoCache(); + this.db.defaults(this.defaults).write(); + this.logService.info("Successfully wrote defaults to db."); + }); + } + + this.ready = true; + } + + async get(key: string): Promise { + await this.waitForReady(); + return this.lockDbFile(() => { + this.readForNoCache(); + const val = this.db.get(key).value(); + this.logService.debug(`Successfully read ${key} from db`); + if (val == null) { + return null; + } + return val as T; + }); + } + + has(key: string): Promise { + return this.get(key).then((v) => v != null); + } + + async save(key: string, obj: any): Promise { + await this.waitForReady(); + return this.lockDbFile(() => { + this.readForNoCache(); + this.db.set(key, obj).write(); + this.logService.debug(`Successfully wrote ${key} to db`); + return; + }); + } + + async remove(key: string): Promise { + await this.waitForReady(); + return this.lockDbFile(() => { + this.readForNoCache(); + this.db.unset(key).write(); + this.logService.debug(`Successfully removed ${key} from db`); + return; + }); + } + + protected async lockDbFile(action: () => T): Promise { + // Lock methods implemented in clients + return Promise.resolve(action()); + } + + private readForNoCache() { + if (!this.allowCache) { + this.db.read(); + } + } + + private async waitForReady() { + if (!this.ready) { + await this.init(); + } + } +} diff --git a/libs/node/src/services/nodeApi.service.ts b/libs/node/src/services/nodeApi.service.ts new file mode 100644 index 0000000000..7dd0341213 --- /dev/null +++ b/libs/node/src/services/nodeApi.service.ts @@ -0,0 +1,43 @@ +import * as FormData from "form-data"; +import { HttpsProxyAgent } from "https-proxy-agent"; +import * as fe from "node-fetch"; + +import { AppIdService } from "jslib-common/abstractions/appId.service"; +import { EnvironmentService } from "jslib-common/abstractions/environment.service"; +import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service"; +import { TokenService } from "jslib-common/abstractions/token.service"; +import { ApiService } from "jslib-common/services/api.service"; + +(global as any).fetch = fe.default; +(global as any).Request = fe.Request; +(global as any).Response = fe.Response; +(global as any).Headers = fe.Headers; +(global as any).FormData = FormData; + +export class NodeApiService extends ApiService { + constructor( + tokenService: TokenService, + platformUtilsService: PlatformUtilsService, + environmentService: EnvironmentService, + appIdService: AppIdService, + logoutCallback: (expired: boolean) => Promise, + customUserAgent: string = null + ) { + super( + tokenService, + platformUtilsService, + environmentService, + appIdService, + logoutCallback, + customUserAgent + ); + } + + nativeFetch(request: Request): Promise { + const proxy = process.env.http_proxy || process.env.https_proxy; + if (proxy) { + (request as any).agent = new HttpsProxyAgent(proxy); + } + return fetch(request); + } +} diff --git a/libs/node/src/services/nodeCryptoFunction.service.ts b/libs/node/src/services/nodeCryptoFunction.service.ts new file mode 100644 index 0000000000..90a045740e --- /dev/null +++ b/libs/node/src/services/nodeCryptoFunction.service.ts @@ -0,0 +1,301 @@ +import * as crypto from "crypto"; + +import * as forge from "node-forge"; + +import { CryptoFunctionService } from "jslib-common/abstractions/cryptoFunction.service"; +import { Utils } from "jslib-common/misc/utils"; +import { DecryptParameters } from "jslib-common/models/domain/decryptParameters"; +import { SymmetricCryptoKey } from "jslib-common/models/domain/symmetricCryptoKey"; + +export class NodeCryptoFunctionService implements CryptoFunctionService { + pbkdf2( + password: string | ArrayBuffer, + salt: string | ArrayBuffer, + algorithm: "sha256" | "sha512", + iterations: number + ): Promise { + const len = algorithm === "sha256" ? 32 : 64; + const nodePassword = this.toNodeValue(password); + const nodeSalt = this.toNodeValue(salt); + return new Promise((resolve, reject) => { + crypto.pbkdf2(nodePassword, nodeSalt, iterations, len, algorithm, (error, key) => { + if (error != null) { + reject(error); + } else { + resolve(this.toArrayBuffer(key)); + } + }); + }); + } + + // ref: https://tools.ietf.org/html/rfc5869 + async hkdf( + ikm: ArrayBuffer, + salt: string | ArrayBuffer, + info: string | ArrayBuffer, + outputByteSize: number, + algorithm: "sha256" | "sha512" + ): Promise { + const saltBuf = this.toArrayBuffer(salt); + const prk = await this.hmac(ikm, saltBuf, algorithm); + return this.hkdfExpand(prk, info, outputByteSize, algorithm); + } + + // ref: https://tools.ietf.org/html/rfc5869 + async hkdfExpand( + prk: ArrayBuffer, + info: string | ArrayBuffer, + outputByteSize: number, + algorithm: "sha256" | "sha512" + ): Promise { + const hashLen = algorithm === "sha256" ? 32 : 64; + if (outputByteSize > 255 * hashLen) { + throw new Error("outputByteSize is too large."); + } + const prkArr = new Uint8Array(prk); + if (prkArr.length < hashLen) { + throw new Error("prk is too small."); + } + const infoBuf = this.toArrayBuffer(info); + const infoArr = new Uint8Array(infoBuf); + let runningOkmLength = 0; + let previousT = new Uint8Array(0); + const n = Math.ceil(outputByteSize / hashLen); + const okm = new Uint8Array(n * hashLen); + for (let i = 0; i < n; i++) { + const t = new Uint8Array(previousT.length + infoArr.length + 1); + t.set(previousT); + t.set(infoArr, previousT.length); + t.set([i + 1], t.length - 1); + previousT = new Uint8Array(await this.hmac(t.buffer, prk, algorithm)); + okm.set(previousT, runningOkmLength); + runningOkmLength += previousT.length; + if (runningOkmLength >= outputByteSize) { + break; + } + } + return okm.slice(0, outputByteSize).buffer; + } + + hash( + value: string | ArrayBuffer, + algorithm: "sha1" | "sha256" | "sha512" | "md5" + ): Promise { + const nodeValue = this.toNodeValue(value); + const hash = crypto.createHash(algorithm); + hash.update(nodeValue); + return Promise.resolve(this.toArrayBuffer(hash.digest())); + } + + hmac( + value: ArrayBuffer, + key: ArrayBuffer, + algorithm: "sha1" | "sha256" | "sha512" + ): Promise { + const nodeValue = this.toNodeBuffer(value); + const nodeKey = this.toNodeBuffer(key); + const hmac = crypto.createHmac(algorithm, nodeKey); + hmac.update(nodeValue); + return Promise.resolve(this.toArrayBuffer(hmac.digest())); + } + + async compare(a: ArrayBuffer, b: ArrayBuffer): Promise { + const key = await this.randomBytes(32); + const mac1 = await this.hmac(a, key, "sha256"); + const mac2 = await this.hmac(b, key, "sha256"); + if (mac1.byteLength !== mac2.byteLength) { + return false; + } + + const arr1 = new Uint8Array(mac1); + const arr2 = new Uint8Array(mac2); + for (let i = 0; i < arr2.length; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + + return true; + } + + hmacFast( + value: ArrayBuffer, + key: ArrayBuffer, + algorithm: "sha1" | "sha256" | "sha512" + ): Promise { + return this.hmac(value, key, algorithm); + } + + compareFast(a: ArrayBuffer, b: ArrayBuffer): Promise { + return this.compare(a, b); + } + + aesEncrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + const nodeData = this.toNodeBuffer(data); + const nodeIv = this.toNodeBuffer(iv); + const nodeKey = this.toNodeBuffer(key); + const cipher = crypto.createCipheriv("aes-256-cbc", nodeKey, nodeIv); + const encBuf = Buffer.concat([cipher.update(nodeData), cipher.final()]); + return Promise.resolve(this.toArrayBuffer(encBuf)); + } + + aesDecryptFastParameters( + data: string, + iv: string, + mac: string, + key: SymmetricCryptoKey + ): DecryptParameters { + const p = new DecryptParameters(); + p.encKey = key.encKey; + p.data = Utils.fromB64ToArray(data).buffer; + p.iv = Utils.fromB64ToArray(iv).buffer; + + const macData = new Uint8Array(p.iv.byteLength + p.data.byteLength); + macData.set(new Uint8Array(p.iv), 0); + macData.set(new Uint8Array(p.data), p.iv.byteLength); + p.macData = macData.buffer; + + if (key.macKey != null) { + p.macKey = key.macKey; + } + if (mac != null) { + p.mac = Utils.fromB64ToArray(mac).buffer; + } + + return p; + } + + async aesDecryptFast(parameters: DecryptParameters): Promise { + const decBuf = await this.aesDecrypt(parameters.data, parameters.iv, parameters.encKey); + return Utils.fromBufferToUtf8(decBuf); + } + + aesDecrypt(data: ArrayBuffer, iv: ArrayBuffer, key: ArrayBuffer): Promise { + const nodeData = this.toNodeBuffer(data); + const nodeIv = this.toNodeBuffer(iv); + const nodeKey = this.toNodeBuffer(key); + const decipher = crypto.createDecipheriv("aes-256-cbc", nodeKey, nodeIv); + const decBuf = Buffer.concat([decipher.update(nodeData), decipher.final()]); + return Promise.resolve(this.toArrayBuffer(decBuf)); + } + + rsaEncrypt( + data: ArrayBuffer, + publicKey: ArrayBuffer, + algorithm: "sha1" | "sha256" + ): Promise { + if (algorithm === "sha256") { + throw new Error("Node crypto does not support RSA-OAEP SHA-256"); + } + + const pem = this.toPemPublicKey(publicKey); + const decipher = crypto.publicEncrypt(pem, this.toNodeBuffer(data)); + return Promise.resolve(this.toArrayBuffer(decipher)); + } + + rsaDecrypt( + data: ArrayBuffer, + privateKey: ArrayBuffer, + algorithm: "sha1" | "sha256" + ): Promise { + if (algorithm === "sha256") { + throw new Error("Node crypto does not support RSA-OAEP SHA-256"); + } + + const pem = this.toPemPrivateKey(privateKey); + const decipher = crypto.privateDecrypt(pem, this.toNodeBuffer(data)); + return Promise.resolve(this.toArrayBuffer(decipher)); + } + + rsaExtractPublicKey(privateKey: ArrayBuffer): Promise { + const privateKeyByteString = Utils.fromBufferToByteString(privateKey); + const privateKeyAsn1 = forge.asn1.fromDer(privateKeyByteString); + const forgePrivateKey: any = forge.pki.privateKeyFromAsn1(privateKeyAsn1); + const forgePublicKey = (forge.pki as any).setRsaPublicKey(forgePrivateKey.n, forgePrivateKey.e); + const publicKeyAsn1 = forge.pki.publicKeyToAsn1(forgePublicKey); + const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).data; + const publicKeyArray = Utils.fromByteStringToArray(publicKeyByteString); + return Promise.resolve(publicKeyArray.buffer); + } + + async rsaGenerateKeyPair(length: 1024 | 2048 | 4096): Promise<[ArrayBuffer, ArrayBuffer]> { + return new Promise<[ArrayBuffer, ArrayBuffer]>((resolve, reject) => { + forge.pki.rsa.generateKeyPair( + { + bits: length, + workers: -1, + e: 0x10001, // 65537 + }, + (error, keyPair) => { + if (error != null) { + reject(error); + return; + } + + const publicKeyAsn1 = forge.pki.publicKeyToAsn1(keyPair.publicKey); + const publicKeyByteString = forge.asn1.toDer(publicKeyAsn1).getBytes(); + const publicKey = Utils.fromByteStringToArray(publicKeyByteString); + + const privateKeyAsn1 = forge.pki.privateKeyToAsn1(keyPair.privateKey); + const privateKeyPkcs8 = forge.pki.wrapRsaPrivateKey(privateKeyAsn1); + const privateKeyByteString = forge.asn1.toDer(privateKeyPkcs8).getBytes(); + const privateKey = Utils.fromByteStringToArray(privateKeyByteString); + + resolve([publicKey.buffer, privateKey.buffer]); + } + ); + }); + } + + randomBytes(length: number): Promise { + return new Promise((resolve, reject) => { + crypto.randomBytes(length, (error, bytes) => { + if (error != null) { + reject(error); + } else { + resolve(this.toArrayBuffer(bytes)); + } + }); + }); + } + + private toNodeValue(value: string | ArrayBuffer): string | Buffer { + let nodeValue: string | Buffer; + if (typeof value === "string") { + nodeValue = value; + } else { + nodeValue = this.toNodeBuffer(value); + } + return nodeValue; + } + + private toNodeBuffer(value: ArrayBuffer): Buffer { + return Buffer.from(new Uint8Array(value) as any); + } + + private toArrayBuffer(value: Buffer | string | ArrayBuffer): ArrayBuffer { + let buf: ArrayBuffer; + if (typeof value === "string") { + buf = Utils.fromUtf8ToArray(value).buffer; + } else { + buf = new Uint8Array(value).buffer; + } + return buf; + } + + private toPemPrivateKey(key: ArrayBuffer): string { + const byteString = Utils.fromBufferToByteString(key); + const asn1 = forge.asn1.fromDer(byteString); + const privateKey = forge.pki.privateKeyFromAsn1(asn1); + const rsaPrivateKey = forge.pki.privateKeyToAsn1(privateKey); + const privateKeyInfo = forge.pki.wrapRsaPrivateKey(rsaPrivateKey); + return forge.pki.privateKeyInfoToPem(privateKeyInfo); + } + + private toPemPublicKey(key: ArrayBuffer): string { + const byteString = Utils.fromBufferToByteString(key); + const asn1 = forge.asn1.fromDer(byteString); + const publicKey = forge.pki.publicKeyFromAsn1(asn1); + return forge.pki.publicKeyToPem(publicKey); + } +} diff --git a/libs/node/tsconfig.json b/libs/node/tsconfig.json new file mode 100644 index 0000000000..f544d7ce54 --- /dev/null +++ b/libs/node/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "../shared/tsconfig", + "compilerOptions": { + "paths": { + "jslib-common/*": ["../common/src/*"], + "jslib-node/*": ["./src/*"] + } + }, + "include": ["src", "spec"], + "exclude": ["node_modules", "dist"] +} diff --git a/libs/node/tsconfig.spec.json b/libs/node/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/libs/node/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/libs/package-lock.json b/libs/package-lock.json new file mode 100644 index 0000000000..535189c985 --- /dev/null +++ b/libs/package-lock.json @@ -0,0 +1,83 @@ +{ + "name": "@bitwarden/jslib", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@bitwarden/jslib", + "version": "0.0.0", + "license": "GPL-3.0", + "dependencies": { + "@bitwarden/jslib-angular": "file:angular", + "@bitwarden/jslib-common": "file:common", + "@bitwarden/jslib-electron": "file:electron", + "@bitwarden/jslib-node": "file:node" + } + }, + "angular": { + "version": "0.0.0", + "license": "GPL-3.0", + "dependencies": { + "@bitwarden/jslib-common": "file:../common" + } + }, + "common": { + "version": "0.0.0", + "license": "GPL-3.0" + }, + "electron": { + "version": "0.0.0", + "license": "GPL-3.0", + "dependencies": { + "@bitwarden/jslib-common": "file:../common" + } + }, + "node": { + "version": "0.0.0", + "license": "GPL-3.0", + "dependencies": { + "@bitwarden/jslib-common": "file:../common" + } + }, + "node_modules/@bitwarden/jslib-angular": { + "resolved": "angular", + "link": true + }, + "node_modules/@bitwarden/jslib-common": { + "resolved": "common", + "link": true + }, + "node_modules/@bitwarden/jslib-electron": { + "resolved": "electron", + "link": true + }, + "node_modules/@bitwarden/jslib-node": { + "resolved": "node", + "link": true + } + }, + "dependencies": { + "@bitwarden/jslib-angular": { + "version": "file:angular", + "requires": { + "@bitwarden/jslib-common": "file:../common" + } + }, + "@bitwarden/jslib-common": { + "version": "file:common" + }, + "@bitwarden/jslib-electron": { + "version": "file:electron", + "requires": { + "@bitwarden/jslib-common": "file:../common" + } + }, + "@bitwarden/jslib-node": { + "version": "file:node", + "requires": { + "@bitwarden/jslib-common": "file:../common" + } + } + } +} diff --git a/libs/package.json b/libs/package.json new file mode 100644 index 0000000000..652cf2ee06 --- /dev/null +++ b/libs/package.json @@ -0,0 +1,27 @@ +{ + "name": "@bitwarden/jslib", + "version": "0.0.0", + "description": "Common code used across Bitwarden JavaScript projects.", + "keywords": [ + "bitwarden" + ], + "author": "Bitwarden Inc.", + "homepage": "https://bitwarden.com", + "repository": { + "type": "git", + "url": "https://github.com/bitwarden/jslib" + }, + "license": "GPL-3.0", + "scripts": { + "clean": "rimraf dist/**/*", + "test": "jest", + "test:watch": "jest --watch", + "test:watch:all": "jest --watchAll" + }, + "dependencies": { + "@bitwarden/jslib-angular": "file:angular", + "@bitwarden/jslib-common": "file:common", + "@bitwarden/jslib-electron": "file:electron", + "@bitwarden/jslib-node": "file:node" + } +} diff --git a/libs/shared/eslintrc.json b/libs/shared/eslintrc.json new file mode 100644 index 0000000000..70c61bc7c4 --- /dev/null +++ b/libs/shared/eslintrc.json @@ -0,0 +1,29 @@ +{ + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + "prettier" + ], + "rules": { + "@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled + "@typescript-eslint/no-unused-vars": ["warn", { "args": "none" }], + "@typescript-eslint/explicit-member-accessibility": [ + "error", + { + "accessibility": "no-public" + } + ], + "@typescript-eslint/no-this-alias": [ + "error", + { + "allowedNames": ["self"] + } + ], + "no-console": "warn", + "import/no-unresolved": "off" // TODO: Look into turning off once each package is an actual package. + } +} diff --git a/libs/shared/tsconfig.json b/libs/shared/tsconfig.json new file mode 100644 index 0000000000..3a70f6b92c --- /dev/null +++ b/libs/shared/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "pretty": true, + "moduleResolution": "node", + "noImplicitAny": true, + "target": "ES6", + "module": "commonjs", + "lib": ["es5", "es6", "es7", "dom"], + "sourceMap": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "outDir": "dist" + } +} diff --git a/libs/tsconfig.json b/libs/tsconfig.json new file mode 100644 index 0000000000..63b3da4e0f --- /dev/null +++ b/libs/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "pretty": true, + "moduleResolution": "node", + "noImplicitAny": true, + "target": "ES6", + "module": "commonjs", + "lib": ["es5", "es6", "es7", "dom"], + "sourceMap": true, + "declaration": true, + "allowSyntheticDefaultImports": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "declarationDir": "dist/types", + "outDir": "dist", + "baseUrl": ".", + "paths": { + "jslib-common/*": ["common/src/*"], + "jslib-angular/*": ["angular/src/*"], + "jslib-electron/*": ["electron/src/*"], + "jslib-node/*": ["node/src/*"] + }, + "plugins": [ + { + "transform": "typescript-transform-paths" + } + ] + }, + "exclude": ["node_modules", "dist"] +} diff --git a/libs/tsconfig.spec.json b/libs/tsconfig.spec.json new file mode 100644 index 0000000000..fc8520e737 --- /dev/null +++ b/libs/tsconfig.spec.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..836c156eb0 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,37835 @@ +{ + "name": "@bitwarden/clients", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@bitwarden/clients", + "version": "0.0.0", + "license": "GPL-3.0", + "dependencies": { + "@angular/animations": "^12.2.13", + "@angular/cdk": "^12.2.13", + "@angular/common": "^12.2.13", + "@angular/compiler": "^12.2.13", + "@angular/core": "^12.2.13", + "@angular/forms": "^12.2.13", + "@angular/platform-browser": "^12.2.13", + "@angular/platform-browser-dynamic": "^12.2.13", + "@angular/router": "^12.2.13", + "@koa/multer": "^3.0.0", + "@koa/router": "^10.1.1", + "@microsoft/signalr": "^5.0.17", + "@microsoft/signalr-protocol-msgpack": "^5.0.17", + "big-integer": "^1.6.51", + "bootstrap": "4.6.0", + "braintree-web-drop-in": "^1.33.1", + "browser-hrtime": "^1.1.8", + "bufferutil": "^4.0.6", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "core-js": "^3.11.0", + "date-input-polyfill": "^2.14.0", + "duo_web_sdk": "github:duosecurity/duo_web_sdk", + "https-proxy-agent": "^5.0.0", + "inquirer": "^8.2.4", + "jquery": "3.6.0", + "jsdom": "^16.7.0", + "jszip": "^3.10.0", + "koa": "^2.13.4", + "koa-bodyparser": "^4.3.0", + "koa-json": "^2.0.2", + "lowdb": "^1.0.0", + "lunr": "^2.3.9", + "mousetrap": "^1.6.5", + "multer": "^1.4.5-lts.1", + "ngx-infinite-scroll": "^10.0.1", + "ngx-toastr": "14.1.4", + "node-fetch": "^2.6.7", + "node-forge": "^1.3.1", + "nord": "^0.2.1", + "open": "^8.4.0", + "papaparse": "^5.3.2", + "popper.js": "^1.16.1", + "proper-lockfile": "^4.1.2", + "qrious": "4.0.2", + "rxjs": "^7.5.5", + "sweetalert2": "^10.16.6", + "tldjs": "^2.3.1", + "utf-8-validate": "^5.0.9", + "web-animations-js": "^2.3.2", + "whatwg-fetch": "^3.6.2", + "zone.js": "^0.11.4", + "zxcvbn": "^4.4.2" + }, + "devDependencies": { + "@angular/compiler-cli": "^12.2.13", + "@fluffy-spoon/substitute": "^1.208.0", + "@ngtools/webpack": "^12.2.13", + "@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4", + "@types/chrome": "^0.0.139", + "@types/duo_web_sdk": "^2.7.1", + "@types/firefox-webext-browser": "^82.0.0", + "@types/inquirer": "^8.2.1", + "@types/jest": "^27.5.0", + "@types/jquery": "^3.5.14", + "@types/jsdom": "^16.2.14", + "@types/koa": "^2.13.4", + "@types/koa__multer": "^2.0.4", + "@types/koa__router": "^8.0.11", + "@types/koa-bodyparser": "^4.3.7", + "@types/koa-json": "^2.0.20", + "@types/lowdb": "^1.0.11", + "@types/lunr": "^2.3.4", + "@types/mousetrap": "^1.6.8", + "@types/node": "^16.11.12", + "@types/node-fetch": "^2.6.1", + "@types/node-forge": "^1.0.2", + "@types/node-ipc": "^9.2.0", + "@types/papaparse": "^5.3.2", + "@types/proper-lockfile": "^4.1.2", + "@types/retry": "^0.12.2", + "@types/tldjs": "^2.3.1", + "@types/webcrypto": "^0.0.28", + "@types/zxcvbn": "^4.4.1", + "@typescript-eslint/eslint-plugin": "^5.22.0", + "@typescript-eslint/parser": "^5.22.0", + "autoprefixer": "^10.4.7", + "buffer": "^6.0.3", + "clean-webpack-plugin": "^4.0.0", + "concurrently": "^7.2.1", + "copy-webpack-plugin": "^10.0.0", + "cross-env": "^7.0.3", + "css-loader": "^6.5.1", + "del": "^6.0.0", + "electron": "16.2.7", + "electron-builder": "^22.11.7", + "electron-log": "^4.4.7", + "electron-notarize": "^1.2.1", + "electron-rebuild": "^3.2.7", + "electron-reload": "^2.0.0-alpha.1", + "electron-store": "^8.0.1", + "electron-updater": "^5.0.1", + "eslint": "^8.14.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-typescript": "^2.7.1", + "eslint-plugin-import": "^2.26.0", + "forcefocus": "^1.1.0", + "gulp": "^4.0.2", + "gulp-filter": "^7.0.0", + "gulp-if": "^3.0.0", + "gulp-json-editor": "^2.5.5", + "gulp-replace": "^1.1.0", + "gulp-zip": "^5.1.0", + "html-loader": "^3.0.1", + "html-webpack-injector": "^1.1.4", + "html-webpack-plugin": "^5.5.0", + "husky": "^7.0.4", + "jasmine-core": "^3.7.1", + "jasmine-spec-reporter": "^7.0.0", + "jest-preset-angular": "^10.1.0", + "keytar": "^7.9.0", + "lint-staged": "^12.4.1", + "mini-css-extract-plugin": "^2.4.5", + "node-ipc": "^9.2.1", + "pkg": "5.7.0", + "postcss": "^8.4.14", + "postcss-loader": "^6.2.1", + "prettier": "^2.6.2", + "process": "^0.11.10", + "regedit": "^3.0.3", + "rimraf": "^3.0.2", + "sass": "^1.34.1", + "sass-loader": "^12.4.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.24", + "tapable": "^1.1.3", + "ts-loader": "^9.2.5", + "tsconfig-paths-webpack-plugin": "^3.5.2", + "typescript": "4.3.5", + "url": "^0.11.0", + "util": "^0.12.4", + "webcrypto-shim": "^0.1.7", + "webpack": "^5.64.4", + "webpack-cli": "^4.9.1", + "webpack-dev-server": "4.6", + "webpack-node-externals": "^3.0.0" + }, + "engines": { + "node": "~16", + "npm": "~8" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular/animations": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.16.tgz", + "integrity": "sha512-Kf6C7Ta+fCMq5DvT9JNVhBkcECrqFa3wumiC6ssGo5sNaEzXz+tlep9ZgEbqfxSn7gAN7L1DgsbS9u0O6tbUkg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/core": "12.2.16" + } + }, + "node_modules/@angular/cdk": { + "version": "12.2.13", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.13.tgz", + "integrity": "sha512-zSKRhECyFqhingIeyRInIyTvYErt4gWo+x5DQr0b7YLUbU8DZSwWnG4w76Ke2s4U8T7ry1jpJBHoX/e8YBpGMg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "optionalDependencies": { + "parse5": "^5.0.0" + }, + "peerDependencies": { + "@angular/common": "^12.0.0 || ^13.0.0-0", + "@angular/core": "^12.0.0 || ^13.0.0-0", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/common": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.16.tgz", + "integrity": "sha512-FEqTXTEsnbDInqV1yFlm97Tz1OFqZS5t0TUkm8gzXRgpIce/F/jLwAg0u1VQkgOsno6cNm0xTWPoZgu85NI4ug==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/core": "12.2.16", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/compiler": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.16.tgz", + "integrity": "sha512-nsYEw+yu8QyeqPf9nAmG419i1mtGM4v8+U+S3eQHQFXTgJzLymMykWHYu2ETdjUpNSLK6xcIQDBWtWnWSfJjAA==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + } + }, + "node_modules/@angular/compiler-cli": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.16.tgz", + "integrity": "sha512-tlalh8SJvdCWbUPRUR5GamaP+wSc/GuCsoUZpSbcczGKgSlbaEVXUYtVXm8/wuT6Slk2sSEbRs7tXGF2i7qxVw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.11.0", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.2.0", + "yargs": "^17.0.0" + }, + "bin": { + "ivy-ngcc": "ngcc/main-ivy-ngcc.js", + "ng-xi18n": "src/extract_i18n.js", + "ngc": "src/main.js", + "ngcc": "ngcc/main-ngcc.js" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/compiler": "12.2.16", + "typescript": ">=4.2.3 <4.4" + } + }, + "node_modules/@angular/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.16.tgz", + "integrity": "sha512-jsmvaRdAfng99z2a9mAmkfcsCE1wm+tBYVDxnc5JquSXznwtncjzcoc2X0J0dzrkCDvzFfpTsZ9vehylytBc+A==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.0.0", + "zone.js": "~0.11.4" + } + }, + "node_modules/@angular/forms": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.16.tgz", + "integrity": "sha512-sb+gpNun5aN7CZfHXS6X7vJcd/0A1P/gRBZpYtQTzBYnqEFCOFIvR62eb05aHQ4JhgKaSPpIXrbz/bAwY/njZw==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/common": "12.2.16", + "@angular/core": "12.2.16", + "@angular/platform-browser": "12.2.16", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@angular/platform-browser": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.16.tgz", + "integrity": "sha512-T855ppLeQO6hRHi7lGf5fwPoUVt+c0h2rgkV5jHElc3ylaGnhecmZc6fnWLX4pw82TMJUgUV88CY8JCFabJWwg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/animations": "12.2.16", + "@angular/common": "12.2.16", + "@angular/core": "12.2.16" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.16.tgz", + "integrity": "sha512-XGxoACAMW/bc3atiVRpaiYwU4LkobYwVzwlxTT/BxOfsdt8ILb5wU8Fx1TMKNECOQHSGdK0qqhch4pTBZ3cb2g==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/common": "12.2.16", + "@angular/compiler": "12.2.16", + "@angular/core": "12.2.16", + "@angular/platform-browser": "12.2.16" + } + }, + "node_modules/@angular/router": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-12.2.16.tgz", + "integrity": "sha512-LuFXSMIvX/VrB4jbYhigG2Y2pGQ9ULsSBUwDWwQCf4kr0eVI37LBJ2Vr74GBEznjgQ0UmWE89E+XYI80UhERTw==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": "^12.14.1 || >=14.0.0" + }, + "peerDependencies": { + "@angular/common": "12.2.16", + "@angular/core": "12.2.16", + "@angular/platform-browser": "12.2.16", + "rxjs": "^6.5.3 || ^7.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", + "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.0", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", + "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", + "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.0", + "@babel/types": "^7.18.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", + "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", + "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", + "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", + "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", + "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", + "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz", + "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.18.0", + "@babel/types": "^7.18.2", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", + "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "peer": true + }, + "node_modules/@braintree/asset-loader": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@braintree/asset-loader/-/asset-loader-0.4.4.tgz", + "integrity": "sha512-uVhXC5dydmngmNVuDiKgfXSlz4kv4x5ytIJodI8N5SY16mRh13m/UmbQ7yH+o8DQqp50qPZ45MUHIZkXKPg85w==", + "dependencies": { + "promise-polyfill": "^8.1.3" + } + }, + "node_modules/@braintree/browser-detection": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@braintree/browser-detection/-/browser-detection-1.12.1.tgz", + "integrity": "sha512-i/54qrax5o/WbJJhsE/7qqKE594/kGhR+xSu/w13rT7Mlr/uITkWDXzxffcKQ6l6FQxK0IG0EfgT6TJpWgZcUQ==" + }, + "node_modules/@braintree/class-list": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@braintree/class-list/-/class-list-0.2.0.tgz", + "integrity": "sha512-iLXJT51jnBFuGvyTAQqZ2uwyEVwdyapyz52F5MK1Uoh2ZOiPJ5hoqI0wncyCP2KfqrgyCpOkkEaLMLb/94unGA==" + }, + "node_modules/@braintree/event-emitter": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@braintree/event-emitter/-/event-emitter-0.4.1.tgz", + "integrity": "sha512-X41357O3OXUDlnwMvS1m0GQEn3zB3s3flOBeg2J5OBvLvdJEIAVpPkblABPtsPrlciDSvfv1aSG5ixHPgFH0Zg==" + }, + "node_modules/@braintree/extended-promise": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@braintree/extended-promise/-/extended-promise-0.4.1.tgz", + "integrity": "sha512-00n7m4z+swWHoFQLHLvrIBIEoxnGUBsl3ogvX79ITpcn8CHczDwtxYy5+RhMoAraRdfN3oB+8QIpN3KOxs2Q7w==" + }, + "node_modules/@braintree/iframer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@braintree/iframer/-/iframer-1.1.0.tgz", + "integrity": "sha512-tVpr7U6u6bqeQlHreEjYMNtnHX62vLnNWziY2kQLqkWhvusPuY5DfuGEIPpWqsd+V/a1slyTQaxK6HWTlH6A/Q==" + }, + "node_modules/@braintree/sanitize-url": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz", + "integrity": "sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==" + }, + "node_modules/@braintree/uuid": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@braintree/uuid/-/uuid-0.1.0.tgz", + "integrity": "sha512-YvZJdlNcK5EnR+7M8AjgEAf4Qx696+FOSYlPfy5ePn80vODtVAUU0FxHnzKZC0og1VbDNQDDiwhthR65D4Na0g==" + }, + "node_modules/@braintree/wrap-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@braintree/wrap-promise/-/wrap-promise-2.1.0.tgz", + "integrity": "sha512-UIrJB+AfKU0CCfbMoWrsGpd2D/hBpY/SGgFI6WRHPOwhaZ3g9rz1weiJ6eb6L9KgVyunT7s2tckcPkbHw+NzeA==" + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@electron/get": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", + "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^9.6.0", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=8.6" + }, + "optionalDependencies": { + "global-agent": "^3.0.0", + "global-tunnel-ng": "^2.7.1" + } + }, + "node_modules/@electron/get/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@electron/universal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", + "integrity": "sha512-zX9O6+jr2NMyAdSkwEUlyltiI4/EBLu2Ls/VD3pUQdi3cAYeYfdQnT2AJJ38HE4QxLccbU13LSpccw1IWlkyag==", + "dev": true, + "dependencies": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.0.3", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.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" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@fluffy-spoon/substitute": { + "version": "1.208.0", + "resolved": "https://registry.npmjs.org/@fluffy-spoon/substitute/-/substitute-1.208.0.tgz", + "integrity": "sha512-BU5vKRoK4OYlKzDtyg4HbtWnUNLOvV0ntqEZIphz+mq2G0HlVFywwJ7M+FbIcnJVDbUReS01FyL5x8R01r7zBg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/substitute-js#section-contribute" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "peer": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "peer": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true, + "peer": true + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "peer": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "peer": true, + "dependencies": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/@jest/types/node_modules/@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@koa/multer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@koa/multer/-/multer-3.0.0.tgz", + "integrity": "sha512-y+OQBmex5D1jIl723gAEUYcAWPEicIXppaAKw/zCMfpllQ08ZNweDPwoCLxEoatqd5pCu2XG6V8dl67JRq3RJw==", + "engines": { + "node": ">= 8" + }, + "peerDependencies": { + "multer": "*" + } + }, + "node_modules/@koa/router": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-10.1.1.tgz", + "integrity": "sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==", + "dependencies": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@microsoft/signalr": { + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-5.0.17.tgz", + "integrity": "sha512-zTjFxjh67WWCe35ZipsqkktM5mM+MsckyyI2ZvFmYWR7ibpUoAyZI1DFdYfwXfsyBdlykDaW84o9lrB+9tDpaA==", + "dependencies": { + "abort-controller": "^3.0.0", + "eventsource": "^1.0.7", + "fetch-cookie": "^0.7.3", + "node-fetch": "^2.6.7", + "ws": "^6.0.0" + } + }, + "node_modules/@microsoft/signalr-protocol-msgpack": { + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/@microsoft/signalr-protocol-msgpack/-/signalr-protocol-msgpack-5.0.17.tgz", + "integrity": "sha512-Gqp1Azw5nFColcwX/eLIs+N2G6/nWtYHZtMccgEv9C1PKMXZEiUPiHmvwbLfywJubtu9cyDie3Q/+VuRc9X5Xg==", + "dependencies": { + "@microsoft/signalr": ">=5.0.17", + "msgpack5": "^4.5.0" + } + }, + "node_modules/@ngtools/webpack": { + "version": "12.2.17", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.17.tgz", + "integrity": "sha512-uaS+2YZgPDW3VmUuwh4/yfIFV1KRVGWefc6xLWIqKRKs6mlRYs65m3ib9dX7CTS4kQMCbhxkxMbpBO2yXlzfvA==", + "dev": true, + "engines": { + "node": "^12.14.1 || >=14.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^12.0.0", + "typescript": "~4.2.3 || ~4.3.2", + "webpack": "^5.30.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodert-win10-rs4/windows.security.credentials.ui": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@nodert-win10-rs4/windows.security.credentials.ui/-/windows.security.credentials.ui-0.4.4.tgz", + "integrity": "sha512-P+EsJw5MCQXTxp7mwXfNDvIzIYsB6ple+HNg01QjPWg/PJfAodPuxL6XM7l0sPtYHsDYnfnvoefZMdZRa2Z1ig==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "nan": "latest" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@scarf/scarf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.1.1.tgz", + "integrity": "sha512-VGbKDbk1RFIaSmdVb0cNjjWJoRWRI/Weo23AjRCC2nryO0iAS8pzsToJfPVPtVs74WHw4L1UTADNdIYRLkirZQ==", + "hasInstallScript": true + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "node_modules/@types/chrome": { + "version": "0.0.139", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.139.tgz", + "integrity": "sha512-YZDKFlSVGFp4zldJlO+PUpxMH8N9vLke0fD6K9PA+TzXxPXu8LBLo5X2dzlOs2N/n+uMdI1lw7OPT1Emop10lQ==", + "dev": true, + "dependencies": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/content-disposition": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.5.tgz", + "integrity": "sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==", + "dev": true + }, + "node_modules/@types/cookies": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", + "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/duo_web_sdk": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@types/duo_web_sdk/-/duo_web_sdk-2.7.1.tgz", + "integrity": "sha512-DePanZjFww36yGSxXwC8B3AsjrrDuPxEcufeh4gTqVsUMpCYByxjX4PERiYZdW0typzKSt9E4I14PPp+PrSIQA==", + "dev": true + }, + "node_modules/@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "node_modules/@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "node_modules/@types/filesystem": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", + "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", + "dev": true, + "dependencies": { + "@types/filewriter": "*" + } + }, + "node_modules/@types/filewriter": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz", + "integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==", + "dev": true + }, + "node_modules/@types/firefox-webext-browser": { + "version": "82.0.1", + "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-82.0.1.tgz", + "integrity": "sha512-odcPKiJ34N8k53clIWen3hLvl09ja7SQ9NqtUbgmqeJ/a/ZRQiF665iXSFPcnl6cBn2XQgEg2lsUUApYNiyj+g==", + "dev": true + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/har-format": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.8.tgz", + "integrity": "sha512-OP6L9VuZNdskgNN3zFQQ54ceYD8OLq5IbqO4VK91ORLfOm7WdT/CiT/pHEBSQEqCInJ2y3O6iCm/zGtPElpgJQ==", + "dev": true + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "node_modules/@types/http-assert": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", + "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==", + "dev": true + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", + "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==", + "dev": true + }, + "node_modules/@types/http-proxy": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", + "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/inquirer": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.1.tgz", + "integrity": "sha512-wKW3SKIUMmltbykg4I5JzCVzUhkuD9trD6efAmYgN2MrSntY0SMRQzEnD3mkyJ/rv9NLbTC7g3hKKE86YwEDLw==", + "dev": true, + "dependencies": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "27.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", + "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", + "dev": true, + "dependencies": { + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" + } + }, + "node_modules/@types/jquery": { + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", + "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", + "dev": true, + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/jsdom": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.14.tgz", + "integrity": "sha512-6BAy1xXEmMuHeAJ4Fv4yXKwBDTGTOseExKE3OaHiNycdHdZw59KfYzrt0DkDluvwmik1HRt6QS7bImxUmpSy+w==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/parse5": "*", + "@types/tough-cookie": "*" + } + }, + "node_modules/@types/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/koa": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz", + "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==", + "dev": true, + "dependencies": { + "@types/accepts": "*", + "@types/content-disposition": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/http-errors": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" + } + }, + "node_modules/@types/koa__multer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/koa__multer/-/koa__multer-2.0.4.tgz", + "integrity": "sha512-WRkshXhE5rpYFUbbtAjyMhdOOSdbu1XX+2AQlRNM6AZtgxd0/WXMU4lrP7e9tk5HWVTWbx8DOOsVBmfHjSGJ4w==", + "dev": true, + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/koa__router": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.11.tgz", + "integrity": "sha512-WXgKWpBsbS14kzmzD9LeFapOIa678h7zvUHxDwXwSx4ETKXhXLVUAToX6jZ/U7EihM7qwyD9W/BZvB0MRu7MTQ==", + "dev": true, + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/koa-bodyparser": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@types/koa-bodyparser/-/koa-bodyparser-4.3.7.tgz", + "integrity": "sha512-21NhEp7LjZm4zbNV5alHHmrNY4J+S7B8lYTO6CzRL8ShTMnl20Gd14dRgVhAxraLaW5iZMofox+BycbuiDvj2Q==", + "dev": true, + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/koa-compose": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", + "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", + "dev": true, + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/koa-json": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/@types/koa-json/-/koa-json-2.0.20.tgz", + "integrity": "sha512-RuQ1Vlpsm/EC5wo2oWCgNnwneixnSQ9aHQAE7nwnbSiCibgfUO2wwSQN6rn8SfF97cRdN9hKAtoc9KSIuiGP6Q==", + "dev": true, + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true + }, + "node_modules/@types/lowdb": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/lowdb/-/lowdb-1.0.11.tgz", + "integrity": "sha512-h99VMxvTuz+VsXUVCCJo4dsps4vbkXwvU71TpmxDoiBU24bJ0VBygIHgmMm+UPoQIFihmV6euRik4z8J7XDJWg==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/lunr": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/lunr/-/lunr-2.3.4.tgz", + "integrity": "sha512-j4x4XJwZvorEUbA519VdQ5b9AOU9TSvfi8tvxMAfP8XzNLtFex7A8vFQwqOx3WACbV0KMXbACV3cZl4/gynQ7g==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "node_modules/@types/mousetrap": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.9.tgz", + "integrity": "sha512-HUAiN65VsRXyFCTicolwb5+I7FM6f72zjMWr+ajGk+YTvzBgXqa2A5U7d+rtsouAkunJ5U4Sb5lNJjo9w+nmXg==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "16.11.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.38.tgz", + "integrity": "sha512-hjO/0K140An3GWDw2HJfq7gko3wWeznbjXgg+rzPdVzhe198hp4x2i1dgveAOEiFKd8sOilAxzoSJiVv5P/CUg==", + "dev": true + }, + "node_modules/@types/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.0.2.tgz", + "integrity": "sha512-J1OkeZGaW0y9Y7xD49Ja8O82B9l5nZDeoYuGWqIOYPAf9LR+xF23k9ILdzv8dH+2H033fx3D5oiA0GlmicI+sg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node-ipc": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@types/node-ipc/-/node-ipc-9.2.0.tgz", + "integrity": "sha512-0v1oucUgINvWPhknecSBE5xkz74sVgeZgiL/LkWXNTSzFaGspEToA4oR56hjza0Jkk6DsS2EiNU3M2R2KQza9A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/papaparse": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.2.tgz", + "integrity": "sha512-BNbCHJkTE4RwmAFkCxEalET4mDvGr/1ld7ZtQ4i/laWI/iiVt+GL07stdvufle4KfywyvloqqpIiJscXNCrKxA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/@types/parse5": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", + "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==", + "dev": true + }, + "node_modules/@types/plist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.2.tgz", + "integrity": "sha512-ULqvZNGMv0zRFvqn8/4LSPtnmN4MfhlPNtJCTpKuIIxGVGZ2rYWzFXrvEBoh9CVyqSE7D6YFRJ1hydLHI6kbWw==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "dev": true, + "peer": true + }, + "node_modules/@types/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-kd4LMvcnpYkspDcp7rmXKedn8iJSCoa331zRRamUp5oanKt/CefbEGPQP7G89enz7sKD4bvsr8mHSsC8j5WOvA==", + "dev": true, + "dependencies": { + "@types/retry": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "node_modules/@types/semver": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", + "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/tldjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@types/tldjs/-/tldjs-2.3.1.tgz", + "integrity": "sha512-BQR04zLE0ve2eNrqxXw/Qp/f6LxvNrj/4A8ZgdQi3SzbBqxFhleI7N4DS/mSjDnODrUaEGgoWg4grAZR1kVj8w==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", + "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", + "dev": true + }, + "node_modules/@types/verror": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.5.tgz", + "integrity": "sha512-9UjMCHK5GPgQRoNbqdLIAvAy0EInuiqbW0PBMtVP6B5B2HQJlvoJHM+KodPZMEjOa5VkSc+5LH7xy+cUzQdmHw==", + "dev": true, + "optional": true + }, + "node_modules/@types/vinyl": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", + "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", + "dev": true, + "dependencies": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } + }, + "node_modules/@types/webcrypto": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/webcrypto/-/webcrypto-0.0.28.tgz", + "integrity": "sha512-jzAoSUvqA+183nJO/Sc73CREQJsv+p77WJdn532GqA3YXQzlwRwHhClVa7U4O8iB2sJSR7G3v6f1mJFNkwA9YQ==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", + "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@types/zxcvbn": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.1.tgz", + "integrity": "sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webpack-cli/configtest": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", + "dev": true, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x", + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/info": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", + "dev": true, + "dependencies": { + "envinfo": "^7.7.3" + }, + "peerDependencies": { + "webpack-cli": "4.x.x" + } + }, + "node_modules/@webpack-cli/serve": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", + "dev": true, + "peerDependencies": { + "webpack-cli": "4.x.x" + }, + "peerDependenciesMeta": { + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/7zip-bin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.1.1.tgz", + "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", + "dev": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "dependencies": { + "ansi-wrap": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==", + "dev": true, + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-builder-bin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.7.1.tgz", + "integrity": "sha512-ql93vEUq6WsstGXD+SBLSIQw6SNnhbDEM0swzgugytMxLp3rT24Ag/jcC80ZHxiPRTdew1niuR7P3/FCrDqIjw==", + "dev": true + }, + "node_modules/app-builder-lib": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.14.13.tgz", + "integrity": "sha512-SufmrtxU+D0Tn948fjEwAOlCN9757UXLkzzTWXMwZKR/5hisvgqeeBepWfphMIE6OkDGz0fbzEhL1P2Pty4XMg==", + "dev": true, + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/universal": "1.0.5", + "@malept/flatpak-bundler": "^0.4.0", + "7zip-bin": "~5.1.1", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.2", + "ejs": "^3.1.6", + "electron-osx-sign": "^0.5.0", + "electron-publish": "22.14.13", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "hosted-git-info": "^4.0.2", + "is-ci": "^3.0.0", + "isbinaryfile": "^4.0.8", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^3.0.4", + "read-config-file": "6.2.0", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.5", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA==", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==", + "dev": true, + "dependencies": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "dependencies": { + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "dependencies": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", + "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asar": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", + "integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", + "dev": true, + "dependencies": { + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + }, + "optionalDependencies": { + "@types/glob": "^7.1.1" + } + }, + "node_modules/asar/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true + }, + "node_modules/async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/atomically": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", + "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", + "dev": true, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "peer": true, + "dependencies": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, + "node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/binaryextensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", + "dev": true, + "engines": { + "node": ">=0.8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true, + "optional": true + }, + "node_modules/bootstrap": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", + "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + }, + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.1" + } + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/braintree-web": { + "version": "3.85.3", + "resolved": "https://registry.npmjs.org/braintree-web/-/braintree-web-3.85.3.tgz", + "integrity": "sha512-slCnjD/YLFDmiOU0vxL7i4uifjRQV5Cw7dSkhRdXiIT+a8iQ7NxtL5FSomv45wuHqgdilZeQ8iB8guIrn6QgwA==", + "dependencies": { + "@braintree/asset-loader": "0.4.4", + "@braintree/browser-detection": "1.12.1", + "@braintree/class-list": "0.2.0", + "@braintree/event-emitter": "0.4.1", + "@braintree/extended-promise": "0.4.1", + "@braintree/iframer": "1.1.0", + "@braintree/sanitize-url": "6.0.0", + "@braintree/uuid": "0.1.0", + "@braintree/wrap-promise": "2.1.0", + "card-validator": "8.1.1", + "credit-card-type": "9.1.0", + "framebus": "5.1.2", + "inject-stylesheet": "5.0.0", + "promise-polyfill": "8.2.3", + "restricted-input": "3.0.5" + } + }, + "node_modules/braintree-web-drop-in": { + "version": "1.33.2", + "resolved": "https://registry.npmjs.org/braintree-web-drop-in/-/braintree-web-drop-in-1.33.2.tgz", + "integrity": "sha512-2iqhHS6UQEvcRAWvI/CQ2OuJLHqXR+6UYBKkaa6T+DXa24/mdwErDTabJHSq8oAebsx3Va+9q06IveJfOoDfqA==", + "dependencies": { + "@braintree/asset-loader": "0.4.4", + "@braintree/browser-detection": "1.12.1", + "@braintree/class-list": "0.2.0", + "@braintree/event-emitter": "0.4.1", + "@braintree/uuid": "0.1.0", + "@braintree/wrap-promise": "2.1.0", + "braintree-web": "3.85.3", + "promise-polyfill": "8.2.3" + } + }, + "node_modules/browser-hrtime": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/browser-hrtime/-/browser-hrtime-1.1.8.tgz", + "integrity": "sha512-kzXheikaJsBtzUBlyVtPIY5r0soQePzjwVwT4IlDpU2RvfB5Py52gpU98M77rgqMCheoSSZvrcrdj3t6cZ3suA==" + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "peer": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "node_modules/bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/builder-util": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.14.13.tgz", + "integrity": "sha512-oePC/qrrUuerhmH5iaCJzPRAKlSBylrhzuAJmRQClTyWnZUv6jbaHh+VoHMbEiE661wrj2S2aV7/bQh12cj1OA==", + "dev": true, + "dependencies": { + "@types/debug": "^4.1.6", + "@types/fs-extra": "^9.0.11", + "7zip-bin": "~5.1.1", + "app-builder-bin": "3.7.1", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "8.9.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", + "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", + "dev": true, + "dependencies": { + "debug": "^4.3.2", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "dependencies": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001346", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001346.tgz", + "integrity": "sha512-q6ibZUO2t88QCIPayP/euuDREq+aMAxFE5S70PkrLh0iTDj/zEhgvJRKC2+CvXY6EWc6oQwUR48lL5vCW6jiXQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "node_modules/card-validator": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/card-validator/-/card-validator-8.1.1.tgz", + "integrity": "sha512-cN4FsKwoTfTFnqPwVc7TQLSsH/QMDB3n/gWm0XelcApz4sKipnOQ6k33sa3bWsNnnIpgs7eXOF+mUV2UQAX2Sw==", + "dependencies": { + "credit-card-type": "^9.1.0" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true + }, + "node_modules/ci-info": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.1.tgz", + "integrity": "sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==", + "dev": true + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true, + "peer": true + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-css": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", + "integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/clean-webpack-plugin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz", + "integrity": "sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==", + "dev": true, + "dependencies": { + "del": "^4.1.1" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "webpack": ">=4.0.0 <6.0.0" + } + }, + "node_modules/clean-webpack-plugin/node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-webpack-plugin/node_modules/del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clean-webpack-plugin/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-webpack-plugin/node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-webpack-plugin/node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/clean-webpack-plugin/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/clean-webpack-plugin/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clone-deep/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "dev": true + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/co-body": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.1.0.tgz", + "integrity": "sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==", + "dependencies": { + "inflation": "^2.0.0", + "qs": "^6.5.2", + "raw-body": "^2.3.3", + "type-is": "^1.6.16" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true, + "peer": true + }, + "node_modules/collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA==", + "dev": true, + "dependencies": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "dev": true + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compress-brotli": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz", + "integrity": "sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==", + "dev": true, + "dependencies": { + "@types/json-buffer": "~3.0.0", + "json-buffer": "~3.0.1" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/compress-brotli/node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concurrently": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.2.1.tgz", + "integrity": "sha512-7cab/QyqipqghrVr9qZmoWbidu0nHsmxrpNqQ7r/67vfl1DWJElexehQnTH1p+87tDkihaAjM79xTZyBQh7HLw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "date-fns": "^2.16.1", + "lodash": "^4.17.21", + "rxjs": "^6.6.3", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "bin": { + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + } + }, + "node_modules/concurrently/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/concurrently/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/concurrently/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/conf": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/conf/-/conf-10.1.2.tgz", + "integrity": "sha512-o9Fv1Mv+6A0JpoayQ8JleNp3hhkbOJP/Re/Q+QqxMPHPkABVsRjQGWZn9A5GcqLiTNC6d89p2PB5ZhHVDSMwyg==", + "dev": true, + "dependencies": { + "ajv": "^8.6.3", + "ajv-formats": "^2.1.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", + "env-paths": "^2.2.1", + "json-schema-typed": "^7.0.3", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conf/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/conf/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/configstore/node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "node_modules/cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "dependencies": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cookies/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-props": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "dev": true, + "dependencies": { + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + } + }, + "node_modules/copy-to": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==" + }, + "node_modules/copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 12.20.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "dev": true, + "dependencies": { + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.22.8", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", + "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/credit-card-type": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/credit-card-type/-/credit-card-type-9.1.0.tgz", + "integrity": "sha512-CpNFuLxiPFxuZqhSKml3M+t0K/484pMAnfYWH14JoD7OZMnmC0Lmo+P7JX9SobqFpRoo7ifA18kOHdxJywYPEA==" + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/css-loader": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.7", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/date-fns": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "dev": true, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/date-input-polyfill": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/date-input-polyfill/-/date-input-polyfill-2.14.0.tgz", + "integrity": "sha512-LUfuBYYlayDyBbQCIMN1RyrDaTmy5pa3u3jIDoWTXk/7tPgOajZczjWZA2ITd/+lbhtUBM6fhT+Grxs1yYATVA==", + "dependencies": { + "babel-runtime": "^6.11.6" + } + }, + "node_modules/debounce-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", + "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true, + "peer": true + }, + "node_modules/deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==" + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "dependencies": { + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dev": true, + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/dir-compare": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", + "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==", + "dev": true, + "dependencies": { + "buffer-equal": "1.0.0", + "colors": "1.0.3", + "commander": "2.9.0", + "minimatch": "3.0.4" + }, + "bin": { + "dircompare": "src/cli/dircompare.js" + } + }, + "node_modules/dir-compare/node_modules/commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", + "dev": true, + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/dmg-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.14.13.tgz", + "integrity": "sha512-xNOugB6AbIRETeU2uID15sUfjdZZcKdxK8xkFnwIggsM00PJ12JxpLNPTjcRoUnfwj3WrPjilrO64vRMwNItQg==", + "dev": true, + "dependencies": { + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "fs-extra": "^10.0.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.9" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "deprecated": "Disk image license agreements are deprecated by Apple and will probably be removed in a future macOS release. Discussion at: https://github.com/argv-minus-one/dmg-license/issues/11", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true + }, + "node_modules/dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==", + "dev": true, + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "node_modules/duo_web_sdk": { + "version": "2.7.0", + "resolved": "git+ssh://git@github.com/duosecurity/duo_web_sdk.git#f43ff8f1325f8630d0cff1cd9fb0df13d22cf28d", + "license": "SEE LICENSE IN LICENSE" + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==", + "dev": true + }, + "node_modules/duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "node_modules/each-props/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/easy-stack": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", + "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "dependencies": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "bin": { + "editorconfig": "bin/editorconfig" + } + }, + "node_modules/editorconfig/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/editorconfig/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/editorconfig/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/editorconfig/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/electron/-/electron-16.2.7.tgz", + "integrity": "sha512-aZKF3b00+rqW/HGs8lJM5DhPNj+mOfCuhLSiFXV6J9dQCIRhctJTmToOrwXfbCxvXK8as8eQTNl5uSfnHmH6tA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@electron/get": "^1.13.0", + "@types/node": "^14.6.2", + "extract-zip": "^1.0.3" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 8.6" + } + }, + "node_modules/electron-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.14.13.tgz", + "integrity": "sha512-3fgLxqF2TXVKiUPeg74O4V3l0l3j7ERLazo8sUbRkApw0+4iVAf2BJkHsHMaXiigsgCoEzK/F4/rB5rne/VAnw==", + "dev": true, + "dependencies": { + "@types/yargs": "^17.0.1", + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "dmg-builder": "22.14.13", + "fs-extra": "^10.0.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.2.0", + "update-notifier": "^5.1.0", + "yargs": "^17.0.1" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-log": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.4.7.tgz", + "integrity": "sha512-uFZQdgevOp9Fn5lDOrJMU/bmmYxDLZitbIHJM7VXN+cpB59ZnPt1FQL4bOf/Dl2gaIMPYJEfXx38GvJma5iV6A==", + "dev": true + }, + "node_modules/electron-notarize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.1.tgz", + "integrity": "sha512-u/ECWhIrhkSQpZM4cJzVZ5TsmkaqrRo5LDC/KMbGF0sPkm53Ng59+M0zp8QVaql0obfJy9vlVT+4iOkAi2UDlA==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-notarize/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-notarize/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-osx-sign": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz", + "integrity": "sha512-icoRLHzFz/qxzDh/N4Pi2z4yVHurlsCAYQvsCSG7fCedJ4UJXBS6PoQyGH71IfcqKupcKeK7HX/NkyfG+v6vlQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/electron-osx-sign/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/electron-osx-sign/node_modules/isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "dependencies": { + "buffer-alloc": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/electron-osx-sign/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/electron-publish": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.14.13.tgz", + "integrity": "sha512-0oP3QiNj3e8ewOaEpEJV/o6Zrmy2VarVvZ/bH7kyO/S/aJf9x8vQsKVWpsdmSiZ5DJEHgarFIXrnO0ZQf0P9iQ==", + "dev": true, + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "fs-extra": "^10.0.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-rebuild": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.7.tgz", + "integrity": "sha512-WvaW1EgRinDQ61khHFZfx30rkPQG5ItaOT0wrI7iJv9A3SbghriQGfZQfHZs25fWLBe6/vkv05LOqg6aDw6Wzw==", + "dev": true, + "dependencies": { + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^1.0.3", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "lzma-native": "^8.0.5", + "node-abi": "^3.0.0", + "node-api-version": "^0.1.4", + "node-gyp": "^8.4.0", + "ora": "^5.1.0", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" + }, + "bin": { + "electron-rebuild": "lib/src/cli.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/electron-rebuild/node_modules/@malept/cross-spawn-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", + "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/electron-rebuild/node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/electron-rebuild/node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-rebuild/node_modules/cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-rebuild/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-rebuild/node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-rebuild/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-rebuild/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-rebuild/node_modules/got": { + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/electron-rebuild/node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/electron-rebuild/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-rebuild/node_modules/keyv": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.3.0.tgz", + "integrity": "sha512-C30Un9+63J0CsR7Wka5quXKqYZsT6dcRQ2aOwGcSc3RiQ4HGWpTAHlCA+puNfw2jA/s11EsxA1nCXgZRuRKMQQ==", + "dev": true, + "dependencies": { + "compress-brotli": "^1.3.8", + "json-buffer": "3.0.1" + } + }, + "node_modules/electron-rebuild/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-rebuild/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-rebuild/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-rebuild/node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-rebuild/node_modules/responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + } + }, + "node_modules/electron-rebuild/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-reload": { + "version": "2.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/electron-reload/-/electron-reload-2.0.0-alpha.1.tgz", + "integrity": "sha512-hTde7gv0TEqxbxlB3pj2CwoyCQ9sdiQrcP8GkpzhosxyVeYM3mZbMEVKCZK3L0fED7Mz5A9IWmK7zEvi4H3P1g==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2" + } + }, + "node_modules/electron-store": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-8.0.1.tgz", + "integrity": "sha512-ZyLvNywiqSpbwC/pp89O/AycVWY/UJIkmtyzF2Bd0Nm/rLmcFc0NTGuLdg6+LE8mS8qsiK5JMoe4PnrecLHH5w==", + "dev": true, + "dependencies": { + "conf": "^10.0.3", + "type-fest": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.144", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.144.tgz", + "integrity": "sha512-R3RV3rU1xWwFJlSClVWDvARaOk6VUO/FubHLodIASDB3Mc2dzuWvNdfOgH9bwHUTqT79u92qw60NWfwUdzAqdg==", + "dev": true + }, + "node_modules/electron-updater": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.0.1.tgz", + "integrity": "sha512-dNnXPCqYmergXy3jgg4UICuD50Orug9GQe/5xfHy+BE2Fy0icB0QE+y6iQWdCDf7yeONxwMBf4HgIkGG5pIaVg==", + "dev": true, + "dependencies": { + "@types/semver": "^7.3.6", + "builder-util-runtime": "9.0.0", + "fs-extra": "^10.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "^7.3.5" + } + }, + "node_modules/electron-updater/node_modules/builder-util-runtime": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.0.tgz", + "integrity": "sha512-SkpEtSmTkREDHRJnxKEv43aAYp8sYWY8fxYBhGLBLOBIRXeaIp6Kv3lBgSD7uR8jQtC7CA659sqJrpSV6zNvSA==", + "dev": true, + "dependencies": { + "debug": "^4.3.2", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/electron-updater/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-updater/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-updater/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron/node_modules/@types/node": { + "version": "14.18.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.20.tgz", + "integrity": "sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA==", + "dev": true + }, + "node_modules/emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enhanced-resolve/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-denodeify": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-denodeify/-/es6-denodeify-0.1.5.tgz", + "integrity": "sha512-731Rf4NqlPvhkT1pIF7r8vZxESJlWocNpXLuyPlVnfEGXlwuJaMvU5WpyyDjpudDC2cgXVX849xljzvQqBg1QQ==" + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz", + "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz", + "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "glob": "^7.2.0", + "is-glob": "^4.0.3", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", + "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "find-up": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "dev": true, + "dependencies": { + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", + "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/eventsource": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz", + "integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==", + "dependencies": { + "original": "^1.0.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "dev": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "dependencies": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + } + }, + "node_modules/extract-zip/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/extract-zip/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "optional": true + }, + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "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.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "peer": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fetch-cookie": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.7.3.tgz", + "integrity": "sha512-rZPkLnI8x5V+zYAiz8QonAHsTb4BY+iFowFBI1RFn0zrO343AVp9X7/yUj/9wL6Ef/8fLls8b/vGtzUvmyAUGA==", + "dependencies": { + "es6-denodeify": "^0.1.1", + "tough-cookie": "^2.3.3" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/finalhandler/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/findup-sync/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dev": true, + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/forcefocus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/forcefocus/-/forcefocus-1.1.0.tgz", + "integrity": "sha512-bnY7rul5kBLyNoCn0FHNiFAF+GGUZx6TvxWhurUS4PlmOzF+FMixGIigHH5UcyM3w1gp2TxAtP6MOUSXA15Sgw==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0", + "prebuild-install": "^5.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha512-Pqq5NnT78ehvUnAk/We/Jr22vSvanRlFTpAmQ88xBY/M1TlHe+P0ILuEyXS595ysdGfaj22634LBkGMA2GTcpA==", + "dev": true + }, + "node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/framebus": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/framebus/-/framebus-5.1.2.tgz", + "integrity": "sha512-Z/y6/0gHVx4Td4c0jkDiASBo0pXlJ2fKOP6CynSFnxTzqojG9xOKOFOqoYkcBHlz1vP4t4yHHR6Esp+GsYIh/Q==", + "dependencies": { + "@braintree/uuid": "^0.1.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fs-mkdirp-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob-stream/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-stream/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob-watcher/node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/glob-watcher/node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/glob-watcher/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/glob-watcher/node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-watcher/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-watcher/node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/glob-watcher/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/global-tunnel-ng": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", + "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", + "dev": true, + "optional": true, + "dependencies": { + "encodeurl": "^1.0.2", + "lodash": "^4.17.10", + "npm-conf": "^1.1.3", + "tunnel": "^0.0.6" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "optional": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", + "dev": true + }, + "node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-cli/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/gulp-cli/node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/gulp-cli/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "node_modules/gulp-cli/node_modules/yargs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "node_modules/gulp-cli/node_modules/yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + }, + "node_modules/gulp-filter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-7.0.0.tgz", + "integrity": "sha512-ZGWtJo0j1mHfP77tVuhyqem4MRA5NfNRjoVe6VAkLGeQQ/QGo2VsFwp7zfPTGDsd1rwzBmoDHhxpE6f5B3Zuaw==", + "dev": true, + "dependencies": { + "multimatch": "^5.0.0", + "plugin-error": "^1.0.1", + "streamfilter": "^3.0.0", + "to-absolute-glob": "^2.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + }, + "peerDependencies": { + "gulp": ">=4" + }, + "peerDependenciesMeta": { + "gulp": { + "optional": true + } + } + }, + "node_modules/gulp-if": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-3.0.0.tgz", + "integrity": "sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw==", + "dev": true, + "dependencies": { + "gulp-match": "^1.1.0", + "ternary-stream": "^3.0.0", + "through2": "^3.0.1" + } + }, + "node_modules/gulp-json-editor": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/gulp-json-editor/-/gulp-json-editor-2.5.6.tgz", + "integrity": "sha512-66Xr6Q6m4mUNd0OOHflMB/RHgFNnLjlHgizOzUcx9CyMRymVZEM+/SpZcCDlvThBdXtQwXpdvtSepxVY/V6nQA==", + "dev": true, + "dependencies": { + "deepmerge": "^4.2.2", + "detect-indent": "^6.0.0", + "js-beautify": "^1.13.13", + "plugin-error": "^1.0.1", + "through2": "^4.0.2" + } + }, + "node_modules/gulp-json-editor/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gulp-json-editor/node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/gulp-match": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", + "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", + "dev": true, + "dependencies": { + "minimatch": "^3.0.3" + } + }, + "node_modules/gulp-replace": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.3.tgz", + "integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==", + "dev": true, + "dependencies": { + "@types/node": "^14.14.41", + "@types/vinyl": "^2.0.4", + "istextorbinary": "^3.0.0", + "replacestream": "^4.0.3", + "yargs-parser": ">=5.0.0-security.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gulp-replace/node_modules/@types/node": { + "version": "14.18.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.20.tgz", + "integrity": "sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA==", + "dev": true + }, + "node_modules/gulp-zip": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-5.1.0.tgz", + "integrity": "sha512-XZr/y91IliK/SpR74g3TkZejGkGEmK7CSDjSghT1jXshgO+dFvpLIz9w9fpuwkew6i7k4F+G24TubNgq1ISzEw==", + "dev": true, + "dependencies": { + "get-stream": "^5.2.0", + "plugin-error": "^1.0.1", + "through2": "^3.0.1", + "vinyl": "^2.1.0", + "yazl": "^2.5.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "gulp": ">=4" + }, + "peerDependenciesMeta": { + "gulp": { + "optional": true + } + } + }, + "node_modules/gulp-zip/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", + "dev": true, + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", + "dev": true + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "peer": true + }, + "node_modules/html-loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-3.1.0.tgz", + "integrity": "sha512-ycMYFRiCF7YANcLDNP72kh3Po5pTcH+bROzdDwh00iVOAY/BwvpuZ1BKPziQ35Dk9D+UD84VGX1Lu/H4HpO4fw==", + "dev": true, + "dependencies": { + "html-minifier-terser": "^6.0.2", + "parse5": "^6.0.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/html-loader/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-injector": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/html-webpack-injector/-/html-webpack-injector-1.1.4.tgz", + "integrity": "sha512-R+HeAYzPeL3dKIr5/a7a2S6R4fy2yHetKiB7cz5rXjwlnU5tghuy58kCBsKA/Qoj94MAgCYwllHmvYqy2nJSdg==", + "dev": true + }, + "node_modules/html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "webpack": "^5.20.0" + } + }, + "node_modules/html-webpack-plugin/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "dependencies": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", + "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "devOptional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/if-async": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/if-async/-/if-async-3.7.4.tgz", + "integrity": "sha512-BFEH2mZyeF6KZKaKLVPZ0wMjIiWOdjvZ7zbx8ENec0qfZhJwKFbX/4jKM5LTKyJEc/GOqUKiiJ2IFKT9yWrZqA==", + "dev": true + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflation": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", + "integrity": "sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inject-stylesheet": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/inject-stylesheet/-/inject-stylesheet-5.0.0.tgz", + "integrity": "sha512-GzncrJP8E/pavMQzoO93CXoYCfTttwVm2cX2TyXJdgtVE0cCvWSFCn1/uMsM6ZkEg7LUsOcKuamcLiGWlv2p9A==" + }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/into-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", + "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "dev": true, + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "dev": true + }, + "node_modules/ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd/node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true + }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "peer": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "peer": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istextorbinary": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-3.3.0.tgz", + "integrity": "sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==", + "dev": true, + "dependencies": { + "binaryextensions": "^2.2.0", + "textextensions": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jasmine-core": { + "version": "3.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", + "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", + "dev": true + }, + "node_modules/jasmine-spec-reporter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-7.0.0.tgz", + "integrity": "sha512-OtC7JRasiTcjsaCBPtMO0Tl8glCejM4J4/dNuOJdA8lBjz4PmWjYQ6pzb0uzpBNAWJMDudYuj9OdXJWqM2QTJg==", + "dev": true, + "dependencies": { + "colors": "1.4.0" + } + }, + "node_modules/jasmine-spec-reporter/node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "peer": true, + "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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, + "peer": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, + "peer": true, + "dependencies": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-preset-angular": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-10.1.0.tgz", + "integrity": "sha512-D4k+BnGoig3w1x4MZiQOdN8UfaLN5aNjmx91U28VYRA+LslbN+D8dGyb5a5lR32mog5y86iVnAZ4mRvFlYr7SQ==", + "dev": true, + "dependencies": { + "jest-environment-jsdom": "^27.0.0", + "pretty-format": "^27.0.0", + "ts-jest": "^27.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@angular/compiler-cli": ">=10.0.0", + "@angular/core": ">=10.0.0", + "@angular/platform-browser-dynamic": ">=10.0.0" + } + }, + "node_modules/jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "dependencies": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "peer": true, + "dependencies": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jquery": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", + "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" + }, + "node_modules/js-beautify": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", + "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", + "dev": true, + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "nopt": "^5.0.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-message": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", + "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", + "dev": true, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/js-queue": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz", + "integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==", + "dev": true, + "dependencies": { + "easy-stack": "^1.0.1" + }, + "engines": { + "node": ">=1.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "node_modules/jsdom/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/jsdom/node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", + "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-schema-typed": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", + "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jszip": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.0.tgz", + "integrity": "sha512-LDfVtOLtOxb9RXkYOwPyNBTQDL4eUbqahtoY6x07GiDJHwSYvn8sHHIw8wINImV3MqbMNve2gSuM1DDqEKk09Q==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "dev": true + }, + "node_modules/keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "dependencies": { + "tsscmp": "1.0.6" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/keytar/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/keytar/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/keytar/node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/keytar/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/keytar/node_modules/detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/keytar/node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/keytar/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/keytar/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/keytar/node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true + }, + "node_modules/keytar/node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/keytar/node_modules/prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/keytar/node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/keytar/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/keytar/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/koa": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz", + "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==", + "dependencies": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "engines": { + "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4" + } + }, + "node_modules/koa-bodyparser": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", + "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", + "dependencies": { + "co-body": "^6.0.0", + "copy-to": "^2.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" + }, + "node_modules/koa-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", + "dependencies": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/koa-is-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw==" + }, + "node_modules/koa-json": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/koa-json/-/koa-json-2.0.2.tgz", + "integrity": "sha512-8+dz0T2ekDuNN1svYoKPCV2txotQ3Ufg8Fn5bft1T48MPJWiC/HKmkk+3xj9EC/iNZuFYeLRazN2h2o3RSUXuQ==", + "dependencies": { + "koa-is-json": "1", + "streaming-json-stringify": "3" + } + }, + "node_modules/koa/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/liftoff/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/lint-staged": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.5.0.tgz", + "integrity": "sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g==", + "dev": true, + "dependencies": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.16", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^5.1.1", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.5.0", + "string-argv": "^0.3.1", + "supports-color": "^9.2.2", + "yaml": "^1.10.2" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/ansi-styles": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz", + "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/lint-staged/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/lint-staged/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/supports-color": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.2.2.tgz", + "integrity": "sha512-XC6g/Kgux+rJXmwokjm9ECpD6k/smUoS5LKlUCcsYr4IY3rW0XyAympon2RmxGrlnZURMpg5T18gWDP9CsHXFA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "dependencies": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "dependencies": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + }, + "node_modules/lzma-native": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-8.0.6.tgz", + "integrity": "sha512-09xfg67mkL2Lz20PrrDeNYZxzeW7ADtpYFbwSQh9U8+76RIzx5QsJBMy8qikv3hbUPfpy6hqwxt6FcGK81g9AA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^3.1.0", + "node-gyp-build": "^4.2.1", + "readable-stream": "^3.6.0" + }, + "bin": { + "lzmajs": "bin/lzmajs" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/lzma-native/node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node_modules/lzma-native/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-iterator/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "peer": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", + "dev": true, + "dependencies": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/matchdep/node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/braces/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/fill-range/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/matchdep/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matchdep/node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz", + "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==", + "dev": true, + "dependencies": { + "fs-monkey": "1.0.3" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", + "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dev": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "node_modules/mousetrap": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", + "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/msgpack5": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-4.5.1.tgz", + "integrity": "sha512-zC1vkcliryc4JGlL6OfpHumSYUHWFGimSI+OgfRCjTFLmKA2/foR9rMTOhWiqfOrfxJOctrpWPvrppf8XynJxw==", + "dependencies": { + "bl": "^2.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.3.6", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", + "dev": true + }, + "node_modules/multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/multistream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/multistream/-/multistream-4.1.0.tgz", + "integrity": "sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "once": "^1.4.0", + "readable-stream": "^3.6.0" + } + }, + "node_modules/multistream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "node_modules/ngx-infinite-scroll": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-10.0.1.tgz", + "integrity": "sha512-7is0eJZ9kJPsaHohRmMhJ/QFHAW9jp9twO5HcHRvFM/Yl/R8QCiokgjwmH0/CR3MuxUanxfHZMfO3PbYTwlBEg==", + "hasInstallScript": true, + "dependencies": { + "@scarf/scarf": "^1.1.0", + "opencollective-postinstall": "^2.0.2" + } + }, + "node_modules/ngx-toastr": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-14.1.4.tgz", + "integrity": "sha512-t1/9r+pOXm65LIl0gevvFat6XIl0g3tMA8UOArFjI4ta/nGwDe/14J/f4cZvOBDcomedvjvGAWi+d/2URdSTBg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "peerDependencies": { + "@angular/common": ">=12.0.0-0", + "@angular/core": ">=12.0.0-0", + "@angular/platform-browser": ">=12.0.0-0" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node_modules/node-api-version": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.1.4.tgz", + "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + } + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", + "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "peer": true + }, + "node_modules/node-ipc": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz", + "integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==", + "dev": true, + "dependencies": { + "event-pubsub": "4.3.0", + "js-message": "1.0.7", + "js-queue": "2.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "node_modules/noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ==", + "dev": true + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/nord": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nord/-/nord-0.2.1.tgz", + "integrity": "sha512-/AD7JGJbcp1pB5XwYkJyivqdeXofUP5u2lkif6vLGLc+SsV9OCC0JFNpVwM5pqHuFqbyojRt6xILuidJOwwJDQ==" + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "optional": true, + "dependencies": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw==", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==" + }, + "node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "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.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/ora/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/ora/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dependencies": { + "url-parse": "^1.4.3" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/papaparse": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz", + "integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dev": true, + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.5.0.tgz", + "integrity": "sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/pkg/-/pkg-5.7.0.tgz", + "integrity": "sha512-PTiAjNq/CGAtK5qUBR6pjheqnipTFjeecgSgIKEcAOJA4GpmZeOZC8pMOoT0rfes5vHsmcFo7wbSRTAmXQurrg==", + "dev": true, + "dependencies": { + "@babel/parser": "7.17.10", + "@babel/types": "7.17.10", + "chalk": "^4.1.2", + "escodegen": "^2.0.0", + "fs-extra": "^9.1.0", + "globby": "^11.1.0", + "into-stream": "^6.0.0", + "is-core-module": "2.9.0", + "minimist": "^1.2.6", + "multistream": "^4.1.0", + "pkg-fetch": "3.4.1", + "prebuild-install": "6.1.4", + "resolve": "^1.22.0", + "stream-meter": "^1.0.4" + }, + "bin": { + "pkg": "lib-es5/bin.js" + }, + "peerDependencies": { + "node-notifier": ">=9.0.1" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-fetch": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-3.4.1.tgz", + "integrity": "sha512-fS4cdayCa1r4jHkOKGPJKnS9PEs6OWZst+s+m0+CmhmPZObMnxoRnf9T9yUWl+lzM2b5aJF7cnQIySCT7Hq8Dg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.2", + "fs-extra": "^9.1.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.6", + "progress": "^2.0.3", + "semver": "^7.3.5", + "tar-fs": "^2.1.1", + "yargs": "^16.2.0" + }, + "bin": { + "pkg-fetch": "lib-es5/bin.js" + } + }, + "node_modules/pkg-fetch/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-fetch/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/pkg-fetch/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/pkg-fetch/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-fetch/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg/node_modules/@babel/parser": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pkg/node_modules/@babel/types": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", + "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/pkg/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/pkg/node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/pkg/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pkg/node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/pkg/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/pkg/node_modules/node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "dependencies": { + "semver": "^5.4.1" + } + }, + "node_modules/pkg/node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/pkg/node_modules/prebuild-install": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.21.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/pkg/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==", + "dev": true, + "dependencies": { + "base64-js": "^1.5.1", + "xmlbuilder": "^9.0.7" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/plist/node_modules/xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.6" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "dev": true, + "dependencies": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/prebuild-install/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/prebuild-install/node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "node_modules/prebuild-install/node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/prebuild-install/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install/node_modules/node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "dependencies": { + "semver": "^5.4.1" + } + }, + "node_modules/prebuild-install/node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/prebuild-install/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/prebuild-install/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prebuild-install/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-polyfill": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.3.tgz", + "integrity": "sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg==" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrious": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/qrious/-/qrious-4.0.2.tgz", + "integrity": "sha512-xWPJIrK1zu5Ypn898fBp8RHkT/9ibquV2Kv24S/JY9VYEhMBMKur1gHVsOiNUh7PHP9uCgejjpZUHUIXXKoU/g==" + }, + "node_modules/qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "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" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/read-config-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.2.0.tgz", + "integrity": "sha512-gx7Pgr5I56JtYz+WuqEbQHj/xWo+5Vwua2jhb1VwM4Wid5PqYmZ4i00ZB0YEGIfkVBsCv9UrjgyqCiQfS/Oosg==", + "dev": true, + "dependencies": { + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg/node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "node_modules/regedit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/regedit/-/regedit-3.0.3.tgz", + "integrity": "sha512-SpHmMKOtiEYx0MiRRC48apBsmThoZ4svZNsYoK8leHd5bdUHV1nYb8pk8gh6Moou7/S9EDi1QsjBTpyXVQrPuQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "if-async": "^3.7.4", + "stream-slicer": "0.0.6", + "through2": "^0.6.3" + } + }, + "node_modules/regedit/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "node_modules/regedit/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/regedit/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/regedit/node_modules/through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "dependencies": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "dependencies": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-bom-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/replacestream/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "node_modules/resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restricted-input": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/restricted-input/-/restricted-input-3.0.5.tgz", + "integrity": "sha512-lUuXZ3wUnHURRarj5/0C8vomWIfWJO+p7T6RYwB46v7Oyuyr3yyupU+i7SjqUv4S6RAeAAZt1C/QCLJ9xhQBow==", + "dependencies": { + "@braintree/browser-detection": "^1.12.1" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sass": { + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz", + "integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "dev": true, + "dependencies": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "node_modules/selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "dependencies": { + "node-forge": "^0.10.0" + } + }, + "node_modules/selfsigned/node_modules/node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true, + "optional": true + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "dependencies": { + "sver-compat": "^1.5.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/send/node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallow-clone/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "dev": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/simple-get/node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "peer": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "dev": true, + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated", + "dev": true + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, + "optional": true + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", + "dependencies": { + "graceful-fs": "^4.1.3" + } + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "node_modules/stream-meter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz", + "integrity": "sha1-Uq+Vql6nYKJJFxZwTb/5D3Ov3R0=", + "dev": true, + "dependencies": { + "readable-stream": "^2.1.4" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/stream-slicer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stream-slicer/-/stream-slicer-0.0.6.tgz", + "integrity": "sha1-+GsqxcJEC3oKh7cfM2ZcB4gEYTg=", + "dev": true + }, + "node_modules/streamfilter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-3.0.0.tgz", + "integrity": "sha512-kvKNfXCmUyC8lAXSSHCIXBUlo/lhsLcCU/OmzACZYpRUdtKIH68xYhm/+HI15jFJYtNJGYtCgn2wmIiExY1VwA==", + "dev": true, + "dependencies": { + "readable-stream": "^3.0.6" + }, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/streamfilter/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/streaming-json-stringify": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/streaming-json-stringify/-/streaming-json-stringify-3.1.0.tgz", + "integrity": "sha1-gCAEN6mTzDnE/gAmO3s7kDrIevU=", + "dependencies": { + "json-stringify-safe": "5", + "readable-stream": "2" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "peer": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "dependencies": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/sweetalert2": { + "version": "10.16.9", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-10.16.9.tgz", + "integrity": "sha512-oNe+md5tmmS3fGfVHa7gVPlun7Td2oANSacnZCeghnrr3OHBi6UPVPU+GFrymwaDqwQspACilLRmRnM7aTjNPA==", + "funding": { + "url": "https://sweetalert2.github.io/#donations" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "node_modules/tailwindcss": { + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", + "integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==", + "dev": true, + "dependencies": { + "arg": "^5.0.1", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.12", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/tar-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ternary-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-3.0.0.tgz", + "integrity": "sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ==", + "dev": true, + "dependencies": { + "duplexify": "^4.1.1", + "fork-stream": "^0.0.4", + "merge-stream": "^2.0.0", + "through2": "^3.0.1" + } + }, + "node_modules/terser": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz", + "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", + "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.7", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.7.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "peer": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/textextensions": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", + "integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true, + "peer": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "dependencies": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/through2-filter/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tldjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tldjs/-/tldjs-2.3.1.tgz", + "integrity": "sha512-W/YVH/QczLUxVjnQhFC61Iq232NWu3TqDdO0S/MtXVz4xybejBov4ud+CIwN9aYqjOecEqIy0PscGkwpG9ZyTw==", + "hasInstallScript": true, + "dependencies": { + "punycode": "^1.4.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/tmp-promise/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "peer": true + }, + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/to-through/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tr46/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "dev": true, + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/ts-jest": { + "version": "27.1.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz", + "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@types/jest": "^27.0.0", + "babel-jest": ">=27.0.0 <28", + "jest": "^27.0.0", + "typescript": ">=3.8 <5.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-loader": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.0.tgz", + "integrity": "sha512-2kLLAdAD+FCKijvGKi9sS0OzoqxLCF3CxHpok7rVgCZ5UldRzH0TkbwG9XECKjBzHsAewntC5oDaI/FwKzEUog==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "typescript": "*", + "webpack": "^5.0.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz", + "integrity": "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^3.9.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", + "engines": { + "node": ">=0.6.x" + } + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/undertaker/node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/union-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "dependencies": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "dependencies": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/update-notifier/node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "dev": true + }, + "node_modules/util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "peer": true, + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "optional": true + }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "peer": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-animations-js": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.2.tgz", + "integrity": "sha512-TOMFWtQdxzjWp8qx4DAraTWTsdhxVSiWa6NkPFSaPtZ1diKUxTn4yTix73A1euG1WbSOMMPcY51cnjTIHrGtDA==" + }, + "node_modules/webcrypto-shim": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/webcrypto-shim/-/webcrypto-shim-0.1.7.tgz", + "integrity": "sha512-JAvAQR5mRNRxZW2jKigWMjCMkjSdmP5cColRP1U/pTg69VgHXEi1orv5vVpJ55Zc5MIaPc1aaurzd9pjv2bveg==", + "dev": true + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.73.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", + "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-cli": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", + "dev": true, + "dependencies": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "bin": { + "webpack-cli": "bin/cli.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "webpack": "4.x.x || 5.x.x" + }, + "peerDependenciesMeta": { + "@webpack-cli/generators": { + "optional": true + }, + "@webpack-cli/migrate": { + "optional": true + }, + "webpack-bundle-analyzer": { + "optional": true + }, + "webpack-dev-server": { + "optional": true + } + } + }, + "node_modules/webpack-cli/node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/webpack-cli/node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.6.0.tgz", + "integrity": "sha512-oojcBIKvx3Ya7qs1/AVWHDgmP1Xml8rGsEBnSobxU/UJSX1xP1GPM3MwsAnDzvqcVmVki8tV7lbcsjEjk0PtYg==", + "dev": true, + "dependencies": { + "ansi-html-community": "^0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^3.5.2", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "default-gateway": "^6.0.3", + "del": "^6.0.0", + "express": "^4.17.1", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.0", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "schema-utils": "^4.0.0", + "selfsigned": "^1.10.11", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "strip-ansi": "^7.0.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^5.2.1", + "ws": "^8.1.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/webpack-dev-server/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", + "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack/node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-encoding/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "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.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, + "node_modules/ylru": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", + "integrity": "sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/zone.js": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.5.tgz", + "integrity": "sha512-D1/7VxEuQ7xk6z/kAROe4SUbd9CzxY4zOwVGnGHerd/SgLIVU5f4esDzQUsOCeArn933BZfWMKydH7l7dPEp0g==", + "dependencies": { + "tslib": "^2.3.0" + } + }, + "node_modules/zxcvbn": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz", + "integrity": "sha1-KOwXzwl0PtyrBW3dixsGJizHPDA=" + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@angular/animations": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.16.tgz", + "integrity": "sha512-Kf6C7Ta+fCMq5DvT9JNVhBkcECrqFa3wumiC6ssGo5sNaEzXz+tlep9ZgEbqfxSn7gAN7L1DgsbS9u0O6tbUkg==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/cdk": { + "version": "12.2.13", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-12.2.13.tgz", + "integrity": "sha512-zSKRhECyFqhingIeyRInIyTvYErt4gWo+x5DQr0b7YLUbU8DZSwWnG4w76Ke2s4U8T7ry1jpJBHoX/e8YBpGMg==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^2.2.0" + } + }, + "@angular/common": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-12.2.16.tgz", + "integrity": "sha512-FEqTXTEsnbDInqV1yFlm97Tz1OFqZS5t0TUkm8gzXRgpIce/F/jLwAg0u1VQkgOsno6cNm0xTWPoZgu85NI4ug==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/compiler": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-12.2.16.tgz", + "integrity": "sha512-nsYEw+yu8QyeqPf9nAmG419i1mtGM4v8+U+S3eQHQFXTgJzLymMykWHYu2ETdjUpNSLK6xcIQDBWtWnWSfJjAA==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/compiler-cli": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-12.2.16.tgz", + "integrity": "sha512-tlalh8SJvdCWbUPRUR5GamaP+wSc/GuCsoUZpSbcczGKgSlbaEVXUYtVXm8/wuT6Slk2sSEbRs7tXGF2i7qxVw==", + "dev": true, + "requires": { + "@babel/core": "^7.8.6", + "@babel/types": "^7.8.6", + "canonical-path": "1.0.0", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.11.0", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "source-map": "^0.6.1", + "sourcemap-codec": "^1.4.8", + "tslib": "^2.2.0", + "yargs": "^17.0.0" + } + }, + "@angular/core": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-12.2.16.tgz", + "integrity": "sha512-jsmvaRdAfng99z2a9mAmkfcsCE1wm+tBYVDxnc5JquSXznwtncjzcoc2X0J0dzrkCDvzFfpTsZ9vehylytBc+A==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/forms": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-12.2.16.tgz", + "integrity": "sha512-sb+gpNun5aN7CZfHXS6X7vJcd/0A1P/gRBZpYtQTzBYnqEFCOFIvR62eb05aHQ4JhgKaSPpIXrbz/bAwY/njZw==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/platform-browser": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-12.2.16.tgz", + "integrity": "sha512-T855ppLeQO6hRHi7lGf5fwPoUVt+c0h2rgkV5jHElc3ylaGnhecmZc6fnWLX4pw82TMJUgUV88CY8JCFabJWwg==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-12.2.16.tgz", + "integrity": "sha512-XGxoACAMW/bc3atiVRpaiYwU4LkobYwVzwlxTT/BxOfsdt8ILb5wU8Fx1TMKNECOQHSGdK0qqhch4pTBZ3cb2g==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@angular/router": { + "version": "12.2.16", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-12.2.16.tgz", + "integrity": "sha512-LuFXSMIvX/VrB4jbYhigG2Y2pGQ9ULsSBUwDWwQCf4kr0eVI37LBJ2Vr74GBEznjgQ0UmWE89E+XYI80UhERTw==", + "requires": { + "tslib": "^2.2.0" + } + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/compat-data": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "dev": true + }, + "@babel/core": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.2.tgz", + "integrity": "sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-compilation-targets": "^7.18.2", + "@babel/helper-module-transforms": "^7.18.0", + "@babel/helpers": "^7.18.2", + "@babel/parser": "^7.18.0", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.2.tgz", + "integrity": "sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==", + "dev": true, + "requires": { + "@babel/types": "^7.18.2", + "@jridgewell/gen-mapping": "^0.3.0", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz", + "integrity": "sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz", + "integrity": "sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz", + "integrity": "sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.0", + "@babel/types": "^7.18.0" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz", + "integrity": "sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==", + "dev": true, + "peer": true + }, + "@babel/helper-simple-access": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz", + "integrity": "sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==", + "dev": true, + "requires": { + "@babel/types": "^7.18.2" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true + }, + "@babel/helpers": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.2.tgz", + "integrity": "sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.18.2", + "@babel/types": "^7.18.2" + } + }, + "@babel/highlight": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.12.tgz", + "integrity": "sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.4.tgz", + "integrity": "sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.17.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz", + "integrity": "sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.17.12" + } + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.2.tgz", + "integrity": "sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.18.2", + "@babel/helper-environment-visitor": "^7.18.2", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.18.0", + "@babel/types": "^7.18.2", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.4.tgz", + "integrity": "sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "peer": true + }, + "@braintree/asset-loader": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@braintree/asset-loader/-/asset-loader-0.4.4.tgz", + "integrity": "sha512-uVhXC5dydmngmNVuDiKgfXSlz4kv4x5ytIJodI8N5SY16mRh13m/UmbQ7yH+o8DQqp50qPZ45MUHIZkXKPg85w==", + "requires": { + "promise-polyfill": "^8.1.3" + } + }, + "@braintree/browser-detection": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/@braintree/browser-detection/-/browser-detection-1.12.1.tgz", + "integrity": "sha512-i/54qrax5o/WbJJhsE/7qqKE594/kGhR+xSu/w13rT7Mlr/uITkWDXzxffcKQ6l6FQxK0IG0EfgT6TJpWgZcUQ==" + }, + "@braintree/class-list": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@braintree/class-list/-/class-list-0.2.0.tgz", + "integrity": "sha512-iLXJT51jnBFuGvyTAQqZ2uwyEVwdyapyz52F5MK1Uoh2ZOiPJ5hoqI0wncyCP2KfqrgyCpOkkEaLMLb/94unGA==" + }, + "@braintree/event-emitter": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@braintree/event-emitter/-/event-emitter-0.4.1.tgz", + "integrity": "sha512-X41357O3OXUDlnwMvS1m0GQEn3zB3s3flOBeg2J5OBvLvdJEIAVpPkblABPtsPrlciDSvfv1aSG5ixHPgFH0Zg==" + }, + "@braintree/extended-promise": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@braintree/extended-promise/-/extended-promise-0.4.1.tgz", + "integrity": "sha512-00n7m4z+swWHoFQLHLvrIBIEoxnGUBsl3ogvX79ITpcn8CHczDwtxYy5+RhMoAraRdfN3oB+8QIpN3KOxs2Q7w==" + }, + "@braintree/iframer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@braintree/iframer/-/iframer-1.1.0.tgz", + "integrity": "sha512-tVpr7U6u6bqeQlHreEjYMNtnHX62vLnNWziY2kQLqkWhvusPuY5DfuGEIPpWqsd+V/a1slyTQaxK6HWTlH6A/Q==" + }, + "@braintree/sanitize-url": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-6.0.0.tgz", + "integrity": "sha512-mgmE7XBYY/21erpzhexk4Cj1cyTQ9LzvnTxtzM17BJ7ERMNE6W72mQRo0I1Ud8eFJ+RVVIcBNhLFZ3GX4XFz5w==" + }, + "@braintree/uuid": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@braintree/uuid/-/uuid-0.1.0.tgz", + "integrity": "sha512-YvZJdlNcK5EnR+7M8AjgEAf4Qx696+FOSYlPfy5ePn80vODtVAUU0FxHnzKZC0og1VbDNQDDiwhthR65D4Na0g==" + }, + "@braintree/wrap-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@braintree/wrap-promise/-/wrap-promise-2.1.0.tgz", + "integrity": "sha512-UIrJB+AfKU0CCfbMoWrsGpd2D/hBpY/SGgFI6WRHPOwhaZ3g9rz1weiJ6eb6L9KgVyunT7s2tckcPkbHw+NzeA==" + }, + "@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "requires": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@electron/get": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", + "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "global-agent": "^3.0.0", + "global-tunnel-ng": "^2.7.1", + "got": "^9.6.0", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@electron/universal": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.0.5.tgz", + "integrity": "sha512-zX9O6+jr2NMyAdSkwEUlyltiI4/EBLu2Ls/VD3pUQdi3cAYeYfdQnT2AJJ38HE4QxLccbU13LSpccw1IWlkyag==", + "dev": true, + "requires": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.0.3", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.3.2", + "globals": "^13.15.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" + }, + "dependencies": { + "globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "@fluffy-spoon/substitute": { + "version": "1.208.0", + "resolved": "https://registry.npmjs.org/@fluffy-spoon/substitute/-/substitute-1.208.0.tgz", + "integrity": "sha512-BU5vKRoK4OYlKzDtyg4HbtWnUNLOvV0ntqEZIphz+mq2G0HlVFywwJ7M+FbIcnJVDbUReS01FyL5x8R01r7zBg==", + "dev": true + }, + "@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "peer": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "peer": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "peer": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "peer": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "peer": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "peer": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "peer": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "peer": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "peer": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "peer": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true, + "peer": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "peer": true + }, + "@jest/console": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", + "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0" + } + }, + "@jest/core": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", + "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/reporters": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^27.5.1", + "jest-config": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-resolve-dependencies": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "jest-watcher": "^27.5.1", + "micromatch": "^4.0.4", + "rimraf": "^3.0.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "@jest/environment": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", + "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1" + } + }, + "@jest/fake-timers": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", + "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@sinonjs/fake-timers": "^8.0.1", + "@types/node": "*", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "@jest/globals": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", + "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/types": "^27.5.1", + "expect": "^27.5.1" + } + }, + "@jest/reporters": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", + "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", + "dev": true, + "peer": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.2", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-haste-map": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "slash": "^3.0.0", + "source-map": "^0.6.0", + "string-length": "^4.0.1", + "terminal-link": "^2.0.0", + "v8-to-istanbul": "^8.1.0" + } + }, + "@jest/source-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", + "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", + "dev": true, + "peer": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", + "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", + "dev": true, + "peer": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", + "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/test-result": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-runtime": "^27.5.1" + } + }, + "@jest/transform": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", + "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^27.5.1", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-util": "^27.5.1", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "dependencies": { + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + } + } + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", + "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.1.tgz", + "integrity": "sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==", + "dev": true + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz", + "integrity": "sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", + "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", + "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@koa/multer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@koa/multer/-/multer-3.0.0.tgz", + "integrity": "sha512-y+OQBmex5D1jIl723gAEUYcAWPEicIXppaAKw/zCMfpllQ08ZNweDPwoCLxEoatqd5pCu2XG6V8dl67JRq3RJw==", + "requires": {} + }, + "@koa/router": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@koa/router/-/router-10.1.1.tgz", + "integrity": "sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==", + "requires": { + "debug": "^4.1.1", + "http-errors": "^1.7.3", + "koa-compose": "^4.1.0", + "methods": "^1.1.2", + "path-to-regexp": "^6.1.0" + } + }, + "@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "@microsoft/signalr": { + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-5.0.17.tgz", + "integrity": "sha512-zTjFxjh67WWCe35ZipsqkktM5mM+MsckyyI2ZvFmYWR7ibpUoAyZI1DFdYfwXfsyBdlykDaW84o9lrB+9tDpaA==", + "requires": { + "abort-controller": "^3.0.0", + "eventsource": "^1.0.7", + "fetch-cookie": "^0.7.3", + "node-fetch": "^2.6.7", + "ws": "^6.0.0" + } + }, + "@microsoft/signalr-protocol-msgpack": { + "version": "5.0.17", + "resolved": "https://registry.npmjs.org/@microsoft/signalr-protocol-msgpack/-/signalr-protocol-msgpack-5.0.17.tgz", + "integrity": "sha512-Gqp1Azw5nFColcwX/eLIs+N2G6/nWtYHZtMccgEv9C1PKMXZEiUPiHmvwbLfywJubtu9cyDie3Q/+VuRc9X5Xg==", + "requires": { + "@microsoft/signalr": ">=5.0.17", + "msgpack5": "^4.5.0" + } + }, + "@ngtools/webpack": { + "version": "12.2.17", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-12.2.17.tgz", + "integrity": "sha512-uaS+2YZgPDW3VmUuwh4/yfIFV1KRVGWefc6xLWIqKRKs6mlRYs65m3ib9dX7CTS4kQMCbhxkxMbpBO2yXlzfvA==", + "dev": true, + "requires": {} + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@nodert-win10-rs4/windows.security.credentials.ui": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@nodert-win10-rs4/windows.security.credentials.ui/-/windows.security.credentials.ui-0.4.4.tgz", + "integrity": "sha512-P+EsJw5MCQXTxp7mwXfNDvIzIYsB6ple+HNg01QjPWg/PJfAodPuxL6XM7l0sPtYHsDYnfnvoefZMdZRa2Z1ig==", + "dev": true, + "requires": { + "nan": "latest" + } + }, + "@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "dev": true, + "requires": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "@scarf/scarf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.1.1.tgz", + "integrity": "sha512-VGbKDbk1RFIaSmdVb0cNjjWJoRWRI/Weo23AjRCC2nryO0iAS8pzsToJfPVPtVs74WHw4L1UTADNdIYRLkirZQ==" + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true + }, + "@types/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/babel__core": { + "version": "7.1.19", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.19.tgz", + "integrity": "sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==", + "dev": true, + "peer": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "peer": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.17.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.17.1.tgz", + "integrity": "sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==", + "dev": true, + "peer": true, + "requires": { + "@babel/types": "^7.3.0" + } + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/cacheable-request": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz", + "integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "*", + "@types/node": "*", + "@types/responselike": "*" + } + }, + "@types/chrome": { + "version": "0.0.139", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.139.tgz", + "integrity": "sha512-YZDKFlSVGFp4zldJlO+PUpxMH8N9vLke0fD6K9PA+TzXxPXu8LBLo5X2dzlOs2N/n+uMdI1lw7OPT1Emop10lQ==", + "dev": true, + "requires": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/content-disposition": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.5.tgz", + "integrity": "sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==", + "dev": true + }, + "@types/cookies": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", + "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dev": true, + "requires": { + "@types/ms": "*" + } + }, + "@types/duo_web_sdk": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@types/duo_web_sdk/-/duo_web_sdk-2.7.1.tgz", + "integrity": "sha512-DePanZjFww36yGSxXwC8B3AsjrrDuPxEcufeh4gTqVsUMpCYByxjX4PERiYZdW0typzKSt9E4I14PPp+PrSIQA==", + "dev": true + }, + "@types/eslint": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.2.tgz", + "integrity": "sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "0.0.51", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", + "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", + "dev": true + }, + "@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "dev": true + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.28", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", + "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, + "@types/filesystem": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", + "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", + "dev": true, + "requires": { + "@types/filewriter": "*" + } + }, + "@types/filewriter": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz", + "integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==", + "dev": true + }, + "@types/firefox-webext-browser": { + "version": "82.0.1", + "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-82.0.1.tgz", + "integrity": "sha512-odcPKiJ34N8k53clIWen3hLvl09ja7SQ9NqtUbgmqeJ/a/ZRQiF665iXSFPcnl6cBn2XQgEg2lsUUApYNiyj+g==", + "dev": true + }, + "@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", + "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*" + } + }, + "@types/har-format": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.8.tgz", + "integrity": "sha512-OP6L9VuZNdskgNN3zFQQ54ceYD8OLq5IbqO4VK91ORLfOm7WdT/CiT/pHEBSQEqCInJ2y3O6iCm/zGtPElpgJQ==", + "dev": true + }, + "@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true + }, + "@types/http-assert": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz", + "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==", + "dev": true + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "@types/http-errors": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz", + "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==", + "dev": true + }, + "@types/http-proxy": { + "version": "1.17.9", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", + "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/inquirer": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.2.1.tgz", + "integrity": "sha512-wKW3SKIUMmltbykg4I5JzCVzUhkuD9trD6efAmYgN2MrSntY0SMRQzEnD3mkyJ/rv9NLbTC7g3hKKE86YwEDLw==", + "dev": true, + "requires": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "27.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.5.2.tgz", + "integrity": "sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==", + "dev": true, + "requires": { + "jest-matcher-utils": "^27.0.0", + "pretty-format": "^27.0.0" + } + }, + "@types/jquery": { + "version": "3.5.14", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz", + "integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==", + "dev": true, + "requires": { + "@types/sizzle": "*" + } + }, + "@types/jsdom": { + "version": "16.2.14", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-16.2.14.tgz", + "integrity": "sha512-6BAy1xXEmMuHeAJ4Fv4yXKwBDTGTOseExKE3OaHiNycdHdZw59KfYzrt0DkDluvwmik1HRt6QS7bImxUmpSy+w==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/parse5": "*", + "@types/tough-cookie": "*" + } + }, + "@types/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "@types/keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", + "dev": true + }, + "@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/koa": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz", + "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==", + "dev": true, + "requires": { + "@types/accepts": "*", + "@types/content-disposition": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/http-errors": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" + } + }, + "@types/koa__multer": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/koa__multer/-/koa__multer-2.0.4.tgz", + "integrity": "sha512-WRkshXhE5rpYFUbbtAjyMhdOOSdbu1XX+2AQlRNM6AZtgxd0/WXMU4lrP7e9tk5HWVTWbx8DOOsVBmfHjSGJ4w==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/koa__router": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.11.tgz", + "integrity": "sha512-WXgKWpBsbS14kzmzD9LeFapOIa678h7zvUHxDwXwSx4ETKXhXLVUAToX6jZ/U7EihM7qwyD9W/BZvB0MRu7MTQ==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/koa-bodyparser": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@types/koa-bodyparser/-/koa-bodyparser-4.3.7.tgz", + "integrity": "sha512-21NhEp7LjZm4zbNV5alHHmrNY4J+S7B8lYTO6CzRL8ShTMnl20Gd14dRgVhAxraLaW5iZMofox+BycbuiDvj2Q==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/koa-compose": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", + "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/koa-json": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/@types/koa-json/-/koa-json-2.0.20.tgz", + "integrity": "sha512-RuQ1Vlpsm/EC5wo2oWCgNnwneixnSQ9aHQAE7nwnbSiCibgfUO2wwSQN6rn8SfF97cRdN9hKAtoc9KSIuiGP6Q==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==", + "dev": true + }, + "@types/lowdb": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@types/lowdb/-/lowdb-1.0.11.tgz", + "integrity": "sha512-h99VMxvTuz+VsXUVCCJo4dsps4vbkXwvU71TpmxDoiBU24bJ0VBygIHgmMm+UPoQIFihmV6euRik4z8J7XDJWg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/lunr": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/lunr/-/lunr-2.3.4.tgz", + "integrity": "sha512-j4x4XJwZvorEUbA519VdQ5b9AOU9TSvfi8tvxMAfP8XzNLtFex7A8vFQwqOx3WACbV0KMXbACV3cZl4/gynQ7g==", + "dev": true + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", + "dev": true + }, + "@types/mousetrap": { + "version": "1.6.9", + "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.9.tgz", + "integrity": "sha512-HUAiN65VsRXyFCTicolwb5+I7FM6f72zjMWr+ajGk+YTvzBgXqa2A5U7d+rtsouAkunJ5U4Sb5lNJjo9w+nmXg==", + "dev": true + }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==", + "dev": true + }, + "@types/node": { + "version": "16.11.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.38.tgz", + "integrity": "sha512-hjO/0K140An3GWDw2HJfq7gko3wWeznbjXgg+rzPdVzhe198hp4x2i1dgveAOEiFKd8sOilAxzoSJiVv5P/CUg==", + "dev": true + }, + "@types/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==", + "dev": true, + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "@types/node-forge": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.0.2.tgz", + "integrity": "sha512-J1OkeZGaW0y9Y7xD49Ja8O82B9l5nZDeoYuGWqIOYPAf9LR+xF23k9ILdzv8dH+2H033fx3D5oiA0GlmicI+sg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/node-ipc": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@types/node-ipc/-/node-ipc-9.2.0.tgz", + "integrity": "sha512-0v1oucUgINvWPhknecSBE5xkz74sVgeZgiL/LkWXNTSzFaGspEToA4oR56hjza0Jkk6DsS2EiNU3M2R2KQza9A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/papaparse": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.2.tgz", + "integrity": "sha512-BNbCHJkTE4RwmAFkCxEalET4mDvGr/1ld7ZtQ4i/laWI/iiVt+GL07stdvufle4KfywyvloqqpIiJscXNCrKxA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/parse5": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", + "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==", + "dev": true + }, + "@types/plist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.2.tgz", + "integrity": "sha512-ULqvZNGMv0zRFvqn8/4LSPtnmN4MfhlPNtJCTpKuIIxGVGZ2rYWzFXrvEBoh9CVyqSE7D6YFRJ1hydLHI6kbWw==", + "dev": true, + "optional": true, + "requires": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "@types/prettier": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.3.tgz", + "integrity": "sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==", + "dev": true, + "peer": true + }, + "@types/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-kd4LMvcnpYkspDcp7rmXKedn8iJSCoa331zRRamUp5oanKt/CefbEGPQP7G89enz7sKD4bvsr8mHSsC8j5WOvA==", + "dev": true, + "requires": { + "@types/retry": "*" + } + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true + }, + "@types/semver": { + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", + "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/tldjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@types/tldjs/-/tldjs-2.3.1.tgz", + "integrity": "sha512-BQR04zLE0ve2eNrqxXw/Qp/f6LxvNrj/4A8ZgdQi3SzbBqxFhleI7N4DS/mSjDnODrUaEGgoWg4grAZR1kVj8w==", + "dev": true + }, + "@types/tough-cookie": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", + "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", + "dev": true + }, + "@types/verror": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.5.tgz", + "integrity": "sha512-9UjMCHK5GPgQRoNbqdLIAvAy0EInuiqbW0PBMtVP6B5B2HQJlvoJHM+KodPZMEjOa5VkSc+5LH7xy+cUzQdmHw==", + "dev": true, + "optional": true + }, + "@types/vinyl": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.6.tgz", + "integrity": "sha512-ayJ0iOCDNHnKpKTgBG6Q6JOnHTj9zFta+3j2b8Ejza0e4cvRyMn0ZoLEmbPrTHe5YYRlDYPvPWVdV4cTaRyH7g==", + "dev": true, + "requires": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } + }, + "@types/webcrypto": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/@types/webcrypto/-/webcrypto-0.0.28.tgz", + "integrity": "sha512-jzAoSUvqA+183nJO/Sc73CREQJsv+p77WJdn532GqA3YXQzlwRwHhClVa7U4O8iB2sJSR7G3v6f1mJFNkwA9YQ==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.10.tgz", + "integrity": "sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "@types/zxcvbn": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@types/zxcvbn/-/zxcvbn-4.4.1.tgz", + "integrity": "sha512-3NoqvZC2W5gAC5DZbTpCeJ251vGQmgcWIHQJGq2J240HY6ErQ9aWKkwfoKJlHLx+A83WPNTZ9+3cd2ILxbvr1w==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz", + "integrity": "sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/type-utils": "5.27.0", + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "functional-red-black-tree": "^1.0.1", + "ignore": "^5.2.0", + "regexpp": "^3.2.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/parser": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.27.0.tgz", + "integrity": "sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz", + "integrity": "sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz", + "integrity": "sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.27.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.27.0.tgz", + "integrity": "sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz", + "integrity": "sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/visitor-keys": "5.27.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.27.0.tgz", + "integrity": "sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.27.0", + "@typescript-eslint/types": "5.27.0", + "@typescript-eslint/typescript-estree": "5.27.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz", + "integrity": "sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.27.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@webassemblyjs/ast": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", + "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", + "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", + "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", + "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", + "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", + "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", + "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", + "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", + "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", + "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", + "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/helper-wasm-section": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-opt": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "@webassemblyjs/wast-printer": "1.11.1" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", + "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", + "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-buffer": "1.11.1", + "@webassemblyjs/wasm-gen": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", + "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/helper-wasm-bytecode": "1.11.1", + "@webassemblyjs/ieee754": "1.11.1", + "@webassemblyjs/leb128": "1.11.1", + "@webassemblyjs/utf8": "1.11.1" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", + "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.1", + "@xtuc/long": "4.2.2" + } + }, + "@webpack-cli/configtest": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", + "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", + "dev": true, + "requires": {} + }, + "@webpack-cli/info": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.4.1.tgz", + "integrity": "sha512-PKVGmazEq3oAo46Q63tpMr4HipI3OPfP7LiNOEJg963RMgT0rqheag28NCML0o3GIzA3DmxP1ZIAv9oTX1CUIA==", + "dev": true, + "requires": { + "envinfo": "^7.7.3" + } + }, + "@webpack-cli/serve": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", + "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", + "dev": true, + "requires": {} + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "7zip-bin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.1.1.tgz", + "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", + "dev": true + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", + "integrity": "sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + } + } + }, + "acorn-import-assertions": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "dev": true, + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", + "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + } + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", + "dev": true + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "app-builder-bin": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-3.7.1.tgz", + "integrity": "sha512-ql93vEUq6WsstGXD+SBLSIQw6SNnhbDEM0swzgugytMxLp3rT24Ag/jcC80ZHxiPRTdew1niuR7P3/FCrDqIjw==", + "dev": true + }, + "app-builder-lib": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-22.14.13.tgz", + "integrity": "sha512-SufmrtxU+D0Tn948fjEwAOlCN9757UXLkzzTWXMwZKR/5hisvgqeeBepWfphMIE6OkDGz0fbzEhL1P2Pty4XMg==", + "dev": true, + "requires": { + "@develar/schema-utils": "~2.6.5", + "@electron/universal": "1.0.5", + "@malept/flatpak-bundler": "^0.4.0", + "7zip-bin": "~5.1.1", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.2", + "ejs": "^3.1.6", + "electron-osx-sign": "^0.5.0", + "electron-publish": "22.14.13", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "hosted-git-info": "^4.0.2", + "is-ci": "^3.0.0", + "isbinaryfile": "^4.0.8", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^3.0.4", + "read-config-file": "6.2.0", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.5", + "temp-file": "^3.4.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", + "dev": true + }, + "are-we-there-yet": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz", + "integrity": "sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "arg": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz", + "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==", + "dev": true + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "dev": true + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA==", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "dev": true + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-includes": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", + "integrity": "sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.7" + } + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "dev": true + }, + "array.prototype.flat": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz", + "integrity": "sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.2", + "es-shim-unscopables": "^1.0.0" + } + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "asar": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.1.0.tgz", + "integrity": "sha512-vyxPxP5arcAqN4F/ebHd/HhwnAiZtwhglvdmc7BR2f0ywbVNTOpSeyhLDbGXtE/y58hv1oC75TaNIXutnsOZsQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "dependencies": { + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "optional": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "atomically": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", + "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", + "dev": true + }, + "autoprefixer": { + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", + "dev": true, + "requires": { + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, + "babel-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", + "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", + "dev": true, + "peer": true, + "requires": { + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "peer": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", + "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "peer": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", + "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", + "dev": true, + "peer": true, + "requires": { + "babel-plugin-jest-hoist": "^27.5.1", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + } + } + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "big-integer": { + "version": "1.6.51", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", + "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "binaryextensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz", + "integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "requires": { + "bluebird": "^3.5.5" + } + }, + "body-parser": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "dev": true, + "optional": true + }, + "bootstrap": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.0.tgz", + "integrity": "sha512-Io55IuQY3kydzHtbGvQya3H+KorS/M9rSNyfCGCg9WZ4pyT/lCxIlpJgG1GXW/PswzC84Tr2fBYi+7+jFVQQBw==", + "requires": {} + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "braintree-web": { + "version": "3.85.3", + "resolved": "https://registry.npmjs.org/braintree-web/-/braintree-web-3.85.3.tgz", + "integrity": "sha512-slCnjD/YLFDmiOU0vxL7i4uifjRQV5Cw7dSkhRdXiIT+a8iQ7NxtL5FSomv45wuHqgdilZeQ8iB8guIrn6QgwA==", + "requires": { + "@braintree/asset-loader": "0.4.4", + "@braintree/browser-detection": "1.12.1", + "@braintree/class-list": "0.2.0", + "@braintree/event-emitter": "0.4.1", + "@braintree/extended-promise": "0.4.1", + "@braintree/iframer": "1.1.0", + "@braintree/sanitize-url": "6.0.0", + "@braintree/uuid": "0.1.0", + "@braintree/wrap-promise": "2.1.0", + "card-validator": "8.1.1", + "credit-card-type": "9.1.0", + "framebus": "5.1.2", + "inject-stylesheet": "5.0.0", + "promise-polyfill": "8.2.3", + "restricted-input": "3.0.5" + } + }, + "braintree-web-drop-in": { + "version": "1.33.2", + "resolved": "https://registry.npmjs.org/braintree-web-drop-in/-/braintree-web-drop-in-1.33.2.tgz", + "integrity": "sha512-2iqhHS6UQEvcRAWvI/CQ2OuJLHqXR+6UYBKkaa6T+DXa24/mdwErDTabJHSq8oAebsx3Va+9q06IveJfOoDfqA==", + "requires": { + "@braintree/asset-loader": "0.4.4", + "@braintree/browser-detection": "1.12.1", + "@braintree/class-list": "0.2.0", + "@braintree/event-emitter": "0.4.1", + "@braintree/uuid": "0.1.0", + "@braintree/wrap-promise": "2.1.0", + "braintree-web": "3.85.3", + "promise-polyfill": "8.2.3" + } + }, + "browser-hrtime": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/browser-hrtime/-/browser-hrtime-1.1.8.tgz", + "integrity": "sha512-kzXheikaJsBtzUBlyVtPIY5r0soQePzjwVwT4IlDpU2RvfB5Py52gpU98M77rgqMCheoSSZvrcrdj3t6cZ3suA==" + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" + }, + "browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "peer": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, + "builder-util": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-22.14.13.tgz", + "integrity": "sha512-oePC/qrrUuerhmH5iaCJzPRAKlSBylrhzuAJmRQClTyWnZUv6jbaHh+VoHMbEiE661wrj2S2aV7/bQh12cj1OA==", + "dev": true, + "requires": { + "@types/debug": "^4.1.6", + "@types/fs-extra": "^9.0.11", + "7zip-bin": "~5.1.1", + "app-builder-bin": "3.7.1", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "builder-util-runtime": { + "version": "8.9.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", + "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", + "dev": true, + "requires": { + "debug": "^4.3.2", + "sax": "^1.2.4" + } + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "dev": true, + "requires": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cache-content-type": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz", + "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==", + "requires": { + "mime-types": "^2.1.18", + "ylru": "^1.2.0" + } + }, + "cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "peer": true + }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001346", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001346.tgz", + "integrity": "sha512-q6ibZUO2t88QCIPayP/euuDREq+aMAxFE5S70PkrLh0iTDj/zEhgvJRKC2+CvXY6EWc6oQwUR48lL5vCW6jiXQ==", + "dev": true + }, + "canonical-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/canonical-path/-/canonical-path-1.0.0.tgz", + "integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==", + "dev": true + }, + "card-validator": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/card-validator/-/card-validator-8.1.1.tgz", + "integrity": "sha512-cN4FsKwoTfTFnqPwVc7TQLSsH/QMDB3n/gWm0XelcApz4sKipnOQ6k33sa3bWsNnnIpgs7eXOF+mUV2UQAX2Sw==", + "requires": { + "credit-card-type": "^9.1.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "peer": true + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.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" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true + }, + "ci-info": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.1.tgz", + "integrity": "sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", + "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "dev": true, + "peer": true + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + } + } + }, + "clean-css": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz", + "integrity": "sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "clean-webpack-plugin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/clean-webpack-plugin/-/clean-webpack-plugin-4.0.0.tgz", + "integrity": "sha512-WuWE1nyTNAyW5T7oNyys2EN0cfP2fdRxhxnIQWiAp0bMabPdHhoGxM8A6YL2GhqwgrPnnaemVE7nv5XJ2Fhh2w==", + "dev": true, + "requires": { + "del": "^4.1.1" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + } + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + }, + "co-body": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/co-body/-/co-body-6.1.0.tgz", + "integrity": "sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==", + "requires": { + "inflation": "^2.0.0", + "qs": "^6.5.2", + "raw-body": "^2.3.3", + "type-is": "^1.6.16" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", + "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "dev": true, + "peer": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA==", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + }, + "compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compress-brotli": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/compress-brotli/-/compress-brotli-1.3.8.tgz", + "integrity": "sha512-lVcQsjhxhIXsuupfy9fmZUFtAIdBmXA7EGY6GBdgZ++qkM9zG4YFT8iU7FoBxzryNDMOpD1HIFHUSX4D87oqhQ==", + "dev": true, + "requires": { + "@types/json-buffer": "~3.0.0", + "json-buffer": "~3.0.1" + }, + "dependencies": { + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + } + } + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concurrently": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.2.1.tgz", + "integrity": "sha512-7cab/QyqipqghrVr9qZmoWbidu0nHsmxrpNqQ7r/67vfl1DWJElexehQnTH1p+87tDkihaAjM79xTZyBQh7HLw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "date-fns": "^2.16.1", + "lodash": "^4.17.21", + "rxjs": "^6.6.3", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "dependencies": { + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "conf": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/conf/-/conf-10.1.2.tgz", + "integrity": "sha512-o9Fv1Mv+6A0JpoayQ8JleNp3hhkbOJP/Re/Q+QqxMPHPkABVsRjQGWZn9A5GcqLiTNC6d89p2PB5ZhHVDSMwyg==", + "dev": true, + "requires": { + "ajv": "^8.6.3", + "ajv-formats": "^2.1.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", + "env-paths": "^2.2.1", + "json-schema-typed": "^7.0.3", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.5" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + } + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "dev": true + }, + "cookies": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", + "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", + "requires": { + "depd": "~2.0.0", + "keygrip": "~1.1.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "dev": true + }, + "copy-props": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "dev": true, + "requires": { + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + } + }, + "copy-to": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/copy-to/-/copy-to-2.0.1.tgz", + "integrity": "sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==" + }, + "copy-webpack-plugin": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", + "integrity": "sha512-xFVltahqlsRcyyJqQbDY6EYTtyQZF9rf+JPjwHObLdPFMEISqkFkr7mFoVOC6BfYS/dNThyoQKvziugm+OnwBg==", + "dev": true, + "requires": { + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "array-union": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-3.0.1.tgz", + "integrity": "sha512-1OvF9IbWwaeiM9VhzYXVQacMibxpXOMYVNIvMtKRyX9SImBXpKcFr8XvFDeEslCyuH/t6KRt7HEO94AlP8Iatw==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globby": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-12.2.0.tgz", + "integrity": "sha512-wiSuFQLZ+urS9x2gGPl1H5drc5twabmm4m2gTR27XDFyjUHJUNsS8o/2aKyIF6IoBaR630atdher0XJ5g6OMmA==", + "dev": true, + "requires": { + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true + } + } + }, + "core-js": { + "version": "3.22.8", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.22.8.tgz", + "integrity": "sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "optional": true, + "requires": { + "buffer": "^5.1.0" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "optional": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, + "credit-card-type": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/credit-card-type/-/credit-card-type-9.1.0.tgz", + "integrity": "sha512-CpNFuLxiPFxuZqhSKml3M+t0K/484pMAnfYWH14JoD7OZMnmC0Lmo+P7JX9SobqFpRoo7ifA18kOHdxJywYPEA==" + }, + "cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, + "css-loader": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", + "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.7", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.5" + } + }, + "css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" + } + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "date-fns": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "dev": true + }, + "date-input-polyfill": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/date-input-polyfill/-/date-input-polyfill-2.14.0.tgz", + "integrity": "sha512-LUfuBYYlayDyBbQCIMN1RyrDaTmy5pa3u3jIDoWTXk/7tPgOajZczjWZA2ITd/+lbhtUBM6fhT+Grxs1yYATVA==", + "requires": { + "babel-runtime": "^6.11.6" + } + }, + "debounce-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", + "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", + "dev": true, + "requires": { + "mimic-fn": "^3.0.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", + "dev": true, + "peer": true + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + } + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ==", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + } + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==" + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "dev": true + }, + "del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "dev": true, + "requires": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==" + }, + "dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "dev": true + }, + "detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "peer": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "diff-sequences": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", + "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", + "dev": true + }, + "dir-compare": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", + "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==", + "dev": true, + "requires": { + "buffer-equal": "1.0.0", + "colors": "1.0.3", + "commander": "2.9.0", + "minimatch": "3.0.4" + }, + "dependencies": { + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "dmg-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-22.14.13.tgz", + "integrity": "sha512-xNOugB6AbIRETeU2uID15sUfjdZZcKdxK8xkFnwIggsM00PJ12JxpLNPTjcRoUnfwj3WrPjilrO64vRMwNItQg==", + "dev": true, + "requires": { + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "dmg-license": "^1.0.9", + "fs-extra": "^10.0.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "optional": true, + "requires": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", + "dev": true + }, + "dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==" + } + } + }, + "domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + } + }, + "domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true + }, + "dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true + }, + "duo_web_sdk": { + "version": "git+ssh://git@github.com/duosecurity/duo_web_sdk.git#f43ff8f1325f8630d0cff1cd9fb0df13d22cf28d", + "from": "duo_web_sdk@github:duosecurity/duo_web_sdk" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA==", + "dev": true + }, + "duplexify": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", + "integrity": "sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==", + "dev": true, + "requires": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "easy-stack": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", + "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", + "dev": true + }, + "editorconfig": { + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, + "electron": { + "version": "16.2.7", + "resolved": "https://registry.npmjs.org/electron/-/electron-16.2.7.tgz", + "integrity": "sha512-aZKF3b00+rqW/HGs8lJM5DhPNj+mOfCuhLSiFXV6J9dQCIRhctJTmToOrwXfbCxvXK8as8eQTNl5uSfnHmH6tA==", + "dev": true, + "requires": { + "@electron/get": "^1.13.0", + "@types/node": "^14.6.2", + "extract-zip": "^1.0.3" + }, + "dependencies": { + "@types/node": { + "version": "14.18.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.20.tgz", + "integrity": "sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA==", + "dev": true + } + } + }, + "electron-builder": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-22.14.13.tgz", + "integrity": "sha512-3fgLxqF2TXVKiUPeg74O4V3l0l3j7ERLazo8sUbRkApw0+4iVAf2BJkHsHMaXiigsgCoEzK/F4/rB5rne/VAnw==", + "dev": true, + "requires": { + "@types/yargs": "^17.0.1", + "app-builder-lib": "22.14.13", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "dmg-builder": "22.14.13", + "fs-extra": "^10.0.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.2.0", + "update-notifier": "^5.1.0", + "yargs": "^17.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "electron-log": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-4.4.7.tgz", + "integrity": "sha512-uFZQdgevOp9Fn5lDOrJMU/bmmYxDLZitbIHJM7VXN+cpB59ZnPt1FQL4bOf/Dl2gaIMPYJEfXx38GvJma5iV6A==", + "dev": true + }, + "electron-notarize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.1.tgz", + "integrity": "sha512-u/ECWhIrhkSQpZM4cJzVZ5TsmkaqrRo5LDC/KMbGF0sPkm53Ng59+M0zp8QVaql0obfJy9vlVT+4iOkAi2UDlA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "electron-osx-sign": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.5.0.tgz", + "integrity": "sha512-icoRLHzFz/qxzDh/N4Pi2z4yVHurlsCAYQvsCSG7fCedJ4UJXBS6PoQyGH71IfcqKupcKeK7HX/NkyfG+v6vlQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "electron-publish": { + "version": "22.14.13", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.14.13.tgz", + "integrity": "sha512-0oP3QiNj3e8ewOaEpEJV/o6Zrmy2VarVvZ/bH7kyO/S/aJf9x8vQsKVWpsdmSiZ5DJEHgarFIXrnO0ZQf0P9iQ==", + "dev": true, + "requires": { + "@types/fs-extra": "^9.0.11", + "builder-util": "22.14.13", + "builder-util-runtime": "8.9.2", + "chalk": "^4.1.1", + "fs-extra": "^10.0.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "electron-rebuild": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/electron-rebuild/-/electron-rebuild-3.2.7.tgz", + "integrity": "sha512-WvaW1EgRinDQ61khHFZfx30rkPQG5ItaOT0wrI7iJv9A3SbghriQGfZQfHZs25fWLBe6/vkv05LOqg6aDw6Wzw==", + "dev": true, + "requires": { + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^1.0.3", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "lzma-native": "^8.0.5", + "node-abi": "^3.0.0", + "node-api-version": "^0.1.4", + "node-gyp": "^8.4.0", + "ora": "^5.1.0", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" + }, + "dependencies": { + "@malept/cross-spawn-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", + "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.1" + } + }, + "@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "got": { + "version": "11.8.5", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.5.tgz", + "integrity": "sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + } + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "keyv": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.3.0.tgz", + "integrity": "sha512-C30Un9+63J0CsR7Wka5quXKqYZsT6dcRQ2aOwGcSc3RiQ4HGWpTAHlCA+puNfw2jA/s11EsxA1nCXgZRuRKMQQ==", + "dev": true, + "requires": { + "compress-brotli": "^1.3.8", + "json-buffer": "3.0.1" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true + }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true + }, + "responselike": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz", + "integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==", + "dev": true, + "requires": { + "lowercase-keys": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "electron-reload": { + "version": "2.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/electron-reload/-/electron-reload-2.0.0-alpha.1.tgz", + "integrity": "sha512-hTde7gv0TEqxbxlB3pj2CwoyCQ9sdiQrcP8GkpzhosxyVeYM3mZbMEVKCZK3L0fED7Mz5A9IWmK7zEvi4H3P1g==", + "dev": true, + "requires": { + "chokidar": "^3.5.2" + } + }, + "electron-store": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-8.0.1.tgz", + "integrity": "sha512-ZyLvNywiqSpbwC/pp89O/AycVWY/UJIkmtyzF2Bd0Nm/rLmcFc0NTGuLdg6+LE8mS8qsiK5JMoe4PnrecLHH5w==", + "dev": true, + "requires": { + "conf": "^10.0.3", + "type-fest": "^1.0.2" + } + }, + "electron-to-chromium": { + "version": "1.4.144", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.144.tgz", + "integrity": "sha512-R3RV3rU1xWwFJlSClVWDvARaOk6VUO/FubHLodIASDB3Mc2dzuWvNdfOgH9bwHUTqT79u92qw60NWfwUdzAqdg==", + "dev": true + }, + "electron-updater": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.0.1.tgz", + "integrity": "sha512-dNnXPCqYmergXy3jgg4UICuD50Orug9GQe/5xfHy+BE2Fy0icB0QE+y6iQWdCDf7yeONxwMBf4HgIkGG5pIaVg==", + "dev": true, + "requires": { + "@types/semver": "^7.3.6", + "builder-util-runtime": "9.0.0", + "fs-extra": "^10.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "^7.3.5" + }, + "dependencies": { + "builder-util-runtime": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.0.0.tgz", + "integrity": "sha512-SkpEtSmTkREDHRJnxKEv43aAYp8sYWY8fxYBhGLBLOBIRXeaIp6Kv3lBgSD7uR8jQtC7CA659sqJrpSV6zNvSA==", + "dev": true, + "requires": { + "debug": "^4.3.2", + "sax": "^1.2.4" + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "emittery": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", + "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "dev": true, + "peer": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz", + "integrity": "sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "dependencies": { + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + } + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true + }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" + } + }, + "es-module-lexer": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", + "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "dev": true + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "dev": true, + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-denodeify": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-denodeify/-/es6-denodeify-0.1.5.tgz", + "integrity": "sha512-731Rf4NqlPvhkT1pIF7r8vZxESJlWocNpXLuyPlVnfEGXlwuJaMvU5WpyyDjpudDC2cgXVX849xljzvQqBg1QQ==" + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "eslint": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.16.0.tgz", + "integrity": "sha512-MBndsoXY/PeVTDJeWsYj7kLZ5hQpJOfMYLsF6LicLHQWbRDG19lK5jOix4DPl8yY4SUFcE3txy86OzFLWT+yoA==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.2", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.15.0.tgz", + "integrity": "sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "requires": {} + }, + "eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-import-resolver-typescript": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz", + "integrity": "sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==", + "dev": true, + "requires": { + "debug": "^4.3.4", + "glob": "^7.2.0", + "is-glob": "^4.0.3", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + } + }, + "eslint-module-utils": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz", + "integrity": "sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "find-up": "^2.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", + "dev": true, + "requires": { + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.2.tgz", + "integrity": "sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==", + "dev": true, + "requires": { + "acorn": "^8.7.1", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true + }, + "event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", + "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", + "dev": true + }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "eventsource": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.1.tgz", + "integrity": "sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA==", + "requires": { + "original": "^1.0.0" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + } + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "peer": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "expect": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", + "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1" + } + }, + "express": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.1.tgz", + "integrity": "sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==", + "dev": true, + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.0", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.10.3", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "dev": true + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + } + } + }, + "extract-zip": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", + "dev": true, + "requires": { + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "optional": true + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", + "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "dev": true, + "peer": true, + "requires": { + "bser": "2.1.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "fetch-cookie": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.7.3.tgz", + "integrity": "sha512-rZPkLnI8x5V+zYAiz8QonAHsTb4BY+iFowFBI1RFn0zrO343AVp9X7/yUj/9wL6Ef/8fLls8b/vGtzUvmyAUGA==", + "requires": { + "es6-denodeify": "^0.1.1", + "tough-cookie": "^2.3.3" + } + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", + "dev": true + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forcefocus": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/forcefocus/-/forcefocus-1.1.0.tgz", + "integrity": "sha512-bnY7rul5kBLyNoCn0FHNiFAF+GGUZx6TvxWhurUS4PlmOzF+FMixGIigHH5UcyM3w1gp2TxAtP6MOUSXA15Sgw==", + "dev": true, + "requires": { + "bindings": "^1.3.0", + "prebuild-install": "^5.0.0" + } + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha512-Pqq5NnT78ehvUnAk/We/Jr22vSvanRlFTpAmQ88xBY/M1TlHe+P0ILuEyXS595ysdGfaj22634LBkGMA2GTcpA==", + "dev": true + }, + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "framebus": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/framebus/-/framebus-5.1.2.tgz", + "integrity": "sha512-Z/y6/0gHVx4Td4c0jkDiASBo0pXlJ2fKOP6CynSFnxTzqojG9xOKOFOqoYkcBHlz1vP4t4yHHR6Esp+GsYIh/Q==", + "requires": { + "@braintree/uuid": "^0.1.0" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "fs-monkey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", + "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "peer": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + } + }, + "global-dirs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz", + "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==", + "dev": true, + "requires": { + "ini": "2.0.0" + }, + "dependencies": { + "ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "dev": true + } + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "global-tunnel-ng": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", + "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", + "dev": true, + "optional": true, + "requires": { + "encodeurl": "^1.0.2", + "lodash": "^4.17.10", + "npm-conf": "^1.1.3", + "tunnel": "^0.0.6" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", + "dev": true + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + } + }, + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "yargs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } + }, + "gulp-filter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-7.0.0.tgz", + "integrity": "sha512-ZGWtJo0j1mHfP77tVuhyqem4MRA5NfNRjoVe6VAkLGeQQ/QGo2VsFwp7zfPTGDsd1rwzBmoDHhxpE6f5B3Zuaw==", + "dev": true, + "requires": { + "multimatch": "^5.0.0", + "plugin-error": "^1.0.1", + "streamfilter": "^3.0.0", + "to-absolute-glob": "^2.0.2" + } + }, + "gulp-if": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-3.0.0.tgz", + "integrity": "sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw==", + "dev": true, + "requires": { + "gulp-match": "^1.1.0", + "ternary-stream": "^3.0.0", + "through2": "^3.0.1" + } + }, + "gulp-json-editor": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/gulp-json-editor/-/gulp-json-editor-2.5.6.tgz", + "integrity": "sha512-66Xr6Q6m4mUNd0OOHflMB/RHgFNnLjlHgizOzUcx9CyMRymVZEM+/SpZcCDlvThBdXtQwXpdvtSepxVY/V6nQA==", + "dev": true, + "requires": { + "deepmerge": "^4.2.2", + "detect-indent": "^6.0.0", + "js-beautify": "^1.13.13", + "plugin-error": "^1.0.1", + "through2": "^4.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + } + } + }, + "gulp-match": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", + "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.3" + } + }, + "gulp-replace": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.3.tgz", + "integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==", + "dev": true, + "requires": { + "@types/node": "^14.14.41", + "@types/vinyl": "^2.0.4", + "istextorbinary": "^3.0.0", + "replacestream": "^4.0.3", + "yargs-parser": ">=5.0.0-security.0" + }, + "dependencies": { + "@types/node": { + "version": "14.18.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.20.tgz", + "integrity": "sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA==", + "dev": true + } + } + }, + "gulp-zip": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-zip/-/gulp-zip-5.1.0.tgz", + "integrity": "sha512-XZr/y91IliK/SpR74g3TkZejGkGEmK7CSDjSghT1jXshgO+dFvpLIz9w9fpuwkew6i7k4F+G24TubNgq1ISzEw==", + "dev": true, + "requires": { + "get-stream": "^5.2.0", + "plugin-error": "^1.0.1", + "through2": "^3.0.1", + "vinyl": "^2.1.0", + "yazl": "^2.5.1" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", + "dev": true, + "requires": { + "glogg": "^1.0.0" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-entities": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", + "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "peer": true + }, + "html-loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-3.1.0.tgz", + "integrity": "sha512-ycMYFRiCF7YANcLDNP72kh3Po5pTcH+bROzdDwh00iVOAY/BwvpuZ1BKPziQ35Dk9D+UD84VGX1Lu/H4HpO4fw==", + "dev": true, + "requires": { + "html-minifier-terser": "^6.0.2", + "parse5": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + } + } + }, + "html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "dependencies": { + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + } + } + }, + "html-webpack-injector": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/html-webpack-injector/-/html-webpack-injector-1.1.4.tgz", + "integrity": "sha512-R+HeAYzPeL3dKIr5/a7a2S6R4fy2yHetKiB7cz5rXjwlnU5tghuy58kCBsKA/Qoj94MAgCYwllHmvYqy2nJSdg==", + "dev": true + }, + "html-webpack-plugin": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "dev": true, + "requires": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "dependencies": { + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + } + } + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "http-assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz", + "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==", + "requires": { + "deep-equal": "~1.0.1", + "http-errors": "~1.8.0" + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "http-parser-js": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.6.tgz", + "integrity": "sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + } + }, + "http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true + }, + "iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "optional": true, + "requires": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "devOptional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "if-async": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/if-async/-/if-async-3.7.4.tgz", + "integrity": "sha512-BFEH2mZyeF6KZKaKLVPZ0wMjIiWOdjvZ7zbx8ENec0qfZhJwKFbX/4jKM5LTKyJEc/GOqUKiiJ2IFKT9yWrZqA==", + "dev": true + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A==", + "dev": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflation": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz", + "integrity": "sha512-m3xv4hJYR2oXw4o4Y5l6P5P16WYmazYof+el6Al3f+YlggGj6qT9kImBAnzDelRALnP5d3h4jGBPKzYCizjZZw==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "inject-stylesheet": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/inject-stylesheet/-/inject-stylesheet-5.0.0.tgz", + "integrity": "sha512-GzncrJP8E/pavMQzoO93CXoYCfTttwVm2cX2TyXJdgtVE0cCvWSFCn1/uMsM6ZkEg7LUsOcKuamcLiGWlv2p9A==" + }, + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + } + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "into-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-6.0.0.tgz", + "integrity": "sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==", + "dev": true, + "requires": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "dev": true + }, + "ip": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", + "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", + "dev": true + }, + "ipaddr.js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", + "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "requires": { + "ci-info": "^3.2.0" + } + }, + "is-core-module": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", + "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "peer": true + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "dev": true, + "requires": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-npm": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-5.0.0.tgz", + "integrity": "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + }, + "dependencies": { + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + } + } + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", + "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", + "dev": true + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "peer": true + }, + "istanbul-lib-instrument": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz", + "integrity": "sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "peer": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "peer": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "peer": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "peer": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "istextorbinary": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-3.3.0.tgz", + "integrity": "sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==", + "dev": true, + "requires": { + "binaryextensions": "^2.2.0", + "textextensions": "^3.2.0" + } + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + } + }, + "jasmine-core": { + "version": "3.99.1", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz", + "integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==", + "dev": true + }, + "jasmine-spec-reporter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-7.0.0.tgz", + "integrity": "sha512-OtC7JRasiTcjsaCBPtMO0Tl8glCejM4J4/dNuOJdA8lBjz4PmWjYQ6pzb0uzpBNAWJMDudYuj9OdXJWqM2QTJg==", + "dev": true, + "requires": { + "colors": "1.4.0" + }, + "dependencies": { + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + } + } + }, + "jest": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", + "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/core": "^27.5.1", + "import-local": "^3.0.2", + "jest-cli": "^27.5.1" + } + }, + "jest-changed-files": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", + "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "execa": "^5.0.0", + "throat": "^6.0.1" + } + }, + "jest-circus": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", + "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^0.7.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3", + "throat": "^6.0.1" + } + }, + "jest-cli": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", + "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", + "dev": true, + "peer": true, + "requires": { + "@jest/core": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + }, + "dependencies": { + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "peer": true, + "requires": { + "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-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "peer": true + } + } + }, + "jest-config": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", + "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.8.0", + "@jest/test-sequencer": "^27.5.1", + "@jest/types": "^27.5.1", + "babel-jest": "^27.5.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.9", + "jest-circus": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-jasmine2": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runner": "^27.5.1", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "jest-diff": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", + "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-docblock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", + "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", + "dev": true, + "peer": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", + "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-environment-jsdom": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", + "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", + "dev": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1", + "jsdom": "^16.6.0" + } + }, + "jest-environment-node": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", + "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "jest-mock": "^27.5.1", + "jest-util": "^27.5.1" + } + }, + "jest-get-type": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", + "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", + "dev": true + }, + "jest-haste-map": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", + "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^27.5.1", + "jest-serializer": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "micromatch": "^4.0.4", + "walker": "^1.0.7" + } + }, + "jest-jasmine2": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", + "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^27.5.1", + "is-generator-fn": "^2.0.0", + "jest-each": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "pretty-format": "^27.5.1", + "throat": "^6.0.1" + } + }, + "jest-leak-detector": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", + "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", + "dev": true, + "peer": true, + "requires": { + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-matcher-utils": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", + "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "pretty-format": "^27.5.1" + } + }, + "jest-message-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", + "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^27.5.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^27.5.1", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + } + }, + "jest-mock": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", + "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*" + } + }, + "jest-pnp-resolver": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "dev": true, + "peer": true, + "requires": {} + }, + "jest-preset-angular": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-10.1.0.tgz", + "integrity": "sha512-D4k+BnGoig3w1x4MZiQOdN8UfaLN5aNjmx91U28VYRA+LslbN+D8dGyb5a5lR32mog5y86iVnAZ4mRvFlYr7SQ==", + "dev": true, + "requires": { + "jest-environment-jsdom": "^27.0.0", + "pretty-format": "^27.0.0", + "ts-jest": "^27.0.0" + } + }, + "jest-regex-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", + "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", + "dev": true, + "peer": true + }, + "jest-resolve": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", + "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^27.5.1", + "jest-validate": "^27.5.1", + "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", + "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-snapshot": "^27.5.1" + } + }, + "jest-runner": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", + "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/console": "^27.5.1", + "@jest/environment": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.8.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^27.5.1", + "jest-environment-jsdom": "^27.5.1", + "jest-environment-node": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-leak-detector": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-runtime": "^27.5.1", + "jest-util": "^27.5.1", + "jest-worker": "^27.5.1", + "source-map-support": "^0.5.6", + "throat": "^6.0.1" + } + }, + "jest-runtime": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", + "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", + "dev": true, + "peer": true, + "requires": { + "@jest/environment": "^27.5.1", + "@jest/fake-timers": "^27.5.1", + "@jest/globals": "^27.5.1", + "@jest/source-map": "^27.5.1", + "@jest/test-result": "^27.5.1", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-mock": "^27.5.1", + "jest-regex-util": "^27.5.1", + "jest-resolve": "^27.5.1", + "jest-snapshot": "^27.5.1", + "jest-util": "^27.5.1", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + } + }, + "jest-serializer": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", + "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", + "dev": true, + "peer": true, + "requires": { + "@types/node": "*", + "graceful-fs": "^4.2.9" + } + }, + "jest-snapshot": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", + "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", + "dev": true, + "peer": true, + "requires": { + "@babel/core": "^7.7.2", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/traverse": "^7.7.2", + "@babel/types": "^7.0.0", + "@jest/transform": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/babel__traverse": "^7.0.4", + "@types/prettier": "^2.1.5", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^27.5.1", + "graceful-fs": "^4.2.9", + "jest-diff": "^27.5.1", + "jest-get-type": "^27.5.1", + "jest-haste-map": "^27.5.1", + "jest-matcher-utils": "^27.5.1", + "jest-message-util": "^27.5.1", + "jest-util": "^27.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^27.5.1", + "semver": "^7.3.2" + } + }, + "jest-util": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", + "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", + "dev": true, + "requires": { + "@jest/types": "^27.5.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", + "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", + "dev": true, + "peer": true, + "requires": { + "@jest/types": "^27.5.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^27.5.1", + "leven": "^3.1.0", + "pretty-format": "^27.5.1" + }, + "dependencies": { + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "peer": true + } + } + }, + "jest-watcher": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", + "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", + "dev": true, + "peer": true, + "requires": { + "@jest/test-result": "^27.5.1", + "@jest/types": "^27.5.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^27.5.1", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jquery": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz", + "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" + }, + "js-beautify": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", + "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", + "dev": true, + "requires": { + "config-chain": "^1.1.13", + "editorconfig": "^0.15.3", + "glob": "^7.1.3", + "nopt": "^5.0.0" + } + }, + "js-message": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", + "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", + "dev": true + }, + "js-queue": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz", + "integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==", + "dev": true, + "requires": { + "easy-stack": "^1.0.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "ws": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.8.tgz", + "integrity": "sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==", + "requires": {} + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-schema-typed": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", + "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jszip": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.0.tgz", + "integrity": "sha512-LDfVtOLtOxb9RXkYOwPyNBTQDL4eUbqahtoY6x07GiDJHwSYvn8sHHIw8wINImV3MqbMNve2gSuM1DDqEKk09Q==", + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "dev": true + }, + "keygrip": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", + "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", + "requires": { + "tsscmp": "1.0.6" + } + }, + "keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "requires": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + } + }, + "detect-libc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", + "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + }, + "node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "prebuild-install": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.0.tgz", + "integrity": "sha512-CNcMgI1xBypOyGqjp3wOc8AAo1nMhZS3Cwd3iHIxOdAUbb+YxdNuM4Z5iIrZ8RLvOsf3F3bl7b7xGq6DjQoNYA==", + "dev": true, + "requires": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "requires": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "peer": true + }, + "klona": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", + "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "dev": true + }, + "koa": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz", + "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==", + "requires": { + "accepts": "^1.3.5", + "cache-content-type": "^1.0.0", + "content-disposition": "~0.5.2", + "content-type": "^1.0.4", + "cookies": "~0.8.0", + "debug": "^4.3.2", + "delegates": "^1.0.0", + "depd": "^2.0.0", + "destroy": "^1.0.4", + "encodeurl": "^1.0.2", + "escape-html": "^1.0.3", + "fresh": "~0.5.2", + "http-assert": "^1.3.0", + "http-errors": "^1.6.3", + "is-generator-function": "^1.0.7", + "koa-compose": "^4.1.0", + "koa-convert": "^2.0.0", + "on-finished": "^2.3.0", + "only": "~0.0.2", + "parseurl": "^1.3.2", + "statuses": "^1.5.0", + "type-is": "^1.6.16", + "vary": "^1.1.2" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "koa-bodyparser": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/koa-bodyparser/-/koa-bodyparser-4.3.0.tgz", + "integrity": "sha512-uyV8G29KAGwZc4q/0WUAjH+Tsmuv9ImfBUF2oZVyZtaeo0husInagyn/JH85xMSxM0hEk/mbCII5ubLDuqW/Rw==", + "requires": { + "co-body": "^6.0.0", + "copy-to": "^2.0.1" + } + }, + "koa-compose": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz", + "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==" + }, + "koa-convert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz", + "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==", + "requires": { + "co": "^4.6.0", + "koa-compose": "^4.1.0" + } + }, + "koa-is-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/koa-is-json/-/koa-is-json-1.0.0.tgz", + "integrity": "sha512-+97CtHAlWDx0ndt0J8y3P12EWLwTLMXIfMnYDev3wOTwH/RpBGMlfn4bDXlMEg1u73K6XRE9BbUp+5ZAYoRYWw==" + }, + "koa-json": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/koa-json/-/koa-json-2.0.2.tgz", + "integrity": "sha512-8+dz0T2ekDuNN1svYoKPCV2txotQ3Ufg8Fn5bft1T48MPJWiC/HKmkk+3xj9EC/iNZuFYeLRazN2h2o3RSUXuQ==", + "requires": { + "koa-is-json": "1", + "streaming-json-stringify": "3" + } + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true + }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "peer": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "requires": { + "immediate": "~3.0.5" + } + }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true + }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "lint-staged": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-12.5.0.tgz", + "integrity": "sha512-BKLUjWDsKquV/JuIcoQW4MSAI3ggwEImF1+sB4zaKvyVx1wBk3FsG7UK9bpnmBTN1pm7EH2BBcMwINJzCRv12g==", + "dev": true, + "requires": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.16", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^5.1.1", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.5.0", + "string-argv": "^0.3.1", + "supports-color": "^9.2.2", + "yaml": "^1.10.2" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.1.0.tgz", + "integrity": "sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==", + "dev": true + }, + "cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + } + }, + "commander": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.3.0.tgz", + "integrity": "sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "supports-color": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.2.2.tgz", + "integrity": "sha512-XC6g/Kgux+rJXmwokjm9ECpD6k/smUoS5LKlUCcsYr4IY3rW0XyAympon2RmxGrlnZURMpg5T18gWDP9CsHXFA==", + "dev": true + } + } + }, + "listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "dependencies": { + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, + "lowdb": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowdb/-/lowdb-1.0.0.tgz", + "integrity": "sha512-2+x8esE/Wb9SQ1F9IHaYWfsC9FIecLOPrK4g17FGEayjUWH172H6nwicRovGvSE2CPZouc2MCIqCI7h9d+GftQ==", + "requires": { + "graceful-fs": "^4.1.3", + "is-promise": "^2.1.0", + "lodash": "4", + "pify": "^3.0.0", + "steno": "^0.4.1" + } + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + }, + "lzma-native": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/lzma-native/-/lzma-native-8.0.6.tgz", + "integrity": "sha512-09xfg67mkL2Lz20PrrDeNYZxzeW7ADtpYFbwSQh9U8+76RIzx5QsJBMy8qikv3hbUPfpy6hqwxt6FcGK81g9AA==", + "dev": true, + "requires": { + "node-addon-api": "^3.1.0", + "node-gyp-build": "^4.2.1", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "dev": true, + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "dependencies": { + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + } + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "peer": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, + "matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "requires": { + "escape-string-regexp": "^4.0.0" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "memfs": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.4.tgz", + "integrity": "sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==", + "dev": true, + "requires": { + "fs-monkey": "1.0.3" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz", + "integrity": "sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==", + "dev": true, + "requires": { + "schema-utils": "^4.0.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "minipass": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "dev": true, + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true + }, + "mousetrap": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.5.tgz", + "integrity": "sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "msgpack5": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/msgpack5/-/msgpack5-4.5.1.tgz", + "integrity": "sha512-zC1vkcliryc4JGlL6OfpHumSYUHWFGimSI+OgfRCjTFLmKA2/foR9rMTOhWiqfOrfxJOctrpWPvrppf8XynJxw==", + "requires": { + "bl": "^2.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.3.6", + "safe-buffer": "^5.1.2" + } + }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", + "dev": true + }, + "multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, + "multistream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/multistream/-/multistream-4.1.0.tgz", + "integrity": "sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==", + "dev": true, + "requires": { + "once": "^1.4.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==", + "dev": true + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "ngx-infinite-scroll": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ngx-infinite-scroll/-/ngx-infinite-scroll-10.0.1.tgz", + "integrity": "sha512-7is0eJZ9kJPsaHohRmMhJ/QFHAW9jp9twO5HcHRvFM/Yl/R8QCiokgjwmH0/CR3MuxUanxfHZMfO3PbYTwlBEg==", + "requires": { + "@scarf/scarf": "^1.1.0", + "opencollective-postinstall": "^2.0.2" + } + }, + "ngx-toastr": { + "version": "14.1.4", + "resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-14.1.4.tgz", + "integrity": "sha512-t1/9r+pOXm65LIl0gevvFat6XIl0g3tMA8UOArFjI4ta/nGwDe/14J/f4cZvOBDcomedvjvGAWi+d/2URdSTBg==", + "requires": { + "tslib": "^2.2.0" + } + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node-abi": { + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.22.0.tgz", + "integrity": "sha512-u4uAs/4Zzmp/jjsD9cyFYDXeISfUWaAVWshPmDZOFOv4Xl4SbzTXm53I04C2uRueYJ+0t5PEtLH/owbn2Npf/w==", + "dev": true, + "requires": { + "semver": "^7.3.5" + } + }, + "node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "optional": true + }, + "node-api-version": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.1.4.tgz", + "integrity": "sha512-KGXihXdUChwJAOHO53bv9/vXcLmdUsZ6jIptbvYvkpKfth+r7jw44JkVxQFA3kX5nQjzjmGu1uAu/xNNLNlI5g==", + "dev": true, + "requires": { + "semver": "^7.3.5" + } + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==" + }, + "node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + } + }, + "node-gyp-build": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", + "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "peer": true + }, + "node-ipc": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz", + "integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==", + "dev": true, + "requires": { + "event-pubsub": "4.3.0", + "js-message": "1.0.7", + "js-queue": "2.0.2" + } + }, + "node-releases": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.5.tgz", + "integrity": "sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==", + "dev": true + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha512-6kM8CLXvuW5crTxsAtva2YLrRrDaiTIkIePWs9moLHqbFWT94WpNFjwS/5dfLfECg5i/lkmw3aoqVidxt23TEQ==", + "dev": true + }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "nord": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nord/-/nord-0.2.1.tgz", + "integrity": "sha512-/AD7JGJbcp1pB5XwYkJyivqdeXofUP5u2lkif6vLGLc+SsV9OCC0JFNpVwM5pqHuFqbyojRt6xILuidJOwwJDQ==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "dev": true, + "optional": true, + "requires": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true + }, + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw==", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.values": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz", + "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + } + } + }, + "only": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz", + "integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==" + }, + "open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==" + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "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.3" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "dependencies": { + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true + } + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "papaparse": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz", + "integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw==" + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", + "optional": true + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "dev": true + }, + "path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pidtree": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.5.0.tgz", + "integrity": "sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pirates": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true, + "peer": true + }, + "pkg": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/pkg/-/pkg-5.7.0.tgz", + "integrity": "sha512-PTiAjNq/CGAtK5qUBR6pjheqnipTFjeecgSgIKEcAOJA4GpmZeOZC8pMOoT0rfes5vHsmcFo7wbSRTAmXQurrg==", + "dev": true, + "requires": { + "@babel/parser": "7.17.10", + "@babel/types": "7.17.10", + "chalk": "^4.1.2", + "escodegen": "^2.0.0", + "fs-extra": "^9.1.0", + "globby": "^11.1.0", + "into-stream": "^6.0.0", + "is-core-module": "2.9.0", + "minimist": "^1.2.6", + "multistream": "^4.1.0", + "pkg-fetch": "3.4.1", + "prebuild-install": "6.1.4", + "resolve": "^1.22.0", + "stream-meter": "^1.0.4" + }, + "dependencies": { + "@babel/parser": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", + "dev": true + }, + "@babel/types": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", + "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "requires": { + "semver": "^5.4.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "prebuild-install": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.21.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "pkg-fetch": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/pkg-fetch/-/pkg-fetch-3.4.1.tgz", + "integrity": "sha512-fS4cdayCa1r4jHkOKGPJKnS9PEs6OWZst+s+m0+CmhmPZObMnxoRnf9T9yUWl+lzM2b5aJF7cnQIySCT7Hq8Dg==", + "dev": true, + "requires": { + "chalk": "^4.1.2", + "fs-extra": "^9.1.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.6", + "progress": "^2.0.3", + "semver": "^7.3.5", + "tar-fs": "^2.1.1", + "yargs": "^16.2.0" + }, + "dependencies": { + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "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-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + } + } + }, + "plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-83vX4eYdQp3vP9SxuYgEM/G/pJQqLUz/V/xzPrzruLs7fz7jxGQ1msZ/mg1nwZxUSuOp4sb+/bEIbRrbzZRxDA==", + "dev": true, + "requires": { + "base64-js": "^1.5.1", + "xmlbuilder": "^9.0.7" + }, + "dependencies": { + "xmlbuilder": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", + "dev": true + } + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + } + }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "dev": true + }, + "postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "dev": true, + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, + "postcss-loader": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", + "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "dev": true, + "requires": { + "cosmiconfig": "^7.0.0", + "klona": "^2.0.5", + "semver": "^7.3.5" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", + "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-nested": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", + "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.6" + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dev": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dev": true, + "requires": { + "semver": "^5.4.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "dev": true + }, + "prettier": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", + "dev": true + }, + "pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "promise-polyfill": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.3.tgz", + "integrity": "sha512-Og0+jCRQetV84U8wVjMNccfGCnMQ9mGs9Hv78QFe+pSDD3gWTpz0y+1QCuxy5d/vBFuZ3iwP2eycAkvqIMPmWg==" + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "peer": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "requires": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + } + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "qrious": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/qrious/-/qrious-4.0.2.tgz", + "integrity": "sha512-xWPJIrK1zu5Ypn898fBp8RHkT/9ibquV2Kv24S/JY9VYEhMBMKur1gHVsOiNUh7PHP9uCgejjpZUHUIXXKoU/g==" + }, + "qs": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz", + "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "read-config-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.2.0.tgz", + "integrity": "sha512-gx7Pgr5I56JtYz+WuqEbQHj/xWo+5Vwua2jhb1VwM4Wid5PqYmZ4i00ZB0YEGIfkVBsCv9UrjgyqCiQfS/Oosg==", + "dev": true, + "requires": { + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "dependencies": { + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "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" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", + "dev": true + }, + "regedit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/regedit/-/regedit-3.0.3.tgz", + "integrity": "sha512-SpHmMKOtiEYx0MiRRC48apBsmThoZ4svZNsYoK8leHd5bdUHV1nYb8pk8gh6Moou7/S9EDi1QsjBTpyXVQrPuQ==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "if-async": "^3.7.4", + "stream-slicer": "0.0.6", + "through2": "^0.6.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "replacestream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz", + "integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.3", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "dev": true, + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "dev": true, + "peer": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "restricted-input": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/restricted-input/-/restricted-input-3.0.5.tgz", + "integrity": "sha512-lUuXZ3wUnHURRarj5/0C8vomWIfWJO+p7T6RYwB46v7Oyuyr3yyupU+i7SjqUv4S6RAeAAZt1C/QCLJ9xhQBow==", + "requires": { + "@braintree/browser-detection": "^1.12.1" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "requires": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.5.tgz", + "integrity": "sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "requires": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "sass": { + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.52.1.tgz", + "integrity": "sha512-fSzYTbr7z8oQnVJ3Acp9hV80dM1fkMN7mSD/25mpcct9F7FPBMOI8krEYALgU1aZoqGhQNhTPsuSmxjnIvAm4Q==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sass-loader": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", + "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", + "dev": true, + "requires": { + "klona": "^2.0.4", + "neo-async": "^2.6.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "requires": { + "xmlchars": "^2.2.0" + } + }, + "schema-utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.14", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz", + "integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + }, + "dependencies": { + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + } + } + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true, + "optional": true + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true + } + } + }, + "serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "requires": { + "type-fest": "^0.13.1" + }, + "dependencies": { + "type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true + } + } + }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shell-quote": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", + "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "dev": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true + } + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "peer": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "socks": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", + "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "dev": true, + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true, + "optional": true + }, + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "stack-utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "steno": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/steno/-/steno-0.4.4.tgz", + "integrity": "sha1-BxEFvfwobmYVwEA8J+nXtdy4Vcs=", + "requires": { + "graceful-fs": "^4.1.3" + } + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-meter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz", + "integrity": "sha1-Uq+Vql6nYKJJFxZwTb/5D3Ov3R0=", + "dev": true, + "requires": { + "readable-stream": "^2.1.4" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "stream-slicer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stream-slicer/-/stream-slicer-0.0.6.tgz", + "integrity": "sha1-+GsqxcJEC3oKh7cfM2ZcB4gEYTg=", + "dev": true + }, + "streamfilter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-3.0.0.tgz", + "integrity": "sha512-kvKNfXCmUyC8lAXSSHCIXBUlo/lhsLcCU/OmzACZYpRUdtKIH68xYhm/+HI15jFJYtNJGYtCgn2wmIiExY1VwA==", + "dev": true, + "requires": { + "readable-stream": "^3.0.6" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "streaming-json-stringify": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/streaming-json-stringify/-/streaming-json-stringify-3.1.0.tgz", + "integrity": "sha1-gCAEN6mTzDnE/gAmO3s7kDrIevU=", + "requires": { + "json-stringify-safe": "5", + "readable-stream": "2" + } + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "peer": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "peer": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "style-loader": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", + "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "dev": true, + "requires": {} + }, + "sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "requires": { + "debug": "^4.1.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "supports-hyperlinks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", + "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "sweetalert2": { + "version": "10.16.9", + "resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-10.16.9.tgz", + "integrity": "sha512-oNe+md5tmmS3fGfVHa7gVPlun7Td2oANSacnZCeghnrr3OHBi6UPVPU+GFrymwaDqwQspACilLRmRnM7aTjNPA==" + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" + }, + "tailwindcss": { + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", + "integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==", + "dev": true, + "requires": { + "arg": "^5.0.1", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.12", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "5.0.6", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.0" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + } + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tar": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + } + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "requires": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + } + } + }, + "terminal-link": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", + "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", + "dev": true, + "peer": true, + "requires": { + "ansi-escapes": "^4.2.1", + "supports-hyperlinks": "^2.0.0" + } + }, + "ternary-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-3.0.0.tgz", + "integrity": "sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ==", + "dev": true, + "requires": { + "duplexify": "^4.1.1", + "fork-stream": "^0.0.4", + "merge-stream": "^2.0.0", + "through2": "^3.0.1" + } + }, + "terser": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.0.tgz", + "integrity": "sha512-JC6qfIEkPBd9j1SMO3Pfn+A6w2kQV54tv+ABQLgZr7dA3k/DL/OBoYSWxzVpZev3J+bUHXfr55L8Mox7AaNo6g==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz", + "integrity": "sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.7", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.0", + "terser": "^5.7.2" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "peer": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "textextensions": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz", + "integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==", + "dev": true + }, + "throat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", + "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", + "dev": true, + "peer": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "tldjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tldjs/-/tldjs-2.3.1.tgz", + "integrity": "sha512-W/YVH/QczLUxVjnQhFC61Iq232NWu3TqDdO0S/MtXVz4xybejBov4ud+CIwN9aYqjOecEqIy0PscGkwpG9ZyTw==", + "requires": { + "punycode": "^1.4.1" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "requires": { + "tmp": "^0.2.0" + }, + "dependencies": { + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + } + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "peer": true + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "requires": { + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + } + } + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "dev": true, + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, + "ts-jest": { + "version": "27.1.5", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.5.tgz", + "integrity": "sha512-Xv6jBQPoBEvBq/5i2TeSG9tt/nqkbpcurrEG1b+2yfBrcJelOZF9Ml6dmyMh7bcW9JyFbRYpR5rxROSlBLTZHA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^27.0.0", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "7.x", + "yargs-parser": "20.x" + }, + "dependencies": { + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "ts-loader": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.3.0.tgz", + "integrity": "sha512-2kLLAdAD+FCKijvGKi9sS0OzoqxLCF3CxHpok7rVgCZ5UldRzH0TkbwG9XECKjBzHsAewntC5oDaI/FwKzEUog==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.0.0", + "micromatch": "^4.0.0", + "semver": "^7.3.4" + } + }, + "tsconfig-paths": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", + "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "tsconfig-paths-webpack-plugin": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-3.5.2.tgz", + "integrity": "sha512-EhnfjHbzm5IYI9YPNVIxx1moxMI4bpHD2e0zTXeDNQcwjjRaGepP7IhTHJkyDBG0CAOoxRfe7jCG630Ou+C6Pw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tsconfig-paths": "^3.9.0" + } + }, + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "optional": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "typescript": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "dependencies": { + "fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + } + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + } + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==", + "dev": true, + "requires": { + "boxen": "^5.0.0", + "chalk": "^4.1.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.4.0", + "is-npm": "^5.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.1.0", + "pupa": "^2.1.1", + "semver": "^7.3.4", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + } + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "dev": true + } + } + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "dev": true + }, + "util": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz", + "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "v8-to-istanbul": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", + "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", + "dev": true, + "peer": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "peer": true + } + } + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "optional": true + } + } + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "peer": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, + "web-animations-js": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/web-animations-js/-/web-animations-js-2.3.2.tgz", + "integrity": "sha512-TOMFWtQdxzjWp8qx4DAraTWTsdhxVSiWa6NkPFSaPtZ1diKUxTn4yTix73A1euG1WbSOMMPcY51cnjTIHrGtDA==" + }, + "webcrypto-shim": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/webcrypto-shim/-/webcrypto-shim-0.1.7.tgz", + "integrity": "sha512-JAvAQR5mRNRxZW2jKigWMjCMkjSdmP5cColRP1U/pTg69VgHXEi1orv5vVpJ55Zc5MIaPc1aaurzd9pjv2bveg==", + "dev": true + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==" + }, + "webpack": { + "version": "5.73.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.73.0.tgz", + "integrity": "sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^0.0.51", + "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/wasm-edit": "1.11.1", + "@webassemblyjs/wasm-parser": "1.11.1", + "acorn": "^8.4.1", + "acorn-import-assertions": "^1.7.6", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.9.3", + "es-module-lexer": "^0.9.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.1.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.1.3", + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "schema-utils": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", + "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + } + } + }, + "webpack-cli": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.2.tgz", + "integrity": "sha512-m3/AACnBBzK/kMTcxWHcZFPrw/eQuY4Df1TxvIWfWM2x7mRqBQCqKEd96oCUa9jkapLBaFfRce33eGDb4Pr7YQ==", + "dev": true, + "requires": { + "@discoveryjs/json-ext": "^0.5.0", + "@webpack-cli/configtest": "^1.1.1", + "@webpack-cli/info": "^1.4.1", + "@webpack-cli/serve": "^1.6.1", + "colorette": "^2.0.14", + "commander": "^7.0.0", + "execa": "^5.0.0", + "fastest-levenshtein": "^1.0.12", + "import-local": "^3.0.2", + "interpret": "^2.2.0", + "rechoir": "^0.7.0", + "webpack-merge": "^5.7.3" + }, + "dependencies": { + "interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "dev": true + }, + "rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "requires": { + "resolve": "^1.9.0" + } + } + } + }, + "webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dev": true, + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + } + }, + "webpack-dev-server": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.6.0.tgz", + "integrity": "sha512-oojcBIKvx3Ya7qs1/AVWHDgmP1Xml8rGsEBnSobxU/UJSX1xP1GPM3MwsAnDzvqcVmVki8tV7lbcsjEjk0PtYg==", + "dev": true, + "requires": { + "ansi-html-community": "^0.0.8", + "bonjour": "^3.5.0", + "chokidar": "^3.5.2", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "default-gateway": "^6.0.3", + "del": "^6.0.0", + "express": "^4.17.1", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.0", + "ipaddr.js": "^2.0.1", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "portfinder": "^1.0.28", + "schema-utils": "^4.0.0", + "selfsigned": "^1.10.11", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "spdy": "^4.0.2", + "strip-ansi": "^7.0.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^5.2.1", + "ws": "^8.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "ws": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.7.0.tgz", + "integrity": "sha512-c2gsP0PRwcLFzUiA8Mkr37/MI7ilIlHQxaEAtd0uNMbVMoy8puJyafRlm0bV9MbGSabUPeLrRRaqIBcFcA2Pqg==", + "dev": true, + "requires": {} + } + } + }, + "webpack-merge": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", + "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "requires": { + "iconv-lite": "0.4.24" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "dev": true + }, + "which-typed-array": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", + "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-abstract": "^1.20.0", + "for-each": "^0.3.3", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.9" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "wildcard": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", + "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", + "dev": true + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" + }, + "xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "optional": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "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.0.0" + } + }, + "yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "requires": { + "buffer-crc32": "~0.2.3" + } + }, + "ylru": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.3.2.tgz", + "integrity": "sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==" + }, + "zone.js": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.5.tgz", + "integrity": "sha512-D1/7VxEuQ7xk6z/kAROe4SUbd9CzxY4zOwVGnGHerd/SgLIVU5f4esDzQUsOCeArn933BZfWMKydH7l7dPEp0g==", + "requires": { + "tslib": "^2.3.0" + } + }, + "zxcvbn": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/zxcvbn/-/zxcvbn-4.4.2.tgz", + "integrity": "sha1-KOwXzwl0PtyrBW3dixsGJizHPDA=" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..d91ff6dd53 --- /dev/null +++ b/package.json @@ -0,0 +1,177 @@ +{ + "name": "@bitwarden/clients", + "version": "0.0.0", + "description": "Bitwarden Client Applications", + "repository": { + "type": "git", + "url": "git+https://github.com/bitwarden/clients.git" + }, + "author": "Bitwarden Inc. (https://bitwarden.com)", + "license": "GPL-3.0", + "bugs": { + "url": "https://github.com/bitwarden/clients/issues" + }, + "homepage": "https://bitwarden.com", + "scripts": { + "lint": "eslint . && prettier --check .", + "lint:fix": "eslint . --fix", + "prettier": "prettier --write .", + "prepare": "husky install" + }, + "devDependencies": { + "@angular/compiler-cli": "^12.2.13", + "@fluffy-spoon/substitute": "^1.208.0", + "@ngtools/webpack": "^12.2.13", + "@nodert-win10-rs4/windows.security.credentials.ui": "^0.4.4", + "@types/chrome": "^0.0.139", + "@types/duo_web_sdk": "^2.7.1", + "@types/firefox-webext-browser": "^82.0.0", + "@types/inquirer": "^8.2.1", + "@types/jest": "^27.5.0", + "@types/jquery": "^3.5.14", + "@types/jsdom": "^16.2.14", + "@types/koa": "^2.13.4", + "@types/koa__multer": "^2.0.4", + "@types/koa__router": "^8.0.11", + "@types/koa-bodyparser": "^4.3.7", + "@types/koa-json": "^2.0.20", + "@types/lowdb": "^1.0.11", + "@types/lunr": "^2.3.4", + "@types/mousetrap": "^1.6.8", + "@types/node": "^16.11.12", + "@types/node-fetch": "^2.6.1", + "@types/node-forge": "^1.0.2", + "@types/node-ipc": "^9.2.0", + "@types/papaparse": "^5.3.2", + "@types/proper-lockfile": "^4.1.2", + "@types/retry": "^0.12.2", + "@types/tldjs": "^2.3.1", + "@types/webcrypto": "^0.0.28", + "@types/zxcvbn": "^4.4.1", + "@typescript-eslint/eslint-plugin": "^5.22.0", + "@typescript-eslint/parser": "^5.22.0", + "autoprefixer": "^10.4.7", + "buffer": "^6.0.3", + "clean-webpack-plugin": "^4.0.0", + "concurrently": "^7.2.1", + "copy-webpack-plugin": "^10.0.0", + "cross-env": "^7.0.3", + "css-loader": "^6.5.1", + "del": "^6.0.0", + "electron": "16.2.7", + "electron-builder": "^22.11.7", + "electron-log": "^4.4.7", + "electron-notarize": "^1.2.1", + "electron-rebuild": "^3.2.7", + "electron-reload": "^2.0.0-alpha.1", + "electron-store": "^8.0.1", + "electron-updater": "^5.0.1", + "eslint": "^8.14.0", + "eslint-config-prettier": "^8.5.0", + "eslint-import-resolver-typescript": "^2.7.1", + "eslint-plugin-import": "^2.26.0", + "forcefocus": "^1.1.0", + "gulp": "^4.0.2", + "gulp-filter": "^7.0.0", + "gulp-if": "^3.0.0", + "gulp-json-editor": "^2.5.5", + "gulp-replace": "^1.1.0", + "gulp-zip": "^5.1.0", + "html-loader": "^3.0.1", + "html-webpack-injector": "^1.1.4", + "html-webpack-plugin": "^5.5.0", + "husky": "^7.0.4", + "jasmine-core": "^3.7.1", + "jasmine-spec-reporter": "^7.0.0", + "jest-preset-angular": "^10.1.0", + "keytar": "^7.9.0", + "lint-staged": "^12.4.1", + "mini-css-extract-plugin": "^2.4.5", + "node-ipc": "^9.2.1", + "pkg": "5.7.0", + "postcss": "^8.4.14", + "postcss-loader": "^6.2.1", + "prettier": "^2.6.2", + "process": "^0.11.10", + "regedit": "^3.0.3", + "rimraf": "^3.0.2", + "sass": "^1.34.1", + "sass-loader": "^12.4.0", + "style-loader": "^3.3.1", + "tailwindcss": "^3.0.24", + "tapable": "^1.1.3", + "ts-loader": "^9.2.5", + "tsconfig-paths-webpack-plugin": "^3.5.2", + "typescript": "4.3.5", + "url": "^0.11.0", + "util": "^0.12.4", + "webcrypto-shim": "^0.1.7", + "webpack": "^5.64.4", + "webpack-cli": "^4.9.1", + "webpack-dev-server": "4.6", + "webpack-node-externals": "^3.0.0" + }, + "dependencies": { + "@angular/animations": "^12.2.13", + "@angular/cdk": "^12.2.13", + "@angular/common": "^12.2.13", + "@angular/compiler": "^12.2.13", + "@angular/core": "^12.2.13", + "@angular/forms": "^12.2.13", + "@angular/platform-browser": "^12.2.13", + "@angular/platform-browser-dynamic": "^12.2.13", + "@angular/router": "^12.2.13", + "@koa/multer": "^3.0.0", + "@koa/router": "^10.1.1", + "@microsoft/signalr": "^5.0.17", + "@microsoft/signalr-protocol-msgpack": "^5.0.17", + "big-integer": "^1.6.51", + "bootstrap": "4.6.0", + "braintree-web-drop-in": "^1.33.1", + "browser-hrtime": "^1.1.8", + "bufferutil": "^4.0.6", + "chalk": "^4.1.0", + "commander": "^7.2.0", + "core-js": "^3.11.0", + "date-input-polyfill": "^2.14.0", + "duo_web_sdk": "github:duosecurity/duo_web_sdk", + "https-proxy-agent": "^5.0.0", + "inquirer": "^8.2.4", + "jquery": "3.6.0", + "jsdom": "^16.7.0", + "jszip": "^3.10.0", + "koa": "^2.13.4", + "koa-bodyparser": "^4.3.0", + "koa-json": "^2.0.2", + "lowdb": "^1.0.0", + "lunr": "^2.3.9", + "mousetrap": "^1.6.5", + "multer": "^1.4.5-lts.1", + "ngx-infinite-scroll": "^10.0.1", + "ngx-toastr": "14.1.4", + "node-fetch": "^2.6.7", + "node-forge": "^1.3.1", + "nord": "^0.2.1", + "open": "^8.4.0", + "papaparse": "^5.3.2", + "popper.js": "^1.16.1", + "proper-lockfile": "^4.1.2", + "qrious": "4.0.2", + "rxjs": "^7.5.5", + "sweetalert2": "^10.16.6", + "tldjs": "^2.3.1", + "utf-8-validate": "^5.0.9", + "web-animations-js": "^2.3.2", + "whatwg-fetch": "^3.6.2", + "zone.js": "^0.11.4", + "zxcvbn": "^4.4.2" + }, + "lint-staged": { + "*": "prettier --ignore-unknown --write", + "*.ts": "eslint --fix" + }, + "engines": { + "node": "~16", + "npm": "~8" + } +}